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

Last change on this file since 3987 was 3987, checked in by kanani, 6 years ago

clean up location, debug and error messages

  • Property svn:keywords set to Id
  • Property svn:mergeinfo set to (toggle deleted branches)
    /palm/branches/chemistry/SOURCE/radiation_model_mod.f902047-3190,​3218-3297
    /palm/branches/forwind/SOURCE/radiation_model_mod.f901564-1913
    /palm/branches/mosaik_M2/radiation_model_mod.f902360-3471
    /palm/branches/palm4u/SOURCE/radiation_model_mod.f902540-2692
    /palm/branches/radiation/SOURCE/radiation_model_mod.f902081-3493
    /palm/branches/rans/SOURCE/radiation_model_mod.f902078-3128
    /palm/branches/resler/SOURCE/radiation_model_mod.f902023-3605
    /palm/branches/salsa/SOURCE/radiation_model_mod.f902503-3460
    /palm/branches/fricke/SOURCE/radiation_model_mod.f90942-977
    /palm/branches/hoffmann/SOURCE/radiation_model_mod.f90989-1052
    /palm/branches/letzel/masked_output/SOURCE/radiation_model_mod.f90296-409
    /palm/branches/suehring/radiation_model_mod.f90423-666
File size: 504.0 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-2019 Institute of Computer Science of the
18!                     Czech Academy of Sciences, Prague
19! Copyright 2015-2019 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 3987 2019-05-22 09:52:13Z kanani $
30! Introduce alternative switch for debug output during timestepping
31!
32! 3943 2019-05-02 09:50:41Z maronga
33! Missing blank characteer added.
34!
35! 3900 2019-04-16 15:17:43Z suehring
36! Fixed initialization problem
37!
38! 3885 2019-04-11 11:29:34Z kanani
39! Changes related to global restructuring of location messages and introduction
40! of additional debug messages
41!
42! 3881 2019-04-10 09:31:22Z suehring
43! Output of albedo and emissivity moved from USM, bugfixes in initialization
44! of albedo
45!
46! 3861 2019-04-04 06:27:41Z maronga
47! Bugfix: factor of 4.0 required instead of 3.0 in calculation of rad_lw_out_change_0
48!
49! 3859 2019-04-03 20:30:31Z maronga
50! Added some descriptions
51!
52! 3847 2019-04-01 14:51:44Z suehring
53! Implement check for dt_radiation (must be > 0)
54!
55! 3846 2019-04-01 13:55:30Z suehring
56! unused variable removed
57!
58! 3814 2019-03-26 08:40:31Z pavelkrc
59! Change zenith(0:0) and others to scalar.
60! Code review.
61! Rename exported nzu, nzp and related variables due to name conflict
62!
63! 3771 2019-02-28 12:19:33Z raasch
64! rrtmg preprocessor for directives moved/added, save attribute added to temporary
65! pointers to avoid compiler warnings about outlived pointer targets,
66! statement added to avoid compiler warning about unused variable
67!
68! 3769 2019-02-28 10:16:49Z moh.hefny
69! removed unused variables and subroutine radiation_radflux_gridbox
70!
71! 3767 2019-02-27 08:18:02Z raasch
72! unused variable for file index removed from rrd-subroutines parameter list
73!
74! 3760 2019-02-21 18:47:35Z moh.hefny
75! Bugfix: initialized simulated_time before calculating solar position
76! to enable restart option with reading in SVF from file(s).
77!
78! 3754 2019-02-19 17:02:26Z kanani
79! (resler, pavelkrc)
80! Bugfixes: add further required MRT factors to read/write_svf,
81! fix for aggregating view factors to eliminate local noise in reflected
82! irradiance at mutually close surfaces (corners, presence of trees) in the
83! angular discretization scheme.
84!
85! 3752 2019-02-19 09:37:22Z resler
86! added read/write number of MRT factors to the respective routines
87!
88! 3705 2019-01-29 19:56:39Z suehring
89! Make variables that are sampled in virtual measurement module public
90!
91! 3704 2019-01-29 19:51:41Z suehring
92! Some interface calls moved to module_interface + cleanup
93!
94! 3667 2019-01-10 14:26:24Z schwenkel
95! Modified check for rrtmg input files
96!
97! 3655 2019-01-07 16:51:22Z knoop
98! nopointer option removed
99!
100! 3633 2018-12-17 16:17:57Z schwenkel
101! Include check for rrtmg files
102!
103! 3630 2018-12-17 11:04:17Z knoop
104! - fix initialization of date and time after calling zenith
105! - fix a bug in radiation_solar_pos
106!
107! 3616 2018-12-10 09:44:36Z Salim
108! fix manipulation of time variables in radiation_presimulate_solar_pos
109!
110! 3608 2018-12-07 12:59:57Z suehring $
111! Bugfix radiation output
112!
113! 3607 2018-12-07 11:56:58Z suehring
114! Output of radiation-related quantities migrated to radiation_model_mod.
115!
116! 3589 2018-11-30 15:09:51Z suehring
117! Remove erroneous UTF encoding
118!
119! 3572 2018-11-28 11:40:28Z suehring
120! Add filling the short- and longwave radiation flux arrays (e.g. diffuse,
121! direct, reflected, resedual) for all surfaces. This is required to surface
122! outputs in suface_output_mod. (M. Salim)
123!
124! 3571 2018-11-28 09:24:03Z moh.hefny
125! Add an epsilon value to compare values in if statement to fix possible
126! precsion related errors in raytrace routines.
127!
128! 3524 2018-11-14 13:36:44Z raasch
129! missing cpp-directives added
130!
131! 3495 2018-11-06 15:22:17Z kanani
132! Resort control_parameters ONLY list,
133! From branch radiation@3491 moh.hefny:
134! bugfix in calculating the apparent solar positions by updating
135! the simulated time so that the actual time is correct.
136!
137! 3464 2018-10-30 18:08:55Z kanani
138! From branch resler@3462, pavelkrc:
139! add MRT shaping function for human
140!
141! 3449 2018-10-29 19:36:56Z suehring
142! New RTM version 3.0: (Pavel Krc, Jaroslav Resler, ICS, Prague)
143!   - Interaction of plant canopy with LW radiation
144!   - Transpiration from resolved plant canopy dependent on radiation
145!     called from RTM
146!
147!
148! 3435 2018-10-26 18:25:44Z gronemeier
149! - workaround: return unit=illegal in check_data_output for certain variables
150!   when check called from init_masks
151! - Use pointer in masked output to reduce code redundancies
152! - Add terrain-following masked output
153!
154! 3424 2018-10-25 07:29:10Z gronemeier
155! bugfix: add rad_lw_in, rad_lw_out, rad_sw_out to radiation_check_data_output
156!
157! 3378 2018-10-19 12:34:59Z kanani
158! merge from radiation branch (r3362) into trunk
159! (moh.hefny):
160! - removed read/write_svf_on_init and read_dist_max_svf (not used anymore)
161! - bugfix nzut > nzpt in calculating maxboxes
162!
163! 3372 2018-10-18 14:03:19Z raasch
164! bugfix: kind type of 2nd argument of mpi_win_allocate changed, misplaced
165!         __parallel directive
166!
167! 3351 2018-10-15 18:40:42Z suehring
168! Do not overwrite values of spectral and broadband albedo during initialization
169! if they are already initialized in the urban-surface model via ASCII input.
170!
171! 3337 2018-10-12 15:17:09Z kanani
172! - New RTM version 2.9: (Pavel Krc, Jaroslav Resler, ICS, Prague)
173!   added calculation of the MRT inside the RTM module
174!   MRT fluxes are consequently used in the new biometeorology module
175!   for calculation of biological indices (MRT, PET)
176!   Fixes of v. 2.5 and SVN trunk:
177!    - proper initialization of rad_net_l
178!    - make arrays nsurfs and surfstart TARGET to prevent some MPI problems
179!    - initialization of arrays used in MPI one-sided operation as 1-D arrays
180!      to prevent problems with some MPI/compiler combinations
181!    - fix indexing of target displacement in subroutine request_itarget to
182!      consider nzub
183!    - fix LAD dimmension range in PCB calculation
184!    - check ierr in all MPI calls
185!    - use proper per-gridbox sky and diffuse irradiance
186!    - fix shading for reflected irradiance
187!    - clear away the residuals of "atmospheric surfaces" implementation
188!    - fix rounding bug in raytrace_2d introduced in SVN trunk
189! - New RTM version 2.5: (Pavel Krc, Jaroslav Resler, ICS, Prague)
190!   can use angular discretization for all SVF
191!   (i.e. reflected and emitted radiation in addition to direct and diffuse),
192!   allowing for much better scaling wih high resoltion and/or complex terrain
193! - Unite array grow factors
194! - Fix slightly shifted terrain height in raytrace_2d
195! - Use more efficient MPI_Win_allocate for reverse gridsurf index
196! - Fix random MPI RMA bugs on Intel compilers
197! - Fix approx. double plant canopy sink values for reflected radiation
198! - Fix mostly missing plant canopy sinks for direct radiation
199! - Fix discretization errors for plant canopy sink in diffuse radiation
200! - Fix rounding errors in raytrace_2d
201!
202! 3274 2018-09-24 15:42:55Z knoop
203! Modularization of all bulk cloud physics code components
204!
205! 3272 2018-09-24 10:16:32Z suehring
206! - split direct and diffusion shortwave radiation using RRTMG rather than using
207!   calc_diffusion_radiation, in case of RRTMG
208! - removed the namelist variable split_diffusion_radiation. Now splitting depends
209!   on the choise of radiation radiation scheme
210! - removed calculating the rdiation flux for surfaces at the radiation scheme
211!   in case of using RTM since it will be calculated anyway in the radiation
212!   interaction routine.
213! - set SW radiation flux for surfaces to zero at night in case of no RTM is used
214! - precalculate the unit vector yxdir of ray direction to avoid the temporarly
215!   array allocation during the subroutine call
216! - fixed a bug in calculating the max number of boxes ray can cross in the domain
217!
218! 3264 2018-09-20 13:54:11Z moh.hefny
219! Bugfix in raytrace_2d calls
220!
221! 3248 2018-09-14 09:42:06Z sward
222! Minor formating changes
223!
224! 3246 2018-09-13 15:14:50Z sward
225! Added error handling for input namelist via parin_fail_message
226!
227! 3241 2018-09-12 15:02:00Z raasch
228! unused variables removed or commented
229!
230! 3233 2018-09-07 13:21:24Z schwenkel
231! Adapted for the use of cloud_droplets
232!
233! 3230 2018-09-05 09:29:05Z schwenkel
234! Bugfix in radiation_constant_surf: changed (10.0 - emissivity_urb) to
235! (1.0 - emissivity_urb)
236!
237! 3226 2018-08-31 12:27:09Z suehring
238! Bugfixes in calculation of sky-view factors and canopy-sink factors.
239!
240! 3186 2018-07-30 17:07:14Z suehring
241! Remove print statement
242!
243! 3180 2018-07-27 11:00:56Z suehring
244! Revise concept for calculation of effective radiative temperature and mapping
245! of radiative heating
246!
247! 3175 2018-07-26 14:07:38Z suehring
248! Bugfix for commit 3172
249!
250! 3173 2018-07-26 12:55:23Z suehring
251! Revise output of surface radiation quantities in case of overhanging
252! structures
253!
254! 3172 2018-07-26 12:06:06Z suehring
255! Bugfixes:
256!  - temporal work-around for calculation of effective radiative surface
257!    temperature
258!  - prevent positive solar radiation during nighttime
259!
260! 3170 2018-07-25 15:19:37Z suehring
261! Bugfix, map signle-column radiation forcing profiles on top of any topography
262!
263! 3156 2018-07-19 16:30:54Z knoop
264! Bugfix: replaced usage of the pt array with the surf%pt_surface array
265!
266! 3137 2018-07-17 06:44:21Z maronga
267! String length for trace_names fixed
268!
269! 3127 2018-07-15 08:01:25Z maronga
270! A few pavement parameters updated.
271!
272! 3123 2018-07-12 16:21:53Z suehring
273! Correct working precision for INTEGER number
274!
275! 3122 2018-07-11 21:46:41Z maronga
276! Bugfix: maximum distance for raytracing was set to  -999 m by default,
277! effectively switching off all surface reflections when max_raytracing_dist
278! was not explicitly set in namelist
279!
280! 3117 2018-07-11 09:59:11Z maronga
281! Bugfix: water vapor was not transfered to RRTMG when bulk_cloud_model = .F.
282! Bugfix: changed the calculation of RRTMG boundary conditions (Mohamed Salim)
283! Bugfix: dry residual atmosphere is replaced by standard RRTMG atmosphere
284!
285! 3116 2018-07-10 14:31:58Z suehring
286! Output of long/shortwave radiation at surface
287!
288! 3107 2018-07-06 15:55:51Z suehring
289! Bugfix, missing index for dz
290!
291! 3066 2018-06-12 08:55:55Z Giersch
292! Error message revised
293!
294! 3065 2018-06-12 07:03:02Z Giersch
295! dz was replaced by dz(1), error message concerning vertical stretching was
296! added 
297!
298! 3049 2018-05-29 13:52:36Z Giersch
299! Error messages revised
300!
301! 3045 2018-05-28 07:55:41Z Giersch
302! Error message revised
303!
304! 3026 2018-05-22 10:30:53Z schwenkel
305! Changed the name specific humidity to mixing ratio, since we are computing
306! mixing ratios.
307!
308! 3016 2018-05-09 10:53:37Z Giersch
309! Revised structure of reading svf data according to PALM coding standard:
310! svf_code_field/len and fsvf removed, error messages PA0493 and PA0494 added,
311! allocation status of output arrays checked.
312!
313! 3014 2018-05-09 08:42:38Z maronga
314! Introduced plant canopy height similar to urban canopy height to limit
315! the memory requirement to allocate lad.
316! Deactivated automatic setting of minimum raytracing distance.
317!
318! 3004 2018-04-27 12:33:25Z Giersch
319! Further allocation checks implemented (averaged data will be assigned to fill
320! values if no allocation happened so far)
321!
322! 2995 2018-04-19 12:13:16Z Giersch
323! IF-statement in radiation_init removed so that the calculation of radiative
324! fluxes at model start is done in any case, bugfix in
325! radiation_presimulate_solar_pos (end_time is the sum of end_time and the
326! spinup_time specified in the p3d_file ), list of variables/fields that have
327! to be written out or read in case of restarts has been extended
328!
329! 2977 2018-04-17 10:27:57Z kanani
330! Implement changes from branch radiation (r2948-2971) with minor modifications,
331! plus some formatting.
332! (moh.hefny):
333! - replaced plant_canopy by npcbl to check tree existence to avoid weird
334!   allocation of related arrays (after domain decomposition some domains
335!   contains no trees although plant_canopy (global parameter) is still TRUE).
336! - added a namelist parameter to force RTM settings
337! - enabled the option to switch radiation reflections off
338! - renamed surf_reflections to surface_reflections
339! - removed average_radiation flag from the namelist (now it is implicitly set
340!   in init_3d_model according to RTM)
341! - edited read and write sky view factors and CSF routines to account for
342!   the sub-domains which may not contain any of them
343!
344! 2967 2018-04-13 11:22:08Z raasch
345! bugfix: missing parallel cpp-directives added
346!
347! 2964 2018-04-12 16:04:03Z Giersch
348! Error message PA0491 has been introduced which could be previously found in
349! check_open. The variable numprocs_previous_run is only known in case of
350! initializing_actions == read_restart_data
351!
352! 2963 2018-04-12 14:47:44Z suehring
353! - Introduce index for vegetation/wall, pavement/green-wall and water/window
354!   surfaces, for clearer access of surface fraction, albedo, emissivity, etc. .
355! - Minor bugfix in initialization of albedo for window surfaces
356!
357! 2944 2018-04-03 16:20:18Z suehring
358! Fixed bad commit
359!
360! 2943 2018-04-03 16:17:10Z suehring
361! No read of nsurfl from SVF file since it is calculated in
362! radiation_interaction_init,
363! allocation of arrays in radiation_read_svf only if not yet allocated,
364! update of 2920 revision comment.
365!
366! 2932 2018-03-26 09:39:22Z maronga
367! renamed radiation_par to radiation_parameters
368!
369! 2930 2018-03-23 16:30:46Z suehring
370! Remove default surfaces from radiation model, does not make much sense to
371! apply radiation model without energy-balance solvers; Further, add check for
372! this.
373!
374! 2920 2018-03-22 11:22:01Z kanani
375! - Bugfix: Initialize pcbl array (=-1)
376! RTM version 2.0 (Jaroslav Resler, Pavel Krc, Mohamed Salim):
377! - new major version of radiation interactions
378! - substantially enhanced performance and scalability
379! - processing of direct and diffuse solar radiation separated from reflected
380!   radiation, removed virtual surfaces
381! - new type of sky discretization by azimuth and elevation angles
382! - diffuse radiation processed cumulatively using sky view factor
383! - used precalculated apparent solar positions for direct irradiance
384! - added new 2D raytracing process for processing whole vertical column at once
385!   to increase memory efficiency and decrease number of MPI RMA operations
386! - enabled limiting the number of view factors between surfaces by the distance
387!   and value
388! - fixing issues induced by transferring radiation interactions from
389!   urban_surface_mod to radiation_mod
390! - bugfixes and other minor enhancements
391!
392! 2906 2018-03-19 08:56:40Z Giersch
393! NAMELIST paramter read/write_svf_on_init have been removed, functions
394! check_open and close_file are used now for opening/closing files related to
395! svf data, adjusted unit number and error numbers
396!
397! 2894 2018-03-15 09:17:58Z Giersch
398! Calculations of the index range of the subdomain on file which overlaps with
399! the current subdomain are already done in read_restart_data_mod
400! radiation_read_restart_data was renamed to radiation_rrd_local and
401! radiation_last_actions was renamed to radiation_wrd_local, variable named
402! found has been introduced for checking if restart data was found, reading
403! of restart strings has been moved completely to read_restart_data_mod,
404! radiation_rrd_local is already inside the overlap loop programmed in
405! read_restart_data_mod, the marker *** end rad *** is not necessary anymore,
406! strings and their respective lengths are written out and read now in case of
407! restart runs to get rid of prescribed character lengths (Giersch)
408!
409! 2809 2018-02-15 09:55:58Z suehring
410! Bugfix for gfortran: Replace the function C_SIZEOF with STORAGE_SIZE
411!
412! 2753 2018-01-16 14:16:49Z suehring
413! Tile approach for spectral albedo implemented.
414!
415! 2746 2018-01-15 12:06:04Z suehring
416! Move flag plant canopy to modules
417!
418! 2724 2018-01-05 12:12:38Z maronga
419! Set default of average_radiation to .FALSE.
420!
421! 2723 2018-01-05 09:27:03Z maronga
422! Bugfix in calculation of rad_lw_out (clear-sky). First grid level was used
423! instead of the surface value
424!
425! 2718 2018-01-02 08:49:38Z maronga
426! Corrected "Former revisions" section
427!
428! 2707 2017-12-18 18:34:46Z suehring
429! Changes from last commit documented
430!
431! 2706 2017-12-18 18:33:49Z suehring
432! Bugfix, in average radiation case calculate exner function before using it.
433!
434! 2701 2017-12-15 15:40:50Z suehring
435! Changes from last commit documented
436!
437! 2698 2017-12-14 18:46:24Z suehring
438! Bugfix in get_topography_top_index
439!
440! 2696 2017-12-14 17:12:51Z kanani
441! - Change in file header (GPL part)
442! - Improved reading/writing of SVF from/to file (BM)
443! - Bugfixes concerning RRTMG as well as average_radiation options (M. Salim)
444! - Revised initialization of surface albedo and some minor bugfixes (MS)
445! - Update net radiation after running radiation interaction routine (MS)
446! - Revisions from M Salim included
447! - Adjustment to topography and surface structure (MS)
448! - Initialization of albedo and surface emissivity via input file (MS)
449! - albedo_pars extended (MS)
450!
451! 2604 2017-11-06 13:29:00Z schwenkel
452! bugfix for calculation of effective radius using morrison microphysics
453!
454! 2601 2017-11-02 16:22:46Z scharf
455! added emissivity to namelist
456!
457! 2575 2017-10-24 09:57:58Z maronga
458! Bugfix: calculation of shortwave and longwave albedos for RRTMG swapped
459!
460! 2547 2017-10-16 12:41:56Z schwenkel
461! extended by cloud_droplets option, minor bugfix and correct calculation of
462! cloud droplet number concentration
463!
464! 2544 2017-10-13 18:09:32Z maronga
465! Moved date and time quantitis to separate module date_and_time_mod
466!
467! 2512 2017-10-04 08:26:59Z raasch
468! upper bounds of cross section and 3d output changed from nx+1,ny+1 to nx,ny
469! no output of ghost layer data
470!
471! 2504 2017-09-27 10:36:13Z maronga
472! Updates pavement types and albedo parameters
473!
474! 2328 2017-08-03 12:34:22Z maronga
475! Emissivity can now be set individually for each pixel.
476! Albedo type can be inferred from land surface model.
477! Added default albedo type for bare soil
478!
479! 2318 2017-07-20 17:27:44Z suehring
480! Get topography top index via Function call
481!
482! 2317 2017-07-20 17:27:19Z suehring
483! Improved syntax layout
484!
485! 2298 2017-06-29 09:28:18Z raasch
486! type of write_binary changed from CHARACTER to LOGICAL
487!
488! 2296 2017-06-28 07:53:56Z maronga
489! Added output of rad_sw_out for radiation_scheme = 'constant'
490!
491! 2270 2017-06-09 12:18:47Z maronga
492! Numbering changed (2 timeseries removed)
493!
494! 2249 2017-06-06 13:58:01Z sward
495! Allow for RRTMG runs without humidity/cloud physics
496!
497! 2248 2017-06-06 13:52:54Z sward
498! Error no changed
499!
500! 2233 2017-05-30 18:08:54Z suehring
501!
502! 2232 2017-05-30 17:47:52Z suehring
503! Adjustments to new topography concept
504! Bugfix in read restart
505!
506! 2200 2017-04-11 11:37:51Z suehring
507! Bugfix in call of exchange_horiz_2d and read restart data
508!
509! 2163 2017-03-01 13:23:15Z schwenkel
510! Bugfix in radiation_check_data_output
511!
512! 2157 2017-02-22 15:10:35Z suehring
513! Bugfix in read_restart data
514!
515! 2011 2016-09-19 17:29:57Z kanani
516! Removed CALL of auxiliary SUBROUTINE get_usm_info,
517! flag urban_surface is now defined in module control_parameters.
518!
519! 2007 2016-08-24 15:47:17Z kanani
520! Added calculation of solar directional vector for new urban surface
521! model,
522! accounted for urban_surface model in radiation_check_parameters,
523! correction of comments for zenith angle.
524!
525! 2000 2016-08-20 18:09:15Z knoop
526! Forced header and separation lines into 80 columns
527!
528! 1976 2016-07-27 13:28:04Z maronga
529! Output of 2D/3D/masked data is now directly done within this module. The
530! radiation schemes have been simplified for better usability so that
531! rad_lw_in, rad_lw_out, rad_sw_in, and rad_sw_out are available independent of
532! the radiation code used.
533!
534! 1856 2016-04-13 12:56:17Z maronga
535! Bugfix: allocation of rad_lw_out for radiation_scheme = 'clear-sky'
536!
537! 1853 2016-04-11 09:00:35Z maronga
538! Added routine for radiation_scheme = constant.
539
540! 1849 2016-04-08 11:33:18Z hoffmann
541! Adapted for modularization of microphysics
542!
543! 1826 2016-04-07 12:01:39Z maronga
544! Further modularization.
545!
546! 1788 2016-03-10 11:01:04Z maronga
547! Added new albedo class for pavements / roads.
548!
549! 1783 2016-03-06 18:36:17Z raasch
550! palm-netcdf-module removed in order to avoid a circular module dependency,
551! netcdf-variables moved to netcdf-module, new routine netcdf_handle_error_rad
552! added
553!
554! 1757 2016-02-22 15:49:32Z maronga
555! Added parameter unscheduled_radiation_calls. Bugfix: interpolation of sounding
556! profiles for pressure and temperature above the LES domain.
557!
558! 1709 2015-11-04 14:47:01Z maronga
559! Bugfix: set initial value for rrtm_lwuflx_dt to zero, small formatting
560! corrections
561!
562! 1701 2015-11-02 07:43:04Z maronga
563! Bugfixes: wrong index for output of timeseries, setting of nz_snd_end
564!
565! 1691 2015-10-26 16:17:44Z maronga
566! Added option for spin-up runs without radiation (skip_time_do_radiation). Bugfix
567! in calculation of pressure profiles. Bugfix in calculation of trace gas profiles.
568! Added output of radiative heating rates.
569!
570! 1682 2015-10-07 23:56:08Z knoop
571! Code annotations made doxygen readable
572!
573! 1606 2015-06-29 10:43:37Z maronga
574! Added preprocessor directive __netcdf to allow for compiling without netCDF.
575! Note, however, that RRTMG cannot be used without netCDF.
576!
577! 1590 2015-05-08 13:56:27Z maronga
578! Bugfix: definition of character strings requires same length for all elements
579!
580! 1587 2015-05-04 14:19:01Z maronga
581! Added albedo class for snow
582!
583! 1585 2015-04-30 07:05:52Z maronga
584! Added support for RRTMG
585!
586! 1571 2015-03-12 16:12:49Z maronga
587! Added missing KIND attribute. Removed upper-case variable names
588!
589! 1551 2015-03-03 14:18:16Z maronga
590! Added support for data output. Various variables have been renamed. Added
591! interface for different radiation schemes (currently: clear-sky, constant, and
592! RRTM (not yet implemented).
593!
594! 1496 2014-12-02 17:25:50Z maronga
595! Initial revision
596!
597!
598! Description:
599! ------------
600!> Radiation models and interfaces
601!> @todo Replace dz(1) appropriatly to account for grid stretching
602!> @todo move variable definitions used in radiation_init only to the subroutine
603!>       as they are no longer required after initialization.
604!> @todo Output of full column vertical profiles used in RRTMG
605!> @todo Output of other rrtm arrays (such as volume mixing ratios)
606!> @todo Check for mis-used NINT() calls in raytrace_2d
607!>       RESULT: Original was correct (carefully verified formula), the change
608!>               to INT broke raytracing      -- P. Krc
609!> @todo Optimize radiation_tendency routines
610!>
611!> @note Many variables have a leading dummy dimension (0:0) in order to
612!>       match the assume-size shape expected by the RRTMG model.
613!------------------------------------------------------------------------------!
614 MODULE radiation_model_mod
615 
616    USE arrays_3d,                                                             &
617        ONLY:  dzw, hyp, nc, pt, p, q, ql, u, v, w, zu, zw, exner, d_exner
618
619    USE basic_constants_and_equations_mod,                                     &
620        ONLY:  c_p, g, lv_d_cp, l_v, pi, r_d, rho_l, solar_constant, sigma_sb, &
621               barometric_formula
622
623    USE calc_mean_profile_mod,                                                 &
624        ONLY:  calc_mean_profile
625
626    USE control_parameters,                                                    &
627        ONLY:  cloud_droplets, coupling_char,                                  &
628               debug_output, debug_output_timestep, debug_string,              &
629               dz, dt_spinup, end_time,                                        &
630               humidity,                                                       &
631               initializing_actions, io_blocks, io_group,                      &
632               land_surface, large_scale_forcing,                              &
633               latitude, longitude, lsf_surf,                                  &
634               message_string, plant_canopy, pt_surface,                       &
635               rho_surface, simulated_time, spinup_time, surface_pressure,     &
636               read_svf, write_svf,                                            &
637               time_since_reference_point, urban_surface, varnamelength
638
639    USE cpulog,                                                                &
640        ONLY:  cpu_log, log_point, log_point_s
641
642    USE grid_variables,                                                        &
643         ONLY:  ddx, ddy, dx, dy 
644
645    USE date_and_time_mod,                                                     &
646        ONLY:  calc_date_and_time, d_hours_day, d_seconds_hour, d_seconds_year,&
647               day_of_year, d_seconds_year, day_of_month, day_of_year_init,    &
648               init_date_and_time, month_of_year, time_utc_init, time_utc
649
650    USE indices,                                                               &
651        ONLY:  nnx, nny, nx, nxl, nxlg, nxr, nxrg, ny, nyn, nyng, nys, nysg,   &
652               nzb, nzt
653
654    USE, INTRINSIC :: iso_c_binding
655
656    USE kinds
657
658    USE bulk_cloud_model_mod,                                                  &
659        ONLY:  bulk_cloud_model, microphysics_morrison, na_init, nc_const, sigma_gc
660
661#if defined ( __netcdf )
662    USE NETCDF
663#endif
664
665    USE netcdf_data_input_mod,                                                 &
666        ONLY:  albedo_type_f, albedo_pars_f, building_type_f, pavement_type_f, &
667               vegetation_type_f, water_type_f
668
669    USE plant_canopy_model_mod,                                                &
670        ONLY:  lad_s, pc_heating_rate, pc_transpiration_rate, pc_latent_rate,  &
671               plant_canopy_transpiration, pcm_calc_transpiration_rate
672
673    USE pegrid
674
675#if defined ( __rrtmg )
676    USE parrrsw,                                                               &
677        ONLY:  naerec, nbndsw
678
679    USE parrrtm,                                                               &
680        ONLY:  nbndlw
681
682    USE rrtmg_lw_init,                                                         &
683        ONLY:  rrtmg_lw_ini
684
685    USE rrtmg_sw_init,                                                         &
686        ONLY:  rrtmg_sw_ini
687
688    USE rrtmg_lw_rad,                                                          &
689        ONLY:  rrtmg_lw
690
691    USE rrtmg_sw_rad,                                                          &
692        ONLY:  rrtmg_sw
693#endif
694    USE statistics,                                                            &
695        ONLY:  hom
696
697    USE surface_mod,                                                           &
698        ONLY:  get_topography_top_index, get_topography_top_index_ji,          &
699               ind_pav_green, ind_veg_wall, ind_wat_win,                       &
700               surf_lsm_h, surf_lsm_v, surf_type, surf_usm_h, surf_usm_v,      &
701               vertical_surfaces_exist
702
703    IMPLICIT NONE
704
705    CHARACTER(10) :: radiation_scheme = 'clear-sky' ! 'constant', 'clear-sky', or 'rrtmg'
706
707!
708!-- Predefined Land surface classes (albedo_type) after Briegleb (1992)
709    CHARACTER(37), DIMENSION(0:33), PARAMETER :: albedo_type_name = (/      &
710                                   'user defined                         ', & !  0
711                                   'ocean                                ', & !  1
712                                   'mixed farming, tall grassland        ', & !  2
713                                   'tall/medium grassland                ', & !  3
714                                   'evergreen shrubland                  ', & !  4
715                                   'short grassland/meadow/shrubland     ', & !  5
716                                   'evergreen needleleaf forest          ', & !  6
717                                   'mixed deciduous evergreen forest     ', & !  7
718                                   'deciduous forest                     ', & !  8
719                                   'tropical evergreen broadleaved forest', & !  9
720                                   'medium/tall grassland/woodland       ', & ! 10
721                                   'desert, sandy                        ', & ! 11
722                                   'desert, rocky                        ', & ! 12
723                                   'tundra                               ', & ! 13
724                                   'land ice                             ', & ! 14
725                                   'sea ice                              ', & ! 15
726                                   'snow                                 ', & ! 16
727                                   'bare soil                            ', & ! 17
728                                   'asphalt/concrete mix                 ', & ! 18
729                                   'asphalt (asphalt concrete)           ', & ! 19
730                                   'concrete (Portland concrete)         ', & ! 20
731                                   'sett                                 ', & ! 21
732                                   'paving stones                        ', & ! 22
733                                   'cobblestone                          ', & ! 23
734                                   'metal                                ', & ! 24
735                                   'wood                                 ', & ! 25
736                                   'gravel                               ', & ! 26
737                                   'fine gravel                          ', & ! 27
738                                   'pebblestone                          ', & ! 28
739                                   'woodchips                            ', & ! 29
740                                   'tartan (sports)                      ', & ! 30
741                                   'artifical turf (sports)              ', & ! 31
742                                   'clay (sports)                        ', & ! 32
743                                   'building (dummy)                     '  & ! 33
744                                                         /)
745
746    INTEGER(iwp) :: albedo_type  = 9999999_iwp, &     !< Albedo surface type
747                    dots_rad     = 0_iwp              !< starting index for timeseries output
748
749    LOGICAL ::  unscheduled_radiation_calls = .TRUE., & !< flag parameter indicating whether additional calls of the radiation code are allowed
750                constant_albedo = .FALSE.,            & !< flag parameter indicating whether the albedo may change depending on zenith
751                force_radiation_call = .FALSE.,       & !< flag parameter for unscheduled radiation calls
752                lw_radiation = .TRUE.,                & !< flag parameter indicating whether longwave radiation shall be calculated
753                radiation = .FALSE.,                  & !< flag parameter indicating whether the radiation model is used
754                sun_up    = .TRUE.,                   & !< flag parameter indicating whether the sun is up or down
755                sw_radiation = .TRUE.,                & !< flag parameter indicating whether shortwave radiation shall be calculated
756                sun_direction = .FALSE.,              & !< flag parameter indicating whether solar direction shall be calculated
757                average_radiation = .FALSE.,          & !< flag to set the calculation of radiation averaging for the domain
758                radiation_interactions = .FALSE.,     & !< flag to activiate RTM (TRUE only if vertical urban/land surface and trees exist)
759                surface_reflections = .TRUE.,         & !< flag to switch the calculation of radiation interaction between surfaces.
760                                                        !< When it switched off, only the effect of buildings and trees shadow
761                                                        !< will be considered. However fewer SVFs are expected.
762                radiation_interactions_on = .TRUE.      !< namelist flag to force RTM activiation regardless to vertical urban/land surface and trees
763
764    REAL(wp) :: albedo = 9999999.9_wp,           & !< NAMELIST alpha
765                albedo_lw_dif = 9999999.9_wp,    & !< NAMELIST aldif
766                albedo_lw_dir = 9999999.9_wp,    & !< NAMELIST aldir
767                albedo_sw_dif = 9999999.9_wp,    & !< NAMELIST asdif
768                albedo_sw_dir = 9999999.9_wp,    & !< NAMELIST asdir
769                decl_1,                          & !< declination coef. 1
770                decl_2,                          & !< declination coef. 2
771                decl_3,                          & !< declination coef. 3
772                dt_radiation = 0.0_wp,           & !< radiation model timestep
773                emissivity = 9999999.9_wp,       & !< NAMELIST surface emissivity
774                lon = 0.0_wp,                    & !< longitude in radians
775                lat = 0.0_wp,                    & !< latitude in radians
776                net_radiation = 0.0_wp,          & !< net radiation at surface
777                skip_time_do_radiation = 0.0_wp, & !< Radiation model is not called before this time
778                sky_trans,                       & !< sky transmissivity
779                time_radiation = 0.0_wp            !< time since last call of radiation code
780
781
782    REAL(wp) ::  cos_zenith        !< cosine of solar zenith angle, also z-coordinate of solar unit vector
783    REAL(wp) ::  sun_dir_lat       !< y-coordinate of solar unit vector
784    REAL(wp) ::  sun_dir_lon       !< x-coordinate of solar unit vector
785
786    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_net_av       !< average of net radiation (rad_net) at surface
787    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_lw_in_xy_av  !< average of incoming longwave radiation at surface
788    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_lw_out_xy_av !< average of outgoing longwave radiation at surface
789    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_sw_in_xy_av  !< average of incoming shortwave radiation at surface
790    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_sw_out_xy_av !< average of outgoing shortwave radiation at surface
791
792    REAL(wp), PARAMETER :: emissivity_atm_clsky = 0.8_wp       !< emissivity of the clear-sky atmosphere
793!
794!-- Land surface albedos for solar zenith angle of 60degree after Briegleb (1992)     
795!-- (shortwave, longwave, broadband):   sw,      lw,      bb,
796    REAL(wp), DIMENSION(0:2,1:33), PARAMETER :: albedo_pars = RESHAPE( (/& 
797                                   0.06_wp, 0.06_wp, 0.06_wp,            & !  1
798                                   0.09_wp, 0.28_wp, 0.19_wp,            & !  2
799                                   0.11_wp, 0.33_wp, 0.23_wp,            & !  3
800                                   0.11_wp, 0.33_wp, 0.23_wp,            & !  4
801                                   0.14_wp, 0.34_wp, 0.25_wp,            & !  5
802                                   0.06_wp, 0.22_wp, 0.14_wp,            & !  6
803                                   0.06_wp, 0.27_wp, 0.17_wp,            & !  7
804                                   0.06_wp, 0.31_wp, 0.19_wp,            & !  8
805                                   0.06_wp, 0.22_wp, 0.14_wp,            & !  9
806                                   0.06_wp, 0.28_wp, 0.18_wp,            & ! 10
807                                   0.35_wp, 0.51_wp, 0.43_wp,            & ! 11
808                                   0.24_wp, 0.40_wp, 0.32_wp,            & ! 12
809                                   0.10_wp, 0.27_wp, 0.19_wp,            & ! 13
810                                   0.90_wp, 0.65_wp, 0.77_wp,            & ! 14
811                                   0.90_wp, 0.65_wp, 0.77_wp,            & ! 15
812                                   0.95_wp, 0.70_wp, 0.82_wp,            & ! 16
813                                   0.08_wp, 0.08_wp, 0.08_wp,            & ! 17
814                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 18
815                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 19
816                                   0.30_wp, 0.30_wp, 0.30_wp,            & ! 20
817                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 21
818                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 22
819                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 23
820                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 24
821                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 25
822                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 26
823                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 27
824                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 28
825                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 29
826                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 30
827                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 31
828                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 32
829                                   0.17_wp, 0.17_wp, 0.17_wp             & ! 33
830                                 /), (/ 3, 33 /) )
831
832    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE, TARGET :: &
833                        rad_lw_cs_hr,                  & !< longwave clear sky radiation heating rate (K/s)
834                        rad_lw_cs_hr_av,               & !< average of rad_lw_cs_hr
835                        rad_lw_hr,                     & !< longwave radiation heating rate (K/s)
836                        rad_lw_hr_av,                  & !< average of rad_sw_hr
837                        rad_lw_in,                     & !< incoming longwave radiation (W/m2)
838                        rad_lw_in_av,                  & !< average of rad_lw_in
839                        rad_lw_out,                    & !< outgoing longwave radiation (W/m2)
840                        rad_lw_out_av,                 & !< average of rad_lw_out
841                        rad_sw_cs_hr,                  & !< shortwave clear sky radiation heating rate (K/s)
842                        rad_sw_cs_hr_av,               & !< average of rad_sw_cs_hr
843                        rad_sw_hr,                     & !< shortwave radiation heating rate (K/s)
844                        rad_sw_hr_av,                  & !< average of rad_sw_hr
845                        rad_sw_in,                     & !< incoming shortwave radiation (W/m2)
846                        rad_sw_in_av,                  & !< average of rad_sw_in
847                        rad_sw_out,                    & !< outgoing shortwave radiation (W/m2)
848                        rad_sw_out_av                    !< average of rad_sw_out
849
850
851!
852!-- Variables and parameters used in RRTMG only
853#if defined ( __rrtmg )
854    CHARACTER(LEN=12) :: rrtm_input_file = "RAD_SND_DATA" !< name of the NetCDF input file (sounding data)
855
856
857!
858!-- Flag parameters to be passed to RRTMG (should not be changed until ice phase in clouds is allowed)
859    INTEGER(iwp), PARAMETER :: rrtm_idrv     = 1, & !< flag for longwave upward flux calculation option (0,1)
860                               rrtm_inflglw  = 2, & !< flag for lw cloud optical properties (0,1,2)
861                               rrtm_iceflglw = 0, & !< flag for lw ice particle specifications (0,1,2,3)
862                               rrtm_liqflglw = 1, & !< flag for lw liquid droplet specifications
863                               rrtm_inflgsw  = 2, & !< flag for sw cloud optical properties (0,1,2)
864                               rrtm_iceflgsw = 0, & !< flag for sw ice particle specifications (0,1,2,3)
865                               rrtm_liqflgsw = 1    !< flag for sw liquid droplet specifications
866
867!
868!-- The following variables should be only changed with care, as this will
869!-- require further setting of some variables, which is currently not
870!-- implemented (aerosols, ice phase).
871    INTEGER(iwp) :: nzt_rad,           & !< upper vertical limit for radiation calculations
872                    rrtm_icld = 0,     & !< cloud flag (0: clear sky column, 1: cloudy column)
873                    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)
874
875    INTEGER(iwp) :: nc_stat !< local variable for storin the result of netCDF calls for error message handling
876
877    LOGICAL :: snd_exists = .FALSE.      !< flag parameter to check whether a user-defined input files exists
878    LOGICAL :: sw_exists = .FALSE.       !< flag parameter to check whether that required rrtmg sw file exists
879    LOGICAL :: lw_exists = .FALSE.       !< flag parameter to check whether that required rrtmg lw file exists
880
881
882    REAL(wp), PARAMETER :: mol_mass_air_d_wv = 1.607793_wp !< molecular weight dry air / water vapor
883
884    REAL(wp), DIMENSION(:), ALLOCATABLE :: hyp_snd,     & !< hypostatic pressure from sounding data (hPa)
885                                           rrtm_tsfc,   & !< dummy array for storing surface temperature
886                                           t_snd          !< actual temperature from sounding data (hPa)
887
888    REAL(wp), DIMENSION(:,:), ALLOCATABLE :: rrtm_ccl4vmr,   & !< CCL4 volume mixing ratio (g/mol)
889                                             rrtm_cfc11vmr,  & !< CFC11 volume mixing ratio (g/mol)
890                                             rrtm_cfc12vmr,  & !< CFC12 volume mixing ratio (g/mol)
891                                             rrtm_cfc22vmr,  & !< CFC22 volume mixing ratio (g/mol)
892                                             rrtm_ch4vmr,    & !< CH4 volume mixing ratio
893                                             rrtm_cicewp,    & !< in-cloud ice water path (g/m2)
894                                             rrtm_cldfr,     & !< cloud fraction (0,1)
895                                             rrtm_cliqwp,    & !< in-cloud liquid water path (g/m2)
896                                             rrtm_co2vmr,    & !< CO2 volume mixing ratio (g/mol)
897                                             rrtm_emis,      & !< surface emissivity (0-1) 
898                                             rrtm_h2ovmr,    & !< H2O volume mixing ratio
899                                             rrtm_n2ovmr,    & !< N2O volume mixing ratio
900                                             rrtm_o2vmr,     & !< O2 volume mixing ratio
901                                             rrtm_o3vmr,     & !< O3 volume mixing ratio
902                                             rrtm_play,      & !< pressure layers (hPa, zu-grid)
903                                             rrtm_plev,      & !< pressure layers (hPa, zw-grid)
904                                             rrtm_reice,     & !< cloud ice effective radius (microns)
905                                             rrtm_reliq,     & !< cloud water drop effective radius (microns)
906                                             rrtm_tlay,      & !< actual temperature (K, zu-grid)
907                                             rrtm_tlev,      & !< actual temperature (K, zw-grid)
908                                             rrtm_lwdflx,    & !< RRTM output of incoming longwave radiation flux (W/m2)
909                                             rrtm_lwdflxc,   & !< RRTM output of outgoing clear sky longwave radiation flux (W/m2)
910                                             rrtm_lwuflx,    & !< RRTM output of outgoing longwave radiation flux (W/m2)
911                                             rrtm_lwuflxc,   & !< RRTM output of incoming clear sky longwave radiation flux (W/m2)
912                                             rrtm_lwuflx_dt, & !< RRTM output of incoming clear sky longwave radiation flux (W/m2)
913                                             rrtm_lwuflxc_dt,& !< RRTM output of outgoing clear sky longwave radiation flux (W/m2)
914                                             rrtm_lwhr,      & !< RRTM output of longwave radiation heating rate (K/d)
915                                             rrtm_lwhrc,     & !< RRTM output of incoming longwave clear sky radiation heating rate (K/d)
916                                             rrtm_swdflx,    & !< RRTM output of incoming shortwave radiation flux (W/m2)
917                                             rrtm_swdflxc,   & !< RRTM output of outgoing clear sky shortwave radiation flux (W/m2)
918                                             rrtm_swuflx,    & !< RRTM output of outgoing shortwave radiation flux (W/m2)
919                                             rrtm_swuflxc,   & !< RRTM output of incoming clear sky shortwave radiation flux (W/m2)
920                                             rrtm_swhr,      & !< RRTM output of shortwave radiation heating rate (K/d)
921                                             rrtm_swhrc,     & !< RRTM output of incoming shortwave clear sky radiation heating rate (K/d)
922                                             rrtm_dirdflux,  & !< RRTM output of incoming direct shortwave (W/m2)
923                                             rrtm_difdflux     !< RRTM output of incoming diffuse shortwave (W/m2)
924
925    REAL(wp), DIMENSION(1) ::                rrtm_aldif,     & !< surface albedo for longwave diffuse radiation
926                                             rrtm_aldir,     & !< surface albedo for longwave direct radiation
927                                             rrtm_asdif,     & !< surface albedo for shortwave diffuse radiation
928                                             rrtm_asdir        !< surface albedo for shortwave direct radiation
929
930!
931!-- Definition of arrays that are currently not used for calling RRTMG (due to setting of flag parameters)
932    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::  rad_lw_cs_in,   & !< incoming clear sky longwave radiation (W/m2) (not used)
933                                                rad_lw_cs_out,  & !< outgoing clear sky longwave radiation (W/m2) (not used)
934                                                rad_sw_cs_in,   & !< incoming clear sky shortwave radiation (W/m2) (not used)
935                                                rad_sw_cs_out,  & !< outgoing clear sky shortwave radiation (W/m2) (not used)
936                                                rrtm_lw_tauaer, & !< lw aerosol optical depth
937                                                rrtm_lw_taucld, & !< lw in-cloud optical depth
938                                                rrtm_sw_taucld, & !< sw in-cloud optical depth
939                                                rrtm_sw_ssacld, & !< sw in-cloud single scattering albedo
940                                                rrtm_sw_asmcld, & !< sw in-cloud asymmetry parameter
941                                                rrtm_sw_fsfcld, & !< sw in-cloud forward scattering fraction
942                                                rrtm_sw_tauaer, & !< sw aerosol optical depth
943                                                rrtm_sw_ssaaer, & !< sw aerosol single scattering albedo
944                                                rrtm_sw_asmaer, & !< sw aerosol asymmetry parameter
945                                                rrtm_sw_ecaer     !< sw aerosol optical detph at 0.55 microns (rrtm_iaer = 6 only)
946
947#endif
948!
949!-- Parameters of urban and land surface models
950    INTEGER(iwp)                                   ::  nz_urban                           !< number of layers of urban surface (will be calculated)
951    INTEGER(iwp)                                   ::  nz_plant                           !< number of layers of plant canopy (will be calculated)
952    INTEGER(iwp)                                   ::  nz_urban_b                         !< bottom layer of urban surface (will be calculated)
953    INTEGER(iwp)                                   ::  nz_urban_t                         !< top layer of urban surface (will be calculated)
954    INTEGER(iwp)                                   ::  nz_plant_t                         !< top layer of plant canopy (will be calculated)
955!-- parameters of urban and land surface models
956    INTEGER(iwp), PARAMETER                        ::  nzut_free = 3                      !< number of free layers above top of of topography
957    INTEGER(iwp), PARAMETER                        ::  ndsvf = 2                          !< number of dimensions of real values in SVF
958    INTEGER(iwp), PARAMETER                        ::  idsvf = 2                          !< number of dimensions of integer values in SVF
959    INTEGER(iwp), PARAMETER                        ::  ndcsf = 1                          !< number of dimensions of real values in CSF
960    INTEGER(iwp), PARAMETER                        ::  idcsf = 2                          !< number of dimensions of integer values in CSF
961    INTEGER(iwp), PARAMETER                        ::  kdcsf = 4                          !< number of dimensions of integer values in CSF calculation array
962    INTEGER(iwp), PARAMETER                        ::  id = 1                             !< position of d-index in surfl and surf
963    INTEGER(iwp), PARAMETER                        ::  iz = 2                             !< position of k-index in surfl and surf
964    INTEGER(iwp), PARAMETER                        ::  iy = 3                             !< position of j-index in surfl and surf
965    INTEGER(iwp), PARAMETER                        ::  ix = 4                             !< position of i-index in surfl and surf
966    INTEGER(iwp), PARAMETER                        ::  im = 5                             !< position of surface m-index in surfl and surf
967    INTEGER(iwp), PARAMETER                        ::  nidx_surf = 5                      !< number of indices in surfl and surf
968
969    INTEGER(iwp), PARAMETER                        ::  nsurf_type = 10                    !< number of surf types incl. phys.(land+urban) & (atm.,sky,boundary) surfaces - 1
970
971    INTEGER(iwp), PARAMETER                        ::  iup_u    = 0                       !< 0 - index of urban upward surface (ground or roof)
972    INTEGER(iwp), PARAMETER                        ::  idown_u  = 1                       !< 1 - index of urban downward surface (overhanging)
973    INTEGER(iwp), PARAMETER                        ::  inorth_u = 2                       !< 2 - index of urban northward facing wall
974    INTEGER(iwp), PARAMETER                        ::  isouth_u = 3                       !< 3 - index of urban southward facing wall
975    INTEGER(iwp), PARAMETER                        ::  ieast_u  = 4                       !< 4 - index of urban eastward facing wall
976    INTEGER(iwp), PARAMETER                        ::  iwest_u  = 5                       !< 5 - index of urban westward facing wall
977
978    INTEGER(iwp), PARAMETER                        ::  iup_l    = 6                       !< 6 - index of land upward surface (ground or roof)
979    INTEGER(iwp), PARAMETER                        ::  inorth_l = 7                       !< 7 - index of land northward facing wall
980    INTEGER(iwp), PARAMETER                        ::  isouth_l = 8                       !< 8 - index of land southward facing wall
981    INTEGER(iwp), PARAMETER                        ::  ieast_l  = 9                       !< 9 - index of land eastward facing wall
982    INTEGER(iwp), PARAMETER                        ::  iwest_l  = 10                      !< 10- index of land westward facing wall
983
984    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  idir = (/0, 0,0, 0,1,-1,0,0, 0,1,-1/)   !< surface normal direction x indices
985    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  jdir = (/0, 0,1,-1,0, 0,0,1,-1,0, 0/)   !< surface normal direction y indices
986    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  kdir = (/1,-1,0, 0,0, 0,1,0, 0,0, 0/)   !< surface normal direction z indices
987    REAL(wp),     DIMENSION(0:nsurf_type)          :: facearea                            !< area of single face in respective
988                                                                                          !< direction (will be calc'd)
989
990
991!-- indices and sizes of urban and land surface models
992    INTEGER(iwp)                                   ::  startland        !< start index of block of land and roof surfaces
993    INTEGER(iwp)                                   ::  endland          !< end index of block of land and roof surfaces
994    INTEGER(iwp)                                   ::  nlands           !< number of land and roof surfaces in local processor
995    INTEGER(iwp)                                   ::  startwall        !< start index of block of wall surfaces
996    INTEGER(iwp)                                   ::  endwall          !< end index of block of wall surfaces
997    INTEGER(iwp)                                   ::  nwalls           !< number of wall surfaces in local processor
998
999!-- indices needed for RTM netcdf output subroutines
1000    INTEGER(iwp), PARAMETER                        :: nd = 5
1001    CHARACTER(LEN=6), DIMENSION(0:nd-1), PARAMETER :: dirname = (/ '_roof ', '_south', '_north', '_west ', '_east ' /)
1002    INTEGER(iwp), DIMENSION(0:nd-1), PARAMETER     :: dirint_u = (/ iup_u, isouth_u, inorth_u, iwest_u, ieast_u /)
1003    INTEGER(iwp), DIMENSION(0:nd-1), PARAMETER     :: dirint_l = (/ iup_l, isouth_l, inorth_l, iwest_l, ieast_l /)
1004    INTEGER(iwp), DIMENSION(0:nd-1)                :: dirstart
1005    INTEGER(iwp), DIMENSION(0:nd-1)                :: dirend
1006
1007!-- indices and sizes of urban and land surface models
1008    INTEGER(iwp), DIMENSION(:,:), POINTER          ::  surfl            !< coordinates of i-th local surface in local grid - surfl[:,k] = [d, z, y, x, m]
1009    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surfl_linear     !< dtto (linearly allocated array)
1010    INTEGER(iwp), DIMENSION(:,:), POINTER          ::  surf             !< coordinates of i-th surface in grid - surf[:,k] = [d, z, y, x, m]
1011    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surf_linear      !< dtto (linearly allocated array)
1012    INTEGER(iwp)                                   ::  nsurfl           !< number of all surfaces in local processor
1013    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  nsurfs           !< array of number of all surfaces in individual processors
1014    INTEGER(iwp)                                   ::  nsurf            !< global number of surfaces in index array of surfaces (nsurf = proc nsurfs)
1015    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surfstart        !< starts of blocks of surfaces for individual processors in array surf (indexed from 1)
1016                                                                        !< respective block for particular processor is surfstart[iproc+1]+1 : surfstart[iproc+1]+nsurfs[iproc+1]
1017
1018!-- block variables needed for calculation of the plant canopy model inside the urban surface model
1019    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pct              !< top layer of the plant canopy
1020    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pch              !< heights of the plant canopy
1021    INTEGER(iwp)                                   ::  npcbl = 0        !< number of the plant canopy gridboxes in local processor
1022    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pcbl             !< k,j,i coordinates of l-th local plant canopy box pcbl[:,l] = [k, j, i]
1023    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinsw          !< array of absorbed sw radiation for local plant canopy box
1024    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdir       !< array of absorbed direct sw radiation for local plant canopy box
1025    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdif       !< array of absorbed diffusion sw radiation for local plant canopy box
1026    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinlw          !< array of absorbed lw radiation for local plant canopy box
1027
1028!-- configuration parameters (they can be setup in PALM config)
1029    LOGICAL                                        ::  raytrace_mpi_rma = .TRUE.          !< use MPI RMA to access LAD and gridsurf from remote processes during raytracing
1030    LOGICAL                                        ::  rad_angular_discretization = .TRUE.!< whether to use fixed resolution discretization of view factors for
1031                                                                                          !< reflected radiation (as opposed to all mutually visible pairs)
1032    LOGICAL                                        ::  plant_lw_interact = .TRUE.         !< whether plant canopy interacts with LW radiation (in addition to SW)
1033    INTEGER(iwp)                                   ::  mrt_nlevels = 0                    !< number of vertical boxes above surface for which to calculate MRT
1034    LOGICAL                                        ::  mrt_skip_roof = .TRUE.             !< do not calculate MRT above roof surfaces
1035    LOGICAL                                        ::  mrt_include_sw = .TRUE.            !< should MRT calculation include SW radiation as well?
1036    LOGICAL                                        ::  mrt_geom_human = .TRUE.            !< MRT direction weights simulate human body instead of a sphere
1037    INTEGER(iwp)                                   ::  nrefsteps = 3                      !< number of reflection steps to perform
1038    REAL(wp), PARAMETER                            ::  ext_coef = 0.6_wp                  !< extinction coefficient (a.k.a. alpha)
1039    INTEGER(iwp), PARAMETER                        ::  rad_version_len = 10               !< length of identification string of rad version
1040    CHARACTER(rad_version_len), PARAMETER          ::  rad_version = 'RAD v. 3.0'         !< identification of version of binary svf and restart files
1041    INTEGER(iwp)                                   ::  raytrace_discrete_elevs = 40       !< number of discretization steps for elevation (nadir to zenith)
1042    INTEGER(iwp)                                   ::  raytrace_discrete_azims = 80       !< number of discretization steps for azimuth (out of 360 degrees)
1043    REAL(wp)                                       ::  max_raytracing_dist = -999.0_wp    !< maximum distance for raytracing (in metres)
1044    REAL(wp)                                       ::  min_irrf_value = 1e-6_wp           !< minimum potential irradiance factor value for raytracing
1045    REAL(wp), DIMENSION(1:30)                      ::  svfnorm_report_thresh = 1e21_wp    !< thresholds of SVF normalization values to report
1046    INTEGER(iwp)                                   ::  svfnorm_report_num                 !< number of SVF normalization thresholds to report
1047
1048!-- radiation related arrays to be used in radiation_interaction routine
1049    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_sw_in_dir    !< direct sw radiation
1050    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_sw_in_diff   !< diffusion sw radiation
1051    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_lw_in_diff   !< diffusion lw radiation
1052
1053!-- parameters required for RRTMG lower boundary condition
1054    REAL(wp)                   :: albedo_urb      !< albedo value retuned to RRTMG boundary cond.
1055    REAL(wp)                   :: emissivity_urb  !< emissivity value retuned to RRTMG boundary cond.
1056    REAL(wp)                   :: t_rad_urb       !< temperature value retuned to RRTMG boundary cond.
1057
1058!-- type for calculation of svf
1059    TYPE t_svf
1060        INTEGER(iwp)                               :: isurflt           !<
1061        INTEGER(iwp)                               :: isurfs            !<
1062        REAL(wp)                                   :: rsvf              !<
1063        REAL(wp)                                   :: rtransp           !<
1064    END TYPE
1065
1066!-- type for calculation of csf
1067    TYPE t_csf
1068        INTEGER(iwp)                               :: ip                !<
1069        INTEGER(iwp)                               :: itx               !<
1070        INTEGER(iwp)                               :: ity               !<
1071        INTEGER(iwp)                               :: itz               !<
1072        INTEGER(iwp)                               :: isurfs            !< Idx of source face / -1 for sky
1073        REAL(wp)                                   :: rcvf              !< Canopy view factor for faces /
1074                                                                        !< canopy sink factor for sky (-1)
1075    END TYPE
1076
1077!-- arrays storing the values of USM
1078    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  svfsurf          !< svfsurf[:,isvf] = index of target and source surface for svf[isvf]
1079    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  svf              !< array of shape view factors+direct irradiation factors for local surfaces
1080    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfins          !< array of sw radiation falling to local surface after i-th reflection
1081    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinl          !< array of lw radiation for local surface after i-th reflection
1082
1083    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  skyvf            !< array of sky view factor for each local surface
1084    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  skyvft           !< array of sky view factor including transparency for each local surface
1085    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsitrans         !< dsidir[isvfl,i] = path transmittance of i-th
1086                                                                        !< direction of direct solar irradiance per target surface
1087    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsitransc        !< dtto per plant canopy box
1088    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsidir           !< dsidir[:,i] = unit vector of i-th
1089                                                                        !< direction of direct solar irradiance
1090    INTEGER(iwp)                                   ::  ndsidir          !< number of apparent solar directions used
1091    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  dsidir_rev       !< dsidir_rev[ielev,iazim] = i for dsidir or -1 if not present
1092
1093    INTEGER(iwp)                                   ::  nmrtbl           !< No. of local grid boxes for which MRT is calculated
1094    INTEGER(iwp)                                   ::  nmrtf            !< number of MRT factors for local processor
1095    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  mrtbl            !< coordinates of i-th local MRT box - surfl[:,i] = [z, y, x]
1096    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  mrtfsurf         !< mrtfsurf[:,imrtf] = index of target MRT box and source surface for mrtf[imrtf]
1097    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtf             !< array of MRT factors for each local MRT box
1098    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtft            !< array of MRT factors including transparency for each local MRT box
1099    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtsky           !< array of sky view factor for each local MRT box
1100    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtskyt          !< array of sky view factor including transparency for each local MRT box
1101    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  mrtdsit          !< array of direct solar transparencies for each local MRT box
1102    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinsw          !< mean SW radiant flux for each MRT box
1103    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinlw          !< mean LW radiant flux for each MRT box
1104    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrt              !< mean radiant temperature for each MRT box
1105    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinsw_av       !< time average mean SW radiant flux for each MRT box
1106    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinlw_av       !< time average mean LW radiant flux for each MRT box
1107    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrt_av           !< time average mean radiant temperature for each MRT box
1108
1109    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinsw         !< array of sw radiation falling to local surface including radiation from reflections
1110    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlw         !< array of lw radiation falling to local surface including radiation from reflections
1111    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdir      !< array of direct sw radiation falling to local surface
1112    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdif      !< array of diffuse sw radiation from sky and model boundary falling to local surface
1113    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwdif      !< array of diffuse lw radiation from sky and model boundary falling to local surface
1114   
1115                                                                        !< Outward radiation is only valid for nonvirtual surfaces
1116    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsl        !< array of reflected sw radiation for local surface in i-th reflection
1117    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutll        !< array of reflected + emitted lw radiation for local surface in i-th reflection
1118    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfouts         !< array of reflected sw radiation for all surfaces in i-th reflection
1119    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutl         !< array of reflected + emitted lw radiation for all surfaces in i-th reflection
1120    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlg         !< global array of incoming lw radiation from plant canopy
1121    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsw        !< array of total sw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1122    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutlw        !< array of total lw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1123    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfemitlwl      !< array of emitted lw radiation for local surface used to calculate effective surface temperature for radiation model
1124
1125!-- block variables needed for calculation of the plant canopy model inside the urban surface model
1126    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  csfsurf          !< csfsurf[:,icsf] = index of target surface and csf grid index for csf[icsf]
1127    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  csf              !< array of plant canopy sink fators + direct irradiation factors (transparency)
1128    REAL(wp), DIMENSION(:,:,:), POINTER            ::  sub_lad          !< subset of lad_s within urban surface, transformed to plain Z coordinate
1129    REAL(wp), DIMENSION(:), POINTER                ::  sub_lad_g        !< sub_lad globalized (used to avoid MPI RMA calls in raytracing)
1130    REAL(wp)                                       ::  prototype_lad    !< prototype leaf area density for computing effective optical depth
1131    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  nzterr, plantt   !< temporary global arrays for raytracing
1132    INTEGER(iwp)                                   ::  plantt_max
1133
1134!-- arrays and variables for calculation of svf and csf
1135    TYPE(t_svf), DIMENSION(:), POINTER             ::  asvf             !< pointer to growing svc array
1136    TYPE(t_csf), DIMENSION(:), POINTER             ::  acsf             !< pointer to growing csf array
1137    TYPE(t_svf), DIMENSION(:), POINTER             ::  amrtf            !< pointer to growing mrtf array
1138    TYPE(t_svf), DIMENSION(:), ALLOCATABLE, TARGET ::  asvf1, asvf2     !< realizations of svf array
1139    TYPE(t_csf), DIMENSION(:), ALLOCATABLE, TARGET ::  acsf1, acsf2     !< realizations of csf array
1140    TYPE(t_svf), DIMENSION(:), ALLOCATABLE, TARGET ::  amrtf1, amrtf2   !< realizations of mftf array
1141    INTEGER(iwp)                                   ::  nsvfla           !< dimmension of array allocated for storage of svf in local processor
1142    INTEGER(iwp)                                   ::  ncsfla           !< dimmension of array allocated for storage of csf in local processor
1143    INTEGER(iwp)                                   ::  nmrtfa           !< dimmension of array allocated for storage of mrt
1144    INTEGER(iwp)                                   ::  msvf, mcsf, mmrtf!< mod for swapping the growing array
1145    INTEGER(iwp), PARAMETER                        ::  gasize = 100000_iwp  !< initial size of growing arrays
1146    REAL(wp), PARAMETER                            ::  grow_factor = 1.4_wp !< growth factor of growing arrays
1147    INTEGER(iwp)                                   ::  nsvfl            !< number of svf for local processor
1148    INTEGER(iwp)                                   ::  ncsfl            !< no. of csf in local processor
1149                                                                        !< needed only during calc_svf but must be here because it is
1150                                                                        !< shared between subroutines calc_svf and raytrace
1151    INTEGER(iwp), DIMENSION(:,:,:,:), POINTER      ::  gridsurf         !< reverse index of local surfl[d,k,j,i] (for case rad_angular_discretization)
1152    INTEGER(iwp), DIMENSION(:,:,:), ALLOCATABLE    ::  gridpcbl         !< reverse index of local pcbl[k,j,i]
1153    INTEGER(iwp), PARAMETER                        ::  nsurf_type_u = 6 !< number of urban surf types (used in gridsurf)
1154
1155!-- temporary arrays for calculation of csf in raytracing
1156    INTEGER(iwp)                                   ::  maxboxesg        !< max number of boxes ray can cross in the domain
1157    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  boxes            !< coordinates of gridboxes being crossed by ray
1158    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  crlens           !< array of crossing lengths of ray for particular grid boxes
1159    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  lad_ip           !< array of numbers of process where lad is stored
1160#if defined( __parallel )
1161    INTEGER(kind=MPI_ADDRESS_KIND), &
1162                  DIMENSION(:), ALLOCATABLE        ::  lad_disp         !< array of displaycements of lad in local array of proc lad_ip
1163    INTEGER(iwp)                                   ::  win_lad          !< MPI RMA window for leaf area density
1164    INTEGER(iwp)                                   ::  win_gridsurf     !< MPI RMA window for reverse grid surface index
1165#endif
1166    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  lad_s_ray        !< array of received lad_s for appropriate gridboxes crossed by ray
1167    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  target_surfl
1168    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  rt2_track
1169    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rt2_track_lad
1170    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  rt2_track_dist
1171    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  rt2_dist
1172
1173!-- arrays for time averages
1174    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfradnet_av    !< average of net radiation to local surface including radiation from reflections
1175    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinsw_av      !< average of sw radiation falling to local surface including radiation from reflections
1176    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlw_av      !< average of lw radiation falling to local surface including radiation from reflections
1177    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdir_av   !< average of direct sw radiation falling to local surface
1178    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdif_av   !< average of diffuse sw radiation from sky and model boundary falling to local surface
1179    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwdif_av   !< average of diffuse lw radiation from sky and model boundary falling to local surface
1180    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswref_av   !< average of sw radiation falling to surface from reflections
1181    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwref_av   !< average of lw radiation falling to surface from reflections
1182    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsw_av     !< average of total sw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1183    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutlw_av     !< average of total lw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1184    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfins_av       !< average of array of residua of sw radiation absorbed in surface after last reflection
1185    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinl_av       !< average of array of residua of lw radiation absorbed in surface after last reflection
1186    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinlw_av       !< Average of pcbinlw
1187    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinsw_av       !< Average of pcbinsw
1188    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdir_av    !< Average of pcbinswdir
1189    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdif_av    !< Average of pcbinswdif
1190    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswref_av    !< Average of pcbinswref
1191
1192
1193!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1194!-- Energy balance variables
1195!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1196!-- parameters of the land, roof and wall surfaces
1197    REAL(wp), DIMENSION(:), ALLOCATABLE            :: albedo_surf        !< albedo of the surface
1198    REAL(wp), DIMENSION(:), ALLOCATABLE            :: emiss_surf         !< emissivity of the wall surface
1199
1200
1201    INTERFACE radiation_check_data_output
1202       MODULE PROCEDURE radiation_check_data_output
1203    END INTERFACE radiation_check_data_output
1204
1205    INTERFACE radiation_check_data_output_ts
1206       MODULE PROCEDURE radiation_check_data_output_ts
1207    END INTERFACE radiation_check_data_output_ts
1208
1209    INTERFACE radiation_check_data_output_pr
1210       MODULE PROCEDURE radiation_check_data_output_pr
1211    END INTERFACE radiation_check_data_output_pr
1212 
1213    INTERFACE radiation_check_parameters
1214       MODULE PROCEDURE radiation_check_parameters
1215    END INTERFACE radiation_check_parameters
1216 
1217    INTERFACE radiation_clearsky
1218       MODULE PROCEDURE radiation_clearsky
1219    END INTERFACE radiation_clearsky
1220 
1221    INTERFACE radiation_constant
1222       MODULE PROCEDURE radiation_constant
1223    END INTERFACE radiation_constant
1224 
1225    INTERFACE radiation_control
1226       MODULE PROCEDURE radiation_control
1227    END INTERFACE radiation_control
1228
1229    INTERFACE radiation_3d_data_averaging
1230       MODULE PROCEDURE radiation_3d_data_averaging
1231    END INTERFACE radiation_3d_data_averaging
1232
1233    INTERFACE radiation_data_output_2d
1234       MODULE PROCEDURE radiation_data_output_2d
1235    END INTERFACE radiation_data_output_2d
1236
1237    INTERFACE radiation_data_output_3d
1238       MODULE PROCEDURE radiation_data_output_3d
1239    END INTERFACE radiation_data_output_3d
1240
1241    INTERFACE radiation_data_output_mask
1242       MODULE PROCEDURE radiation_data_output_mask
1243    END INTERFACE radiation_data_output_mask
1244
1245    INTERFACE radiation_define_netcdf_grid
1246       MODULE PROCEDURE radiation_define_netcdf_grid
1247    END INTERFACE radiation_define_netcdf_grid
1248
1249    INTERFACE radiation_header
1250       MODULE PROCEDURE radiation_header
1251    END INTERFACE radiation_header 
1252 
1253    INTERFACE radiation_init
1254       MODULE PROCEDURE radiation_init
1255    END INTERFACE radiation_init
1256
1257    INTERFACE radiation_parin
1258       MODULE PROCEDURE radiation_parin
1259    END INTERFACE radiation_parin
1260   
1261    INTERFACE radiation_rrtmg
1262       MODULE PROCEDURE radiation_rrtmg
1263    END INTERFACE radiation_rrtmg
1264
1265#if defined( __rrtmg )
1266    INTERFACE radiation_tendency
1267       MODULE PROCEDURE radiation_tendency
1268       MODULE PROCEDURE radiation_tendency_ij
1269    END INTERFACE radiation_tendency
1270#endif
1271
1272    INTERFACE radiation_rrd_local
1273       MODULE PROCEDURE radiation_rrd_local
1274    END INTERFACE radiation_rrd_local
1275
1276    INTERFACE radiation_wrd_local
1277       MODULE PROCEDURE radiation_wrd_local
1278    END INTERFACE radiation_wrd_local
1279
1280    INTERFACE radiation_interaction
1281       MODULE PROCEDURE radiation_interaction
1282    END INTERFACE radiation_interaction
1283
1284    INTERFACE radiation_interaction_init
1285       MODULE PROCEDURE radiation_interaction_init
1286    END INTERFACE radiation_interaction_init
1287 
1288    INTERFACE radiation_presimulate_solar_pos
1289       MODULE PROCEDURE radiation_presimulate_solar_pos
1290    END INTERFACE radiation_presimulate_solar_pos
1291
1292    INTERFACE radiation_calc_svf
1293       MODULE PROCEDURE radiation_calc_svf
1294    END INTERFACE radiation_calc_svf
1295
1296    INTERFACE radiation_write_svf
1297       MODULE PROCEDURE radiation_write_svf
1298    END INTERFACE radiation_write_svf
1299
1300    INTERFACE radiation_read_svf
1301       MODULE PROCEDURE radiation_read_svf
1302    END INTERFACE radiation_read_svf
1303
1304
1305    SAVE
1306
1307    PRIVATE
1308
1309!
1310!-- Public functions / NEEDS SORTING
1311    PUBLIC radiation_check_data_output, radiation_check_data_output_pr,        &
1312           radiation_check_data_output_ts,                                     &
1313           radiation_check_parameters, radiation_control,                      &
1314           radiation_header, radiation_init, radiation_parin,                  &
1315           radiation_3d_data_averaging,                                        &
1316           radiation_data_output_2d, radiation_data_output_3d,                 &
1317           radiation_define_netcdf_grid, radiation_wrd_local,                  &
1318           radiation_rrd_local, radiation_data_output_mask,                    &
1319           radiation_calc_svf, radiation_write_svf,                            &
1320           radiation_interaction, radiation_interaction_init,                  &
1321           radiation_read_svf, radiation_presimulate_solar_pos
1322
1323   
1324!
1325!-- Public variables and constants / NEEDS SORTING
1326    PUBLIC albedo, albedo_type, decl_1, decl_2, decl_3, dots_rad, dt_radiation,&
1327           emissivity, force_radiation_call, lat, lon, mrt_geom_human,         &
1328           mrt_include_sw, mrt_nlevels, mrtbl, mrtinsw, mrtinlw, nmrtbl,       &
1329           rad_net_av, radiation, radiation_scheme, rad_lw_in,                 &
1330           rad_lw_in_av, rad_lw_out, rad_lw_out_av,                            &
1331           rad_lw_cs_hr, rad_lw_cs_hr_av, rad_lw_hr, rad_lw_hr_av, rad_sw_in,  &
1332           rad_sw_in_av, rad_sw_out, rad_sw_out_av, rad_sw_cs_hr,              &
1333           rad_sw_cs_hr_av, rad_sw_hr, rad_sw_hr_av, solar_constant,           &
1334           skip_time_do_radiation, time_radiation, unscheduled_radiation_calls,&
1335           cos_zenith, calc_zenith, sun_direction, sun_dir_lat, sun_dir_lon,   &
1336           idir, jdir, kdir, id, iz, iy, ix,                                   &
1337           iup_u, inorth_u, isouth_u, ieast_u, iwest_u,                        &
1338           iup_l, inorth_l, isouth_l, ieast_l, iwest_l,                        &
1339           nsurf_type, nz_urban_b, nz_urban_t, nz_urban, pch, nsurf,                 &
1340           idsvf, ndsvf, idcsf, ndcsf, kdcsf, pct,                             &
1341           radiation_interactions, startwall, startland, endland, endwall,     &
1342           skyvf, skyvft, radiation_interactions_on, average_radiation,        &
1343           rad_sw_in_diff, rad_sw_in_dir
1344
1345
1346#if defined ( __rrtmg )
1347    PUBLIC radiation_tendency, rrtm_aldif, rrtm_aldir, rrtm_asdif, rrtm_asdir
1348#endif
1349
1350 CONTAINS
1351
1352
1353!------------------------------------------------------------------------------!
1354! Description:
1355! ------------
1356!> This subroutine controls the calls of the radiation schemes
1357!------------------------------------------------------------------------------!
1358    SUBROUTINE radiation_control
1359 
1360 
1361       IMPLICIT NONE
1362
1363
1364       IF ( debug_output_timestep )  CALL debug_message( 'radiation_control', 'start' )
1365
1366
1367       SELECT CASE ( TRIM( radiation_scheme ) )
1368
1369          CASE ( 'constant' )
1370             CALL radiation_constant
1371         
1372          CASE ( 'clear-sky' ) 
1373             CALL radiation_clearsky
1374       
1375          CASE ( 'rrtmg' )
1376             CALL radiation_rrtmg
1377
1378          CASE DEFAULT
1379
1380       END SELECT
1381
1382       IF ( debug_output_timestep )  CALL debug_message( 'radiation_control', 'end' )
1383
1384    END SUBROUTINE radiation_control
1385
1386!------------------------------------------------------------------------------!
1387! Description:
1388! ------------
1389!> Check data output for radiation model
1390!------------------------------------------------------------------------------!
1391    SUBROUTINE radiation_check_data_output( variable, unit, i, ilen, k )
1392 
1393 
1394       USE control_parameters,                                                 &
1395           ONLY: data_output, message_string
1396
1397       IMPLICIT NONE
1398
1399       CHARACTER (LEN=*) ::  unit          !<
1400       CHARACTER (LEN=*) ::  variable      !<
1401
1402       INTEGER(iwp) :: i, k
1403       INTEGER(iwp) :: ilen
1404       CHARACTER(LEN=varnamelength) :: var          !< TRIM(variable)
1405
1406       var = TRIM(variable)
1407
1408!--    first process diractional variables
1409       IF ( var(1:12) == 'rtm_rad_net_'  .OR.  var(1:13) == 'rtm_rad_insw_'  .OR.        &
1410            var(1:13) == 'rtm_rad_inlw_'  .OR.  var(1:16) == 'rtm_rad_inswdir_'  .OR.    &
1411            var(1:16) == 'rtm_rad_inswdif_'  .OR.  var(1:16) == 'rtm_rad_inswref_'  .OR. &
1412            var(1:16) == 'rtm_rad_inlwdif_'  .OR.  var(1:16) == 'rtm_rad_inlwref_'  .OR. &
1413            var(1:14) == 'rtm_rad_outsw_'  .OR.  var(1:14) == 'rtm_rad_outlw_'  .OR.     &
1414            var(1:14) == 'rtm_rad_ressw_'  .OR.  var(1:14) == 'rtm_rad_reslw_'  ) THEN
1415          IF ( .NOT.  radiation ) THEN
1416                message_string = 'output of "' // TRIM( var ) // '" require'&
1417                                 // 's radiation = .TRUE.'
1418                CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1419          ENDIF
1420          unit = 'W/m2'
1421       ELSE IF ( var(1:7) == 'rtm_svf'  .OR.  var(1:7) == 'rtm_dif'  .OR.                &
1422                 var(1:9) == 'rtm_skyvf' .OR. var(1:9) == 'rtm_skyvft'  .OR.             &
1423                 var(1:12) == 'rtm_surfalb_'  .OR.  var(1:13) == 'rtm_surfemis_'  ) THEN
1424          IF ( .NOT.  radiation ) THEN
1425                message_string = 'output of "' // TRIM( var ) // '" require'&
1426                                 // 's radiation = .TRUE.'
1427                CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1428          ENDIF
1429          unit = '1'
1430       ELSE
1431!--       non-directional variables
1432          SELECT CASE ( TRIM( var ) )
1433             CASE ( 'rad_lw_cs_hr', 'rad_lw_hr', 'rad_lw_in', 'rad_lw_out', &
1434                    'rad_sw_cs_hr', 'rad_sw_hr', 'rad_sw_in', 'rad_sw_out'  )
1435                IF (  .NOT.  radiation  .OR.  radiation_scheme /= 'rrtmg' )  THEN
1436                   message_string = '"output of "' // TRIM( var ) // '" requi' // &
1437                                    'res radiation = .TRUE. and ' //              &
1438                                    'radiation_scheme = "rrtmg"'
1439                   CALL message( 'check_parameters', 'PA0406', 1, 2, 0, 6, 0 )
1440                ENDIF
1441                unit = 'K/h'
1442
1443             CASE ( 'rad_net*', 'rrtm_aldif*', 'rrtm_aldir*', 'rrtm_asdif*',      &
1444                    'rrtm_asdir*', 'rad_lw_in*', 'rad_lw_out*', 'rad_sw_in*',     &
1445                    'rad_sw_out*')
1446                IF ( i == 0 .AND. ilen == 0 .AND. k == 0)  THEN
1447                   ! Workaround for masked output (calls with i=ilen=k=0)
1448                   unit = 'illegal'
1449                   RETURN
1450                ENDIF
1451                IF ( k == 0  .OR.  data_output(i)(ilen-2:ilen) /= '_xy' )  THEN
1452                   message_string = 'illegal value for data_output: "' //         &
1453                                    TRIM( var ) // '" & only 2d-horizontal ' //   &
1454                                    'cross sections are allowed for this value'
1455                   CALL message( 'check_parameters', 'PA0111', 1, 2, 0, 6, 0 )
1456                ENDIF
1457                IF (  .NOT.  radiation  .OR.  radiation_scheme /= "rrtmg" )  THEN
1458                   IF ( TRIM( var ) == 'rrtm_aldif*'  .OR.                        &
1459                        TRIM( var ) == 'rrtm_aldir*'  .OR.                        &
1460                        TRIM( var ) == 'rrtm_asdif*'  .OR.                        &
1461                        TRIM( var ) == 'rrtm_asdir*'      )                       &
1462                   THEN
1463                      message_string = 'output of "' // TRIM( var ) // '" require'&
1464                                       // 's radiation = .TRUE. and radiation_sch'&
1465                                       // 'eme = "rrtmg"'
1466                      CALL message( 'check_parameters', 'PA0409', 1, 2, 0, 6, 0 )
1467                   ENDIF
1468                ENDIF
1469
1470                IF ( TRIM( var ) == 'rad_net*'      ) unit = 'W/m2'
1471                IF ( TRIM( var ) == 'rad_lw_in*'    ) unit = 'W/m2'
1472                IF ( TRIM( var ) == 'rad_lw_out*'   ) unit = 'W/m2'
1473                IF ( TRIM( var ) == 'rad_sw_in*'    ) unit = 'W/m2'
1474                IF ( TRIM( var ) == 'rad_sw_out*'   ) unit = 'W/m2'
1475                IF ( TRIM( var ) == 'rad_sw_in'     ) unit = 'W/m2'
1476                IF ( TRIM( var ) == 'rrtm_aldif*'   ) unit = ''
1477                IF ( TRIM( var ) == 'rrtm_aldir*'   ) unit = ''
1478                IF ( TRIM( var ) == 'rrtm_asdif*'   ) unit = ''
1479                IF ( TRIM( var ) == 'rrtm_asdir*'   ) unit = ''
1480
1481             CASE ( 'rtm_rad_pc_inlw', 'rtm_rad_pc_insw', 'rtm_rad_pc_inswdir', &
1482                    'rtm_rad_pc_inswdif', 'rtm_rad_pc_inswref')
1483                IF ( .NOT.  radiation ) THEN
1484                   message_string = 'output of "' // TRIM( var ) // '" require'&
1485                                    // 's radiation = .TRUE.'
1486                   CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1487                ENDIF
1488                unit = 'W'
1489
1490             CASE ( 'rtm_mrt', 'rtm_mrt_sw', 'rtm_mrt_lw'  )
1491                IF ( i == 0 .AND. ilen == 0 .AND. k == 0)  THEN
1492                   ! Workaround for masked output (calls with i=ilen=k=0)
1493                   unit = 'illegal'
1494                   RETURN
1495                ENDIF
1496
1497                IF ( .NOT.  radiation ) THEN
1498                   message_string = 'output of "' // TRIM( var ) // '" require'&
1499                                    // 's radiation = .TRUE.'
1500                   CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1501                ENDIF
1502                IF ( mrt_nlevels == 0 ) THEN
1503                   message_string = 'output of "' // TRIM( var ) // '" require'&
1504                                    // 's mrt_nlevels > 0'
1505                   CALL message( 'check_parameters', 'PA0510', 1, 2, 0, 6, 0 )
1506                ENDIF
1507                IF ( TRIM( var ) == 'rtm_mrt_sw'  .AND.  .NOT. mrt_include_sw ) THEN
1508                   message_string = 'output of "' // TRIM( var ) // '" require'&
1509                                    // 's rtm_mrt_sw = .TRUE.'
1510                   CALL message( 'check_parameters', 'PA0511', 1, 2, 0, 6, 0 )
1511                ENDIF
1512                IF ( TRIM( var ) == 'rtm_mrt' ) THEN
1513                   unit = 'K'
1514                ELSE
1515                   unit = 'W m-2'
1516                ENDIF
1517
1518             CASE DEFAULT
1519                unit = 'illegal'
1520
1521          END SELECT
1522       ENDIF
1523
1524    END SUBROUTINE radiation_check_data_output
1525
1526
1527!------------------------------------------------------------------------------!
1528! Description:
1529! ------------
1530!> Set module-specific timeseries units and labels
1531!------------------------------------------------------------------------------!
1532 SUBROUTINE radiation_check_data_output_ts( dots_max, dots_num )
1533
1534
1535    INTEGER(iwp),      INTENT(IN)     ::  dots_max
1536    INTEGER(iwp),      INTENT(INOUT)  ::  dots_num
1537
1538!
1539!-- Next line is just to avoid compiler warning about unused variable.
1540    IF ( dots_max == 0 )  CONTINUE
1541
1542!
1543!-- Temporary solution to add LSM and radiation time series to the default
1544!-- output
1545    IF ( land_surface  .OR.  radiation )  THEN
1546       IF ( TRIM( radiation_scheme ) == 'rrtmg' )  THEN
1547          dots_num = dots_num + 15
1548       ELSE
1549          dots_num = dots_num + 11
1550       ENDIF
1551    ENDIF
1552
1553
1554 END SUBROUTINE radiation_check_data_output_ts
1555
1556!------------------------------------------------------------------------------!
1557! Description:
1558! ------------
1559!> Check data output of profiles for radiation model
1560!------------------------------------------------------------------------------! 
1561    SUBROUTINE radiation_check_data_output_pr( variable, var_count, unit,      &
1562               dopr_unit )
1563 
1564       USE arrays_3d,                                                          &
1565           ONLY: zu
1566
1567       USE control_parameters,                                                 &
1568           ONLY: data_output_pr, message_string
1569
1570       USE indices
1571
1572       USE profil_parameter
1573
1574       USE statistics
1575
1576       IMPLICIT NONE
1577   
1578       CHARACTER (LEN=*) ::  unit      !<
1579       CHARACTER (LEN=*) ::  variable  !<
1580       CHARACTER (LEN=*) ::  dopr_unit !< local value of dopr_unit
1581 
1582       INTEGER(iwp) ::  var_count     !<
1583
1584       SELECT CASE ( TRIM( variable ) )
1585       
1586         CASE ( 'rad_net' )
1587             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme == 'constant' )&
1588             THEN
1589                message_string = 'data_output_pr = ' //                        &
1590                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1591                                 'not available for radiation = .FALSE. or ' //&
1592                                 'radiation_scheme = "constant"'
1593                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1594             ELSE
1595                dopr_index(var_count) = 99
1596                dopr_unit  = 'W/m2'
1597                hom(:,2,99,:)  = SPREAD( zw, 2, statistic_regions+1 )
1598                unit = dopr_unit
1599             ENDIF
1600
1601          CASE ( 'rad_lw_in' )
1602             IF ( (  .NOT.  radiation)  .OR.  radiation_scheme == 'constant' ) &
1603             THEN
1604                message_string = 'data_output_pr = ' //                        &
1605                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1606                                 'not available for radiation = .FALSE. or ' //&
1607                                 'radiation_scheme = "constant"'
1608                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1609             ELSE
1610                dopr_index(var_count) = 100
1611                dopr_unit  = 'W/m2'
1612                hom(:,2,100,:)  = SPREAD( zw, 2, statistic_regions+1 )
1613                unit = dopr_unit 
1614             ENDIF
1615
1616          CASE ( 'rad_lw_out' )
1617             IF ( (  .NOT. radiation )  .OR.  radiation_scheme == 'constant' ) &
1618             THEN
1619                message_string = 'data_output_pr = ' //                        &
1620                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1621                                 'not available for radiation = .FALSE. or ' //&
1622                                 'radiation_scheme = "constant"'
1623                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1624             ELSE
1625                dopr_index(var_count) = 101
1626                dopr_unit  = 'W/m2'
1627                hom(:,2,101,:)  = SPREAD( zw, 2, statistic_regions+1 )
1628                unit = dopr_unit   
1629             ENDIF
1630
1631          CASE ( 'rad_sw_in' )
1632             IF ( (  .NOT. radiation )  .OR.  radiation_scheme == 'constant' ) &
1633             THEN
1634                message_string = 'data_output_pr = ' //                        &
1635                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1636                                 'not available for radiation = .FALSE. or ' //&
1637                                 'radiation_scheme = "constant"'
1638                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1639             ELSE
1640                dopr_index(var_count) = 102
1641                dopr_unit  = 'W/m2'
1642                hom(:,2,102,:)  = SPREAD( zw, 2, statistic_regions+1 )
1643                unit = dopr_unit
1644             ENDIF
1645
1646          CASE ( 'rad_sw_out')
1647             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme == 'constant' )&
1648             THEN
1649                message_string = 'data_output_pr = ' //                        &
1650                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1651                                 'not available for radiation = .FALSE. or ' //&
1652                                 'radiation_scheme = "constant"'
1653                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1654             ELSE
1655                dopr_index(var_count) = 103
1656                dopr_unit  = 'W/m2'
1657                hom(:,2,103,:)  = SPREAD( zw, 2, statistic_regions+1 )
1658                unit = dopr_unit
1659             ENDIF
1660
1661          CASE ( 'rad_lw_cs_hr' )
1662             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1663             THEN
1664                message_string = 'data_output_pr = ' //                        &
1665                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1666                                 'not available for radiation = .FALSE. or ' //&
1667                                 'radiation_scheme /= "rrtmg"'
1668                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1669             ELSE
1670                dopr_index(var_count) = 104
1671                dopr_unit  = 'K/h'
1672                hom(:,2,104,:)  = SPREAD( zu, 2, statistic_regions+1 )
1673                unit = dopr_unit
1674             ENDIF
1675
1676          CASE ( 'rad_lw_hr' )
1677             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1678             THEN
1679                message_string = 'data_output_pr = ' //                        &
1680                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1681                                 'not available for radiation = .FALSE. or ' //&
1682                                 'radiation_scheme /= "rrtmg"'
1683                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1684             ELSE
1685                dopr_index(var_count) = 105
1686                dopr_unit  = 'K/h'
1687                hom(:,2,105,:)  = SPREAD( zu, 2, statistic_regions+1 )
1688                unit = dopr_unit
1689             ENDIF
1690
1691          CASE ( 'rad_sw_cs_hr' )
1692             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1693             THEN
1694                message_string = 'data_output_pr = ' //                        &
1695                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1696                                 'not available for radiation = .FALSE. or ' //&
1697                                 'radiation_scheme /= "rrtmg"'
1698                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1699             ELSE
1700                dopr_index(var_count) = 106
1701                dopr_unit  = 'K/h'
1702                hom(:,2,106,:)  = SPREAD( zu, 2, statistic_regions+1 )
1703                unit = dopr_unit
1704             ENDIF
1705
1706          CASE ( 'rad_sw_hr' )
1707             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1708             THEN
1709                message_string = 'data_output_pr = ' //                        &
1710                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1711                                 'not available for radiation = .FALSE. or ' //&
1712                                 'radiation_scheme /= "rrtmg"'
1713                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1714             ELSE
1715                dopr_index(var_count) = 107
1716                dopr_unit  = 'K/h'
1717                hom(:,2,107,:)  = SPREAD( zu, 2, statistic_regions+1 )
1718                unit = dopr_unit
1719             ENDIF
1720
1721
1722          CASE DEFAULT
1723             unit = 'illegal'
1724
1725       END SELECT
1726
1727
1728    END SUBROUTINE radiation_check_data_output_pr
1729 
1730 
1731!------------------------------------------------------------------------------!
1732! Description:
1733! ------------
1734!> Check parameters routine for radiation model
1735!------------------------------------------------------------------------------!
1736    SUBROUTINE radiation_check_parameters
1737
1738       USE control_parameters,                                                 &
1739           ONLY: land_surface, message_string, urban_surface
1740
1741       USE netcdf_data_input_mod,                                              &
1742           ONLY:  input_pids_static                 
1743   
1744       IMPLICIT NONE
1745       
1746!
1747!--    In case no urban-surface or land-surface model is applied, usage of
1748!--    a radiation model make no sense.         
1749       IF ( .NOT. land_surface  .AND.  .NOT. urban_surface )  THEN
1750          message_string = 'Usage of radiation module is only allowed if ' //  &
1751                           'land-surface and/or urban-surface model is applied.'
1752          CALL message( 'check_parameters', 'PA0486', 1, 2, 0, 6, 0 )
1753       ENDIF
1754
1755       IF ( radiation_scheme /= 'constant'   .AND.                             &
1756            radiation_scheme /= 'clear-sky'  .AND.                             &
1757            radiation_scheme /= 'rrtmg' )  THEN
1758          message_string = 'unknown radiation_scheme = '//                     &
1759                           TRIM( radiation_scheme )
1760          CALL message( 'check_parameters', 'PA0405', 1, 2, 0, 6, 0 )
1761       ELSEIF ( radiation_scheme == 'rrtmg' )  THEN
1762#if ! defined ( __rrtmg )
1763          message_string = 'radiation_scheme = "rrtmg" requires ' //           & 
1764                           'compilation of PALM with pre-processor ' //        &
1765                           'directive -D__rrtmg'
1766          CALL message( 'check_parameters', 'PA0407', 1, 2, 0, 6, 0 )
1767#endif
1768#if defined ( __rrtmg ) && ! defined( __netcdf )
1769          message_string = 'radiation_scheme = "rrtmg" requires ' //           & 
1770                           'the use of NetCDF (preprocessor directive ' //     &
1771                           '-D__netcdf'
1772          CALL message( 'check_parameters', 'PA0412', 1, 2, 0, 6, 0 )
1773#endif
1774
1775       ENDIF
1776!
1777!--    Checks performed only if data is given via namelist only.
1778       IF ( .NOT. input_pids_static )  THEN
1779          IF ( albedo_type == 0  .AND.  albedo == 9999999.9_wp  .AND.          &
1780               radiation_scheme == 'clear-sky')  THEN
1781             message_string = 'radiation_scheme = "clear-sky" in combination'//& 
1782                              'with albedo_type = 0 requires setting of'//     &
1783                              'albedo /= 9999999.9'
1784             CALL message( 'check_parameters', 'PA0410', 1, 2, 0, 6, 0 )
1785          ENDIF
1786
1787          IF ( albedo_type == 0  .AND.  radiation_scheme == 'rrtmg'  .AND.     &
1788             ( albedo_lw_dif == 9999999.9_wp .OR. albedo_lw_dir == 9999999.9_wp&
1789          .OR. albedo_sw_dif == 9999999.9_wp .OR. albedo_sw_dir == 9999999.9_wp& 
1790             ) ) THEN
1791             message_string = 'radiation_scheme = "rrtmg" in combination' //   & 
1792                              'with albedo_type = 0 requires setting of ' //   &
1793                              'albedo_lw_dif /= 9999999.9' //                  &
1794                              'albedo_lw_dir /= 9999999.9' //                  &
1795                              'albedo_sw_dif /= 9999999.9 and' //              &
1796                              'albedo_sw_dir /= 9999999.9'
1797             CALL message( 'check_parameters', 'PA0411', 1, 2, 0, 6, 0 )
1798          ENDIF
1799       ENDIF
1800!
1801!--    Parallel rad_angular_discretization without raytrace_mpi_rma is not implemented
1802#if defined( __parallel )     
1803       IF ( rad_angular_discretization  .AND.  .NOT. raytrace_mpi_rma )  THEN
1804          message_string = 'rad_angular_discretization can only be used ' //  &
1805                           'together with raytrace_mpi_rma or when ' //  &
1806                           'no parallelization is applied.'
1807          CALL message( 'check_parameters', 'PA0486', 1, 2, 0, 6, 0 )
1808       ENDIF
1809#endif
1810
1811       IF ( cloud_droplets  .AND.   radiation_scheme == 'rrtmg'  .AND.         &
1812            average_radiation ) THEN
1813          message_string = 'average_radiation = .T. with radiation_scheme'//   & 
1814                           '= "rrtmg" in combination cloud_droplets = .T.'//   &
1815                           'is not implementd'
1816          CALL message( 'check_parameters', 'PA0560', 1, 2, 0, 6, 0 )
1817       ENDIF
1818
1819!
1820!--    Incialize svf normalization reporting histogram
1821       svfnorm_report_num = 1
1822       DO WHILE ( svfnorm_report_thresh(svfnorm_report_num) < 1e20_wp          &
1823                   .AND. svfnorm_report_num <= 30 )
1824          svfnorm_report_num = svfnorm_report_num + 1
1825       ENDDO
1826       svfnorm_report_num = svfnorm_report_num - 1
1827!
1828!--    Check for dt_radiation
1829       IF ( dt_radiation <= 0.0 )  THEN
1830          message_string = 'dt_radiation must be > 0.0' 
1831          CALL message( 'check_parameters', 'PA0591', 1, 2, 0, 6, 0 ) 
1832       ENDIF
1833 
1834    END SUBROUTINE radiation_check_parameters 
1835 
1836 
1837!------------------------------------------------------------------------------!
1838! Description:
1839! ------------
1840!> Initialization of the radiation model
1841!------------------------------------------------------------------------------!
1842    SUBROUTINE radiation_init
1843   
1844       IMPLICIT NONE
1845
1846       INTEGER(iwp) ::  i         !< running index x-direction
1847       INTEGER(iwp) ::  ioff      !< offset in x between surface element reference grid point in atmosphere and actual surface
1848       INTEGER(iwp) ::  j         !< running index y-direction
1849       INTEGER(iwp) ::  joff      !< offset in y between surface element reference grid point in atmosphere and actual surface
1850       INTEGER(iwp) ::  l         !< running index for orientation of vertical surfaces
1851       INTEGER(iwp) ::  m         !< running index for surface elements
1852#if defined( __rrtmg )
1853       INTEGER(iwp) ::  ind_type  !< running index for subgrid-surface tiles
1854#endif
1855
1856
1857       IF ( debug_output )  CALL debug_message( 'radiation_init', 'start' )
1858!
1859!--    Activate radiation_interactions according to the existence of vertical surfaces and/or trees.
1860!--    The namelist parameter radiation_interactions_on can override this behavior.
1861!--    (This check cannot be performed in check_parameters, because vertical_surfaces_exist is first set in
1862!--    init_surface_arrays.)
1863       IF ( radiation_interactions_on )  THEN
1864          IF ( vertical_surfaces_exist  .OR.  plant_canopy )  THEN
1865             radiation_interactions    = .TRUE.
1866             average_radiation         = .TRUE.
1867          ELSE
1868             radiation_interactions_on = .FALSE.   !< reset namelist parameter: no interactions
1869                                                   !< calculations necessary in case of flat surface
1870          ENDIF
1871       ELSEIF ( vertical_surfaces_exist  .OR.  plant_canopy )  THEN
1872          message_string = 'radiation_interactions_on is set to .FALSE. although '     // &
1873                           'vertical surfaces and/or trees exist. The model will run ' // &
1874                           'without RTM (no shadows, no radiation reflections)'
1875          CALL message( 'init_3d_model', 'PA0348', 0, 1, 0, 6, 0 )
1876       ENDIF
1877!
1878!--    If required, initialize radiation interactions between surfaces
1879!--    via sky-view factors. This must be done before radiation is initialized.
1880       IF ( radiation_interactions )  CALL radiation_interaction_init
1881!
1882!--    Allocate array for storing the surface net radiation
1883       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_net )  .AND.                      &
1884                  surf_lsm_h%ns > 0  )   THEN
1885          ALLOCATE( surf_lsm_h%rad_net(1:surf_lsm_h%ns) )
1886          surf_lsm_h%rad_net = 0.0_wp 
1887       ENDIF
1888       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_net )  .AND.                      &
1889                  surf_usm_h%ns > 0  )  THEN
1890          ALLOCATE( surf_usm_h%rad_net(1:surf_usm_h%ns) )
1891          surf_usm_h%rad_net = 0.0_wp 
1892       ENDIF
1893       DO  l = 0, 3
1894          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_net )  .AND.                &
1895                     surf_lsm_v(l)%ns > 0  )  THEN
1896             ALLOCATE( surf_lsm_v(l)%rad_net(1:surf_lsm_v(l)%ns) )
1897             surf_lsm_v(l)%rad_net = 0.0_wp 
1898          ENDIF
1899          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_net )  .AND.                &
1900                     surf_usm_v(l)%ns > 0  )  THEN
1901             ALLOCATE( surf_usm_v(l)%rad_net(1:surf_usm_v(l)%ns) )
1902             surf_usm_v(l)%rad_net = 0.0_wp 
1903          ENDIF
1904       ENDDO
1905
1906
1907!
1908!--    Allocate array for storing the surface longwave (out) radiation change
1909       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_lw_out_change_0 )  .AND.          &
1910                  surf_lsm_h%ns > 0  )   THEN
1911          ALLOCATE( surf_lsm_h%rad_lw_out_change_0(1:surf_lsm_h%ns) )
1912          surf_lsm_h%rad_lw_out_change_0 = 0.0_wp 
1913       ENDIF
1914       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_lw_out_change_0 )  .AND.          &
1915                  surf_usm_h%ns > 0  )  THEN
1916          ALLOCATE( surf_usm_h%rad_lw_out_change_0(1:surf_usm_h%ns) )
1917          surf_usm_h%rad_lw_out_change_0 = 0.0_wp 
1918       ENDIF
1919       DO  l = 0, 3
1920          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_lw_out_change_0 )  .AND.    &
1921                     surf_lsm_v(l)%ns > 0  )  THEN
1922             ALLOCATE( surf_lsm_v(l)%rad_lw_out_change_0(1:surf_lsm_v(l)%ns) )
1923             surf_lsm_v(l)%rad_lw_out_change_0 = 0.0_wp 
1924          ENDIF
1925          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_lw_out_change_0 )  .AND.    &
1926                     surf_usm_v(l)%ns > 0  )  THEN
1927             ALLOCATE( surf_usm_v(l)%rad_lw_out_change_0(1:surf_usm_v(l)%ns) )
1928             surf_usm_v(l)%rad_lw_out_change_0 = 0.0_wp 
1929          ENDIF
1930       ENDDO
1931
1932!
1933!--    Allocate surface arrays for incoming/outgoing short/longwave radiation
1934       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_sw_in )  .AND.                    &
1935                  surf_lsm_h%ns > 0  )   THEN
1936          ALLOCATE( surf_lsm_h%rad_sw_in(1:surf_lsm_h%ns)  )
1937          ALLOCATE( surf_lsm_h%rad_sw_out(1:surf_lsm_h%ns) )
1938          ALLOCATE( surf_lsm_h%rad_sw_dir(1:surf_lsm_h%ns) )
1939          ALLOCATE( surf_lsm_h%rad_sw_dif(1:surf_lsm_h%ns) )
1940          ALLOCATE( surf_lsm_h%rad_sw_ref(1:surf_lsm_h%ns) )
1941          ALLOCATE( surf_lsm_h%rad_sw_res(1:surf_lsm_h%ns) )
1942          ALLOCATE( surf_lsm_h%rad_lw_in(1:surf_lsm_h%ns)  )
1943          ALLOCATE( surf_lsm_h%rad_lw_out(1:surf_lsm_h%ns) )
1944          ALLOCATE( surf_lsm_h%rad_lw_dif(1:surf_lsm_h%ns) )
1945          ALLOCATE( surf_lsm_h%rad_lw_ref(1:surf_lsm_h%ns) )
1946          ALLOCATE( surf_lsm_h%rad_lw_res(1:surf_lsm_h%ns) )
1947          surf_lsm_h%rad_sw_in  = 0.0_wp 
1948          surf_lsm_h%rad_sw_out = 0.0_wp 
1949          surf_lsm_h%rad_sw_dir = 0.0_wp 
1950          surf_lsm_h%rad_sw_dif = 0.0_wp 
1951          surf_lsm_h%rad_sw_ref = 0.0_wp 
1952          surf_lsm_h%rad_sw_res = 0.0_wp 
1953          surf_lsm_h%rad_lw_in  = 0.0_wp 
1954          surf_lsm_h%rad_lw_out = 0.0_wp 
1955          surf_lsm_h%rad_lw_dif = 0.0_wp 
1956          surf_lsm_h%rad_lw_ref = 0.0_wp 
1957          surf_lsm_h%rad_lw_res = 0.0_wp 
1958       ENDIF
1959       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_sw_in )  .AND.                    &
1960                  surf_usm_h%ns > 0  )  THEN
1961          ALLOCATE( surf_usm_h%rad_sw_in(1:surf_usm_h%ns)  )
1962          ALLOCATE( surf_usm_h%rad_sw_out(1:surf_usm_h%ns) )
1963          ALLOCATE( surf_usm_h%rad_sw_dir(1:surf_usm_h%ns) )
1964          ALLOCATE( surf_usm_h%rad_sw_dif(1:surf_usm_h%ns) )
1965          ALLOCATE( surf_usm_h%rad_sw_ref(1:surf_usm_h%ns) )
1966          ALLOCATE( surf_usm_h%rad_sw_res(1:surf_usm_h%ns) )
1967          ALLOCATE( surf_usm_h%rad_lw_in(1:surf_usm_h%ns)  )
1968          ALLOCATE( surf_usm_h%rad_lw_out(1:surf_usm_h%ns) )
1969          ALLOCATE( surf_usm_h%rad_lw_dif(1:surf_usm_h%ns) )
1970          ALLOCATE( surf_usm_h%rad_lw_ref(1:surf_usm_h%ns) )
1971          ALLOCATE( surf_usm_h%rad_lw_res(1:surf_usm_h%ns) )
1972          surf_usm_h%rad_sw_in  = 0.0_wp 
1973          surf_usm_h%rad_sw_out = 0.0_wp 
1974          surf_usm_h%rad_sw_dir = 0.0_wp 
1975          surf_usm_h%rad_sw_dif = 0.0_wp 
1976          surf_usm_h%rad_sw_ref = 0.0_wp 
1977          surf_usm_h%rad_sw_res = 0.0_wp 
1978          surf_usm_h%rad_lw_in  = 0.0_wp 
1979          surf_usm_h%rad_lw_out = 0.0_wp 
1980          surf_usm_h%rad_lw_dif = 0.0_wp 
1981          surf_usm_h%rad_lw_ref = 0.0_wp 
1982          surf_usm_h%rad_lw_res = 0.0_wp 
1983       ENDIF
1984       DO  l = 0, 3
1985          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_sw_in )  .AND.              &
1986                     surf_lsm_v(l)%ns > 0  )  THEN
1987             ALLOCATE( surf_lsm_v(l)%rad_sw_in(1:surf_lsm_v(l)%ns)  )
1988             ALLOCATE( surf_lsm_v(l)%rad_sw_out(1:surf_lsm_v(l)%ns) )
1989             ALLOCATE( surf_lsm_v(l)%rad_sw_dir(1:surf_lsm_v(l)%ns) )
1990             ALLOCATE( surf_lsm_v(l)%rad_sw_dif(1:surf_lsm_v(l)%ns) )
1991             ALLOCATE( surf_lsm_v(l)%rad_sw_ref(1:surf_lsm_v(l)%ns) )
1992             ALLOCATE( surf_lsm_v(l)%rad_sw_res(1:surf_lsm_v(l)%ns) )
1993
1994             ALLOCATE( surf_lsm_v(l)%rad_lw_in(1:surf_lsm_v(l)%ns)  )
1995             ALLOCATE( surf_lsm_v(l)%rad_lw_out(1:surf_lsm_v(l)%ns) )
1996             ALLOCATE( surf_lsm_v(l)%rad_lw_dif(1:surf_lsm_v(l)%ns) )
1997             ALLOCATE( surf_lsm_v(l)%rad_lw_ref(1:surf_lsm_v(l)%ns) )
1998             ALLOCATE( surf_lsm_v(l)%rad_lw_res(1:surf_lsm_v(l)%ns) )
1999
2000             surf_lsm_v(l)%rad_sw_in  = 0.0_wp 
2001             surf_lsm_v(l)%rad_sw_out = 0.0_wp
2002             surf_lsm_v(l)%rad_sw_dir = 0.0_wp
2003             surf_lsm_v(l)%rad_sw_dif = 0.0_wp
2004             surf_lsm_v(l)%rad_sw_ref = 0.0_wp
2005             surf_lsm_v(l)%rad_sw_res = 0.0_wp
2006
2007             surf_lsm_v(l)%rad_lw_in  = 0.0_wp 
2008             surf_lsm_v(l)%rad_lw_out = 0.0_wp 
2009             surf_lsm_v(l)%rad_lw_dif = 0.0_wp 
2010             surf_lsm_v(l)%rad_lw_ref = 0.0_wp 
2011             surf_lsm_v(l)%rad_lw_res = 0.0_wp 
2012          ENDIF
2013          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_sw_in )  .AND.              &
2014                     surf_usm_v(l)%ns > 0  )  THEN
2015             ALLOCATE( surf_usm_v(l)%rad_sw_in(1:surf_usm_v(l)%ns)  )
2016             ALLOCATE( surf_usm_v(l)%rad_sw_out(1:surf_usm_v(l)%ns) )
2017             ALLOCATE( surf_usm_v(l)%rad_sw_dir(1:surf_usm_v(l)%ns) )
2018             ALLOCATE( surf_usm_v(l)%rad_sw_dif(1:surf_usm_v(l)%ns) )
2019             ALLOCATE( surf_usm_v(l)%rad_sw_ref(1:surf_usm_v(l)%ns) )
2020             ALLOCATE( surf_usm_v(l)%rad_sw_res(1:surf_usm_v(l)%ns) )
2021             ALLOCATE( surf_usm_v(l)%rad_lw_in(1:surf_usm_v(l)%ns)  )
2022             ALLOCATE( surf_usm_v(l)%rad_lw_out(1:surf_usm_v(l)%ns) )
2023             ALLOCATE( surf_usm_v(l)%rad_lw_dif(1:surf_usm_v(l)%ns) )
2024             ALLOCATE( surf_usm_v(l)%rad_lw_ref(1:surf_usm_v(l)%ns) )
2025             ALLOCATE( surf_usm_v(l)%rad_lw_res(1:surf_usm_v(l)%ns) )
2026             surf_usm_v(l)%rad_sw_in  = 0.0_wp 
2027             surf_usm_v(l)%rad_sw_out = 0.0_wp
2028             surf_usm_v(l)%rad_sw_dir = 0.0_wp
2029             surf_usm_v(l)%rad_sw_dif = 0.0_wp
2030             surf_usm_v(l)%rad_sw_ref = 0.0_wp
2031             surf_usm_v(l)%rad_sw_res = 0.0_wp
2032             surf_usm_v(l)%rad_lw_in  = 0.0_wp 
2033             surf_usm_v(l)%rad_lw_out = 0.0_wp 
2034             surf_usm_v(l)%rad_lw_dif = 0.0_wp 
2035             surf_usm_v(l)%rad_lw_ref = 0.0_wp 
2036             surf_usm_v(l)%rad_lw_res = 0.0_wp 
2037          ENDIF
2038       ENDDO
2039!
2040!--    Fix net radiation in case of radiation_scheme = 'constant'
2041       IF ( radiation_scheme == 'constant' )  THEN
2042          IF ( ALLOCATED( surf_lsm_h%rad_net ) )                               &
2043             surf_lsm_h%rad_net    = net_radiation
2044          IF ( ALLOCATED( surf_usm_h%rad_net ) )                               &
2045             surf_usm_h%rad_net    = net_radiation
2046!
2047!--       Todo: weight with inclination angle
2048          DO  l = 0, 3
2049             IF ( ALLOCATED( surf_lsm_v(l)%rad_net ) )                         &
2050                surf_lsm_v(l)%rad_net = net_radiation
2051             IF ( ALLOCATED( surf_usm_v(l)%rad_net ) )                         &
2052                surf_usm_v(l)%rad_net = net_radiation
2053          ENDDO
2054!          radiation = .FALSE.
2055!
2056!--    Calculate orbital constants
2057       ELSE
2058          decl_1 = SIN(23.45_wp * pi / 180.0_wp)
2059          decl_2 = 2.0_wp * pi / 365.0_wp
2060          decl_3 = decl_2 * 81.0_wp
2061          lat    = latitude * pi / 180.0_wp
2062          lon    = longitude * pi / 180.0_wp
2063       ENDIF
2064
2065       IF ( radiation_scheme == 'clear-sky'  .OR.                              &
2066            radiation_scheme == 'constant')  THEN
2067
2068
2069!
2070!--       Allocate arrays for incoming/outgoing short/longwave radiation
2071          IF ( .NOT. ALLOCATED ( rad_sw_in ) )  THEN
2072             ALLOCATE ( rad_sw_in(0:0,nysg:nyng,nxlg:nxrg) )
2073          ENDIF
2074          IF ( .NOT. ALLOCATED ( rad_sw_out ) )  THEN
2075             ALLOCATE ( rad_sw_out(0:0,nysg:nyng,nxlg:nxrg) )
2076          ENDIF
2077
2078          IF ( .NOT. ALLOCATED ( rad_lw_in ) )  THEN
2079             ALLOCATE ( rad_lw_in(0:0,nysg:nyng,nxlg:nxrg) )
2080          ENDIF
2081          IF ( .NOT. ALLOCATED ( rad_lw_out ) )  THEN
2082             ALLOCATE ( rad_lw_out(0:0,nysg:nyng,nxlg:nxrg) )
2083          ENDIF
2084
2085!
2086!--       Allocate average arrays for incoming/outgoing short/longwave radiation
2087          IF ( .NOT. ALLOCATED ( rad_sw_in_av ) )  THEN
2088             ALLOCATE ( rad_sw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
2089          ENDIF
2090          IF ( .NOT. ALLOCATED ( rad_sw_out_av ) )  THEN
2091             ALLOCATE ( rad_sw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
2092          ENDIF
2093
2094          IF ( .NOT. ALLOCATED ( rad_lw_in_av ) )  THEN
2095             ALLOCATE ( rad_lw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
2096          ENDIF
2097          IF ( .NOT. ALLOCATED ( rad_lw_out_av ) )  THEN
2098             ALLOCATE ( rad_lw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
2099          ENDIF
2100!
2101!--       Allocate arrays for broadband albedo, and level 1 initialization
2102!--       via namelist paramter, unless not already allocated.
2103          IF ( .NOT. ALLOCATED(surf_lsm_h%albedo) )  THEN
2104             ALLOCATE( surf_lsm_h%albedo(0:2,1:surf_lsm_h%ns)     )
2105             surf_lsm_h%albedo    = albedo
2106          ENDIF
2107          IF ( .NOT. ALLOCATED(surf_usm_h%albedo) )  THEN
2108             ALLOCATE( surf_usm_h%albedo(0:2,1:surf_usm_h%ns)     )
2109             surf_usm_h%albedo    = albedo
2110          ENDIF
2111
2112          DO  l = 0, 3
2113             IF ( .NOT. ALLOCATED( surf_lsm_v(l)%albedo ) )  THEN
2114                ALLOCATE( surf_lsm_v(l)%albedo(0:2,1:surf_lsm_v(l)%ns) )
2115                surf_lsm_v(l)%albedo = albedo
2116             ENDIF
2117             IF ( .NOT. ALLOCATED( surf_usm_v(l)%albedo ) )  THEN
2118                ALLOCATE( surf_usm_v(l)%albedo(0:2,1:surf_usm_v(l)%ns) )
2119                surf_usm_v(l)%albedo = albedo
2120             ENDIF
2121          ENDDO
2122!
2123!--       Level 2 initialization of broadband albedo via given albedo_type.
2124!--       Only if albedo_type is non-zero. In case of urban surface and
2125!--       input data is read from ASCII file, albedo_type will be zero, so that
2126!--       albedo won't be overwritten.
2127          DO  m = 1, surf_lsm_h%ns
2128             IF ( surf_lsm_h%albedo_type(ind_veg_wall,m) /= 0 )                &
2129                surf_lsm_h%albedo(ind_veg_wall,m) =                            &
2130                           albedo_pars(2,surf_lsm_h%albedo_type(ind_veg_wall,m))
2131             IF ( surf_lsm_h%albedo_type(ind_pav_green,m) /= 0 )               &
2132                surf_lsm_h%albedo(ind_pav_green,m) =                           &
2133                           albedo_pars(2,surf_lsm_h%albedo_type(ind_pav_green,m))
2134             IF ( surf_lsm_h%albedo_type(ind_wat_win,m) /= 0 )                 &
2135                surf_lsm_h%albedo(ind_wat_win,m) =                             &
2136                           albedo_pars(2,surf_lsm_h%albedo_type(ind_wat_win,m))
2137          ENDDO
2138          DO  m = 1, surf_usm_h%ns
2139             IF ( surf_usm_h%albedo_type(ind_veg_wall,m) /= 0 )                &
2140                surf_usm_h%albedo(ind_veg_wall,m) =                            &
2141                           albedo_pars(2,surf_usm_h%albedo_type(ind_veg_wall,m))
2142             IF ( surf_usm_h%albedo_type(ind_pav_green,m) /= 0 )               &
2143                surf_usm_h%albedo(ind_pav_green,m) =                           &
2144                           albedo_pars(2,surf_usm_h%albedo_type(ind_pav_green,m))
2145             IF ( surf_usm_h%albedo_type(ind_wat_win,m) /= 0 )                 &
2146                surf_usm_h%albedo(ind_wat_win,m) =                             &
2147                           albedo_pars(2,surf_usm_h%albedo_type(ind_wat_win,m))
2148          ENDDO
2149
2150          DO  l = 0, 3
2151             DO  m = 1, surf_lsm_v(l)%ns
2152                IF ( surf_lsm_v(l)%albedo_type(ind_veg_wall,m) /= 0 )          &
2153                   surf_lsm_v(l)%albedo(ind_veg_wall,m) =                      &
2154                        albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_veg_wall,m))
2155                IF ( surf_lsm_v(l)%albedo_type(ind_pav_green,m) /= 0 )         &
2156                   surf_lsm_v(l)%albedo(ind_pav_green,m) =                     &
2157                        albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_pav_green,m))
2158                IF ( surf_lsm_v(l)%albedo_type(ind_wat_win,m) /= 0 )           &
2159                   surf_lsm_v(l)%albedo(ind_wat_win,m) =                       &
2160                        albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_wat_win,m))
2161             ENDDO
2162             DO  m = 1, surf_usm_v(l)%ns
2163                IF ( surf_usm_v(l)%albedo_type(ind_veg_wall,m) /= 0 )          &
2164                   surf_usm_v(l)%albedo(ind_veg_wall,m) =                      &
2165                        albedo_pars(2,surf_usm_v(l)%albedo_type(ind_veg_wall,m))
2166                IF ( surf_usm_v(l)%albedo_type(ind_pav_green,m) /= 0 )         &
2167                   surf_usm_v(l)%albedo(ind_pav_green,m) =                     &
2168                        albedo_pars(2,surf_usm_v(l)%albedo_type(ind_pav_green,m))
2169                IF ( surf_usm_v(l)%albedo_type(ind_wat_win,m) /= 0 )           &
2170                   surf_usm_v(l)%albedo(ind_wat_win,m) =                       &
2171                        albedo_pars(2,surf_usm_v(l)%albedo_type(ind_wat_win,m))
2172             ENDDO
2173          ENDDO
2174
2175!
2176!--       Level 3 initialization at grid points where albedo type is zero.
2177!--       This case, albedo is taken from file. In case of constant radiation
2178!--       or clear sky, only broadband albedo is given.
2179          IF ( albedo_pars_f%from_file )  THEN
2180!
2181!--          Horizontal surfaces
2182             DO  m = 1, surf_lsm_h%ns
2183                i = surf_lsm_h%i(m)
2184                j = surf_lsm_h%j(m)
2185                IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2186                   IF ( surf_lsm_h%albedo_type(ind_veg_wall,m) == 0 )          &
2187                      surf_lsm_h%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2188                   IF ( surf_lsm_h%albedo_type(ind_pav_green,m) == 0 )         &
2189                      surf_lsm_h%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2190                   IF ( surf_lsm_h%albedo_type(ind_wat_win,m) == 0 )           &
2191                      surf_lsm_h%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2192                ENDIF
2193             ENDDO
2194             DO  m = 1, surf_usm_h%ns
2195                i = surf_usm_h%i(m)
2196                j = surf_usm_h%j(m)
2197                IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2198                   IF ( surf_usm_h%albedo_type(ind_veg_wall,m) == 0 )          &
2199                      surf_usm_h%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2200                   IF ( surf_usm_h%albedo_type(ind_pav_green,m) == 0 )         &
2201                      surf_usm_h%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2202                   IF ( surf_usm_h%albedo_type(ind_wat_win,m) == 0 )           &
2203                      surf_usm_h%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2204                ENDIF
2205             ENDDO 
2206!
2207!--          Vertical surfaces           
2208             DO  l = 0, 3
2209
2210                ioff = surf_lsm_v(l)%ioff
2211                joff = surf_lsm_v(l)%joff
2212                DO  m = 1, surf_lsm_v(l)%ns
2213                   i = surf_lsm_v(l)%i(m) + ioff
2214                   j = surf_lsm_v(l)%j(m) + joff
2215                   IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2216                      IF ( surf_lsm_v(l)%albedo_type(ind_veg_wall,m) == 0 )    &
2217                         surf_lsm_v(l)%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2218                      IF ( surf_lsm_v(l)%albedo_type(ind_pav_green,m) == 0 )   &
2219                         surf_lsm_v(l)%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2220                      IF ( surf_lsm_v(l)%albedo_type(ind_wat_win,m) == 0 )     &
2221                         surf_lsm_v(l)%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2222                   ENDIF
2223                ENDDO
2224
2225                ioff = surf_usm_v(l)%ioff
2226                joff = surf_usm_v(l)%joff
2227                DO  m = 1, surf_usm_v(l)%ns
2228                   i = surf_usm_v(l)%i(m) + joff
2229                   j = surf_usm_v(l)%j(m) + joff
2230                   IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2231                      IF ( surf_usm_v(l)%albedo_type(ind_veg_wall,m) == 0 )    &
2232                         surf_usm_v(l)%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2233                      IF ( surf_usm_v(l)%albedo_type(ind_pav_green,m) == 0 )   &
2234                         surf_usm_v(l)%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2235                      IF ( surf_usm_v(l)%albedo_type(ind_wat_win,m) == 0 )     &
2236                         surf_usm_v(l)%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2237                   ENDIF
2238                ENDDO
2239             ENDDO
2240
2241          ENDIF 
2242!
2243!--    Initialization actions for RRTMG
2244       ELSEIF ( radiation_scheme == 'rrtmg' )  THEN
2245#if defined ( __rrtmg )
2246!
2247!--       Allocate albedos for short/longwave radiation, horizontal surfaces
2248!--       for wall/green/window (USM) or vegetation/pavement/water surfaces
2249!--       (LSM).
2250          ALLOCATE ( surf_lsm_h%aldif(0:2,1:surf_lsm_h%ns)       )
2251          ALLOCATE ( surf_lsm_h%aldir(0:2,1:surf_lsm_h%ns)       )
2252          ALLOCATE ( surf_lsm_h%asdif(0:2,1:surf_lsm_h%ns)       )
2253          ALLOCATE ( surf_lsm_h%asdir(0:2,1:surf_lsm_h%ns)       )
2254          ALLOCATE ( surf_lsm_h%rrtm_aldif(0:2,1:surf_lsm_h%ns)  )
2255          ALLOCATE ( surf_lsm_h%rrtm_aldir(0:2,1:surf_lsm_h%ns)  )
2256          ALLOCATE ( surf_lsm_h%rrtm_asdif(0:2,1:surf_lsm_h%ns)  )
2257          ALLOCATE ( surf_lsm_h%rrtm_asdir(0:2,1:surf_lsm_h%ns)  )
2258
2259          ALLOCATE ( surf_usm_h%aldif(0:2,1:surf_usm_h%ns)       )
2260          ALLOCATE ( surf_usm_h%aldir(0:2,1:surf_usm_h%ns)       )
2261          ALLOCATE ( surf_usm_h%asdif(0:2,1:surf_usm_h%ns)       )
2262          ALLOCATE ( surf_usm_h%asdir(0:2,1:surf_usm_h%ns)       )
2263          ALLOCATE ( surf_usm_h%rrtm_aldif(0:2,1:surf_usm_h%ns)  )
2264          ALLOCATE ( surf_usm_h%rrtm_aldir(0:2,1:surf_usm_h%ns)  )
2265          ALLOCATE ( surf_usm_h%rrtm_asdif(0:2,1:surf_usm_h%ns)  )
2266          ALLOCATE ( surf_usm_h%rrtm_asdir(0:2,1:surf_usm_h%ns)  )
2267
2268!
2269!--       Allocate broadband albedo (temporary for the current radiation
2270!--       implementations)
2271          IF ( .NOT. ALLOCATED(surf_lsm_h%albedo) )                            &
2272             ALLOCATE( surf_lsm_h%albedo(0:2,1:surf_lsm_h%ns)     )
2273          IF ( .NOT. ALLOCATED(surf_usm_h%albedo) )                            &
2274             ALLOCATE( surf_usm_h%albedo(0:2,1:surf_usm_h%ns)     )
2275
2276!
2277!--       Allocate albedos for short/longwave radiation, vertical surfaces
2278          DO  l = 0, 3
2279
2280             ALLOCATE ( surf_lsm_v(l)%aldif(0:2,1:surf_lsm_v(l)%ns)      )
2281             ALLOCATE ( surf_lsm_v(l)%aldir(0:2,1:surf_lsm_v(l)%ns)      )
2282             ALLOCATE ( surf_lsm_v(l)%asdif(0:2,1:surf_lsm_v(l)%ns)      )
2283             ALLOCATE ( surf_lsm_v(l)%asdir(0:2,1:surf_lsm_v(l)%ns)      )
2284
2285             ALLOCATE ( surf_lsm_v(l)%rrtm_aldif(0:2,1:surf_lsm_v(l)%ns) )
2286             ALLOCATE ( surf_lsm_v(l)%rrtm_aldir(0:2,1:surf_lsm_v(l)%ns) )
2287             ALLOCATE ( surf_lsm_v(l)%rrtm_asdif(0:2,1:surf_lsm_v(l)%ns) )
2288             ALLOCATE ( surf_lsm_v(l)%rrtm_asdir(0:2,1:surf_lsm_v(l)%ns) )
2289
2290             ALLOCATE ( surf_usm_v(l)%aldif(0:2,1:surf_usm_v(l)%ns)      )
2291             ALLOCATE ( surf_usm_v(l)%aldir(0:2,1:surf_usm_v(l)%ns)      )
2292             ALLOCATE ( surf_usm_v(l)%asdif(0:2,1:surf_usm_v(l)%ns)      )
2293             ALLOCATE ( surf_usm_v(l)%asdir(0:2,1:surf_usm_v(l)%ns)      )
2294
2295             ALLOCATE ( surf_usm_v(l)%rrtm_aldif(0:2,1:surf_usm_v(l)%ns) )
2296             ALLOCATE ( surf_usm_v(l)%rrtm_aldir(0:2,1:surf_usm_v(l)%ns) )
2297             ALLOCATE ( surf_usm_v(l)%rrtm_asdif(0:2,1:surf_usm_v(l)%ns) )
2298             ALLOCATE ( surf_usm_v(l)%rrtm_asdir(0:2,1:surf_usm_v(l)%ns) )
2299!
2300!--          Allocate broadband albedo (temporary for the current radiation
2301!--          implementations)
2302             IF ( .NOT. ALLOCATED( surf_lsm_v(l)%albedo ) )                    &
2303                ALLOCATE( surf_lsm_v(l)%albedo(0:2,1:surf_lsm_v(l)%ns) )
2304             IF ( .NOT. ALLOCATED( surf_usm_v(l)%albedo ) )                    &
2305                ALLOCATE( surf_usm_v(l)%albedo(0:2,1:surf_usm_v(l)%ns) )
2306
2307          ENDDO
2308!
2309!--       Level 1 initialization of spectral albedos via namelist
2310!--       paramters. Please note, this case all surface tiles are initialized
2311!--       the same.
2312          IF ( surf_lsm_h%ns > 0 )  THEN
2313             surf_lsm_h%aldif  = albedo_lw_dif
2314             surf_lsm_h%aldir  = albedo_lw_dir
2315             surf_lsm_h%asdif  = albedo_sw_dif
2316             surf_lsm_h%asdir  = albedo_sw_dir
2317             surf_lsm_h%albedo = albedo_sw_dif
2318          ENDIF
2319          IF ( surf_usm_h%ns > 0 )  THEN
2320             IF ( surf_usm_h%albedo_from_ascii )  THEN
2321                surf_usm_h%aldif  = surf_usm_h%albedo
2322                surf_usm_h%aldir  = surf_usm_h%albedo
2323                surf_usm_h%asdif  = surf_usm_h%albedo
2324                surf_usm_h%asdir  = surf_usm_h%albedo
2325             ELSE
2326                surf_usm_h%aldif  = albedo_lw_dif
2327                surf_usm_h%aldir  = albedo_lw_dir
2328                surf_usm_h%asdif  = albedo_sw_dif
2329                surf_usm_h%asdir  = albedo_sw_dir
2330                surf_usm_h%albedo = albedo_sw_dif
2331             ENDIF
2332          ENDIF
2333
2334          DO  l = 0, 3
2335
2336             IF ( surf_lsm_v(l)%ns > 0 )  THEN
2337                surf_lsm_v(l)%aldif  = albedo_lw_dif
2338                surf_lsm_v(l)%aldir  = albedo_lw_dir
2339                surf_lsm_v(l)%asdif  = albedo_sw_dif
2340                surf_lsm_v(l)%asdir  = albedo_sw_dir
2341                surf_lsm_v(l)%albedo = albedo_sw_dif
2342             ENDIF
2343
2344             IF ( surf_usm_v(l)%ns > 0 )  THEN
2345                IF ( surf_usm_v(l)%albedo_from_ascii )  THEN
2346                   surf_usm_v(l)%aldif  = surf_usm_v(l)%albedo
2347                   surf_usm_v(l)%aldir  = surf_usm_v(l)%albedo
2348                   surf_usm_v(l)%asdif  = surf_usm_v(l)%albedo
2349                   surf_usm_v(l)%asdir  = surf_usm_v(l)%albedo
2350                ELSE
2351                   surf_usm_v(l)%aldif  = albedo_lw_dif
2352                   surf_usm_v(l)%aldir  = albedo_lw_dir
2353                   surf_usm_v(l)%asdif  = albedo_sw_dif
2354                   surf_usm_v(l)%asdir  = albedo_sw_dir
2355                ENDIF
2356             ENDIF
2357          ENDDO
2358
2359!
2360!--       Level 2 initialization of spectral albedos via albedo_type.
2361!--       Please note, for natural- and urban-type surfaces, a tile approach
2362!--       is applied so that the resulting albedo is calculated via the weighted
2363!--       average of respective surface fractions.
2364          DO  m = 1, surf_lsm_h%ns
2365!
2366!--          Spectral albedos for vegetation/pavement/water surfaces
2367             DO  ind_type = 0, 2
2368                IF ( surf_lsm_h%albedo_type(ind_type,m) /= 0 )  THEN
2369                   surf_lsm_h%aldif(ind_type,m) =                              &
2370                               albedo_pars(0,surf_lsm_h%albedo_type(ind_type,m))
2371                   surf_lsm_h%asdif(ind_type,m) =                              &
2372                               albedo_pars(1,surf_lsm_h%albedo_type(ind_type,m))
2373                   surf_lsm_h%aldir(ind_type,m) =                              &
2374                               albedo_pars(0,surf_lsm_h%albedo_type(ind_type,m))
2375                   surf_lsm_h%asdir(ind_type,m) =                              &
2376                               albedo_pars(1,surf_lsm_h%albedo_type(ind_type,m))
2377                   surf_lsm_h%albedo(ind_type,m) =                             &
2378                               albedo_pars(2,surf_lsm_h%albedo_type(ind_type,m))
2379                ENDIF
2380             ENDDO
2381
2382          ENDDO
2383!
2384!--       For urban surface only if albedo has not been already initialized
2385!--       in the urban-surface model via the ASCII file.
2386          IF ( .NOT. surf_usm_h%albedo_from_ascii )  THEN
2387             DO  m = 1, surf_usm_h%ns
2388!
2389!--             Spectral albedos for wall/green/window surfaces
2390                DO  ind_type = 0, 2
2391                   IF ( surf_usm_h%albedo_type(ind_type,m) /= 0 )  THEN
2392                      surf_usm_h%aldif(ind_type,m) =                           &
2393                               albedo_pars(0,surf_usm_h%albedo_type(ind_type,m))
2394                      surf_usm_h%asdif(ind_type,m) =                           &
2395                               albedo_pars(1,surf_usm_h%albedo_type(ind_type,m))
2396                      surf_usm_h%aldir(ind_type,m) =                           &
2397                               albedo_pars(0,surf_usm_h%albedo_type(ind_type,m))
2398                      surf_usm_h%asdir(ind_type,m) =                           &
2399                               albedo_pars(1,surf_usm_h%albedo_type(ind_type,m))
2400                      surf_usm_h%albedo(ind_type,m) =                          &
2401                               albedo_pars(2,surf_usm_h%albedo_type(ind_type,m))
2402                   ENDIF
2403                ENDDO
2404
2405             ENDDO
2406          ENDIF
2407
2408          DO l = 0, 3
2409
2410             DO  m = 1, surf_lsm_v(l)%ns
2411!
2412!--             Spectral albedos for vegetation/pavement/water surfaces
2413                DO  ind_type = 0, 2
2414                   IF ( surf_lsm_v(l)%albedo_type(ind_type,m) /= 0 )  THEN
2415                      surf_lsm_v(l)%aldif(ind_type,m) =                        &
2416                            albedo_pars(0,surf_lsm_v(l)%albedo_type(ind_type,m))
2417                      surf_lsm_v(l)%asdif(ind_type,m) =                        &
2418                            albedo_pars(1,surf_lsm_v(l)%albedo_type(ind_type,m))
2419                      surf_lsm_v(l)%aldir(ind_type,m) =                        &
2420                            albedo_pars(0,surf_lsm_v(l)%albedo_type(ind_type,m))
2421                      surf_lsm_v(l)%asdir(ind_type,m) =                        &
2422                            albedo_pars(1,surf_lsm_v(l)%albedo_type(ind_type,m))
2423                      surf_lsm_v(l)%albedo(ind_type,m) =                       &
2424                            albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_type,m))
2425                   ENDIF
2426                ENDDO
2427             ENDDO
2428!
2429!--          For urban surface only if albedo has not been already initialized
2430!--          in the urban-surface model via the ASCII file.
2431             IF ( .NOT. surf_usm_v(l)%albedo_from_ascii )  THEN
2432                DO  m = 1, surf_usm_v(l)%ns
2433!
2434!--                Spectral albedos for wall/green/window surfaces
2435                   DO  ind_type = 0, 2
2436                      IF ( surf_usm_v(l)%albedo_type(ind_type,m) /= 0 )  THEN
2437                         surf_usm_v(l)%aldif(ind_type,m) =                     &
2438                            albedo_pars(0,surf_usm_v(l)%albedo_type(ind_type,m))
2439                         surf_usm_v(l)%asdif(ind_type,m) =                     &
2440                            albedo_pars(1,surf_usm_v(l)%albedo_type(ind_type,m))
2441                         surf_usm_v(l)%aldir(ind_type,m) =                     &
2442                            albedo_pars(0,surf_usm_v(l)%albedo_type(ind_type,m))
2443                         surf_usm_v(l)%asdir(ind_type,m) =                     &
2444                            albedo_pars(1,surf_usm_v(l)%albedo_type(ind_type,m))
2445                         surf_usm_v(l)%albedo(ind_type,m) =                    &
2446                            albedo_pars(2,surf_usm_v(l)%albedo_type(ind_type,m))
2447                      ENDIF
2448                   ENDDO
2449
2450                ENDDO
2451             ENDIF
2452          ENDDO
2453!
2454!--       Level 3 initialization at grid points where albedo type is zero.
2455!--       This case, spectral albedos are taken from file if available
2456          IF ( albedo_pars_f%from_file )  THEN
2457!
2458!--          Horizontal
2459             DO  m = 1, surf_lsm_h%ns
2460                i = surf_lsm_h%i(m)
2461                j = surf_lsm_h%j(m)
2462!
2463!--             Spectral albedos for vegetation/pavement/water surfaces
2464                DO  ind_type = 0, 2
2465                   IF ( surf_lsm_h%albedo_type(ind_type,m) == 0 )  THEN
2466                      IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )&
2467                         surf_lsm_h%albedo(ind_type,m) =                       &
2468                                                albedo_pars_f%pars_xy(0,j,i)
2469                      IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2470                         surf_lsm_h%aldir(ind_type,m) =                        &
2471                                                albedo_pars_f%pars_xy(1,j,i)
2472                      IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2473                         surf_lsm_h%aldif(ind_type,m) =                        &
2474                                                albedo_pars_f%pars_xy(1,j,i)
2475                      IF ( albedo_pars_f%pars_xy(2,j,i) /= albedo_pars_f%fill )&
2476                         surf_lsm_h%asdir(ind_type,m) =                        &
2477                                                albedo_pars_f%pars_xy(2,j,i)
2478                      IF ( albedo_pars_f%pars_xy(2,j,i) /= albedo_pars_f%fill )&
2479                         surf_lsm_h%asdif(ind_type,m) =                        &
2480                                                albedo_pars_f%pars_xy(2,j,i)
2481                   ENDIF
2482                ENDDO
2483             ENDDO
2484!
2485!--          For urban surface only if albedo has not been already initialized
2486!--          in the urban-surface model via the ASCII file.
2487             IF ( .NOT. surf_usm_h%albedo_from_ascii )  THEN
2488                DO  m = 1, surf_usm_h%ns
2489                   i = surf_usm_h%i(m)
2490                   j = surf_usm_h%j(m)
2491!
2492!--                Broadband albedos for wall/green/window surfaces
2493                   DO  ind_type = 0, 2
2494                      IF ( surf_usm_h%albedo_type(ind_type,m) == 0 )  THEN
2495                         IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )&
2496                            surf_usm_h%albedo(ind_type,m) =                       &
2497                                                albedo_pars_f%pars_xy(0,j,i)
2498                      ENDIF
2499                   ENDDO
2500!
2501!--                Spectral albedos especially for building wall surfaces
2502                   IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )  THEN
2503                      surf_usm_h%aldir(ind_veg_wall,m) =                       &
2504                                                albedo_pars_f%pars_xy(1,j,i)
2505                      surf_usm_h%aldif(ind_veg_wall,m) =                       &
2506                                                albedo_pars_f%pars_xy(1,j,i)
2507                   ENDIF
2508                   IF ( albedo_pars_f%pars_xy(2,j,i) /= albedo_pars_f%fill )  THEN
2509                      surf_usm_h%asdir(ind_veg_wall,m) =                       &
2510                                                albedo_pars_f%pars_xy(2,j,i)
2511                      surf_usm_h%asdif(ind_veg_wall,m) =                       &
2512                                                albedo_pars_f%pars_xy(2,j,i)
2513                   ENDIF
2514!
2515!--                Spectral albedos especially for building green surfaces
2516                   IF ( albedo_pars_f%pars_xy(3,j,i) /= albedo_pars_f%fill )  THEN
2517                      surf_usm_h%aldir(ind_pav_green,m) =                      &
2518                                                albedo_pars_f%pars_xy(3,j,i)
2519                      surf_usm_h%aldif(ind_pav_green,m) =                      &
2520                                                albedo_pars_f%pars_xy(3,j,i)
2521                   ENDIF
2522                   IF ( albedo_pars_f%pars_xy(4,j,i) /= albedo_pars_f%fill )  THEN
2523                      surf_usm_h%asdir(ind_pav_green,m) =                      &
2524                                                albedo_pars_f%pars_xy(4,j,i)
2525                      surf_usm_h%asdif(ind_pav_green,m) =                      &
2526                                                albedo_pars_f%pars_xy(4,j,i)
2527                   ENDIF
2528!
2529!--                Spectral albedos especially for building window surfaces
2530                   IF ( albedo_pars_f%pars_xy(5,j,i) /= albedo_pars_f%fill )  THEN
2531                      surf_usm_h%aldir(ind_wat_win,m) =                        &
2532                                                albedo_pars_f%pars_xy(5,j,i)
2533                      surf_usm_h%aldif(ind_wat_win,m) =                        &
2534                                                albedo_pars_f%pars_xy(5,j,i)
2535                   ENDIF
2536                   IF ( albedo_pars_f%pars_xy(6,j,i) /= albedo_pars_f%fill )  THEN
2537                      surf_usm_h%asdir(ind_wat_win,m) =                        &
2538                                                albedo_pars_f%pars_xy(6,j,i)
2539                      surf_usm_h%asdif(ind_wat_win,m) =                        &
2540                                                albedo_pars_f%pars_xy(6,j,i)
2541                   ENDIF
2542
2543                ENDDO
2544             ENDIF
2545!
2546!--          Vertical
2547             DO  l = 0, 3
2548                ioff = surf_lsm_v(l)%ioff
2549                joff = surf_lsm_v(l)%joff
2550
2551                DO  m = 1, surf_lsm_v(l)%ns
2552                   i = surf_lsm_v(l)%i(m)
2553                   j = surf_lsm_v(l)%j(m)
2554!
2555!--                Spectral albedos for vegetation/pavement/water surfaces
2556                   DO  ind_type = 0, 2
2557                      IF ( surf_lsm_v(l)%albedo_type(ind_type,m) == 0 )  THEN
2558                         IF ( albedo_pars_f%pars_xy(0,j+joff,i+ioff) /=        &
2559                              albedo_pars_f%fill )                             &
2560                            surf_lsm_v(l)%albedo(ind_type,m) =                 &
2561                                          albedo_pars_f%pars_xy(0,j+joff,i+ioff)
2562                         IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2563                              albedo_pars_f%fill )                             &
2564                            surf_lsm_v(l)%aldir(ind_type,m) =                  &
2565                                          albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2566                         IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2567                              albedo_pars_f%fill )                             &
2568                            surf_lsm_v(l)%aldif(ind_type,m) =                  &
2569                                          albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2570                         IF ( albedo_pars_f%pars_xy(2,j+joff,i+ioff) /=        &
2571                              albedo_pars_f%fill )                             &
2572                            surf_lsm_v(l)%asdir(ind_type,m) =                  &
2573                                          albedo_pars_f%pars_xy(2,j+joff,i+ioff)
2574                         IF ( albedo_pars_f%pars_xy(2,j+joff,i+ioff) /=        &
2575                              albedo_pars_f%fill )                             &
2576                            surf_lsm_v(l)%asdif(ind_type,m) =                  &
2577                                          albedo_pars_f%pars_xy(2,j+joff,i+ioff)
2578                      ENDIF
2579                   ENDDO
2580                ENDDO
2581!
2582!--             For urban surface only if albedo has not been already initialized
2583!--             in the urban-surface model via the ASCII file.
2584                IF ( .NOT. surf_usm_v(l)%albedo_from_ascii )  THEN
2585                   ioff = surf_usm_v(l)%ioff
2586                   joff = surf_usm_v(l)%joff
2587
2588                   DO  m = 1, surf_usm_v(l)%ns
2589                      i = surf_usm_v(l)%i(m)
2590                      j = surf_usm_v(l)%j(m)
2591!
2592!--                   Broadband albedos for wall/green/window surfaces
2593                      DO  ind_type = 0, 2
2594                         IF ( surf_usm_v(l)%albedo_type(ind_type,m) == 0 )  THEN
2595                            IF ( albedo_pars_f%pars_xy(0,j+joff,i+ioff) /=     &
2596                                 albedo_pars_f%fill )                          &
2597                               surf_usm_v(l)%albedo(ind_type,m) =              &
2598                                             albedo_pars_f%pars_xy(0,j+joff,i+ioff)
2599                         ENDIF
2600                      ENDDO
2601!
2602!--                   Spectral albedos especially for building wall surfaces
2603                      IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=           &
2604                           albedo_pars_f%fill )  THEN
2605                         surf_usm_v(l)%aldir(ind_veg_wall,m) =                 &
2606                                         albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2607                         surf_usm_v(l)%aldif(ind_veg_wall,m) =                 &
2608                                         albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2609                      ENDIF
2610                      IF ( albedo_pars_f%pars_xy(2,j+joff,i+ioff) /=           &
2611                           albedo_pars_f%fill )  THEN
2612                         surf_usm_v(l)%asdir(ind_veg_wall,m) =                 &
2613                                         albedo_pars_f%pars_xy(2,j+joff,i+ioff)
2614                         surf_usm_v(l)%asdif(ind_veg_wall,m) =                 &
2615                                         albedo_pars_f%pars_xy(2,j+joff,i+ioff)
2616                      ENDIF
2617!                     
2618!--                   Spectral albedos especially for building green surfaces
2619                      IF ( albedo_pars_f%pars_xy(3,j+joff,i+ioff) /=           &
2620                           albedo_pars_f%fill )  THEN
2621                         surf_usm_v(l)%aldir(ind_pav_green,m) =                &
2622                                         albedo_pars_f%pars_xy(3,j+joff,i+ioff)
2623                         surf_usm_v(l)%aldif(ind_pav_green,m) =                &
2624                                         albedo_pars_f%pars_xy(3,j+joff,i+ioff)
2625                      ENDIF
2626                      IF ( albedo_pars_f%pars_xy(4,j+joff,i+ioff) /=           &
2627                           albedo_pars_f%fill )  THEN
2628                         surf_usm_v(l)%asdir(ind_pav_green,m) =                &
2629                                         albedo_pars_f%pars_xy(4,j+joff,i+ioff)
2630                         surf_usm_v(l)%asdif(ind_pav_green,m) =                &
2631                                         albedo_pars_f%pars_xy(4,j+joff,i+ioff)
2632                      ENDIF
2633!                     
2634!--                   Spectral albedos especially for building window surfaces
2635                      IF ( albedo_pars_f%pars_xy(5,j+joff,i+ioff) /=           &
2636                           albedo_pars_f%fill )  THEN
2637                         surf_usm_v(l)%aldir(ind_wat_win,m) =                  &
2638                                         albedo_pars_f%pars_xy(5,j+joff,i+ioff)
2639                         surf_usm_v(l)%aldif(ind_wat_win,m) =                  &
2640                                         albedo_pars_f%pars_xy(5,j+joff,i+ioff)
2641                      ENDIF
2642                      IF ( albedo_pars_f%pars_xy(6,j+joff,i+ioff) /=           &
2643                           albedo_pars_f%fill )  THEN
2644                         surf_usm_v(l)%asdir(ind_wat_win,m) =                  &
2645                                         albedo_pars_f%pars_xy(6,j+joff,i+ioff)
2646                         surf_usm_v(l)%asdif(ind_wat_win,m) =                  &
2647                                         albedo_pars_f%pars_xy(6,j+joff,i+ioff)
2648                      ENDIF
2649                   ENDDO
2650                ENDIF
2651             ENDDO
2652
2653          ENDIF
2654
2655!
2656!--       Calculate initial values of current (cosine of) the zenith angle and
2657!--       whether the sun is up
2658          CALL calc_zenith
2659!
2660!--       readjust date and time to its initial value
2661          CALL init_date_and_time
2662!
2663!--       Calculate initial surface albedo for different surfaces
2664          IF ( .NOT. constant_albedo )  THEN
2665#if defined( __netcdf )
2666!
2667!--          Horizontally aligned natural and urban surfaces
2668             CALL calc_albedo( surf_lsm_h )
2669             CALL calc_albedo( surf_usm_h )
2670!
2671!--          Vertically aligned natural and urban surfaces
2672             DO  l = 0, 3
2673                CALL calc_albedo( surf_lsm_v(l) )
2674                CALL calc_albedo( surf_usm_v(l) )
2675             ENDDO
2676#endif
2677          ELSE
2678!
2679!--          Initialize sun-inclination independent spectral albedos
2680!--          Horizontal surfaces
2681             IF ( surf_lsm_h%ns > 0 )  THEN
2682                surf_lsm_h%rrtm_aldir = surf_lsm_h%aldir
2683                surf_lsm_h%rrtm_asdir = surf_lsm_h%asdir
2684                surf_lsm_h%rrtm_aldif = surf_lsm_h%aldif
2685                surf_lsm_h%rrtm_asdif = surf_lsm_h%asdif
2686             ENDIF
2687             IF ( surf_usm_h%ns > 0 )  THEN
2688                surf_usm_h%rrtm_aldir = surf_usm_h%aldir
2689                surf_usm_h%rrtm_asdir = surf_usm_h%asdir
2690                surf_usm_h%rrtm_aldif = surf_usm_h%aldif
2691                surf_usm_h%rrtm_asdif = surf_usm_h%asdif
2692             ENDIF
2693!
2694!--          Vertical surfaces
2695             DO  l = 0, 3
2696                IF ( surf_lsm_v(l)%ns > 0 )  THEN
2697                   surf_lsm_v(l)%rrtm_aldir = surf_lsm_v(l)%aldir
2698                   surf_lsm_v(l)%rrtm_asdir = surf_lsm_v(l)%asdir
2699                   surf_lsm_v(l)%rrtm_aldif = surf_lsm_v(l)%aldif
2700                   surf_lsm_v(l)%rrtm_asdif = surf_lsm_v(l)%asdif
2701                ENDIF
2702                IF ( surf_usm_v(l)%ns > 0 )  THEN
2703                   surf_usm_v(l)%rrtm_aldir = surf_usm_v(l)%aldir
2704                   surf_usm_v(l)%rrtm_asdir = surf_usm_v(l)%asdir
2705                   surf_usm_v(l)%rrtm_aldif = surf_usm_v(l)%aldif
2706                   surf_usm_v(l)%rrtm_asdif = surf_usm_v(l)%asdif
2707                ENDIF
2708             ENDDO
2709
2710          ENDIF
2711
2712!
2713!--       Allocate 3d arrays of radiative fluxes and heating rates
2714          IF ( .NOT. ALLOCATED ( rad_sw_in ) )  THEN
2715             ALLOCATE ( rad_sw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2716             rad_sw_in = 0.0_wp
2717          ENDIF
2718
2719          IF ( .NOT. ALLOCATED ( rad_sw_in_av ) )  THEN
2720             ALLOCATE ( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2721          ENDIF
2722
2723          IF ( .NOT. ALLOCATED ( rad_sw_out ) )  THEN
2724             ALLOCATE ( rad_sw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2725             rad_sw_out = 0.0_wp
2726          ENDIF
2727
2728          IF ( .NOT. ALLOCATED ( rad_sw_out_av ) )  THEN
2729             ALLOCATE ( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2730          ENDIF
2731
2732          IF ( .NOT. ALLOCATED ( rad_sw_hr ) )  THEN
2733             ALLOCATE ( rad_sw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2734             rad_sw_hr = 0.0_wp
2735          ENDIF
2736
2737          IF ( .NOT. ALLOCATED ( rad_sw_hr_av ) )  THEN
2738             ALLOCATE ( rad_sw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2739             rad_sw_hr_av = 0.0_wp
2740          ENDIF
2741
2742          IF ( .NOT. ALLOCATED ( rad_sw_cs_hr ) )  THEN
2743             ALLOCATE ( rad_sw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2744             rad_sw_cs_hr = 0.0_wp
2745          ENDIF
2746
2747          IF ( .NOT. ALLOCATED ( rad_sw_cs_hr_av ) )  THEN
2748             ALLOCATE ( rad_sw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2749             rad_sw_cs_hr_av = 0.0_wp
2750          ENDIF
2751
2752          IF ( .NOT. ALLOCATED ( rad_lw_in ) )  THEN
2753             ALLOCATE ( rad_lw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2754             rad_lw_in = 0.0_wp
2755          ENDIF
2756
2757          IF ( .NOT. ALLOCATED ( rad_lw_in_av ) )  THEN
2758             ALLOCATE ( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2759          ENDIF
2760
2761          IF ( .NOT. ALLOCATED ( rad_lw_out ) )  THEN
2762             ALLOCATE ( rad_lw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2763            rad_lw_out = 0.0_wp
2764          ENDIF
2765
2766          IF ( .NOT. ALLOCATED ( rad_lw_out_av ) )  THEN
2767             ALLOCATE ( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2768          ENDIF
2769
2770          IF ( .NOT. ALLOCATED ( rad_lw_hr ) )  THEN
2771             ALLOCATE ( rad_lw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2772             rad_lw_hr = 0.0_wp
2773          ENDIF
2774
2775          IF ( .NOT. ALLOCATED ( rad_lw_hr_av ) )  THEN
2776             ALLOCATE ( rad_lw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2777             rad_lw_hr_av = 0.0_wp
2778          ENDIF
2779
2780          IF ( .NOT. ALLOCATED ( rad_lw_cs_hr ) )  THEN
2781             ALLOCATE ( rad_lw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2782             rad_lw_cs_hr = 0.0_wp
2783          ENDIF
2784
2785          IF ( .NOT. ALLOCATED ( rad_lw_cs_hr_av ) )  THEN
2786             ALLOCATE ( rad_lw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2787             rad_lw_cs_hr_av = 0.0_wp
2788          ENDIF
2789
2790          ALLOCATE ( rad_sw_cs_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2791          ALLOCATE ( rad_sw_cs_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2792          rad_sw_cs_in  = 0.0_wp
2793          rad_sw_cs_out = 0.0_wp
2794
2795          ALLOCATE ( rad_lw_cs_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2796          ALLOCATE ( rad_lw_cs_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2797          rad_lw_cs_in  = 0.0_wp
2798          rad_lw_cs_out = 0.0_wp
2799
2800!
2801!--       Allocate 1-element array for surface temperature
2802!--       (RRTMG anticipates an array as passed argument).
2803          ALLOCATE ( rrtm_tsfc(1) )
2804!
2805!--       Allocate surface emissivity.
2806!--       Values will be given directly before calling rrtm_lw.
2807          ALLOCATE ( rrtm_emis(0:0,1:nbndlw+1) )
2808
2809!
2810!--       Initialize RRTMG, before check if files are existent
2811          INQUIRE( FILE='rrtmg_lw.nc', EXIST=lw_exists )
2812          IF ( .NOT. lw_exists )  THEN
2813             message_string = 'Input file rrtmg_lw.nc' //                &
2814                            '&for rrtmg missing. ' // &
2815                            '&Please provide <jobname>_lsw file in the INPUT directory.'
2816             CALL message( 'radiation_init', 'PA0583', 1, 2, 0, 6, 0 )
2817          ENDIF         
2818          INQUIRE( FILE='rrtmg_sw.nc', EXIST=sw_exists )
2819          IF ( .NOT. sw_exists )  THEN
2820             message_string = 'Input file rrtmg_sw.nc' //                &
2821                            '&for rrtmg missing. ' // &
2822                            '&Please provide <jobname>_rsw file in the INPUT directory.'
2823             CALL message( 'radiation_init', 'PA0584', 1, 2, 0, 6, 0 )
2824          ENDIF         
2825         
2826          IF ( lw_radiation )  CALL rrtmg_lw_ini ( c_p )
2827          IF ( sw_radiation )  CALL rrtmg_sw_ini ( c_p )
2828         
2829!
2830!--       Set input files for RRTMG
2831          INQUIRE(FILE="RAD_SND_DATA", EXIST=snd_exists) 
2832          IF ( .NOT. snd_exists )  THEN
2833             rrtm_input_file = "rrtmg_lw.nc"
2834          ENDIF
2835
2836!
2837!--       Read vertical layers for RRTMG from sounding data
2838!--       The routine provides nzt_rad, hyp_snd(1:nzt_rad),
2839!--       t_snd(nzt+2:nzt_rad), rrtm_play(1:nzt_rad), rrtm_plev(1_nzt_rad+1),
2840!--       rrtm_tlay(nzt+2:nzt_rad), rrtm_tlev(nzt+2:nzt_rad+1)
2841          CALL read_sounding_data
2842
2843!
2844!--       Read trace gas profiles from file. This routine provides
2845!--       the rrtm_ arrays (1:nzt_rad+1)
2846          CALL read_trace_gas_data
2847#endif
2848       ENDIF
2849
2850!
2851!--    Perform user actions if required
2852       CALL user_init_radiation
2853
2854!
2855!--    Calculate radiative fluxes at model start
2856       SELECT CASE ( TRIM( radiation_scheme ) )
2857
2858          CASE ( 'rrtmg' )
2859             CALL radiation_rrtmg
2860
2861          CASE ( 'clear-sky' )
2862             CALL radiation_clearsky
2863
2864          CASE ( 'constant' )
2865             CALL radiation_constant
2866
2867          CASE DEFAULT
2868
2869       END SELECT
2870
2871! readjust date and time to its initial value
2872       CALL init_date_and_time
2873
2874!
2875!--    Find all discretized apparent solar positions for radiation interaction.
2876       IF ( radiation_interactions )  CALL radiation_presimulate_solar_pos
2877
2878!
2879!--    If required, read or calculate and write out the SVF
2880       IF ( radiation_interactions .AND. read_svf)  THEN
2881!
2882!--       Read sky-view factors and further required data from file
2883          CALL radiation_read_svf()
2884
2885       ELSEIF ( radiation_interactions .AND. .NOT. read_svf)  THEN
2886!
2887!--       calculate SFV and CSF
2888          CALL radiation_calc_svf()
2889       ENDIF
2890
2891       IF ( radiation_interactions .AND. write_svf)  THEN
2892!
2893!--       Write svf, csf svfsurf and csfsurf data to file
2894          CALL radiation_write_svf()
2895       ENDIF
2896
2897!
2898!--    Adjust radiative fluxes. In case of urban and land surfaces, also
2899!--    call an initial interaction.
2900       IF ( radiation_interactions )  THEN
2901          CALL radiation_interaction
2902       ENDIF
2903
2904       IF ( debug_output )  CALL debug_message( 'radiation_init', 'end' )
2905
2906       RETURN !todo: remove, I don't see what we need this for here
2907
2908    END SUBROUTINE radiation_init
2909
2910
2911!------------------------------------------------------------------------------!
2912! Description:
2913! ------------
2914!> A simple clear sky radiation model
2915!------------------------------------------------------------------------------!
2916    SUBROUTINE radiation_clearsky
2917
2918
2919       IMPLICIT NONE
2920
2921       INTEGER(iwp) ::  l         !< running index for surface orientation
2922       REAL(wp)     ::  pt1       !< potential temperature at first grid level or mean value at urban layer top
2923       REAL(wp)     ::  pt1_l     !< potential temperature at first grid level or mean value at urban layer top at local subdomain
2924       REAL(wp)     ::  ql1       !< liquid water mixing ratio at first grid level or mean value at urban layer top
2925       REAL(wp)     ::  ql1_l     !< liquid water mixing ratio at first grid level or mean value at urban layer top at local subdomain
2926
2927       TYPE(surf_type), POINTER ::  surf !< pointer on respective surface type, used to generalize routine   
2928
2929!
2930!--    Calculate current zenith angle
2931       CALL calc_zenith
2932
2933!
2934!--    Calculate sky transmissivity
2935       sky_trans = 0.6_wp + 0.2_wp * cos_zenith
2936
2937!
2938!--    Calculate value of the Exner function at model surface
2939!
2940!--    In case averaged radiation is used, calculate mean temperature and
2941!--    liquid water mixing ratio at the urban-layer top.
2942       IF ( average_radiation ) THEN
2943          pt1   = 0.0_wp
2944          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1   = 0.0_wp
2945
2946          pt1_l = SUM( pt(nz_urban_t,nys:nyn,nxl:nxr) )
2947          IF ( bulk_cloud_model  .OR.  cloud_droplets  )  ql1_l = SUM( ql(nz_urban_t,nys:nyn,nxl:nxr) )
2948
2949#if defined( __parallel )     
2950          IF ( collective_wait )  CALL MPI_BARRIER( comm2d, ierr )
2951          CALL MPI_ALLREDUCE( pt1_l, pt1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
2952          IF ( ierr /= 0 ) THEN
2953              WRITE(9,*) 'Error MPI_AllReduce1:', ierr, pt1_l, pt1
2954              FLUSH(9)
2955          ENDIF
2956
2957          IF ( bulk_cloud_model  .OR.  cloud_droplets ) THEN
2958              CALL MPI_ALLREDUCE( ql1_l, ql1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
2959              IF ( ierr /= 0 ) THEN
2960                  WRITE(9,*) 'Error MPI_AllReduce2:', ierr, ql1_l, ql1
2961                  FLUSH(9)
2962              ENDIF
2963          ENDIF
2964#else
2965          pt1 = pt1_l 
2966          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1 = ql1_l
2967#endif
2968
2969          IF ( bulk_cloud_model  .OR.  cloud_droplets  )  pt1 = pt1 + lv_d_cp / exner(nz_urban_t) * ql1
2970!
2971!--       Finally, divide by number of grid points
2972          pt1 = pt1 / REAL( ( nx + 1 ) * ( ny + 1 ), KIND=wp )
2973       ENDIF
2974!
2975!--    Call clear-sky calculation for each surface orientation.
2976!--    First, horizontal surfaces
2977       surf => surf_lsm_h
2978       CALL radiation_clearsky_surf
2979       surf => surf_usm_h
2980       CALL radiation_clearsky_surf
2981!
2982!--    Vertical surfaces
2983       DO  l = 0, 3
2984          surf => surf_lsm_v(l)
2985          CALL radiation_clearsky_surf
2986          surf => surf_usm_v(l)
2987          CALL radiation_clearsky_surf
2988       ENDDO
2989
2990       CONTAINS
2991
2992          SUBROUTINE radiation_clearsky_surf
2993
2994             IMPLICIT NONE
2995
2996             INTEGER(iwp) ::  i         !< index x-direction
2997             INTEGER(iwp) ::  j         !< index y-direction
2998             INTEGER(iwp) ::  k         !< index z-direction
2999             INTEGER(iwp) ::  m         !< running index for surface elements
3000
3001             IF ( surf%ns < 1 )  RETURN
3002
3003!
3004!--          Calculate radiation fluxes and net radiation (rad_net) assuming
3005!--          homogeneous urban radiation conditions.
3006             IF ( average_radiation ) THEN       
3007
3008                k = nz_urban_t
3009
3010                surf%rad_sw_in  = solar_constant * sky_trans * cos_zenith
3011                surf%rad_sw_out = albedo_urb * surf%rad_sw_in
3012               
3013                surf%rad_lw_in  = emissivity_atm_clsky * sigma_sb * (pt1 * exner(k+1))**4
3014
3015                surf%rad_lw_out = emissivity_urb * sigma_sb * (t_rad_urb)**4   &
3016                                    + (1.0_wp - emissivity_urb) * surf%rad_lw_in
3017
3018                surf%rad_net = surf%rad_sw_in - surf%rad_sw_out                &
3019                             + surf%rad_lw_in - surf%rad_lw_out
3020
3021                surf%rad_lw_out_change_0 = 4.0_wp * emissivity_urb * sigma_sb  &
3022                                           * (t_rad_urb)**3
3023
3024!
3025!--          Calculate radiation fluxes and net radiation (rad_net) for each surface
3026!--          element.
3027             ELSE
3028
3029                DO  m = 1, surf%ns
3030                   i = surf%i(m)
3031                   j = surf%j(m)
3032                   k = surf%k(m)
3033
3034                   surf%rad_sw_in(m) = solar_constant * sky_trans * cos_zenith
3035
3036!
3037!--                Weighted average according to surface fraction.
3038!--                ATTENTION: when radiation interactions are switched on the
3039!--                calculated fluxes below are not actually used as they are
3040!--                overwritten in radiation_interaction.
3041                   surf%rad_sw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
3042                                          surf%albedo(ind_veg_wall,m)          &
3043                                        + surf%frac(ind_pav_green,m) *         &
3044                                          surf%albedo(ind_pav_green,m)         &
3045                                        + surf%frac(ind_wat_win,m)   *         &
3046                                          surf%albedo(ind_wat_win,m) )         &
3047                                        * surf%rad_sw_in(m)
3048
3049                   surf%rad_lw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
3050                                          surf%emissivity(ind_veg_wall,m)      &
3051                                        + surf%frac(ind_pav_green,m) *         &
3052                                          surf%emissivity(ind_pav_green,m)     &
3053                                        + surf%frac(ind_wat_win,m)   *         &
3054                                          surf%emissivity(ind_wat_win,m)       &
3055                                        )                                      &
3056                                        * sigma_sb                             &
3057                                        * ( surf%pt_surface(m) * exner(nzb) )**4
3058
3059                   surf%rad_lw_out_change_0(m) =                               &
3060                                      ( surf%frac(ind_veg_wall,m)  *           &
3061                                        surf%emissivity(ind_veg_wall,m)        &
3062                                      + surf%frac(ind_pav_green,m) *           &
3063                                        surf%emissivity(ind_pav_green,m)       &
3064                                      + surf%frac(ind_wat_win,m)   *           &
3065                                        surf%emissivity(ind_wat_win,m)         &
3066                                      ) * 4.0_wp * sigma_sb                    &
3067                                      * ( surf%pt_surface(m) * exner(nzb) )** 3
3068
3069
3070                   IF ( bulk_cloud_model  .OR.  cloud_droplets  )  THEN
3071                      pt1 = pt(k,j,i) + lv_d_cp / exner(k) * ql(k,j,i)
3072                      surf%rad_lw_in(m)  = emissivity_atm_clsky * sigma_sb * (pt1 * exner(k))**4
3073                   ELSE
3074                      surf%rad_lw_in(m)  = emissivity_atm_clsky * sigma_sb * (pt(k,j,i) * exner(k))**4
3075                   ENDIF
3076
3077                   surf%rad_net(m) = surf%rad_sw_in(m) - surf%rad_sw_out(m)    &
3078                                   + surf%rad_lw_in(m) - surf%rad_lw_out(m)
3079
3080                ENDDO
3081
3082             ENDIF
3083
3084!
3085!--          Fill out values in radiation arrays
3086             DO  m = 1, surf%ns
3087                i = surf%i(m)
3088                j = surf%j(m)
3089                rad_sw_in(0,j,i) = surf%rad_sw_in(m)
3090                rad_sw_out(0,j,i) = surf%rad_sw_out(m)
3091                rad_lw_in(0,j,i) = surf%rad_lw_in(m)
3092                rad_lw_out(0,j,i) = surf%rad_lw_out(m)
3093             ENDDO
3094 
3095          END SUBROUTINE radiation_clearsky_surf
3096
3097    END SUBROUTINE radiation_clearsky
3098
3099
3100!------------------------------------------------------------------------------!
3101! Description:
3102! ------------
3103!> This scheme keeps the prescribed net radiation constant during the run
3104!------------------------------------------------------------------------------!
3105    SUBROUTINE radiation_constant
3106
3107
3108       IMPLICIT NONE
3109
3110       INTEGER(iwp) ::  l         !< running index for surface orientation
3111
3112       REAL(wp)     ::  pt1       !< potential temperature at first grid level or mean value at urban layer top
3113       REAL(wp)     ::  pt1_l     !< potential temperature at first grid level or mean value at urban layer top at local subdomain
3114       REAL(wp)     ::  ql1       !< liquid water mixing ratio at first grid level or mean value at urban layer top
3115       REAL(wp)     ::  ql1_l     !< liquid water mixing ratio at first grid level or mean value at urban layer top at local subdomain
3116
3117       TYPE(surf_type), POINTER ::  surf !< pointer on respective surface type, used to generalize routine
3118
3119!
3120!--    In case averaged radiation is used, calculate mean temperature and
3121!--    liquid water mixing ratio at the urban-layer top.
3122       IF ( average_radiation ) THEN   
3123          pt1   = 0.0_wp
3124          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1   = 0.0_wp
3125
3126          pt1_l = SUM( pt(nz_urban_t,nys:nyn,nxl:nxr) )
3127          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1_l = SUM( ql(nz_urban_t,nys:nyn,nxl:nxr) )
3128
3129#if defined( __parallel )     
3130          IF ( collective_wait )  CALL MPI_BARRIER( comm2d, ierr )
3131          CALL MPI_ALLREDUCE( pt1_l, pt1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
3132          IF ( ierr /= 0 ) THEN
3133              WRITE(9,*) 'Error MPI_AllReduce3:', ierr, pt1_l, pt1
3134              FLUSH(9)
3135          ENDIF
3136          IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
3137             CALL MPI_ALLREDUCE( ql1_l, ql1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
3138             IF ( ierr /= 0 ) THEN
3139                 WRITE(9,*) 'Error MPI_AllReduce4:', ierr, ql1_l, ql1
3140                 FLUSH(9)
3141             ENDIF
3142          ENDIF
3143#else
3144          pt1 = pt1_l
3145          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1 = ql1_l
3146#endif
3147          IF ( bulk_cloud_model  .OR.  cloud_droplets )  pt1 = pt1 + lv_d_cp / exner(nz_urban_t+1) * ql1
3148!
3149!--       Finally, divide by number of grid points
3150          pt1 = pt1 / REAL( ( nx + 1 ) * ( ny + 1 ), KIND=wp )
3151       ENDIF
3152
3153!
3154!--    First, horizontal surfaces
3155       surf => surf_lsm_h
3156       CALL radiation_constant_surf
3157       surf => surf_usm_h
3158       CALL radiation_constant_surf
3159!
3160!--    Vertical surfaces
3161       DO  l = 0, 3
3162          surf => surf_lsm_v(l)
3163          CALL radiation_constant_surf
3164          surf => surf_usm_v(l)
3165          CALL radiation_constant_surf
3166       ENDDO
3167
3168       CONTAINS
3169
3170          SUBROUTINE radiation_constant_surf
3171
3172             IMPLICIT NONE
3173
3174             INTEGER(iwp) ::  i         !< index x-direction
3175             INTEGER(iwp) ::  ioff      !< offset between surface element and adjacent grid point along x
3176             INTEGER(iwp) ::  j         !< index y-direction
3177             INTEGER(iwp) ::  joff      !< offset between surface element and adjacent grid point along y
3178             INTEGER(iwp) ::  k         !< index z-direction
3179             INTEGER(iwp) ::  koff      !< offset between surface element and adjacent grid point along z
3180             INTEGER(iwp) ::  m         !< running index for surface elements
3181
3182             IF ( surf%ns < 1 )  RETURN
3183
3184!--          Calculate homogenoeus urban radiation fluxes
3185             IF ( average_radiation ) THEN
3186
3187                surf%rad_net = net_radiation
3188
3189                surf%rad_lw_in  = emissivity_atm_clsky * sigma_sb * (pt1 * exner(nz_urban_t+1))**4
3190
3191                surf%rad_lw_out = emissivity_urb * sigma_sb * (t_rad_urb)**4   &
3192                                    + ( 1.0_wp - emissivity_urb )             & ! shouldn't be this a bulk value -- emissivity_urb?
3193                                    * surf%rad_lw_in
3194
3195                surf%rad_lw_out_change_0 = 4.0_wp * emissivity_urb * sigma_sb  &
3196                                           * t_rad_urb**3
3197
3198                surf%rad_sw_in = ( surf%rad_net - surf%rad_lw_in               &
3199                                     + surf%rad_lw_out )                       &
3200                                     / ( 1.0_wp - albedo_urb )
3201
3202                surf%rad_sw_out =  albedo_urb * surf%rad_sw_in
3203
3204!
3205!--          Calculate radiation fluxes for each surface element
3206             ELSE
3207!
3208!--             Determine index offset between surface element and adjacent
3209!--             atmospheric grid point
3210                ioff = surf%ioff
3211                joff = surf%joff
3212                koff = surf%koff
3213
3214!
3215!--             Prescribe net radiation and estimate the remaining radiative fluxes
3216                DO  m = 1, surf%ns
3217                   i = surf%i(m)
3218                   j = surf%j(m)
3219                   k = surf%k(m)
3220
3221                   surf%rad_net(m) = net_radiation
3222
3223                   IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
3224                      pt1 = pt(k,j,i) + lv_d_cp / exner(k) * ql(k,j,i)
3225                      surf%rad_lw_in(m)  = emissivity_atm_clsky * sigma_sb * (pt1 * exner(k))**4
3226                   ELSE
3227                      surf%rad_lw_in(m)  = emissivity_atm_clsky * sigma_sb *                 &
3228                                             ( pt(k,j,i) * exner(k) )**4
3229                   ENDIF
3230
3231!
3232!--                Weighted average according to surface fraction.
3233                   surf%rad_lw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
3234                                          surf%emissivity(ind_veg_wall,m)      &
3235                                        + surf%frac(ind_pav_green,m) *         &
3236                                          surf%emissivity(ind_pav_green,m)     &
3237                                        + surf%frac(ind_wat_win,m)   *         &
3238                                          surf%emissivity(ind_wat_win,m)       &
3239                                        )                                      &
3240                                      * sigma_sb                               &
3241                                      * ( surf%pt_surface(m) * exner(nzb) )**4
3242
3243                   surf%rad_sw_in(m) = ( surf%rad_net(m) - surf%rad_lw_in(m)   &
3244                                       + surf%rad_lw_out(m) )                  &
3245                                       / ( 1.0_wp -                            &
3246                                          ( surf%frac(ind_veg_wall,m)  *       &
3247                                            surf%albedo(ind_veg_wall,m)        &
3248                                         +  surf%frac(ind_pav_green,m) *       &
3249                                            surf%albedo(ind_pav_green,m)       &
3250                                         +  surf%frac(ind_wat_win,m)   *       &
3251                                            surf%albedo(ind_wat_win,m) )       &
3252                                         )
3253
3254                   surf%rad_sw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
3255                                          surf%albedo(ind_veg_wall,m)          &
3256                                        + surf%frac(ind_pav_green,m) *         &
3257                                          surf%albedo(ind_pav_green,m)         &
3258                                        + surf%frac(ind_wat_win,m)   *         &
3259                                          surf%albedo(ind_wat_win,m) )         &
3260                                      * surf%rad_sw_in(m)
3261
3262                ENDDO
3263
3264             ENDIF
3265
3266!
3267!--          Fill out values in radiation arrays
3268             DO  m = 1, surf%ns
3269                i = surf%i(m)
3270                j = surf%j(m)
3271                rad_sw_in(0,j,i) = surf%rad_sw_in(m)
3272                rad_sw_out(0,j,i) = surf%rad_sw_out(m)
3273                rad_lw_in(0,j,i) = surf%rad_lw_in(m)
3274                rad_lw_out(0,j,i) = surf%rad_lw_out(m)
3275             ENDDO
3276
3277          END SUBROUTINE radiation_constant_surf
3278         
3279
3280    END SUBROUTINE radiation_constant
3281
3282!------------------------------------------------------------------------------!
3283! Description:
3284! ------------
3285!> Header output for radiation model
3286!------------------------------------------------------------------------------!
3287    SUBROUTINE radiation_header ( io )
3288
3289
3290       IMPLICIT NONE
3291 
3292       INTEGER(iwp), INTENT(IN) ::  io            !< Unit of the output file
3293   
3294
3295       
3296!
3297!--    Write radiation model header
3298       WRITE( io, 3 )
3299
3300       IF ( radiation_scheme == "constant" )  THEN
3301          WRITE( io, 4 ) net_radiation
3302       ELSEIF ( radiation_scheme == "clear-sky" )  THEN
3303          WRITE( io, 5 )
3304       ELSEIF ( radiation_scheme == "rrtmg" )  THEN
3305          WRITE( io, 6 )
3306          IF ( .NOT. lw_radiation )  WRITE( io, 10 )
3307          IF ( .NOT. sw_radiation )  WRITE( io, 11 )
3308       ENDIF
3309
3310       IF ( albedo_type_f%from_file  .OR.  vegetation_type_f%from_file  .OR.   &
3311            pavement_type_f%from_file  .OR.  water_type_f%from_file  .OR.      &
3312            building_type_f%from_file )  THEN
3313             WRITE( io, 13 )
3314       ELSE 
3315          IF ( albedo_type == 0 )  THEN
3316             WRITE( io, 7 ) albedo
3317          ELSE
3318             WRITE( io, 8 ) TRIM( albedo_type_name(albedo_type) )
3319          ENDIF
3320       ENDIF
3321       IF ( constant_albedo )  THEN
3322          WRITE( io, 9 )
3323       ENDIF
3324       
3325       WRITE( io, 12 ) dt_radiation
3326 
3327
3328 3 FORMAT (//' Radiation model information:'/                                  &
3329              ' ----------------------------'/)
3330 4 FORMAT ('    --> Using constant net radiation: net_radiation = ', F6.2,     &
3331           // 'W/m**2')
3332 5 FORMAT ('    --> Simple radiation scheme for clear sky is used (no clouds,',&
3333                   ' default)')
3334 6 FORMAT ('    --> RRTMG scheme is used')
3335 7 FORMAT (/'    User-specific surface albedo: albedo =', F6.3)
3336 8 FORMAT (/'    Albedo is set for land surface type: ', A)
3337 9 FORMAT (/'    --> Albedo is fixed during the run')
333810 FORMAT (/'    --> Longwave radiation is disabled')
333911 FORMAT (/'    --> Shortwave radiation is disabled.')
334012 FORMAT  ('    Timestep: dt_radiation = ', F6.2, '  s')
334113 FORMAT (/'    Albedo is set individually for each xy-location, according ', &
3342                 'to given surface type.')
3343
3344
3345    END SUBROUTINE radiation_header
3346   
3347
3348!------------------------------------------------------------------------------!
3349! Description:
3350! ------------
3351!> Parin for &radiation_parameters for radiation model
3352!------------------------------------------------------------------------------!
3353    SUBROUTINE radiation_parin
3354
3355
3356       IMPLICIT NONE
3357
3358       CHARACTER (LEN=80) ::  line  !< dummy string that contains the current line of the parameter file
3359       
3360       NAMELIST /radiation_par/   albedo, albedo_lw_dif, albedo_lw_dir,         &
3361                                  albedo_sw_dif, albedo_sw_dir, albedo_type,    &
3362                                  constant_albedo, dt_radiation, emissivity,    &
3363                                  lw_radiation, max_raytracing_dist,            &
3364                                  min_irrf_value, mrt_geom_human,               &
3365                                  mrt_include_sw, mrt_nlevels,                  &
3366                                  mrt_skip_roof, net_radiation, nrefsteps,      &
3367                                  plant_lw_interact, rad_angular_discretization,&
3368                                  radiation_interactions_on, radiation_scheme,  &
3369                                  raytrace_discrete_azims,                      &
3370                                  raytrace_discrete_elevs, raytrace_mpi_rma,    &
3371                                  skip_time_do_radiation, surface_reflections,  &
3372                                  svfnorm_report_thresh, sw_radiation,          &
3373                                  unscheduled_radiation_calls
3374
3375   
3376       NAMELIST /radiation_parameters/ albedo, albedo_lw_dif, albedo_lw_dir,    &
3377                                  albedo_sw_dif, albedo_sw_dir, albedo_type,    &
3378                                  constant_albedo, dt_radiation, emissivity,    &
3379                                  lw_radiation, max_raytracing_dist,            &
3380                                  min_irrf_value, mrt_geom_human,               &
3381                                  mrt_include_sw, mrt_nlevels,                  &
3382                                  mrt_skip_roof, net_radiation, nrefsteps,      &
3383                                  plant_lw_interact, rad_angular_discretization,&
3384                                  radiation_interactions_on, radiation_scheme,  &
3385                                  raytrace_discrete_azims,                      &
3386                                  raytrace_discrete_elevs, raytrace_mpi_rma,    &
3387                                  skip_time_do_radiation, surface_reflections,  &
3388                                  svfnorm_report_thresh, sw_radiation,          &
3389                                  unscheduled_radiation_calls
3390   
3391       line = ' '
3392       
3393!
3394!--    Try to find radiation model namelist
3395       REWIND ( 11 )
3396       line = ' '
3397       DO WHILE ( INDEX( line, '&radiation_parameters' ) == 0 )
3398          READ ( 11, '(A)', END=12 )  line
3399       ENDDO
3400       BACKSPACE ( 11 )
3401
3402!
3403!--    Read user-defined namelist
3404       READ ( 11, radiation_parameters, ERR = 10 )
3405
3406!
3407!--    Set flag that indicates that the radiation model is switched on
3408       radiation = .TRUE.
3409
3410       GOTO 14
3411
3412 10    BACKSPACE( 11 )
3413       READ( 11 , '(A)') line
3414       CALL parin_fail_message( 'radiation_parameters', line )
3415!
3416!--    Try to find old namelist
3417 12    REWIND ( 11 )
3418       line = ' '
3419       DO WHILE ( INDEX( line, '&radiation_par' ) == 0 )
3420          READ ( 11, '(A)', END=14 )  line
3421       ENDDO
3422       BACKSPACE ( 11 )
3423
3424!
3425!--    Read user-defined namelist
3426       READ ( 11, radiation_par, ERR = 13, END = 14 )
3427
3428       message_string = 'namelist radiation_par is deprecated and will be ' // &
3429                     'removed in near future. Please use namelist ' //         &
3430                     'radiation_parameters instead'
3431       CALL message( 'radiation_parin', 'PA0487', 0, 1, 0, 6, 0 )
3432
3433!
3434!--    Set flag that indicates that the radiation model is switched on
3435       radiation = .TRUE.
3436
3437       IF ( .NOT.  radiation_interactions_on  .AND.  surface_reflections )  THEN
3438          message_string = 'surface_reflections is allowed only when '      // &
3439               'radiation_interactions_on is set to TRUE'
3440          CALL message( 'radiation_parin', 'PA0293',1, 2, 0, 6, 0 )
3441       ENDIF
3442
3443       GOTO 14
3444
3445 13    BACKSPACE( 11 )
3446       READ( 11 , '(A)') line
3447       CALL parin_fail_message( 'radiation_par', line )
3448
3449 14    CONTINUE
3450       
3451    END SUBROUTINE radiation_parin
3452
3453
3454!------------------------------------------------------------------------------!
3455! Description:
3456! ------------
3457!> Implementation of the RRTMG radiation_scheme
3458!------------------------------------------------------------------------------!
3459    SUBROUTINE radiation_rrtmg
3460
3461#if defined ( __rrtmg )
3462       USE indices,                                                            &
3463           ONLY:  nbgp
3464
3465       USE particle_attributes,                                                &
3466           ONLY:  grid_particles, number_of_particles, particles, prt_count
3467
3468       IMPLICIT NONE
3469
3470
3471       INTEGER(iwp) ::  i, j, k, l, m, n !< loop indices
3472       INTEGER(iwp) ::  k_topo     !< topography top index
3473
3474       REAL(wp)     ::  nc_rad, &    !< number concentration of cloud droplets
3475                        s_r2,   &    !< weighted sum over all droplets with r^2
3476                        s_r3         !< weighted sum over all droplets with r^3
3477
3478       REAL(wp), DIMENSION(0:nzt+1) :: pt_av, q_av, ql_av
3479       REAL(wp), DIMENSION(0:0)     :: zenith   !< to provide indexed array
3480!
3481!--    Just dummy arguments
3482       REAL(wp), DIMENSION(:,:,:), ALLOCATABLE :: rrtm_lw_taucld_dum,          &
3483                                                  rrtm_lw_tauaer_dum,          &
3484                                                  rrtm_sw_taucld_dum,          &
3485                                                  rrtm_sw_ssacld_dum,          &
3486                                                  rrtm_sw_asmcld_dum,          &
3487                                                  rrtm_sw_fsfcld_dum,          &
3488                                                  rrtm_sw_tauaer_dum,          &
3489                                                  rrtm_sw_ssaaer_dum,          &
3490                                                  rrtm_sw_asmaer_dum,          &
3491                                                  rrtm_sw_ecaer_dum
3492
3493!
3494!--    Calculate current (cosine of) zenith angle and whether the sun is up
3495       CALL calc_zenith     
3496       zenith(0) = cos_zenith
3497!
3498!--    Calculate surface albedo. In case average radiation is applied,
3499!--    this is not required.
3500#if defined( __netcdf )
3501       IF ( .NOT. constant_albedo )  THEN
3502!
3503!--       Horizontally aligned default, natural and urban surfaces
3504          CALL calc_albedo( surf_lsm_h    )
3505          CALL calc_albedo( surf_usm_h    )
3506!
3507!--       Vertically aligned default, natural and urban surfaces
3508          DO  l = 0, 3
3509             CALL calc_albedo( surf_lsm_v(l) )
3510             CALL calc_albedo( surf_usm_v(l) )
3511          ENDDO
3512       ENDIF
3513#endif
3514
3515!
3516!--    Prepare input data for RRTMG
3517
3518!
3519!--    In case of large scale forcing with surface data, calculate new pressure
3520!--    profile. nzt_rad might be modified by these calls and all required arrays
3521!--    will then be re-allocated
3522       IF ( large_scale_forcing  .AND.  lsf_surf )  THEN
3523          CALL read_sounding_data
3524          CALL read_trace_gas_data
3525       ENDIF
3526
3527
3528       IF ( average_radiation ) THEN
3529
3530          rrtm_asdir(1)  = albedo_urb
3531          rrtm_asdif(1)  = albedo_urb
3532          rrtm_aldir(1)  = albedo_urb
3533          rrtm_aldif(1)  = albedo_urb
3534
3535          rrtm_emis = emissivity_urb
3536!
3537!--       Calculate mean pt profile. Actually, only one height level is required.
3538          CALL calc_mean_profile( pt, 4 )
3539          pt_av = hom(:, 1, 4, 0)
3540         
3541          IF ( humidity )  THEN
3542             CALL calc_mean_profile( q, 41 )
3543             q_av  = hom(:, 1, 41, 0)
3544          ENDIF
3545!
3546!--       Prepare profiles of temperature and H2O volume mixing ratio
3547          rrtm_tlev(0,nzb+1) = t_rad_urb
3548
3549          IF ( bulk_cloud_model )  THEN
3550
3551             CALL calc_mean_profile( ql, 54 )
3552             ! average ql is now in hom(:, 1, 54, 0)
3553             ql_av = hom(:, 1, 54, 0)
3554             
3555             DO k = nzb+1, nzt+1
3556                rrtm_tlay(0,k) = pt_av(k) * ( (hyp(k) ) / 100000._wp       &
3557                                 )**.286_wp + lv_d_cp * ql_av(k)
3558                rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * (q_av(k) - ql_av(k))
3559             ENDDO
3560          ELSE
3561             DO k = nzb+1, nzt+1
3562                rrtm_tlay(0,k) = pt_av(k) * ( (hyp(k) ) / 100000._wp       &
3563                                 )**.286_wp
3564             ENDDO
3565
3566             IF ( humidity )  THEN
3567                DO k = nzb+1, nzt+1
3568                   rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * q_av(k)
3569                ENDDO
3570             ELSE
3571                rrtm_h2ovmr(0,nzb+1:nzt+1) = 0.0_wp
3572             ENDIF
3573          ENDIF
3574
3575!
3576!--       Avoid temperature/humidity jumps at the top of the PALM domain by
3577!--       linear interpolation from nzt+2 to nzt+7. Jumps are induced by
3578!--       discrepancies between the values in the  domain and those above that
3579!--       are prescribed in RRTMG
3580          DO k = nzt+2, nzt+7
3581             rrtm_tlay(0,k) = rrtm_tlay(0,nzt+1)                            &
3582                           + ( rrtm_tlay(0,nzt+8) - rrtm_tlay(0,nzt+1) )    &
3583                           / ( rrtm_play(0,nzt+8) - rrtm_play(0,nzt+1) )    &
3584                           * ( rrtm_play(0,k) - rrtm_play(0,nzt+1) )
3585
3586             rrtm_h2ovmr(0,k) = rrtm_h2ovmr(0,nzt+1)                        &
3587                           + ( rrtm_h2ovmr(0,nzt+8) - rrtm_h2ovmr(0,nzt+1) )&
3588                           / ( rrtm_play(0,nzt+8)   - rrtm_play(0,nzt+1)   )&
3589                           * ( rrtm_play(0,k) - rrtm_play(0,nzt+1) )
3590
3591          ENDDO
3592
3593!--       Linear interpolate to zw grid. Loop reaches one level further up
3594!--       due to the staggered grid in RRTMG
3595          DO k = nzb+2, nzt+8
3596             rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k) -        &
3597                                rrtm_tlay(0,k-1))                           &
3598                                / ( rrtm_play(0,k) - rrtm_play(0,k-1) )     &
3599                                * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
3600          ENDDO
3601
3602
3603!
3604!--       Calculate liquid water path and cloud fraction for each column.
3605!--       Note that LWP is required in g/m2 instead of kg/kg m.
3606          rrtm_cldfr  = 0.0_wp
3607          rrtm_reliq  = 0.0_wp
3608          rrtm_cliqwp = 0.0_wp
3609          rrtm_icld   = 0
3610
3611          IF ( bulk_cloud_model )  THEN
3612             DO k = nzb+1, nzt+1
3613                rrtm_cliqwp(0,k) =  ql_av(k) * 1000._wp *                   &
3614                                    (rrtm_plev(0,k) - rrtm_plev(0,k+1))     &
3615                                    * 100._wp / g 
3616
3617                IF ( rrtm_cliqwp(0,k) > 0._wp )  THEN
3618                   rrtm_cldfr(0,k) = 1._wp
3619                   IF ( rrtm_icld == 0 )  rrtm_icld = 1
3620
3621!
3622!--                Calculate cloud droplet effective radius
3623                   rrtm_reliq(0,k) = 1.0E6_wp * ( 3.0_wp * ql_av(k)         &
3624                                     * rho_surface                          &
3625                                     / ( 4.0_wp * pi * nc_const * rho_l )   &
3626                                     )**0.33333333333333_wp                 &
3627                                     * EXP( LOG( sigma_gc )**2 )
3628!
3629!--                Limit effective radius
3630                   IF ( rrtm_reliq(0,k) > 0.0_wp )  THEN
3631                      rrtm_reliq(0,k) = MAX(rrtm_reliq(0,k),2.5_wp)
3632                      rrtm_reliq(0,k) = MIN(rrtm_reliq(0,k),60.0_wp)
3633                   ENDIF
3634                ENDIF
3635             ENDDO
3636          ENDIF
3637
3638!
3639!--       Set surface temperature
3640          rrtm_tsfc = t_rad_urb
3641         
3642          IF ( lw_radiation )  THEN       
3643         
3644             CALL rrtmg_lw( 1, nzt_rad      , rrtm_icld    , rrtm_idrv      ,&
3645             rrtm_play       , rrtm_plev    , rrtm_tlay    , rrtm_tlev      ,&
3646             rrtm_tsfc       , rrtm_h2ovmr  , rrtm_o3vmr   , rrtm_co2vmr    ,&
3647             rrtm_ch4vmr     , rrtm_n2ovmr  , rrtm_o2vmr   , rrtm_cfc11vmr  ,&
3648             rrtm_cfc12vmr   , rrtm_cfc22vmr, rrtm_ccl4vmr , rrtm_emis      ,&
3649             rrtm_inflglw    , rrtm_iceflglw, rrtm_liqflglw, rrtm_cldfr     ,&
3650             rrtm_lw_taucld  , rrtm_cicewp  , rrtm_cliqwp  , rrtm_reice     ,& 
3651             rrtm_reliq      , rrtm_lw_tauaer,                               &
3652             rrtm_lwuflx     , rrtm_lwdflx  , rrtm_lwhr  ,                   &
3653             rrtm_lwuflxc    , rrtm_lwdflxc , rrtm_lwhrc ,                   &
3654             rrtm_lwuflx_dt  ,  rrtm_lwuflxc_dt )
3655
3656!
3657!--          Save fluxes
3658             DO k = nzb, nzt+1
3659                rad_lw_in(k,:,:)  = rrtm_lwdflx(0,k)
3660                rad_lw_out(k,:,:) = rrtm_lwuflx(0,k)
3661             ENDDO
3662             rad_lw_in_diff(:,:) = rad_lw_in(0,:,:)
3663!
3664!--          Save heating rates (convert from K/d to K/h).
3665!--          Further, even though an aggregated radiation is computed, map
3666!--          signle-column profiles on top of any topography, in order to
3667!--          obtain correct near surface radiation heating/cooling rates.
3668             DO  i = nxl, nxr
3669                DO  j = nys, nyn
3670                   k_topo = get_topography_top_index_ji( j, i, 's' )
3671                   DO k = k_topo+1, nzt+1
3672                      rad_lw_hr(k,j,i)     = rrtm_lwhr(0,k-k_topo)  * d_hours_day
3673                      rad_lw_cs_hr(k,j,i)  = rrtm_lwhrc(0,k-k_topo) * d_hours_day
3674                   ENDDO
3675                ENDDO
3676             ENDDO
3677
3678          ENDIF
3679
3680          IF ( sw_radiation .AND. sun_up )  THEN
3681             CALL rrtmg_sw( 1, nzt_rad      , rrtm_icld     , rrtm_iaer      ,&
3682             rrtm_play      , rrtm_plev     , rrtm_tlay     , rrtm_tlev      ,&
3683             rrtm_tsfc      , rrtm_h2ovmr   , rrtm_o3vmr    , rrtm_co2vmr    ,&
3684             rrtm_ch4vmr    , rrtm_n2ovmr   , rrtm_o2vmr    , rrtm_asdir     ,&
3685             rrtm_asdif     , rrtm_aldir    , rrtm_aldif    , zenith         ,&
3686             0.0_wp         , day_of_year   , solar_constant, rrtm_inflgsw   ,&
3687             rrtm_iceflgsw  , rrtm_liqflgsw , rrtm_cldfr    , rrtm_sw_taucld ,&
3688             rrtm_sw_ssacld , rrtm_sw_asmcld, rrtm_sw_fsfcld, rrtm_cicewp    ,&
3689             rrtm_cliqwp    , rrtm_reice    , rrtm_reliq    , rrtm_sw_tauaer ,&
3690             rrtm_sw_ssaaer , rrtm_sw_asmaer, rrtm_sw_ecaer , rrtm_swuflx    ,&
3691             rrtm_swdflx    , rrtm_swhr     , rrtm_swuflxc  , rrtm_swdflxc   ,&
3692             rrtm_swhrc     , rrtm_dirdflux , rrtm_difdflux )
3693 
3694!
3695!--          Save fluxes:
3696!--          - whole domain
3697             DO k = nzb, nzt+1
3698                rad_sw_in(k,:,:)  = rrtm_swdflx(0,k)
3699                rad_sw_out(k,:,:) = rrtm_swuflx(0,k)
3700             ENDDO
3701!--          - direct and diffuse SW at urban-surface-layer (required by RTM)
3702             rad_sw_in_dir(:,:) = rrtm_dirdflux(0,nzb)
3703             rad_sw_in_diff(:,:) = rrtm_difdflux(0,nzb)
3704
3705!
3706!--          Save heating rates (convert from K/d to K/s)
3707             DO k = nzb+1, nzt+1
3708                rad_sw_hr(k,:,:)     = rrtm_swhr(0,k)  * d_hours_day
3709                rad_sw_cs_hr(k,:,:)  = rrtm_swhrc(0,k) * d_hours_day
3710             ENDDO
3711!
3712!--       Solar radiation is zero during night
3713          ELSE
3714             rad_sw_in  = 0.0_wp
3715             rad_sw_out = 0.0_wp
3716             rad_sw_in_dir(:,:) = 0.0_wp
3717             rad_sw_in_diff(:,:) = 0.0_wp
3718          ENDIF
3719!
3720!--    RRTMG is called for each (j,i) grid point separately, starting at the
3721!--    highest topography level. Here no RTM is used since average_radiation is false
3722       ELSE
3723!
3724!--       Loop over all grid points
3725          DO i = nxl, nxr
3726             DO j = nys, nyn
3727
3728!
3729!--             Prepare profiles of temperature and H2O volume mixing ratio
3730                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
3731                   rrtm_tlev(0,nzb+1) = surf_lsm_h%pt_surface(m) * exner(nzb)
3732                ENDDO
3733                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
3734                   rrtm_tlev(0,nzb+1) = surf_usm_h%pt_surface(m) * exner(nzb)
3735                ENDDO
3736
3737
3738                IF ( bulk_cloud_model )  THEN
3739                   DO k = nzb+1, nzt+1
3740                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)                    &
3741                                        + lv_d_cp * ql(k,j,i)
3742                      rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * (q(k,j,i) - ql(k,j,i))
3743                   ENDDO
3744                ELSEIF ( cloud_droplets )  THEN
3745                   DO k = nzb+1, nzt+1
3746                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)                     &
3747                                        + lv_d_cp * ql(k,j,i)
3748                      rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * q(k,j,i) 
3749                   ENDDO
3750                ELSE
3751                   DO k = nzb+1, nzt+1
3752                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)
3753                   ENDDO
3754
3755                   IF ( humidity )  THEN
3756                      DO k = nzb+1, nzt+1
3757                         rrtm_h2ovmr(0,k) =  mol_mass_air_d_wv * q(k,j,i)
3758                      ENDDO   
3759                   ELSE
3760                      rrtm_h2ovmr(0,nzb+1:nzt+1) = 0.0_wp
3761                   ENDIF
3762                ENDIF
3763
3764!
3765!--             Avoid temperature/humidity jumps at the top of the LES domain by
3766!--             linear interpolation from nzt+2 to nzt+7
3767                DO k = nzt+2, nzt+7
3768                   rrtm_tlay(0,k) = rrtm_tlay(0,nzt+1)                         &
3769                                 + ( rrtm_tlay(0,nzt+8) - rrtm_tlay(0,nzt+1) ) &
3770                                 / ( rrtm_play(0,nzt+8) - rrtm_play(0,nzt+1) ) &
3771                                 * ( rrtm_play(0,k)     - rrtm_play(0,nzt+1) )
3772
3773                   rrtm_h2ovmr(0,k) = rrtm_h2ovmr(0,nzt+1)                     &
3774                              + ( rrtm_h2ovmr(0,nzt+8) - rrtm_h2ovmr(0,nzt+1) )&
3775                              / ( rrtm_play(0,nzt+8)   - rrtm_play(0,nzt+1)   )&
3776                              * ( rrtm_play(0,k)       - rrtm_play(0,nzt+1) )
3777
3778                ENDDO
3779
3780!--             Linear interpolate to zw grid
3781                DO k = nzb+2, nzt+8
3782                   rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k) -     &
3783                                      rrtm_tlay(0,k-1))                        &
3784                                      / ( rrtm_play(0,k) - rrtm_play(0,k-1) )  &
3785                                      * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
3786                ENDDO
3787
3788
3789!
3790!--             Calculate liquid water path and cloud fraction for each column.
3791!--             Note that LWP is required in g/m2 instead of kg/kg m.
3792                rrtm_cldfr  = 0.0_wp
3793                rrtm_reliq  = 0.0_wp
3794                rrtm_cliqwp = 0.0_wp
3795                rrtm_icld   = 0
3796
3797                IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
3798                   DO k = nzb+1, nzt+1
3799                      rrtm_cliqwp(0,k) =  ql(k,j,i) * 1000.0_wp *              &
3800                                          (rrtm_plev(0,k) - rrtm_plev(0,k+1))  &
3801                                          * 100.0_wp / g 
3802
3803                      IF ( rrtm_cliqwp(0,k) > 0.0_wp )  THEN
3804                         rrtm_cldfr(0,k) = 1.0_wp
3805                         IF ( rrtm_icld == 0 )  rrtm_icld = 1
3806
3807!
3808!--                      Calculate cloud droplet effective radius
3809                         IF ( bulk_cloud_model )  THEN
3810!
3811!--                         Calculete effective droplet radius. In case of using
3812!--                         cloud_scheme = 'morrison' and a non reasonable number
3813!--                         of cloud droplets the inital aerosol number 
3814!--                         concentration is considered.
3815                            IF ( microphysics_morrison )  THEN
3816                               IF ( nc(k,j,i) > 1.0E-20_wp )  THEN
3817                                  nc_rad = nc(k,j,i)
3818                               ELSE
3819                                  nc_rad = na_init
3820                               ENDIF
3821                            ELSE
3822                               nc_rad = nc_const
3823                            ENDIF 
3824
3825                            rrtm_reliq(0,k) = 1.0E6_wp * ( 3.0_wp * ql(k,j,i)     &
3826                                              * rho_surface                       &
3827                                              / ( 4.0_wp * pi * nc_rad * rho_l )  &
3828                                              )**0.33333333333333_wp              &
3829                                              * EXP( LOG( sigma_gc )**2 )
3830
3831                         ELSEIF ( cloud_droplets )  THEN
3832                            number_of_particles = prt_count(k,j,i)
3833
3834                            IF (number_of_particles <= 0)  CYCLE
3835                            particles => grid_particles(k,j,i)%particles(1:number_of_particles)
3836                            s_r2 = 0.0_wp
3837                            s_r3 = 0.0_wp
3838
3839                            DO  n = 1, number_of_particles
3840                               IF ( particles(n)%particle_mask )  THEN
3841                                  s_r2 = s_r2 + particles(n)%radius**2 *       &
3842                                         particles(n)%weight_factor
3843                                  s_r3 = s_r3 + particles(n)%radius**3 *       &
3844                                         particles(n)%weight_factor
3845                               ENDIF
3846                            ENDDO
3847
3848                            IF ( s_r2 > 0.0_wp )  rrtm_reliq(0,k) = s_r3 / s_r2
3849
3850                         ENDIF
3851
3852!
3853!--                      Limit effective radius
3854                         IF ( rrtm_reliq(0,k) > 0.0_wp )  THEN
3855                            rrtm_reliq(0,k) = MAX(rrtm_reliq(0,k),2.5_wp)
3856                            rrtm_reliq(0,k) = MIN(rrtm_reliq(0,k),60.0_wp)
3857                        ENDIF
3858                      ENDIF
3859                   ENDDO
3860                ENDIF
3861
3862!
3863!--             Write surface emissivity and surface temperature at current
3864!--             surface element on RRTMG-shaped array.
3865!--             Please note, as RRTMG is a single column model, surface attributes
3866!--             are only obtained from horizontally aligned surfaces (for
3867!--             simplicity). Taking surface attributes from horizontal and
3868!--             vertical walls would lead to multiple solutions. 
3869!--             Moreover, for natural- and urban-type surfaces, several surface
3870!--             classes can exist at a surface element next to each other.
3871!--             To obtain bulk parameters, apply a weighted average for these
3872!--             surfaces.
3873                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
3874                   rrtm_emis = surf_lsm_h%frac(ind_veg_wall,m)  *              &
3875                               surf_lsm_h%emissivity(ind_veg_wall,m)  +        &
3876                               surf_lsm_h%frac(ind_pav_green,m) *              &
3877                               surf_lsm_h%emissivity(ind_pav_green,m) +        & 
3878                               surf_lsm_h%frac(ind_wat_win,m)   *              &
3879                               surf_lsm_h%emissivity(ind_wat_win,m)
3880                   rrtm_tsfc = surf_lsm_h%pt_surface(m) * exner(nzb)
3881                ENDDO             
3882                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
3883                   rrtm_emis = surf_usm_h%frac(ind_veg_wall,m)  *              &
3884                               surf_usm_h%emissivity(ind_veg_wall,m)  +        &
3885                               surf_usm_h%frac(ind_pav_green,m) *              &
3886                               surf_usm_h%emissivity(ind_pav_green,m) +        & 
3887                               surf_usm_h%frac(ind_wat_win,m)   *              &
3888                               surf_usm_h%emissivity(ind_wat_win,m)
3889                   rrtm_tsfc = surf_usm_h%pt_surface(m) * exner(nzb)
3890                ENDDO
3891!
3892!--             Obtain topography top index (lower bound of RRTMG)
3893                k_topo = get_topography_top_index_ji( j, i, 's' )
3894
3895                IF ( lw_radiation )  THEN
3896!
3897!--                Due to technical reasons, copy optical depth to dummy arguments
3898!--                which are allocated on the exact size as the rrtmg_lw is called.
3899!--                As one dimesion is allocated with zero size, compiler complains
3900!--                that rank of the array does not match that of the
3901!--                assumed-shaped arguments in the RRTMG library. In order to
3902!--                avoid this, write to dummy arguments and give pass the entire
3903!--                dummy array. Seems to be the only existing work-around. 
3904                   ALLOCATE( rrtm_lw_taucld_dum(1:nbndlw+1,0:0,k_topo+1:nzt_rad+1) )
3905                   ALLOCATE( rrtm_lw_tauaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndlw+1) )
3906
3907                   rrtm_lw_taucld_dum =                                        &
3908                               rrtm_lw_taucld(1:nbndlw+1,0:0,k_topo+1:nzt_rad+1)
3909                   rrtm_lw_tauaer_dum =                                        &
3910                               rrtm_lw_tauaer(0:0,k_topo+1:nzt_rad+1,1:nbndlw+1)
3911
3912                   CALL rrtmg_lw( 1,                                           &                                       
3913                                  nzt_rad-k_topo,                              &
3914                                  rrtm_icld,                                   &
3915                                  rrtm_idrv,                                   &
3916                                  rrtm_play(:,k_topo+1:nzt_rad+1),             &
3917                                  rrtm_plev(:,k_topo+1:nzt_rad+2),             &
3918                                  rrtm_tlay(:,k_topo+1:nzt_rad+1),             &
3919                                  rrtm_tlev(:,k_topo+1:nzt_rad+2),             &
3920                                  rrtm_tsfc,                                   &
3921                                  rrtm_h2ovmr(:,k_topo+1:nzt_rad+1),           &
3922                                  rrtm_o3vmr(:,k_topo+1:nzt_rad+1),            &
3923                                  rrtm_co2vmr(:,k_topo+1:nzt_rad+1),           &
3924                                  rrtm_ch4vmr(:,k_topo+1:nzt_rad+1),           &
3925                                  rrtm_n2ovmr(:,k_topo+1:nzt_rad+1),           &
3926                                  rrtm_o2vmr(:,k_topo+1:nzt_rad+1),            &
3927                                  rrtm_cfc11vmr(:,k_topo+1:nzt_rad+1),         &
3928                                  rrtm_cfc12vmr(:,k_topo+1:nzt_rad+1),         &
3929                                  rrtm_cfc22vmr(:,k_topo+1:nzt_rad+1),         &
3930                                  rrtm_ccl4vmr(:,k_topo+1:nzt_rad+1),          &
3931                                  rrtm_emis,                                   &
3932                                  rrtm_inflglw,                                &
3933                                  rrtm_iceflglw,                               &
3934                                  rrtm_liqflglw,                               &
3935                                  rrtm_cldfr(:,k_topo+1:nzt_rad+1),            &
3936                                  rrtm_lw_taucld_dum,                          &
3937                                  rrtm_cicewp(:,k_topo+1:nzt_rad+1),           &
3938                                  rrtm_cliqwp(:,k_topo+1:nzt_rad+1),           &
3939                                  rrtm_reice(:,k_topo+1:nzt_rad+1),            & 
3940                                  rrtm_reliq(:,k_topo+1:nzt_rad+1),            &
3941                                  rrtm_lw_tauaer_dum,                          &
3942                                  rrtm_lwuflx(:,k_topo:nzt_rad+1),             &
3943                                  rrtm_lwdflx(:,k_topo:nzt_rad+1),             &
3944                                  rrtm_lwhr(:,k_topo+1:nzt_rad+1),             &
3945                                  rrtm_lwuflxc(:,k_topo:nzt_rad+1),            &
3946                                  rrtm_lwdflxc(:,k_topo:nzt_rad+1),            &
3947                                  rrtm_lwhrc(:,k_topo+1:nzt_rad+1),            &
3948                                  rrtm_lwuflx_dt(:,k_topo:nzt_rad+1),          &
3949                                  rrtm_lwuflxc_dt(:,k_topo:nzt_rad+1) )
3950
3951                   DEALLOCATE ( rrtm_lw_taucld_dum )
3952                   DEALLOCATE ( rrtm_lw_tauaer_dum )
3953!
3954!--                Save fluxes
3955                   DO k = k_topo, nzt+1
3956                      rad_lw_in(k,j,i)  = rrtm_lwdflx(0,k)
3957                      rad_lw_out(k,j,i) = rrtm_lwuflx(0,k)
3958                   ENDDO
3959
3960!
3961!--                Save heating rates (convert from K/d to K/h)
3962                   DO k = k_topo+1, nzt+1
3963                      rad_lw_hr(k,j,i)     = rrtm_lwhr(0,k-k_topo)  * d_hours_day
3964                      rad_lw_cs_hr(k,j,i)  = rrtm_lwhrc(0,k-k_topo) * d_hours_day
3965                   ENDDO
3966
3967!
3968!--                Save surface radiative fluxes and change in LW heating rate
3969!--                onto respective surface elements
3970!--                Horizontal surfaces
3971                   DO  m = surf_lsm_h%start_index(j,i),                        &
3972                           surf_lsm_h%end_index(j,i)
3973                      surf_lsm_h%rad_lw_in(m)           = rrtm_lwdflx(0,k_topo)
3974                      surf_lsm_h%rad_lw_out(m)          = rrtm_lwuflx(0,k_topo)
3975                      surf_lsm_h%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k_topo)
3976                   ENDDO             
3977                   DO  m = surf_usm_h%start_index(j,i),                        &
3978                           surf_usm_h%end_index(j,i)
3979                      surf_usm_h%rad_lw_in(m)           = rrtm_lwdflx(0,k_topo)
3980                      surf_usm_h%rad_lw_out(m)          = rrtm_lwuflx(0,k_topo)
3981                      surf_usm_h%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k_topo)
3982                   ENDDO 
3983!
3984!--                Vertical surfaces. Fluxes are obtain at vertical level of the
3985!--                respective surface element
3986                   DO  l = 0, 3
3987                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
3988                              surf_lsm_v(l)%end_index(j,i)
3989                         k                                    = surf_lsm_v(l)%k(m)
3990                         surf_lsm_v(l)%rad_lw_in(m)           = rrtm_lwdflx(0,k)
3991                         surf_lsm_v(l)%rad_lw_out(m)          = rrtm_lwuflx(0,k)
3992                         surf_lsm_v(l)%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k)
3993                      ENDDO             
3994                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
3995                              surf_usm_v(l)%end_index(j,i)
3996                         k                                    = surf_usm_v(l)%k(m)
3997                         surf_usm_v(l)%rad_lw_in(m)           = rrtm_lwdflx(0,k)
3998                         surf_usm_v(l)%rad_lw_out(m)          = rrtm_lwuflx(0,k)
3999                         surf_usm_v(l)%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k)
4000                      ENDDO 
4001                   ENDDO
4002
4003                ENDIF
4004
4005                IF ( sw_radiation .AND. sun_up )  THEN
4006!
4007!--                Get albedo for direct/diffusive long/shortwave radiation at
4008!--                current (y,x)-location from surface variables.
4009!--                Only obtain it from horizontal surfaces, as RRTMG is a single
4010!--                column model
4011!--                (Please note, only one loop will entered, controlled by
4012!--                start-end index.)
4013                   DO  m = surf_lsm_h%start_index(j,i),                        &
4014                           surf_lsm_h%end_index(j,i)
4015                      rrtm_asdir(1)  = SUM( surf_lsm_h%frac(:,m) *             &
4016                                            surf_lsm_h%rrtm_asdir(:,m) )
4017                      rrtm_asdif(1)  = SUM( surf_lsm_h%frac(:,m) *             &
4018                                            surf_lsm_h%rrtm_asdif(:,m) )
4019                      rrtm_aldir(1)  = SUM( surf_lsm_h%frac(:,m) *             &
4020                                            surf_lsm_h%rrtm_aldir(:,m) )
4021                      rrtm_aldif(1)  = SUM( surf_lsm_h%frac(:,m) *             &
4022                                            surf_lsm_h%rrtm_aldif(:,m) )
4023                   ENDDO             
4024                   DO  m = surf_usm_h%start_index(j,i),                        &
4025                           surf_usm_h%end_index(j,i)
4026                      rrtm_asdir(1)  = SUM( surf_usm_h%frac(:,m) *             &
4027                                            surf_usm_h%rrtm_asdir(:,m) )
4028                      rrtm_asdif(1)  = SUM( surf_usm_h%frac(:,m) *             &
4029                                            surf_usm_h%rrtm_asdif(:,m) )
4030                      rrtm_aldir(1)  = SUM( surf_usm_h%frac(:,m) *             &
4031                                            surf_usm_h%rrtm_aldir(:,m) )
4032                      rrtm_aldif(1)  = SUM( surf_usm_h%frac(:,m) *             &
4033                                            surf_usm_h%rrtm_aldif(:,m) )
4034                   ENDDO
4035!
4036!--                Due to technical reasons, copy optical depths and other
4037!--                to dummy arguments which are allocated on the exact size as the
4038!--                rrtmg_sw is called.
4039!--                As one dimesion is allocated with zero size, compiler complains
4040!--                that rank of the array does not match that of the
4041!--                assumed-shaped arguments in the RRTMG library. In order to
4042!--                avoid this, write to dummy arguments and give pass the entire
4043!--                dummy array. Seems to be the only existing work-around. 
4044                   ALLOCATE( rrtm_sw_taucld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
4045                   ALLOCATE( rrtm_sw_ssacld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
4046                   ALLOCATE( rrtm_sw_asmcld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
4047                   ALLOCATE( rrtm_sw_fsfcld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
4048                   ALLOCATE( rrtm_sw_tauaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
4049                   ALLOCATE( rrtm_sw_ssaaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
4050                   ALLOCATE( rrtm_sw_asmaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
4051                   ALLOCATE( rrtm_sw_ecaer_dum(0:0,k_topo+1:nzt_rad+1,1:naerec+1)  )
4052     
4053                   rrtm_sw_taucld_dum = rrtm_sw_taucld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
4054                   rrtm_sw_ssacld_dum = rrtm_sw_ssacld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
4055                   rrtm_sw_asmcld_dum = rrtm_sw_asmcld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
4056                   rrtm_sw_fsfcld_dum = rrtm_sw_fsfcld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
4057                   rrtm_sw_tauaer_dum = rrtm_sw_tauaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
4058                   rrtm_sw_ssaaer_dum = rrtm_sw_ssaaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
4059                   rrtm_sw_asmaer_dum = rrtm_sw_asmaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
4060                   rrtm_sw_ecaer_dum  = rrtm_sw_ecaer(0:0,k_topo+1:nzt_rad+1,1:naerec+1)
4061
4062                   CALL rrtmg_sw( 1,                                           &
4063                                  nzt_rad-k_topo,                              &
4064                                  rrtm_icld,                                   &
4065                                  rrtm_iaer,                                   &
4066                                  rrtm_play(:,k_topo+1:nzt_rad+1),             &
4067                                  rrtm_plev(:,k_topo+1:nzt_rad+2),             &
4068                                  rrtm_tlay(:,k_topo+1:nzt_rad+1),             &
4069                                  rrtm_tlev(:,k_topo+1:nzt_rad+2),             &
4070                                  rrtm_tsfc,                                   &
4071                                  rrtm_h2ovmr(:,k_topo+1:nzt_rad+1),           &                               
4072                                  rrtm_o3vmr(:,k_topo+1:nzt_rad+1),            &       
4073                                  rrtm_co2vmr(:,k_topo+1:nzt_rad+1),           &
4074                                  rrtm_ch4vmr(:,k_topo+1:nzt_rad+1),           &
4075                                  rrtm_n2ovmr(:,k_topo+1:nzt_rad+1),           &
4076                                  rrtm_o2vmr(:,k_topo+1:nzt_rad+1),            &
4077                                  rrtm_asdir,                                  & 
4078                                  rrtm_asdif,                                  &
4079                                  rrtm_aldir,                                  &
4080                                  rrtm_aldif,                                  &
4081                                  zenith,                                      &
4082                                  0.0_wp,                                      &
4083                                  day_of_year,                                 &
4084                                  solar_constant,                              &
4085                                  rrtm_inflgsw,                                &
4086                                  rrtm_iceflgsw,                               &
4087                                  rrtm_liqflgsw,                               &
4088                                  rrtm_cldfr(:,k_topo+1:nzt_rad+1),            &
4089                                  rrtm_sw_taucld_dum,                          &
4090                                  rrtm_sw_ssacld_dum,                          &
4091                                  rrtm_sw_asmcld_dum,                          &
4092                                  rrtm_sw_fsfcld_dum,                          &
4093                                  rrtm_cicewp(:,k_topo+1:nzt_rad+1),           &
4094                                  rrtm_cliqwp(:,k_topo+1:nzt_rad+1),           &
4095                                  rrtm_reice(:,k_topo+1:nzt_rad+1),            &
4096                                  rrtm_reliq(:,k_topo+1:nzt_rad+1),            &
4097                                  rrtm_sw_tauaer_dum,                          &
4098                                  rrtm_sw_ssaaer_dum,                          &
4099                                  rrtm_sw_asmaer_dum,                          &
4100                                  rrtm_sw_ecaer_dum,                           &
4101                                  rrtm_swuflx(:,k_topo:nzt_rad+1),             & 
4102                                  rrtm_swdflx(:,k_topo:nzt_rad+1),             & 
4103                                  rrtm_swhr(:,k_topo+1:nzt_rad+1),             & 
4104                                  rrtm_swuflxc(:,k_topo:nzt_rad+1),            & 
4105                                  rrtm_swdflxc(:,k_topo:nzt_rad+1),            &
4106                                  rrtm_swhrc(:,k_topo+1:nzt_rad+1),            &
4107                                  rrtm_dirdflux(:,k_topo:nzt_rad+1),           &
4108                                  rrtm_difdflux(:,k_topo:nzt_rad+1) )
4109
4110                   DEALLOCATE( rrtm_sw_taucld_dum )
4111                   DEALLOCATE( rrtm_sw_ssacld_dum )
4112                   DEALLOCATE( rrtm_sw_asmcld_dum )
4113                   DEALLOCATE( rrtm_sw_fsfcld_dum )
4114                   DEALLOCATE( rrtm_sw_tauaer_dum )
4115                   DEALLOCATE( rrtm_sw_ssaaer_dum )
4116                   DEALLOCATE( rrtm_sw_asmaer_dum )
4117                   DEALLOCATE( rrtm_sw_ecaer_dum )
4118!
4119!--                Save fluxes
4120                   DO k = nzb, nzt+1
4121                      rad_sw_in(k,j,i)  = rrtm_swdflx(0,k)
4122                      rad_sw_out(k,j,i) = rrtm_swuflx(0,k)
4123                   ENDDO
4124!
4125!--                Save heating rates (convert from K/d to K/s)
4126                   DO k = nzb+1, nzt+1
4127                      rad_sw_hr(k,j,i)     = rrtm_swhr(0,k)  * d_hours_day
4128                      rad_sw_cs_hr(k,j,i)  = rrtm_swhrc(0,k) * d_hours_day
4129                   ENDDO
4130
4131!
4132!--                Save surface radiative fluxes onto respective surface elements
4133!--                Horizontal surfaces
4134                   DO  m = surf_lsm_h%start_index(j,i),                        &
4135                           surf_lsm_h%end_index(j,i)
4136                      surf_lsm_h%rad_sw_in(m)     = rrtm_swdflx(0,k_topo)
4137                      surf_lsm_h%rad_sw_out(m)    = rrtm_swuflx(0,k_topo)
4138                   ENDDO             
4139                   DO  m = surf_usm_h%start_index(j,i),                        &
4140                           surf_usm_h%end_index(j,i)
4141                      surf_usm_h%rad_sw_in(m)     = rrtm_swdflx(0,k_topo)
4142                      surf_usm_h%rad_sw_out(m)    = rrtm_swuflx(0,k_topo)
4143                   ENDDO 
4144!
4145!--                Vertical surfaces. Fluxes are obtain at respective vertical
4146!--                level of the surface element
4147                   DO  l = 0, 3
4148                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
4149                              surf_lsm_v(l)%end_index(j,i)
4150                         k                           = surf_lsm_v(l)%k(m)
4151                         surf_lsm_v(l)%rad_sw_in(m)  = rrtm_swdflx(0,k)
4152                         surf_lsm_v(l)%rad_sw_out(m) = rrtm_swuflx(0,k)
4153                      ENDDO             
4154                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
4155                              surf_usm_v(l)%end_index(j,i)
4156                         k                           = surf_usm_v(l)%k(m)
4157                         surf_usm_v(l)%rad_sw_in(m)  = rrtm_swdflx(0,k)
4158                         surf_usm_v(l)%rad_sw_out(m) = rrtm_swuflx(0,k)
4159                      ENDDO 
4160                   ENDDO
4161!
4162!--             Solar radiation is zero during night
4163                ELSE
4164                   rad_sw_in  = 0.0_wp
4165                   rad_sw_out = 0.0_wp
4166!--             !!!!!!!! ATTENSION !!!!!!!!!!!!!!!
4167!--             Surface radiative fluxes should be also set to zero here                 
4168!--                Save surface radiative fluxes onto respective surface elements
4169!--                Horizontal surfaces
4170                   DO  m = surf_lsm_h%start_index(j,i),                        &
4171                           surf_lsm_h%end_index(j,i)
4172                      surf_lsm_h%rad_sw_in(m)     = 0.0_wp
4173                      surf_lsm_h%rad_sw_out(m)    = 0.0_wp
4174                   ENDDO             
4175                   DO  m = surf_usm_h%start_index(j,i),                        &
4176                           surf_usm_h%end_index(j,i)
4177                      surf_usm_h%rad_sw_in(m)     = 0.0_wp
4178                      surf_usm_h%rad_sw_out(m)    = 0.0_wp
4179                   ENDDO 
4180!
4181!--                Vertical surfaces. Fluxes are obtain at respective vertical
4182!--                level of the surface element
4183                   DO  l = 0, 3
4184                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
4185                              surf_lsm_v(l)%end_index(j,i)
4186                         k                           = surf_lsm_v(l)%k(m)
4187                         surf_lsm_v(l)%rad_sw_in(m)  = 0.0_wp
4188                         surf_lsm_v(l)%rad_sw_out(m) = 0.0_wp
4189                      ENDDO             
4190                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
4191                              surf_usm_v(l)%end_index(j,i)
4192                         k                           = surf_usm_v(l)%k(m)
4193                         surf_usm_v(l)%rad_sw_in(m)  = 0.0_wp
4194                         surf_usm_v(l)%rad_sw_out(m) = 0.0_wp
4195                      ENDDO 
4196                   ENDDO
4197                ENDIF
4198
4199             ENDDO
4200          ENDDO
4201
4202       ENDIF
4203!
4204!--    Finally, calculate surface net radiation for surface elements.
4205       IF (  .NOT.  radiation_interactions  ) THEN
4206!--       First, for horizontal surfaces   
4207          DO  m = 1, surf_lsm_h%ns
4208             surf_lsm_h%rad_net(m) = surf_lsm_h%rad_sw_in(m)                   &
4209                                   - surf_lsm_h%rad_sw_out(m)                  &
4210                                   + surf_lsm_h%rad_lw_in(m)                   &
4211                                   - surf_lsm_h%rad_lw_out(m)
4212          ENDDO
4213          DO  m = 1, surf_usm_h%ns
4214             surf_usm_h%rad_net(m) = surf_usm_h%rad_sw_in(m)                   &
4215                                   - surf_usm_h%rad_sw_out(m)                  &
4216                                   + surf_usm_h%rad_lw_in(m)                   &
4217                                   - surf_usm_h%rad_lw_out(m)
4218          ENDDO
4219!
4220!--       Vertical surfaces.
4221!--       Todo: weight with azimuth and zenith angle according to their orientation!
4222          DO  l = 0, 3     
4223             DO  m = 1, surf_lsm_v(l)%ns
4224                surf_lsm_v(l)%rad_net(m) = surf_lsm_v(l)%rad_sw_in(m)          &
4225                                         - surf_lsm_v(l)%rad_sw_out(m)         &
4226                                         + surf_lsm_v(l)%rad_lw_in(m)          &
4227                                         - surf_lsm_v(l)%rad_lw_out(m)
4228             ENDDO
4229             DO  m = 1, surf_usm_v(l)%ns
4230                surf_usm_v(l)%rad_net(m) = surf_usm_v(l)%rad_sw_in(m)          &
4231                                         - surf_usm_v(l)%rad_sw_out(m)         &
4232                                         + surf_usm_v(l)%rad_lw_in(m)          &
4233                                         - surf_usm_v(l)%rad_lw_out(m)
4234             ENDDO
4235          ENDDO
4236       ENDIF
4237
4238
4239       CALL exchange_horiz( rad_lw_in,  nbgp )
4240       CALL exchange_horiz( rad_lw_out, nbgp )
4241       CALL exchange_horiz( rad_lw_hr,    nbgp )
4242       CALL exchange_horiz( rad_lw_cs_hr, nbgp )
4243
4244       CALL exchange_horiz( rad_sw_in,  nbgp )
4245       CALL exchange_horiz( rad_sw_out, nbgp ) 
4246       CALL exchange_horiz( rad_sw_hr,    nbgp )
4247       CALL exchange_horiz( rad_sw_cs_hr, nbgp )
4248
4249#endif
4250
4251    END SUBROUTINE radiation_rrtmg
4252
4253
4254!------------------------------------------------------------------------------!
4255! Description:
4256! ------------
4257!> Calculate the cosine of the zenith angle (variable is called zenith)
4258!------------------------------------------------------------------------------!
4259    SUBROUTINE calc_zenith
4260
4261       IMPLICIT NONE
4262
4263       REAL(wp) ::  declination,  & !< solar declination angle
4264                    hour_angle      !< solar hour angle
4265!
4266!--    Calculate current day and time based on the initial values and simulation
4267!--    time
4268       CALL calc_date_and_time
4269
4270!
4271!--    Calculate solar declination and hour angle   
4272       declination = ASIN( decl_1 * SIN(decl_2 * REAL(day_of_year, KIND=wp) - decl_3) )
4273       hour_angle  = 2.0_wp * pi * (time_utc / 86400.0_wp) + lon - pi
4274
4275!
4276!--    Calculate cosine of solar zenith angle
4277       cos_zenith = SIN(lat) * SIN(declination) + COS(lat) * COS(declination)   &
4278                                            * COS(hour_angle)
4279       cos_zenith = MAX(0.0_wp,cos_zenith)
4280
4281!
4282!--    Calculate solar directional vector
4283       IF ( sun_direction )  THEN
4284
4285!
4286!--       Direction in longitudes equals to sin(solar_azimuth) * sin(zenith)
4287          sun_dir_lon = -SIN(hour_angle) * COS(declination)
4288
4289!
4290!--       Direction in latitues equals to cos(solar_azimuth) * sin(zenith)
4291          sun_dir_lat = SIN(declination) * COS(lat) - COS(hour_angle) &
4292                              * COS(declination) * SIN(lat)
4293       ENDIF
4294
4295!
4296!--    Check if the sun is up (otheriwse shortwave calculations can be skipped)
4297       IF ( cos_zenith > 0.0_wp )  THEN
4298          sun_up = .TRUE.
4299       ELSE
4300          sun_up = .FALSE.
4301       END IF
4302
4303    END SUBROUTINE calc_zenith
4304
4305#if defined ( __rrtmg ) && defined ( __netcdf )
4306!------------------------------------------------------------------------------!
4307! Description:
4308! ------------
4309!> Calculates surface albedo components based on Briegleb (1992) and
4310!> Briegleb et al. (1986)
4311!------------------------------------------------------------------------------!
4312    SUBROUTINE calc_albedo( surf )
4313
4314        IMPLICIT NONE
4315
4316        INTEGER(iwp)    ::  ind_type !< running index surface tiles
4317        INTEGER(iwp)    ::  m        !< running index surface elements
4318
4319        TYPE(surf_type) ::  surf !< treated surfaces
4320
4321        IF ( sun_up  .AND.  .NOT. average_radiation )  THEN
4322
4323           DO  m = 1, surf%ns
4324!
4325!--           Loop over surface elements
4326              DO  ind_type = 0, SIZE( surf%albedo_type, 1 ) - 1
4327           
4328!
4329!--              Ocean
4330                 IF ( surf%albedo_type(ind_type,m) == 1 )  THEN
4331                    surf%rrtm_aldir(ind_type,m) = 0.026_wp /                    &
4332                                                ( cos_zenith**1.7_wp + 0.065_wp )&
4333                                     + 0.15_wp * ( cos_zenith - 0.1_wp )         &
4334                                               * ( cos_zenith - 0.5_wp )         &
4335                                               * ( cos_zenith - 1.0_wp )
4336                    surf%rrtm_asdir(ind_type,m) = surf%rrtm_aldir(ind_type,m)
4337!
4338!--              Snow
4339                 ELSEIF ( surf%albedo_type(ind_type,m) == 16 )  THEN
4340                    IF ( cos_zenith < 0.5_wp )  THEN
4341                       surf%rrtm_aldir(ind_type,m) =                           &
4342                                 0.5_wp * ( 1.0_wp - surf%aldif(ind_type,m) )  &
4343                                        * ( 3.0_wp / ( 1.0_wp + 4.0_wp         &
4344                                        * cos_zenith ) ) - 1.0_wp
4345                       surf%rrtm_asdir(ind_type,m) =                           &
4346                                 0.5_wp * ( 1.0_wp - surf%asdif(ind_type,m) )  &
4347                                        * ( 3.0_wp / ( 1.0_wp + 4.0_wp         &
4348                                        * cos_zenith ) ) - 1.0_wp
4349
4350                       surf%rrtm_aldir(ind_type,m) =                           &
4351                                       MIN(0.98_wp, surf%rrtm_aldir(ind_type,m))
4352                       surf%rrtm_asdir(ind_type,m) =                           &
4353                                       MIN(0.98_wp, surf%rrtm_asdir(ind_type,m))
4354                    ELSE
4355                       surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4356                       surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4357                    ENDIF
4358!
4359!--              Sea ice
4360                 ELSEIF ( surf%albedo_type(ind_type,m) == 15 )  THEN
4361                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4362                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4363
4364!
4365!--              Asphalt
4366                 ELSEIF ( surf%albedo_type(ind_type,m) == 17 )  THEN
4367                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4368                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4369
4370
4371!
4372!--              Bare soil
4373                 ELSEIF ( surf%albedo_type(ind_type,m) == 18 )  THEN
4374                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4375                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4376
4377!
4378!--              Land surfaces
4379                 ELSE
4380                    SELECT CASE ( surf%albedo_type(ind_type,m) )
4381
4382!
4383!--                    Surface types with strong zenith dependence
4384                       CASE ( 1, 2, 3, 4, 11, 12, 13 )
4385                          surf%rrtm_aldir(ind_type,m) =                        &
4386                                surf%aldif(ind_type,m) * 1.4_wp /              &
4387                                           ( 1.0_wp + 0.8_wp * cos_zenith )
4388                          surf%rrtm_asdir(ind_type,m) =                        &
4389                                surf%asdif(ind_type,m) * 1.4_wp /              &
4390                                           ( 1.0_wp + 0.8_wp * cos_zenith )
4391!
4392!--                    Surface types with weak zenith dependence
4393                       CASE ( 5, 6, 7, 8, 9, 10, 14 )
4394                          surf%rrtm_aldir(ind_type,m) =                        &
4395                                surf%aldif(ind_type,m) * 1.1_wp /              &
4396                                           ( 1.0_wp + 0.2_wp * cos_zenith )
4397                          surf%rrtm_asdir(ind_type,m) =                        &
4398                                surf%asdif(ind_type,m) * 1.1_wp /              &
4399                                           ( 1.0_wp + 0.2_wp * cos_zenith )
4400
4401                       CASE DEFAULT
4402
4403                    END SELECT
4404                 ENDIF
4405!
4406!--              Diffusive albedo is taken from Table 2
4407                 surf%rrtm_aldif(ind_type,m) = surf%aldif(ind_type,m)
4408                 surf%rrtm_asdif(ind_type,m) = surf%asdif(ind_type,m)
4409              ENDDO
4410           ENDDO
4411!
4412!--     Set albedo in case of average radiation
4413        ELSEIF ( sun_up  .AND.  average_radiation )  THEN
4414           surf%rrtm_asdir = albedo_urb
4415           surf%rrtm_asdif = albedo_urb
4416           surf%rrtm_aldir = albedo_urb
4417           surf%rrtm_aldif = albedo_urb 
4418!
4419!--     Darkness
4420        ELSE
4421           surf%rrtm_aldir = 0.0_wp
4422           surf%rrtm_asdir = 0.0_wp
4423           surf%rrtm_aldif = 0.0_wp
4424           surf%rrtm_asdif = 0.0_wp
4425        ENDIF
4426
4427    END SUBROUTINE calc_albedo
4428
4429!------------------------------------------------------------------------------!
4430! Description:
4431! ------------
4432!> Read sounding data (pressure and temperature) from RADIATION_DATA.
4433!------------------------------------------------------------------------------!
4434    SUBROUTINE read_sounding_data
4435
4436       IMPLICIT NONE
4437
4438       INTEGER(iwp) :: id,           & !< NetCDF id of input file
4439                       id_dim_zrad,  & !< pressure level id in the NetCDF file
4440                       id_var,       & !< NetCDF variable id
4441                       k,            & !< loop index
4442                       nz_snd,       & !< number of vertical levels in the sounding data
4443                       nz_snd_start, & !< start vertical index for sounding data to be used
4444                       nz_snd_end      !< end vertical index for souding data to be used
4445
4446       REAL(wp) :: t_surface           !< actual surface temperature
4447
4448       REAL(wp), DIMENSION(:), ALLOCATABLE ::  hyp_snd_tmp, & !< temporary hydrostatic pressure profile (sounding)
4449                                               t_snd_tmp      !< temporary temperature profile (sounding)
4450
4451!
4452!--    In case of updates, deallocate arrays first (sufficient to check one
4453!--    array as the others are automatically allocated). This is required
4454!--    because nzt_rad might change during the update
4455       IF ( ALLOCATED ( hyp_snd ) )  THEN
4456          DEALLOCATE( hyp_snd )
4457          DEALLOCATE( t_snd )
4458          DEALLOCATE ( rrtm_play )
4459          DEALLOCATE ( rrtm_plev )
4460          DEALLOCATE ( rrtm_tlay )
4461          DEALLOCATE ( rrtm_tlev )
4462
4463          DEALLOCATE ( rrtm_cicewp )
4464          DEALLOCATE ( rrtm_cldfr )
4465          DEALLOCATE ( rrtm_cliqwp )
4466          DEALLOCATE ( rrtm_reice )
4467          DEALLOCATE ( rrtm_reliq )
4468          DEALLOCATE ( rrtm_lw_taucld )
4469          DEALLOCATE ( rrtm_lw_tauaer )
4470
4471          DEALLOCATE ( rrtm_lwdflx  )
4472          DEALLOCATE ( rrtm_lwdflxc )
4473          DEALLOCATE ( rrtm_lwuflx  )
4474          DEALLOCATE ( rrtm_lwuflxc )
4475          DEALLOCATE ( rrtm_lwuflx_dt )
4476          DEALLOCATE ( rrtm_lwuflxc_dt )
4477          DEALLOCATE ( rrtm_lwhr  )
4478          DEALLOCATE ( rrtm_lwhrc )
4479
4480          DEALLOCATE ( rrtm_sw_taucld )
4481          DEALLOCATE ( rrtm_sw_ssacld )
4482          DEALLOCATE ( rrtm_sw_asmcld )
4483          DEALLOCATE ( rrtm_sw_fsfcld )
4484          DEALLOCATE ( rrtm_sw_tauaer )
4485          DEALLOCATE ( rrtm_sw_ssaaer )
4486          DEALLOCATE ( rrtm_sw_asmaer ) 
4487          DEALLOCATE ( rrtm_sw_ecaer )   
4488 
4489          DEALLOCATE ( rrtm_swdflx  )
4490          DEALLOCATE ( rrtm_swdflxc )
4491          DEALLOCATE ( rrtm_swuflx  )
4492          DEALLOCATE ( rrtm_swuflxc )
4493          DEALLOCATE ( rrtm_swhr  )
4494          DEALLOCATE ( rrtm_swhrc )
4495          DEALLOCATE ( rrtm_dirdflux )
4496          DEALLOCATE ( rrtm_difdflux )
4497
4498       ENDIF
4499
4500!
4501!--    Open file for reading
4502       nc_stat = NF90_OPEN( rrtm_input_file, NF90_NOWRITE, id )
4503       CALL netcdf_handle_error_rad( 'read_sounding_data', 549 )
4504
4505!
4506!--    Inquire dimension of z axis and save in nz_snd
4507       nc_stat = NF90_INQ_DIMID( id, "Pressure", id_dim_zrad )
4508       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim_zrad, len = nz_snd )
4509       CALL netcdf_handle_error_rad( 'read_sounding_data', 551 )
4510
4511!
4512! !--    Allocate temporary array for storing pressure data
4513       ALLOCATE( hyp_snd_tmp(1:nz_snd) )
4514       hyp_snd_tmp = 0.0_wp
4515
4516
4517!--    Read pressure from file
4518       nc_stat = NF90_INQ_VARID( id, "Pressure", id_var )
4519       nc_stat = NF90_GET_VAR( id, id_var, hyp_snd_tmp(:), start = (/1/),      &
4520                               count = (/nz_snd/) )
4521       CALL netcdf_handle_error_rad( 'read_sounding_data', 552 )
4522
4523!
4524!--    Allocate temporary array for storing temperature data
4525       ALLOCATE( t_snd_tmp(1:nz_snd) )
4526       t_snd_tmp = 0.0_wp
4527
4528!
4529!--    Read temperature from file
4530       nc_stat = NF90_INQ_VARID( id, "ReferenceTemperature", id_var )
4531       nc_stat = NF90_GET_VAR( id, id_var, t_snd_tmp(:), start = (/1/),        &
4532                               count = (/nz_snd/) )
4533       CALL netcdf_handle_error_rad( 'read_sounding_data', 553 )
4534
4535!
4536!--    Calculate start of sounding data
4537       nz_snd_start = nz_snd + 1
4538       nz_snd_end   = nz_snd + 1
4539
4540!
4541!--    Start filling vertical dimension at 10hPa above the model domain (hyp is
4542!--    in Pa, hyp_snd in hPa).
4543       DO  k = 1, nz_snd
4544          IF ( hyp_snd_tmp(k) < ( hyp(nzt+1) - 1000.0_wp) * 0.01_wp )  THEN
4545             nz_snd_start = k
4546             EXIT
4547          END IF
4548       END DO
4549
4550       IF ( nz_snd_start <= nz_snd )  THEN
4551          nz_snd_end = nz_snd
4552       END IF
4553
4554
4555!
4556!--    Calculate of total grid points for RRTMG calculations
4557       nzt_rad = nzt + nz_snd_end - nz_snd_start + 1
4558
4559!
4560!--    Save data above LES domain in hyp_snd, t_snd
4561       ALLOCATE( hyp_snd(nzb+1:nzt_rad) )
4562       ALLOCATE( t_snd(nzb+1:nzt_rad)   )
4563       hyp_snd = 0.0_wp
4564       t_snd = 0.0_wp
4565
4566       hyp_snd(nzt+2:nzt_rad) = hyp_snd_tmp(nz_snd_start+1:nz_snd_end)
4567       t_snd(nzt+2:nzt_rad)   = t_snd_tmp(nz_snd_start+1:nz_snd_end)
4568
4569       nc_stat = NF90_CLOSE( id )
4570
4571!
4572!--    Calculate pressure levels on zu and zw grid. Sounding data is added at
4573!--    top of the LES domain. This routine does not consider horizontal or
4574!--    vertical variability of pressure and temperature
4575       ALLOCATE ( rrtm_play(0:0,nzb+1:nzt_rad+1)   )
4576       ALLOCATE ( rrtm_plev(0:0,nzb+1:nzt_rad+2)   )
4577
4578       t_surface = pt_surface * exner(nzb)
4579       DO k = nzb+1, nzt+1
4580          rrtm_play(0,k) = hyp(k) * 0.01_wp
4581          rrtm_plev(0,k) = barometric_formula(zw(k-1),                         &
4582                              pt_surface * exner(nzb), &
4583                              surface_pressure )
4584       ENDDO
4585
4586       DO k = nzt+2, nzt_rad
4587          rrtm_play(0,k) = hyp_snd(k)
4588          rrtm_plev(0,k) = 0.5_wp * ( rrtm_play(0,k) + rrtm_play(0,k-1) )
4589       ENDDO
4590       rrtm_plev(0,nzt_rad+1) = MAX( 0.5 * hyp_snd(nzt_rad),                   &
4591                                   1.5 * hyp_snd(nzt_rad)                      &
4592                                 - 0.5 * hyp_snd(nzt_rad-1) )
4593       rrtm_plev(0,nzt_rad+2)  = MIN( 1.0E-4_wp,                               &
4594                                      0.25_wp * rrtm_plev(0,nzt_rad+1) )
4595
4596       rrtm_play(0,nzt_rad+1) = 0.5 * rrtm_plev(0,nzt_rad+1)
4597
4598!
4599!--    Calculate temperature/humidity levels at top of the LES domain.
4600!--    Currently, the temperature is taken from sounding data (might lead to a
4601!--    temperature jump at interface. To do: Humidity is currently not
4602!--    calculated above the LES domain.
4603       ALLOCATE ( rrtm_tlay(0:0,nzb+1:nzt_rad+1)   )
4604       ALLOCATE ( rrtm_tlev(0:0,nzb+1:nzt_rad+2)   )
4605
4606       DO k = nzt+8, nzt_rad
4607          rrtm_tlay(0,k)   = t_snd(k)
4608       ENDDO
4609       rrtm_tlay(0,nzt_rad+1) = 2.0_wp * rrtm_tlay(0,nzt_rad)                  &
4610                                - rrtm_tlay(0,nzt_rad-1)
4611       DO k = nzt+9, nzt_rad+1
4612          rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k)                &
4613                             - rrtm_tlay(0,k-1))                               &
4614                             / ( rrtm_play(0,k) - rrtm_play(0,k-1) )           &
4615                             * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
4616       ENDDO
4617
4618       rrtm_tlev(0,nzt_rad+2)   = 2.0_wp * rrtm_tlay(0,nzt_rad+1)              &
4619                                  - rrtm_tlev(0,nzt_rad)
4620!
4621!--    Allocate remaining RRTMG arrays
4622       ALLOCATE ( rrtm_cicewp(0:0,nzb+1:nzt_rad+1) )
4623       ALLOCATE ( rrtm_cldfr(0:0,nzb+1:nzt_rad+1) )
4624       ALLOCATE ( rrtm_cliqwp(0:0,nzb+1:nzt_rad+1) )
4625       ALLOCATE ( rrtm_reice(0:0,nzb+1:nzt_rad+1) )
4626       ALLOCATE ( rrtm_reliq(0:0,nzb+1:nzt_rad+1) )
4627       ALLOCATE ( rrtm_lw_taucld(1:nbndlw+1,0:0,nzb+1:nzt_rad+1) )
4628       ALLOCATE ( rrtm_lw_tauaer(0:0,nzb+1:nzt_rad+1,1:nbndlw+1) )
4629       ALLOCATE ( rrtm_sw_taucld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4630       ALLOCATE ( rrtm_sw_ssacld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4631       ALLOCATE ( rrtm_sw_asmcld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4632       ALLOCATE ( rrtm_sw_fsfcld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4633       ALLOCATE ( rrtm_sw_tauaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) )
4634       ALLOCATE ( rrtm_sw_ssaaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) )
4635       ALLOCATE ( rrtm_sw_asmaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) ) 
4636       ALLOCATE ( rrtm_sw_ecaer(0:0,nzb+1:nzt_rad+1,1:naerec+1) )   
4637
4638!
4639!--    The ice phase is currently not considered in PALM
4640       rrtm_cicewp = 0.0_wp
4641       rrtm_reice  = 0.0_wp
4642
4643!
4644!--    Set other parameters (move to NAMELIST parameters in the future)
4645       rrtm_lw_tauaer = 0.0_wp
4646       rrtm_lw_taucld = 0.0_wp
4647       rrtm_sw_taucld = 0.0_wp
4648       rrtm_sw_ssacld = 0.0_wp
4649       rrtm_sw_asmcld = 0.0_wp
4650       rrtm_sw_fsfcld = 0.0_wp
4651       rrtm_sw_tauaer = 0.0_wp
4652       rrtm_sw_ssaaer = 0.0_wp
4653       rrtm_sw_asmaer = 0.0_wp
4654       rrtm_sw_ecaer  = 0.0_wp
4655
4656
4657       ALLOCATE ( rrtm_swdflx(0:0,nzb:nzt_rad+1)  )
4658       ALLOCATE ( rrtm_swuflx(0:0,nzb:nzt_rad+1)  )
4659       ALLOCATE ( rrtm_swhr(0:0,nzb+1:nzt_rad+1)  )
4660       ALLOCATE ( rrtm_swuflxc(0:0,nzb:nzt_rad+1) )
4661       ALLOCATE ( rrtm_swdflxc(0:0,nzb:nzt_rad+1) )
4662       ALLOCATE ( rrtm_swhrc(0:0,nzb+1:nzt_rad+1) )
4663       ALLOCATE ( rrtm_dirdflux(0:0,nzb:nzt_rad+1) )
4664       ALLOCATE ( rrtm_difdflux(0:0,nzb:nzt_rad+1) )
4665
4666       rrtm_swdflx  = 0.0_wp
4667       rrtm_swuflx  = 0.0_wp
4668       rrtm_swhr    = 0.0_wp 
4669       rrtm_swuflxc = 0.0_wp
4670       rrtm_swdflxc = 0.0_wp
4671       rrtm_swhrc   = 0.0_wp
4672       rrtm_dirdflux = 0.0_wp
4673       rrtm_difdflux = 0.0_wp
4674
4675       ALLOCATE ( rrtm_lwdflx(0:0,nzb:nzt_rad+1)  )
4676       ALLOCATE ( rrtm_lwuflx(0:0,nzb:nzt_rad+1)  )
4677       ALLOCATE ( rrtm_lwhr(0:0,nzb+1:nzt_rad+1)  )
4678       ALLOCATE ( rrtm_lwuflxc(0:0,nzb:nzt_rad+1) )
4679       ALLOCATE ( rrtm_lwdflxc(0:0,nzb:nzt_rad+1) )
4680       ALLOCATE ( rrtm_lwhrc(0:0,nzb+1:nzt_rad+1) )
4681
4682       rrtm_lwdflx  = 0.0_wp
4683       rrtm_lwuflx  = 0.0_wp
4684       rrtm_lwhr    = 0.0_wp 
4685       rrtm_lwuflxc = 0.0_wp
4686       rrtm_lwdflxc = 0.0_wp
4687       rrtm_lwhrc   = 0.0_wp
4688
4689       ALLOCATE ( rrtm_lwuflx_dt(0:0,nzb:nzt_rad+1) )
4690       ALLOCATE ( rrtm_lwuflxc_dt(0:0,nzb:nzt_rad+1) )
4691
4692       rrtm_lwuflx_dt = 0.0_wp
4693       rrtm_lwuflxc_dt = 0.0_wp
4694
4695    END SUBROUTINE read_sounding_data
4696
4697
4698!------------------------------------------------------------------------------!
4699! Description:
4700! ------------
4701!> Read trace gas data from file and convert into trace gas paths / volume
4702!> mixing ratios. If a user-defined input file is provided it needs to follow
4703!> the convections used in RRTMG (see respective netCDF files shipped with
4704!> RRTMG)
4705!------------------------------------------------------------------------------!
4706    SUBROUTINE read_trace_gas_data
4707
4708       USE rrsw_ncpar
4709
4710       IMPLICIT NONE
4711
4712       INTEGER(iwp), PARAMETER :: num_trace_gases = 10 !< number of trace gases (absorbers)
4713
4714       CHARACTER(LEN=5), DIMENSION(num_trace_gases), PARAMETER ::              & !< trace gas names
4715           trace_names = (/'O3   ', 'CO2  ', 'CH4  ', 'N2O  ', 'O2   ',        &
4716                           'CFC11', 'CFC12', 'CFC22', 'CCL4 ', 'H2O  '/)
4717
4718       INTEGER(iwp) :: id,     & !< NetCDF id
4719                       k,      & !< loop index
4720                       m,      & !< loop index
4721                       n,      & !< loop index
4722                       nabs,   & !< number of absorbers
4723                       np,     & !< number of pressure levels
4724                       id_abs, & !< NetCDF id of the respective absorber
4725                       id_dim, & !< NetCDF id of asborber's dimension
4726                       id_var    !< NetCDf id ot the absorber
4727
4728       REAL(wp) :: p_mls_l, &    !< pressure lower limit for interpolation
4729                   p_mls_u, &    !< pressure upper limit for interpolation
4730                   p_wgt_l, &    !< pressure weight lower limit for interpolation
4731                   p_wgt_u, &    !< pressure weight upper limit for interpolation
4732                   p_mls_m       !< mean pressure between upper and lower limits
4733
4734
4735       REAL(wp), DIMENSION(:), ALLOCATABLE   ::  p_mls,          & !< pressure levels for the absorbers
4736                                                 rrtm_play_tmp,  & !< temporary array for pressure zu-levels
4737                                                 rrtm_plev_tmp,  & !< temporary array for pressure zw-levels
4738                                                 trace_path_tmp    !< temporary array for storing trace gas path data
4739
4740       REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  trace_mls,      & !< array for storing the absorber amounts
4741                                                 trace_mls_path, & !< array for storing trace gas path data
4742                                                 trace_mls_tmp     !< temporary array for storing trace gas data
4743
4744
4745!
4746!--    In case of updates, deallocate arrays first (sufficient to check one
4747!--    array as the others are automatically allocated)
4748       IF ( ALLOCATED ( rrtm_o3vmr ) )  THEN
4749          DEALLOCATE ( rrtm_o3vmr  )
4750          DEALLOCATE ( rrtm_co2vmr )
4751          DEALLOCATE ( rrtm_ch4vmr )
4752          DEALLOCATE ( rrtm_n2ovmr )
4753          DEALLOCATE ( rrtm_o2vmr  )
4754          DEALLOCATE ( rrtm_cfc11vmr )
4755          DEALLOCATE ( rrtm_cfc12vmr )
4756          DEALLOCATE ( rrtm_cfc22vmr )
4757          DEALLOCATE ( rrtm_ccl4vmr  )
4758          DEALLOCATE ( rrtm_h2ovmr  )     
4759       ENDIF
4760
4761!
4762!--    Allocate trace gas profiles
4763       ALLOCATE ( rrtm_o3vmr(0:0,1:nzt_rad+1)  )
4764       ALLOCATE ( rrtm_co2vmr(0:0,1:nzt_rad+1) )
4765       ALLOCATE ( rrtm_ch4vmr(0:0,1:nzt_rad+1) )
4766       ALLOCATE ( rrtm_n2ovmr(0:0,1:nzt_rad+1) )
4767       ALLOCATE ( rrtm_o2vmr(0:0,1:nzt_rad+1)  )
4768       ALLOCATE ( rrtm_cfc11vmr(0:0,1:nzt_rad+1) )
4769       ALLOCATE ( rrtm_cfc12vmr(0:0,1:nzt_rad+1) )
4770       ALLOCATE ( rrtm_cfc22vmr(0:0,1:nzt_rad+1) )
4771       ALLOCATE ( rrtm_ccl4vmr(0:0,1:nzt_rad+1)  )
4772       ALLOCATE ( rrtm_h2ovmr(0:0,1:nzt_rad+1)  )
4773
4774!
4775!--    Open file for reading
4776       nc_stat = NF90_OPEN( rrtm_input_file, NF90_NOWRITE, id )
4777       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 549 )
4778!
4779!--    Inquire dimension ids and dimensions
4780       nc_stat = NF90_INQ_DIMID( id, "Pressure", id_dim )
4781       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4782       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim, len = np) 
4783       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4784
4785       nc_stat = NF90_INQ_DIMID( id, "Absorber", id_dim )
4786       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4787       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim, len = nabs ) 
4788       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4789   
4790
4791!
4792!--    Allocate pressure, and trace gas arrays     
4793       ALLOCATE( p_mls(1:np) )
4794       ALLOCATE( trace_mls(1:num_trace_gases,1:np) ) 
4795       ALLOCATE( trace_mls_tmp(1:nabs,1:np) ) 
4796
4797
4798       nc_stat = NF90_INQ_VARID( id, "Pressure", id_var )
4799       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4800       nc_stat = NF90_GET_VAR( id, id_var, p_mls )
4801       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4802
4803       nc_stat = NF90_INQ_VARID( id, "AbsorberAmountMLS", id_var )
4804       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4805       nc_stat = NF90_GET_VAR( id, id_var, trace_mls_tmp )
4806       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4807
4808
4809!
4810!--    Write absorber amounts (mls) to trace_mls
4811       DO n = 1, num_trace_gases
4812          CALL getAbsorberIndex( TRIM( trace_names(n) ), id_abs )
4813
4814          trace_mls(n,1:np) = trace_mls_tmp(id_abs,1:np)
4815
4816!
4817!--       Replace missing values by zero
4818          WHERE ( trace_mls(n,:) > 2.0_wp ) 
4819             trace_mls(n,:) = 0.0_wp
4820          END WHERE
4821       END DO
4822
4823       DEALLOCATE ( trace_mls_tmp )
4824
4825       nc_stat = NF90_CLOSE( id )
4826       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 551 )
4827
4828!
4829!--    Add extra pressure level for calculations of the trace gas paths
4830       ALLOCATE ( rrtm_play_tmp(1:nzt_rad+1) )
4831       ALLOCATE ( rrtm_plev_tmp(1:nzt_rad+2) )
4832
4833       rrtm_play_tmp(1:nzt_rad)   = rrtm_play(0,1:nzt_rad) 
4834       rrtm_plev_tmp(1:nzt_rad+1) = rrtm_plev(0,1:nzt_rad+1)
4835       rrtm_play_tmp(nzt_rad+1)   = rrtm_plev(0,nzt_rad+1) * 0.5_wp
4836       rrtm_plev_tmp(nzt_rad+2)   = MIN( 1.0E-4_wp, 0.25_wp                    &
4837                                         * rrtm_plev(0,nzt_rad+1) )
4838 
4839!
4840!--    Calculate trace gas path (zero at surface) with interpolation to the
4841!--    sounding levels
4842       ALLOCATE ( trace_mls_path(1:nzt_rad+2,1:num_trace_gases) )
4843
4844       trace_mls_path(nzb+1,:) = 0.0_wp
4845       
4846       DO k = nzb+2, nzt_rad+2
4847          DO m = 1, num_trace_gases
4848             trace_mls_path(k,m) = trace_mls_path(k-1,m)
4849
4850!
4851!--          When the pressure level is higher than the trace gas pressure
4852!--          level, assume that
4853             IF ( rrtm_plev_tmp(k-1) > p_mls(1) )  THEN             
4854               
4855                trace_mls_path(k,m) = trace_mls_path(k,m) + trace_mls(m,1)     &
4856                                      * ( rrtm_plev_tmp(k-1)                   &
4857                                          - MAX( p_mls(1), rrtm_plev_tmp(k) )  &
4858                                        ) / g
4859             ENDIF
4860
4861!
4862!--          Integrate for each sounding level from the contributing p_mls
4863!--          levels
4864             DO n = 2, np
4865!
4866!--             Limit p_mls so that it is within the model level
4867                p_mls_u = MIN( rrtm_plev_tmp(k-1),                             &
4868                          MAX( rrtm_plev_tmp(k), p_mls(n) ) )
4869                p_mls_l = MIN( rrtm_plev_tmp(k-1),                             &
4870                          MAX( rrtm_plev_tmp(k), p_mls(n-1) ) )
4871
4872                IF ( p_mls_l > p_mls_u )  THEN
4873
4874!
4875!--                Calculate weights for interpolation
4876                   p_mls_m = 0.5_wp * (p_mls_l + p_mls_u)
4877                   p_wgt_u = (p_mls(n-1) - p_mls_m) / (p_mls(n-1) - p_mls(n))
4878                   p_wgt_l = (p_mls_m - p_mls(n))   / (p_mls(n-1) - p_mls(n))
4879
4880!
4881!--                Add level to trace gas path
4882                   trace_mls_path(k,m) = trace_mls_path(k,m)                   &
4883                                         +  ( p_wgt_u * trace_mls(m,n)         &
4884                                            + p_wgt_l * trace_mls(m,n-1) )     &
4885                                         * (p_mls_l - p_mls_u) / g
4886                ENDIF
4887             ENDDO
4888
4889             IF ( rrtm_plev_tmp(k) < p_mls(np) )  THEN
4890                trace_mls_path(k,m) = trace_mls_path(k,m) + trace_mls(m,np)    &
4891                                      * ( MIN( rrtm_plev_tmp(k-1), p_mls(np) ) &
4892                                          - rrtm_plev_tmp(k)                   &
4893                                        ) / g 
4894             ENDIF 
4895          ENDDO
4896       ENDDO
4897
4898
4899!
4900!--    Prepare trace gas path profiles
4901       ALLOCATE ( trace_path_tmp(1:nzt_rad+1) )
4902
4903       DO m = 1, num_trace_gases
4904
4905          trace_path_tmp(1:nzt_rad+1) = ( trace_mls_path(2:nzt_rad+2,m)        &
4906                                       - trace_mls_path(1:nzt_rad+1,m) ) * g   &
4907                                       / ( rrtm_plev_tmp(1:nzt_rad+1)          &
4908                                       - rrtm_plev_tmp(2:nzt_rad+2) )
4909
4910!
4911!--       Save trace gas paths to the respective arrays
4912          SELECT CASE ( TRIM( trace_names(m) ) )
4913
4914             CASE ( 'O3' )
4915
4916                rrtm_o3vmr(0,:) = trace_path_tmp(:)
4917
4918             CASE ( 'CO2' )
4919
4920                rrtm_co2vmr(0,:) = trace_path_tmp(:)
4921
4922             CASE ( 'CH4' )
4923
4924                rrtm_ch4vmr(0,:) = trace_path_tmp(:)
4925
4926             CASE ( 'N2O' )
4927
4928                rrtm_n2ovmr(0,:) = trace_path_tmp(:)
4929
4930             CASE ( 'O2' )
4931
4932                rrtm_o2vmr(0,:) = trace_path_tmp(:)
4933
4934             CASE ( 'CFC11' )
4935
4936                rrtm_cfc11vmr(0,:) = trace_path_tmp(:)
4937
4938             CASE ( 'CFC12' )
4939
4940                rrtm_cfc12vmr(0,:) = trace_path_tmp(:)
4941
4942             CASE ( 'CFC22' )
4943
4944                rrtm_cfc22vmr(0,:) = trace_path_tmp(:)
4945
4946             CASE ( 'CCL4' )
4947
4948                rrtm_ccl4vmr(0,:) = trace_path_tmp(:)
4949
4950             CASE ( 'H2O' )
4951
4952                rrtm_h2ovmr(0,:) = trace_path_tmp(:)
4953               
4954             CASE DEFAULT
4955
4956          END SELECT
4957
4958       ENDDO
4959
4960       DEALLOCATE ( trace_path_tmp )
4961       DEALLOCATE ( trace_mls_path )
4962       DEALLOCATE ( rrtm_play_tmp )
4963       DEALLOCATE ( rrtm_plev_tmp )
4964       DEALLOCATE ( trace_mls )
4965       DEALLOCATE ( p_mls )
4966
4967    END SUBROUTINE read_trace_gas_data
4968
4969
4970    SUBROUTINE netcdf_handle_error_rad( routine_name, errno )
4971
4972       USE control_parameters,                                                 &
4973           ONLY:  message_string
4974
4975       USE NETCDF
4976
4977       USE pegrid
4978
4979       IMPLICIT NONE
4980
4981       CHARACTER(LEN=6) ::  message_identifier
4982       CHARACTER(LEN=*) ::  routine_name
4983
4984       INTEGER(iwp) ::  errno
4985
4986       IF ( nc_stat /= NF90_NOERR )  THEN
4987
4988          WRITE( message_identifier, '(''NC'',I4.4)' )  errno
4989          message_string = TRIM( NF90_STRERROR( nc_stat ) )
4990
4991          CALL message( routine_name, message_identifier, 2, 2, 0, 6, 1 )
4992
4993       ENDIF
4994
4995    END SUBROUTINE netcdf_handle_error_rad
4996#endif
4997
4998
4999!------------------------------------------------------------------------------!
5000! Description:
5001! ------------
5002!> Calculate temperature tendency due to radiative cooling/heating.
5003!> Cache-optimized version.
5004!------------------------------------------------------------------------------!
5005#if defined( __rrtmg )
5006 SUBROUTINE radiation_tendency_ij ( i, j, tend )
5007
5008    IMPLICIT NONE
5009
5010    INTEGER(iwp) :: i, j, k !< loop indices
5011
5012    REAL(wp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg) :: tend !< pt tendency term
5013
5014    IF ( radiation_scheme == 'rrtmg' )  THEN
5015!
5016!--    Calculate tendency based on heating rate
5017       DO k = nzb+1, nzt+1
5018          tend(k,j,i) = tend(k,j,i) + (rad_lw_hr(k,j,i) + rad_sw_hr(k,j,i))    &
5019                                         * d_exner(k) * d_seconds_hour
5020       ENDDO
5021
5022    ENDIF
5023
5024 END SUBROUTINE radiation_tendency_ij
5025#endif
5026
5027
5028!------------------------------------------------------------------------------!
5029! Description:
5030! ------------
5031!> Calculate temperature tendency due to radiative cooling/heating.
5032!> Vector-optimized version
5033!------------------------------------------------------------------------------!
5034#if defined( __rrtmg )
5035 SUBROUTINE radiation_tendency ( tend )
5036
5037    USE indices,                                                               &
5038        ONLY:  nxl, nxr, nyn, nys
5039
5040    IMPLICIT NONE
5041
5042    INTEGER(iwp) :: i, j, k !< loop indices
5043
5044    REAL(wp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg) :: tend !< pt tendency term
5045
5046    IF ( radiation_scheme == 'rrtmg' )  THEN
5047!
5048!--    Calculate tendency based on heating rate
5049       DO  i = nxl, nxr
5050          DO  j = nys, nyn
5051             DO k = nzb+1, nzt+1
5052                tend(k,j,i) = tend(k,j,i) + ( rad_lw_hr(k,j,i)                 &
5053                                          +  rad_sw_hr(k,j,i) ) * d_exner(k)   &
5054                                          * d_seconds_hour
5055             ENDDO
5056          ENDDO
5057       ENDDO
5058    ENDIF
5059
5060 END SUBROUTINE radiation_tendency
5061#endif
5062
5063!------------------------------------------------------------------------------!
5064! Description:
5065! ------------
5066!> This subroutine calculates interaction of the solar radiation
5067!> with urban and land surfaces and updates all surface heatfluxes.
5068!> It calculates also the required parameters for RRTMG lower BC.
5069!>
5070!> For more info. see Resler et al. 2017
5071!>
5072!> The new version 2.0 was radically rewriten, the discretization scheme
5073!> has been changed. This new version significantly improves effectivity
5074!> of the paralelization and the scalability of the model.
5075!------------------------------------------------------------------------------!
5076
5077 SUBROUTINE radiation_interaction
5078
5079     IMPLICIT NONE
5080
5081     INTEGER(iwp)                      :: i, j, k, kk, d, refstep, m, mm, l, ll
5082     INTEGER(iwp)                      :: isurf, isurfsrc, isvf, icsf, ipcgb
5083     INTEGER(iwp)                      :: imrt, imrtf
5084     INTEGER(iwp)                      :: isd                !< solar direction number
5085     INTEGER(iwp)                      :: pc_box_dimshift    !< transform for best accuracy
5086     INTEGER(iwp), DIMENSION(0:3)      :: reorder = (/ 1, 0, 3, 2 /)
5087     
5088     REAL(wp), DIMENSION(3,3)          :: mrot               !< grid rotation matrix (zyx)
5089     REAL(wp), DIMENSION(3,0:nsurf_type):: vnorm             !< face direction normal vectors (zyx)
5090     REAL(wp), DIMENSION(3)            :: sunorig            !< grid rotated solar direction unit vector (zyx)
5091     REAL(wp), DIMENSION(3)            :: sunorig_grid       !< grid squashed solar direction unit vector (zyx)
5092     REAL(wp), DIMENSION(0:nsurf_type) :: costheta           !< direct irradiance factor of solar angle
5093     REAL(wp), DIMENSION(nz_urban_b:nz_urban_t)    :: pchf_prep          !< precalculated factor for canopy temperature tendency
5094     REAL(wp), PARAMETER               :: alpha = 0._wp      !< grid rotation (TODO: synchronize with rotation_angle
5095                                                             !< from netcdf_data_input_mod)
5096     REAL(wp)                          :: pc_box_area, pc_abs_frac, pc_abs_eff
5097     REAL(wp)                          :: asrc               !< area of source face
5098     REAL(wp)                          :: pcrad              !< irradiance from plant canopy
5099     REAL(wp)                          :: pabsswl  = 0.0_wp  !< total absorbed SW radiation energy in local processor (W)
5100     REAL(wp)                          :: pabssw   = 0.0_wp  !< total absorbed SW radiation energy in all processors (W)
5101     REAL(wp)                          :: pabslwl  = 0.0_wp  !< total absorbed LW radiation energy in local processor (W)
5102     REAL(wp)                          :: pabslw   = 0.0_wp  !< total absorbed LW radiation energy in all processors (W)
5103     REAL(wp)                          :: pemitlwl = 0.0_wp  !< total emitted LW radiation energy in all processors (W)
5104     REAL(wp)                          :: pemitlw  = 0.0_wp  !< total emitted LW radiation energy in all processors (W)
5105     REAL(wp)                          :: pinswl   = 0.0_wp  !< total received SW radiation energy in local processor (W)
5106     REAL(wp)                          :: pinsw    = 0.0_wp  !< total received SW radiation energy in all processor (W)
5107     REAL(wp)                          :: pinlwl   = 0.0_wp  !< total received LW radiation energy in local processor (W)
5108     REAL(wp)                          :: pinlw    = 0.0_wp  !< total received LW radiation energy in all processor (W)
5109     REAL(wp)                          :: emiss_sum_surfl    !< sum of emissisivity of surfaces in local processor
5110     REAL(wp)                          :: emiss_sum_surf     !< sum of emissisivity of surfaces in all processor
5111     REAL(wp)                          :: area_surfl         !< total area of surfaces in local processor
5112     REAL(wp)                          :: area_surf          !< total area of surfaces in all processor
5113     REAL(wp)                          :: area_hor           !< total horizontal area of domain in all processor
5114
5115
5116     IF ( debug_output_timestep )  CALL debug_message( 'radiation_interaction', 'start' )
5117
5118     IF ( plant_canopy )  THEN
5119         pchf_prep(:) = r_d * exner(nz_urban_b:nz_urban_t)                                 &
5120                     / (c_p * hyp(nz_urban_b:nz_urban_t) * dx*dy*dz(1)) !< equals to 1 / (rho * c_p * Vbox * T)
5121     ENDIF
5122
5123     sun_direction = .TRUE.
5124     CALL calc_zenith  !< required also for diffusion radiation
5125
5126!--     prepare rotated normal vectors and irradiance factor
5127     vnorm(1,:) = kdir(:)
5128     vnorm(2,:) = jdir(:)
5129     vnorm(3,:) = idir(:)
5130     mrot(1, :) = (/ 1._wp,  0._wp,      0._wp      /)
5131     mrot(2, :) = (/ 0._wp,  COS(alpha), SIN(alpha) /)
5132     mrot(3, :) = (/ 0._wp, -SIN(alpha), COS(alpha) /)
5133     sunorig = (/ cos_zenith, sun_dir_lat, sun_dir_lon /)
5134     sunorig = MATMUL(mrot, sunorig)
5135     DO d = 0, nsurf_type
5136         costheta(d) = DOT_PRODUCT(sunorig, vnorm(:,d))
5137     ENDDO
5138
5139     IF ( cos_zenith > 0 )  THEN
5140!--      now we will "squash" the sunorig vector by grid box size in
5141!--      each dimension, so that this new direction vector will allow us
5142!--      to traverse the ray path within grid coordinates directly
5143         sunorig_grid = (/ sunorig(1)/dz(1), sunorig(2)/dy, sunorig(3)/dx /)
5144!--      sunorig_grid = sunorig_grid / norm2(sunorig_grid)
5145         sunorig_grid = sunorig_grid / SQRT(SUM(sunorig_grid**2))
5146
5147         IF ( npcbl > 0 )  THEN
5148!--         precompute effective box depth with prototype Leaf Area Density
5149            pc_box_dimshift = MAXLOC(ABS(sunorig), 1) - 1
5150            CALL box_absorb(CSHIFT((/dz(1),dy,dx/), pc_box_dimshift),       &
5151                                60, prototype_lad,                          &
5152                                CSHIFT(ABS(sunorig), pc_box_dimshift),      &
5153                                pc_box_area, pc_abs_frac)
5154            pc_box_area = pc_box_area * ABS(sunorig(pc_box_dimshift+1)      &
5155                          / sunorig(1))
5156            pc_abs_eff = LOG(1._wp - pc_abs_frac) / prototype_lad
5157         ENDIF
5158     ENDIF
5159
5160!--  if radiation scheme is not RRTMG, split diffusion and direct part of the solar downward radiation
5161!--  comming from radiation model and store it in 2D arrays
5162     IF (  radiation_scheme /= 'rrtmg'  )  CALL calc_diffusion_radiation
5163
5164!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5165!--     First pass: direct + diffuse irradiance + thermal
5166!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5167     surfinswdir   = 0._wp !nsurfl
5168     surfins       = 0._wp !nsurfl
5169     surfinl       = 0._wp !nsurfl
5170     surfoutsl(:)  = 0.0_wp !start-end
5171     surfoutll(:)  = 0.0_wp !start-end
5172     IF ( nmrtbl > 0 )  THEN
5173        mrtinsw(:) = 0._wp
5174        mrtinlw(:) = 0._wp
5175     ENDIF
5176     surfinlg(:)  = 0._wp !global
5177
5178
5179!--  Set up thermal radiation from surfaces
5180!--  emiss_surf is defined only for surfaces for which energy balance is calculated
5181!--  Workaround: reorder surface data type back on 1D array including all surfaces,
5182!--  which implies to reorder horizontal and vertical surfaces
5183!
5184!--  Horizontal walls
5185     mm = 1
5186     DO  i = nxl, nxr
5187        DO  j = nys, nyn
5188!--           urban
5189           DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
5190              surfoutll(mm) = SUM ( surf_usm_h%frac(:,m) *                  &
5191                                    surf_usm_h%emissivity(:,m) )            &
5192                                  * sigma_sb                                &
5193                                  * surf_usm_h%pt_surface(m)**4
5194              albedo_surf(mm) = SUM ( surf_usm_h%frac(:,m) *                &
5195                                      surf_usm_h%albedo(:,m) )
5196              emiss_surf(mm)  = SUM ( surf_usm_h%frac(:,m) *                &
5197                                      surf_usm_h%emissivity(:,m) )
5198              mm = mm + 1
5199           ENDDO
5200!--           land
5201           DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
5202              surfoutll(mm) = SUM ( surf_lsm_h%frac(:,m) *                  &
5203                                    surf_lsm_h%emissivity(:,m) )            &
5204                                  * sigma_sb                                &
5205                                  * surf_lsm_h%pt_surface(m)**4
5206              albedo_surf(mm) = SUM ( surf_lsm_h%frac(:,m) *                &
5207                                      surf_lsm_h%albedo(:,m) )
5208              emiss_surf(mm)  = SUM ( surf_lsm_h%frac(:,m) *                &
5209                                      surf_lsm_h%emissivity(:,m) )
5210              mm = mm + 1
5211           ENDDO
5212        ENDDO
5213     ENDDO
5214!
5215!--     Vertical walls
5216     DO  i = nxl, nxr
5217        DO  j = nys, nyn
5218           DO  ll = 0, 3
5219              l = reorder(ll)
5220!--              urban
5221              DO  m = surf_usm_v(l)%start_index(j,i),                       &
5222                      surf_usm_v(l)%end_index(j,i)
5223                 surfoutll(mm) = SUM ( surf_usm_v(l)%frac(:,m) *            &
5224                                       surf_usm_v(l)%emissivity(:,m) )      &
5225                                  * sigma_sb                                &
5226                                  * surf_usm_v(l)%pt_surface(m)**4
5227                 albedo_surf(mm) = SUM ( surf_usm_v(l)%frac(:,m) *          &
5228                                         surf_usm_v(l)%albedo(:,m) )
5229                 emiss_surf(mm)  = SUM ( surf_usm_v(l)%frac(:,m) *          &
5230                                         surf_usm_v(l)%emissivity(:,m) )
5231                 mm = mm + 1
5232              ENDDO
5233!--              land
5234              DO  m = surf_lsm_v(l)%start_index(j,i),                       &
5235                      surf_lsm_v(l)%end_index(j,i)
5236                 surfoutll(mm) = SUM ( surf_lsm_v(l)%frac(:,m) *            &
5237                                       surf_lsm_v(l)%emissivity(:,m) )      &
5238                                  * sigma_sb                                &
5239                                  * surf_lsm_v(l)%pt_surface(m)**4
5240                 albedo_surf(mm) = SUM ( surf_lsm_v(l)%frac(:,m) *          &
5241                                         surf_lsm_v(l)%albedo(:,m) )
5242                 emiss_surf(mm)  = SUM ( surf_lsm_v(l)%frac(:,m) *          &
5243                                         surf_lsm_v(l)%emissivity(:,m) )
5244                 mm = mm + 1
5245              ENDDO
5246           ENDDO
5247        ENDDO
5248     ENDDO
5249
5250#if defined( __parallel )
5251!--     might be optimized and gather only values relevant for current processor
5252     CALL MPI_AllGatherv(surfoutll, nsurfl, MPI_REAL, &
5253                         surfoutl, nsurfs, surfstart, MPI_REAL, comm2d, ierr) !nsurf global
5254     IF ( ierr /= 0 ) THEN
5255         WRITE(9,*) 'Error MPI_AllGatherv1:', ierr, SIZE(surfoutll), nsurfl, &
5256                     SIZE(surfoutl), nsurfs, surfstart
5257         FLUSH(9)
5258     ENDIF
5259#else
5260     surfoutl(:) = surfoutll(:) !nsurf global
5261#endif
5262
5263     IF ( surface_reflections)  THEN
5264        DO  isvf = 1, nsvfl
5265           isurf = svfsurf(1, isvf)
5266           k     = surfl(iz, isurf)
5267           j     = surfl(iy, isurf)
5268           i     = surfl(ix, isurf)
5269           isurfsrc = svfsurf(2, isvf)
5270!
5271!--        For surface-to-surface factors we calculate thermal radiation in 1st pass
5272           IF ( plant_lw_interact )  THEN
5273              surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * svf(2,isvf) * surfoutl(isurfsrc)
5274           ELSE
5275              surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * surfoutl(isurfsrc)
5276           ENDIF
5277        ENDDO
5278     ENDIF
5279!
5280!--  diffuse radiation using sky view factor
5281     DO isurf = 1, nsurfl
5282        j = surfl(iy, isurf)
5283        i = surfl(ix, isurf)
5284        surfinswdif(isurf) = rad_sw_in_diff(j,i) * skyvft(isurf)
5285        IF ( plant_lw_interact )  THEN
5286           surfinlwdif(isurf) = rad_lw_in_diff(j,i) * skyvft(isurf)
5287        ELSE
5288           surfinlwdif(isurf) = rad_lw_in_diff(j,i) * skyvf(isurf)
5289        ENDIF
5290     ENDDO
5291!
5292!--  MRT diffuse irradiance
5293     DO  imrt = 1, nmrtbl
5294        j = mrtbl(iy, imrt)
5295        i = mrtbl(ix, imrt)
5296        mrtinsw(imrt) = mrtskyt(imrt) * rad_sw_in_diff(j,i)
5297        mrtinlw(imrt) = mrtsky(imrt) * rad_lw_in_diff(j,i)
5298     ENDDO
5299
5300     !-- direct radiation
5301     IF ( cos_zenith > 0 )  THEN
5302        !--Identify solar direction vector (discretized number) 1)
5303        !--
5304        j = FLOOR(ACOS(cos_zenith) / pi * raytrace_discrete_elevs)
5305        i = MODULO(NINT(ATAN2(sun_dir_lon, sun_dir_lat)               &
5306                        / (2._wp*pi) * raytrace_discrete_azims-.5_wp, iwp), &
5307                   raytrace_discrete_azims)
5308        isd = dsidir_rev(j, i)
5309!-- TODO: check if isd = -1 to report that this solar position is not precalculated
5310        DO isurf = 1, nsurfl
5311           j = surfl(iy, isurf)
5312           i = surfl(ix, isurf)
5313           surfinswdir(isurf) = rad_sw_in_dir(j,i) *                        &
5314                costheta(surfl(id, isurf)) * dsitrans(isurf, isd) / cos_zenith
5315        ENDDO
5316!
5317!--     MRT direct irradiance
5318        DO  imrt = 1, nmrtbl
5319           j = mrtbl(iy, imrt)
5320           i = mrtbl(ix, imrt)
5321           mrtinsw(imrt) = mrtinsw(imrt) + mrtdsit(imrt, isd) * rad_sw_in_dir(j,i) &
5322                                     / cos_zenith / 4._wp ! normal to sphere
5323        ENDDO
5324     ENDIF
5325!
5326!--  MRT first pass thermal
5327     DO  imrtf = 1, nmrtf
5328        imrt = mrtfsurf(1, imrtf)
5329        isurfsrc = mrtfsurf(2, imrtf)
5330        mrtinlw(imrt) = mrtinlw(imrt) + mrtf(imrtf) * surfoutl(isurfsrc)
5331     ENDDO
5332!
5333!--  Absorption in each local plant canopy grid box from the first atmospheric
5334!--  pass of radiation
5335     IF ( npcbl > 0 )  THEN
5336
5337         pcbinswdir(:) = 0._wp
5338         pcbinswdif(:) = 0._wp
5339         pcbinlw(:) = 0._wp
5340
5341         DO icsf = 1, ncsfl
5342             ipcgb = csfsurf(1, icsf)
5343             i = pcbl(ix,ipcgb)
5344             j = pcbl(iy,ipcgb)
5345             k = pcbl(iz,ipcgb)
5346             isurfsrc = csfsurf(2, icsf)
5347
5348             IF ( isurfsrc == -1 )  THEN
5349!
5350!--             Diffuse radiation from sky
5351                pcbinswdif(ipcgb) = csf(1,icsf) * rad_sw_in_diff(j,i)
5352!
5353!--             Absorbed diffuse LW radiation from sky minus emitted to sky
5354                IF ( plant_lw_interact )  THEN
5355                   pcbinlw(ipcgb) = csf(1,icsf)                                  &
5356                                       * (rad_lw_in_diff(j, i)                   &
5357                                          - sigma_sb * (pt(k,j,i)*exner(k))**4)
5358                ENDIF
5359!
5360!--             Direct solar radiation
5361                IF ( cos_zenith > 0 )  THEN
5362!--                Estimate directed box absorption
5363                   pc_abs_frac = 1._wp - exp(pc_abs_eff * lad_s(k,j,i))
5364!
5365!--                isd has already been established, see 1)
5366                   pcbinswdir(ipcgb) = rad_sw_in_dir(j, i) * pc_box_area &
5367                                       * pc_abs_frac * dsitransc(ipcgb, isd)
5368                ENDIF
5369             ELSE
5370                IF ( plant_lw_interact )  THEN
5371!
5372!--                Thermal emission from plan canopy towards respective face
5373                   pcrad = sigma_sb * (pt(k,j,i) * exner(k))**4 * csf(1,icsf)
5374                   surfinlg(isurfsrc) = surfinlg(isurfsrc) + pcrad
5375!
5376!--                Remove the flux above + absorb LW from first pass from surfaces
5377                   asrc = facearea(surf(id, isurfsrc))
5378                   pcbinlw(ipcgb) = pcbinlw(ipcgb)                      &
5379                                    + (csf(1,icsf) * surfoutl(isurfsrc) & ! Absorb from first pass surf emit
5380                                       - pcrad)                         & ! Remove emitted heatflux
5381                                    * asrc
5382                ENDIF
5383             ENDIF
5384         ENDDO
5385
5386         pcbinsw(:) = pcbinswdir(:) + pcbinswdif(:)
5387     ENDIF
5388
5389     IF ( plant_lw_interact )  THEN
5390!
5391!--     Exchange incoming lw radiation from plant canopy
5392#if defined( __parallel )
5393        CALL MPI_Allreduce(MPI_IN_PLACE, surfinlg, nsurf, MPI_REAL, MPI_SUM, comm2d, ierr)
5394        IF ( ierr /= 0 )  THEN
5395           WRITE (9,*) 'Error MPI_Allreduce:', ierr
5396           FLUSH(9)
5397        ENDIF
5398        surfinl(:) = surfinl(:) + surfinlg(surfstart(myid)+1:surfstart(myid+1))
5399#else
5400        surfinl(:) = surfinl(:) + surfinlg(:)
5401#endif
5402     ENDIF
5403
5404     surfins = surfinswdir + surfinswdif
5405     surfinl = surfinl + surfinlwdif
5406     surfinsw = surfins
5407     surfinlw = surfinl
5408     surfoutsw = 0.0_wp
5409     surfoutlw = surfoutll
5410     surfemitlwl = surfoutll
5411
5412     IF ( .NOT.  surface_reflections )  THEN
5413!
5414!--     Set nrefsteps to 0 to disable reflections       
5415        nrefsteps = 0
5416        surfoutsl = albedo_surf * surfins
5417        surfoutll = (1._wp - emiss_surf) * surfinl
5418        surfoutsw = surfoutsw + surfoutsl
5419        surfoutlw = surfoutlw + surfoutll
5420     ENDIF
5421
5422!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5423!--     Next passes - reflections
5424!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5425     DO refstep = 1, nrefsteps
5426
5427         surfoutsl = albedo_surf * surfins
5428!
5429!--      for non-transparent surfaces, longwave albedo is 1 - emissivity
5430         surfoutll = (1._wp - emiss_surf) * surfinl
5431
5432#if defined( __parallel )
5433         CALL MPI_AllGatherv(surfoutsl, nsurfl, MPI_REAL, &
5434             surfouts, nsurfs, surfstart, MPI_REAL, comm2d, ierr)
5435         IF ( ierr /= 0 )  THEN
5436             WRITE(9,*) 'Error MPI_AllGatherv2:', ierr, SIZE(surfoutsl), nsurfl, &
5437                        SIZE(surfouts), nsurfs, surfstart
5438             FLUSH(9)
5439         ENDIF
5440
5441         CALL MPI_AllGatherv(surfoutll, nsurfl, MPI_REAL, &
5442             surfoutl, nsurfs, surfstart, MPI_REAL, comm2d, ierr)
5443         IF ( ierr /= 0 )  THEN
5444             WRITE(9,*) 'Error MPI_AllGatherv3:', ierr, SIZE(surfoutll), nsurfl, &
5445                        SIZE(surfoutl), nsurfs, surfstart
5446             FLUSH(9)
5447         ENDIF
5448
5449#else
5450         surfouts = surfoutsl
5451         surfoutl = surfoutll
5452#endif
5453!
5454!--      Reset for the input from next reflective pass
5455         surfins = 0._wp
5456         surfinl = 0._wp
5457!
5458!--      Reflected radiation
5459         DO isvf = 1, nsvfl
5460             isurf = svfsurf(1, isvf)
5461             isurfsrc = svfsurf(2, isvf)
5462             surfins(isurf) = surfins(isurf) + svf(1,isvf) * svf(2,isvf) * surfouts(isurfsrc)
5463             IF ( plant_lw_interact )  THEN
5464                surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * svf(2,isvf) * surfoutl(isurfsrc)
5465             ELSE
5466                surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * surfoutl(isurfsrc)
5467             ENDIF
5468         ENDDO
5469!
5470!--      NOTE: PC absorbtion and MRT from reflected can both be done at once
5471!--      after all reflections if we do one more MPI_ALLGATHERV on surfout.
5472!--      Advantage: less local computation. Disadvantage: one more collective
5473!--      MPI call.
5474!
5475!--      Radiation absorbed by plant canopy
5476         DO  icsf = 1, ncsfl
5477             ipcgb = csfsurf(1, icsf)
5478             isurfsrc = csfsurf(2, icsf)
5479             IF ( isurfsrc == -1 )  CYCLE ! sky->face only in 1st pass, not here
5480!
5481!--          Calculate source surface area. If the `surf' array is removed
5482!--          before timestepping starts (future version), then asrc must be
5483!--          stored within `csf'
5484             asrc = facearea(surf(id, isurfsrc))
5485             pcbinsw(ipcgb) = pcbinsw(ipcgb) + csf(1,icsf) * surfouts(isurfsrc) * asrc
5486             IF ( plant_lw_interact )  THEN
5487                pcbinlw(ipcgb) = pcbinlw(ipcgb) + csf(1,icsf) * surfoutl(isurfsrc) * asrc
5488             ENDIF
5489         ENDDO
5490!
5491!--      MRT reflected
5492         DO  imrtf = 1, nmrtf
5493            imrt = mrtfsurf(1, imrtf)
5494            isurfsrc = mrtfsurf(2, imrtf)
5495            mrtinsw(imrt) = mrtinsw(imrt) + mrtft(imrtf) * surfouts(isurfsrc)
5496            mrtinlw(imrt) = mrtinlw(imrt) + mrtf(imrtf) * surfoutl(isurfsrc)
5497         ENDDO
5498
5499         surfinsw = surfinsw  + surfins
5500         surfinlw = surfinlw  + surfinl
5501         surfoutsw = surfoutsw + surfoutsl
5502         surfoutlw = surfoutlw + surfoutll
5503
5504     ENDDO ! refstep
5505
5506!--  push heat flux absorbed by plant canopy to respective 3D arrays
5507     IF ( npcbl > 0 )  THEN
5508         pc_heating_rate(:,:,:) = 0.0_wp
5509         DO ipcgb = 1, npcbl
5510             j = pcbl(iy, ipcgb)
5511             i = pcbl(ix, ipcgb)
5512             k = pcbl(iz, ipcgb)
5513!
5514!--          Following expression equals former kk = k - nzb_s_inner(j,i)
5515             kk = k - get_topography_top_index_ji( j, i, 's' )  !- lad arrays are defined flat
5516             pc_heating_rate(kk, j, i) = (pcbinsw(ipcgb) + pcbinlw(ipcgb)) &
5517                 * pchf_prep(k) * pt(k, j, i) !-- = dT/dt
5518         ENDDO
5519
5520         IF ( humidity .AND. plant_canopy_transpiration ) THEN
5521!--          Calculation of plant canopy transpiration rate and correspondidng latent heat rate
5522             pc_transpiration_rate(:,:,:) = 0.0_wp
5523             pc_latent_rate(:,:,:) = 0.0_wp
5524             DO ipcgb = 1, npcbl
5525                 i = pcbl(ix, ipcgb)
5526                 j = pcbl(iy, ipcgb)
5527                 k = pcbl(iz, ipcgb)
5528                 kk = k - get_topography_top_index_ji( j, i, 's' )  !- lad arrays are defined flat
5529                 CALL pcm_calc_transpiration_rate( i, j, k, kk, pcbinsw(ipcgb), pcbinlw(ipcgb), &
5530                                                   pc_transpiration_rate(kk,j,i), pc_latent_rate(kk,j,i) )
5531              ENDDO
5532         ENDIF
5533     ENDIF
5534!
5535!--  Calculate black body MRT (after all reflections)
5536     IF ( nmrtbl > 0 )  THEN
5537        IF ( mrt_include_sw )  THEN
5538           mrt(:) = ((mrtinsw(:) + mrtinlw(:)) / sigma_sb) ** .25_wp
5539        ELSE
5540           mrt(:) = (mrtinlw(:) / sigma_sb) ** .25_wp
5541        ENDIF
5542     ENDIF
5543!
5544!--     Transfer radiation arrays required for energy balance to the respective data types
5545     DO  i = 1, nsurfl
5546        m  = surfl(im,i)
5547!
5548!--     (1) Urban surfaces
5549!--     upward-facing
5550        IF ( surfl(1,i) == iup_u )  THEN
5551           surf_usm_h%rad_sw_in(m)  = surfinsw(i)
5552           surf_usm_h%rad_sw_out(m) = surfoutsw(i)
5553           surf_usm_h%rad_sw_dir(m) = surfinswdir(i)
5554           surf_usm_h%rad_sw_dif(m) = surfinswdif(i)
5555           surf_usm_h%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -        &
5556                                      surfinswdif(i)
5557           surf_usm_h%rad_sw_res(m) = surfins(i)
5558           surf_usm_h%rad_lw_in(m)  = surfinlw(i)
5559           surf_usm_h%rad_lw_out(m) = surfoutlw(i)
5560           surf_usm_h%rad_net(m)    = surfinsw(i) - surfoutsw(i) +          &
5561                                      surfinlw(i) - surfoutlw(i)
5562           surf_usm_h%rad_net_l(m)  = surf_usm_h%rad_net(m)
5563           surf_usm_h%rad_lw_dif(m) = surfinlwdif(i)
5564           surf_usm_h%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5565           surf_usm_h%rad_lw_res(m) = surfinl(i)
5566!
5567!--     northward-facding
5568        ELSEIF ( surfl(1,i) == inorth_u )  THEN
5569           surf_usm_v(0)%rad_sw_in(m)  = surfinsw(i)
5570           surf_usm_v(0)%rad_sw_out(m) = surfoutsw(i)
5571           surf_usm_v(0)%rad_sw_dir(m) = surfinswdir(i)
5572           surf_usm_v(0)%rad_sw_dif(m) = surfinswdif(i)
5573           surf_usm_v(0)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5574                                         surfinswdif(i)
5575           surf_usm_v(0)%rad_sw_res(m) = surfins(i)
5576           surf_usm_v(0)%rad_lw_in(m)  = surfinlw(i)
5577           surf_usm_v(0)%rad_lw_out(m) = surfoutlw(i)
5578           surf_usm_v(0)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5579                                         surfinlw(i) - surfoutlw(i)
5580           surf_usm_v(0)%rad_net_l(m)  = surf_usm_v(0)%rad_net(m)
5581           surf_usm_v(0)%rad_lw_dif(m) = surfinlwdif(i)
5582           surf_usm_v(0)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5583           surf_usm_v(0)%rad_lw_res(m) = surfinl(i)
5584!
5585!--     southward-facding
5586        ELSEIF ( surfl(1,i) == isouth_u )  THEN
5587           surf_usm_v(1)%rad_sw_in(m)  = surfinsw(i)
5588           surf_usm_v(1)%rad_sw_out(m) = surfoutsw(i)
5589           surf_usm_v(1)%rad_sw_dir(m) = surfinswdir(i)
5590           surf_usm_v(1)%rad_sw_dif(m) = surfinswdif(i)
5591           surf_usm_v(1)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5592                                         surfinswdif(i)
5593           surf_usm_v(1)%rad_sw_res(m) = surfins(i)
5594           surf_usm_v(1)%rad_lw_in(m)  = surfinlw(i)
5595           surf_usm_v(1)%rad_lw_out(m) = surfoutlw(i)
5596           surf_usm_v(1)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5597                                         surfinlw(i) - surfoutlw(i)
5598           surf_usm_v(1)%rad_net_l(m)  = surf_usm_v(1)%rad_net(m)
5599           surf_usm_v(1)%rad_lw_dif(m) = surfinlwdif(i)
5600           surf_usm_v(1)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5601           surf_usm_v(1)%rad_lw_res(m) = surfinl(i)
5602!
5603!--     eastward-facing
5604        ELSEIF ( surfl(1,i) == ieast_u )  THEN
5605           surf_usm_v(2)%rad_sw_in(m)  = surfinsw(i)
5606           surf_usm_v(2)%rad_sw_out(m) = surfoutsw(i)
5607           surf_usm_v(2)%rad_sw_dir(m) = surfinswdir(i)
5608           surf_usm_v(2)%rad_sw_dif(m) = surfinswdif(i)
5609           surf_usm_v(2)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5610                                         surfinswdif(i)
5611           surf_usm_v(2)%rad_sw_res(m) = surfins(i)
5612           surf_usm_v(2)%rad_lw_in(m)  = surfinlw(i)
5613           surf_usm_v(2)%rad_lw_out(m) = surfoutlw(i)
5614           surf_usm_v(2)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5615                                         surfinlw(i) - surfoutlw(i)
5616           surf_usm_v(2)%rad_net_l(m)  = surf_usm_v(2)%rad_net(m)
5617           surf_usm_v(2)%rad_lw_dif(m) = surfinlwdif(i)
5618           surf_usm_v(2)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5619           surf_usm_v(2)%rad_lw_res(m) = surfinl(i)
5620!
5621!--     westward-facding
5622        ELSEIF ( surfl(1,i) == iwest_u )  THEN
5623           surf_usm_v(3)%rad_sw_in(m)  = surfinsw(i)
5624           surf_usm_v(3)%rad_sw_out(m) = surfoutsw(i)
5625           surf_usm_v(3)%rad_sw_dir(m) = surfinswdir(i)
5626           surf_usm_v(3)%rad_sw_dif(m) = surfinswdif(i)
5627           surf_usm_v(3)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5628                                         surfinswdif(i)
5629           surf_usm_v(3)%rad_sw_res(m) = surfins(i)
5630           surf_usm_v(3)%rad_lw_in(m)  = surfinlw(i)
5631           surf_usm_v(3)%rad_lw_out(m) = surfoutlw(i)
5632           surf_usm_v(3)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5633                                         surfinlw(i) - surfoutlw(i)
5634           surf_usm_v(3)%rad_net_l(m)  = surf_usm_v(3)%rad_net(m)
5635           surf_usm_v(3)%rad_lw_dif(m) = surfinlwdif(i)
5636           surf_usm_v(3)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5637           surf_usm_v(3)%rad_lw_res(m) = surfinl(i)
5638!
5639!--     (2) land surfaces
5640!--     upward-facing
5641        ELSEIF ( surfl(1,i) == iup_l )  THEN
5642           surf_lsm_h%rad_sw_in(m)  = surfinsw(i)
5643           surf_lsm_h%rad_sw_out(m) = surfoutsw(i)
5644           surf_lsm_h%rad_sw_dir(m) = surfinswdir(i)
5645           surf_lsm_h%rad_sw_dif(m) = surfinswdif(i)
5646           surf_lsm_h%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -        &
5647                                         surfinswdif(i)
5648           surf_lsm_h%rad_sw_res(m) = surfins(i)
5649           surf_lsm_h%rad_lw_in(m)  = surfinlw(i)
5650           surf_lsm_h%rad_lw_out(m) = surfoutlw(i)
5651           surf_lsm_h%rad_net(m)    = surfinsw(i) - surfoutsw(i) +          &
5652                                      surfinlw(i) - surfoutlw(i)
5653           surf_lsm_h%rad_lw_dif(m) = surfinlwdif(i)
5654           surf_lsm_h%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5655           surf_lsm_h%rad_lw_res(m) = surfinl(i)
5656!
5657!--     northward-facding
5658        ELSEIF ( surfl(1,i) == inorth_l )  THEN
5659           surf_lsm_v(0)%rad_sw_in(m)  = surfinsw(i)
5660           surf_lsm_v(0)%rad_sw_out(m) = surfoutsw(i)
5661           surf_lsm_v(0)%rad_sw_dir(m) = surfinswdir(i)
5662           surf_lsm_v(0)%rad_sw_dif(m) = surfinswdif(i)
5663           surf_lsm_v(0)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5664                                         surfinswdif(i)
5665           surf_lsm_v(0)%rad_sw_res(m) = surfins(i)
5666           surf_lsm_v(0)%rad_lw_in(m)  = surfinlw(i)
5667           surf_lsm_v(0)%rad_lw_out(m) = surfoutlw(i)
5668           surf_lsm_v(0)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5669                                         surfinlw(i) - surfoutlw(i)
5670           surf_lsm_v(0)%rad_lw_dif(m) = surfinlwdif(i)
5671           surf_lsm_v(0)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5672           surf_lsm_v(0)%rad_lw_res(m) = surfinl(i)
5673!
5674!--     southward-facding
5675        ELSEIF ( surfl(1,i) == isouth_l )  THEN
5676           surf_lsm_v(1)%rad_sw_in(m)  = surfinsw(i)
5677           surf_lsm_v(1)%rad_sw_out(m) = surfoutsw(i)
5678           surf_lsm_v(1)%rad_sw_dir(m) = surfinswdir(i)
5679           surf_lsm_v(1)%rad_sw_dif(m) = surfinswdif(i)
5680           surf_lsm_v(1)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5681                                         surfinswdif(i)
5682           surf_lsm_v(1)%rad_sw_res(m) = surfins(i)
5683           surf_lsm_v(1)%rad_lw_in(m)  = surfinlw(i)
5684           surf_lsm_v(1)%rad_lw_out(m) = surfoutlw(i)
5685           surf_lsm_v(1)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5686                                         surfinlw(i) - surfoutlw(i)
5687           surf_lsm_v(1)%rad_lw_dif(m) = surfinlwdif(i)
5688           surf_lsm_v(1)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5689           surf_lsm_v(1)%rad_lw_res(m) = surfinl(i)
5690!
5691!--     eastward-facing
5692        ELSEIF ( surfl(1,i) == ieast_l )  THEN
5693           surf_lsm_v(2)%rad_sw_in(m)  = surfinsw(i)
5694           surf_lsm_v(2)%rad_sw_out(m) = surfoutsw(i)
5695           surf_lsm_v(2)%rad_sw_dir(m) = surfinswdir(i)
5696           surf_lsm_v(2)%rad_sw_dif(m) = surfinswdif(i)
5697           surf_lsm_v(2)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5698                                         surfinswdif(i)
5699           surf_lsm_v(2)%rad_sw_res(m) = surfins(i)
5700           surf_lsm_v(2)%rad_lw_in(m)  = surfinlw(i)
5701           surf_lsm_v(2)%rad_lw_out(m) = surfoutlw(i)
5702           surf_lsm_v(2)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5703                                         surfinlw(i) - surfoutlw(i)
5704           surf_lsm_v(2)%rad_lw_dif(m) = surfinlwdif(i)
5705           surf_lsm_v(2)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5706           surf_lsm_v(2)%rad_lw_res(m) = surfinl(i)
5707!
5708!--     westward-facing
5709        ELSEIF ( surfl(1,i) == iwest_l )  THEN
5710           surf_lsm_v(3)%rad_sw_in(m)  = surfinsw(i)
5711           surf_lsm_v(3)%rad_sw_out(m) = surfoutsw(i)
5712           surf_lsm_v(3)%rad_sw_dir(m) = surfinswdir(i)
5713           surf_lsm_v(3)%rad_sw_dif(m) = surfinswdif(i)
5714           surf_lsm_v(3)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5715                                         surfinswdif(i)
5716           surf_lsm_v(3)%rad_sw_res(m) = surfins(i)
5717           surf_lsm_v(3)%rad_lw_in(m)  = surfinlw(i)
5718           surf_lsm_v(3)%rad_lw_out(m) = surfoutlw(i)
5719           surf_lsm_v(3)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5720                                         surfinlw(i) - surfoutlw(i)
5721           surf_lsm_v(3)%rad_lw_dif(m) = surfinlwdif(i)
5722           surf_lsm_v(3)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5723           surf_lsm_v(3)%rad_lw_res(m) = surfinl(i)
5724        ENDIF
5725
5726     ENDDO
5727
5728     DO  m = 1, surf_usm_h%ns
5729        surf_usm_h%surfhf(m) = surf_usm_h%rad_sw_in(m)  +                   &
5730                               surf_usm_h%rad_lw_in(m)  -                   &
5731                               surf_usm_h%rad_sw_out(m) -                   &
5732                               surf_usm_h%rad_lw_out(m)
5733     ENDDO
5734     DO  m = 1, surf_lsm_h%ns
5735        surf_lsm_h%surfhf(m) = surf_lsm_h%rad_sw_in(m)  +                   &
5736                               surf_lsm_h%rad_lw_in(m)  -                   &
5737                               surf_lsm_h%rad_sw_out(m) -                   &
5738                               surf_lsm_h%rad_lw_out(m)
5739     ENDDO
5740
5741     DO  l = 0, 3
5742!--     urban
5743        DO  m = 1, surf_usm_v(l)%ns
5744           surf_usm_v(l)%surfhf(m) = surf_usm_v(l)%rad_sw_in(m)  +          &
5745                                     surf_usm_v(l)%rad_lw_in(m)  -          &
5746                                     surf_usm_v(l)%rad_sw_out(m) -          &
5747                                     surf_usm_v(l)%rad_lw_out(m)
5748        ENDDO
5749!--     land
5750        DO  m = 1, surf_lsm_v(l)%ns
5751           surf_lsm_v(l)%surfhf(m) = surf_lsm_v(l)%rad_sw_in(m)  +          &
5752                                     surf_lsm_v(l)%rad_lw_in(m)  -          &
5753                                     surf_lsm_v(l)%rad_sw_out(m) -          &
5754                                     surf_lsm_v(l)%rad_lw_out(m)
5755
5756        ENDDO
5757     ENDDO
5758!
5759!--  Calculate the average temperature, albedo, and emissivity for urban/land
5760!--  domain when using average_radiation in the respective radiation model
5761
5762!--  calculate horizontal area
5763! !!! ATTENTION!!! uniform grid is assumed here
5764     area_hor = (nx+1) * (ny+1) * dx * dy
5765!
5766!--  absorbed/received SW & LW and emitted LW energy of all physical
5767!--  surfaces (land and urban) in local processor
5768     pinswl = 0._wp
5769     pinlwl = 0._wp
5770     pabsswl = 0._wp
5771     pabslwl = 0._wp
5772     pemitlwl = 0._wp
5773     emiss_sum_surfl = 0._wp
5774     area_surfl = 0._wp
5775     DO  i = 1, nsurfl
5776        d = surfl(id, i)
5777!--  received SW & LW
5778        pinswl = pinswl + (surfinswdir(i) + surfinswdif(i)) * facearea(d)
5779        pinlwl = pinlwl + surfinlwdif(i) * facearea(d)
5780!--   absorbed SW & LW
5781        pabsswl = pabsswl + (1._wp - albedo_surf(i)) *                   &
5782                                                surfinsw(i) * facearea(d)
5783        pabslwl = pabslwl + emiss_surf(i) * surfinlw(i) * facearea(d)
5784!--   emitted LW
5785        pemitlwl = pemitlwl + surfemitlwl(i) * facearea(d)
5786!--   emissivity and area sum
5787        emiss_sum_surfl = emiss_sum_surfl + emiss_surf(i) * facearea(d)
5788        area_surfl = area_surfl + facearea(d)
5789     END DO
5790!
5791!--  add the absorbed SW energy by plant canopy
5792     IF ( npcbl > 0 )  THEN
5793        pabsswl = pabsswl + SUM(pcbinsw)
5794        pabslwl = pabslwl + SUM(pcbinlw)
5795        pinswl = pinswl + SUM(pcbinswdir) + SUM(pcbinswdif)
5796     ENDIF
5797!
5798!--  gather all rad flux energy in all processors
5799#if defined( __parallel )
5800     CALL MPI_ALLREDUCE( pinswl, pinsw, 1, MPI_REAL, MPI_SUM, comm2d, ierr)
5801     IF ( ierr /= 0 ) THEN
5802         WRITE(9,*) 'Error MPI_AllReduce5:', ierr, pinswl, pinsw
5803         FLUSH(9)
5804     ENDIF
5805     CALL MPI_ALLREDUCE( pinlwl, pinlw, 1, MPI_REAL, MPI_SUM, comm2d, ierr)
5806     IF ( ierr /= 0 ) THEN
5807         WRITE(9,*) 'Error MPI_AllReduce6:', ierr, pinlwl, pinlw
5808         FLUSH(9)
5809     ENDIF
5810     CALL MPI_ALLREDUCE( pabsswl, pabssw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5811     IF ( ierr /= 0 ) THEN
5812         WRITE(9,*) 'Error MPI_AllReduce7:', ierr, pabsswl, pabssw
5813         FLUSH(9)
5814     ENDIF
5815     CALL MPI_ALLREDUCE( pabslwl, pabslw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5816     IF ( ierr /= 0 ) THEN
5817         WRITE(9,*) 'Error MPI_AllReduce8:', ierr, pabslwl, pabslw
5818         FLUSH(9)
5819     ENDIF
5820     CALL MPI_ALLREDUCE( pemitlwl, pemitlw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5821     IF ( ierr /= 0 ) THEN
5822         WRITE(9,*) 'Error MPI_AllReduce8:', ierr, pemitlwl, pemitlw
5823         FLUSH(9)
5824     ENDIF
5825     CALL MPI_ALLREDUCE( emiss_sum_surfl, emiss_sum_surf, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5826     IF ( ierr /= 0 ) THEN
5827         WRITE(9,*) 'Error MPI_AllReduce9:', ierr, emiss_sum_surfl, emiss_sum_surf
5828         FLUSH(9)
5829     ENDIF
5830     CALL MPI_ALLREDUCE( area_surfl, area_surf, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5831     IF ( ierr /= 0 ) THEN
5832         WRITE(9,*) 'Error MPI_AllReduce10:', ierr, area_surfl, area_surf
5833         FLUSH(9)
5834     ENDIF
5835#else
5836     pinsw = pinswl
5837     pinlw = pinlwl
5838     pabssw = pabsswl
5839     pabslw = pabslwl
5840     pemitlw = pemitlwl
5841     emiss_sum_surf = emiss_sum_surfl
5842     area_surf = area_surfl
5843#endif
5844
5845!--  (1) albedo
5846     IF ( pinsw /= 0.0_wp )  &
5847          albedo_urb = (pinsw - pabssw) / pinsw
5848!--  (2) average emmsivity
5849     IF ( area_surf /= 0.0_wp ) &
5850          emissivity_urb = emiss_sum_surf / area_surf
5851!
5852!--  Temporally comment out calculation of effective radiative temperature.
5853!--  See below for more explanation.
5854!--  (3) temperature
5855!--   first we calculate an effective horizontal area to account for
5856!--   the effect of vertical surfaces (which contributes to LW emission)
5857!--   We simply use the ratio of the total LW to the incoming LW flux
5858      area_hor = pinlw/rad_lw_in_diff(nyn,nxl)
5859      t_rad_urb = ( (pemitlw - pabslw + emissivity_urb*pinlw) / &
5860           (emissivity_urb*sigma_sb * area_hor) )**0.25_wp
5861
5862     IF ( debug_output_timestep )  CALL debug_message( 'radiation_interaction', 'end' )
5863
5864
5865    CONTAINS
5866
5867!------------------------------------------------------------------------------!
5868!> Calculates radiation absorbed by box with given size and LAD.
5869!>
5870!> Simulates resol**2 rays (by equally spacing a bounding horizontal square
5871!> conatining all possible rays that would cross the box) and calculates
5872!> average transparency per ray. Returns fraction of absorbed radiation flux
5873!> and area for which this fraction is effective.
5874!------------------------------------------------------------------------------!
5875    PURE SUBROUTINE box_absorb(boxsize, resol, dens, uvec, area, absorb)
5876       IMPLICIT NONE
5877
5878       REAL(wp), DIMENSION(3), INTENT(in) :: &
5879            boxsize, &      !< z, y, x size of box in m
5880            uvec            !< z, y, x unit vector of incoming flux
5881       INTEGER(iwp), INTENT(in) :: &
5882            resol           !< No. of rays in x and y dimensions
5883       REAL(wp), INTENT(in) :: &
5884            dens            !< box density (e.g. Leaf Area Density)
5885       REAL(wp), INTENT(out) :: &
5886            area, &         !< horizontal area for flux absorbtion
5887            absorb          !< fraction of absorbed flux
5888       REAL(wp) :: &
5889            xshift, yshift, &
5890            xmin, xmax, ymin, ymax, &
5891            xorig, yorig, &
5892            dx1, dy1, dz1, dx2, dy2, dz2, &
5893            crdist, &
5894            transp
5895       INTEGER(iwp) :: &
5896            i, j
5897
5898       xshift = uvec(3) / uvec(1) * boxsize(1)
5899       xmin = min(0._wp, -xshift)
5900       xmax = boxsize(3) + max(0._wp, -xshift)
5901       yshift = uvec(2) / uvec(1) * boxsize(1)
5902       ymin = min(0._wp, -yshift)
5903       ymax = boxsize(2) + max(0._wp, -yshift)
5904
5905       transp = 0._wp
5906       DO i = 1, resol
5907          xorig = xmin + (xmax-xmin) * (i-.5_wp) / resol
5908          DO j = 1, resol
5909             yorig = ymin + (ymax-ymin) * (j-.5_wp) / resol
5910
5911             dz1 = 0._wp
5912             dz2 = boxsize(1)/uvec(1)
5913
5914             IF ( uvec(2) > 0._wp )  THEN
5915                dy1 = -yorig             / uvec(2) !< crossing with y=0
5916                dy2 = (boxsize(2)-yorig) / uvec(2) !< crossing with y=boxsize(2)
5917             ELSE !uvec(2)==0
5918                dy1 = -huge(1._wp)
5919                dy2 = huge(1._wp)
5920             ENDIF
5921
5922             IF ( uvec(3) > 0._wp )  THEN
5923                dx1 = -xorig             / uvec(3) !< crossing with x=0
5924                dx2 = (boxsize(3)-xorig) / uvec(3) !< crossing with x=boxsize(3)
5925             ELSE !uvec(3)==0
5926                dx1 = -huge(1._wp)
5927                dx2 = huge(1._wp)
5928             ENDIF
5929
5930             crdist = max(0._wp, (min(dz2, dy2, dx2) - max(dz1, dy1, dx1)))
5931             transp = transp + exp(-ext_coef * dens * crdist)
5932          ENDDO
5933       ENDDO
5934       transp = transp / resol**2
5935       area = (boxsize(3)+xshift)*(boxsize(2)+yshift)
5936       absorb = 1._wp - transp
5937
5938    END SUBROUTINE box_absorb
5939
5940!------------------------------------------------------------------------------!
5941! Description:
5942! ------------
5943!> This subroutine splits direct and diffusion dw radiation
5944!> It sould not be called in case the radiation model already does it
5945!> It follows Boland, Ridley & Brown (2008)
5946!------------------------------------------------------------------------------!
5947    SUBROUTINE calc_diffusion_radiation 
5948   
5949        REAL(wp), PARAMETER                          :: lowest_solarUp = 0.1_wp  !< limit the sun elevation to protect stability of the calculation
5950        INTEGER(iwp)                                 :: i, j
5951        REAL(wp)                                     ::  year_angle              !< angle
5952        REAL(wp)                                     ::  etr                     !< extraterestrial radiation
5953        REAL(wp)                                     ::  corrected_solarUp       !< corrected solar up radiation
5954        REAL(wp)                                     ::  horizontalETR           !< horizontal extraterestrial radiation
5955        REAL(wp)                                     ::  clearnessIndex          !< clearness index
5956        REAL(wp)                                     ::  diff_frac               !< diffusion fraction of the radiation
5957
5958       
5959!--     Calculate current day and time based on the initial values and simulation time
5960        year_angle = ( (day_of_year_init * 86400) + time_utc_init              &
5961                        + time_since_reference_point )  * d_seconds_year       &
5962                        * 2.0_wp * pi
5963       
5964        etr = solar_constant * (1.00011_wp +                                   &
5965                          0.034221_wp * cos(year_angle) +                      &
5966                          0.001280_wp * sin(year_angle) +                      &
5967                          0.000719_wp * cos(2.0_wp * year_angle) +             &
5968                          0.000077_wp * sin(2.0_wp * year_angle))
5969       
5970!--   
5971!--     Under a very low angle, we keep extraterestrial radiation at
5972!--     the last small value, therefore the clearness index will be pushed
5973!--     towards 0 while keeping full continuity.
5974!--   
5975        IF ( cos_zenith <= lowest_solarUp )  THEN
5976            corrected_solarUp = lowest_solarUp
5977        ELSE
5978            corrected_solarUp = cos_zenith
5979        ENDIF
5980       
5981        horizontalETR = etr * corrected_solarUp
5982       
5983        DO i = nxl, nxr
5984            DO j = nys, nyn
5985                clearnessIndex = rad_sw_in(0,j,i) / horizontalETR
5986                diff_frac = 1.0_wp / (1.0_wp + exp(-5.0033_wp + 8.6025_wp * clearnessIndex))
5987                rad_sw_in_diff(j,i) = rad_sw_in(0,j,i) * diff_frac
5988                rad_sw_in_dir(j,i)  = rad_sw_in(0,j,i) * (1.0_wp - diff_frac)
5989                rad_lw_in_diff(j,i) = rad_lw_in(0,j,i)
5990            ENDDO
5991        ENDDO
5992       
5993    END SUBROUTINE calc_diffusion_radiation
5994
5995 END SUBROUTINE radiation_interaction
5996   
5997!------------------------------------------------------------------------------!
5998! Description:
5999! ------------
6000!> This subroutine initializes structures needed for radiative transfer
6001!> model. This model calculates transformation processes of the
6002!> radiation inside urban and land canopy layer. The module includes also
6003!> the interaction of the radiation with the resolved plant canopy.
6004!>
6005!> For more info. see Resler et al. 2017
6006!>
6007!> The new version 2.0 was radically rewriten, the discretization scheme
6008!> has been changed. This new version significantly improves effectivity
6009!> of the paralelization and the scalability of the model.
6010!>
6011!------------------------------------------------------------------------------!
6012    SUBROUTINE radiation_interaction_init
6013
6014       USE control_parameters,                                                 &
6015           ONLY:  dz_stretch_level_start
6016           
6017       USE netcdf_data_input_mod,                                              &
6018           ONLY:  leaf_area_density_f
6019
6020       USE plant_canopy_model_mod,                                             &
6021           ONLY:  pch_index, lad_s
6022
6023       IMPLICIT NONE
6024
6025       INTEGER(iwp) :: i, j, k, l, m, d
6026       INTEGER(iwp) :: k_topo     !< vertical index indicating topography top for given (j,i)
6027       INTEGER(iwp) :: nzptl, nzubl, nzutl, isurf, ipcgb, imrt
6028       REAL(wp)     :: mrl
6029#if defined( __parallel )
6030       INTEGER(iwp), DIMENSION(:), POINTER, SAVE ::  gridsurf_rma   !< fortran pointer, but lower bounds are 1
6031       TYPE(c_ptr)                               ::  gridsurf_rma_p !< allocated c pointer
6032       INTEGER(iwp)                              ::  minfo          !< MPI RMA window info handle
6033#endif
6034
6035!
6036!--     precalculate face areas for different face directions using normal vector
6037        DO d = 0, nsurf_type
6038            facearea(d) = 1._wp
6039            IF ( idir(d) == 0 ) facearea(d) = facearea(d) * dx
6040            IF ( jdir(d) == 0 ) facearea(d) = facearea(d) * dy
6041            IF ( kdir(d) == 0 ) facearea(d) = facearea(d) * dz(1)
6042        ENDDO
6043!
6044!--    Find nz_urban_b, nz_urban_t, nz_urban via wall_flag_0 array (nzb_s_inner will be
6045!--    removed later). The following contruct finds the lowest / largest index
6046!--    for any upward-facing wall (see bit 12).
6047       nzubl = MINVAL( get_topography_top_index( 's' ) )
6048       nzutl = MAXVAL( get_topography_top_index( 's' ) )
6049
6050       nzubl = MAX( nzubl, nzb )
6051
6052       IF ( plant_canopy )  THEN
6053!--        allocate needed arrays
6054           ALLOCATE( pct(nys:nyn,nxl:nxr) )
6055           ALLOCATE( pch(nys:nyn,nxl:nxr) )
6056
6057!--        calculate plant canopy height
6058           npcbl = 0
6059           pct   = 0
6060           pch   = 0
6061           DO i = nxl, nxr
6062               DO j = nys, nyn
6063!
6064!--                Find topography top index
6065                   k_topo = get_topography_top_index_ji( j, i, 's' )
6066
6067                   DO k = nzt+1, 0, -1
6068                       IF ( lad_s(k,j,i) /= 0.0_wp )  THEN
6069!--                        we are at the top of the pcs
6070                           pct(j,i) = k + k_topo
6071                           pch(j,i) = k
6072                           npcbl = npcbl + pch(j,i)
6073                           EXIT
6074                       ENDIF
6075                   ENDDO
6076               ENDDO
6077           ENDDO
6078
6079           nzutl = MAX( nzutl, MAXVAL( pct ) )
6080           nzptl = MAXVAL( pct )
6081!--        code of plant canopy model uses parameter pch_index
6082!--        we need to setup it here to right value
6083!--        (pch_index, lad_s and other arrays in PCM are defined flat)
6084           pch_index = MERGE( leaf_area_density_f%nz - 1, MAXVAL( pch ),       &
6085                              leaf_area_density_f%from_file )
6086
6087           prototype_lad = MAXVAL( lad_s ) * .9_wp  !< better be *1.0 if lad is either 0 or maxval(lad) everywhere
6088           IF ( prototype_lad <= 0._wp ) prototype_lad = .3_wp
6089           !WRITE(message_string, '(a,f6.3)') 'Precomputing effective box optical ' &
6090           !    // 'depth using prototype leaf area density = ', prototype_lad
6091           !CALL message('radiation_interaction_init', 'PA0520', 0, 0, -1, 6, 0)
6092       ENDIF
6093
6094       nzutl = MIN( nzutl + nzut_free, nzt )
6095
6096#if defined( __parallel )
6097       CALL MPI_AllReduce(nzubl, nz_urban_b, 1, MPI_INTEGER, MPI_MIN, comm2d, ierr )
6098       IF ( ierr /= 0 ) THEN
6099           WRITE(9,*) 'Error MPI_AllReduce11:', ierr, nzubl, nz_urban_b
6100           FLUSH(9)
6101       ENDIF
6102       CALL MPI_AllReduce(nzutl, nz_urban_t, 1, MPI_INTEGER, MPI_MAX, comm2d, ierr )
6103       IF ( ierr /= 0 ) THEN
6104           WRITE(9,*) 'Error MPI_AllReduce12:', ierr, nzutl, nz_urban_t
6105           FLUSH(9)
6106       ENDIF
6107       CALL MPI_AllReduce(nzptl, nz_plant_t, 1, MPI_INTEGER, MPI_MAX, comm2d, ierr )
6108       IF ( ierr /= 0 ) THEN
6109           WRITE(9,*) 'Error MPI_AllReduce13:', ierr, nzptl, nz_plant_t
6110           FLUSH(9)
6111       ENDIF
6112#else
6113       nz_urban_b = nzubl
6114       nz_urban_t = nzutl
6115       nz_plant_t = nzptl
6116#endif
6117!
6118!--    Stretching (non-uniform grid spacing) is not considered in the radiation
6119!--    model. Therefore, vertical stretching has to be applied above the area
6120!--    where the parts of the radiation model which assume constant grid spacing
6121!--    are active. ABS (...) is required because the default value of
6122!--    dz_stretch_level_start is -9999999.9_wp (negative).
6123       IF ( ABS( dz_stretch_level_start(1) ) <= zw(nz_urban_t) ) THEN
6124          WRITE( message_string, * ) 'The lowest level where vertical ',       &
6125                                     'stretching is applied have to be ',      &
6126                                     'greater than ', zw(nz_urban_t)
6127          CALL message( 'radiation_interaction_init', 'PA0496', 1, 2, 0, 6, 0 )
6128       ENDIF 
6129!
6130!--    global number of urban and plant layers
6131       nz_urban = nz_urban_t - nz_urban_b + 1
6132       nz_plant = nz_plant_t - nz_urban_b + 1
6133!
6134!--    check max_raytracing_dist relative to urban surface layer height
6135       mrl = 2.0_wp * nz_urban * dz(1)
6136!--    set max_raytracing_dist to double the urban surface layer height, if not set
6137       IF ( max_raytracing_dist == -999.0_wp ) THEN
6138          max_raytracing_dist = mrl
6139       ENDIF
6140!--    check if max_raytracing_dist set too low (here we only warn the user. Other
6141!      option is to correct the value again to double the urban surface layer height)
6142       IF ( max_raytracing_dist  <  mrl ) THEN
6143          WRITE(message_string, '(a,f6.1)') 'Max_raytracing_dist is set less than ', &
6144               'double the urban surface layer height, i.e. ', mrl
6145          CALL message('radiation_interaction_init', 'PA0521', 0, 0, -1, 6, 0)
6146       ENDIF
6147!        IF ( max_raytracing_dist <= mrl ) THEN
6148!           IF ( max_raytracing_dist /= -999.0_wp ) THEN
6149! !--          max_raytracing_dist too low
6150!              WRITE(message_string, '(a,f6.1)') 'Max_raytracing_dist too low, ' &
6151!                    // 'override to value ', mrl
6152!              CALL message('radiation_interaction_init', 'PA0521', 0, 0, -1, 6, 0)
6153!           ENDIF
6154!           max_raytracing_dist = mrl
6155!        ENDIF
6156!
6157!--    allocate urban surfaces grid
6158!--    calc number of surfaces in local proc
6159       IF ( debug_output )  CALL debug_message( 'calculation of indices for surfaces', 'info' )
6160
6161       nsurfl = 0
6162!
6163!--    Number of horizontal surfaces including land- and roof surfaces in both USM and LSM. Note that
6164!--    All horizontal surface elements are already counted in surface_mod.
6165       startland = 1
6166       nsurfl    = surf_usm_h%ns + surf_lsm_h%ns
6167       endland   = nsurfl
6168       nlands    = endland - startland + 1
6169
6170!
6171!--    Number of vertical surfaces in both USM and LSM. Note that all vertical surface elements are
6172!--    already counted in surface_mod.
6173       startwall = nsurfl+1
6174       DO  i = 0,3
6175          nsurfl = nsurfl + surf_usm_v(i)%ns + surf_lsm_v(i)%ns
6176       ENDDO
6177       endwall = nsurfl
6178       nwalls  = endwall - startwall + 1
6179       dirstart = (/ startland, startwall, startwall, startwall, startwall /)
6180       dirend = (/ endland, endwall, endwall, endwall, endwall /)
6181
6182!--    fill gridpcbl and pcbl
6183       IF ( npcbl > 0 )  THEN
6184           ALLOCATE( pcbl(iz:ix, 1:npcbl) )
6185           ALLOCATE( gridpcbl(nz_urban_b:nz_plant_t,nys:nyn,nxl:nxr) )
6186           pcbl = -1
6187           gridpcbl(:,:,:) = 0
6188           ipcgb = 0
6189           DO i = nxl, nxr
6190               DO j = nys, nyn
6191!
6192!--                Find topography top index
6193                   k_topo = get_topography_top_index_ji( j, i, 's' )
6194
6195                   DO k = k_topo + 1, pct(j,i)
6196                       ipcgb = ipcgb + 1
6197                       gridpcbl(k,j,i) = ipcgb
6198                       pcbl(:,ipcgb) = (/ k, j, i /)
6199                   ENDDO
6200               ENDDO
6201           ENDDO
6202           ALLOCATE( pcbinsw( 1:npcbl ) )
6203           ALLOCATE( pcbinswdir( 1:npcbl ) )
6204           ALLOCATE( pcbinswdif( 1:npcbl ) )
6205           ALLOCATE( pcbinlw( 1:npcbl ) )
6206       ENDIF
6207
6208!
6209!--    Fill surfl (the ordering of local surfaces given by the following
6210!--    cycles must not be altered, certain file input routines may depend
6211!--    on it).
6212!
6213!--    We allocate the array as linear and then use a two-dimensional pointer
6214!--    into it, because some MPI implementations crash with 2D-allocated arrays.
6215       ALLOCATE(surfl_linear(nidx_surf*nsurfl))
6216       surfl(1:nidx_surf,1:nsurfl) => surfl_linear(1:nidx_surf*nsurfl)
6217       isurf = 0
6218       IF ( rad_angular_discretization )  THEN
6219!
6220!--       Allocate and fill the reverse indexing array gridsurf
6221#if defined( __parallel )
6222!
6223!--       raytrace_mpi_rma is asserted
6224
6225          CALL MPI_Info_create(minfo, ierr)
6226          IF ( ierr /= 0 ) THEN
6227              WRITE(9,*) 'Error MPI_Info_create1:', ierr
6228              FLUSH(9)
6229          ENDIF
6230          CALL MPI_Info_set(minfo, 'accumulate_ordering', '', ierr)
6231          IF ( ierr /= 0 ) THEN
6232              WRITE(9,*) 'Error MPI_Info_set1:', ierr
6233              FLUSH(9)
6234          ENDIF
6235          CALL MPI_Info_set(minfo, 'accumulate_ops', 'same_op', ierr)
6236          IF ( ierr /= 0 ) THEN
6237              WRITE(9,*) 'Error MPI_Info_set2:', ierr
6238              FLUSH(9)
6239          ENDIF
6240          CALL MPI_Info_set(minfo, 'same_size', 'true', ierr)
6241          IF ( ierr /= 0 ) THEN
6242              WRITE(9,*) 'Error MPI_Info_set3:', ierr
6243              FLUSH(9)
6244          ENDIF
6245          CALL MPI_Info_set(minfo, 'same_disp_unit', 'true', ierr)
6246          IF ( ierr /= 0 ) THEN
6247              WRITE(9,*) 'Error MPI_Info_set4:', ierr
6248              FLUSH(9)
6249          ENDIF
6250
6251          CALL MPI_Win_allocate(INT(STORAGE_SIZE(1_iwp)/8*nsurf_type_u*nz_urban*nny*nnx, &
6252                                    kind=MPI_ADDRESS_KIND), STORAGE_SIZE(1_iwp)/8,  &
6253                                minfo, comm2d, gridsurf_rma_p, win_gridsurf, ierr)
6254          IF ( ierr /= 0 ) THEN
6255              WRITE(9,*) 'Error MPI_Win_allocate1:', ierr, &
6256                 INT(STORAGE_SIZE(1_iwp)/8*nsurf_type_u*nz_urban*nny*nnx,kind=MPI_ADDRESS_KIND), &
6257                 STORAGE_SIZE(1_iwp)/8, win_gridsurf
6258              FLUSH(9)
6259          ENDIF
6260
6261          CALL MPI_Info_free(minfo, ierr)
6262          IF ( ierr /= 0 ) THEN
6263              WRITE(9,*) 'Error MPI_Info_free1:', ierr
6264              FLUSH(9)
6265          ENDIF
6266
6267!
6268!--       On Intel compilers, calling c_f_pointer to transform a C pointer
6269!--       directly to a multi-dimensional Fotran pointer leads to strange
6270!--       errors on dimension boundaries. However, transforming to a 1D
6271!--       pointer and then redirecting a multidimensional pointer to it works
6272!--       fine.
6273          CALL c_f_pointer(gridsurf_rma_p, gridsurf_rma, (/ nsurf_type_u*nz_urban*nny*nnx /))
6274          gridsurf(0:nsurf_type_u-1, nz_urban_b:nz_urban_t, nys:nyn, nxl:nxr) =>                &
6275                     gridsurf_rma(1:nsurf_type_u*nz_urban*nny*nnx)
6276#else
6277          ALLOCATE(gridsurf(0:nsurf_type_u-1,nz_urban_b:nz_urban_t,nys:nyn,nxl:nxr) )
6278#endif
6279          gridsurf(:,:,:,:) = -999
6280       ENDIF
6281
6282!--    add horizontal surface elements (land and urban surfaces)
6283!--    TODO: add urban overhanging surfaces (idown_u)
6284       DO i = nxl, nxr
6285           DO j = nys, nyn
6286              DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
6287                 k = surf_usm_h%k(m)
6288                 isurf = isurf + 1
6289                 surfl(:,isurf) = (/iup_u,k,j,i,m/)
6290                 IF ( rad_angular_discretization ) THEN
6291                    gridsurf(iup_u,k,j,i) = isurf
6292                 ENDIF
6293              ENDDO
6294
6295              DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6296                 k = surf_lsm_h%k(m)
6297                 isurf = isurf + 1
6298                 surfl(:,isurf) = (/iup_l,k,j,i,m/)
6299                 IF ( rad_angular_discretization ) THEN
6300                    gridsurf(iup_u,k,j,i) = isurf
6301                 ENDIF
6302              ENDDO
6303
6304           ENDDO
6305       ENDDO
6306
6307!--    add vertical surface elements (land and urban surfaces)
6308!--    TODO: remove the hard coding of l = 0 to l = idirection
6309       DO i = nxl, nxr
6310           DO j = nys, nyn
6311              l = 0
6312              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6313                 k = surf_usm_v(l)%k(m)
6314                 isurf = isurf + 1
6315                 surfl(:,isurf) = (/inorth_u,k,j,i,m/)
6316                 IF ( rad_angular_discretization ) THEN
6317                    gridsurf(inorth_u,k,j,i) = isurf
6318                 ENDIF
6319              ENDDO
6320              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6321                 k = surf_lsm_v(l)%k(m)
6322                 isurf = isurf + 1
6323                 surfl(:,isurf) = (/inorth_l,k,j,i,m/)
6324                 IF ( rad_angular_discretization ) THEN
6325                    gridsurf(inorth_u,k,j,i) = isurf
6326                 ENDIF
6327              ENDDO
6328
6329              l = 1
6330              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6331                 k = surf_usm_v(l)%k(m)
6332                 isurf = isurf + 1
6333                 surfl(:,isurf) = (/isouth_u,k,j,i,m/)
6334                 IF ( rad_angular_discretization ) THEN
6335                    gridsurf(isouth_u,k,j,i) = isurf
6336                 ENDIF
6337              ENDDO
6338              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6339                 k = surf_lsm_v(l)%k(m)
6340                 isurf = isurf + 1
6341                 surfl(:,isurf) = (/isouth_l,k,j,i,m/)
6342                 IF ( rad_angular_discretization ) THEN
6343                    gridsurf(isouth_u,k,j,i) = isurf
6344                 ENDIF
6345              ENDDO
6346
6347              l = 2
6348              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6349                 k = surf_usm_v(l)%k(m)
6350                 isurf = isurf + 1
6351                 surfl(:,isurf) = (/ieast_u,k,j,i,m/)
6352                 IF ( rad_angular_discretization ) THEN
6353                    gridsurf(ieast_u,k,j,i) = isurf
6354                 ENDIF
6355              ENDDO
6356              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6357                 k = surf_lsm_v(l)%k(m)
6358                 isurf = isurf + 1
6359                 surfl(:,isurf) = (/ieast_l,k,j,i,m/)
6360                 IF ( rad_angular_discretization ) THEN
6361                    gridsurf(ieast_u,k,j,i) = isurf
6362                 ENDIF
6363              ENDDO
6364
6365              l = 3
6366              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6367                 k = surf_usm_v(l)%k(m)
6368                 isurf = isurf + 1
6369                 surfl(:,isurf) = (/iwest_u,k,j,i,m/)
6370                 IF ( rad_angular_discretization ) THEN
6371                    gridsurf(iwest_u,k,j,i) = isurf
6372                 ENDIF
6373              ENDDO
6374              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6375                 k = surf_lsm_v(l)%k(m)
6376                 isurf = isurf + 1
6377                 surfl(:,isurf) = (/iwest_l,k,j,i,m/)
6378                 IF ( rad_angular_discretization ) THEN
6379                    gridsurf(iwest_u,k,j,i) = isurf
6380                 ENDIF
6381              ENDDO
6382           ENDDO
6383       ENDDO
6384!
6385!--    Add local MRT boxes for specified number of levels
6386       nmrtbl = 0
6387       IF ( mrt_nlevels > 0 )  THEN
6388          DO  i = nxl, nxr
6389             DO  j = nys, nyn
6390                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
6391!
6392!--                Skip roof if requested
6393                   IF ( mrt_skip_roof  .AND.  surf_usm_h%isroof_surf(m) )  CYCLE
6394!
6395!--                Cycle over specified no of levels
6396                   nmrtbl = nmrtbl + mrt_nlevels
6397                ENDDO
6398!
6399!--             Dtto for LSM
6400                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6401                   nmrtbl = nmrtbl + mrt_nlevels
6402                ENDDO
6403             ENDDO
6404          ENDDO
6405
6406          ALLOCATE( mrtbl(iz:ix,nmrtbl), mrtsky(nmrtbl), mrtskyt(nmrtbl), &
6407                    mrtinsw(nmrtbl), mrtinlw(nmrtbl), mrt(nmrtbl) )
6408
6409          imrt = 0
6410          DO  i = nxl, nxr
6411             DO  j = nys, nyn
6412                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
6413!
6414!--                Skip roof if requested
6415                   IF ( mrt_skip_roof  .AND.  surf_usm_h%isroof_surf(m) )  CYCLE
6416!
6417!--                Cycle over specified no of levels
6418                   l = surf_usm_h%k(m)
6419                   DO  k = l, l + mrt_nlevels - 1
6420                      imrt = imrt + 1
6421                      mrtbl(:,imrt) = (/k,j,i/)
6422                   ENDDO
6423                ENDDO
6424!
6425!--             Dtto for LSM
6426                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6427                   l = surf_lsm_h%k(m)
6428                   DO  k = l, l + mrt_nlevels - 1
6429                      imrt = imrt + 1
6430                      mrtbl(:,imrt) = (/k,j,i/)
6431                   ENDDO
6432                ENDDO
6433             ENDDO
6434          ENDDO
6435       ENDIF
6436
6437!
6438!--    broadband albedo of the land, roof and wall surface
6439!--    for domain border and sky set artifically to 1.0
6440!--    what allows us to calculate heat flux leaving over
6441!--    side and top borders of the domain
6442       ALLOCATE ( albedo_surf(nsurfl) )
6443       albedo_surf = 1.0_wp
6444!
6445!--    Also allocate further array for emissivity with identical order of
6446!--    surface elements as radiation arrays.
6447       ALLOCATE ( emiss_surf(nsurfl)  )
6448
6449
6450!
6451!--    global array surf of indices of surfaces and displacement index array surfstart
6452       ALLOCATE(nsurfs(0:numprocs-1))
6453
6454#if defined( __parallel )
6455       CALL MPI_Allgather(nsurfl,1,MPI_INTEGER,nsurfs,1,MPI_INTEGER,comm2d,ierr)
6456       IF ( ierr /= 0 ) THEN
6457         WRITE(9,*) 'Error MPI_AllGather1:', ierr, nsurfl, nsurfs
6458         FLUSH(9)
6459     ENDIF
6460
6461#else
6462       nsurfs(0) = nsurfl
6463#endif
6464       ALLOCATE(surfstart(0:numprocs))
6465       k = 0
6466       DO i=0,numprocs-1
6467           surfstart(i) = k
6468           k = k+nsurfs(i)
6469       ENDDO
6470       surfstart(numprocs) = k
6471       nsurf = k
6472!
6473!--    We allocate the array as linear and then use a two-dimensional pointer
6474!--    into it, because some MPI implementations crash with 2D-allocated arrays.
6475       ALLOCATE(surf_linear(nidx_surf*nsurf))
6476       surf(1:nidx_surf,1:nsurf) => surf_linear(1:nidx_surf*nsurf)
6477
6478#if defined( __parallel )
6479       CALL MPI_AllGatherv(surfl_linear, nsurfl*nidx_surf, MPI_INTEGER,    &
6480                           surf_linear, nsurfs*nidx_surf,                  &
6481                           surfstart(0:numprocs-1)*nidx_surf, MPI_INTEGER, &
6482                           comm2d, ierr)
6483       IF ( ierr /= 0 ) THEN
6484           WRITE(9,*) 'Error MPI_AllGatherv4:', ierr, SIZE(surfl_linear),    &
6485                      nsurfl*nidx_surf, SIZE(surf_linear), nsurfs*nidx_surf, &
6486                      surfstart(0:numprocs-1)*nidx_surf
6487           FLUSH(9)
6488       ENDIF
6489#else
6490       surf = surfl
6491#endif
6492
6493!--
6494!--    allocation of the arrays for direct and diffusion radiation
6495       IF ( debug_output )  CALL debug_message( 'allocation of radiation arrays', 'info' )
6496!--    rad_sw_in, rad_lw_in are computed in radiation model,
6497!--    splitting of direct and diffusion part is done
6498!--    in calc_diffusion_radiation for now
6499
6500       ALLOCATE( rad_sw_in_dir(nysg:nyng,nxlg:nxrg) )
6501       ALLOCATE( rad_sw_in_diff(nysg:nyng,nxlg:nxrg) )
6502       ALLOCATE( rad_lw_in_diff(nysg:nyng,nxlg:nxrg) )
6503       rad_sw_in_dir  = 0.0_wp
6504       rad_sw_in_diff = 0.0_wp
6505       rad_lw_in_diff = 0.0_wp
6506
6507!--    allocate radiation arrays
6508       ALLOCATE( surfins(nsurfl) )
6509       ALLOCATE( surfinl(nsurfl) )
6510       ALLOCATE( surfinsw(nsurfl) )
6511       ALLOCATE( surfinlw(nsurfl) )
6512       ALLOCATE( surfinswdir(nsurfl) )
6513       ALLOCATE( surfinswdif(nsurfl) )
6514       ALLOCATE( surfinlwdif(nsurfl) )
6515       ALLOCATE( surfoutsl(nsurfl) )
6516       ALLOCATE( surfoutll(nsurfl) )
6517       ALLOCATE( surfoutsw(nsurfl) )
6518       ALLOCATE( surfoutlw(nsurfl) )
6519       ALLOCATE( surfouts(nsurf) )
6520       ALLOCATE( surfoutl(nsurf) )
6521       ALLOCATE( surfinlg(nsurf) )
6522       ALLOCATE( skyvf(nsurfl) )
6523       ALLOCATE( skyvft(nsurfl) )
6524       ALLOCATE( surfemitlwl(nsurfl) )
6525
6526!
6527!--    In case of average_radiation, aggregated surface albedo and emissivity,
6528!--    also set initial value for t_rad_urb.
6529!--    For now set an arbitrary initial value.
6530       IF ( average_radiation )  THEN
6531          albedo_urb = 0.1_wp
6532          emissivity_urb = 0.9_wp
6533          t_rad_urb = pt_surface
6534       ENDIF
6535
6536    END SUBROUTINE radiation_interaction_init
6537
6538!------------------------------------------------------------------------------!
6539! Description:
6540! ------------
6541!> Calculates shape view factors (SVF), plant sink canopy factors (PCSF),
6542!> sky-view factors, discretized path for direct solar radiation, MRT factors
6543!> and other preprocessed data needed for radiation_interaction.
6544!------------------------------------------------------------------------------!
6545    SUBROUTINE radiation_calc_svf
6546   
6547        IMPLICIT NONE
6548       
6549        INTEGER(iwp)                                  :: i, j, k, d, ip, jp
6550        INTEGER(iwp)                                  :: isvf, ksvf, icsf, kcsf, npcsfl, isvf_surflt, imrt, imrtf, ipcgb
6551        INTEGER(iwp)                                  :: sd, td
6552        INTEGER(iwp)                                  :: iaz, izn      !< azimuth, zenith counters
6553        INTEGER(iwp)                                  :: naz, nzn      !< azimuth, zenith num of steps
6554        REAL(wp)                                      :: az0, zn0      !< starting azimuth/zenith
6555        REAL(wp)                                      :: azs, zns      !< azimuth/zenith cycle step
6556        REAL(wp)                                      :: az1, az2      !< relative azimuth of section borders
6557        REAL(wp)                                      :: azmid         !< ray (center) azimuth
6558        REAL(wp)                                      :: yxlen         !< |yxdir|
6559        REAL(wp), DIMENSION(2)                        :: yxdir         !< y,x *unit* vector of ray direction (in grid units)
6560        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zdirs         !< directions in z (tangent of elevation)
6561        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zcent         !< zenith angle centers
6562        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zbdry         !< zenith angle boundaries
6563        REAL(wp), DIMENSION(:), ALLOCATABLE           :: vffrac        !< view factor fractions for individual rays
6564        REAL(wp), DIMENSION(:), ALLOCATABLE           :: vffrac0       !< dtto (original values)
6565        REAL(wp), DIMENSION(:), ALLOCATABLE           :: ztransp       !< array of transparency in z steps
6566        INTEGER(iwp)                                  :: lowest_free_ray !< index into zdirs
6567        INTEGER(iwp), DIMENSION(:), ALLOCATABLE       :: itarget       !< face indices of detected obstacles
6568        INTEGER(iwp)                                  :: itarg0, itarg1
6569
6570        INTEGER(iwp)                                  :: udim
6571        INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET:: nzterrl_l
6572        INTEGER(iwp), DIMENSION(:,:), POINTER         :: nzterrl
6573        REAL(wp),     DIMENSION(:), ALLOCATABLE,TARGET:: csflt_l, pcsflt_l
6574        REAL(wp),     DIMENSION(:,:), POINTER         :: csflt, pcsflt
6575        INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET:: kcsflt_l,kpcsflt_l
6576        INTEGER(iwp), DIMENSION(:,:), POINTER         :: kcsflt,kpcsflt
6577        INTEGER(iwp), DIMENSION(:), ALLOCATABLE       :: icsflt,dcsflt,ipcsflt,dpcsflt
6578        REAL(wp), DIMENSION(3)                        :: uv
6579        LOGICAL                                       :: visible
6580        REAL(wp), DIMENSION(3)                        :: sa, ta          !< real coordinates z,y,x of source and target
6581        REAL(wp)                                      :: difvf           !< differential view factor
6582        REAL(wp)                                      :: transparency, rirrf, sqdist, svfsum
6583        INTEGER(iwp)                                  :: isurflt, isurfs, isurflt_prev
6584        INTEGER(idp)                                  :: ray_skip_maxdist, ray_skip_minval !< skipped raytracing counts
6585        INTEGER(iwp)                                  :: max_track_len !< maximum 2d track length
6586        INTEGER(iwp)                                  :: minfo
6587        REAL(wp), DIMENSION(:), POINTER, SAVE         :: lad_s_rma       !< fortran 1D pointer
6588        TYPE(c_ptr)                                   :: lad_s_rma_p     !< allocated c pointer
6589#if defined( __parallel )
6590        INTEGER(kind=MPI_ADDRESS_KIND)                :: size_lad_rma
6591#endif
6592!   
6593        INTEGER(iwp), DIMENSION(0:svfnorm_report_num) :: svfnorm_counts
6594
6595
6596!--     calculation of the SVF
6597        CALL location_message( 'calculating view factors for radiation interaction', 'start' )
6598
6599!--     initialize variables and temporary arrays for calculation of svf and csf
6600        nsvfl  = 0
6601        ncsfl  = 0
6602        nsvfla = gasize
6603        msvf   = 1
6604        ALLOCATE( asvf1(nsvfla) )
6605        asvf => asvf1
6606        IF ( plant_canopy )  THEN
6607            ncsfla = gasize
6608            mcsf   = 1
6609            ALLOCATE( acsf1(ncsfla) )
6610            acsf => acsf1
6611        ENDIF
6612        nmrtf = 0
6613        IF ( mrt_nlevels > 0 )  THEN
6614           nmrtfa = gasize
6615           mmrtf = 1
6616           ALLOCATE ( amrtf1(nmrtfa) )
6617           amrtf => amrtf1
6618        ENDIF
6619        ray_skip_maxdist = 0
6620        ray_skip_minval = 0
6621       
6622!--     initialize temporary terrain and plant canopy height arrays (global 2D array!)
6623        ALLOCATE( nzterr(0:(nx+1)*(ny+1)-1) )
6624#if defined( __parallel )
6625        !ALLOCATE( nzterrl(nys:nyn,nxl:nxr) )
6626        ALLOCATE( nzterrl_l((nyn-nys+1)*(nxr-nxl+1)) )
6627        nzterrl(nys:nyn,nxl:nxr) => nzterrl_l(1:(nyn-nys+1)*(nxr-nxl+1))
6628        nzterrl = get_topography_top_index( 's' )
6629        CALL MPI_AllGather( nzterrl_l, nnx*nny, MPI_INTEGER, &
6630                            nzterr, nnx*nny, MPI_INTEGER, comm2d, ierr )
6631        IF ( ierr /= 0 ) THEN
6632            WRITE(9,*) 'Error MPI_AllGather1:', ierr, SIZE(nzterrl_l), nnx*nny, &
6633                       SIZE(nzterr), nnx*nny
6634            FLUSH(9)
6635        ENDIF
6636        DEALLOCATE(nzterrl_l)
6637#else
6638        nzterr = RESHAPE( get_topography_top_index( 's' ), (/(nx+1)*(ny+1)/) )
6639#endif
6640        IF ( plant_canopy )  THEN
6641            ALLOCATE( plantt(0:(nx+1)*(ny+1)-1) )
6642            maxboxesg = nx + ny + nz_plant + 1
6643            max_track_len = nx + ny + 1
6644!--         temporary arrays storing values for csf calculation during raytracing
6645            ALLOCATE( boxes(3, maxboxesg) )
6646            ALLOCATE( crlens(maxboxesg) )
6647
6648#if defined( __parallel )
6649            CALL MPI_AllGather( pct, nnx*nny, MPI_INTEGER, &
6650                                plantt, nnx*nny, MPI_INTEGER, comm2d, ierr )
6651            IF ( ierr /= 0 ) THEN
6652                WRITE(9,*) 'Error MPI_AllGather2:', ierr, SIZE(pct), nnx*nny, &
6653                           SIZE(plantt), nnx*nny
6654                FLUSH(9)
6655            ENDIF
6656
6657!--         temporary arrays storing values for csf calculation during raytracing
6658            ALLOCATE( lad_ip(maxboxesg) )
6659            ALLOCATE( lad_disp(maxboxesg) )
6660
6661            IF ( raytrace_mpi_rma )  THEN
6662                ALLOCATE( lad_s_ray(maxboxesg) )
6663               
6664                ! set conditions for RMA communication
6665                CALL MPI_Info_create(minfo, ierr)
6666                IF ( ierr /= 0 ) THEN
6667                    WRITE(9,*) 'Error MPI_Info_create2:', ierr
6668                    FLUSH(9)
6669                ENDIF
6670                CALL MPI_Info_set(minfo, 'accumulate_ordering', '', ierr)
6671                IF ( ierr /= 0 ) THEN
6672                    WRITE(9,*) 'Error MPI_Info_set5:', ierr
6673                    FLUSH(9)
6674                ENDIF
6675                CALL MPI_Info_set(minfo, 'accumulate_ops', 'same_op', ierr)
6676                IF ( ierr /= 0 ) THEN
6677                    WRITE(9,*) 'Error MPI_Info_set6:', ierr
6678                    FLUSH(9)
6679                ENDIF
6680                CALL MPI_Info_set(minfo, 'same_size', 'true', ierr)
6681                IF ( ierr /= 0 ) THEN
6682                    WRITE(9,*) 'Error MPI_Info_set7:', ierr
6683                    FLUSH(9)
6684                ENDIF
6685                CALL MPI_Info_set(minfo, 'same_disp_unit', 'true', ierr)
6686                IF ( ierr /= 0 ) THEN
6687                    WRITE(9,*) 'Error MPI_Info_set8:', ierr
6688                    FLUSH(9)
6689                ENDIF
6690
6691!--             Allocate and initialize the MPI RMA window
6692!--             must be in accordance with allocation of lad_s in plant_canopy_model
6693!--             optimization of memory should be done
6694!--             Argument X of function STORAGE_SIZE(X) needs arbitrary REAL(wp) value, set to 1.0_wp for now
6695                size_lad_rma = STORAGE_SIZE(1.0_wp)/8*nnx*nny*nz_plant
6696                CALL MPI_Win_allocate(size_lad_rma, STORAGE_SIZE(1.0_wp)/8, minfo, comm2d, &
6697                                        lad_s_rma_p, win_lad, ierr)
6698                IF ( ierr /= 0 ) THEN
6699                    WRITE(9,*) 'Error MPI_Win_allocate2:', ierr, size_lad_rma, &
6700                                STORAGE_SIZE(1.0_wp)/8, win_lad
6701                    FLUSH(9)
6702                ENDIF
6703                CALL c_f_pointer(lad_s_rma_p, lad_s_rma, (/ nz_plant*nny*nnx /))
6704                sub_lad(nz_urban_b:nz_plant_t, nys:nyn, nxl:nxr) => lad_s_rma(1:nz_plant*nny*nnx)
6705            ELSE
6706                ALLOCATE(sub_lad(nz_urban_b:nz_plant_t, nys:nyn, nxl:nxr))
6707            ENDIF
6708#else
6709            plantt = RESHAPE( pct(nys:nyn,nxl:nxr), (/(nx+1)*(ny+1)/) )
6710            ALLOCATE(sub_lad(nz_urban_b:nz_plant_t, nys:nyn, nxl:nxr))
6711#endif
6712            plantt_max = MAXVAL(plantt)
6713            ALLOCATE( rt2_track(2, max_track_len), rt2_track_lad(nz_urban_b:plantt_max, max_track_len), &
6714                      rt2_track_dist(0:max_track_len), rt2_dist(plantt_max-nz_urban_b+2) )
6715
6716            sub_lad(:,:,:) = 0._wp
6717            DO i = nxl, nxr
6718                DO j = nys, nyn
6719                    k = get_topography_top_index_ji( j, i, 's' )
6720
6721                    sub_lad(k:nz_plant_t, j, i) = lad_s(0:nz_plant_t-k, j, i)
6722                ENDDO
6723            ENDDO
6724
6725#if defined( __parallel )
6726            IF ( raytrace_mpi_rma )  THEN
6727                CALL MPI_Info_free(minfo, ierr)
6728                IF ( ierr /= 0 ) THEN
6729                    WRITE(9,*) 'Error MPI_Info_free2:', ierr
6730                    FLUSH(9)
6731                ENDIF
6732                CALL MPI_Win_lock_all(0, win_lad, ierr)
6733                IF ( ierr /= 0 ) THEN
6734                    WRITE(9,*) 'Error MPI_Win_lock_all1:', ierr, win_lad
6735                    FLUSH(9)
6736                ENDIF
6737               
6738            ELSE
6739                ALLOCATE( sub_lad_g(0:(nx+1)*(ny+1)*nz_plant-1) )
6740                CALL MPI_AllGather( sub_lad, nnx*nny*nz_plant, MPI_REAL, &
6741                                    sub_lad_g, nnx*nny*nz_plant, MPI_REAL, comm2d, ierr )
6742                IF ( ierr /= 0 ) THEN
6743                    WRITE(9,*) 'Error MPI_AllGather3:', ierr, SIZE(sub_lad), &
6744                                nnx*nny*nz_plant, SIZE(sub_lad_g), nnx*nny*nz_plant
6745                    FLUSH(9)
6746                ENDIF
6747            ENDIF
6748#endif
6749        ENDIF
6750
6751!--     prepare the MPI_Win for collecting the surface indices
6752!--     from the reverse index arrays gridsurf from processors of target surfaces
6753#if defined( __parallel )
6754        IF ( rad_angular_discretization )  THEN
6755!
6756!--         raytrace_mpi_rma is asserted
6757            CALL MPI_Win_lock_all(0, win_gridsurf, ierr)
6758            IF ( ierr /= 0 ) THEN
6759                WRITE(9,*) 'Error MPI_Win_lock_all2:', ierr, win_gridsurf
6760                FLUSH(9)
6761            ENDIF
6762        ENDIF
6763#endif
6764
6765
6766        !--Directions opposite to face normals are not even calculated,
6767        !--they must be preset to 0
6768        !--
6769        dsitrans(:,:) = 0._wp
6770       
6771        DO isurflt = 1, nsurfl
6772!--         determine face centers
6773            td = surfl(id, isurflt)
6774            ta = (/ REAL(surfl(iz, isurflt), wp) - 0.5_wp * kdir(td),  &
6775                      REAL(surfl(iy, isurflt), wp) - 0.5_wp * jdir(td),  &
6776                      REAL(surfl(ix, isurflt), wp) - 0.5_wp * idir(td)  /)
6777
6778            !--Calculate sky view factor and raytrace DSI paths
6779            skyvf(isurflt) = 0._wp
6780            skyvft(isurflt) = 0._wp
6781
6782            !--Select a proper half-sphere for 2D raytracing
6783            SELECT CASE ( td )
6784               CASE ( iup_u, iup_l )
6785                  az0 = 0._wp
6786                  naz = raytrace_discrete_azims
6787                  azs = 2._wp * pi / REAL(naz, wp)
6788                  zn0 = 0._wp
6789                  nzn = raytrace_discrete_elevs / 2
6790                  zns = pi / 2._wp / REAL(nzn, wp)
6791               CASE ( isouth_u, isouth_l )
6792                  az0 = pi / 2._wp
6793                  naz = raytrace_discrete_azims / 2
6794                  azs = pi / REAL(naz, wp)
6795                  zn0 = 0._wp
6796                  nzn = raytrace_discrete_elevs
6797                  zns = pi / REAL(nzn, wp)
6798               CASE ( inorth_u, inorth_l )
6799                  az0 = - pi / 2._wp
6800                  naz = raytrace_discrete_azims / 2
6801                  azs = pi / REAL(naz, wp)
6802                  zn0 = 0._wp
6803                  nzn = raytrace_discrete_elevs
6804                  zns = pi / REAL(nzn, wp)
6805               CASE ( iwest_u, iwest_l )
6806                  az0 = pi
6807                  naz = raytrace_discrete_azims / 2
6808                  azs = pi / REAL(naz, wp)
6809                  zn0 = 0._wp
6810                  nzn = raytrace_discrete_elevs
6811                  zns = pi / REAL(nzn, wp)
6812               CASE ( ieast_u, ieast_l )
6813                  az0 = 0._wp
6814                  naz = raytrace_discrete_azims / 2
6815                  azs = pi / REAL(naz, wp)
6816                  zn0 = 0._wp
6817                  nzn = raytrace_discrete_elevs
6818                  zns = pi / REAL(nzn, wp)
6819               CASE DEFAULT
6820                  WRITE(message_string, *) 'ERROR: the surface type ', td,     &
6821                                           ' is not supported for calculating',&
6822                                           ' SVF'
6823                  CALL message( 'radiation_calc_svf', 'PA0488', 1, 2, 0, 6, 0 )
6824            END SELECT
6825
6826            ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), zbdry(0:nzn), vffrac(1:nzn*naz), &
6827                       ztransp(1:nzn*naz), itarget(1:nzn*naz) )   !FIXME allocate itarget only
6828                                                                  !in case of rad_angular_discretization
6829
6830            itarg0 = 1
6831            itarg1 = nzn
6832            zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
6833            zbdry(:) = (/( zn0+REAL(izn,wp)*zns, izn=0, nzn )/)
6834            IF ( td == iup_u  .OR.  td == iup_l )  THEN
6835               vffrac(1:nzn) = (COS(2 * zbdry(0:nzn-1)) - COS(2 * zbdry(1:nzn))) / 2._wp / REAL(naz, wp)
6836!
6837!--            For horizontal target, vf fractions are constant per azimuth
6838               DO iaz = 1, naz-1
6839                  vffrac(iaz*nzn+1:(iaz+1)*nzn) = vffrac(1:nzn)
6840               ENDDO
6841!--            sum of whole vffrac equals 1, verified
6842            ENDIF
6843!
6844!--         Calculate sky-view factor and direct solar visibility using 2D raytracing
6845            DO iaz = 1, naz
6846               azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
6847               IF ( td /= iup_u  .AND.  td /= iup_l )  THEN
6848                  az2 = REAL(iaz, wp) * azs - pi/2._wp
6849                  az1 = az2 - azs
6850                  !TODO precalculate after 1st line
6851                  vffrac(itarg0:itarg1) = (SIN(az2) - SIN(az1))               &
6852                              * (zbdry(1:nzn) - zbdry(0:nzn-1)                &
6853                                 + SIN(zbdry(0:nzn-1))*COS(zbdry(0:nzn-1))    &
6854                                 - SIN(zbdry(1:nzn))*COS(zbdry(1:nzn)))       &
6855                              / (2._wp * pi)
6856!--               sum of whole vffrac equals 1, verified
6857               ENDIF
6858               yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
6859               yxlen = SQRT(SUM(yxdir(:)**2))
6860               zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
6861               yxdir(:) = yxdir(:) / yxlen
6862
6863               CALL raytrace_2d(ta, yxdir, nzn, zdirs,                        &
6864                                    surfstart(myid) + isurflt, facearea(td),  &
6865                                    vffrac(itarg0:itarg1), .TRUE., .TRUE.,    &
6866                                    .FALSE., lowest_free_ray,                 &
6867                                    ztransp(itarg0:itarg1),                   &
6868                                    itarget(itarg0:itarg1))
6869
6870               skyvf(isurflt) = skyvf(isurflt) + &
6871                                SUM(vffrac(itarg0:itarg0+lowest_free_ray-1))
6872               skyvft(isurflt) = skyvft(isurflt) + &
6873                                 SUM(ztransp(itarg0:itarg0+lowest_free_ray-1) &
6874                                             * vffrac(itarg0:itarg0+lowest_free_ray-1))
6875 
6876!--            Save direct solar transparency
6877               j = MODULO(NINT(azmid/                                          &
6878                               (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
6879                          raytrace_discrete_azims)
6880
6881               DO k = 1, raytrace_discrete_elevs/2
6882                  i = dsidir_rev(k-1, j)
6883                  IF ( i /= -1  .AND.  k <= lowest_free_ray )  &
6884                     dsitrans(isurflt, i) = ztransp(itarg0+k-1)
6885               ENDDO
6886
6887!
6888!--            Advance itarget indices
6889               itarg0 = itarg1 + 1
6890               itarg1 = itarg1 + nzn
6891            ENDDO
6892
6893            IF ( rad_angular_discretization )  THEN
6894!--            sort itarget by face id
6895               CALL quicksort_itarget(itarget,vffrac,ztransp,1,nzn*naz)
6896!
6897!--            For aggregation, we need fractions multiplied by transmissivities
6898               ztransp(:) = vffrac(:) * ztransp(:)
6899!
6900!--            find the first valid position
6901               itarg0 = 1
6902               DO WHILE ( itarg0 <= nzn*naz )
6903                  IF ( itarget(itarg0) /= -1 )  EXIT
6904                  itarg0 = itarg0 + 1
6905               ENDDO
6906
6907               DO  i = itarg0, nzn*naz
6908!
6909!--               For duplicate values, only sum up vf fraction value
6910                  IF ( i < nzn*naz )  THEN
6911                     IF ( itarget(i+1) == itarget(i) )  THEN
6912                        vffrac(i+1) = vffrac(i+1) + vffrac(i)
6913                        ztransp(i+1) = ztransp(i+1) + ztransp(i)
6914                        CYCLE
6915                     ENDIF
6916                  ENDIF
6917!
6918!--               write to the svf array
6919                  nsvfl = nsvfl + 1
6920!--               check dimmension of asvf array and enlarge it if needed
6921                  IF ( nsvfla < nsvfl )  THEN
6922                     k = CEILING(REAL(nsvfla, kind=wp) * grow_factor)
6923                     IF ( msvf == 0 )  THEN
6924                        msvf = 1
6925                        ALLOCATE( asvf1(k) )
6926                        asvf => asvf1
6927                        asvf1(1:nsvfla) = asvf2
6928                        DEALLOCATE( asvf2 )
6929                     ELSE
6930                        msvf = 0
6931                        ALLOCATE( asvf2(k) )
6932                        asvf => asvf2
6933                        asvf2(1:nsvfla) = asvf1
6934                        DEALLOCATE( asvf1 )
6935                     ENDIF
6936
6937                     IF ( debug_output )  THEN
6938                        WRITE( debug_string, '(A,3I12)' ) 'Grow asvf:', nsvfl, nsvfla, k
6939                        CALL debug_message( debug_string, 'info' )
6940                     ENDIF
6941                     
6942                     nsvfla = k
6943                  ENDIF
6944!--               write svf values into the array
6945                  asvf(nsvfl)%isurflt = isurflt
6946                  asvf(nsvfl)%isurfs = itarget(i)
6947                  asvf(nsvfl)%rsvf = vffrac(i)
6948                  asvf(nsvfl)%rtransp = ztransp(i) / vffrac(i)
6949               END DO
6950
6951            ENDIF ! rad_angular_discretization
6952
6953            DEALLOCATE ( zdirs, zcent, zbdry, vffrac, ztransp, itarget ) !FIXME itarget shall be allocated only
6954                                                                  !in case of rad_angular_discretization
6955!
6956!--         Following calculations only required for surface_reflections
6957            IF ( surface_reflections  .AND.  .NOT. rad_angular_discretization )  THEN
6958
6959               DO  isurfs = 1, nsurf
6960                  IF ( .NOT.  surface_facing(surfl(ix, isurflt), surfl(iy, isurflt), &
6961                     surfl(iz, isurflt), surfl(id, isurflt), &
6962                     surf(ix, isurfs), surf(iy, isurfs), &
6963                     surf(iz, isurfs), surf(id, isurfs)) )  THEN
6964                     CYCLE
6965                  ENDIF
6966                 
6967                  sd = surf(id, isurfs)
6968                  sa = (/ REAL(surf(iz, isurfs), wp) - 0.5_wp * kdir(sd),  &
6969                          REAL(surf(iy, isurfs), wp) - 0.5_wp * jdir(sd),  &
6970                          REAL(surf(ix, isurfs), wp) - 0.5_wp * idir(sd)  /)
6971
6972!--               unit vector source -> target
6973                  uv = (/ (ta(1)-sa(1))*dz(1), (ta(2)-sa(2))*dy, (ta(3)-sa(3))*dx /)
6974                  sqdist = SUM(uv(:)**2)
6975                  uv = uv / SQRT(sqdist)
6976
6977!--               reject raytracing above max distance
6978                  IF ( SQRT(sqdist) > max_raytracing_dist ) THEN
6979                     ray_skip_maxdist = ray_skip_maxdist + 1
6980                     CYCLE
6981                  ENDIF
6982                 
6983                  difvf = dot_product((/ kdir(sd), jdir(sd), idir(sd) /), uv) & ! cosine of source normal and direction
6984                      * dot_product((/ kdir(td), jdir(td), idir(td) /), -uv) &  ! cosine of target normal and reverse direction
6985                      / (pi * sqdist) ! square of distance between centers
6986!
6987!--               irradiance factor (our unshaded shape view factor) = view factor per differential target area * source area
6988                  rirrf = difvf * facearea(sd)
6989
6990!--               reject raytracing for potentially too small view factor values
6991                  IF ( rirrf < min_irrf_value ) THEN
6992                      ray_skip_minval = ray_skip_minval + 1
6993                      CYCLE
6994                  ENDIF
6995
6996!--               raytrace + process plant canopy sinks within
6997                  CALL raytrace(sa, ta, isurfs, difvf, facearea(td), .TRUE., &
6998                                visible, transparency)
6999
7000                  IF ( .NOT.  visible ) CYCLE
7001                 ! rsvf = rirrf * transparency
7002
7003!--               write to the svf array
7004                  nsvfl = nsvfl + 1
7005!--               check dimmension of asvf array and enlarge it if needed
7006                  IF ( nsvfla < nsvfl )  THEN
7007                     k = CEILING(REAL(nsvfla, kind=wp) * grow_factor)
7008                     IF ( msvf == 0 )  THEN
7009                        msvf = 1
7010                        ALLOCATE( asvf1(k) )
7011                        asvf => asvf1
7012                        asvf1(1:nsvfla) = asvf2
7013                        DEALLOCATE( asvf2 )
7014                     ELSE
7015                        msvf = 0
7016                        ALLOCATE( asvf2(k) )
7017                        asvf => asvf2
7018                        asvf2(1:nsvfla) = asvf1
7019                        DEALLOCATE( asvf1 )
7020                     ENDIF
7021
7022                     IF ( debug_output )  THEN
7023                        WRITE( debug_string, '(A,3I12)' ) 'Grow asvf:', nsvfl, nsvfla, k
7024                        CALL debug_message( debug_string, 'info' )
7025                     ENDIF
7026                     
7027                     nsvfla = k
7028                  ENDIF
7029!--               write svf values into the array
7030                  asvf(nsvfl)%isurflt = isurflt
7031                  asvf(nsvfl)%isurfs = isurfs
7032                  asvf(nsvfl)%rsvf = rirrf !we postopne multiplication by transparency
7033                  asvf(nsvfl)%rtransp = transparency !a.k.a. Direct Irradiance Factor
7034               ENDDO
7035            ENDIF
7036        ENDDO
7037
7038!--
7039!--     Raytrace to canopy boxes to fill dsitransc TODO optimize
7040        dsitransc(:,:) = 0._wp
7041        az0 = 0._wp
7042        naz = raytrace_discrete_azims
7043        azs = 2._wp * pi / REAL(naz, wp)
7044        zn0 = 0._wp
7045        nzn = raytrace_discrete_elevs / 2
7046        zns = pi / 2._wp / REAL(nzn, wp)
7047        ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), vffrac(1:nzn), ztransp(1:nzn), &
7048               itarget(1:nzn) )
7049        zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
7050        vffrac(:) = 0._wp
7051
7052        DO  ipcgb = 1, npcbl
7053           ta = (/ REAL(pcbl(iz, ipcgb), wp),  &
7054                   REAL(pcbl(iy, ipcgb), wp),  &
7055                   REAL(pcbl(ix, ipcgb), wp) /)
7056!--        Calculate direct solar visibility using 2D raytracing
7057           DO  iaz = 1, naz
7058              azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
7059              yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
7060              yxlen = SQRT(SUM(yxdir(:)**2))
7061              zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
7062              yxdir(:) = yxdir(:) / yxlen
7063              CALL raytrace_2d(ta, yxdir, nzn, zdirs,                                &
7064                                   -999, -999._wp, vffrac, .FALSE., .FALSE., .TRUE., &
7065                                   lowest_free_ray, ztransp, itarget)
7066
7067!--           Save direct solar transparency
7068              j = MODULO(NINT(azmid/                                         &
7069                             (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
7070                         raytrace_discrete_azims)
7071              DO  k = 1, raytrace_discrete_elevs/2
7072                 i = dsidir_rev(k-1, j)
7073                 IF ( i /= -1  .AND.  k <= lowest_free_ray ) &
7074                    dsitransc(ipcgb, i) = ztransp(k)
7075              ENDDO
7076           ENDDO
7077        ENDDO
7078        DEALLOCATE ( zdirs, zcent, vffrac, ztransp, itarget )
7079!--
7080!--     Raytrace to MRT boxes
7081        IF ( nmrtbl > 0 )  THEN
7082           mrtdsit(:,:) = 0._wp
7083           mrtsky(:) = 0._wp
7084           mrtskyt(:) = 0._wp
7085           az0 = 0._wp
7086           naz = raytrace_discrete_azims
7087           azs = 2._wp * pi / REAL(naz, wp)
7088           zn0 = 0._wp
7089           nzn = raytrace_discrete_elevs
7090           zns = pi / REAL(nzn, wp)
7091           ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), zbdry(0:nzn), vffrac(1:nzn*naz), vffrac0(1:nzn), &
7092                      ztransp(1:nzn*naz), itarget(1:nzn*naz) )   !FIXME allocate itarget only
7093                                                                 !in case of rad_angular_discretization
7094
7095           zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
7096           zbdry(:) = (/( zn0+REAL(izn,wp)*zns, izn=0, nzn )/)
7097           vffrac0(:) = (COS(zbdry(0:nzn-1)) - COS(zbdry(1:nzn))) / 2._wp / REAL(naz, wp)
7098           !
7099           !--Modify direction weights to simulate human body (lower weight for top-down)
7100           IF ( mrt_geom_human )  THEN
7101              vffrac0(:) = vffrac0(:) * MAX(0._wp, SIN(zcent(:))*0.88_wp + COS(zcent(:))*0.12_wp)
7102              vffrac0(:) = vffrac0(:) / (SUM(vffrac0) * REAL(naz, wp))
7103           ENDIF
7104
7105           DO  imrt = 1, nmrtbl
7106              ta = (/ REAL(mrtbl(iz, imrt), wp),  &
7107                      REAL(mrtbl(iy, imrt), wp),  &
7108                      REAL(mrtbl(ix, imrt), wp) /)
7109!
7110!--           vf fractions are constant per azimuth
7111              DO iaz = 0, naz-1
7112                 vffrac(iaz*nzn+1:(iaz+1)*nzn) = vffrac0(:)
7113              ENDDO
7114!--           sum of whole vffrac equals 1, verified
7115              itarg0 = 1
7116              itarg1 = nzn
7117!
7118!--           Calculate sky-view factor and direct solar visibility using 2D raytracing
7119              DO  iaz = 1, naz
7120                 azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
7121                 yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
7122                 yxlen = SQRT(SUM(yxdir(:)**2))
7123                 zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
7124                 yxdir(:) = yxdir(:) / yxlen
7125
7126                 CALL raytrace_2d(ta, yxdir, nzn, zdirs,                         &
7127                                  -999, -999._wp, vffrac(itarg0:itarg1), .TRUE., &
7128                                  .FALSE., .TRUE., lowest_free_ray,              &
7129                                  ztransp(itarg0:itarg1),                        &
7130                                  itarget(itarg0:itarg1))
7131
7132!--              Sky view factors for MRT
7133                 mrtsky(imrt) = mrtsky(imrt) + &
7134                                  SUM(vffrac(itarg0:itarg0+lowest_free_ray-1))
7135                 mrtskyt(imrt) = mrtskyt(imrt) + &
7136                                   SUM(ztransp(itarg0:itarg0+lowest_free_ray-1) &
7137                                               * vffrac(itarg0:itarg0+lowest_free_ray-1))
7138!--              Direct solar transparency for MRT
7139                 j = MODULO(NINT(azmid/                                         &
7140                                (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
7141                            raytrace_discrete_azims)
7142                 DO  k = 1, raytrace_discrete_elevs/2
7143                    i = dsidir_rev(k-1, j)
7144                    IF ( i /= -1  .AND.  k <= lowest_free_ray ) &
7145                       mrtdsit(imrt, i) = ztransp(itarg0+k-1)
7146                 ENDDO
7147!
7148!--              Advance itarget indices
7149                 itarg0 = itarg1 + 1
7150                 itarg1 = itarg1 + nzn
7151              ENDDO
7152
7153!--           sort itarget by face id
7154              CALL quicksort_itarget(itarget,vffrac,ztransp,1,nzn*naz)
7155!
7156!--           find the first valid position
7157              itarg0 = 1
7158              DO WHILE ( itarg0 <= nzn*naz )
7159                 IF ( itarget(itarg0) /= -1 )  EXIT
7160                 itarg0 = itarg0 + 1
7161              ENDDO
7162
7163              DO  i = itarg0, nzn*naz
7164!
7165!--              For duplicate values, only sum up vf fraction value
7166                 IF ( i < nzn*naz )  THEN
7167                    IF ( itarget(i+1) == itarget(i) )  THEN
7168                       vffrac(i+1) = vffrac(i+1) + vffrac(i)
7169                       CYCLE
7170                    ENDIF
7171                 ENDIF
7172!
7173!--              write to the mrtf array
7174                 nmrtf = nmrtf + 1
7175!--              check dimmension of mrtf array and enlarge it if needed
7176                 IF ( nmrtfa < nmrtf )  THEN
7177                    k = CEILING(REAL(nmrtfa, kind=wp) * grow_factor)
7178                    IF ( mmrtf == 0 )  THEN
7179                       mmrtf = 1
7180                       ALLOCATE( amrtf1(k) )
7181                       amrtf => amrtf1
7182                       amrtf1(1:nmrtfa) = amrtf2
7183                       DEALLOCATE( amrtf2 )
7184                    ELSE
7185                       mmrtf = 0
7186                       ALLOCATE( amrtf2(k) )
7187                       amrtf => amrtf2
7188                       amrtf2(1:nmrtfa) = amrtf1
7189                       DEALLOCATE( amrtf1 )
7190                    ENDIF
7191
7192                    IF ( debug_output )  THEN
7193                       WRITE( debug_string, '(A,3I12)' ) 'Grow amrtf:', nmrtf, nmrtfa, k
7194                       CALL debug_message( debug_string, 'info' )
7195                    ENDIF
7196
7197                    nmrtfa = k
7198                 ENDIF
7199!--              write mrtf values into the array
7200                 amrtf(nmrtf)%isurflt = imrt
7201                 amrtf(nmrtf)%isurfs = itarget(i)
7202                 amrtf(nmrtf)%rsvf = vffrac(i)
7203                 amrtf(nmrtf)%rtransp = ztransp(i)
7204              ENDDO ! itarg
7205
7206           ENDDO ! imrt
7207           DEALLOCATE ( zdirs, zcent, zbdry, vffrac, vffrac0, ztransp, itarget )
7208!
7209!--        Move MRT factors to final arrays
7210           ALLOCATE ( mrtf(nmrtf), mrtft(nmrtf), mrtfsurf(2,nmrtf) )
7211           DO  imrtf = 1, nmrtf
7212              mrtf(imrtf) = amrtf(imrtf)%rsvf
7213              mrtft(imrtf) = amrtf(imrtf)%rsvf * amrtf(imrtf)%rtransp
7214              mrtfsurf(:,imrtf) = (/amrtf(imrtf)%isurflt, amrtf(imrtf)%isurfs /)
7215           ENDDO
7216           IF ( ALLOCATED(amrtf1) )  DEALLOCATE( amrtf1 )
7217           IF ( ALLOCATED(amrtf2) )  DEALLOCATE( amrtf2 )
7218        ENDIF ! nmrtbl > 0
7219
7220        IF ( rad_angular_discretization )  THEN
7221#if defined( __parallel )
7222!--        finalize MPI_RMA communication established to get global index of the surface from grid indices
7223!--        flush all MPI window pending requests
7224           CALL MPI_Win_flush_all(win_gridsurf, ierr)
7225           IF ( ierr /= 0 ) THEN
7226               WRITE(9,*) 'Error MPI_Win_flush_all1:', ierr, win_gridsurf
7227               FLUSH(9)
7228           ENDIF
7229!--        unlock MPI window
7230           CALL MPI_Win_unlock_all(win_gridsurf, ierr)
7231           IF ( ierr /= 0 ) THEN
7232               WRITE(9,*) 'Error MPI_Win_unlock_all1:', ierr, win_gridsurf
7233               FLUSH(9)
7234           ENDIF
7235!--        free MPI window
7236           CALL MPI_Win_free(win_gridsurf, ierr)
7237           IF ( ierr /= 0 ) THEN
7238               WRITE(9,*) 'Error MPI_Win_free1:', ierr, win_gridsurf
7239               FLUSH(9)
7240           ENDIF
7241#else
7242           DEALLOCATE ( gridsurf )
7243#endif
7244        ENDIF
7245
7246        IF ( debug_output )  CALL debug_message( 'waiting for completion of SVF and CSF calculation in all processes', 'info' )
7247
7248!--     deallocate temporary global arrays
7249        DEALLOCATE(nzterr)
7250       
7251        IF ( plant_canopy )  THEN
7252!--         finalize mpi_rma communication and deallocate temporary arrays
7253#if defined( __parallel )
7254            IF ( raytrace_mpi_rma )  THEN
7255                CALL MPI_Win_flush_all(win_lad, ierr)
7256                IF ( ierr /= 0 ) THEN
7257                    WRITE(9,*) 'Error MPI_Win_flush_all2:', ierr, win_lad
7258                    FLUSH(9)
7259                ENDIF
7260!--             unlock MPI window
7261                CALL MPI_Win_unlock_all(win_lad, ierr)
7262                IF ( ierr /= 0 ) THEN
7263                    WRITE(9,*) 'Error MPI_Win_unlock_all2:', ierr, win_lad
7264                    FLUSH(9)
7265                ENDIF
7266!--             free MPI window
7267                CALL MPI_Win_free(win_lad, ierr)
7268                IF ( ierr /= 0 ) THEN
7269                    WRITE(9,*) 'Error MPI_Win_free2:', ierr, win_lad
7270                    FLUSH(9)
7271                ENDIF
7272!--             deallocate temporary arrays storing values for csf calculation during raytracing
7273                DEALLOCATE( lad_s_ray )
7274!--             sub_lad is the pointer to lad_s_rma in case of raytrace_mpi_rma
7275!--             and must not be deallocated here
7276            ELSE
7277                DEALLOCATE(sub_lad)
7278                DEALLOCATE(sub_lad_g)
7279            ENDIF
7280#else
7281            DEALLOCATE(sub_lad)
7282#endif
7283            DEALLOCATE( boxes )
7284            DEALLOCATE( crlens )
7285            DEALLOCATE( plantt )
7286            DEALLOCATE( rt2_track, rt2_track_lad, rt2_track_dist, rt2_dist )
7287        ENDIF
7288
7289        IF ( debug_output )  CALL debug_message( 'calculation of the complete SVF array', 'info' )
7290
7291        IF ( rad_angular_discretization )  THEN
7292           IF ( debug_output )  CALL debug_message( 'Load svf from the structure array to plain arrays', 'info' )
7293           ALLOCATE( svf(ndsvf,nsvfl) )
7294           ALLOCATE( svfsurf(idsvf,nsvfl) )
7295
7296           DO isvf = 1, nsvfl
7297               svf(:, isvf) = (/ asvf(isvf)%rsvf, asvf(isvf)%rtransp /)
7298               svfsurf(:, isvf) = (/ asvf(isvf)%isurflt, asvf(isvf)%isurfs /)
7299           ENDDO
7300        ELSE
7301           IF ( debug_output )  CALL debug_message( 'Start SVF sort', 'info' )
7302!--        sort svf ( a version of quicksort )
7303           CALL quicksort_svf(asvf,1,nsvfl)
7304
7305           !< load svf from the structure array to plain arrays
7306           IF ( debug_output )  CALL debug_message( 'Load svf from the structure array to plain arrays', 'info' )
7307           ALLOCATE( svf(ndsvf,nsvfl) )
7308           ALLOCATE( svfsurf(idsvf,nsvfl) )
7309           svfnorm_counts(:) = 0._wp
7310           isurflt_prev = -1
7311           ksvf = 1
7312           svfsum = 0._wp
7313           DO isvf = 1, nsvfl
7314!--            normalize svf per target face
7315               IF ( asvf(ksvf)%isurflt /= isurflt_prev )  THEN
7316                   IF ( isurflt_prev /= -1  .AND.  svfsum /= 0._wp )  THEN
7317                       !< update histogram of logged svf normalization values
7318                       i = searchsorted(svfnorm_report_thresh, svfsum / (1._wp-skyvf(isurflt_prev)))
7319                       svfnorm_counts(i) = svfnorm_counts(i) + 1
7320
7321                       svf(1, isvf_surflt:isvf-1) = svf(1, isvf_surflt:isvf-1) / svfsum * (1._wp-skyvf(isurflt_prev))
7322                   ENDIF
7323                   isurflt_prev = asvf(ksvf)%isurflt
7324                   isvf_surflt = isvf
7325                   svfsum = asvf(ksvf)%rsvf !?? / asvf(ksvf)%rtransp
7326               ELSE
7327                   svfsum = svfsum + asvf(ksvf)%rsvf !?? / asvf(ksvf)%rtransp
7328               ENDIF
7329
7330               svf(:, isvf) = (/ asvf(ksvf)%rsvf, asvf(ksvf)%rtransp /)
7331               svfsurf(:, isvf) = (/ asvf(ksvf)%isurflt, asvf(ksvf)%isurfs /)
7332
7333!--            next element
7334               ksvf = ksvf + 1
7335           ENDDO
7336
7337           IF ( isurflt_prev /= -1  .AND.  svfsum /= 0._wp )  THEN
7338               i = searchsorted(svfnorm_report_thresh, svfsum / (1._wp-skyvf(isurflt_prev)))
7339               svfnorm_counts(i) = svfnorm_counts(i) + 1
7340
7341               svf(1, isvf_surflt:nsvfl) = svf(1, isvf_surflt:nsvfl) / svfsum * (1._wp-skyvf(isurflt_prev))
7342           ENDIF
7343           WRITE(9, *) 'SVF normalization histogram:', svfnorm_counts,  &
7344                       'on thresholds:', svfnorm_report_thresh(1:svfnorm_report_num), '(val < thresh <= val)'
7345           !TODO we should be able to deallocate skyvf, from now on we only need skyvft
7346        ENDIF ! rad_angular_discretization
7347
7348!--     deallocate temporary asvf array
7349!--     DEALLOCATE(asvf) - ifort has a problem with deallocation of allocatable target
7350!--     via pointing pointer - we need to test original targets
7351        IF ( ALLOCATED(asvf1) )  THEN
7352            DEALLOCATE(asvf1)
7353        ENDIF
7354        IF ( ALLOCATED(asvf2) )  THEN
7355            DEALLOCATE(asvf2)
7356        ENDIF
7357
7358        npcsfl = 0
7359        IF ( plant_canopy )  THEN
7360
7361            IF ( debug_output )  CALL debug_message( 'Calculation of the complete CSF array', 'info' )
7362!--         sort and merge csf for the last time, keeping the array size to minimum
7363            CALL merge_and_grow_csf(-1)
7364           
7365!--         aggregate csb among processors
7366!--         allocate necessary arrays
7367            udim = max(ncsfl,1)
7368            ALLOCATE( csflt_l(ndcsf*udim) )
7369            csflt(1:ndcsf,1:udim) => csflt_l(1:ndcsf*udim)
7370            ALLOCATE( kcsflt_l(kdcsf*udim) )
7371            kcsflt(1:kdcsf,1:udim) => kcsflt_l(1:kdcsf*udim)
7372            ALLOCATE( icsflt(0:numprocs-1) )
7373            ALLOCATE( dcsflt(0:numprocs-1) )
7374            ALLOCATE( ipcsflt(0:numprocs-1) )
7375            ALLOCATE( dpcsflt(0:numprocs-1) )
7376           
7377!--         fill out arrays of csf values and
7378!--         arrays of number of elements and displacements
7379!--         for particular precessors
7380            icsflt = 0
7381            dcsflt = 0
7382            ip = -1
7383            j = -1
7384            d = 0
7385            DO kcsf = 1, ncsfl
7386                j = j+1
7387                IF ( acsf(kcsf)%ip /= ip )  THEN
7388!--                 new block of the processor
7389!--                 number of elements of previous block
7390                    IF ( ip>=0) icsflt(ip) = j
7391                    d = d+j
7392!--                 blank blocks
7393                    DO jp = ip+1, acsf(kcsf)%ip-1
7394!--                     number of elements is zero, displacement is equal to previous
7395                        icsflt(jp) = 0
7396                        dcsflt(jp) = d
7397                    ENDDO
7398!--                 the actual block
7399                    ip = acsf(kcsf)%ip
7400                    dcsflt(ip) = d
7401                    j = 0
7402                ENDIF
7403                csflt(1,kcsf) = acsf(kcsf)%rcvf
7404!--             fill out integer values of itz,ity,itx,isurfs
7405                kcsflt(1,kcsf) = acsf(kcsf)%itz
7406                kcsflt(2,kcsf) = acsf(kcsf)%ity
7407                kcsflt(3,kcsf) = acsf(kcsf)%itx
7408                kcsflt(4,kcsf) = acsf(kcsf)%isurfs
7409            ENDDO
7410!--         last blank blocks at the end of array
7411            j = j+1
7412            IF ( ip>=0 ) icsflt(ip) = j
7413            d = d+j
7414            DO jp = ip+1, numprocs-1
7415!--             number of elements is zero, displacement is equal to previous
7416                icsflt(jp) = 0
7417                dcsflt(jp) = d
7418            ENDDO
7419           
7420!--         deallocate temporary acsf array
7421!--         DEALLOCATE(acsf) - ifort has a problem with deallocation of allocatable target
7422!--         via pointing pointer - we need to test original targets
7423            IF ( ALLOCATED(acsf1) )  THEN
7424                DEALLOCATE(acsf1)
7425            ENDIF
7426            IF ( ALLOCATED(acsf2) )  THEN
7427                DEALLOCATE(acsf2)
7428            ENDIF
7429                   
7430#if defined( __parallel )
7431!--         scatter and gather the number of elements to and from all processor
7432!--         and calculate displacements
7433            IF ( debug_output )  CALL debug_message( 'Scatter and gather the number of elements to and from all processor', 'info' )
7434
7435            CALL MPI_AlltoAll(icsflt,1,MPI_INTEGER,ipcsflt,1,MPI_INTEGER,comm2d, ierr)
7436
7437            IF ( ierr /= 0 ) THEN
7438                WRITE(9,*) 'Error MPI_AlltoAll1:', ierr, SIZE(icsflt), SIZE(ipcsflt)
7439                FLUSH(9)
7440            ENDIF
7441
7442            npcsfl = SUM(ipcsflt)
7443            d = 0
7444            DO i = 0, numprocs-1
7445                dpcsflt(i) = d
7446                d = d + ipcsflt(i)
7447            ENDDO
7448
7449!--         exchange csf fields between processors
7450            IF ( debug_output )  CALL debug_message( 'Exchange csf fields between processors', 'info' )
7451            udim = max(npcsfl,1)
7452            ALLOCATE( pcsflt_l(ndcsf*udim) )
7453            pcsflt(1:ndcsf,1:udim) => pcsflt_l(1:ndcsf*udim)
7454            ALLOCATE( kpcsflt_l(kdcsf*udim) )
7455            kpcsflt(1:kdcsf,1:udim) => kpcsflt_l(1:kdcsf*udim)
7456            CALL MPI_AlltoAllv(csflt_l, ndcsf*icsflt, ndcsf*dcsflt, MPI_REAL, &
7457                pcsflt_l, ndcsf*ipcsflt, ndcsf*dpcsflt, MPI_REAL, comm2d, ierr)
7458            IF ( ierr /= 0 ) THEN
7459                WRITE(9,*) 'Error MPI_AlltoAllv1:', ierr, SIZE(ipcsflt), ndcsf*icsflt, &
7460                            ndcsf*dcsflt, SIZE(pcsflt_l),ndcsf*ipcsflt, ndcsf*dpcsflt
7461                FLUSH(9)
7462            ENDIF
7463
7464            CALL MPI_AlltoAllv(kcsflt_l, kdcsf*icsflt, kdcsf*dcsflt, MPI_INTEGER, &
7465                kpcsflt_l, kdcsf*ipcsflt, kdcsf*dpcsflt, MPI_INTEGER, comm2d, ierr)
7466            IF ( ierr /= 0 ) THEN
7467                WRITE(9,*) 'Error MPI_AlltoAllv2:', ierr, SIZE(kcsflt_l),kdcsf*icsflt, &
7468                           kdcsf*dcsflt, SIZE(kpcsflt_l), kdcsf*ipcsflt, kdcsf*dpcsflt
7469                FLUSH(9)
7470            ENDIF
7471           
7472#else
7473            npcsfl = ncsfl
7474            ALLOCATE( pcsflt(ndcsf,max(npcsfl,ndcsf)) )
7475            ALLOCATE( kpcsflt(kdcsf,max(npcsfl,kdcsf)) )
7476            pcsflt = csflt
7477            kpcsflt = kcsflt
7478#endif
7479
7480!--         deallocate temporary arrays
7481            DEALLOCATE( csflt_l )
7482            DEALLOCATE( kcsflt_l )
7483            DEALLOCATE( icsflt )
7484            DEALLOCATE( dcsflt )
7485            DEALLOCATE( ipcsflt )
7486            DEALLOCATE( dpcsflt )
7487
7488!--         sort csf ( a version of quicksort )
7489            IF ( debug_output )  CALL debug_message( 'Sort csf', 'info' )
7490            CALL quicksort_csf2(kpcsflt, pcsflt, 1, npcsfl)
7491
7492!--         aggregate canopy sink factor records with identical box & source
7493!--         againg across all values from all processors
7494            IF ( debug_output )  CALL debug_message( 'Aggregate canopy sink factor records with identical box', 'info' )
7495
7496            IF ( npcsfl > 0 )  THEN
7497                icsf = 1 !< reading index
7498                kcsf = 1 !< writing index
7499                DO WHILE (icsf < npcsfl)
7500!--                 here kpcsf(kcsf) already has values from kpcsf(icsf)
7501                    IF ( kpcsflt(3,icsf) == kpcsflt(3,icsf+1)  .AND.  &
7502                         kpcsflt(2,icsf) == kpcsflt(2,icsf+1)  .AND.  &
7503                         kpcsflt(1,icsf) == kpcsflt(1,icsf+1)  .AND.  &
7504                         kpcsflt(4,icsf) == kpcsflt(4,icsf+1) )  THEN
7505
7506                        pcsflt(1,kcsf) = pcsflt(1,kcsf) + pcsflt(1,icsf+1)
7507
7508!--                     advance reading index, keep writing index
7509                        icsf = icsf + 1
7510                    ELSE
7511!--                     not identical, just advance and copy
7512                        icsf = icsf + 1
7513                        kcsf = kcsf + 1
7514                        kpcsflt(:,kcsf) = kpcsflt(:,icsf)
7515                        pcsflt(:,kcsf) = pcsflt(:,icsf)
7516                    ENDIF
7517                ENDDO
7518!--             last written item is now also the last item in valid part of array
7519                npcsfl = kcsf
7520            ENDIF
7521
7522            ncsfl = npcsfl
7523            IF ( ncsfl > 0 )  THEN
7524                ALLOCATE( csf(ndcsf,ncsfl) )
7525                ALLOCATE( csfsurf(idcsf,ncsfl) )
7526                DO icsf = 1, ncsfl
7527                    csf(:,icsf) = pcsflt(:,icsf)
7528                    csfsurf(1,icsf) =  gridpcbl(kpcsflt(1,icsf),kpcsflt(2,icsf),kpcsflt(3,icsf))
7529                    csfsurf(2,icsf) =  kpcsflt(4,icsf)
7530                ENDDO
7531            ENDIF
7532           
7533!--         deallocation of temporary arrays
7534            IF ( npcbl > 0 )  DEALLOCATE( gridpcbl )
7535            DEALLOCATE( pcsflt_l )
7536            DEALLOCATE( kpcsflt_l )
7537            IF ( debug_output )  CALL debug_message( 'End of aggregate csf', 'info' )
7538           
7539        ENDIF
7540
7541#if defined( __parallel )
7542        CALL MPI_BARRIER( comm2d, ierr )
7543#endif
7544        CALL location_message( 'calculating view factors for radiation interaction', 'finished' )
7545
7546        RETURN  !todo: remove
7547       
7548!        WRITE( message_string, * )  &
7549!            'I/O error when processing shape view factors / ',  &
7550!            'plant canopy sink factors / direct irradiance factors.'
7551!        CALL message( 'init_urban_surface', 'PA0502', 2, 2, 0, 6, 0 )
7552       
7553    END SUBROUTINE radiation_calc_svf
7554
7555   
7556!------------------------------------------------------------------------------!
7557! Description:
7558! ------------
7559!> Raytracing for detecting obstacles and calculating compound canopy sink
7560!> factors. (A simple obstacle detection would only need to process faces in
7561!> 3 dimensions without any ordering.)
7562!> Assumtions:
7563!> -----------
7564!> 1. The ray always originates from a face midpoint (only one coordinate equals
7565!>    *.5, i.e. wall) and doesn't travel parallel to the surface (that would mean
7566!>    shape factor=0). Therefore, the ray may never travel exactly along a face
7567!>    or an edge.
7568!> 2. From grid bottom to urban surface top the grid has to be *equidistant*
7569!>    within each of the dimensions, including vertical (but the resolution
7570!>    doesn't need to be the same in all three dimensions).
7571!------------------------------------------------------------------------------!
7572    SUBROUTINE raytrace(src, targ, isrc, difvf, atarg, create_csf, visible, transparency)
7573        IMPLICIT NONE
7574
7575        REAL(wp), DIMENSION(3), INTENT(in)     :: src, targ    !< real coordinates z,y,x
7576        INTEGER(iwp), INTENT(in)               :: isrc         !< index of source face for csf
7577        REAL(wp), INTENT(in)                   :: difvf        !< differential view factor for csf
7578        REAL(wp), INTENT(in)                   :: atarg        !< target surface area for csf
7579        LOGICAL, INTENT(in)                    :: create_csf   !< whether to generate new CSFs during raytracing
7580        LOGICAL, INTENT(out)                   :: visible
7581        REAL(wp), INTENT(out)                  :: transparency !< along whole path
7582        INTEGER(iwp)                           :: i, k, d
7583        INTEGER(iwp)                           :: seldim       !< dimension to be incremented
7584        INTEGER(iwp)                           :: ncsb         !< no of written plant canopy sinkboxes
7585        INTEGER(iwp)                           :: maxboxes     !< max no of gridboxes visited
7586        REAL(wp)                               :: distance     !< euclidean along path
7587        REAL(wp)                               :: crlen        !< length of gridbox crossing
7588        REAL(wp)                               :: lastdist     !< beginning of current crossing
7589        REAL(wp)                               :: nextdist     !< end of current crossing
7590        REAL(wp)                               :: realdist     !< distance in meters per unit distance
7591        REAL(wp)                               :: crmid        !< midpoint of crossing
7592        REAL(wp)                               :: cursink      !< sink factor for current canopy box
7593        REAL(wp), DIMENSION(3)                 :: delta        !< path vector
7594        REAL(wp), DIMENSION(3)                 :: uvect        !< unit vector
7595        REAL(wp), DIMENSION(3)                 :: dimnextdist  !< distance for each dimension increments
7596        INTEGER(iwp), DIMENSION(3)             :: box          !< gridbox being crossed
7597        INTEGER(iwp), DIMENSION(3)             :: dimnext      !< next dimension increments along path
7598        INTEGER(iwp), DIMENSION(3)             :: dimdelta     !< dimension direction = +- 1
7599        INTEGER(iwp)                           :: px, py       !< number of processors in x and y dir before
7600                                                               !< the processor in the question
7601        INTEGER(iwp)                           :: ip           !< number of processor where gridbox reside
7602        INTEGER(iwp)                           :: ig           !< 1D index of gridbox in global 2D array
7603       
7604        REAL(wp)                               :: eps = 1E-10_wp !< epsilon for value comparison
7605        REAL(wp)                               :: lad_s_target   !< recieved lad_s of particular grid box
7606
7607!
7608!--     Maximum number of gridboxes visited equals to maximum number of boundaries crossed in each dimension plus one. That's also
7609!--     the maximum number of plant canopy boxes written. We grow the acsf array accordingly using exponential factor.
7610        maxboxes = SUM(ABS(NINT(targ, iwp) - NINT(src, iwp))) + 1
7611        IF ( plant_canopy  .AND.  ncsfl + maxboxes > ncsfla )  THEN
7612!--         use this code for growing by fixed exponential increments (equivalent to case where ncsfl always increases by 1)
7613!--         k = CEILING(grow_factor ** real(CEILING(log(real(ncsfl + maxboxes, kind=wp)) &
7614!--                                                / log(grow_factor)), kind=wp))
7615!--         or use this code to simply always keep some extra space after growing
7616            k = CEILING(REAL(ncsfl + maxboxes, kind=wp) * grow_factor)
7617
7618            CALL merge_and_grow_csf(k)
7619        ENDIF
7620       
7621        transparency = 1._wp
7622        ncsb = 0
7623
7624        delta(:) = targ(:) - src(:)
7625        distance = SQRT(SUM(delta(:)**2))
7626        IF ( distance == 0._wp )  THEN
7627            visible = .TRUE.
7628            RETURN
7629        ENDIF
7630        uvect(:) = delta(:) / distance
7631        realdist = SQRT(SUM( (uvect(:)*(/dz(1),dy,dx/))**2 ))
7632
7633        lastdist = 0._wp
7634
7635!--     Since all face coordinates have values *.5 and we'd like to use
7636!--     integers, all these have .5 added
7637        DO d = 1, 3
7638            IF ( uvect(d) == 0._wp )  THEN
7639                dimnext(d) = 999999999
7640                dimdelta(d) = 999999999
7641                dimnextdist(d) = 1.0E20_wp
7642            ELSE IF ( uvect(d) > 0._wp )  THEN
7643                dimnext(d) = CEILING(src(d) + .5_wp)
7644                dimdelta(d) = 1
7645                dimnextdist(d) = (dimnext(d) - .5_wp - src(d)) / uvect(d)
7646            ELSE
7647                dimnext(d) = FLOOR(src(d) + .5_wp)
7648                dimdelta(d) = -1
7649                dimnextdist(d) = (dimnext(d) - .5_wp - src(d)) / uvect(d)
7650            ENDIF
7651        ENDDO
7652
7653        DO
7654!--         along what dimension will the next wall crossing be?
7655            seldim = minloc(dimnextdist, 1)
7656            nextdist = dimnextdist(seldim)
7657            IF ( nextdist > distance ) nextdist = distance
7658
7659            crlen = nextdist - lastdist
7660            IF ( crlen > .001_wp )  THEN
7661                crmid = (lastdist + nextdist) * .5_wp
7662                box = NINT(src(:) + uvect(:) * crmid, iwp)
7663
7664!--             calculate index of the grid with global indices (box(2),box(3))
7665!--             in the array nzterr and plantt and id of the coresponding processor
7666                px = box(3)/nnx
7667                py = box(2)/nny
7668                ip = px*pdims(2)+py
7669                ig = ip*nnx*nny + (box(3)-px*nnx)*nny + box(2)-py*nny
7670                IF ( box(1) <= nzterr(ig) )  THEN
7671                    visible = .FALSE.
7672                    RETURN
7673                ENDIF
7674
7675                IF ( plant_canopy )  THEN
7676                    IF ( box(1) <= plantt(ig) )  THEN
7677                        ncsb = ncsb + 1
7678                        boxes(:,ncsb) = box
7679                        crlens(ncsb) = crlen
7680#if defined( __parallel )
7681                        lad_ip(ncsb) = ip
7682                        lad_disp(ncsb) = (box(3)-px*nnx)*(nny*nz_plant) + (box(2)-py*nny)*nz_plant + box(1)-nz_urban_b
7683#endif
7684                    ENDIF
7685                ENDIF
7686            ENDIF
7687
7688            IF ( ABS(distance - nextdist) < eps )  EXIT
7689            lastdist = nextdist
7690            dimnext(seldim) = dimnext(seldim) + dimdelta(seldim)
7691            dimnextdist(seldim) = (dimnext(seldim) - .5_wp - src(seldim)) / uvect(seldim)
7692        ENDDO
7693       
7694        IF ( plant_canopy )  THEN
7695#if defined( __parallel )
7696            IF ( raytrace_mpi_rma )  THEN
7697!--             send requests for lad_s to appropriate processor
7698                CALL cpu_log( log_point_s(77), 'rad_rma_lad', 'start' )
7699                DO i = 1, ncsb
7700                    CALL MPI_Get(lad_s_ray(i), 1, MPI_REAL, lad_ip(i), lad_disp(i), &
7701                                 1, MPI_REAL, win_lad, ierr)
7702                    IF ( ierr /= 0 )  THEN
7703                        WRITE(9,*) 'Error MPI_Get1:', ierr, lad_s_ray(i), &
7704                                   lad_ip(i), lad_disp(i), win_lad
7705                        FLUSH(9)
7706                    ENDIF
7707                ENDDO
7708               
7709!--             wait for all pending local requests complete
7710                CALL MPI_Win_flush_local_all(win_lad, ierr)
7711                IF ( ierr /= 0 )  THEN
7712                    WRITE(9,*) 'Error MPI_Win_flush_local_all1:', ierr, win_lad
7713                    FLUSH(9)
7714                ENDIF
7715                CALL cpu_log( log_point_s(77), 'rad_rma_lad', 'stop' )
7716               
7717            ENDIF
7718#endif
7719
7720!--         calculate csf and transparency
7721            DO i = 1, ncsb
7722#if defined( __parallel )
7723                IF ( raytrace_mpi_rma )  THEN
7724                    lad_s_target = lad_s_ray(i)
7725                ELSE
7726                    lad_s_target = sub_lad_g(lad_ip(i)*nnx*nny*nz_plant + lad_disp(i))
7727                ENDIF
7728#else
7729                lad_s_target = sub_lad(boxes(1,i),boxes(2,i),boxes(3,i))
7730#endif
7731                cursink = 1._wp - exp(-ext_coef * lad_s_target * crlens(i)*realdist)
7732
7733                IF ( create_csf )  THEN
7734!--                 write svf values into the array
7735                    ncsfl = ncsfl + 1
7736                    acsf(ncsfl)%ip = lad_ip(i)
7737                    acsf(ncsfl)%itx = boxes(3,i)
7738                    acsf(ncsfl)%ity = boxes(2,i)
7739                    acsf(ncsfl)%itz = boxes(1,i)
7740                    acsf(ncsfl)%isurfs = isrc
7741                    acsf(ncsfl)%rcvf = cursink*transparency*difvf*atarg
7742                ENDIF  !< create_csf
7743
7744                transparency = transparency * (1._wp - cursink)
7745               
7746            ENDDO
7747        ENDIF
7748       
7749        visible = .TRUE.
7750
7751    END SUBROUTINE raytrace
7752   
7753 
7754!------------------------------------------------------------------------------!
7755! Description:
7756! ------------
7757!> A new, more efficient version of ray tracing algorithm that processes a whole
7758!> arc instead of a single ray.
7759!>
7760!> In all comments, horizon means tangent of horizon angle, i.e.
7761!> vertical_delta / horizontal_distance
7762!------------------------------------------------------------------------------!
7763   SUBROUTINE raytrace_2d(origin, yxdir, nrays, zdirs, iorig, aorig, vffrac,  &
7764                              calc_svf, create_csf, skip_1st_pcb,             &
7765                              lowest_free_ray, transparency, itarget)
7766      IMPLICIT NONE
7767
7768      REAL(wp), DIMENSION(3), INTENT(IN)     ::  origin        !< z,y,x coordinates of ray origin
7769      REAL(wp), DIMENSION(2), INTENT(IN)     ::  yxdir         !< y,x *unit* vector of ray direction (in grid units)
7770      INTEGER(iwp)                           ::  nrays         !< number of rays (z directions) to raytrace
7771      REAL(wp), DIMENSION(nrays), INTENT(IN) ::  zdirs         !< list of z directions to raytrace (z/hdist, grid, zenith->nadir)
7772      INTEGER(iwp), INTENT(in)               ::  iorig         !< index of origin face for csf
7773      REAL(wp), INTENT(in)                   ::  aorig         !< origin face area for csf
7774      REAL(wp), DIMENSION(nrays), INTENT(in) ::  vffrac        !< view factor fractions of each ray for csf
7775      LOGICAL, INTENT(in)                    ::  calc_svf      !< whether to calculate SFV (identify obstacle surfaces)
7776      LOGICAL, INTENT(in)                    ::  create_csf    !< whether to create canopy sink factors
7777      LOGICAL, INTENT(in)                    ::  skip_1st_pcb  !< whether to skip first plant canopy box during raytracing
7778      INTEGER(iwp), INTENT(out)              ::  lowest_free_ray !< index into zdirs
7779      REAL(wp), DIMENSION(nrays), INTENT(OUT) ::  transparency !< transparencies of zdirs paths
7780      INTEGER(iwp), DIMENSION(nrays), INTENT(OUT) ::  itarget  !< global indices of target faces for zdirs
7781
7782      INTEGER(iwp), DIMENSION(nrays)         ::  target_procs
7783      REAL(wp)                               ::  horizon       !< highest horizon found after raytracing (z/hdist)
7784      INTEGER(iwp)                           ::  i, k, l, d
7785      INTEGER(iwp)                           ::  seldim       !< dimension to be incremented
7786      REAL(wp), DIMENSION(2)                 ::  yxorigin     !< horizontal copy of origin (y,x)
7787      REAL(wp)                               ::  distance     !< euclidean along path
7788      REAL(wp)                               ::  lastdist     !< beginning of current crossing
7789      REAL(wp)                               ::  nextdist     !< end of current crossing
7790      REAL(wp)                               ::  crmid        !< midpoint of crossing
7791      REAL(wp)                               ::  horz_entry   !< horizon at entry to column
7792      REAL(wp)                               ::  horz_exit    !< horizon at exit from column
7793      REAL(wp)                               ::  bdydim       !< boundary for current dimension
7794      REAL(wp), DIMENSION(2)                 ::  crossdist    !< distances to boundary for dimensions
7795      REAL(wp), DIMENSION(2)                 ::  dimnextdist  !< distance for each dimension increments
7796      INTEGER(iwp), DIMENSION(2)             ::  column       !< grid column being crossed
7797      INTEGER(iwp), DIMENSION(2)             ::  dimnext      !< next dimension increments along path
7798      INTEGER(iwp), DIMENSION(2)             ::  dimdelta     !< dimension direction = +- 1
7799      INTEGER(iwp)                           ::  px, py       !< number of processors in x and y dir before
7800                                                              !< the processor in the question
7801      INTEGER(iwp)                           ::  ip           !< number of processor where gridbox reside
7802      INTEGER(iwp)                           ::  ig           !< 1D index of gridbox in global 2D array
7803      INTEGER(iwp)                           ::  wcount       !< RMA window item count
7804      INTEGER(iwp)                           ::  maxboxes     !< max no of CSF created
7805      INTEGER(iwp)                           ::  nly          !< maximum  plant canopy height
7806      INTEGER(iwp)                           ::  ntrack
7807     
7808      INTEGER(iwp)                           ::  zb0
7809      INTEGER(iwp)                           ::  zb1
7810      INTEGER(iwp)                           ::  nz
7811      INTEGER(iwp)                           ::  iz
7812      INTEGER(iwp)                           ::  zsgn
7813      INTEGER(iwp)                           ::  lowest_lad   !< lowest column cell for which we need LAD
7814      INTEGER(iwp)                           ::  lastdir      !< wall direction before hitting this column
7815      INTEGER(iwp), DIMENSION(2)             ::  lastcolumn
7816
7817#if defined( __parallel )
7818      INTEGER(MPI_ADDRESS_KIND)              ::  wdisp        !< RMA window displacement
7819#endif
7820     
7821      REAL(wp)                               ::  eps = 1E-10_wp !< epsilon for value comparison
7822      REAL(wp)                               ::  zbottom, ztop !< urban surface boundary in real numbers
7823      REAL(wp)                               ::  zorig         !< z coordinate of ray column entry
7824      REAL(wp)                               ::  zexit         !< z coordinate of ray column exit
7825      REAL(wp)                               ::  qdist         !< ratio of real distance to z coord difference
7826      REAL(wp)                               ::  dxxyy         !< square of real horizontal distance
7827      REAL(wp)                               ::  curtrans      !< transparency of current PC box crossing
7828     
7829
7830     
7831      yxorigin(:) = origin(2:3)
7832      transparency(:) = 1._wp !-- Pre-set the all rays to transparent before reducing
7833      horizon = -HUGE(1._wp)
7834      lowest_free_ray = nrays
7835      IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7836         ALLOCATE(target_surfl(nrays))
7837         target_surfl(:) = -1
7838         lastdir = -999
7839         lastcolumn(:) = -999
7840      ENDIF
7841
7842!--   Determine distance to boundary (in 2D xy)
7843      IF ( yxdir(1) > 0._wp )  THEN
7844         bdydim = ny + .5_wp !< north global boundary
7845         crossdist(1) = (bdydim - yxorigin(1)) / yxdir(1)
7846      ELSEIF ( yxdir(1) == 0._wp )  THEN
7847         crossdist(1) = HUGE(1._wp)
7848      ELSE
7849          bdydim = -.5_wp !< south global boundary
7850          crossdist(1) = (bdydim - yxorigin(1)) / yxdir(1)
7851      ENDIF
7852
7853      IF ( yxdir(2) > 0._wp )  THEN
7854          bdydim = nx + .5_wp !< east global boundary
7855          crossdist(2) = (bdydim - yxorigin(2)) / yxdir(2)
7856      ELSEIF ( yxdir(2) == 0._wp )  THEN
7857         crossdist(2) = HUGE(1._wp)
7858      ELSE
7859          bdydim = -.5_wp !< west global boundary
7860          crossdist(2) = (bdydim - yxorigin(2)) / yxdir(2)
7861      ENDIF
7862      distance = minval(crossdist, 1)
7863
7864      IF ( plant_canopy )  THEN
7865         rt2_track_dist(0) = 0._wp
7866         rt2_track_lad(:,:) = 0._wp
7867         nly = plantt_max - nz_urban_b + 1
7868      ENDIF
7869
7870      lastdist = 0._wp
7871
7872!--   Since all face coordinates have values *.5 and we'd like to use
7873!--   integers, all these have .5 added
7874      DO  d = 1, 2
7875          IF ( yxdir(d) == 0._wp )  THEN
7876              dimnext(d) = HUGE(1_iwp)
7877              dimdelta(d) = HUGE(1_iwp)
7878              dimnextdist(d) = HUGE(1._wp)
7879          ELSE IF ( yxdir(d) > 0._wp )  THEN
7880              dimnext(d) = FLOOR(yxorigin(d) + .5_wp) + 1
7881              dimdelta(d) = 1
7882              dimnextdist(d) = (dimnext(d) - .5_wp - yxorigin(d)) / yxdir(d)
7883          ELSE
7884              dimnext(d) = CEILING(yxorigin(d) + .5_wp) - 1
7885              dimdelta(d) = -1
7886              dimnextdist(d) = (dimnext(d) - .5_wp - yxorigin(d)) / yxdir(d)
7887          ENDIF
7888      ENDDO
7889
7890      ntrack = 0
7891      DO
7892!--      along what dimension will the next wall crossing be?
7893         seldim = minloc(dimnextdist, 1)
7894         nextdist = dimnextdist(seldim)
7895         IF ( nextdist > distance )  nextdist = distance
7896
7897         IF ( nextdist > lastdist )  THEN
7898            ntrack = ntrack + 1
7899            crmid = (lastdist + nextdist) * .5_wp
7900            column = NINT(yxorigin(:) + yxdir(:) * crmid, iwp)
7901
7902!--         calculate index of the grid with global indices (column(1),column(2))
7903!--         in the array nzterr and plantt and id of the coresponding processor
7904            px = column(2)/nnx
7905            py = column(1)/nny
7906            ip = px*pdims(2)+py
7907            ig = ip*nnx*nny + (column(2)-px*nnx)*nny + column(1)-py*nny
7908
7909            IF ( lastdist == 0._wp )  THEN
7910               horz_entry = -HUGE(1._wp)
7911            ELSE
7912               horz_entry = (REAL(nzterr(ig), wp) + .5_wp - origin(1)) / lastdist
7913            ENDIF
7914            horz_exit = (REAL(nzterr(ig), wp) + .5_wp - origin(1)) / nextdist
7915
7916            IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7917!
7918!--            Identify vertical obstacles hit by rays in current column
7919               DO WHILE ( lowest_free_ray > 0 )
7920                  IF ( zdirs(lowest_free_ray) > horz_entry )  EXIT
7921!
7922!--               This may only happen after 1st column, so lastdir and lastcolumn are valid
7923                  CALL request_itarget(lastdir,                                         &
7924                        CEILING(-0.5_wp + origin(1) + zdirs(lowest_free_ray)*lastdist), &
7925                        lastcolumn(1), lastcolumn(2),                                   &
7926                        target_surfl(lowest_free_ray), target_procs(lowest_free_ray))
7927                  lowest_free_ray = lowest_free_ray - 1
7928               ENDDO
7929!
7930!--            Identify horizontal obstacles hit by rays in current column
7931               DO WHILE ( lowest_free_ray > 0 )
7932                  IF ( zdirs(lowest_free_ray) > horz_exit )  EXIT
7933                  CALL request_itarget(iup_u, nzterr(ig)+1, column(1), column(2), &
7934                                       target_surfl(lowest_free_ray),           &
7935                                       target_procs(lowest_free_ray))
7936                  lowest_free_ray = lowest_free_ray - 1
7937               ENDDO
7938            ENDIF
7939
7940            horizon = MAX(horizon, horz_entry, horz_exit)
7941
7942            IF ( plant_canopy )  THEN
7943               rt2_track(:, ntrack) = column(:)
7944               rt2_track_dist(ntrack) = nextdist
7945            ENDIF
7946         ENDIF
7947
7948         IF ( nextdist + eps >= distance )  EXIT
7949
7950         IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7951!
7952!--         Save wall direction of coming building column (= this air column)
7953            IF ( seldim == 1 )  THEN
7954               IF ( dimdelta(seldim) == 1 )  THEN
7955                  lastdir = isouth_u
7956               ELSE
7957                  lastdir = inorth_u
7958               ENDIF
7959            ELSE
7960               IF ( dimdelta(seldim) == 1 )  THEN
7961                  lastdir = iwest_u
7962               ELSE
7963                  lastdir = ieast_u
7964               ENDIF
7965            ENDIF
7966            lastcolumn = column
7967         ENDIF
7968         lastdist = nextdist
7969         dimnext(seldim) = dimnext(seldim) + dimdelta(seldim)
7970         dimnextdist(seldim) = (dimnext(seldim) - .5_wp - yxorigin(seldim)) / yxdir(seldim)
7971      ENDDO
7972
7973      IF ( plant_canopy )  THEN
7974!--      Request LAD WHERE applicable
7975!--     
7976#if defined( __parallel )
7977         IF ( raytrace_mpi_rma )  THEN
7978!--         send requests for lad_s to appropriate processor
7979            !CALL cpu_log( log_point_s(77), 'usm_init_rma', 'start' )
7980            DO  i = 1, ntrack
7981               px = rt2_track(2,i)/nnx
7982               py = rt2_track(1,i)/nny
7983               ip = px*pdims(2)+py
7984               ig = ip*nnx*nny + (rt2_track(2,i)-px*nnx)*nny + rt2_track(1,i)-py*nny
7985
7986               IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7987!
7988!--               For fixed view resolution, we need plant canopy even for rays
7989!--               to opposing surfaces
7990                  lowest_lad = nzterr(ig) + 1
7991               ELSE
7992!
7993!--               We only need LAD for rays directed above horizon (to sky)
7994                  lowest_lad = CEILING( -0.5_wp + origin(1) +            &
7995                                    MIN( horizon * rt2_track_dist(i-1),  & ! entry
7996                                         horizon * rt2_track_dist(i)   ) ) ! exit
7997               ENDIF
7998!
7999!--            Skip asking for LAD where all plant canopy is under requested level
8000               IF ( plantt(ig) < lowest_lad )  CYCLE
8001
8002               wdisp = (rt2_track(2,i)-px*nnx)*(nny*nz_plant) + (rt2_track(1,i)-py*nny)*nz_plant + lowest_lad-nz_urban_b
8003               wcount = plantt(ig)-lowest_lad+1
8004               ! TODO send request ASAP - even during raytracing
8005               CALL MPI_Get(rt2_track_lad(lowest_lad:plantt(ig), i), wcount, MPI_REAL, ip,    &
8006                            wdisp, wcount, MPI_REAL, win_lad, ierr)
8007               IF ( ierr /= 0 )  THEN
8008                  WRITE(9,*) 'Error MPI_Get2:', ierr, rt2_track_lad(lowest_lad:plantt(ig), i), &
8009                             wcount, ip, wdisp, win_lad
8010                  FLUSH(9)
8011               ENDIF
8012            ENDDO
8013
8014!--         wait for all pending local requests complete
8015            ! TODO WAIT selectively for each column later when needed
8016            CALL MPI_Win_flush_local_all(win_lad, ierr)
8017            IF ( ierr /= 0 )  THEN
8018               WRITE(9,*) 'Error MPI_Win_flush_local_all2:', ierr, win_lad
8019               FLUSH(9)
8020            ENDIF
8021            !CALL cpu_log( log_point_s(77), 'usm_init_rma', 'stop' )
8022
8023         ELSE ! raytrace_mpi_rma = .F.
8024            DO  i = 1, ntrack
8025               px = rt2_track(2,i)/nnx
8026               py = rt2_track(1,i)/nny
8027               ip = px*pdims(2)+py
8028               ig = ip*nnx*nny*nz_plant + (rt2_track(2,i)-px*nnx)*(nny*nz_plant) + (rt2_track(1,i)-py*nny)*nz_plant
8029               rt2_track_lad(nz_urban_b:plantt_max, i) = sub_lad_g(ig:ig+nly-1)
8030            ENDDO
8031         ENDIF
8032#else
8033         DO  i = 1, ntrack
8034            rt2_track_lad(nz_urban_b:plantt_max, i) = sub_lad(rt2_track(1,i), rt2_track(2,i), nz_urban_b:plantt_max)
8035         ENDDO
8036#endif
8037      ENDIF ! plant_canopy
8038
8039      IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
8040#if defined( __parallel )
8041!--      wait for all gridsurf requests to complete
8042         CALL MPI_Win_flush_local_all(win_gridsurf, ierr)
8043         IF ( ierr /= 0 )  THEN
8044            WRITE(9,*) 'Error MPI_Win_flush_local_all3:', ierr, win_gridsurf
8045            FLUSH(9)
8046         ENDIF
8047#endif
8048!
8049!--      recalculate local surf indices into global ones
8050         DO i = 1, nrays
8051            IF ( target_surfl(i) == -1 )  THEN
8052               itarget(i) = -1
8053            ELSE
8054               itarget(i) = target_surfl(i) + surfstart(target_procs(i))
8055            ENDIF
8056         ENDDO
8057         
8058         DEALLOCATE( target_surfl )
8059         
8060      ELSE
8061         itarget(:) = -1
8062      ENDIF ! rad_angular_discretization
8063
8064      IF ( plant_canopy )  THEN
8065!--      Skip the PCB around origin if requested (for MRT, the PCB might not be there)
8066!--     
8067         IF ( skip_1st_pcb  .AND.  NINT(origin(1)) <= plantt_max )  THEN
8068            rt2_track_lad(NINT(origin(1), iwp), 1) = 0._wp
8069         ENDIF
8070
8071!--      Assert that we have space allocated for CSFs
8072!--     
8073         maxboxes = (ntrack + MAX(CEILING(origin(1)-.5_wp) - nz_urban_b,          &
8074                                  nz_urban_t - CEILING(origin(1)-.5_wp))) * nrays
8075         IF ( ncsfl + maxboxes > ncsfla )  THEN
8076!--         use this code for growing by fixed exponential increments (equivalent to case where ncsfl always increases by 1)
8077!--         k = CEILING(grow_factor ** real(CEILING(log(real(ncsfl + maxboxes, kind=wp)) &
8078!--                                                / log(grow_factor)), kind=wp))
8079!--         or use this code to simply always keep some extra space after growing
8080            k = CEILING(REAL(ncsfl + maxboxes, kind=wp) * grow_factor)
8081            CALL merge_and_grow_csf(k)
8082         ENDIF
8083
8084!--      Calculate transparencies and store new CSFs
8085!--     
8086         zbottom = REAL(nz_urban_b, wp) - .5_wp
8087         ztop = REAL(plantt_max, wp) + .5_wp
8088
8089!--      Reverse direction of radiation (face->sky), only when calc_svf
8090!--     
8091         IF ( calc_svf )  THEN
8092            DO  i = 1, ntrack ! for each column
8093               dxxyy = ((dy*yxdir(1))**2 + (dx*yxdir(2))**2) * (rt2_track_dist(i)-rt2_track_dist(i-1))**2
8094               px = rt2_track(2,i)/nnx
8095               py = rt2_track(1,i)/nny
8096               ip = px*pdims(2)+py
8097
8098               DO  k = 1, nrays ! for each ray
8099!
8100!--               NOTE 6778:
8101!--               With traditional svf discretization, CSFs under the horizon
8102!--               (i.e. for surface to surface radiation)  are created in
8103!--               raytrace(). With rad_angular_discretization, we must create
8104!--               CSFs under horizon only for one direction, otherwise we would
8105!--               have duplicate amount of energy. Although we could choose
8106!--               either of the two directions (they differ only by
8107!--               discretization error with no bias), we choose the the backward
8108!--               direction, because it tends to cumulate high canopy sink
8109!--               factors closer to raytrace origin, i.e. it should potentially
8110!--               cause less moiree.
8111                  IF ( .NOT. rad_angular_discretization )  THEN
8112                     IF ( zdirs(k) <= horizon )  CYCLE
8113                  ENDIF
8114
8115                  zorig = origin(1) + zdirs(k) * rt2_track_dist(i-1)
8116                  IF ( zorig <= zbottom  .OR.  zorig >= ztop )  CYCLE
8117
8118                  zsgn = INT(SIGN(1._wp, zdirs(k)), iwp)
8119                  rt2_dist(1) = 0._wp
8120                  IF ( zdirs(k) == 0._wp )  THEN ! ray is exactly horizontal
8121                     nz = 2
8122                     rt2_dist(nz) = SQRT(dxxyy)
8123                     iz = CEILING(-.5_wp + zorig, iwp)
8124                  ELSE
8125                     zexit = MIN(MAX(origin(1) + zdirs(k) * rt2_track_dist(i), zbottom), ztop)
8126
8127                     zb0 = FLOOR(  zorig * zsgn - .5_wp) + 1  ! because it must be greater than orig
8128                     zb1 = CEILING(zexit * zsgn - .5_wp) - 1  ! because it must be smaller than exit
8129                     nz = MAX(zb1 - zb0 + 3, 2)
8130                     rt2_dist(nz) = SQRT(((zexit-zorig)*dz(1))**2 + dxxyy)
8131                     qdist = rt2_dist(nz) / (zexit-zorig)
8132                     rt2_dist(2:nz-1) = (/( ((REAL(l, wp) + .5_wp) * zsgn - zorig) * qdist , l = zb0, zb1 )/)
8133                     iz = zb0 * zsgn
8134                  ENDIF
8135
8136                  DO  l = 2, nz
8137                     IF ( rt2_track_lad(iz, i) > 0._wp )  THEN
8138                        curtrans = exp(-ext_coef * rt2_track_lad(iz, i) * (rt2_dist(l)-rt2_dist(l-1)))
8139
8140                        IF ( create_csf )  THEN
8141                           ncsfl = ncsfl + 1
8142                           acsf(ncsfl)%ip = ip
8143                           acsf(ncsfl)%itx = rt2_track(2,i)
8144                           acsf(ncsfl)%ity = rt2_track(1,i)
8145                           acsf(ncsfl)%itz = iz
8146                           acsf(ncsfl)%isurfs = iorig
8147                           acsf(ncsfl)%rcvf = (1._wp - curtrans)*transparency(k)*vffrac(k)
8148                        ENDIF
8149
8150                        transparency(k) = transparency(k) * curtrans
8151                     ENDIF
8152                     iz = iz + zsgn
8153                  ENDDO ! l = 1, nz - 1
8154               ENDDO ! k = 1, nrays
8155            ENDDO ! i = 1, ntrack
8156
8157            transparency(1:lowest_free_ray) = 1._wp !-- Reset rays above horizon to transparent (see NOTE 6778)
8158         ENDIF
8159
8160!--      Forward direction of radiation (sky->face), always
8161!--     
8162         DO  i = ntrack, 1, -1 ! for each column backwards
8163            dxxyy = ((dy*yxdir(1))**2 + (dx*yxdir(2))**2) * (rt2_track_dist(i)-rt2_track_dist(i-1))**2
8164            px = rt2_track(2,i)/nnx
8165            py = rt2_track(1,i)/nny
8166            ip = px*pdims(2)+py
8167
8168            DO  k = 1, nrays ! for each ray
8169!
8170!--            See NOTE 6778 above
8171               IF ( zdirs(k) <= horizon )  CYCLE
8172
8173               zexit = origin(1) + zdirs(k) * rt2_track_dist(i-1)
8174               IF ( zexit <= zbottom  .OR.  zexit >= ztop )  CYCLE
8175
8176               zsgn = -INT(SIGN(1._wp, zdirs(k)), iwp)
8177               rt2_dist(1) = 0._wp
8178               IF ( zdirs(k) == 0._wp )  THEN ! ray is exactly horizontal
8179                  nz = 2
8180                  rt2_dist(nz) = SQRT(dxxyy)
8181                  iz = NINT(zexit, iwp)
8182               ELSE
8183                  zorig = MIN(MAX(origin(1) + zdirs(k) * rt2_track_dist(i), zbottom), ztop)
8184
8185                  zb0 = FLOOR(  zorig * zsgn - .5_wp) + 1  ! because it must be greater than orig
8186                  zb1 = CEILING(zexit * zsgn - .5_wp) - 1  ! because it must be smaller than exit
8187                  nz = MAX(zb1 - zb0 + 3, 2)
8188                  rt2_dist(nz) = SQRT(((zexit-zorig)*dz(1))**2 + dxxyy)
8189                  qdist = rt2_dist(nz) / (zexit-zorig)
8190                  rt2_dist(2:nz-1) = (/( ((REAL(l, wp) + .5_wp) * zsgn - zorig) * qdist , l = zb0, zb1 )/)
8191                  iz = zb0 * zsgn
8192               ENDIF
8193
8194               DO  l = 2, nz
8195                  IF ( rt2_track_lad(iz, i) > 0._wp )  THEN
8196                     curtrans = exp(-ext_coef * rt2_track_lad(iz, i) * (rt2_dist(l)-rt2_dist(l-1)))
8197
8198                     IF ( create_csf )  THEN
8199                        ncsfl = ncsfl + 1
8200                        acsf(ncsfl)%ip = ip
8201                        acsf(ncsfl)%itx = rt2_track(2,i)
8202                        acsf(ncsfl)%ity = rt2_track(1,i)
8203                        acsf(ncsfl)%itz = iz
8204                        IF ( itarget(k) /= -1 ) STOP 1 !FIXME remove after test
8205                        acsf(ncsfl)%isurfs = -1
8206                        acsf(ncsfl)%rcvf = (1._wp - curtrans)*transparency(k)*aorig*vffrac(k)
8207                     ENDIF  ! create_csf
8208
8209                     transparency(k) = transparency(k) * curtrans
8210                  ENDIF
8211                  iz = iz + zsgn
8212               ENDDO ! l = 1, nz - 1
8213            ENDDO ! k = 1, nrays
8214         ENDDO ! i = 1, ntrack
8215      ENDIF ! plant_canopy
8216
8217      IF ( .NOT. (rad_angular_discretization  .AND.  calc_svf) )  THEN
8218!
8219!--      Just update lowest_free_ray according to horizon
8220         DO WHILE ( lowest_free_ray > 0 )
8221            IF ( zdirs(lowest_free_ray) > horizon )  EXIT
8222            lowest_free_ray = lowest_free_ray - 1
8223         ENDDO
8224      ENDIF
8225
8226   CONTAINS
8227
8228      SUBROUTINE request_itarget( d, z, y, x, isurfl, iproc )
8229
8230         INTEGER(iwp), INTENT(in)            ::  d, z, y, x
8231         INTEGER(iwp), TARGET, INTENT(out)   ::  isurfl
8232         INTEGER(iwp), INTENT(out)           ::  iproc
8233#if defined( __parallel )
8234#else
8235         INTEGER(iwp)                        ::  target_displ  !< index of the grid in the local gridsurf array
8236#endif
8237         INTEGER(iwp)                        ::  px, py        !< number of processors in x and y direction
8238                                                               !< before the processor in the question
8239#if defined( __parallel )
8240         INTEGER(KIND=MPI_ADDRESS_KIND)      ::  target_displ  !< index of the grid in the local gridsurf array
8241
8242!
8243!--      Calculate target processor and index in the remote local target gridsurf array
8244         px = x / nnx
8245         py = y / nny
8246         iproc = px * pdims(2) + py
8247         target_displ = ((x-px*nnx) * nny + y - py*nny ) * nz_urban * nsurf_type_u +&
8248                        ( z-nz_urban_b ) * nsurf_type_u + d
8249!
8250!--      Send MPI_Get request to obtain index target_surfl(i)
8251         CALL MPI_GET( isurfl, 1, MPI_INTEGER, iproc, target_displ,            &
8252                       1, MPI_INTEGER, win_gridsurf, ierr)
8253         IF ( ierr /= 0 )  THEN
8254            WRITE( 9,* ) 'Error MPI_Get3:', ierr, isurfl, iproc, target_displ, &
8255                         win_gridsurf
8256            FLUSH( 9 )
8257         ENDIF
8258#else
8259!--      set index target_surfl(i)
8260         isurfl = gridsurf(d,z,y,x)
8261#endif
8262
8263      END SUBROUTINE request_itarget
8264
8265   END SUBROUTINE raytrace_2d
8266 
8267
8268!------------------------------------------------------------------------------!
8269!
8270! Description:
8271! ------------
8272!> Calculates apparent solar positions for all timesteps and stores discretized
8273!> positions.
8274!------------------------------------------------------------------------------!
8275   SUBROUTINE radiation_presimulate_solar_pos
8276
8277      IMPLICIT NONE
8278
8279      INTEGER(iwp)                              ::  it, i, j
8280      INTEGER(iwp)                              ::  day_of_month_prev,month_of_year_prev
8281      REAL(wp)                                  ::  tsrp_prev
8282      REAL(wp)                                  ::  simulated_time_prev
8283      REAL(wp), DIMENSION(:,:), ALLOCATABLE     ::  dsidir_tmp       !< dsidir_tmp[:,i] = unit vector of i-th
8284                                                                     !< appreant solar direction
8285
8286      ALLOCATE ( dsidir_rev(0:raytrace_discrete_elevs/2-1,                 &
8287                            0:raytrace_discrete_azims-1) )
8288      dsidir_rev(:,:) = -1
8289      ALLOCATE ( dsidir_tmp(3,                                             &
8290                     raytrace_discrete_elevs/2*raytrace_discrete_azims) )
8291      ndsidir = 0
8292
8293!
8294!--   We will artificialy update time_since_reference_point and return to
8295!--   true value later
8296      tsrp_prev = time_since_reference_point
8297      simulated_time_prev = simulated_time
8298      day_of_month_prev = day_of_month
8299      month_of_year_prev = month_of_year
8300      sun_direction = .TRUE.
8301
8302!
8303!--   initialize the simulated_time
8304      simulated_time = 0._wp
8305!
8306!--   Process spinup time if configured
8307      IF ( spinup_time > 0._wp )  THEN
8308         DO  it = 0, CEILING(spinup_time / dt_spinup)
8309            time_since_reference_point = -spinup_time + REAL(it, wp) * dt_spinup
8310            simulated_time = simulated_time + dt_spinup
8311            CALL simulate_pos
8312         ENDDO
8313      ENDIF
8314!
8315!--   Process simulation time
8316      DO  it = 0, CEILING(( end_time - spinup_time ) / dt_radiation)
8317         time_since_reference_point = REAL(it, wp) * dt_radiation
8318         simulated_time = simulated_time + dt_radiation
8319         CALL simulate_pos
8320      ENDDO
8321!
8322!--   Return date and time to its original values
8323      time_since_reference_point = tsrp_prev
8324      simulated_time = simulated_time_prev
8325      day_of_month = day_of_month_prev
8326      month_of_year = month_of_year_prev
8327      CALL init_date_and_time
8328
8329!--   Allocate global vars which depend on ndsidir
8330      ALLOCATE ( dsidir ( 3, ndsidir ) )
8331      dsidir(:,:) = dsidir_tmp(:, 1:ndsidir)
8332      DEALLOCATE ( dsidir_tmp )
8333
8334      ALLOCATE ( dsitrans(nsurfl, ndsidir) )
8335      ALLOCATE ( dsitransc(npcbl, ndsidir) )
8336      IF ( nmrtbl > 0 )  ALLOCATE ( mrtdsit(nmrtbl, ndsidir) )
8337
8338      WRITE ( message_string, * ) 'Precalculated', ndsidir, ' solar positions', &
8339                                  ' from', it, ' timesteps.'
8340      CALL message( 'radiation_presimulate_solar_pos', 'UI0013', 0, 0, 0, 6, 0 )
8341
8342      CONTAINS
8343
8344      !------------------------------------------------------------------------!
8345      ! Description:
8346      ! ------------
8347      !> Simuates a single position
8348      !------------------------------------------------------------------------!
8349      SUBROUTINE simulate_pos
8350         IMPLICIT NONE
8351!
8352!--      Update apparent solar position based on modified t_s_r_p
8353         CALL calc_zenith
8354         IF ( cos_zenith > 0 )  THEN
8355!--         
8356!--         Identify solar direction vector (discretized number) 1)
8357            i = MODULO(NINT(ATAN2(sun_dir_lon, sun_dir_lat)               &
8358                            / (2._wp*pi) * raytrace_discrete_azims-.5_wp, iwp), &
8359                       raytrace_discrete_azims)
8360            j = FLOOR(ACOS(cos_zenith) / pi * raytrace_discrete_elevs)
8361            IF ( dsidir_rev(j, i) == -1 )  THEN
8362               ndsidir = ndsidir + 1
8363               dsidir_tmp(:, ndsidir) =                                              &
8364                     (/ COS((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs), &
8365                        SIN((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs)  &
8366                      * COS((REAL(i,wp)+.5_wp) * 2_wp*pi / raytrace_discrete_azims), &
8367                        SIN((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs)  &
8368                      * SIN((REAL(i,wp)+.5_wp) * 2_wp*pi / raytrace_discrete_azims) /)
8369               dsidir_rev(j, i) = ndsidir
8370            ENDIF
8371         ENDIF
8372      END SUBROUTINE simulate_pos
8373
8374   END SUBROUTINE radiation_presimulate_solar_pos
8375
8376
8377
8378!------------------------------------------------------------------------------!
8379! Description:
8380! ------------
8381!> Determines whether two faces are oriented towards each other. Since the
8382!> surfaces follow the gird box surfaces, it checks first whether the two surfaces
8383!> are directed in the same direction, then it checks if the two surfaces are
8384!> located in confronted direction but facing away from each other, e.g. <--| |-->
8385!------------------------------------------------------------------------------!
8386    PURE LOGICAL FUNCTION surface_facing(x, y, z, d, x2, y2, z2, d2)
8387        IMPLICIT NONE
8388        INTEGER(iwp),   INTENT(in)  :: x, y, z, d, x2, y2, z2, d2
8389     
8390        surface_facing = .FALSE.
8391
8392!-- first check: are the two surfaces directed in the same direction
8393        IF ( (d==iup_u  .OR.  d==iup_l )                             &
8394             .AND. (d2==iup_u  .OR. d2==iup_l) ) RETURN
8395        IF ( (d==isouth_u  .OR.  d==isouth_l ) &
8396             .AND.  (d2==isouth_u  .OR.  d2==isouth_l) ) RETURN
8397        IF ( (d==inorth_u  .OR.  d==inorth_l ) &
8398             .AND.  (d2==inorth_u  .OR.  d2==inorth_l) ) RETURN
8399        IF ( (d==iwest_u  .OR.  d==iwest_l )     &
8400             .AND.  (d2==iwest_u  .OR.  d2==iwest_l ) ) RETURN
8401        IF ( (d==ieast_u  .OR.  d==ieast_l )     &
8402             .AND.  (d2==ieast_u  .OR.  d2==ieast_l ) ) RETURN
8403
8404!-- second check: are surfaces facing away from each other
8405        SELECT CASE (d)
8406            CASE (iup_u, iup_l)                     !< upward facing surfaces
8407                IF ( z2 < z ) RETURN
8408            CASE (isouth_u, isouth_l)               !< southward facing surfaces
8409                IF ( y2 > y ) RETURN
8410            CASE (inorth_u, inorth_l)               !< northward facing surfaces
8411                IF ( y2 < y ) RETURN
8412            CASE (iwest_u, iwest_l)                 !< westward facing surfaces
8413                IF ( x2 > x ) RETURN
8414            CASE (ieast_u, ieast_l)                 !< eastward facing surfaces
8415                IF ( x2 < x ) RETURN
8416        END SELECT
8417
8418        SELECT CASE (d2)
8419            CASE (iup_u)                            !< ground, roof
8420                IF ( z < z2 ) RETURN
8421            CASE (isouth_u, isouth_l)               !< south facing
8422                IF ( y > y2 ) RETURN
8423            CASE (inorth_u, inorth_l)               !< north facing
8424                IF ( y < y2 ) RETURN
8425            CASE (iwest_u, iwest_l)                 !< west facing
8426                IF ( x > x2 ) RETURN
8427            CASE (ieast_u, ieast_l)                 !< east facing
8428                IF ( x < x2 ) RETURN
8429            CASE (-1)
8430                CONTINUE
8431        END SELECT
8432
8433        surface_facing = .TRUE.
8434       
8435    END FUNCTION surface_facing
8436
8437
8438!------------------------------------------------------------------------------!
8439!
8440! Description:
8441! ------------
8442!> Reads svf, svfsurf, csf, csfsurf and mrt factors data from saved file
8443!> SVF means sky view factors and CSF means canopy sink factors
8444!------------------------------------------------------------------------------!
8445    SUBROUTINE radiation_read_svf
8446
8447       IMPLICIT NONE
8448       
8449       CHARACTER(rad_version_len)   :: rad_version_field
8450       
8451       INTEGER(iwp)                 :: i
8452       INTEGER(iwp)                 :: ndsidir_from_file = 0
8453       INTEGER(iwp)                 :: npcbl_from_file = 0
8454       INTEGER(iwp)                 :: nsurfl_from_file = 0
8455       INTEGER(iwp)                 :: nmrtbl_from_file = 0
8456
8457
8458       CALL location_message( 'reading view factors for radiation interaction', 'start' )
8459
8460       DO  i = 0, io_blocks-1
8461          IF ( i == io_group )  THEN
8462
8463!
8464!--          numprocs_previous_run is only known in case of reading restart
8465!--          data. If a new initial run which reads svf data is started the
8466!--          following query will be skipped
8467             IF ( initializing_actions == 'read_restart_data' ) THEN
8468
8469                IF ( numprocs_previous_run /= numprocs ) THEN
8470                   WRITE( message_string, * ) 'A different number of ',        &
8471                                              'processors between the run ',   &
8472                                              'that has written the svf data ',&
8473                                              'and the one that will read it ',&
8474                                              'is not allowed' 
8475                   CALL message( 'check_open', 'PA0491', 1, 2, 0, 6, 0 )
8476                ENDIF
8477
8478             ENDIF
8479             
8480!
8481!--          Open binary file
8482             CALL check_open( 88 )
8483
8484!
8485!--          read and check version
8486             READ ( 88 ) rad_version_field
8487             IF ( TRIM(rad_version_field) /= TRIM(rad_version) )  THEN
8488                 WRITE( message_string, * ) 'Version of binary SVF file "',    &
8489                             TRIM(rad_version_field), '" does not match ',     &
8490                             'the version of model "', TRIM(rad_version), '"'
8491                 CALL message( 'radiation_read_svf', 'PA0482', 1, 2, 0, 6, 0 )
8492             ENDIF
8493             
8494!
8495!--          read nsvfl, ncsfl, nsurfl, nmrtf
8496             READ ( 88 ) nsvfl, ncsfl, nsurfl_from_file, npcbl_from_file,      &
8497                         ndsidir_from_file, nmrtbl_from_file, nmrtf
8498             
8499             IF ( nsvfl < 0  .OR.  ncsfl < 0 )  THEN
8500                 WRITE( message_string, * ) 'Wrong number of SVF or CSF'
8501                 CALL message( 'radiation_read_svf', 'PA0483', 1, 2, 0, 6, 0 )
8502             ELSE
8503                 WRITE(debug_string,*)   'Number of SVF, CSF, and nsurfl ',    &
8504                                         'to read', nsvfl, ncsfl,              &
8505                                         nsurfl_from_file
8506                 IF ( debug_output )  CALL debug_message( debug_string, 'info' )
8507             ENDIF
8508             
8509             IF ( nsurfl_from_file /= nsurfl )  THEN
8510                 WRITE( message_string, * ) 'nsurfl from SVF file does not ',  &
8511                                            'match calculated nsurfl from ',   &
8512                                            'radiation_interaction_init'
8513                 CALL message( 'radiation_read_svf', 'PA0490', 1, 2, 0, 6, 0 )
8514             ENDIF
8515             
8516             IF ( npcbl_from_file /= npcbl )  THEN
8517                 WRITE( message_string, * ) 'npcbl from SVF file does not ',   &
8518                                            'match calculated npcbl from ',    &
8519                                            'radiation_interaction_init'
8520                 CALL message( 'radiation_read_svf', 'PA0493', 1, 2, 0, 6, 0 )
8521             ENDIF
8522             
8523             IF ( ndsidir_from_file /= ndsidir )  THEN
8524                 WRITE( message_string, * ) 'ndsidir from SVF file does not ', &
8525                                            'match calculated ndsidir from ',  &
8526                                            'radiation_presimulate_solar_pos'
8527                 CALL message( 'radiation_read_svf', 'PA0494', 1, 2, 0, 6, 0 )
8528             ENDIF
8529             IF ( nmrtbl_from_file /= nmrtbl )  THEN
8530                 WRITE( message_string, * ) 'nmrtbl from SVF file does not ',  &
8531                                            'match calculated nmrtbl from ',   &
8532                                            'radiation_interaction_init'
8533                 CALL message( 'radiation_read_svf', 'PA0494', 1, 2, 0, 6, 0 )
8534             ELSE
8535                 WRITE(debug_string,*) 'Number of nmrtf to read ', nmrtf
8536                 IF ( debug_output )  CALL debug_message( debug_string, 'info' )
8537             ENDIF
8538             
8539!
8540!--          Arrays skyvf, skyvft, dsitrans and dsitransc are allready
8541!--          allocated in radiation_interaction_init and
8542!--          radiation_presimulate_solar_pos
8543             IF ( nsurfl > 0 )  THEN
8544                READ(88) skyvf
8545                READ(88) skyvft
8546                READ(88) dsitrans 
8547             ENDIF
8548             
8549             IF ( plant_canopy  .AND.  npcbl > 0 ) THEN
8550                READ ( 88 )  dsitransc
8551             ENDIF
8552             
8553!
8554!--          The allocation of svf, svfsurf, csf, csfsurf, mrtf, mrtft, and
8555!--          mrtfsurf happens in routine radiation_calc_svf which is not
8556!--          called if the program enters radiation_read_svf. Therefore
8557!--          these arrays has to allocate in the following
8558             IF ( nsvfl > 0 )  THEN
8559                ALLOCATE( svf(ndsvf,nsvfl) )
8560                ALLOCATE( svfsurf(idsvf,nsvfl) )
8561                READ(88) svf
8562                READ(88) svfsurf
8563             ENDIF
8564
8565             IF ( plant_canopy  .AND.  ncsfl > 0 )  THEN
8566                ALLOCATE( csf(ndcsf,ncsfl) )
8567                ALLOCATE( csfsurf(idcsf,ncsfl) )
8568                READ(88) csf
8569                READ(88) csfsurf
8570             ENDIF
8571
8572             IF ( nmrtbl > 0 )  THEN
8573                READ(88) mrtsky
8574                READ(88) mrtskyt
8575                READ(88) mrtdsit
8576             ENDIF
8577
8578             IF ( nmrtf > 0 )  THEN
8579                ALLOCATE ( mrtf(nmrtf) )
8580                ALLOCATE ( mrtft(nmrtf) )
8581                ALLOCATE ( mrtfsurf(2,nmrtf) )
8582                READ(88) mrtf
8583                READ(88) mrtft
8584                READ(88) mrtfsurf
8585             ENDIF
8586             
8587!
8588!--          Close binary file                 
8589             CALL close_file( 88 )
8590               
8591          ENDIF
8592#if defined( __parallel )
8593          CALL MPI_BARRIER( comm2d, ierr )
8594#endif
8595       ENDDO
8596
8597       CALL location_message( 'reading view factors for radiation interaction', 'finished' )
8598
8599
8600    END SUBROUTINE radiation_read_svf
8601
8602
8603!------------------------------------------------------------------------------!
8604!
8605! Description:
8606! ------------
8607!> Subroutine stores svf, svfsurf, csf, csfsurf and mrt data to a file.
8608!------------------------------------------------------------------------------!
8609    SUBROUTINE radiation_write_svf
8610
8611       IMPLICIT NONE
8612       
8613       INTEGER(iwp)        :: i
8614
8615
8616       CALL location_message( 'writing view factors for radiation interaction', 'start' )
8617
8618       DO  i = 0, io_blocks-1
8619          IF ( i == io_group )  THEN
8620!
8621!--          Open binary file
8622             CALL check_open( 89 )
8623
8624             WRITE ( 89 )  rad_version
8625             WRITE ( 89 )  nsvfl, ncsfl, nsurfl, npcbl, ndsidir, nmrtbl, nmrtf
8626             IF ( nsurfl > 0 ) THEN
8627                WRITE ( 89 )  skyvf
8628                WRITE ( 89 )  skyvft
8629                WRITE ( 89 )  dsitrans
8630             ENDIF
8631             IF ( npcbl > 0 ) THEN
8632                WRITE ( 89 )  dsitransc
8633             ENDIF
8634             IF ( nsvfl > 0 ) THEN
8635                WRITE ( 89 )  svf
8636                WRITE ( 89 )  svfsurf
8637             ENDIF
8638             IF ( plant_canopy  .AND.  ncsfl > 0 )  THEN
8639                 WRITE ( 89 )  csf
8640                 WRITE ( 89 )  csfsurf
8641             ENDIF
8642             IF ( nmrtbl > 0 )  THEN
8643                WRITE ( 89 ) mrtsky
8644                WRITE ( 89 ) mrtskyt
8645                WRITE ( 89 ) mrtdsit
8646             ENDIF
8647             IF ( nmrtf > 0 )  THEN
8648                 WRITE ( 89 )  mrtf
8649                 WRITE ( 89 )  mrtft               
8650                 WRITE ( 89 )  mrtfsurf
8651             ENDIF
8652!
8653!--          Close binary file                 
8654             CALL close_file( 89 )
8655
8656          ENDIF
8657#if defined( __parallel )
8658          CALL MPI_BARRIER( comm2d, ierr )
8659#endif
8660       ENDDO
8661
8662       CALL location_message( 'writing view factors for radiation interaction', 'finished' )
8663
8664
8665    END SUBROUTINE radiation_write_svf
8666
8667
8668!------------------------------------------------------------------------------!
8669!
8670! Description:
8671! ------------
8672!> Block of auxiliary subroutines:
8673!> 1. quicksort and corresponding comparison
8674!> 2. merge_and_grow_csf for implementation of "dynamical growing"
8675!>    array for csf
8676!------------------------------------------------------------------------------!
8677!-- quicksort.f -*-f90-*-
8678!-- Author: t-nissie, adaptation J.Resler
8679!-- License: GPLv3
8680!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8681    RECURSIVE SUBROUTINE quicksort_itarget(itarget, vffrac, ztransp, first, last)
8682        IMPLICIT NONE
8683        INTEGER(iwp), DIMENSION(:), INTENT(INOUT)   :: itarget
8684        REAL(wp), DIMENSION(:), INTENT(INOUT)       :: vffrac, ztransp
8685        INTEGER(iwp), INTENT(IN)                    :: first, last
8686        INTEGER(iwp)                                :: x, t
8687        INTEGER(iwp)                                :: i, j
8688        REAL(wp)                                    :: tr
8689
8690        IF ( first>=last ) RETURN
8691        x = itarget((first+last)/2)
8692        i = first
8693        j = last
8694        DO
8695            DO WHILE ( itarget(i) < x )
8696               i=i+1
8697            ENDDO
8698            DO WHILE ( x < itarget(j) )
8699                j=j-1
8700            ENDDO
8701            IF ( i >= j ) EXIT
8702            t = itarget(i);  itarget(i) = itarget(j);  itarget(j) = t
8703            tr = vffrac(i);  vffrac(i) = vffrac(j);  vffrac(j) = tr
8704            tr = ztransp(i);  ztransp(i) = ztransp(j);  ztransp(j) = tr
8705            i=i+1
8706            j=j-1
8707        ENDDO
8708        IF ( first < i-1 ) CALL quicksort_itarget(itarget, vffrac, ztransp, first, i-1)
8709        IF ( j+1 < last )  CALL quicksort_itarget(itarget, vffrac, ztransp, j+1, last)
8710    END SUBROUTINE quicksort_itarget
8711
8712    PURE FUNCTION svf_lt(svf1,svf2) result (res)
8713      TYPE (t_svf), INTENT(in) :: svf1,svf2
8714      LOGICAL                  :: res
8715      IF ( svf1%isurflt < svf2%isurflt  .OR.    &
8716          (svf1%isurflt == svf2%isurflt  .AND.  svf1%isurfs < svf2%isurfs) )  THEN
8717          res = .TRUE.
8718      ELSE
8719          res = .FALSE.
8720      ENDIF
8721    END FUNCTION svf_lt
8722
8723
8724!-- quicksort.f -*-f90-*-
8725!-- Author: t-nissie, adaptation J.Resler
8726!-- License: GPLv3
8727!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8728    RECURSIVE SUBROUTINE quicksort_svf(svfl, first, last)
8729        IMPLICIT NONE
8730        TYPE(t_svf), DIMENSION(:), INTENT(INOUT)  :: svfl
8731        INTEGER(iwp), INTENT(IN)                  :: first, last
8732        TYPE(t_svf)                               :: x, t
8733        INTEGER(iwp)                              :: i, j
8734
8735        IF ( first>=last ) RETURN
8736        x = svfl( (first+last) / 2 )
8737        i = first
8738        j = last
8739        DO
8740            DO while ( svf_lt(svfl(i),x) )
8741               i=i+1
8742            ENDDO
8743            DO while ( svf_lt(x,svfl(j)) )
8744                j=j-1
8745            ENDDO
8746            IF ( i >= j ) EXIT
8747            t = svfl(i);  svfl(i) = svfl(j);  svfl(j) = t
8748            i=i+1
8749            j=j-1
8750        ENDDO
8751        IF ( first < i-1 ) CALL quicksort_svf(svfl, first, i-1)
8752        IF ( j+1 < last )  CALL quicksort_svf(svfl, j+1, last)
8753    END SUBROUTINE quicksort_svf
8754
8755    PURE FUNCTION csf_lt(csf1,csf2) result (res)
8756      TYPE (t_csf), INTENT(in) :: csf1,csf2
8757      LOGICAL                  :: res
8758      IF ( csf1%ip < csf2%ip  .OR.    &
8759           (csf1%ip == csf2%ip  .AND.  csf1%itx < csf2%itx)  .OR.  &
8760           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity < csf2%ity)  .OR.  &
8761           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity == csf2%ity  .AND.   &
8762            csf1%itz < csf2%itz)  .OR.  &
8763           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity == csf2%ity  .AND.   &
8764            csf1%itz == csf2%itz  .AND.  csf1%isurfs < csf2%isurfs) )  THEN
8765          res = .TRUE.
8766      ELSE
8767          res = .FALSE.
8768      ENDIF
8769    END FUNCTION csf_lt
8770
8771
8772!-- quicksort.f -*-f90-*-
8773!-- Author: t-nissie, adaptation J.Resler
8774!-- License: GPLv3
8775!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8776    RECURSIVE SUBROUTINE quicksort_csf(csfl, first, last)
8777        IMPLICIT NONE
8778        TYPE(t_csf), DIMENSION(:), INTENT(INOUT)  :: csfl
8779        INTEGER(iwp), INTENT(IN)                  :: first, last
8780        TYPE(t_csf)                               :: x, t
8781        INTEGER(iwp)                              :: i, j
8782
8783        IF ( first>=last ) RETURN
8784        x = csfl( (first+last)/2 )
8785        i = first
8786        j = last
8787        DO
8788            DO while ( csf_lt(csfl(i),x) )
8789                i=i+1
8790            ENDDO
8791            DO while ( csf_lt(x,csfl(j)) )
8792                j=j-1
8793            ENDDO
8794            IF ( i >= j ) EXIT
8795            t = csfl(i);  csfl(i) = csfl(j);  csfl(j) = t
8796            i=i+1
8797            j=j-1
8798        ENDDO
8799        IF ( first < i-1 ) CALL quicksort_csf(csfl, first, i-1)
8800        IF ( j+1 < last )  CALL quicksort_csf(csfl, j+1, last)
8801    END SUBROUTINE quicksort_csf
8802
8803   
8804!------------------------------------------------------------------------------!
8805!
8806! Description:
8807! ------------
8808!> Grows the CSF array exponentially after it is full. During that, the ray
8809!> canopy sink factors with common source face and target plant canopy grid
8810!> cell are merged together so that the size doesn't grow out of control.
8811!------------------------------------------------------------------------------!
8812    SUBROUTINE merge_and_grow_csf(newsize)
8813        INTEGER(iwp), INTENT(in)                :: newsize  !< new array size after grow, must be >= ncsfl
8814                                                            !< or -1 to shrink to minimum
8815        INTEGER(iwp)                            :: iread, iwrite
8816        TYPE(t_csf), DIMENSION(:), POINTER      :: acsfnew
8817
8818
8819        IF ( newsize == -1 )  THEN
8820!--         merge in-place
8821            acsfnew => acsf
8822        ELSE
8823!--         allocate new array
8824            IF ( mcsf == 0 )  THEN
8825                ALLOCATE( acsf1(newsize) )
8826                acsfnew => acsf1
8827            ELSE
8828                ALLOCATE( acsf2(newsize) )
8829                acsfnew => acsf2
8830            ENDIF
8831        ENDIF
8832
8833        IF ( ncsfl >= 1 )  THEN
8834!--         sort csf in place (quicksort)
8835            CALL quicksort_csf(acsf,1,ncsfl)
8836
8837!--         while moving to a new array, aggregate canopy sink factor records with identical box & source
8838            acsfnew(1) = acsf(1)
8839            iwrite = 1
8840            DO iread = 2, ncsfl
8841!--             here acsf(kcsf) already has values from acsf(icsf)
8842                IF ( acsfnew(iwrite)%itx == acsf(iread)%itx &
8843                         .AND.  acsfnew(iwrite)%ity == acsf(iread)%ity &
8844                         .AND.  acsfnew(iwrite)%itz == acsf(iread)%itz &
8845                         .AND.  acsfnew(iwrite)%isurfs == acsf(iread)%isurfs )  THEN
8846
8847                    acsfnew(iwrite)%rcvf = acsfnew(iwrite)%rcvf + acsf(iread)%rcvf
8848!--                 advance reading index, keep writing index
8849                ELSE
8850!--                 not identical, just advance and copy
8851                    iwrite = iwrite + 1
8852                    acsfnew(iwrite) = acsf(iread)
8853                ENDIF
8854            ENDDO
8855            ncsfl = iwrite
8856        ENDIF
8857
8858        IF ( newsize == -1 )  THEN
8859!--         allocate new array and copy shrinked data
8860            IF ( mcsf == 0 )  THEN
8861                ALLOCATE( acsf1(ncsfl) )
8862                acsf1(1:ncsfl) = acsf2(1:ncsfl)
8863            ELSE
8864                ALLOCATE( acsf2(ncsfl) )
8865                acsf2(1:ncsfl) = acsf1(1:ncsfl)
8866            ENDIF
8867        ENDIF
8868
8869!--     deallocate old array
8870        IF ( mcsf == 0 )  THEN
8871            mcsf = 1
8872            acsf => acsf1
8873            DEALLOCATE( acsf2 )
8874        ELSE
8875            mcsf = 0
8876            acsf => acsf2
8877            DEALLOCATE( acsf1 )
8878        ENDIF
8879        ncsfla = newsize
8880
8881        IF ( debug_output )  THEN
8882           WRITE( debug_string, '(A,2I12)' ) 'Grow acsf2:', ncsfl, ncsfla
8883           CALL debug_message( debug_string, 'info' )
8884        ENDIF
8885
8886    END SUBROUTINE merge_and_grow_csf
8887
8888   
8889!-- quicksort.f -*-f90-*-
8890!-- Author: t-nissie, adaptation J.Resler
8891!-- License: GPLv3
8892!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8893    RECURSIVE SUBROUTINE quicksort_csf2(kpcsflt, pcsflt, first, last)
8894        IMPLICIT NONE
8895        INTEGER(iwp), DIMENSION(:,:), INTENT(INOUT)  :: kpcsflt
8896        REAL(wp), DIMENSION(:,:), INTENT(INOUT)      :: pcsflt
8897        INTEGER(iwp), INTENT(IN)                     :: first, last
8898        REAL(wp), DIMENSION(ndcsf)                   :: t2
8899        INTEGER(iwp), DIMENSION(kdcsf)               :: x, t1
8900        INTEGER(iwp)                                 :: i, j
8901
8902        IF ( first>=last ) RETURN
8903        x = kpcsflt(:, (first+last)/2 )
8904        i = first
8905        j = last
8906        DO
8907            DO while ( csf_lt2(kpcsflt(:,i),x) )
8908                i=i+1
8909            ENDDO
8910            DO while ( csf_lt2(x,kpcsflt(:,j)) )
8911                j=j-1
8912            ENDDO
8913            IF ( i >= j ) EXIT
8914            t1 = kpcsflt(:,i);  kpcsflt(:,i) = kpcsflt(:,j);  kpcsflt(:,j) = t1
8915            t2 = pcsflt(:,i);  pcsflt(:,i) = pcsflt(:,j);  pcsflt(:,j) = t2
8916            i=i+1
8917            j=j-1
8918        ENDDO
8919        IF ( first < i-1 ) CALL quicksort_csf2(kpcsflt, pcsflt, first, i-1)
8920        IF ( j+1 < last )  CALL quicksort_csf2(kpcsflt, pcsflt, j+1, last)
8921    END SUBROUTINE quicksort_csf2
8922   
8923
8924    PURE FUNCTION csf_lt2(item1, item2) result(res)
8925        INTEGER(iwp), DIMENSION(kdcsf), INTENT(in)  :: item1, item2
8926        LOGICAL                                     :: res
8927        res = ( (item1(3) < item2(3))                                                        &
8928             .OR.  (item1(3) == item2(3)  .AND.  item1(2) < item2(2))                            &
8929             .OR.  (item1(3) == item2(3)  .AND.  item1(2) == item2(2)  .AND.  item1(1) < item2(1)) &
8930             .OR.  (item1(3) == item2(3)  .AND.  item1(2) == item2(2)  .AND.  item1(1) == item2(1) &
8931                 .AND.  item1(4) < item2(4)) )
8932    END FUNCTION csf_lt2
8933
8934    PURE FUNCTION searchsorted(athresh, val) result(ind)
8935        REAL(wp), DIMENSION(:), INTENT(IN)  :: athresh
8936        REAL(wp), INTENT(IN)                :: val
8937        INTEGER(iwp)                        :: ind
8938        INTEGER(iwp)                        :: i
8939
8940        DO i = LBOUND(athresh, 1), UBOUND(athresh, 1)
8941            IF ( val < athresh(i) ) THEN
8942                ind = i - 1
8943                RETURN
8944            ENDIF
8945        ENDDO
8946        ind = UBOUND(athresh, 1)
8947    END FUNCTION searchsorted
8948
8949
8950!------------------------------------------------------------------------------!
8951!
8952! Description:
8953! ------------
8954!> Subroutine for averaging 3D data
8955!------------------------------------------------------------------------------!
8956SUBROUTINE radiation_3d_data_averaging( mode, variable )
8957 
8958
8959    USE control_parameters
8960
8961    USE indices
8962
8963    USE kinds
8964
8965    IMPLICIT NONE
8966
8967    CHARACTER (LEN=*) ::  mode    !<
8968    CHARACTER (LEN=*) :: variable !<
8969
8970    LOGICAL      ::  match_lsm !< flag indicating natural-type surface
8971    LOGICAL      ::  match_usm !< flag indicating urban-type surface
8972   
8973    INTEGER(iwp) ::  i !<
8974    INTEGER(iwp) ::  j !<
8975    INTEGER(iwp) ::  k !<
8976    INTEGER(iwp) ::  l, m !< index of current surface element
8977
8978    INTEGER(iwp)                                       :: ids, idsint_u, idsint_l, isurf
8979    CHARACTER(LEN=varnamelength)                       :: var
8980
8981!-- find the real name of the variable
8982    ids = -1
8983    l = -1
8984    var = TRIM(variable)
8985    DO i = 0, nd-1
8986        k = len(TRIM(var))
8987        j = len(TRIM(dirname(i)))
8988        IF ( k-j+1 >= 1_iwp ) THEN
8989           IF ( TRIM(var(k-j+1:k)) == TRIM(dirname(i)) )  THEN
8990               ids = i
8991               idsint_u = dirint_u(ids)
8992               idsint_l = dirint_l(ids)
8993               var = var(:k-j)
8994               EXIT
8995           ENDIF
8996        ENDIF
8997    ENDDO
8998    IF ( ids == -1 )  THEN
8999        var = TRIM(variable)
9000    ENDIF
9001
9002    IF ( mode == 'allocate' )  THEN
9003
9004       SELECT CASE ( TRIM( var ) )
9005!--          block of large scale (e.g. RRTMG) radiation output variables
9006             CASE ( 'rad_net*' )
9007                IF ( .NOT. ALLOCATED( rad_net_av ) )  THEN
9008                   ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
9009                ENDIF
9010                rad_net_av = 0.0_wp
9011             
9012             CASE ( 'rad_lw_in*' )
9013                IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) )  THEN
9014                   ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
9015                ENDIF
9016                rad_lw_in_xy_av = 0.0_wp
9017               
9018             CASE ( 'rad_lw_out*' )
9019                IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) )  THEN
9020                   ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
9021                ENDIF
9022                rad_lw_out_xy_av = 0.0_wp
9023               
9024             CASE ( 'rad_sw_in*' )
9025                IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) )  THEN
9026                   ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
9027                ENDIF
9028                rad_sw_in_xy_av = 0.0_wp
9029               
9030             CASE ( 'rad_sw_out*' )
9031                IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) )  THEN
9032                   ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
9033                ENDIF
9034                rad_sw_out_xy_av = 0.0_wp               
9035
9036             CASE ( 'rad_lw_in' )
9037                IF ( .NOT. ALLOCATED( rad_lw_in_av ) )  THEN
9038                   ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9039                ENDIF
9040                rad_lw_in_av = 0.0_wp
9041
9042             CASE ( 'rad_lw_out' )
9043                IF ( .NOT. ALLOCATED( rad_lw_out_av ) )  THEN
9044                   ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9045                ENDIF
9046                rad_lw_out_av = 0.0_wp
9047
9048             CASE ( 'rad_lw_cs_hr' )
9049                IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) )  THEN
9050                   ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9051                ENDIF
9052                rad_lw_cs_hr_av = 0.0_wp
9053
9054             CASE ( 'rad_lw_hr' )
9055                IF ( .NOT. ALLOCATED( rad_lw_hr_av ) )  THEN
9056                   ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9057                ENDIF
9058                rad_lw_hr_av = 0.0_wp
9059
9060             CASE ( 'rad_sw_in' )
9061                IF ( .NOT. ALLOCATED( rad_sw_in_av ) )  THEN
9062                   ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9063                ENDIF
9064                rad_sw_in_av = 0.0_wp
9065
9066             CASE ( 'rad_sw_out' )
9067                IF ( .NOT. ALLOCATED( rad_sw_out_av ) )  THEN
9068                   ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9069                ENDIF
9070                rad_sw_out_av = 0.0_wp
9071
9072             CASE ( 'rad_sw_cs_hr' )
9073                IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) )  THEN
9074                   ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9075                ENDIF
9076                rad_sw_cs_hr_av = 0.0_wp
9077
9078             CASE ( 'rad_sw_hr' )
9079                IF ( .NOT. ALLOCATED( rad_sw_hr_av ) )  THEN
9080                   ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9081                ENDIF
9082                rad_sw_hr_av = 0.0_wp
9083
9084!--          block of RTM output variables
9085             CASE ( 'rtm_rad_net' )
9086!--              array of complete radiation balance
9087                 IF ( .NOT.  ALLOCATED(surfradnet_av) )  THEN
9088                     ALLOCATE( surfradnet_av(nsurfl) )
9089                     surfradnet_av = 0.0_wp
9090                 ENDIF
9091
9092             CASE ( 'rtm_rad_insw' )
9093!--                 array of sw radiation falling to surface after i-th reflection
9094                 IF ( .NOT.  ALLOCATED(surfinsw_av) )  THEN
9095                     ALLOCATE( surfinsw_av(nsurfl) )
9096                     surfinsw_av = 0.0_wp
9097                 ENDIF
9098
9099             CASE ( 'rtm_rad_inlw' )
9100!--                 array of lw radiation falling to surface after i-th reflection
9101                 IF ( .NOT.  ALLOCATED(surfinlw_av) )  THEN
9102                     ALLOCATE( surfinlw_av(nsurfl) )
9103                     surfinlw_av = 0.0_wp
9104                 ENDIF
9105
9106             CASE ( 'rtm_rad_inswdir' )
9107!--                 array of direct sw radiation falling to surface from sun
9108                 IF ( .NOT.  ALLOCATED(surfinswdir_av) )  THEN
9109                     ALLOCATE( surfinswdir_av(nsurfl) )
9110                     surfinswdir_av = 0.0_wp
9111                 ENDIF
9112
9113             CASE ( 'rtm_rad_inswdif' )
9114!--                 array of difusion sw radiation falling to surface from sky and borders of the domain
9115                 IF ( .NOT.  ALLOCATED(surfinswdif_av) )  THEN
9116                     ALLOCATE( surfinswdif_av(nsurfl) )
9117                     surfinswdif_av = 0.0_wp
9118                 ENDIF
9119
9120             CASE ( 'rtm_rad_inswref' )
9121!--                 array of sw radiation falling to surface from reflections
9122                 IF ( .NOT.  ALLOCATED(surfinswref_av) )  THEN
9123                     ALLOCATE( surfinswref_av(nsurfl) )
9124                     surfinswref_av = 0.0_wp
9125                 ENDIF
9126
9127             CASE ( 'rtm_rad_inlwdif' )
9128!--                 array of sw radiation falling to surface after i-th reflection
9129                IF ( .NOT.  ALLOCATED(surfinlwdif_av) )  THEN
9130                     ALLOCATE( surfinlwdif_av(nsurfl) )
9131                     surfinlwdif_av = 0.0_wp
9132                 ENDIF
9133
9134             CASE ( 'rtm_rad_inlwref' )
9135!--                 array of lw radiation falling to surface from reflections
9136                 IF ( .NOT.  ALLOCATED(surfinlwref_av) )  THEN
9137                     ALLOCATE( surfinlwref_av(nsurfl) )
9138                     surfinlwref_av = 0.0_wp
9139                 ENDIF
9140
9141             CASE ( 'rtm_rad_outsw' )
9142!--                 array of sw radiation emitted from surface after i-th reflection
9143                 IF ( .NOT.  ALLOCATED(surfoutsw_av) )  THEN
9144                     ALLOCATE( surfoutsw_av(nsurfl) )
9145                     surfoutsw_av = 0.0_wp
9146                 ENDIF
9147
9148             CASE ( 'rtm_rad_outlw' )
9149!--                 array of lw radiation emitted from surface after i-th reflection
9150                 IF ( .NOT.  ALLOCATED(surfoutlw_av) )  THEN
9151                     ALLOCATE( surfoutlw_av(nsurfl) )
9152                     surfoutlw_av = 0.0_wp
9153                 ENDIF
9154             CASE ( 'rtm_rad_ressw' )
9155!--                 array of residua of sw radiation absorbed in surface after last reflection
9156                 IF ( .NOT.  ALLOCATED(surfins_av) )  THEN
9157                     ALLOCATE( surfins_av(nsurfl) )
9158                     surfins_av = 0.0_wp
9159                 ENDIF
9160
9161             CASE ( 'rtm_rad_reslw' )
9162!--                 array of residua of lw radiation absorbed in surface after last reflection
9163                 IF ( .NOT.  ALLOCATED(surfinl_av) )  THEN
9164                     ALLOCATE( surfinl_av(nsurfl) )
9165                     surfinl_av = 0.0_wp
9166                 ENDIF
9167
9168             CASE ( 'rtm_rad_pc_inlw' )
9169!--                 array of of lw radiation absorbed in plant canopy
9170                 IF ( .NOT.  ALLOCATED(pcbinlw_av) )  THEN
9171                     ALLOCATE( pcbinlw_av(1:npcbl) )
9172                     pcbinlw_av = 0.0_wp
9173                 ENDIF
9174
9175             CASE ( 'rtm_rad_pc_insw' )
9176!--                 array of of sw radiation absorbed in plant canopy
9177                 IF ( .NOT.  ALLOCATED(pcbinsw_av) )  THEN
9178                     ALLOCATE( pcbinsw_av(1:npcbl) )
9179                     pcbinsw_av = 0.0_wp
9180                 ENDIF
9181
9182             CASE ( 'rtm_rad_pc_inswdir' )
9183!--                 array of of direct sw radiation absorbed in plant canopy
9184                 IF ( .NOT.  ALLOCATED(pcbinswdir_av) )  THEN
9185                     ALLOCATE( pcbinswdir_av(1:npcbl) )
9186                     pcbinswdir_av = 0.0_wp
9187                 ENDIF
9188
9189             CASE ( 'rtm_rad_pc_inswdif' )
9190!--                 array of of diffuse sw radiation absorbed in plant canopy
9191                 IF ( .NOT.  ALLOCATED(pcbinswdif_av) )  THEN
9192                     ALLOCATE( pcbinswdif_av(1:npcbl) )
9193                     pcbinswdif_av = 0.0_wp
9194                 ENDIF
9195
9196             CASE ( 'rtm_rad_pc_inswref' )
9197!--                 array of of reflected sw radiation absorbed in plant canopy
9198                 IF ( .NOT.  ALLOCATED(pcbinswref_av) )  THEN
9199                     ALLOCATE( pcbinswref_av(1:npcbl) )
9200                     pcbinswref_av = 0.0_wp
9201                 ENDIF
9202
9203             CASE ( 'rtm_mrt_sw' )
9204                IF ( .NOT. ALLOCATED( mrtinsw_av ) )  THEN
9205                   ALLOCATE( mrtinsw_av(nmrtbl) )
9206                ENDIF
9207                mrtinsw_av = 0.0_wp
9208
9209             CASE ( 'rtm_mrt_lw' )
9210                IF ( .NOT. ALLOCATED( mrtinlw_av ) )  THEN
9211                   ALLOCATE( mrtinlw_av(nmrtbl) )
9212                ENDIF
9213                mrtinlw_av = 0.0_wp
9214
9215             CASE ( 'rtm_mrt' )
9216                IF ( .NOT. ALLOCATED( mrt_av ) )  THEN
9217                   ALLOCATE( mrt_av(nmrtbl) )
9218                ENDIF
9219                mrt_av = 0.0_wp
9220
9221          CASE DEFAULT
9222             CONTINUE
9223
9224       END SELECT
9225
9226    ELSEIF ( mode == 'sum' )  THEN
9227
9228       SELECT CASE ( TRIM( var ) )
9229!--       block of large scale (e.g. RRTMG) radiation output variables
9230          CASE ( 'rad_net*' )
9231             IF ( ALLOCATED( rad_net_av ) ) THEN
9232                DO  i = nxl, nxr
9233                   DO  j = nys, nyn
9234                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9235                                  surf_lsm_h%end_index(j,i)
9236                      match_usm = surf_usm_h%start_index(j,i) <=               &
9237                                  surf_usm_h%end_index(j,i)
9238
9239                     IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9240                         m = surf_lsm_h%end_index(j,i)
9241                         rad_net_av(j,i) = rad_net_av(j,i) +                   &
9242                                         surf_lsm_h%rad_net(m)
9243                      ELSEIF ( match_usm )  THEN
9244                         m = surf_usm_h%end_index(j,i)
9245                         rad_net_av(j,i) = rad_net_av(j,i) +                   &
9246                                         surf_usm_h%rad_net(m)
9247                      ENDIF
9248                   ENDDO
9249                ENDDO
9250             ENDIF
9251
9252          CASE ( 'rad_lw_in*' )
9253             IF ( ALLOCATED( rad_lw_in_xy_av ) ) THEN
9254                DO  i = nxl, nxr
9255                   DO  j = nys, nyn
9256                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9257                                  surf_lsm_h%end_index(j,i)
9258                      match_usm = surf_usm_h%start_index(j,i) <=               &
9259                                  surf_usm_h%end_index(j,i)
9260
9261                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9262                         m = surf_lsm_h%end_index(j,i)
9263                         rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i) +         &
9264                                         surf_lsm_h%rad_lw_in(m)
9265                      ELSEIF ( match_usm )  THEN
9266                         m = surf_usm_h%end_index(j,i)
9267                         rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i) +         &
9268                                         surf_usm_h%rad_lw_in(m)
9269                      ENDIF
9270                   ENDDO
9271                ENDDO
9272             ENDIF
9273             
9274          CASE ( 'rad_lw_out*' )
9275             IF ( ALLOCATED( rad_lw_out_xy_av ) ) THEN
9276                DO  i = nxl, nxr
9277                   DO  j = nys, nyn
9278                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9279                                  surf_lsm_h%end_index(j,i)
9280                      match_usm = surf_usm_h%start_index(j,i) <=               &
9281                                  surf_usm_h%end_index(j,i)
9282
9283                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9284                         m = surf_lsm_h%end_index(j,i)
9285                         rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i) +       &
9286                                                 surf_lsm_h%rad_lw_out(m)
9287                      ELSEIF ( match_usm )  THEN
9288                         m = surf_usm_h%end_index(j,i)
9289                         rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i) +       &
9290                                                 surf_usm_h%rad_lw_out(m)
9291                      ENDIF
9292                   ENDDO
9293                ENDDO
9294             ENDIF
9295             
9296          CASE ( 'rad_sw_in*' )
9297             IF ( ALLOCATED( rad_sw_in_xy_av ) ) THEN
9298                DO  i = nxl, nxr
9299                   DO  j = nys, nyn
9300                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9301                                  surf_lsm_h%end_index(j,i)
9302                      match_usm = surf_usm_h%start_index(j,i) <=               &
9303                                  surf_usm_h%end_index(j,i)
9304
9305                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9306                         m = surf_lsm_h%end_index(j,i)
9307                         rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i) +         &
9308                                                surf_lsm_h%rad_sw_in(m)
9309                      ELSEIF ( match_usm )  THEN
9310                         m = surf_usm_h%end_index(j,i)
9311                         rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i) +         &
9312                                                surf_usm_h%rad_sw_in(m)
9313                      ENDIF
9314                   ENDDO
9315                ENDDO
9316             ENDIF
9317             
9318          CASE ( 'rad_sw_out*' )
9319             IF ( ALLOCATED( rad_sw_out_xy_av ) ) THEN
9320                DO  i = nxl, nxr
9321                   DO  j = nys, nyn
9322                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9323                                  surf_lsm_h%end_index(j,i)
9324                      match_usm = surf_usm_h%start_index(j,i) <=               &
9325                                  surf_usm_h%end_index(j,i)
9326
9327                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9328                         m = surf_lsm_h%end_index(j,i)
9329                         rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i) +       &
9330                                                 surf_lsm_h%rad_sw_out(m)
9331                      ELSEIF ( match_usm )  THEN
9332                         m = surf_usm_h%end_index(j,i)
9333                         rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i) +       &
9334                                                 surf_usm_h%rad_sw_out(m)
9335                      ENDIF
9336                   ENDDO
9337                ENDDO
9338             ENDIF
9339             
9340          CASE ( 'rad_lw_in' )
9341             IF ( ALLOCATED( rad_lw_in_av ) ) THEN
9342                DO  i = nxlg, nxrg
9343                   DO  j = nysg, nyng
9344                      DO  k = nzb, nzt+1
9345                         rad_lw_in_av(k,j,i) = rad_lw_in_av(k,j,i)             &
9346                                               + rad_lw_in(k,j,i)
9347                      ENDDO
9348                   ENDDO
9349                ENDDO
9350             ENDIF
9351
9352          CASE ( 'rad_lw_out' )
9353             IF ( ALLOCATED( rad_lw_out_av ) ) THEN
9354                DO  i = nxlg, nxrg
9355                   DO  j = nysg, nyng
9356                      DO  k = nzb, nzt+1
9357                         rad_lw_out_av(k,j,i) = rad_lw_out_av(k,j,i)           &
9358                                                + rad_lw_out(k,j,i)
9359                      ENDDO
9360                   ENDDO
9361                ENDDO
9362             ENDIF
9363
9364          CASE ( 'rad_lw_cs_hr' )
9365             IF ( ALLOCATED( rad_lw_cs_hr_av ) ) THEN
9366                DO  i = nxlg, nxrg
9367                   DO  j = nysg, nyng
9368                      DO  k = nzb, nzt+1
9369                         rad_lw_cs_hr_av(k,j,i) = rad_lw_cs_hr_av(k,j,i)       &
9370                                                  + rad_lw_cs_hr(k,j,i)
9371                      ENDDO
9372                   ENDDO
9373                ENDDO
9374             ENDIF
9375
9376          CASE ( 'rad_lw_hr' )
9377             IF ( ALLOCATED( rad_lw_hr_av ) ) THEN
9378                DO  i = nxlg, nxrg
9379                   DO  j = nysg, nyng
9380                      DO  k = nzb, nzt+1
9381                         rad_lw_hr_av(k,j,i) = rad_lw_hr_av(k,j,i)             &
9382                                               + rad_lw_hr(k,j,i)
9383                      ENDDO
9384                   ENDDO
9385                ENDDO
9386             ENDIF
9387
9388          CASE ( 'rad_sw_in' )
9389             IF ( ALLOCATED( rad_sw_in_av ) ) THEN
9390                DO  i = nxlg, nxrg
9391                   DO  j = nysg, nyng
9392                      DO  k = nzb, nzt+1
9393                         rad_sw_in_av(k,j,i) = rad_sw_in_av(k,j,i)             &
9394                                               + rad_sw_in(k,j,i)
9395                      ENDDO
9396                   ENDDO
9397                ENDDO
9398             ENDIF
9399
9400          CASE ( 'rad_sw_out' )
9401             IF ( ALLOCATED( rad_sw_out_av ) ) THEN
9402                DO  i = nxlg, nxrg
9403                   DO  j = nysg, nyng
9404                      DO  k = nzb, nzt+1
9405                         rad_sw_out_av(k,j,i) = rad_sw_out_av(k,j,i)           &
9406                                                + rad_sw_out(k,j,i)
9407                      ENDDO
9408                   ENDDO
9409                ENDDO
9410             ENDIF
9411
9412          CASE ( 'rad_sw_cs_hr' )
9413             IF ( ALLOCATED( rad_sw_cs_hr_av ) ) THEN
9414                DO  i = nxlg, nxrg
9415                   DO  j = nysg, nyng
9416                      DO  k = nzb, nzt+1
9417                         rad_sw_cs_hr_av(k,j,i) = rad_sw_cs_hr_av(k,j,i)       &
9418                                                  + rad_sw_cs_hr(k,j,i)
9419                      ENDDO
9420                   ENDDO
9421                ENDDO
9422             ENDIF
9423
9424          CASE ( 'rad_sw_hr' )
9425             IF ( ALLOCATED( rad_sw_hr_av ) ) THEN
9426                DO  i = nxlg, nxrg
9427                   DO  j = nysg, nyng
9428                      DO  k = nzb, nzt+1
9429                         rad_sw_hr_av(k,j,i) = rad_sw_hr_av(k,j,i)             &
9430                                               + rad_sw_hr(k,j,i)
9431                      ENDDO
9432                   ENDDO
9433                ENDDO
9434             ENDIF
9435
9436!--       block of RTM output variables
9437          CASE ( 'rtm_rad_net' )
9438!--           array of complete radiation balance
9439              DO isurf = dirstart(ids), dirend(ids)
9440                 IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9441                    surfradnet_av(isurf) = surfinsw(isurf) - surfoutsw(isurf) +  surfinlw(isurf) - surfoutlw(isurf)
9442                 ENDIF
9443              ENDDO
9444
9445          CASE ( 'rtm_rad_insw' )
9446!--           array of sw radiation falling to surface after i-th reflection
9447              DO isurf = dirstart(ids), dirend(ids)
9448                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9449                      surfinsw_av(isurf) = surfinsw_av(isurf) + surfinsw(isurf)
9450                  ENDIF
9451              ENDDO
9452
9453          CASE ( 'rtm_rad_inlw' )
9454!--           array of lw radiation falling to surface after i-th reflection
9455              DO isurf = dirstart(ids), dirend(ids)
9456                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9457                      surfinlw_av(isurf) = surfinlw_av(isurf) + surfinlw(isurf)
9458                  ENDIF
9459              ENDDO
9460
9461          CASE ( 'rtm_rad_inswdir' )
9462!--           array of direct sw radiation falling to surface from sun
9463              DO isurf = dirstart(ids), dirend(ids)
9464                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9465                      surfinswdir_av(isurf) = surfinswdir_av(isurf) + surfinswdir(isurf)
9466                  ENDIF
9467              ENDDO
9468
9469          CASE ( 'rtm_rad_inswdif' )
9470!--           array of difusion sw radiation falling to surface from sky and borders of the domain
9471              DO isurf = dirstart(ids), dirend(ids)
9472                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9473                      surfinswdif_av(isurf) = surfinswdif_av(isurf) + surfinswdif(isurf)
9474                  ENDIF
9475              ENDDO
9476
9477          CASE ( 'rtm_rad_inswref' )
9478!--           array of sw radiation falling to surface from reflections
9479              DO isurf = dirstart(ids), dirend(ids)
9480                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9481                      surfinswref_av(isurf) = surfinswref_av(isurf) + surfinsw(isurf) - &
9482                                          surfinswdir(isurf) - surfinswdif(isurf)
9483                  ENDIF
9484              ENDDO
9485
9486
9487          CASE ( 'rtm_rad_inlwdif' )
9488!--           array of sw radiation falling to surface after i-th reflection
9489              DO isurf = dirstart(ids), dirend(ids)
9490                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9491                      surfinlwdif_av(isurf) = surfinlwdif_av(isurf) + surfinlwdif(isurf)
9492                  ENDIF
9493              ENDDO
9494!
9495          CASE ( 'rtm_rad_inlwref' )
9496!--           array of lw radiation falling to surface from reflections
9497              DO isurf = dirstart(ids), dirend(ids)
9498                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9499                      surfinlwref_av(isurf) = surfinlwref_av(isurf) + &
9500                                          surfinlw(isurf) - surfinlwdif(isurf)
9501                  ENDIF
9502              ENDDO
9503
9504          CASE ( 'rtm_rad_outsw' )
9505!--           array of sw radiation emitted from surface after i-th reflection
9506              DO isurf = dirstart(ids), dirend(ids)
9507                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9508                      surfoutsw_av(isurf) = surfoutsw_av(isurf) + surfoutsw(isurf)
9509                  ENDIF
9510              ENDDO
9511
9512          CASE ( 'rtm_rad_outlw' )
9513!--           array of lw radiation emitted from surface after i-th reflection
9514              DO isurf = dirstart(ids), dirend(ids)
9515                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9516                      surfoutlw_av(isurf) = surfoutlw_av(isurf) + surfoutlw(isurf)
9517                  ENDIF
9518              ENDDO
9519
9520          CASE ( 'rtm_rad_ressw' )
9521!--           array of residua of sw radiation absorbed in surface after last reflection
9522              DO isurf = dirstart(ids), dirend(ids)
9523                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9524                      surfins_av(isurf) = surfins_av(isurf) + surfins(isurf)
9525                  ENDIF
9526              ENDDO
9527
9528          CASE ( 'rtm_rad_reslw' )
9529!--           array of residua of lw radiation absorbed in surface after last reflection
9530              DO isurf = dirstart(ids), dirend(ids)
9531                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9532                      surfinl_av(isurf) = surfinl_av(isurf) + surfinl(isurf)
9533                  ENDIF
9534              ENDDO
9535
9536          CASE ( 'rtm_rad_pc_inlw' )
9537              DO l = 1, npcbl
9538                 pcbinlw_av(l) = pcbinlw_av(l) + pcbinlw(l)
9539              ENDDO
9540
9541          CASE ( 'rtm_rad_pc_insw' )
9542              DO l = 1, npcbl
9543                 pcbinsw_av(l) = pcbinsw_av(l) + pcbinsw(l)
9544              ENDDO
9545
9546          CASE ( 'rtm_rad_pc_inswdir' )
9547              DO l = 1, npcbl
9548                 pcbinswdir_av(l) = pcbinswdir_av(l) + pcbinswdir(l)
9549              ENDDO
9550
9551          CASE ( 'rtm_rad_pc_inswdif' )
9552              DO l = 1, npcbl
9553                 pcbinswdif_av(l) = pcbinswdif_av(l) + pcbinswdif(l)
9554              ENDDO
9555
9556          CASE ( 'rtm_rad_pc_inswref' )
9557              DO l = 1, npcbl
9558                 pcbinswref_av(l) = pcbinswref_av(l) + pcbinsw(l) - pcbinswdir(l) - pcbinswdif(l)
9559              ENDDO
9560
9561          CASE ( 'rad_mrt_sw' )
9562             IF ( ALLOCATED( mrtinsw_av ) )  THEN
9563                mrtinsw_av(:) = mrtinsw_av(:) + mrtinsw(:)
9564             ENDIF
9565
9566          CASE ( 'rad_mrt_lw' )
9567             IF ( ALLOCATED( mrtinlw_av ) )  THEN
9568                mrtinlw_av(:) = mrtinlw_av(:) + mrtinlw(:)
9569             ENDIF
9570
9571          CASE ( 'rad_mrt' )
9572             IF ( ALLOCATED( mrt_av ) )  THEN
9573                mrt_av(:) = mrt_av(:) + mrt(:)
9574             ENDIF
9575
9576          CASE DEFAULT
9577             CONTINUE
9578
9579       END SELECT
9580
9581    ELSEIF ( mode == 'average' )  THEN
9582
9583       SELECT CASE ( TRIM( var ) )
9584!--       block of large scale (e.g. RRTMG) radiation output variables
9585          CASE ( 'rad_net*' )
9586             IF ( ALLOCATED( rad_net_av ) ) THEN
9587                DO  i = nxlg, nxrg
9588                   DO  j = nysg, nyng
9589                      rad_net_av(j,i) = rad_net_av(j,i)                        &
9590                                        / REAL( average_count_3d, KIND=wp )
9591                   ENDDO
9592                ENDDO
9593             ENDIF
9594             
9595          CASE ( 'rad_lw_in*' )
9596             IF ( ALLOCATED( rad_lw_in_xy_av ) ) THEN
9597                DO  i = nxlg, nxrg
9598                   DO  j = nysg, nyng
9599                      rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i)              &
9600                                        / REAL( average_count_3d, KIND=wp )
9601                   ENDDO
9602                ENDDO
9603             ENDIF
9604             
9605          CASE ( 'rad_lw_out*' )
9606             IF ( ALLOCATED( rad_lw_out_xy_av ) ) THEN
9607                DO  i = nxlg, nxrg
9608                   DO  j = nysg, nyng
9609                      rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i)            &
9610                                        / REAL( average_count_3d, KIND=wp )
9611                   ENDDO
9612                ENDDO
9613             ENDIF
9614             
9615          CASE ( 'rad_sw_in*' )
9616             IF ( ALLOCATED( rad_sw_in_xy_av ) ) THEN
9617                DO  i = nxlg, nxrg
9618                   DO  j = nysg, nyng
9619                      rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i)              &
9620                                        / REAL( average_count_3d, KIND=wp )
9621                   ENDDO
9622                ENDDO
9623             ENDIF
9624             
9625          CASE ( 'rad_sw_out*' )
9626             IF ( ALLOCATED( rad_sw_out_xy_av ) ) THEN
9627                DO  i = nxlg, nxrg
9628                   DO  j = nysg, nyng
9629                      rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i)             &
9630                                        / REAL( average_count_3d, KIND=wp )
9631                   ENDDO
9632                ENDDO
9633             ENDIF
9634
9635          CASE ( 'rad_lw_in' )
9636             IF ( ALLOCATED( rad_lw_in_av ) ) THEN
9637                DO  i = nxlg, nxrg
9638                   DO  j = nysg, nyng
9639                      DO  k = nzb, nzt+1
9640                         rad_lw_in_av(k,j,i) = rad_lw_in_av(k,j,i)             &
9641                                               / REAL( average_count_3d, KIND=wp )
9642                      ENDDO
9643                   ENDDO
9644                ENDDO
9645             ENDIF
9646
9647          CASE ( 'rad_lw_out' )
9648             IF ( ALLOCATED( rad_lw_out_av ) ) THEN
9649                DO  i = nxlg, nxrg
9650                   DO  j = nysg, nyng
9651                      DO  k = nzb, nzt+1
9652                         rad_lw_out_av(k,j,i) = rad_lw_out_av(k,j,i)           &
9653                                                / REAL( average_count_3d, KIND=wp )
9654                      ENDDO
9655                   ENDDO
9656                ENDDO
9657             ENDIF
9658
9659          CASE ( 'rad_lw_cs_hr' )
9660             IF ( ALLOCATED( rad_lw_cs_hr_av ) ) THEN
9661                DO  i = nxlg, nxrg
9662                   DO  j = nysg, nyng
9663                      DO  k = nzb, nzt+1
9664                         rad_lw_cs_hr_av(k,j,i) = rad_lw_cs_hr_av(k,j,i)       &
9665                                                / REAL( average_count_3d, KIND=wp )
9666                      ENDDO
9667                   ENDDO
9668                ENDDO
9669             ENDIF
9670
9671          CASE ( 'rad_lw_hr' )
9672             IF ( ALLOCATED( rad_lw_hr_av ) ) THEN
9673                DO  i = nxlg, nxrg
9674                   DO  j = nysg, nyng
9675                      DO  k = nzb, nzt+1
9676                         rad_lw_hr_av(k,j,i) = rad_lw_hr_av(k,j,i)             &
9677                                               / REAL( average_count_3d, KIND=wp )
9678                      ENDDO
9679                   ENDDO
9680                ENDDO
9681             ENDIF
9682
9683          CASE ( 'rad_sw_in' )
9684             IF ( ALLOCATED( rad_sw_in_av ) ) THEN
9685                DO  i = nxlg, nxrg
9686                   DO  j = nysg, nyng
9687                      DO  k = nzb, nzt+1
9688                         rad_sw_in_av(k,j,i) = rad_sw_in_av(k,j,i)             &
9689                                               / REAL( average_count_3d, KIND=wp )
9690                      ENDDO
9691                   ENDDO
9692                ENDDO
9693             ENDIF
9694
9695          CASE ( 'rad_sw_out' )
9696             IF ( ALLOCATED( rad_sw_out_av ) ) THEN
9697                DO  i = nxlg, nxrg
9698                   DO  j = nysg, nyng
9699                      DO  k = nzb, nzt+1
9700                         rad_sw_out_av(k,j,i) = rad_sw_out_av(k,j,i)           &
9701                                                / REAL( average_count_3d, KIND=wp )
9702                      ENDDO
9703                   ENDDO
9704                ENDDO
9705             ENDIF
9706
9707          CASE ( 'rad_sw_cs_hr' )
9708             IF ( ALLOCATED( rad_sw_cs_hr_av ) ) THEN
9709                DO  i = nxlg, nxrg
9710                   DO  j = nysg, nyng
9711                      DO  k = nzb, nzt+1
9712                         rad_sw_cs_hr_av(k,j,i) = rad_sw_cs_hr_av(k,j,i)       &
9713                                                / REAL( average_count_3d, KIND=wp )
9714                      ENDDO
9715                   ENDDO
9716                ENDDO
9717             ENDIF
9718
9719          CASE ( 'rad_sw_hr' )
9720             IF ( ALLOCATED( rad_sw_hr_av ) ) THEN
9721                DO  i = nxlg, nxrg
9722                   DO  j = nysg, nyng
9723                      DO  k = nzb, nzt+1
9724                         rad_sw_hr_av(k,j,i) = rad_sw_hr_av(k,j,i)             &
9725                                               / REAL( average_count_3d, KIND=wp )
9726                      ENDDO
9727                   ENDDO
9728                ENDDO
9729             ENDIF
9730
9731!--       block of RTM output variables
9732          CASE ( 'rtm_rad_net' )
9733!--           array of complete radiation balance
9734              DO isurf = dirstart(ids), dirend(ids)
9735                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9736                      surfradnet_av(isurf) = surfinsw_av(isurf) / REAL( average_count_3d, kind=wp )
9737                  ENDIF
9738              ENDDO
9739
9740          CASE ( 'rtm_rad_insw' )
9741!--           array of sw radiation falling to surface after i-th reflection
9742              DO isurf = dirstart(ids), dirend(ids)
9743                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9744                      surfinsw_av(isurf) = surfinsw_av(isurf) / REAL( average_count_3d, kind=wp )
9745                  ENDIF
9746              ENDDO
9747
9748          CASE ( 'rtm_rad_inlw' )
9749!--           array of lw radiation falling to surface after i-th reflection
9750              DO isurf = dirstart(ids), dirend(ids)
9751                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9752                      surfinlw_av(isurf) = surfinlw_av(isurf) / REAL( average_count_3d, kind=wp )
9753                  ENDIF
9754              ENDDO
9755
9756          CASE ( 'rtm_rad_inswdir' )
9757!--           array of direct sw radiation falling to surface from sun
9758              DO isurf = dirstart(ids), dirend(ids)
9759                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9760                      surfinswdir_av(isurf) = surfinswdir_av(isurf) / REAL( average_count_3d, kind=wp )
9761                  ENDIF
9762              ENDDO
9763
9764          CASE ( 'rtm_rad_inswdif' )
9765!--           array of difusion sw radiation falling to surface from sky and borders of the domain
9766              DO isurf = dirstart(ids), dirend(ids)
9767                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9768                      surfinswdif_av(isurf) = surfinswdif_av(isurf) / REAL( average_count_3d, kind=wp )
9769                  ENDIF
9770              ENDDO
9771
9772          CASE ( 'rtm_rad_inswref' )
9773!--           array of sw radiation falling to surface from reflections
9774              DO isurf = dirstart(ids), dirend(ids)
9775                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9776                      surfinswref_av(isurf) = surfinswref_av(isurf) / REAL( average_count_3d, kind=wp )
9777                  ENDIF
9778              ENDDO
9779
9780          CASE ( 'rtm_rad_inlwdif' )
9781!--           array of sw radiation falling to surface after i-th reflection
9782              DO isurf = dirstart(ids), dirend(ids)
9783                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9784                      surfinlwdif_av(isurf) = surfinlwdif_av(isurf) / REAL( average_count_3d, kind=wp )
9785                  ENDIF
9786              ENDDO
9787
9788          CASE ( 'rtm_rad_inlwref' )
9789!--           array of lw radiation falling to surface from reflections
9790              DO isurf = dirstart(ids), dirend(ids)
9791                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9792                      surfinlwref_av(isurf) = surfinlwref_av(isurf) / REAL( average_count_3d, kind=wp )
9793                  ENDIF
9794              ENDDO
9795
9796          CASE ( 'rtm_rad_outsw' )
9797!--           array of sw radiation emitted from surface after i-th reflection
9798              DO isurf = dirstart(ids), dirend(ids)
9799                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9800                      surfoutsw_av(isurf) = surfoutsw_av(isurf) / REAL( average_count_3d, kind=wp )
9801                  ENDIF
9802              ENDDO
9803
9804          CASE ( 'rtm_rad_outlw' )
9805!--           array of lw radiation emitted from surface after i-th reflection
9806              DO isurf = dirstart(ids), dirend(ids)
9807                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9808                      surfoutlw_av(isurf) = surfoutlw_av(isurf) / REAL( average_count_3d, kind=wp )
9809                  ENDIF
9810              ENDDO
9811
9812          CASE ( 'rtm_rad_ressw' )
9813!--           array of residua of sw radiation absorbed in surface after last reflection
9814              DO isurf = dirstart(ids), dirend(ids)
9815                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9816                      surfins_av(isurf) = surfins_av(isurf) / REAL( average_count_3d, kind=wp )
9817                  ENDIF
9818              ENDDO
9819
9820          CASE ( 'rtm_rad_reslw' )
9821!--           array of residua of lw radiation absorbed in surface after last reflection
9822              DO isurf = dirstart(ids), dirend(ids)
9823                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9824                      surfinl_av(isurf) = surfinl_av(isurf) / REAL( average_count_3d, kind=wp )
9825                  ENDIF
9826              ENDDO
9827
9828          CASE ( 'rtm_rad_pc_inlw' )
9829              DO l = 1, npcbl
9830                 pcbinlw_av(:) = pcbinlw_av(:) / REAL( average_count_3d, kind=wp )
9831              ENDDO
9832
9833          CASE ( 'rtm_rad_pc_insw' )
9834              DO l = 1, npcbl
9835                 pcbinsw_av(:) = pcbinsw_av(:) / REAL( average_count_3d, kind=wp )
9836              ENDDO
9837
9838          CASE ( 'rtm_rad_pc_inswdir' )
9839              DO l = 1, npcbl
9840                 pcbinswdir_av(:) = pcbinswdir_av(:) / REAL( average_count_3d, kind=wp )
9841              ENDDO
9842
9843          CASE ( 'rtm_rad_pc_inswdif' )
9844              DO l = 1, npcbl
9845                 pcbinswdif_av(:) = pcbinswdif_av(:) / REAL( average_count_3d, kind=wp )
9846              ENDDO
9847
9848          CASE ( 'rtm_rad_pc_inswref' )
9849              DO l = 1, npcbl
9850                 pcbinswref_av(:) = pcbinswref_av(:) / REAL( average_count_3d, kind=wp )
9851              ENDDO
9852
9853          CASE ( 'rad_mrt_lw' )
9854             IF ( ALLOCATED( mrtinlw_av ) )  THEN
9855                mrtinlw_av(:) = mrtinlw_av(:) / REAL( average_count_3d, KIND=wp )
9856             ENDIF
9857
9858          CASE ( 'rad_mrt' )
9859             IF ( ALLOCATED( mrt_av ) )  THEN
9860                mrt_av(:) = mrt_av(:) / REAL( average_count_3d, KIND=wp )
9861             ENDIF
9862
9863       END SELECT
9864
9865    ENDIF
9866
9867END SUBROUTINE radiation_3d_data_averaging
9868
9869
9870!------------------------------------------------------------------------------!
9871!
9872! Description:
9873! ------------
9874!> Subroutine defining appropriate grid for netcdf variables.
9875!> It is called out from subroutine netcdf.
9876!------------------------------------------------------------------------------!
9877SUBROUTINE radiation_define_netcdf_grid( variable, found, grid_x, grid_y, grid_z )
9878   
9879    IMPLICIT NONE
9880
9881    CHARACTER (LEN=*), INTENT(IN)  ::  variable    !<
9882    LOGICAL, INTENT(OUT)           ::  found       !<
9883    CHARACTER (LEN=*), INTENT(OUT) ::  grid_x      !<
9884    CHARACTER (LEN=*), INTENT(OUT) ::  grid_y      !<
9885    CHARACTER (LEN=*), INTENT(OUT) ::  grid_z      !<
9886
9887    CHARACTER (len=varnamelength)  :: var
9888
9889    found  = .TRUE.
9890
9891!
9892!-- Check for the grid
9893    var = TRIM(variable)
9894!-- RTM directional variables
9895    IF ( var(1:12) == 'rtm_rad_net_'  .OR.  var(1:13) == 'rtm_rad_insw_'  .OR.          &
9896         var(1:13) == 'rtm_rad_inlw_'  .OR.  var(1:16) == 'rtm_rad_inswdir_'  .OR.      &
9897         var(1:16) == 'rtm_rad_inswdif_'  .OR.  var(1:16) == 'rtm_rad_inswref_'  .OR.   &
9898         var(1:16) == 'rtm_rad_inlwdif_'  .OR.  var(1:16) == 'rtm_rad_inlwref_'  .OR.   &
9899         var(1:14) == 'rtm_rad_outsw_'  .OR.  var(1:14) == 'rtm_rad_outlw_'  .OR.       &
9900         var(1:14) == 'rtm_rad_ressw_'  .OR.  var(1:14) == 'rtm_rad_reslw_'  .OR.       &
9901         var == 'rtm_rad_pc_inlw'  .OR.                                                 &
9902         var == 'rtm_rad_pc_insw'  .OR.  var == 'rtm_rad_pc_inswdir'  .OR.              &
9903         var == 'rtm_rad_pc_inswdif'  .OR.  var == 'rtm_rad_pc_inswref'  .OR.           &
9904         var(1:7) == 'rtm_svf'  .OR.  var(1:7) == 'rtm_dif'  .OR.                       &
9905         var(1:9) == 'rtm_skyvf' .OR. var(1:10) == 'rtm_skyvft'  .OR.                   &
9906         var(1:12) == 'rtm_surfalb_'  .OR.  var(1:13) == 'rtm_surfemis_'  .OR.          &
9907         var == 'rtm_mrt'  .OR.  var ==  'rtm_mrt_sw'  .OR.  var == 'rtm_mrt_lw' )  THEN
9908
9909         found = .TRUE.
9910         grid_x = 'x'
9911         grid_y = 'y'
9912         grid_z = 'zu'
9913    ELSE
9914
9915       SELECT CASE ( TRIM( var ) )
9916
9917          CASE ( 'rad_lw_cs_hr', 'rad_lw_hr', 'rad_sw_cs_hr', 'rad_sw_hr',        &
9918                 'rad_lw_cs_hr_xy', 'rad_lw_hr_xy', 'rad_sw_cs_hr_xy',            &
9919                 'rad_sw_hr_xy', 'rad_lw_cs_hr_xz', 'rad_lw_hr_xz',               &
9920                 'rad_sw_cs_hr_xz', 'rad_sw_hr_xz', 'rad_lw_cs_hr_yz',            &
9921                 'rad_lw_hr_yz', 'rad_sw_cs_hr_yz', 'rad_sw_hr_yz',               &
9922                 'rad_mrt', 'rad_mrt_sw', 'rad_mrt_lw' )
9923             grid_x = 'x'
9924             grid_y = 'y'
9925             grid_z = 'zu'
9926
9927          CASE ( 'rad_lw_in', 'rad_lw_out', 'rad_sw_in', 'rad_sw_out',            &
9928                 'rad_lw_in_xy', 'rad_lw_out_xy', 'rad_sw_in_xy','rad_sw_out_xy', &
9929                 'rad_lw_in_xz', 'rad_lw_out_xz', 'rad_sw_in_xz','rad_sw_out_xz', &
9930                 'rad_lw_in_yz', 'rad_lw_out_yz', 'rad_sw_in_yz','rad_sw_out_yz' )
9931             grid_x = 'x'
9932             grid_y = 'y'
9933             grid_z = 'zw'
9934
9935
9936          CASE DEFAULT
9937             found  = .FALSE.
9938             grid_x = 'none'
9939             grid_y = 'none'
9940             grid_z = 'none'
9941
9942           END SELECT
9943       ENDIF
9944
9945    END SUBROUTINE radiation_define_netcdf_grid
9946
9947!------------------------------------------------------------------------------!
9948!
9949! Description:
9950! ------------
9951!> Subroutine defining 2D output variables
9952!------------------------------------------------------------------------------!
9953 SUBROUTINE radiation_data_output_2d( av, variable, found, grid, mode,         &
9954                                      local_pf, two_d, nzb_do, nzt_do )
9955 
9956    USE indices
9957
9958    USE kinds
9959
9960
9961    IMPLICIT NONE
9962
9963    CHARACTER (LEN=*) ::  grid     !<
9964    CHARACTER (LEN=*) ::  mode     !<
9965    CHARACTER (LEN=*) ::  variable !<
9966
9967    INTEGER(iwp) ::  av !<
9968    INTEGER(iwp) ::  i  !<
9969    INTEGER(iwp) ::  j  !<
9970    INTEGER(iwp) ::  k  !<
9971    INTEGER(iwp) ::  m  !< index of surface element at grid point (j,i)
9972    INTEGER(iwp) ::  nzb_do   !<
9973    INTEGER(iwp) ::  nzt_do   !<
9974
9975    LOGICAL      ::  found !<
9976    LOGICAL      ::  two_d !< flag parameter that indicates 2D variables (horizontal cross sections)
9977
9978    REAL(wp) ::  fill_value = -999.0_wp    !< value for the _FillValue attribute
9979
9980    REAL(wp), DIMENSION(nxl:nxr,nys:nyn,nzb_do:nzt_do) ::  local_pf !<
9981
9982    found = .TRUE.
9983
9984    SELECT CASE ( TRIM( variable ) )
9985
9986       CASE ( 'rad_net*_xy' )        ! 2d-array
9987          IF ( av == 0 ) THEN
9988             DO  i = nxl, nxr
9989                DO  j = nys, nyn
9990!
9991!--                Obtain rad_net from its respective surface type
9992!--                Natural-type surfaces
9993                   DO  m = surf_lsm_h%start_index(j,i),                        &
9994                           surf_lsm_h%end_index(j,i) 
9995                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_net(m)
9996                   ENDDO
9997!
9998!--                Urban-type surfaces
9999                   DO  m = surf_usm_h%start_index(j,i),                        &
10000                           surf_usm_h%end_index(j,i) 
10001                      local_pf(i,j,nzb+1) = surf_usm_h%rad_net(m)
10002                   ENDDO
10003                ENDDO
10004             ENDDO
10005          ELSE
10006             IF ( .NOT. ALLOCATED( rad_net_av ) ) THEN
10007                ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
10008                rad_net_av = REAL( fill_value, KIND = wp )
10009             ENDIF
10010             DO  i = nxl, nxr
10011                DO  j = nys, nyn 
10012                   local_pf(i,j,nzb+1) = rad_net_av(j,i)
10013                ENDDO
10014             ENDDO
10015          ENDIF
10016          two_d = .TRUE.
10017          grid = 'zu1'
10018         
10019       CASE ( 'rad_lw_in*_xy' )        ! 2d-array
10020          IF ( av == 0 ) THEN
10021             DO  i = nxl, nxr
10022                DO  j = nys, nyn
10023!
10024!--                Obtain rad_net from its respective surface type
10025!--                Natural-type surfaces
10026                   DO  m = surf_lsm_h%start_index(j,i),                        &
10027                           surf_lsm_h%end_index(j,i) 
10028                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_lw_in(m)
10029                   ENDDO
10030!
10031!--                Urban-type surfaces
10032                   DO  m = surf_usm_h%start_index(j,i),                        &
10033                           surf_usm_h%end_index(j,i) 
10034                      local_pf(i,j,nzb+1) = surf_usm_h%rad_lw_in(m)
10035                   ENDDO
10036                ENDDO
10037             ENDDO
10038          ELSE
10039             IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) ) THEN
10040                ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
10041                rad_lw_in_xy_av = REAL( fill_value, KIND = wp )
10042             ENDIF
10043             DO  i = nxl, nxr
10044                DO  j = nys, nyn 
10045                   local_pf(i,j,nzb+1) = rad_lw_in_xy_av(j,i)
10046                ENDDO
10047             ENDDO
10048          ENDIF
10049          two_d = .TRUE.
10050          grid = 'zu1'
10051         
10052       CASE ( 'rad_lw_out*_xy' )        ! 2d-array
10053          IF ( av == 0 ) THEN
10054             DO  i = nxl, nxr
10055                DO  j = nys, nyn
10056!
10057!--                Obtain rad_net from its respective surface type
10058!--                Natural-type surfaces
10059                   DO  m = surf_lsm_h%start_index(j,i),                        &
10060                           surf_lsm_h%end_index(j,i) 
10061                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_lw_out(m)
10062                   ENDDO
10063!
10064!--                Urban-type surfaces
10065                   DO  m = surf_usm_h%start_index(j,i),                        &
10066                           surf_usm_h%end_index(j,i) 
10067                      local_pf(i,j,nzb+1) = surf_usm_h%rad_lw_out(m)
10068                   ENDDO
10069                ENDDO
10070             ENDDO
10071          ELSE
10072             IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) ) THEN
10073                ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
10074                rad_lw_out_xy_av = REAL( fill_value, KIND = wp )
10075             ENDIF
10076             DO  i = nxl, nxr
10077                DO  j = nys, nyn 
10078                   local_pf(i,j,nzb+1) = rad_lw_out_xy_av(j,i)
10079                ENDDO
10080             ENDDO
10081          ENDIF
10082          two_d = .TRUE.
10083          grid = 'zu1'
10084         
10085       CASE ( 'rad_sw_in*_xy' )        ! 2d-array
10086          IF ( av == 0 ) THEN
10087             DO  i = nxl, nxr
10088                DO  j = nys, nyn
10089!
10090!--                Obtain rad_net from its respective surface type
10091!--                Natural-type surfaces
10092                   DO  m = surf_lsm_h%start_index(j,i),                        &
10093                           surf_lsm_h%end_index(j,i) 
10094                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_sw_in(m)
10095                   ENDDO
10096!
10097!--                Urban-type surfaces
10098                   DO  m = surf_usm_h%start_index(j,i),                        &
10099                           surf_usm_h%end_index(j,i) 
10100                      local_pf(i,j,nzb+1) = surf_usm_h%rad_sw_in(m)
10101                   ENDDO
10102                ENDDO
10103             ENDDO
10104          ELSE
10105             IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) ) THEN
10106                ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
10107                rad_sw_in_xy_av = REAL( fill_value, KIND = wp )
10108             ENDIF
10109             DO  i = nxl, nxr
10110                DO  j = nys, nyn 
10111                   local_pf(i,j,nzb+1) = rad_sw_in_xy_av(j,i)
10112                ENDDO
10113             ENDDO
10114          ENDIF
10115          two_d = .TRUE.
10116          grid = 'zu1'
10117         
10118       CASE ( 'rad_sw_out*_xy' )        ! 2d-array
10119          IF ( av == 0 ) THEN
10120             DO  i = nxl, nxr
10121                DO  j = nys, nyn
10122!
10123!--                Obtain rad_net from its respective surface type
10124!--                Natural-type surfaces
10125                   DO  m = surf_lsm_h%start_index(j,i),                        &
10126                           surf_lsm_h%end_index(j,i) 
10127                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_sw_out(m)
10128                   ENDDO
10129!
10130!--                Urban-type surfaces
10131                   DO  m = surf_usm_h%start_index(j,i),                        &
10132                           surf_usm_h%end_index(j,i) 
10133                      local_pf(i,j,nzb+1) = surf_usm_h%rad_sw_out(m)
10134                   ENDDO
10135                ENDDO
10136             ENDDO
10137          ELSE
10138             IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) ) THEN
10139                ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
10140                rad_sw_out_xy_av = REAL( fill_value, KIND = wp )
10141             ENDIF
10142             DO  i = nxl, nxr
10143                DO  j = nys, nyn 
10144                   local_pf(i,j,nzb+1) = rad_sw_out_xy_av(j,i)
10145                ENDDO
10146             ENDDO
10147          ENDIF
10148          two_d = .TRUE.
10149          grid = 'zu1'         
10150         
10151       CASE ( 'rad_lw_in_xy', 'rad_lw_in_xz', 'rad_lw_in_yz' )
10152          IF ( av == 0 ) THEN
10153             DO  i = nxl, nxr
10154                DO  j = nys, nyn
10155                   DO  k = nzb_do, nzt_do
10156                      local_pf(i,j,k) = rad_lw_in(k,j,i)
10157                   ENDDO
10158                ENDDO
10159             ENDDO
10160          ELSE
10161            IF ( .NOT. ALLOCATED( rad_lw_in_av ) ) THEN
10162               ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10163               rad_lw_in_av = REAL( fill_value, KIND = wp )
10164            ENDIF
10165             DO  i = nxl, nxr
10166                DO  j = nys, nyn 
10167                   DO  k = nzb_do, nzt_do
10168                      local_pf(i,j,k) = rad_lw_in_av(k,j,i)
10169                   ENDDO
10170                ENDDO
10171             ENDDO
10172          ENDIF
10173          IF ( mode == 'xy' )  grid = 'zu'
10174
10175       CASE ( 'rad_lw_out_xy', 'rad_lw_out_xz', 'rad_lw_out_yz' )
10176          IF ( av == 0 ) THEN
10177             DO  i = nxl, nxr
10178                DO  j = nys, nyn
10179                   DO  k = nzb_do, nzt_do
10180                      local_pf(i,j,k) = rad_lw_out(k,j,i)
10181                   ENDDO
10182                ENDDO
10183             ENDDO
10184          ELSE
10185            IF ( .NOT. ALLOCATED( rad_lw_out_av ) ) THEN
10186               ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10187               rad_lw_out_av = REAL( fill_value, KIND = wp )
10188            ENDIF
10189             DO  i = nxl, nxr
10190                DO  j = nys, nyn 
10191                   DO  k = nzb_do, nzt_do
10192                      local_pf(i,j,k) = rad_lw_out_av(k,j,i)
10193                   ENDDO
10194                ENDDO
10195             ENDDO
10196          ENDIF   
10197          IF ( mode == 'xy' )  grid = 'zu'
10198
10199       CASE ( 'rad_lw_cs_hr_xy', 'rad_lw_cs_hr_xz', 'rad_lw_cs_hr_yz' )
10200          IF ( av == 0 ) THEN
10201             DO  i = nxl, nxr
10202                DO  j = nys, nyn
10203                   DO  k = nzb_do, nzt_do
10204                      local_pf(i,j,k) = rad_lw_cs_hr(k,j,i)
10205                   ENDDO
10206                ENDDO
10207             ENDDO
10208          ELSE
10209            IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) ) THEN
10210               ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10211               rad_lw_cs_hr_av = REAL( fill_value, KIND = wp )
10212            ENDIF
10213             DO  i = nxl, nxr
10214                DO  j = nys, nyn 
10215                   DO  k = nzb_do, nzt_do
10216                      local_pf(i,j,k) = rad_lw_cs_hr_av(k,j,i)
10217                   ENDDO
10218                ENDDO
10219             ENDDO
10220          ENDIF
10221          IF ( mode == 'xy' )  grid = 'zw'
10222
10223       CASE ( 'rad_lw_hr_xy', 'rad_lw_hr_xz', 'rad_lw_hr_yz' )
10224          IF ( av == 0 ) THEN
10225             DO  i = nxl, nxr
10226                DO  j = nys, nyn
10227                   DO  k = nzb_do, nzt_do
10228                      local_pf(i,j,k) = rad_lw_hr(k,j,i)
10229                   ENDDO
10230                ENDDO
10231             ENDDO
10232          ELSE
10233            IF ( .NOT. ALLOCATED( rad_lw_hr_av ) ) THEN
10234               ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10235               rad_lw_hr_av= REAL( fill_value, KIND = wp )
10236            ENDIF
10237             DO  i = nxl, nxr
10238                DO  j = nys, nyn 
10239                   DO  k = nzb_do, nzt_do
10240                      local_pf(i,j,k) = rad_lw_hr_av(k,j,i)
10241                   ENDDO
10242                ENDDO
10243             ENDDO
10244          ENDIF
10245          IF ( mode == 'xy' )  grid = 'zw'
10246
10247       CASE ( 'rad_sw_in_xy', 'rad_sw_in_xz', 'rad_sw_in_yz' )
10248          IF ( av == 0 ) THEN
10249             DO  i = nxl, nxr
10250                DO  j = nys, nyn
10251                   DO  k = nzb_do, nzt_do
10252                      local_pf(i,j,k) = rad_sw_in(k,j,i)
10253                   ENDDO
10254                ENDDO
10255             ENDDO
10256          ELSE
10257            IF ( .NOT. ALLOCATED( rad_sw_in_av ) ) THEN
10258               ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10259               rad_sw_in_av = REAL( fill_value, KIND = wp )
10260            ENDIF
10261             DO  i = nxl, nxr
10262                DO  j = nys, nyn 
10263                   DO  k = nzb_do, nzt_do
10264                      local_pf(i,j,k) = rad_sw_in_av(k,j,i)
10265                   ENDDO
10266                ENDDO
10267             ENDDO
10268          ENDIF
10269          IF ( mode == 'xy' )  grid = 'zu'
10270
10271       CASE ( 'rad_sw_out_xy', 'rad_sw_out_xz', 'rad_sw_out_yz' )
10272          IF ( av == 0 ) THEN
10273             DO  i = nxl, nxr
10274                DO  j = nys, nyn
10275                   DO  k = nzb_do, nzt_do
10276                      local_pf(i,j,k) = rad_sw_out(k,j,i)
10277                   ENDDO
10278                ENDDO
10279             ENDDO
10280          ELSE
10281            IF ( .NOT. ALLOCATED( rad_sw_out_av ) ) THEN
10282               ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10283               rad_sw_out_av = REAL( fill_value, KIND = wp )
10284            ENDIF
10285             DO  i = nxl, nxr
10286                DO  j = nys, nyn 
10287                   DO  k = nzb, nzt+1
10288                      local_pf(i,j,k) = rad_sw_out_av(k,j,i)
10289                   ENDDO
10290                ENDDO
10291             ENDDO
10292          ENDIF
10293          IF ( mode == 'xy' )  grid = 'zu'
10294
10295       CASE ( 'rad_sw_cs_hr_xy', 'rad_sw_cs_hr_xz', 'rad_sw_cs_hr_yz' )
10296          IF ( av == 0 ) THEN
10297             DO  i = nxl, nxr
10298                DO  j = nys, nyn
10299                   DO  k = nzb_do, nzt_do
10300                      local_pf(i,j,k) = rad_sw_cs_hr(k,j,i)
10301                   ENDDO
10302                ENDDO
10303             ENDDO
10304          ELSE
10305            IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) ) THEN
10306               ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10307               rad_sw_cs_hr_av = REAL( fill_value, KIND = wp )
10308            ENDIF
10309             DO  i = nxl, nxr
10310                DO  j = nys, nyn 
10311                   DO  k = nzb_do, nzt_do
10312                      local_pf(i,j,k) = rad_sw_cs_hr_av(k,j,i)
10313                   ENDDO
10314                ENDDO
10315             ENDDO
10316          ENDIF
10317          IF ( mode == 'xy' )  grid = 'zw'
10318
10319       CASE ( 'rad_sw_hr_xy', 'rad_sw_hr_xz', 'rad_sw_hr_yz' )
10320          IF ( av == 0 ) THEN
10321             DO  i = nxl, nxr
10322                DO  j = nys, nyn
10323                   DO  k = nzb_do, nzt_do
10324                      local_pf(i,j,k) = rad_sw_hr(k,j,i)
10325                   ENDDO
10326                ENDDO
10327             ENDDO
10328          ELSE
10329            IF ( .NOT. ALLOCATED( rad_sw_hr_av ) ) THEN
10330               ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10331               rad_sw_hr_av = REAL( fill_value, KIND = wp )
10332            ENDIF
10333             DO  i = nxl, nxr
10334                DO  j = nys, nyn 
10335                   DO  k = nzb_do, nzt_do
10336                      local_pf(i,j,k) = rad_sw_hr_av(k,j,i)
10337                   ENDDO
10338                ENDDO
10339             ENDDO
10340          ENDIF
10341          IF ( mode == 'xy' )  grid = 'zw'
10342
10343       CASE DEFAULT
10344          found = .FALSE.
10345          grid  = 'none'
10346
10347    END SELECT
10348 
10349 END SUBROUTINE radiation_data_output_2d
10350
10351
10352!------------------------------------------------------------------------------!
10353!
10354! Description:
10355! ------------
10356!> Subroutine defining 3D output variables
10357!------------------------------------------------------------------------------!
10358 SUBROUTINE radiation_data_output_3d( av, variable, found, local_pf, nzb_do, nzt_do )
10359 
10360
10361    USE indices
10362
10363    USE kinds
10364
10365
10366    IMPLICIT NONE
10367
10368    CHARACTER (LEN=*) ::  variable !<
10369
10370    INTEGER(iwp) ::  av          !<
10371    INTEGER(iwp) ::  i, j, k, l  !<
10372    INTEGER(iwp) ::  nzb_do      !<
10373    INTEGER(iwp) ::  nzt_do      !<
10374
10375    LOGICAL      ::  found       !<
10376
10377    REAL(wp)     ::  fill_value = -999.0_wp    !< value for the _FillValue attribute
10378
10379    REAL(sp), DIMENSION(nxl:nxr,nys:nyn,nzb_do:nzt_do) ::  local_pf !<
10380
10381    CHARACTER (len=varnamelength)                   :: var, surfid
10382    INTEGER(iwp)                                    :: ids,idsint_u,idsint_l,isurf,isvf,isurfs,isurflt,ipcgb
10383    INTEGER(iwp)                                    :: is, js, ks, istat
10384
10385    found = .TRUE.
10386
10387    ids = -1
10388    var = TRIM(variable)
10389    DO i = 0, nd-1
10390        k = len(TRIM(var))
10391        j = len(TRIM(dirname(i)))
10392        IF ( TRIM(var(k-j+1:k)) == TRIM(dirname(i)) )  THEN
10393            ids = i
10394            idsint_u = dirint_u(ids)
10395            idsint_l = dirint_l(ids)
10396            var = var(:k-j)
10397            EXIT
10398        ENDIF
10399    ENDDO
10400    IF ( ids == -1 )  THEN
10401        var = TRIM(variable)
10402    ENDIF
10403
10404    IF ( (var(1:8) == 'rtm_svf_'  .OR.  var(1:8) == 'rtm_dif_')  .AND.  len(TRIM(var)) >= 13 )  THEN
10405!--     svf values to particular surface
10406        surfid = var(9:)
10407        i = index(surfid,'_')
10408        j = index(surfid(i+1:),'_')
10409        READ(surfid(1:i-1),*, iostat=istat ) is
10410        IF ( istat == 0 )  THEN
10411            READ(surfid(i+1:i+j-1),*, iostat=istat ) js
10412        ENDIF
10413        IF ( istat == 0 )  THEN
10414            READ(surfid(i+j+1:),*, iostat=istat ) ks
10415        ENDIF
10416        IF ( istat == 0 )  THEN
10417            var = var(1:7)
10418        ENDIF
10419    ENDIF
10420
10421    local_pf = fill_value
10422
10423    SELECT CASE ( TRIM( var ) )
10424!--   block of large scale radiation model (e.g. RRTMG) output variables
10425      CASE ( 'rad_sw_in' )
10426         IF ( av == 0 )  THEN
10427            DO  i = nxl, nxr
10428               DO  j = nys, nyn
10429                  DO  k = nzb_do, nzt_do
10430                     local_pf(i,j,k) = rad_sw_in(k,j,i)
10431                  ENDDO
10432               ENDDO
10433            ENDDO
10434         ELSE
10435            IF ( .NOT. ALLOCATED( rad_sw_in_av ) ) THEN
10436               ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10437               rad_sw_in_av = REAL( fill_value, KIND = wp )
10438            ENDIF
10439            DO  i = nxl, nxr
10440               DO  j = nys, nyn
10441                  DO  k = nzb_do, nzt_do
10442                     local_pf(i,j,k) = rad_sw_in_av(k,j,i)
10443                  ENDDO
10444               ENDDO
10445            ENDDO
10446         ENDIF
10447
10448      CASE ( 'rad_sw_out' )
10449         IF ( av == 0 )  THEN
10450            DO  i = nxl, nxr
10451               DO  j = nys, nyn
10452                  DO  k = nzb_do, nzt_do
10453                     local_pf(i,j,k) = rad_sw_out(k,j,i)
10454                  ENDDO
10455               ENDDO
10456            ENDDO
10457         ELSE
10458            IF ( .NOT. ALLOCATED( rad_sw_out_av ) ) THEN
10459               ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10460               rad_sw_out_av = REAL( fill_value, KIND = wp )
10461            ENDIF
10462            DO  i = nxl, nxr
10463               DO  j = nys, nyn
10464                  DO  k = nzb_do, nzt_do
10465                     local_pf(i,j,k) = rad_sw_out_av(k,j,i)
10466                  ENDDO
10467               ENDDO
10468            ENDDO
10469         ENDIF
10470
10471      CASE ( 'rad_sw_cs_hr' )
10472         IF ( av == 0 )  THEN
10473            DO  i = nxl, nxr
10474               DO  j = nys, nyn
10475                  DO  k = nzb_do, nzt_do
10476                     local_pf(i,j,k) = rad_sw_cs_hr(k,j,i)
10477                  ENDDO
10478               ENDDO
10479            ENDDO
10480         ELSE
10481            IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) ) THEN
10482               ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10483               rad_sw_cs_hr_av = REAL( fill_value, KIND = wp )
10484            ENDIF
10485            DO  i = nxl, nxr
10486               DO  j = nys, nyn
10487                  DO  k = nzb_do, nzt_do
10488                     local_pf(i,j,k) = rad_sw_cs_hr_av(k,j,i)
10489                  ENDDO
10490               ENDDO
10491            ENDDO
10492         ENDIF
10493
10494      CASE ( 'rad_sw_hr' )
10495         IF ( av == 0 )  THEN
10496            DO  i = nxl, nxr
10497               DO  j = nys, nyn
10498                  DO  k = nzb_do, nzt_do
10499                     local_pf(i,j,k) = rad_sw_hr(k,j,i)
10500                  ENDDO
10501               ENDDO
10502            ENDDO
10503         ELSE
10504            IF ( .NOT. ALLOCATED( rad_sw_hr_av ) ) THEN
10505               ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10506               rad_sw_hr_av = REAL( fill_value, KIND = wp )
10507            ENDIF
10508            DO  i = nxl, nxr
10509               DO  j = nys, nyn
10510                  DO  k = nzb_do, nzt_do
10511                     local_pf(i,j,k) = rad_sw_hr_av(k,j,i)
10512                  ENDDO
10513               ENDDO
10514            ENDDO
10515         ENDIF
10516
10517      CASE ( 'rad_lw_in' )
10518         IF ( av == 0 )  THEN
10519            DO  i = nxl, nxr
10520               DO  j = nys, nyn
10521                  DO  k = nzb_do, nzt_do
10522                     local_pf(i,j,k) = rad_lw_in(k,j,i)
10523                  ENDDO
10524               ENDDO
10525            ENDDO
10526         ELSE
10527            IF ( .NOT. ALLOCATED( rad_lw_in_av ) ) THEN
10528               ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10529               rad_lw_in_av = REAL( fill_value, KIND = wp )
10530            ENDIF
10531            DO  i = nxl, nxr
10532               DO  j = nys, nyn
10533                  DO  k = nzb_do, nzt_do
10534                     local_pf(i,j,k) = rad_lw_in_av(k,j,i)
10535                  ENDDO
10536               ENDDO
10537            ENDDO
10538         ENDIF
10539
10540      CASE ( 'rad_lw_out' )
10541         IF ( av == 0 )  THEN
10542            DO  i = nxl, nxr
10543               DO  j = nys, nyn
10544                  DO  k = nzb_do, nzt_do
10545                     local_pf(i,j,k) = rad_lw_out(k,j,i)
10546                  ENDDO
10547               ENDDO
10548            ENDDO
10549         ELSE
10550            IF ( .NOT. ALLOCATED( rad_lw_out_av ) ) THEN
10551               ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10552               rad_lw_out_av = REAL( fill_value, KIND = wp )
10553            ENDIF
10554            DO  i = nxl, nxr
10555               DO  j = nys, nyn
10556                  DO  k = nzb_do, nzt_do
10557                     local_pf(i,j,k) = rad_lw_out_av(k,j,i)
10558                  ENDDO
10559               ENDDO
10560            ENDDO
10561         ENDIF
10562
10563      CASE ( 'rad_lw_cs_hr' )
10564         IF ( av == 0 )  THEN
10565            DO  i = nxl, nxr
10566               DO  j = nys, nyn
10567                  DO  k = nzb_do, nzt_do
10568                     local_pf(i,j,k) = rad_lw_cs_hr(k,j,i)
10569                  ENDDO
10570               ENDDO
10571            ENDDO
10572         ELSE
10573            IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) ) THEN
10574               ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10575               rad_lw_cs_hr_av = REAL( fill_value, KIND = wp )
10576            ENDIF
10577            DO  i = nxl, nxr
10578               DO  j = nys, nyn
10579                  DO  k = nzb_do, nzt_do
10580                     local_pf(i,j,k) = rad_lw_cs_hr_av(k,j,i)
10581                  ENDDO
10582               ENDDO
10583            ENDDO
10584         ENDIF
10585
10586      CASE ( 'rad_lw_hr' )
10587         IF ( av == 0 )  THEN
10588            DO  i = nxl, nxr
10589               DO  j = nys, nyn
10590                  DO  k = nzb_do, nzt_do
10591                     local_pf(i,j,k) = rad_lw_hr(k,j,i)
10592                  ENDDO
10593               ENDDO
10594            ENDDO
10595         ELSE
10596            IF ( .NOT. ALLOCATED( rad_lw_hr_av ) ) THEN
10597               ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10598              rad_lw_hr_av = REAL( fill_value, KIND = wp )
10599            ENDIF
10600            DO  i = nxl, nxr
10601               DO  j = nys, nyn
10602                  DO  k = nzb_do, nzt_do
10603                     local_pf(i,j,k) = rad_lw_hr_av(k,j,i)
10604                  ENDDO
10605               ENDDO
10606            ENDDO
10607         ENDIF
10608
10609      CASE ( 'rtm_rad_net' )
10610!--     array of complete radiation balance
10611         DO isurf = dirstart(ids), dirend(ids)
10612            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10613               IF ( av == 0 )  THEN
10614                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = &
10615                         surfinsw(isurf) - surfoutsw(isurf) +  surfinlw(isurf) - surfoutlw(isurf)
10616               ELSE
10617                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfradnet_av(isurf)
10618               ENDIF
10619            ENDIF
10620         ENDDO
10621
10622      CASE ( 'rtm_rad_insw' )
10623!--      array of sw radiation falling to surface after i-th reflection
10624         DO isurf = dirstart(ids), dirend(ids)
10625            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10626               IF ( av == 0 )  THEN
10627                 local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinsw(isurf)
10628               ELSE
10629                 local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinsw_av(isurf)
10630               ENDIF
10631            ENDIF
10632         ENDDO
10633
10634      CASE ( 'rtm_rad_inlw' )
10635!--      array of lw radiation falling to surface after i-th reflection
10636         DO isurf = dirstart(ids), dirend(ids)
10637            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10638               IF ( av == 0 )  THEN
10639                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlw(isurf)
10640               ELSE
10641                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlw_av(isurf)
10642               ENDIF
10643             ENDIF
10644         ENDDO
10645
10646      CASE ( 'rtm_rad_inswdir' )
10647!--      array of direct sw radiation falling to surface from sun
10648         DO isurf = dirstart(ids), dirend(ids)
10649            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10650               IF ( av == 0 )  THEN
10651                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdir(isurf)
10652               ELSE
10653                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdir_av(isurf)
10654               ENDIF
10655            ENDIF
10656         ENDDO
10657
10658      CASE ( 'rtm_rad_inswdif' )
10659!--      array of difusion sw radiation falling to surface from sky and borders of the domain
10660         DO isurf = dirstart(ids), dirend(ids)
10661            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10662               IF ( av == 0 )  THEN
10663                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdif(isurf)
10664               ELSE
10665                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdif_av(isurf)
10666               ENDIF
10667            ENDIF
10668         ENDDO
10669
10670      CASE ( 'rtm_rad_inswref' )
10671!--      array of sw radiation falling to surface from reflections
10672         DO isurf = dirstart(ids), dirend(ids)
10673            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10674               IF ( av == 0 )  THEN
10675                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = &
10676                    surfinsw(isurf) - surfinswdir(isurf) - surfinswdif(isurf)
10677               ELSE
10678                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswref_av(isurf)
10679               ENDIF
10680            ENDIF
10681         ENDDO
10682
10683      CASE ( 'rtm_rad_inlwdif' )
10684!--      array of difusion lw radiation falling to surface from sky and borders of the domain
10685         DO isurf = dirstart(ids), dirend(ids)
10686            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10687               IF ( av == 0 )  THEN
10688                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlwdif(isurf)
10689               ELSE
10690                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlwdif_av(isurf)
10691               ENDIF
10692            ENDIF
10693         ENDDO
10694
10695      CASE ( 'rtm_rad_inlwref' )
10696!--      array of lw radiation falling to surface from reflections
10697         DO isurf = dirstart(ids), dirend(ids)
10698            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10699               IF ( av == 0 )  THEN
10700                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlw(isurf) - surfinlwdif(isurf)
10701               ELSE
10702                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlwref_av(isurf)
10703               ENDIF
10704            ENDIF
10705         ENDDO
10706
10707      CASE ( 'rtm_rad_outsw' )
10708!--      array of sw radiation emitted from surface after i-th reflection
10709         DO isurf = dirstart(ids), dirend(ids)
10710            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10711               IF ( av == 0 )  THEN
10712                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutsw(isurf)
10713               ELSE
10714                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutsw_av(isurf)
10715               ENDIF
10716            ENDIF
10717         ENDDO
10718
10719      CASE ( 'rtm_rad_outlw' )
10720!--      array of lw radiation emitted from surface after i-th reflection
10721         DO isurf = dirstart(ids), dirend(ids)
10722            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10723               IF ( av == 0 )  THEN
10724                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutlw(isurf)
10725               ELSE
10726                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutlw_av(isurf)
10727               ENDIF
10728            ENDIF
10729         ENDDO
10730
10731      CASE ( 'rtm_rad_ressw' )
10732!--      average of array of residua of sw radiation absorbed in surface after last reflection
10733         DO isurf = dirstart(ids), dirend(ids)
10734            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10735               IF ( av == 0 )  THEN
10736                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfins(isurf)
10737               ELSE
10738                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfins_av(isurf)
10739               ENDIF
10740            ENDIF
10741         ENDDO
10742
10743      CASE ( 'rtm_rad_reslw' )
10744!--      average of array of residua of lw radiation absorbed in surface after last reflection
10745         DO isurf = dirstart(ids), dirend(ids)
10746            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10747               IF ( av == 0 )  THEN
10748                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinl(isurf)
10749               ELSE
10750                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinl_av(isurf)
10751               ENDIF
10752            ENDIF
10753         ENDDO
10754
10755      CASE ( 'rtm_rad_pc_inlw' )
10756!--      array of lw radiation absorbed by plant canopy
10757         DO ipcgb = 1, npcbl
10758            IF ( av == 0 )  THEN
10759               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinlw(ipcgb)
10760            ELSE
10761               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinlw_av(ipcgb)
10762            ENDIF
10763         ENDDO
10764
10765      CASE ( 'rtm_rad_pc_insw' )
10766!--      array of sw radiation absorbed by plant canopy
10767         DO ipcgb = 1, npcbl
10768            IF ( av == 0 )  THEN
10769              local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinsw(ipcgb)
10770            ELSE
10771              local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinsw_av(ipcgb)
10772            ENDIF
10773         ENDDO
10774
10775      CASE ( 'rtm_rad_pc_inswdir' )
10776!--      array of direct sw radiation absorbed by plant canopy
10777         DO ipcgb = 1, npcbl
10778            IF ( av == 0 )  THEN
10779               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdir(ipcgb)
10780            ELSE
10781               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdir_av(ipcgb)
10782            ENDIF
10783         ENDDO
10784
10785      CASE ( 'rtm_rad_pc_inswdif' )
10786!--      array of diffuse sw radiation absorbed by plant canopy
10787         DO ipcgb = 1, npcbl
10788            IF ( av == 0 )  THEN
10789               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdif(ipcgb)
10790            ELSE
10791               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdif_av(ipcgb)
10792            ENDIF
10793         ENDDO
10794
10795      CASE ( 'rtm_rad_pc_inswref' )
10796!--      array of reflected sw radiation absorbed by plant canopy
10797         DO ipcgb = 1, npcbl
10798            IF ( av == 0 )  THEN
10799               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = &
10800                                    pcbinsw(ipcgb) - pcbinswdir(ipcgb) - pcbinswdif(ipcgb)
10801            ELSE
10802               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswref_av(ipcgb)
10803            ENDIF
10804         ENDDO
10805
10806      CASE ( 'rtm_mrt_sw' )
10807         local_pf = REAL( fill_value, KIND = wp )
10808         IF ( av == 0 )  THEN
10809            DO  l = 1, nmrtbl
10810               local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinsw(l)
10811            ENDDO
10812         ELSE
10813            IF ( ALLOCATED( mrtinsw_av ) ) THEN
10814               DO  l = 1, nmrtbl
10815                  local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinsw_av(l)
10816               ENDDO
10817            ENDIF
10818         ENDIF
10819
10820      CASE ( 'rtm_mrt_lw' )
10821         local_pf = REAL( fill_value, KIND = wp )
10822         IF ( av == 0 )  THEN
10823            DO  l = 1, nmrtbl
10824               local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinlw(l)
10825            ENDDO
10826         ELSE
10827            IF ( ALLOCATED( mrtinlw_av ) ) THEN
10828               DO  l = 1, nmrtbl
10829                  local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinlw_av(l)
10830               ENDDO
10831            ENDIF
10832         ENDIF
10833
10834      CASE ( 'rtm_mrt' )
10835         local_pf = REAL( fill_value, KIND = wp )
10836         IF ( av == 0 )  THEN
10837            DO  l = 1, nmrtbl
10838               local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrt(l)
10839            ENDDO
10840         ELSE
10841            IF ( ALLOCATED( mrt_av ) ) THEN
10842               DO  l = 1, nmrtbl
10843                  local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrt_av(l)
10844               ENDDO
10845            ENDIF
10846         ENDIF
10847!         
10848!--   block of RTM output variables
10849!--   variables are intended mainly for debugging and detailed analyse purposes
10850      CASE ( 'rtm_skyvf' )
10851!     
10852!--      sky view factor
10853         DO isurf = dirstart(ids), dirend(ids)
10854            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10855               local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = skyvf(isurf)
10856            ENDIF
10857         ENDDO
10858
10859      CASE ( 'rtm_skyvft' )
10860!
10861!--      sky view factor
10862         DO isurf = dirstart(ids), dirend(ids)
10863            IF ( surfl(id,isurf) == ids )  THEN
10864               local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = skyvft(isurf)
10865            ENDIF
10866         ENDDO
10867
10868      CASE ( 'rtm_svf', 'rtm_dif' )
10869!
10870!--      shape view factors or iradiance factors to selected surface
10871         IF ( TRIM(var)=='rtm_svf' )  THEN
10872             k = 1
10873         ELSE
10874             k = 2
10875         ENDIF
10876         DO isvf = 1, nsvfl
10877            isurflt = svfsurf(1, isvf)
10878            isurfs = svfsurf(2, isvf)
10879
10880            IF ( surf(ix,isurfs) == is  .AND.  surf(iy,isurfs) == js  .AND. surf(iz,isurfs) == ks  .AND. &
10881                 (surf(id,isurfs) == idsint_u .OR. surfl(id,isurfs) == idsint_l ) ) THEN
10882!
10883!--            correct source surface
10884               local_pf(surfl(ix,isurflt),surfl(iy,isurflt),surfl(iz,isurflt)) = svf(k,isvf)
10885            ENDIF
10886         ENDDO
10887
10888      CASE ( 'rtm_surfalb' )
10889!
10890!--      surface albedo
10891         DO isurf = dirstart(ids), dirend(ids)
10892            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10893               local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = albedo_surf(isurf)
10894            ENDIF
10895         ENDDO
10896
10897      CASE ( 'rtm_surfemis' )
10898!
10899!--      surface emissivity, weighted average
10900         DO isurf = dirstart(ids), dirend(ids)
10901            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10902               local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = emiss_surf(isurf)
10903            ENDIF
10904         ENDDO
10905
10906      CASE DEFAULT
10907         found = .FALSE.
10908
10909    END SELECT
10910
10911
10912 END SUBROUTINE radiation_data_output_3d
10913
10914!------------------------------------------------------------------------------!
10915!
10916! Description:
10917! ------------
10918!> Subroutine defining masked data output
10919!------------------------------------------------------------------------------!
10920 SUBROUTINE radiation_data_output_mask( av, variable, found, local_pf )
10921 
10922    USE control_parameters
10923       
10924    USE indices
10925   
10926    USE kinds
10927   
10928
10929    IMPLICIT NONE
10930
10931    CHARACTER (LEN=*) ::  variable   !<
10932
10933    CHARACTER(LEN=5) ::  grid        !< flag to distinquish between staggered grids
10934
10935    INTEGER(iwp) ::  av              !<
10936    INTEGER(iwp) ::  i               !<
10937    INTEGER(iwp) ::  j               !<
10938    INTEGER(iwp) ::  k               !<
10939    INTEGER(iwp) ::  topo_top_ind    !< k index of highest horizontal surface
10940
10941    LOGICAL ::  found                !< true if output array was found
10942    LOGICAL ::  resorted             !< true if array is resorted
10943
10944
10945    REAL(wp),                                                                  &
10946       DIMENSION(mask_size_l(mid,1),mask_size_l(mid,2),mask_size_l(mid,3)) ::  &
10947          local_pf   !<
10948
10949    REAL(wp), DIMENSION(:,:,:), POINTER ::  to_be_resorted  !< points to array which needs to be resorted for output
10950
10951
10952    found    = .TRUE.
10953    grid     = 's'
10954    resorted = .FALSE.
10955
10956    SELECT CASE ( TRIM( variable ) )
10957
10958
10959       CASE ( 'rad_lw_in' )
10960          IF ( av == 0 )  THEN
10961             to_be_resorted => rad_lw_in
10962          ELSE
10963             to_be_resorted => rad_lw_in_av
10964          ENDIF
10965
10966       CASE ( 'rad_lw_out' )
10967          IF ( av == 0 )  THEN
10968             to_be_resorted => rad_lw_out
10969          ELSE
10970             to_be_resorted => rad_lw_out_av
10971          ENDIF
10972
10973       CASE ( 'rad_lw_cs_hr' )
10974          IF ( av == 0 )  THEN
10975             to_be_resorted => rad_lw_cs_hr
10976          ELSE
10977             to_be_resorted => rad_lw_cs_hr_av
10978          ENDIF
10979
10980       CASE ( 'rad_lw_hr' )
10981          IF ( av == 0 )  THEN
10982             to_be_resorted => rad_lw_hr
10983          ELSE
10984             to_be_resorted => rad_lw_hr_av
10985          ENDIF
10986
10987       CASE ( 'rad_sw_in' )
10988          IF ( av == 0 )  THEN
10989             to_be_resorted => rad_sw_in
10990          ELSE
10991             to_be_resorted => rad_sw_in_av
10992          ENDIF
10993
10994       CASE ( 'rad_sw_out' )
10995          IF ( av == 0 )  THEN
10996             to_be_resorted => rad_sw_out
10997          ELSE
10998             to_be_resorted => rad_sw_out_av
10999          ENDIF
11000
11001       CASE ( 'rad_sw_cs_hr' )
11002          IF ( av == 0 )  THEN
11003             to_be_resorted => rad_sw_cs_hr
11004          ELSE
11005             to_be_resorted => rad_sw_cs_hr_av
11006          ENDIF
11007
11008       CASE ( 'rad_sw_hr' )
11009          IF ( av == 0 )  THEN
11010             to_be_resorted => rad_sw_hr
11011          ELSE
11012             to_be_resorted => rad_sw_hr_av
11013          ENDIF
11014
11015       CASE DEFAULT
11016          found = .FALSE.
11017
11018    END SELECT
11019
11020!
11021!-- Resort the array to be output, if not done above
11022    IF ( .NOT. resorted )  THEN
11023       IF ( .NOT. mask_surface(mid) )  THEN
11024!
11025!--       Default masked output
11026          DO  i = 1, mask_size_l(mid,1)
11027             DO  j = 1, mask_size_l(mid,2)
11028                DO  k = 1, mask_size_l(mid,3)
11029                   local_pf(i,j,k) =  to_be_resorted(mask_k(mid,k), &
11030                                      mask_j(mid,j),mask_i(mid,i))
11031                ENDDO
11032             ENDDO
11033          ENDDO
11034
11035       ELSE
11036!
11037!--       Terrain-following masked output
11038          DO  i = 1, mask_size_l(mid,1)
11039             DO  j = 1, mask_size_l(mid,2)
11040!
11041!--             Get k index of highest horizontal surface
11042                topo_top_ind = get_topography_top_index_ji( mask_j(mid,j), &
11043                                                            mask_i(mid,i), &
11044                                                            grid )
11045!
11046!--             Save output array
11047                DO  k = 1, mask_size_l(mid,3)
11048                   local_pf(i,j,k) = to_be_resorted(                       &
11049                                          MIN( topo_top_ind+mask_k(mid,k), &
11050                                               nzt+1 ),                    &
11051                                          mask_j(mid,j),                   &
11052                                          mask_i(mid,i)                     )
11053                ENDDO
11054             ENDDO
11055          ENDDO
11056
11057       ENDIF
11058    ENDIF
11059
11060
11061
11062 END SUBROUTINE radiation_data_output_mask
11063
11064
11065!------------------------------------------------------------------------------!
11066! Description:
11067! ------------
11068!> Subroutine writes local (subdomain) restart data
11069!------------------------------------------------------------------------------!
11070 SUBROUTINE radiation_wrd_local
11071
11072
11073    IMPLICIT NONE
11074
11075
11076    IF ( ALLOCATED( rad_net_av ) )  THEN
11077       CALL wrd_write_string( 'rad_net_av' )
11078       WRITE ( 14 )  rad_net_av
11079    ENDIF
11080   
11081    IF ( ALLOCATED( rad_lw_in_xy_av ) )  THEN
11082       CALL wrd_write_string( 'rad_lw_in_xy_av' )
11083       WRITE ( 14 )  rad_lw_in_xy_av
11084    ENDIF
11085   
11086    IF ( ALLOCATED( rad_lw_out_xy_av ) )  THEN
11087       CALL wrd_write_string( 'rad_lw_out_xy_av' )
11088       WRITE ( 14 )  rad_lw_out_xy_av
11089    ENDIF
11090   
11091    IF ( ALLOCATED( rad_sw_in_xy_av ) )  THEN
11092       CALL wrd_write_string( 'rad_sw_in_xy_av' )
11093       WRITE ( 14 )  rad_sw_in_xy_av
11094    ENDIF
11095   
11096    IF ( ALLOCATED( rad_sw_out_xy_av ) )  THEN
11097       CALL wrd_write_string( 'rad_sw_out_xy_av' )
11098       WRITE ( 14 )  rad_sw_out_xy_av
11099    ENDIF
11100
11101    IF ( ALLOCATED( rad_lw_in ) )  THEN
11102       CALL wrd_write_string( 'rad_lw_in' )
11103       WRITE ( 14 )  rad_lw_in
11104    ENDIF
11105
11106    IF ( ALLOCATED( rad_lw_in_av ) )  THEN
11107       CALL wrd_write_string( 'rad_lw_in_av' )
11108       WRITE ( 14 )  rad_lw_in_av
11109    ENDIF
11110
11111    IF ( ALLOCATED( rad_lw_out ) )  THEN
11112       CALL wrd_write_string( 'rad_lw_out' )
11113       WRITE ( 14 )  rad_lw_out
11114    ENDIF
11115
11116    IF ( ALLOCATED( rad_lw_out_av) )  THEN
11117       CALL wrd_write_string( 'rad_lw_out_av' )
11118       WRITE ( 14 )  rad_lw_out_av
11119    ENDIF
11120
11121    IF ( ALLOCATED( rad_lw_cs_hr) )  THEN
11122       CALL wrd_write_string( 'rad_lw_cs_hr' )
11123       WRITE ( 14 )  rad_lw_cs_hr
11124    ENDIF
11125
11126    IF ( ALLOCATED( rad_lw_cs_hr_av) )  THEN
11127       CALL wrd_write_string( 'rad_lw_cs_hr_av' )
11128       WRITE ( 14 )  rad_lw_cs_hr_av
11129    ENDIF
11130
11131    IF ( ALLOCATED( rad_lw_hr) )  THEN
11132       CALL wrd_write_string( 'rad_lw_hr' )
11133       WRITE ( 14 )  rad_lw_hr
11134    ENDIF
11135
11136    IF ( ALLOCATED( rad_lw_hr_av) )  THEN
11137       CALL wrd_write_string( 'rad_lw_hr_av' )
11138       WRITE ( 14 )  rad_lw_hr_av
11139    ENDIF
11140
11141    IF ( ALLOCATED( rad_sw_in) )  THEN
11142       CALL wrd_write_string( 'rad_sw_in' )
11143       WRITE ( 14 )  rad_sw_in
11144    ENDIF
11145
11146    IF ( ALLOCATED( rad_sw_in_av) )  THEN
11147       CALL wrd_write_string( 'rad_sw_in_av' )
11148       WRITE ( 14 )  rad_sw_in_av
11149    ENDIF
11150
11151    IF ( ALLOCATED( rad_sw_out) )  THEN
11152       CALL wrd_write_string( 'rad_sw_out' )
11153       WRITE ( 14 )  rad_sw_out
11154    ENDIF
11155
11156    IF ( ALLOCATED( rad_sw_out_av) )  THEN
11157       CALL wrd_write_string( 'rad_sw_out_av' )
11158       WRITE ( 14 )  rad_sw_out_av
11159    ENDIF
11160
11161    IF ( ALLOCATED( rad_sw_cs_hr) )  THEN
11162       CALL wrd_write_string( 'rad_sw_cs_hr' )
11163       WRITE ( 14 )  rad_sw_cs_hr
11164    ENDIF
11165
11166    IF ( ALLOCATED( rad_sw_cs_hr_av) )  THEN
11167       CALL wrd_write_string( 'rad_sw_cs_hr_av' )
11168       WRITE ( 14 )  rad_sw_cs_hr_av
11169    ENDIF
11170
11171    IF ( ALLOCATED( rad_sw_hr) )  THEN
11172       CALL wrd_write_string( 'rad_sw_hr' )
11173       WRITE ( 14 )  rad_sw_hr
11174    ENDIF
11175
11176    IF ( ALLOCATED( rad_sw_hr_av) )  THEN
11177       CALL wrd_write_string( 'rad_sw_hr_av' )
11178       WRITE ( 14 )  rad_sw_hr_av
11179    ENDIF
11180
11181
11182 END SUBROUTINE radiation_wrd_local
11183
11184!------------------------------------------------------------------------------!
11185! Description:
11186! ------------
11187!> Subroutine reads local (subdomain) restart data
11188!------------------------------------------------------------------------------!
11189 SUBROUTINE radiation_rrd_local( k, nxlf, nxlc, nxl_on_file, nxrf, nxrc,       &
11190                                nxr_on_file, nynf, nync, nyn_on_file, nysf,    &
11191                                nysc, nys_on_file, tmp_2d, tmp_3d, found )
11192 
11193
11194    USE control_parameters
11195       
11196    USE indices
11197   
11198    USE kinds
11199   
11200    USE pegrid
11201
11202
11203    IMPLICIT NONE
11204
11205    INTEGER(iwp) ::  k               !<
11206    INTEGER(iwp) ::  nxlc            !<
11207    INTEGER(iwp) ::  nxlf            !<
11208    INTEGER(iwp) ::  nxl_on_file     !<
11209    INTEGER(iwp) ::  nxrc            !<
11210    INTEGER(iwp) ::  nxrf            !<
11211    INTEGER(iwp) ::  nxr_on_file     !<
11212    INTEGER(iwp) ::  nync            !<
11213    INTEGER(iwp) ::  nynf            !<
11214    INTEGER(iwp) ::  nyn_on_file     !<
11215    INTEGER(iwp) ::  nysc            !<
11216    INTEGER(iwp) ::  nysf            !<
11217    INTEGER(iwp) ::  nys_on_file     !<
11218
11219    LOGICAL, INTENT(OUT)  :: found
11220
11221    REAL(wp), DIMENSION(nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_2d   !<
11222
11223    REAL(wp), DIMENSION(nzb:nzt+1,nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_3d   !<
11224
11225    REAL(wp), DIMENSION(0:0,nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_3d2   !<
11226
11227
11228    found = .TRUE.
11229
11230
11231    SELECT CASE ( restart_string(1:length) )
11232
11233       CASE ( 'rad_net_av' )
11234          IF ( .NOT. ALLOCATED( rad_net_av ) )  THEN
11235             ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
11236          ENDIF 
11237          IF ( k == 1 )  READ ( 13 )  tmp_2d
11238          rad_net_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =           &
11239                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11240                       
11241       CASE ( 'rad_lw_in_xy_av' )
11242          IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) )  THEN
11243             ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
11244          ENDIF 
11245          IF ( k == 1 )  READ ( 13 )  tmp_2d
11246          rad_lw_in_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =      &
11247                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11248                       
11249       CASE ( 'rad_lw_out_xy_av' )
11250          IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) )  THEN
11251             ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
11252          ENDIF 
11253          IF ( k == 1 )  READ ( 13 )  tmp_2d
11254          rad_lw_out_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =     &
11255                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11256                       
11257       CASE ( 'rad_sw_in_xy_av' )
11258          IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) )  THEN
11259             ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
11260          ENDIF 
11261          IF ( k == 1 )  READ ( 13 )  tmp_2d
11262          rad_sw_in_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =      &
11263                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11264                       
11265       CASE ( 'rad_sw_out_xy_av' )
11266          IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) )  THEN
11267             ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
11268          ENDIF 
11269          IF ( k == 1 )  READ ( 13 )  tmp_2d
11270          rad_sw_out_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =     &
11271                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11272                       
11273       CASE ( 'rad_lw_in' )
11274          IF ( .NOT. ALLOCATED( rad_lw_in ) )  THEN
11275             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11276                  radiation_scheme == 'constant')  THEN
11277                ALLOCATE( rad_lw_in(0:0,nysg:nyng,nxlg:nxrg) )
11278             ELSE
11279                ALLOCATE( rad_lw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11280             ENDIF
11281          ENDIF 
11282          IF ( k == 1 )  THEN
11283             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11284                  radiation_scheme == 'constant')  THEN
11285                READ ( 13 )  tmp_3d2
11286                rad_lw_in(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =   &
11287                   tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11288             ELSE
11289                READ ( 13 )  tmp_3d
11290                rad_lw_in(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11291                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11292             ENDIF
11293          ENDIF
11294
11295       CASE ( 'rad_lw_in_av' )
11296          IF ( .NOT. ALLOCATED( rad_lw_in_av ) )  THEN
11297             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11298                  radiation_scheme == 'constant')  THEN
11299                ALLOCATE( rad_lw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
11300             ELSE
11301                ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11302             ENDIF
11303          ENDIF 
11304          IF ( k == 1 )  THEN
11305             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11306                  radiation_scheme == 'constant')  THEN
11307                READ ( 13 )  tmp_3d2
11308                rad_lw_in_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =&
11309                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11310             ELSE
11311                READ ( 13 )  tmp_3d
11312                rad_lw_in_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11313                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11314             ENDIF
11315          ENDIF
11316
11317       CASE ( 'rad_lw_out' )
11318          IF ( .NOT. ALLOCATED( rad_lw_out ) )  THEN
11319             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11320                  radiation_scheme == 'constant')  THEN
11321                ALLOCATE( rad_lw_out(0:0,nysg:nyng,nxlg:nxrg) )
11322             ELSE
11323                ALLOCATE( rad_lw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11324             ENDIF
11325          ENDIF 
11326          IF ( k == 1 )  THEN
11327             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11328                  radiation_scheme == 'constant')  THEN
11329                READ ( 13 )  tmp_3d2
11330                rad_lw_out(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11331                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11332             ELSE
11333                READ ( 13 )  tmp_3d
11334                rad_lw_out(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =    &
11335                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11336             ENDIF
11337          ENDIF
11338
11339       CASE ( 'rad_lw_out_av' )
11340          IF ( .NOT. ALLOCATED( rad_lw_out_av ) )  THEN
11341             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11342                  radiation_scheme == 'constant')  THEN
11343                ALLOCATE( rad_lw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
11344             ELSE
11345                ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11346             ENDIF
11347          ENDIF 
11348          IF ( k == 1 )  THEN
11349             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11350                  radiation_scheme == 'constant')  THEN
11351                READ ( 13 )  tmp_3d2
11352                rad_lw_out_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) &
11353                   = tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11354             ELSE
11355                READ ( 13 )  tmp_3d
11356                rad_lw_out_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &
11357                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11358             ENDIF
11359          ENDIF
11360
11361       CASE ( 'rad_lw_cs_hr' )
11362          IF ( .NOT. ALLOCATED( rad_lw_cs_hr ) )  THEN
11363             ALLOCATE( rad_lw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11364          ENDIF
11365          IF ( k == 1 )  READ ( 13 )  tmp_3d
11366          rad_lw_cs_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11367                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11368
11369       CASE ( 'rad_lw_cs_hr_av' )
11370          IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) )  THEN
11371             ALLOCATE( rad_lw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11372          ENDIF
11373          IF ( k == 1 )  READ ( 13 )  tmp_3d
11374          rad_lw_cs_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11375                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11376
11377       CASE ( 'rad_lw_hr' )
11378          IF ( .NOT. ALLOCATED( rad_lw_hr ) )  THEN
11379             ALLOCATE( rad_lw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11380          ENDIF
11381          IF ( k == 1 )  READ ( 13 )  tmp_3d
11382          rad_lw_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =           &
11383                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11384
11385       CASE ( 'rad_lw_hr_av' )
11386          IF ( .NOT. ALLOCATED( rad_lw_hr_av ) )  THEN
11387             ALLOCATE( rad_lw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11388          ENDIF
11389          IF ( k == 1 )  READ ( 13 )  tmp_3d
11390          rad_lw_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11391                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11392
11393       CASE ( 'rad_sw_in' )
11394          IF ( .NOT. ALLOCATED( rad_sw_in ) )  THEN
11395             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11396                  radiation_scheme == 'constant')  THEN
11397                ALLOCATE( rad_sw_in(0:0,nysg:nyng,nxlg:nxrg) )
11398             ELSE
11399                ALLOCATE( rad_sw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11400             ENDIF
11401          ENDIF 
11402          IF ( k == 1 )  THEN
11403             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11404                  radiation_scheme == 'constant')  THEN
11405                READ ( 13 )  tmp_3d2
11406                rad_sw_in(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =   &
11407                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11408             ELSE
11409                READ ( 13 )  tmp_3d
11410                rad_sw_in(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11411                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11412             ENDIF
11413          ENDIF
11414
11415       CASE ( 'rad_sw_in_av' )
11416          IF ( .NOT. ALLOCATED( rad_sw_in_av ) )  THEN
11417             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11418                  radiation_scheme == 'constant')  THEN
11419                ALLOCATE( rad_sw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
11420             ELSE
11421                ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11422             ENDIF
11423          ENDIF 
11424          IF ( k == 1 )  THEN
11425             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11426                  radiation_scheme == 'constant')  THEN
11427                READ ( 13 )  tmp_3d2
11428                rad_sw_in_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =&
11429                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11430             ELSE
11431                READ ( 13 )  tmp_3d
11432                rad_sw_in_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11433                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11434             ENDIF
11435          ENDIF
11436
11437       CASE ( 'rad_sw_out' )
11438          IF ( .NOT. ALLOCATED( rad_sw_out ) )  THEN
11439             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11440                  radiation_scheme == 'constant')  THEN
11441                ALLOCATE( rad_sw_out(0:0,nysg:nyng,nxlg:nxrg) )
11442             ELSE
11443                ALLOCATE( rad_sw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11444             ENDIF
11445          ENDIF 
11446          IF ( k == 1 )  THEN
11447             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11448                  radiation_scheme == 'constant')  THEN
11449                READ ( 13 )  tmp_3d2
11450                rad_sw_out(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11451                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11452             ELSE
11453                READ ( 13 )  tmp_3d
11454                rad_sw_out(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =    &
11455                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11456             ENDIF
11457          ENDIF
11458
11459       CASE ( 'rad_sw_out_av' )
11460          IF ( .NOT. ALLOCATED( rad_sw_out_av ) )  THEN
11461             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11462                  radiation_scheme == 'constant')  THEN
11463                ALLOCATE( rad_sw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
11464             ELSE
11465                ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11466             ENDIF
11467          ENDIF 
11468          IF ( k == 1 )  THEN
11469             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11470                  radiation_scheme == 'constant')  THEN
11471                READ ( 13 )  tmp_3d2
11472                rad_sw_out_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) &
11473                   = tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11474             ELSE
11475                READ ( 13 )  tmp_3d
11476                rad_sw_out_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &
11477                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11478             ENDIF
11479          ENDIF
11480
11481       CASE ( 'rad_sw_cs_hr' )
11482          IF ( .NOT. ALLOCATED( rad_sw_cs_hr ) )  THEN
11483             ALLOCATE( rad_sw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11484          ENDIF
11485          IF ( k == 1 )  READ ( 13 )  tmp_3d
11486          rad_sw_cs_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11487                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11488
11489       CASE ( 'rad_sw_cs_hr_av' )
11490          IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) )  THEN
11491             ALLOCATE( rad_sw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11492          ENDIF
11493          IF ( k == 1 )  READ ( 13 )  tmp_3d
11494          rad_sw_cs_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11495                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11496
11497       CASE ( 'rad_sw_hr' )
11498          IF ( .NOT. ALLOCATED( rad_sw_hr ) )  THEN
11499             ALLOCATE( rad_sw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11500          ENDIF
11501          IF ( k == 1 )  READ ( 13 )  tmp_3d
11502          rad_sw_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =           &
11503                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11504
11505       CASE ( 'rad_sw_hr_av' )
11506          IF ( .NOT. ALLOCATED( rad_sw_hr_av ) )  THEN
11507             ALLOCATE( rad_sw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11508          ENDIF
11509          IF ( k == 1 )  READ ( 13 )  tmp_3d
11510          rad_lw_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11511                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11512
11513       CASE DEFAULT
11514
11515          found = .FALSE.
11516
11517    END SELECT
11518
11519 END SUBROUTINE radiation_rrd_local
11520
11521
11522 END MODULE radiation_model_mod
Note: See TracBrowser for help on using the repository browser.