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

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

Bugfixes in initialization and STG

  • 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: 503.8 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 3900 2019-04-16 15:17:43Z suehring $
30! Fixed initialization problem
31!
32! 3885 2019-04-11 11:29:34Z kanani
33! Changes related to global restructuring of location messages and introduction
34! of additional debug messages
35!
36! 3881 2019-04-10 09:31:22Z suehring
37! Output of albedo and emissivity moved from USM, bugfixes in initialization
38! of albedo
39!
40! 3861 2019-04-04 06:27:41Z maronga
41! Bugfix: factor of 4.0 required instead of 3.0 in calculation of rad_lw_out_change_0
42!
43! 3859 2019-04-03 20:30:31Z maronga
44! Added some descriptions
45!
46! 3847 2019-04-01 14:51:44Z suehring
47! Implement check for dt_radiation (must be > 0)
48!
49! 3846 2019-04-01 13:55:30Z suehring
50! unused variable removed
51!
52! 3814 2019-03-26 08:40:31Z pavelkrc
53! Change zenith(0:0) and others to scalar.
54! Code review.
55! Rename exported nzu, nzp and related variables due to name conflict
56!
57! 3771 2019-02-28 12:19:33Z raasch
58! rrtmg preprocessor for directives moved/added, save attribute added to temporary
59! pointers to avoid compiler warnings about outlived pointer targets,
60! statement added to avoid compiler warning about unused variable
61!
62! 3769 2019-02-28 10:16:49Z moh.hefny
63! removed unused variables and subroutine radiation_radflux_gridbox
64!
65! 3767 2019-02-27 08:18:02Z raasch
66! unused variable for file index removed from rrd-subroutines parameter list
67!
68! 3760 2019-02-21 18:47:35Z moh.hefny
69! Bugfix: initialized simulated_time before calculating solar position
70! to enable restart option with reading in SVF from file(s).
71!
72! 3754 2019-02-19 17:02:26Z kanani
73! (resler, pavelkrc)
74! Bugfixes: add further required MRT factors to read/write_svf,
75! fix for aggregating view factors to eliminate local noise in reflected
76! irradiance at mutually close surfaces (corners, presence of trees) in the
77! angular discretization scheme.
78!
79! 3752 2019-02-19 09:37:22Z resler
80! added read/write number of MRT factors to the respective routines
81!
82! 3705 2019-01-29 19:56:39Z suehring
83! Make variables that are sampled in virtual measurement module public
84!
85! 3704 2019-01-29 19:51:41Z suehring
86! Some interface calls moved to module_interface + cleanup
87!
88! 3667 2019-01-10 14:26:24Z schwenkel
89! Modified check for rrtmg input files
90!
91! 3655 2019-01-07 16:51:22Z knoop
92! nopointer option removed
93!
94! 3633 2018-12-17 16:17:57Z schwenkel
95! Include check for rrtmg files
96!
97! 3630 2018-12-17 11:04:17Z knoop
98! - fix initialization of date and time after calling zenith
99! - fix a bug in radiation_solar_pos
100!
101! 3616 2018-12-10 09:44:36Z Salim
102! fix manipulation of time variables in radiation_presimulate_solar_pos
103!
104! 3608 2018-12-07 12:59:57Z suehring $
105! Bugfix radiation output
106!
107! 3607 2018-12-07 11:56:58Z suehring
108! Output of radiation-related quantities migrated to radiation_model_mod.
109!
110! 3589 2018-11-30 15:09:51Z suehring
111! Remove erroneous UTF encoding
112!
113! 3572 2018-11-28 11:40:28Z suehring
114! Add filling the short- and longwave radiation flux arrays (e.g. diffuse,
115! direct, reflected, resedual) for all surfaces. This is required to surface
116! outputs in suface_output_mod. (M. Salim)
117!
118! 3571 2018-11-28 09:24:03Z moh.hefny
119! Add an epsilon value to compare values in if statement to fix possible
120! precsion related errors in raytrace routines.
121!
122! 3524 2018-11-14 13:36:44Z raasch
123! missing cpp-directives added
124!
125! 3495 2018-11-06 15:22:17Z kanani
126! Resort control_parameters ONLY list,
127! From branch radiation@3491 moh.hefny:
128! bugfix in calculating the apparent solar positions by updating
129! the simulated time so that the actual time is correct.
130!
131! 3464 2018-10-30 18:08:55Z kanani
132! From branch resler@3462, pavelkrc:
133! add MRT shaping function for human
134!
135! 3449 2018-10-29 19:36:56Z suehring
136! New RTM version 3.0: (Pavel Krc, Jaroslav Resler, ICS, Prague)
137!   - Interaction of plant canopy with LW radiation
138!   - Transpiration from resolved plant canopy dependent on radiation
139!     called from RTM
140!
141!
142! 3435 2018-10-26 18:25:44Z gronemeier
143! - workaround: return unit=illegal in check_data_output for certain variables
144!   when check called from init_masks
145! - Use pointer in masked output to reduce code redundancies
146! - Add terrain-following masked output
147!
148! 3424 2018-10-25 07:29:10Z gronemeier
149! bugfix: add rad_lw_in, rad_lw_out, rad_sw_out to radiation_check_data_output
150!
151! 3378 2018-10-19 12:34:59Z kanani
152! merge from radiation branch (r3362) into trunk
153! (moh.hefny):
154! - removed read/write_svf_on_init and read_dist_max_svf (not used anymore)
155! - bugfix nzut > nzpt in calculating maxboxes
156!
157! 3372 2018-10-18 14:03:19Z raasch
158! bugfix: kind type of 2nd argument of mpi_win_allocate changed, misplaced
159!         __parallel directive
160!
161! 3351 2018-10-15 18:40:42Z suehring
162! Do not overwrite values of spectral and broadband albedo during initialization
163! if they are already initialized in the urban-surface model via ASCII input.
164!
165! 3337 2018-10-12 15:17:09Z kanani
166! - New RTM version 2.9: (Pavel Krc, Jaroslav Resler, ICS, Prague)
167!   added calculation of the MRT inside the RTM module
168!   MRT fluxes are consequently used in the new biometeorology module
169!   for calculation of biological indices (MRT, PET)
170!   Fixes of v. 2.5 and SVN trunk:
171!    - proper initialization of rad_net_l
172!    - make arrays nsurfs and surfstart TARGET to prevent some MPI problems
173!    - initialization of arrays used in MPI one-sided operation as 1-D arrays
174!      to prevent problems with some MPI/compiler combinations
175!    - fix indexing of target displacement in subroutine request_itarget to
176!      consider nzub
177!    - fix LAD dimmension range in PCB calculation
178!    - check ierr in all MPI calls
179!    - use proper per-gridbox sky and diffuse irradiance
180!    - fix shading for reflected irradiance
181!    - clear away the residuals of "atmospheric surfaces" implementation
182!    - fix rounding bug in raytrace_2d introduced in SVN trunk
183! - New RTM version 2.5: (Pavel Krc, Jaroslav Resler, ICS, Prague)
184!   can use angular discretization for all SVF
185!   (i.e. reflected and emitted radiation in addition to direct and diffuse),
186!   allowing for much better scaling wih high resoltion and/or complex terrain
187! - Unite array grow factors
188! - Fix slightly shifted terrain height in raytrace_2d
189! - Use more efficient MPI_Win_allocate for reverse gridsurf index
190! - Fix random MPI RMA bugs on Intel compilers
191! - Fix approx. double plant canopy sink values for reflected radiation
192! - Fix mostly missing plant canopy sinks for direct radiation
193! - Fix discretization errors for plant canopy sink in diffuse radiation
194! - Fix rounding errors in raytrace_2d
195!
196! 3274 2018-09-24 15:42:55Z knoop
197! Modularization of all bulk cloud physics code components
198!
199! 3272 2018-09-24 10:16:32Z suehring
200! - split direct and diffusion shortwave radiation using RRTMG rather than using
201!   calc_diffusion_radiation, in case of RRTMG
202! - removed the namelist variable split_diffusion_radiation. Now splitting depends
203!   on the choise of radiation radiation scheme
204! - removed calculating the rdiation flux for surfaces at the radiation scheme
205!   in case of using RTM since it will be calculated anyway in the radiation
206!   interaction routine.
207! - set SW radiation flux for surfaces to zero at night in case of no RTM is used
208! - precalculate the unit vector yxdir of ray direction to avoid the temporarly
209!   array allocation during the subroutine call
210! - fixed a bug in calculating the max number of boxes ray can cross in the domain
211!
212! 3264 2018-09-20 13:54:11Z moh.hefny
213! Bugfix in raytrace_2d calls
214!
215! 3248 2018-09-14 09:42:06Z sward
216! Minor formating changes
217!
218! 3246 2018-09-13 15:14:50Z sward
219! Added error handling for input namelist via parin_fail_message
220!
221! 3241 2018-09-12 15:02:00Z raasch
222! unused variables removed or commented
223!
224! 3233 2018-09-07 13:21:24Z schwenkel
225! Adapted for the use of cloud_droplets
226!
227! 3230 2018-09-05 09:29:05Z schwenkel
228! Bugfix in radiation_constant_surf: changed (10.0 - emissivity_urb) to
229! (1.0 - emissivity_urb)
230!
231! 3226 2018-08-31 12:27:09Z suehring
232! Bugfixes in calculation of sky-view factors and canopy-sink factors.
233!
234! 3186 2018-07-30 17:07:14Z suehring
235! Remove print statement
236!
237! 3180 2018-07-27 11:00:56Z suehring
238! Revise concept for calculation of effective radiative temperature and mapping
239! of radiative heating
240!
241! 3175 2018-07-26 14:07:38Z suehring
242! Bugfix for commit 3172
243!
244! 3173 2018-07-26 12:55:23Z suehring
245! Revise output of surface radiation quantities in case of overhanging
246! structures
247!
248! 3172 2018-07-26 12:06:06Z suehring
249! Bugfixes:
250!  - temporal work-around for calculation of effective radiative surface
251!    temperature
252!  - prevent positive solar radiation during nighttime
253!
254! 3170 2018-07-25 15:19:37Z suehring
255! Bugfix, map signle-column radiation forcing profiles on top of any topography
256!
257! 3156 2018-07-19 16:30:54Z knoop
258! Bugfix: replaced usage of the pt array with the surf%pt_surface array
259!
260! 3137 2018-07-17 06:44:21Z maronga
261! String length for trace_names fixed
262!
263! 3127 2018-07-15 08:01:25Z maronga
264! A few pavement parameters updated.
265!
266! 3123 2018-07-12 16:21:53Z suehring
267! Correct working precision for INTEGER number
268!
269! 3122 2018-07-11 21:46:41Z maronga
270! Bugfix: maximum distance for raytracing was set to  -999 m by default,
271! effectively switching off all surface reflections when max_raytracing_dist
272! was not explicitly set in namelist
273!
274! 3117 2018-07-11 09:59:11Z maronga
275! Bugfix: water vapor was not transfered to RRTMG when bulk_cloud_model = .F.
276! Bugfix: changed the calculation of RRTMG boundary conditions (Mohamed Salim)
277! Bugfix: dry residual atmosphere is replaced by standard RRTMG atmosphere
278!
279! 3116 2018-07-10 14:31:58Z suehring
280! Output of long/shortwave radiation at surface
281!
282! 3107 2018-07-06 15:55:51Z suehring
283! Bugfix, missing index for dz
284!
285! 3066 2018-06-12 08:55:55Z Giersch
286! Error message revised
287!
288! 3065 2018-06-12 07:03:02Z Giersch
289! dz was replaced by dz(1), error message concerning vertical stretching was
290! added 
291!
292! 3049 2018-05-29 13:52:36Z Giersch
293! Error messages revised
294!
295! 3045 2018-05-28 07:55:41Z Giersch
296! Error message revised
297!
298! 3026 2018-05-22 10:30:53Z schwenkel
299! Changed the name specific humidity to mixing ratio, since we are computing
300! mixing ratios.
301!
302! 3016 2018-05-09 10:53:37Z Giersch
303! Revised structure of reading svf data according to PALM coding standard:
304! svf_code_field/len and fsvf removed, error messages PA0493 and PA0494 added,
305! allocation status of output arrays checked.
306!
307! 3014 2018-05-09 08:42:38Z maronga
308! Introduced plant canopy height similar to urban canopy height to limit
309! the memory requirement to allocate lad.
310! Deactivated automatic setting of minimum raytracing distance.
311!
312! 3004 2018-04-27 12:33:25Z Giersch
313! Further allocation checks implemented (averaged data will be assigned to fill
314! values if no allocation happened so far)
315!
316! 2995 2018-04-19 12:13:16Z Giersch
317! IF-statement in radiation_init removed so that the calculation of radiative
318! fluxes at model start is done in any case, bugfix in
319! radiation_presimulate_solar_pos (end_time is the sum of end_time and the
320! spinup_time specified in the p3d_file ), list of variables/fields that have
321! to be written out or read in case of restarts has been extended
322!
323! 2977 2018-04-17 10:27:57Z kanani
324! Implement changes from branch radiation (r2948-2971) with minor modifications,
325! plus some formatting.
326! (moh.hefny):
327! - replaced plant_canopy by npcbl to check tree existence to avoid weird
328!   allocation of related arrays (after domain decomposition some domains
329!   contains no trees although plant_canopy (global parameter) is still TRUE).
330! - added a namelist parameter to force RTM settings
331! - enabled the option to switch radiation reflections off
332! - renamed surf_reflections to surface_reflections
333! - removed average_radiation flag from the namelist (now it is implicitly set
334!   in init_3d_model according to RTM)
335! - edited read and write sky view factors and CSF routines to account for
336!   the sub-domains which may not contain any of them
337!
338! 2967 2018-04-13 11:22:08Z raasch
339! bugfix: missing parallel cpp-directives added
340!
341! 2964 2018-04-12 16:04:03Z Giersch
342! Error message PA0491 has been introduced which could be previously found in
343! check_open. The variable numprocs_previous_run is only known in case of
344! initializing_actions == read_restart_data
345!
346! 2963 2018-04-12 14:47:44Z suehring
347! - Introduce index for vegetation/wall, pavement/green-wall and water/window
348!   surfaces, for clearer access of surface fraction, albedo, emissivity, etc. .
349! - Minor bugfix in initialization of albedo for window surfaces
350!
351! 2944 2018-04-03 16:20:18Z suehring
352! Fixed bad commit
353!
354! 2943 2018-04-03 16:17:10Z suehring
355! No read of nsurfl from SVF file since it is calculated in
356! radiation_interaction_init,
357! allocation of arrays in radiation_read_svf only if not yet allocated,
358! update of 2920 revision comment.
359!
360! 2932 2018-03-26 09:39:22Z maronga
361! renamed radiation_par to radiation_parameters
362!
363! 2930 2018-03-23 16:30:46Z suehring
364! Remove default surfaces from radiation model, does not make much sense to
365! apply radiation model without energy-balance solvers; Further, add check for
366! this.
367!
368! 2920 2018-03-22 11:22:01Z kanani
369! - Bugfix: Initialize pcbl array (=-1)
370! RTM version 2.0 (Jaroslav Resler, Pavel Krc, Mohamed Salim):
371! - new major version of radiation interactions
372! - substantially enhanced performance and scalability
373! - processing of direct and diffuse solar radiation separated from reflected
374!   radiation, removed virtual surfaces
375! - new type of sky discretization by azimuth and elevation angles
376! - diffuse radiation processed cumulatively using sky view factor
377! - used precalculated apparent solar positions for direct irradiance
378! - added new 2D raytracing process for processing whole vertical column at once
379!   to increase memory efficiency and decrease number of MPI RMA operations
380! - enabled limiting the number of view factors between surfaces by the distance
381!   and value
382! - fixing issues induced by transferring radiation interactions from
383!   urban_surface_mod to radiation_mod
384! - bugfixes and other minor enhancements
385!
386! 2906 2018-03-19 08:56:40Z Giersch
387! NAMELIST paramter read/write_svf_on_init have been removed, functions
388! check_open and close_file are used now for opening/closing files related to
389! svf data, adjusted unit number and error numbers
390!
391! 2894 2018-03-15 09:17:58Z Giersch
392! Calculations of the index range of the subdomain on file which overlaps with
393! the current subdomain are already done in read_restart_data_mod
394! radiation_read_restart_data was renamed to radiation_rrd_local and
395! radiation_last_actions was renamed to radiation_wrd_local, variable named
396! found has been introduced for checking if restart data was found, reading
397! of restart strings has been moved completely to read_restart_data_mod,
398! radiation_rrd_local is already inside the overlap loop programmed in
399! read_restart_data_mod, the marker *** end rad *** is not necessary anymore,
400! strings and their respective lengths are written out and read now in case of
401! restart runs to get rid of prescribed character lengths (Giersch)
402!
403! 2809 2018-02-15 09:55:58Z suehring
404! Bugfix for gfortran: Replace the function C_SIZEOF with STORAGE_SIZE
405!
406! 2753 2018-01-16 14:16:49Z suehring
407! Tile approach for spectral albedo implemented.
408!
409! 2746 2018-01-15 12:06:04Z suehring
410! Move flag plant canopy to modules
411!
412! 2724 2018-01-05 12:12:38Z maronga
413! Set default of average_radiation to .FALSE.
414!
415! 2723 2018-01-05 09:27:03Z maronga
416! Bugfix in calculation of rad_lw_out (clear-sky). First grid level was used
417! instead of the surface value
418!
419! 2718 2018-01-02 08:49:38Z maronga
420! Corrected "Former revisions" section
421!
422! 2707 2017-12-18 18:34:46Z suehring
423! Changes from last commit documented
424!
425! 2706 2017-12-18 18:33:49Z suehring
426! Bugfix, in average radiation case calculate exner function before using it.
427!
428! 2701 2017-12-15 15:40:50Z suehring
429! Changes from last commit documented
430!
431! 2698 2017-12-14 18:46:24Z suehring
432! Bugfix in get_topography_top_index
433!
434! 2696 2017-12-14 17:12:51Z kanani
435! - Change in file header (GPL part)
436! - Improved reading/writing of SVF from/to file (BM)
437! - Bugfixes concerning RRTMG as well as average_radiation options (M. Salim)
438! - Revised initialization of surface albedo and some minor bugfixes (MS)
439! - Update net radiation after running radiation interaction routine (MS)
440! - Revisions from M Salim included
441! - Adjustment to topography and surface structure (MS)
442! - Initialization of albedo and surface emissivity via input file (MS)
443! - albedo_pars extended (MS)
444!
445! 2604 2017-11-06 13:29:00Z schwenkel
446! bugfix for calculation of effective radius using morrison microphysics
447!
448! 2601 2017-11-02 16:22:46Z scharf
449! added emissivity to namelist
450!
451! 2575 2017-10-24 09:57:58Z maronga
452! Bugfix: calculation of shortwave and longwave albedos for RRTMG swapped
453!
454! 2547 2017-10-16 12:41:56Z schwenkel
455! extended by cloud_droplets option, minor bugfix and correct calculation of
456! cloud droplet number concentration
457!
458! 2544 2017-10-13 18:09:32Z maronga
459! Moved date and time quantitis to separate module date_and_time_mod
460!
461! 2512 2017-10-04 08:26:59Z raasch
462! upper bounds of cross section and 3d output changed from nx+1,ny+1 to nx,ny
463! no output of ghost layer data
464!
465! 2504 2017-09-27 10:36:13Z maronga
466! Updates pavement types and albedo parameters
467!
468! 2328 2017-08-03 12:34:22Z maronga
469! Emissivity can now be set individually for each pixel.
470! Albedo type can be inferred from land surface model.
471! Added default albedo type for bare soil
472!
473! 2318 2017-07-20 17:27:44Z suehring
474! Get topography top index via Function call
475!
476! 2317 2017-07-20 17:27:19Z suehring
477! Improved syntax layout
478!
479! 2298 2017-06-29 09:28:18Z raasch
480! type of write_binary changed from CHARACTER to LOGICAL
481!
482! 2296 2017-06-28 07:53:56Z maronga
483! Added output of rad_sw_out for radiation_scheme = 'constant'
484!
485! 2270 2017-06-09 12:18:47Z maronga
486! Numbering changed (2 timeseries removed)
487!
488! 2249 2017-06-06 13:58:01Z sward
489! Allow for RRTMG runs without humidity/cloud physics
490!
491! 2248 2017-06-06 13:52:54Z sward
492! Error no changed
493!
494! 2233 2017-05-30 18:08:54Z suehring
495!
496! 2232 2017-05-30 17:47:52Z suehring
497! Adjustments to new topography concept
498! Bugfix in read restart
499!
500! 2200 2017-04-11 11:37:51Z suehring
501! Bugfix in call of exchange_horiz_2d and read restart data
502!
503! 2163 2017-03-01 13:23:15Z schwenkel
504! Bugfix in radiation_check_data_output
505!
506! 2157 2017-02-22 15:10:35Z suehring
507! Bugfix in read_restart data
508!
509! 2011 2016-09-19 17:29:57Z kanani
510! Removed CALL of auxiliary SUBROUTINE get_usm_info,
511! flag urban_surface is now defined in module control_parameters.
512!
513! 2007 2016-08-24 15:47:17Z kanani
514! Added calculation of solar directional vector for new urban surface
515! model,
516! accounted for urban_surface model in radiation_check_parameters,
517! correction of comments for zenith angle.
518!
519! 2000 2016-08-20 18:09:15Z knoop
520! Forced header and separation lines into 80 columns
521!
522! 1976 2016-07-27 13:28:04Z maronga
523! Output of 2D/3D/masked data is now directly done within this module. The
524! radiation schemes have been simplified for better usability so that
525! rad_lw_in, rad_lw_out, rad_sw_in, and rad_sw_out are available independent of
526! the radiation code used.
527!
528! 1856 2016-04-13 12:56:17Z maronga
529! Bugfix: allocation of rad_lw_out for radiation_scheme = 'clear-sky'
530!
531! 1853 2016-04-11 09:00:35Z maronga
532! Added routine for radiation_scheme = constant.
533
534! 1849 2016-04-08 11:33:18Z hoffmann
535! Adapted for modularization of microphysics
536!
537! 1826 2016-04-07 12:01:39Z maronga
538! Further modularization.
539!
540! 1788 2016-03-10 11:01:04Z maronga
541! Added new albedo class for pavements / roads.
542!
543! 1783 2016-03-06 18:36:17Z raasch
544! palm-netcdf-module removed in order to avoid a circular module dependency,
545! netcdf-variables moved to netcdf-module, new routine netcdf_handle_error_rad
546! added
547!
548! 1757 2016-02-22 15:49:32Z maronga
549! Added parameter unscheduled_radiation_calls. Bugfix: interpolation of sounding
550! profiles for pressure and temperature above the LES domain.
551!
552! 1709 2015-11-04 14:47:01Z maronga
553! Bugfix: set initial value for rrtm_lwuflx_dt to zero, small formatting
554! corrections
555!
556! 1701 2015-11-02 07:43:04Z maronga
557! Bugfixes: wrong index for output of timeseries, setting of nz_snd_end
558!
559! 1691 2015-10-26 16:17:44Z maronga
560! Added option for spin-up runs without radiation (skip_time_do_radiation). Bugfix
561! in calculation of pressure profiles. Bugfix in calculation of trace gas profiles.
562! Added output of radiative heating rates.
563!
564! 1682 2015-10-07 23:56:08Z knoop
565! Code annotations made doxygen readable
566!
567! 1606 2015-06-29 10:43:37Z maronga
568! Added preprocessor directive __netcdf to allow for compiling without netCDF.
569! Note, however, that RRTMG cannot be used without netCDF.
570!
571! 1590 2015-05-08 13:56:27Z maronga
572! Bugfix: definition of character strings requires same length for all elements
573!
574! 1587 2015-05-04 14:19:01Z maronga
575! Added albedo class for snow
576!
577! 1585 2015-04-30 07:05:52Z maronga
578! Added support for RRTMG
579!
580! 1571 2015-03-12 16:12:49Z maronga
581! Added missing KIND attribute. Removed upper-case variable names
582!
583! 1551 2015-03-03 14:18:16Z maronga
584! Added support for data output. Various variables have been renamed. Added
585! interface for different radiation schemes (currently: clear-sky, constant, and
586! RRTM (not yet implemented).
587!
588! 1496 2014-12-02 17:25:50Z maronga
589! Initial revision
590!
591!
592! Description:
593! ------------
594!> Radiation models and interfaces
595!> @todo Replace dz(1) appropriatly to account for grid stretching
596!> @todo move variable definitions used in radiation_init only to the subroutine
597!>       as they are no longer required after initialization.
598!> @todo Output of full column vertical profiles used in RRTMG
599!> @todo Output of other rrtm arrays (such as volume mixing ratios)
600!> @todo Check for mis-used NINT() calls in raytrace_2d
601!>       RESULT: Original was correct (carefully verified formula), the change
602!>               to INT broke raytracing      -- P. Krc
603!> @todo Optimize radiation_tendency routines
604!>
605!> @note Many variables have a leading dummy dimension (0:0) in order to
606!>       match the assume-size shape expected by the RRTMG model.
607!------------------------------------------------------------------------------!
608 MODULE radiation_model_mod
609 
610    USE arrays_3d,                                                             &
611        ONLY:  dzw, hyp, nc, pt, p, q, ql, u, v, w, zu, zw, exner, d_exner
612
613    USE basic_constants_and_equations_mod,                                     &
614        ONLY:  c_p, g, lv_d_cp, l_v, pi, r_d, rho_l, solar_constant, sigma_sb, &
615               barometric_formula
616
617    USE calc_mean_profile_mod,                                                 &
618        ONLY:  calc_mean_profile
619
620    USE control_parameters,                                                    &
621        ONLY:  cloud_droplets, coupling_char,                                  &
622               debug_output, debug_string,                                     &
623               dz, dt_spinup, end_time,                                        &
624               humidity,                                                       &
625               initializing_actions, io_blocks, io_group,                      &
626               land_surface, large_scale_forcing,                              &
627               latitude, longitude, lsf_surf,                                  &
628               message_string, plant_canopy, pt_surface,                       &
629               rho_surface, simulated_time, spinup_time, surface_pressure,     &
630               read_svf, write_svf,                                            &
631               time_since_reference_point, urban_surface, varnamelength
632
633    USE cpulog,                                                                &
634        ONLY:  cpu_log, log_point, log_point_s
635
636    USE grid_variables,                                                        &
637         ONLY:  ddx, ddy, dx, dy 
638
639    USE date_and_time_mod,                                                     &
640        ONLY:  calc_date_and_time, d_hours_day, d_seconds_hour, d_seconds_year,&
641               day_of_year, d_seconds_year, day_of_month, day_of_year_init,    &
642               init_date_and_time, month_of_year, time_utc_init, time_utc
643
644    USE indices,                                                               &
645        ONLY:  nnx, nny, nx, nxl, nxlg, nxr, nxrg, ny, nyn, nyng, nys, nysg,   &
646               nzb, nzt
647
648    USE, INTRINSIC :: iso_c_binding
649
650    USE kinds
651
652    USE bulk_cloud_model_mod,                                                  &
653        ONLY:  bulk_cloud_model, microphysics_morrison, na_init, nc_const, sigma_gc
654
655#if defined ( __netcdf )
656    USE NETCDF
657#endif
658
659    USE netcdf_data_input_mod,                                                 &
660        ONLY:  albedo_type_f, albedo_pars_f, building_type_f, pavement_type_f, &
661               vegetation_type_f, water_type_f
662
663    USE plant_canopy_model_mod,                                                &
664        ONLY:  lad_s, pc_heating_rate, pc_transpiration_rate, pc_latent_rate,  &
665               plant_canopy_transpiration, pcm_calc_transpiration_rate
666
667    USE pegrid
668
669#if defined ( __rrtmg )
670    USE parrrsw,                                                               &
671        ONLY:  naerec, nbndsw
672
673    USE parrrtm,                                                               &
674        ONLY:  nbndlw
675
676    USE rrtmg_lw_init,                                                         &
677        ONLY:  rrtmg_lw_ini
678
679    USE rrtmg_sw_init,                                                         &
680        ONLY:  rrtmg_sw_ini
681
682    USE rrtmg_lw_rad,                                                          &
683        ONLY:  rrtmg_lw
684
685    USE rrtmg_sw_rad,                                                          &
686        ONLY:  rrtmg_sw
687#endif
688    USE statistics,                                                            &
689        ONLY:  hom
690
691    USE surface_mod,                                                           &
692        ONLY:  get_topography_top_index, get_topography_top_index_ji,          &
693               ind_pav_green, ind_veg_wall, ind_wat_win,                       &
694               surf_lsm_h, surf_lsm_v, surf_type, surf_usm_h, surf_usm_v,      &
695               vertical_surfaces_exist
696
697    IMPLICIT NONE
698
699    CHARACTER(10) :: radiation_scheme = 'clear-sky' ! 'constant', 'clear-sky', or 'rrtmg'
700
701!
702!-- Predefined Land surface classes (albedo_type) after Briegleb (1992)
703    CHARACTER(37), DIMENSION(0:33), PARAMETER :: albedo_type_name = (/      &
704                                   'user defined                         ', & !  0
705                                   'ocean                                ', & !  1
706                                   'mixed farming, tall grassland        ', & !  2
707                                   'tall/medium grassland                ', & !  3
708                                   'evergreen shrubland                  ', & !  4
709                                   'short grassland/meadow/shrubland     ', & !  5
710                                   'evergreen needleleaf forest          ', & !  6
711                                   'mixed deciduous evergreen forest     ', & !  7
712                                   'deciduous forest                     ', & !  8
713                                   'tropical evergreen broadleaved forest', & !  9
714                                   'medium/tall grassland/woodland       ', & ! 10
715                                   'desert, sandy                        ', & ! 11
716                                   'desert, rocky                        ', & ! 12
717                                   'tundra                               ', & ! 13
718                                   'land ice                             ', & ! 14
719                                   'sea ice                              ', & ! 15
720                                   'snow                                 ', & ! 16
721                                   'bare soil                            ', & ! 17
722                                   'asphalt/concrete mix                 ', & ! 18
723                                   'asphalt (asphalt concrete)           ', & ! 19
724                                   'concrete (Portland concrete)         ', & ! 20
725                                   'sett                                 ', & ! 21
726                                   'paving stones                        ', & ! 22
727                                   'cobblestone                          ', & ! 23
728                                   'metal                                ', & ! 24
729                                   'wood                                 ', & ! 25
730                                   'gravel                               ', & ! 26
731                                   'fine gravel                          ', & ! 27
732                                   'pebblestone                          ', & ! 28
733                                   'woodchips                            ', & ! 29
734                                   'tartan (sports)                      ', & ! 30
735                                   'artifical turf (sports)              ', & ! 31
736                                   'clay (sports)                        ', & ! 32
737                                   'building (dummy)                     '  & ! 33
738                                                         /)
739
740    INTEGER(iwp) :: albedo_type  = 9999999_iwp, &     !< Albedo surface type
741                    dots_rad     = 0_iwp              !< starting index for timeseries output
742
743    LOGICAL ::  unscheduled_radiation_calls = .TRUE., & !< flag parameter indicating whether additional calls of the radiation code are allowed
744                constant_albedo = .FALSE.,            & !< flag parameter indicating whether the albedo may change depending on zenith
745                force_radiation_call = .FALSE.,       & !< flag parameter for unscheduled radiation calls
746                lw_radiation = .TRUE.,                & !< flag parameter indicating whether longwave radiation shall be calculated
747                radiation = .FALSE.,                  & !< flag parameter indicating whether the radiation model is used
748                sun_up    = .TRUE.,                   & !< flag parameter indicating whether the sun is up or down
749                sw_radiation = .TRUE.,                & !< flag parameter indicating whether shortwave radiation shall be calculated
750                sun_direction = .FALSE.,              & !< flag parameter indicating whether solar direction shall be calculated
751                average_radiation = .FALSE.,          & !< flag to set the calculation of radiation averaging for the domain
752                radiation_interactions = .FALSE.,     & !< flag to activiate RTM (TRUE only if vertical urban/land surface and trees exist)
753                surface_reflections = .TRUE.,         & !< flag to switch the calculation of radiation interaction between surfaces.
754                                                        !< When it switched off, only the effect of buildings and trees shadow
755                                                        !< will be considered. However fewer SVFs are expected.
756                radiation_interactions_on = .TRUE.      !< namelist flag to force RTM activiation regardless to vertical urban/land surface and trees
757
758    REAL(wp) :: albedo = 9999999.9_wp,           & !< NAMELIST alpha
759                albedo_lw_dif = 9999999.9_wp,    & !< NAMELIST aldif
760                albedo_lw_dir = 9999999.9_wp,    & !< NAMELIST aldir
761                albedo_sw_dif = 9999999.9_wp,    & !< NAMELIST asdif
762                albedo_sw_dir = 9999999.9_wp,    & !< NAMELIST asdir
763                decl_1,                          & !< declination coef. 1
764                decl_2,                          & !< declination coef. 2
765                decl_3,                          & !< declination coef. 3
766                dt_radiation = 0.0_wp,           & !< radiation model timestep
767                emissivity = 9999999.9_wp,       & !< NAMELIST surface emissivity
768                lon = 0.0_wp,                    & !< longitude in radians
769                lat = 0.0_wp,                    & !< latitude in radians
770                net_radiation = 0.0_wp,          & !< net radiation at surface
771                skip_time_do_radiation = 0.0_wp, & !< Radiation model is not called before this time
772                sky_trans,                       & !< sky transmissivity
773                time_radiation = 0.0_wp            !< time since last call of radiation code
774
775
776    REAL(wp) ::  cos_zenith        !< cosine of solar zenith angle, also z-coordinate of solar unit vector
777    REAL(wp) ::  sun_dir_lat       !< y-coordinate of solar unit vector
778    REAL(wp) ::  sun_dir_lon       !< x-coordinate of solar unit vector
779
780    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_net_av       !< average of net radiation (rad_net) at surface
781    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_lw_in_xy_av  !< average of incoming longwave radiation at surface
782    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_lw_out_xy_av !< average of outgoing longwave radiation at surface
783    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_sw_in_xy_av  !< average of incoming shortwave radiation at surface
784    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_sw_out_xy_av !< average of outgoing shortwave radiation at surface
785
786    REAL(wp), PARAMETER :: emissivity_atm_clsky = 0.8_wp       !< emissivity of the clear-sky atmosphere
787!
788!-- Land surface albedos for solar zenith angle of 60degree after Briegleb (1992)     
789!-- (shortwave, longwave, broadband):   sw,      lw,      bb,
790    REAL(wp), DIMENSION(0:2,1:33), PARAMETER :: albedo_pars = RESHAPE( (/& 
791                                   0.06_wp, 0.06_wp, 0.06_wp,            & !  1
792                                   0.09_wp, 0.28_wp, 0.19_wp,            & !  2
793                                   0.11_wp, 0.33_wp, 0.23_wp,            & !  3
794                                   0.11_wp, 0.33_wp, 0.23_wp,            & !  4
795                                   0.14_wp, 0.34_wp, 0.25_wp,            & !  5
796                                   0.06_wp, 0.22_wp, 0.14_wp,            & !  6
797                                   0.06_wp, 0.27_wp, 0.17_wp,            & !  7
798                                   0.06_wp, 0.31_wp, 0.19_wp,            & !  8
799                                   0.06_wp, 0.22_wp, 0.14_wp,            & !  9
800                                   0.06_wp, 0.28_wp, 0.18_wp,            & ! 10
801                                   0.35_wp, 0.51_wp, 0.43_wp,            & ! 11
802                                   0.24_wp, 0.40_wp, 0.32_wp,            & ! 12
803                                   0.10_wp, 0.27_wp, 0.19_wp,            & ! 13
804                                   0.90_wp, 0.65_wp, 0.77_wp,            & ! 14
805                                   0.90_wp, 0.65_wp, 0.77_wp,            & ! 15
806                                   0.95_wp, 0.70_wp, 0.82_wp,            & ! 16
807                                   0.08_wp, 0.08_wp, 0.08_wp,            & ! 17
808                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 18
809                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 19
810                                   0.30_wp, 0.30_wp, 0.30_wp,            & ! 20
811                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 21
812                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 22
813                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 23
814                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 24
815                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 25
816                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 26
817                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 27
818                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 28
819                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 29
820                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 30
821                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 31
822                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 32
823                                   0.17_wp, 0.17_wp, 0.17_wp             & ! 33
824                                 /), (/ 3, 33 /) )
825
826    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE, TARGET :: &
827                        rad_lw_cs_hr,                  & !< longwave clear sky radiation heating rate (K/s)
828                        rad_lw_cs_hr_av,               & !< average of rad_lw_cs_hr
829                        rad_lw_hr,                     & !< longwave radiation heating rate (K/s)
830                        rad_lw_hr_av,                  & !< average of rad_sw_hr
831                        rad_lw_in,                     & !< incoming longwave radiation (W/m2)
832                        rad_lw_in_av,                  & !< average of rad_lw_in
833                        rad_lw_out,                    & !< outgoing longwave radiation (W/m2)
834                        rad_lw_out_av,                 & !< average of rad_lw_out
835                        rad_sw_cs_hr,                  & !< shortwave clear sky radiation heating rate (K/s)
836                        rad_sw_cs_hr_av,               & !< average of rad_sw_cs_hr
837                        rad_sw_hr,                     & !< shortwave radiation heating rate (K/s)
838                        rad_sw_hr_av,                  & !< average of rad_sw_hr
839                        rad_sw_in,                     & !< incoming shortwave radiation (W/m2)
840                        rad_sw_in_av,                  & !< average of rad_sw_in
841                        rad_sw_out,                    & !< outgoing shortwave radiation (W/m2)
842                        rad_sw_out_av                    !< average of rad_sw_out
843
844
845!
846!-- Variables and parameters used in RRTMG only
847#if defined ( __rrtmg )
848    CHARACTER(LEN=12) :: rrtm_input_file = "RAD_SND_DATA" !< name of the NetCDF input file (sounding data)
849
850
851!
852!-- Flag parameters to be passed to RRTMG (should not be changed until ice phase in clouds is allowed)
853    INTEGER(iwp), PARAMETER :: rrtm_idrv     = 1, & !< flag for longwave upward flux calculation option (0,1)
854                               rrtm_inflglw  = 2, & !< flag for lw cloud optical properties (0,1,2)
855                               rrtm_iceflglw = 0, & !< flag for lw ice particle specifications (0,1,2,3)
856                               rrtm_liqflglw = 1, & !< flag for lw liquid droplet specifications
857                               rrtm_inflgsw  = 2, & !< flag for sw cloud optical properties (0,1,2)
858                               rrtm_iceflgsw = 0, & !< flag for sw ice particle specifications (0,1,2,3)
859                               rrtm_liqflgsw = 1    !< flag for sw liquid droplet specifications
860
861!
862!-- The following variables should be only changed with care, as this will
863!-- require further setting of some variables, which is currently not
864!-- implemented (aerosols, ice phase).
865    INTEGER(iwp) :: nzt_rad,           & !< upper vertical limit for radiation calculations
866                    rrtm_icld = 0,     & !< cloud flag (0: clear sky column, 1: cloudy column)
867                    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)
868
869    INTEGER(iwp) :: nc_stat !< local variable for storin the result of netCDF calls for error message handling
870
871    LOGICAL :: snd_exists = .FALSE.      !< flag parameter to check whether a user-defined input files exists
872    LOGICAL :: sw_exists = .FALSE.       !< flag parameter to check whether that required rrtmg sw file exists
873    LOGICAL :: lw_exists = .FALSE.       !< flag parameter to check whether that required rrtmg lw file exists
874
875
876    REAL(wp), PARAMETER :: mol_mass_air_d_wv = 1.607793_wp !< molecular weight dry air / water vapor
877
878    REAL(wp), DIMENSION(:), ALLOCATABLE :: hyp_snd,     & !< hypostatic pressure from sounding data (hPa)
879                                           rrtm_tsfc,   & !< dummy array for storing surface temperature
880                                           t_snd          !< actual temperature from sounding data (hPa)
881
882    REAL(wp), DIMENSION(:,:), ALLOCATABLE :: rrtm_ccl4vmr,   & !< CCL4 volume mixing ratio (g/mol)
883                                             rrtm_cfc11vmr,  & !< CFC11 volume mixing ratio (g/mol)
884                                             rrtm_cfc12vmr,  & !< CFC12 volume mixing ratio (g/mol)
885                                             rrtm_cfc22vmr,  & !< CFC22 volume mixing ratio (g/mol)
886                                             rrtm_ch4vmr,    & !< CH4 volume mixing ratio
887                                             rrtm_cicewp,    & !< in-cloud ice water path (g/m2)
888                                             rrtm_cldfr,     & !< cloud fraction (0,1)
889                                             rrtm_cliqwp,    & !< in-cloud liquid water path (g/m2)
890                                             rrtm_co2vmr,    & !< CO2 volume mixing ratio (g/mol)
891                                             rrtm_emis,      & !< surface emissivity (0-1) 
892                                             rrtm_h2ovmr,    & !< H2O volume mixing ratio
893                                             rrtm_n2ovmr,    & !< N2O volume mixing ratio
894                                             rrtm_o2vmr,     & !< O2 volume mixing ratio
895                                             rrtm_o3vmr,     & !< O3 volume mixing ratio
896                                             rrtm_play,      & !< pressure layers (hPa, zu-grid)
897                                             rrtm_plev,      & !< pressure layers (hPa, zw-grid)
898                                             rrtm_reice,     & !< cloud ice effective radius (microns)
899                                             rrtm_reliq,     & !< cloud water drop effective radius (microns)
900                                             rrtm_tlay,      & !< actual temperature (K, zu-grid)
901                                             rrtm_tlev,      & !< actual temperature (K, zw-grid)
902                                             rrtm_lwdflx,    & !< RRTM output of incoming longwave radiation flux (W/m2)
903                                             rrtm_lwdflxc,   & !< RRTM output of outgoing clear sky longwave radiation flux (W/m2)
904                                             rrtm_lwuflx,    & !< RRTM output of outgoing longwave radiation flux (W/m2)
905                                             rrtm_lwuflxc,   & !< RRTM output of incoming clear sky longwave radiation flux (W/m2)
906                                             rrtm_lwuflx_dt, & !< RRTM output of incoming clear sky longwave radiation flux (W/m2)
907                                             rrtm_lwuflxc_dt,& !< RRTM output of outgoing clear sky longwave radiation flux (W/m2)
908                                             rrtm_lwhr,      & !< RRTM output of longwave radiation heating rate (K/d)
909                                             rrtm_lwhrc,     & !< RRTM output of incoming longwave clear sky radiation heating rate (K/d)
910                                             rrtm_swdflx,    & !< RRTM output of incoming shortwave radiation flux (W/m2)
911                                             rrtm_swdflxc,   & !< RRTM output of outgoing clear sky shortwave radiation flux (W/m2)
912                                             rrtm_swuflx,    & !< RRTM output of outgoing shortwave radiation flux (W/m2)
913                                             rrtm_swuflxc,   & !< RRTM output of incoming clear sky shortwave radiation flux (W/m2)
914                                             rrtm_swhr,      & !< RRTM output of shortwave radiation heating rate (K/d)
915                                             rrtm_swhrc,     & !< RRTM output of incoming shortwave clear sky radiation heating rate (K/d)
916                                             rrtm_dirdflux,  & !< RRTM output of incoming direct shortwave (W/m2)
917                                             rrtm_difdflux     !< RRTM output of incoming diffuse shortwave (W/m2)
918
919    REAL(wp), DIMENSION(1) ::                rrtm_aldif,     & !< surface albedo for longwave diffuse radiation
920                                             rrtm_aldir,     & !< surface albedo for longwave direct radiation
921                                             rrtm_asdif,     & !< surface albedo for shortwave diffuse radiation
922                                             rrtm_asdir        !< surface albedo for shortwave direct radiation
923
924!
925!-- Definition of arrays that are currently not used for calling RRTMG (due to setting of flag parameters)
926    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::  rad_lw_cs_in,   & !< incoming clear sky longwave radiation (W/m2) (not used)
927                                                rad_lw_cs_out,  & !< outgoing clear sky longwave radiation (W/m2) (not used)
928                                                rad_sw_cs_in,   & !< incoming clear sky shortwave radiation (W/m2) (not used)
929                                                rad_sw_cs_out,  & !< outgoing clear sky shortwave radiation (W/m2) (not used)
930                                                rrtm_lw_tauaer, & !< lw aerosol optical depth
931                                                rrtm_lw_taucld, & !< lw in-cloud optical depth
932                                                rrtm_sw_taucld, & !< sw in-cloud optical depth
933                                                rrtm_sw_ssacld, & !< sw in-cloud single scattering albedo
934                                                rrtm_sw_asmcld, & !< sw in-cloud asymmetry parameter
935                                                rrtm_sw_fsfcld, & !< sw in-cloud forward scattering fraction
936                                                rrtm_sw_tauaer, & !< sw aerosol optical depth
937                                                rrtm_sw_ssaaer, & !< sw aerosol single scattering albedo
938                                                rrtm_sw_asmaer, & !< sw aerosol asymmetry parameter
939                                                rrtm_sw_ecaer     !< sw aerosol optical detph at 0.55 microns (rrtm_iaer = 6 only)
940
941#endif
942!
943!-- Parameters of urban and land surface models
944    INTEGER(iwp)                                   ::  nz_urban                           !< number of layers of urban surface (will be calculated)
945    INTEGER(iwp)                                   ::  nz_plant                           !< number of layers of plant canopy (will be calculated)
946    INTEGER(iwp)                                   ::  nz_urban_b                         !< bottom layer of urban surface (will be calculated)
947    INTEGER(iwp)                                   ::  nz_urban_t                         !< top layer of urban surface (will be calculated)
948    INTEGER(iwp)                                   ::  nz_plant_t                         !< top layer of plant canopy (will be calculated)
949!-- parameters of urban and land surface models
950    INTEGER(iwp), PARAMETER                        ::  nzut_free = 3                      !< number of free layers above top of of topography
951    INTEGER(iwp), PARAMETER                        ::  ndsvf = 2                          !< number of dimensions of real values in SVF
952    INTEGER(iwp), PARAMETER                        ::  idsvf = 2                          !< number of dimensions of integer values in SVF
953    INTEGER(iwp), PARAMETER                        ::  ndcsf = 1                          !< number of dimensions of real values in CSF
954    INTEGER(iwp), PARAMETER                        ::  idcsf = 2                          !< number of dimensions of integer values in CSF
955    INTEGER(iwp), PARAMETER                        ::  kdcsf = 4                          !< number of dimensions of integer values in CSF calculation array
956    INTEGER(iwp), PARAMETER                        ::  id = 1                             !< position of d-index in surfl and surf
957    INTEGER(iwp), PARAMETER                        ::  iz = 2                             !< position of k-index in surfl and surf
958    INTEGER(iwp), PARAMETER                        ::  iy = 3                             !< position of j-index in surfl and surf
959    INTEGER(iwp), PARAMETER                        ::  ix = 4                             !< position of i-index in surfl and surf
960    INTEGER(iwp), PARAMETER                        ::  im = 5                             !< position of surface m-index in surfl and surf
961    INTEGER(iwp), PARAMETER                        ::  nidx_surf = 5                      !< number of indices in surfl and surf
962
963    INTEGER(iwp), PARAMETER                        ::  nsurf_type = 10                    !< number of surf types incl. phys.(land+urban) & (atm.,sky,boundary) surfaces - 1
964
965    INTEGER(iwp), PARAMETER                        ::  iup_u    = 0                       !< 0 - index of urban upward surface (ground or roof)
966    INTEGER(iwp), PARAMETER                        ::  idown_u  = 1                       !< 1 - index of urban downward surface (overhanging)
967    INTEGER(iwp), PARAMETER                        ::  inorth_u = 2                       !< 2 - index of urban northward facing wall
968    INTEGER(iwp), PARAMETER                        ::  isouth_u = 3                       !< 3 - index of urban southward facing wall
969    INTEGER(iwp), PARAMETER                        ::  ieast_u  = 4                       !< 4 - index of urban eastward facing wall
970    INTEGER(iwp), PARAMETER                        ::  iwest_u  = 5                       !< 5 - index of urban westward facing wall
971
972    INTEGER(iwp), PARAMETER                        ::  iup_l    = 6                       !< 6 - index of land upward surface (ground or roof)
973    INTEGER(iwp), PARAMETER                        ::  inorth_l = 7                       !< 7 - index of land northward facing wall
974    INTEGER(iwp), PARAMETER                        ::  isouth_l = 8                       !< 8 - index of land southward facing wall
975    INTEGER(iwp), PARAMETER                        ::  ieast_l  = 9                       !< 9 - index of land eastward facing wall
976    INTEGER(iwp), PARAMETER                        ::  iwest_l  = 10                      !< 10- index of land westward facing wall
977
978    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  idir = (/0, 0,0, 0,1,-1,0,0, 0,1,-1/)   !< surface normal direction x indices
979    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  jdir = (/0, 0,1,-1,0, 0,0,1,-1,0, 0/)   !< surface normal direction y indices
980    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  kdir = (/1,-1,0, 0,0, 0,1,0, 0,0, 0/)   !< surface normal direction z indices
981    REAL(wp),     DIMENSION(0:nsurf_type)          :: facearea                            !< area of single face in respective
982                                                                                          !< direction (will be calc'd)
983
984
985!-- indices and sizes of urban and land surface models
986    INTEGER(iwp)                                   ::  startland        !< start index of block of land and roof surfaces
987    INTEGER(iwp)                                   ::  endland          !< end index of block of land and roof surfaces
988    INTEGER(iwp)                                   ::  nlands           !< number of land and roof surfaces in local processor
989    INTEGER(iwp)                                   ::  startwall        !< start index of block of wall surfaces
990    INTEGER(iwp)                                   ::  endwall          !< end index of block of wall surfaces
991    INTEGER(iwp)                                   ::  nwalls           !< number of wall surfaces in local processor
992
993!-- indices needed for RTM netcdf output subroutines
994    INTEGER(iwp), PARAMETER                        :: nd = 5
995    CHARACTER(LEN=6), DIMENSION(0:nd-1), PARAMETER :: dirname = (/ '_roof ', '_south', '_north', '_west ', '_east ' /)
996    INTEGER(iwp), DIMENSION(0:nd-1), PARAMETER     :: dirint_u = (/ iup_u, isouth_u, inorth_u, iwest_u, ieast_u /)
997    INTEGER(iwp), DIMENSION(0:nd-1), PARAMETER     :: dirint_l = (/ iup_l, isouth_l, inorth_l, iwest_l, ieast_l /)
998    INTEGER(iwp), DIMENSION(0:nd-1)                :: dirstart
999    INTEGER(iwp), DIMENSION(0:nd-1)                :: dirend
1000
1001!-- indices and sizes of urban and land surface models
1002    INTEGER(iwp), DIMENSION(:,:), POINTER          ::  surfl            !< coordinates of i-th local surface in local grid - surfl[:,k] = [d, z, y, x, m]
1003    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surfl_linear     !< dtto (linearly allocated array)
1004    INTEGER(iwp), DIMENSION(:,:), POINTER          ::  surf             !< coordinates of i-th surface in grid - surf[:,k] = [d, z, y, x, m]
1005    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surf_linear      !< dtto (linearly allocated array)
1006    INTEGER(iwp)                                   ::  nsurfl           !< number of all surfaces in local processor
1007    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  nsurfs           !< array of number of all surfaces in individual processors
1008    INTEGER(iwp)                                   ::  nsurf            !< global number of surfaces in index array of surfaces (nsurf = proc nsurfs)
1009    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surfstart        !< starts of blocks of surfaces for individual processors in array surf (indexed from 1)
1010                                                                        !< respective block for particular processor is surfstart[iproc+1]+1 : surfstart[iproc+1]+nsurfs[iproc+1]
1011
1012!-- block variables needed for calculation of the plant canopy model inside the urban surface model
1013    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pct              !< top layer of the plant canopy
1014    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pch              !< heights of the plant canopy
1015    INTEGER(iwp)                                   ::  npcbl = 0        !< number of the plant canopy gridboxes in local processor
1016    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pcbl             !< k,j,i coordinates of l-th local plant canopy box pcbl[:,l] = [k, j, i]
1017    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinsw          !< array of absorbed sw radiation for local plant canopy box
1018    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdir       !< array of absorbed direct sw radiation for local plant canopy box
1019    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdif       !< array of absorbed diffusion sw radiation for local plant canopy box
1020    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinlw          !< array of absorbed lw radiation for local plant canopy box
1021
1022!-- configuration parameters (they can be setup in PALM config)
1023    LOGICAL                                        ::  raytrace_mpi_rma = .TRUE.          !< use MPI RMA to access LAD and gridsurf from remote processes during raytracing
1024    LOGICAL                                        ::  rad_angular_discretization = .TRUE.!< whether to use fixed resolution discretization of view factors for
1025                                                                                          !< reflected radiation (as opposed to all mutually visible pairs)
1026    LOGICAL                                        ::  plant_lw_interact = .TRUE.         !< whether plant canopy interacts with LW radiation (in addition to SW)
1027    INTEGER(iwp)                                   ::  mrt_nlevels = 0                    !< number of vertical boxes above surface for which to calculate MRT
1028    LOGICAL                                        ::  mrt_skip_roof = .TRUE.             !< do not calculate MRT above roof surfaces
1029    LOGICAL                                        ::  mrt_include_sw = .TRUE.            !< should MRT calculation include SW radiation as well?
1030    LOGICAL                                        ::  mrt_geom_human = .TRUE.            !< MRT direction weights simulate human body instead of a sphere
1031    INTEGER(iwp)                                   ::  nrefsteps = 3                      !< number of reflection steps to perform
1032    REAL(wp), PARAMETER                            ::  ext_coef = 0.6_wp                  !< extinction coefficient (a.k.a. alpha)
1033    INTEGER(iwp), PARAMETER                        ::  rad_version_len = 10               !< length of identification string of rad version
1034    CHARACTER(rad_version_len), PARAMETER          ::  rad_version = 'RAD v. 3.0'         !< identification of version of binary svf and restart files
1035    INTEGER(iwp)                                   ::  raytrace_discrete_elevs = 40       !< number of discretization steps for elevation (nadir to zenith)
1036    INTEGER(iwp)                                   ::  raytrace_discrete_azims = 80       !< number of discretization steps for azimuth (out of 360 degrees)
1037    REAL(wp)                                       ::  max_raytracing_dist = -999.0_wp    !< maximum distance for raytracing (in metres)
1038    REAL(wp)                                       ::  min_irrf_value = 1e-6_wp           !< minimum potential irradiance factor value for raytracing
1039    REAL(wp), DIMENSION(1:30)                      ::  svfnorm_report_thresh = 1e21_wp    !< thresholds of SVF normalization values to report
1040    INTEGER(iwp)                                   ::  svfnorm_report_num                 !< number of SVF normalization thresholds to report
1041
1042!-- radiation related arrays to be used in radiation_interaction routine
1043    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_sw_in_dir    !< direct sw radiation
1044    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_sw_in_diff   !< diffusion sw radiation
1045    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_lw_in_diff   !< diffusion lw radiation
1046
1047!-- parameters required for RRTMG lower boundary condition
1048    REAL(wp)                   :: albedo_urb      !< albedo value retuned to RRTMG boundary cond.
1049    REAL(wp)                   :: emissivity_urb  !< emissivity value retuned to RRTMG boundary cond.
1050    REAL(wp)                   :: t_rad_urb       !< temperature value retuned to RRTMG boundary cond.
1051
1052!-- type for calculation of svf
1053    TYPE t_svf
1054        INTEGER(iwp)                               :: isurflt           !<
1055        INTEGER(iwp)                               :: isurfs            !<
1056        REAL(wp)                                   :: rsvf              !<
1057        REAL(wp)                                   :: rtransp           !<
1058    END TYPE
1059
1060!-- type for calculation of csf
1061    TYPE t_csf
1062        INTEGER(iwp)                               :: ip                !<
1063        INTEGER(iwp)                               :: itx               !<
1064        INTEGER(iwp)                               :: ity               !<
1065        INTEGER(iwp)                               :: itz               !<
1066        INTEGER(iwp)                               :: isurfs            !< Idx of source face / -1 for sky
1067        REAL(wp)                                   :: rcvf              !< Canopy view factor for faces /
1068                                                                        !< canopy sink factor for sky (-1)
1069    END TYPE
1070
1071!-- arrays storing the values of USM
1072    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  svfsurf          !< svfsurf[:,isvf] = index of target and source surface for svf[isvf]
1073    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  svf              !< array of shape view factors+direct irradiation factors for local surfaces
1074    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfins          !< array of sw radiation falling to local surface after i-th reflection
1075    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinl          !< array of lw radiation for local surface after i-th reflection
1076
1077    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  skyvf            !< array of sky view factor for each local surface
1078    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  skyvft           !< array of sky view factor including transparency for each local surface
1079    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsitrans         !< dsidir[isvfl,i] = path transmittance of i-th
1080                                                                        !< direction of direct solar irradiance per target surface
1081    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsitransc        !< dtto per plant canopy box
1082    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsidir           !< dsidir[:,i] = unit vector of i-th
1083                                                                        !< direction of direct solar irradiance
1084    INTEGER(iwp)                                   ::  ndsidir          !< number of apparent solar directions used
1085    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  dsidir_rev       !< dsidir_rev[ielev,iazim] = i for dsidir or -1 if not present
1086
1087    INTEGER(iwp)                                   ::  nmrtbl           !< No. of local grid boxes for which MRT is calculated
1088    INTEGER(iwp)                                   ::  nmrtf            !< number of MRT factors for local processor
1089    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  mrtbl            !< coordinates of i-th local MRT box - surfl[:,i] = [z, y, x]
1090    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  mrtfsurf         !< mrtfsurf[:,imrtf] = index of target MRT box and source surface for mrtf[imrtf]
1091    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtf             !< array of MRT factors for each local MRT box
1092    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtft            !< array of MRT factors including transparency for each local MRT box
1093    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtsky           !< array of sky view factor for each local MRT box
1094    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtskyt          !< array of sky view factor including transparency for each local MRT box
1095    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  mrtdsit          !< array of direct solar transparencies for each local MRT box
1096    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinsw          !< mean SW radiant flux for each MRT box
1097    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinlw          !< mean LW radiant flux for each MRT box
1098    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrt              !< mean radiant temperature for each MRT box
1099    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinsw_av       !< time average mean SW radiant flux for each MRT box
1100    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinlw_av       !< time average mean LW radiant flux for each MRT box
1101    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrt_av           !< time average mean radiant temperature for each MRT box
1102
1103    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinsw         !< array of sw radiation falling to local surface including radiation from reflections
1104    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlw         !< array of lw radiation falling to local surface including radiation from reflections
1105    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdir      !< array of direct sw radiation falling to local surface
1106    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdif      !< array of diffuse sw radiation from sky and model boundary falling to local surface
1107    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwdif      !< array of diffuse lw radiation from sky and model boundary falling to local surface
1108   
1109                                                                        !< Outward radiation is only valid for nonvirtual surfaces
1110    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsl        !< array of reflected sw radiation for local surface in i-th reflection
1111    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutll        !< array of reflected + emitted lw radiation for local surface in i-th reflection
1112    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfouts         !< array of reflected sw radiation for all surfaces in i-th reflection
1113    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutl         !< array of reflected + emitted lw radiation for all surfaces in i-th reflection
1114    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlg         !< global array of incoming lw radiation from plant canopy
1115    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsw        !< array of total sw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1116    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutlw        !< array of total lw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1117    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfemitlwl      !< array of emitted lw radiation for local surface used to calculate effective surface temperature for radiation model
1118
1119!-- block variables needed for calculation of the plant canopy model inside the urban surface model
1120    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  csfsurf          !< csfsurf[:,icsf] = index of target surface and csf grid index for csf[icsf]
1121    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  csf              !< array of plant canopy sink fators + direct irradiation factors (transparency)
1122    REAL(wp), DIMENSION(:,:,:), POINTER            ::  sub_lad          !< subset of lad_s within urban surface, transformed to plain Z coordinate
1123    REAL(wp), DIMENSION(:), POINTER                ::  sub_lad_g        !< sub_lad globalized (used to avoid MPI RMA calls in raytracing)
1124    REAL(wp)                                       ::  prototype_lad    !< prototype leaf area density for computing effective optical depth
1125    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  nzterr, plantt   !< temporary global arrays for raytracing
1126    INTEGER(iwp)                                   ::  plantt_max
1127
1128!-- arrays and variables for calculation of svf and csf
1129    TYPE(t_svf), DIMENSION(:), POINTER             ::  asvf             !< pointer to growing svc array
1130    TYPE(t_csf), DIMENSION(:), POINTER             ::  acsf             !< pointer to growing csf array
1131    TYPE(t_svf), DIMENSION(:), POINTER             ::  amrtf            !< pointer to growing mrtf array
1132    TYPE(t_svf), DIMENSION(:), ALLOCATABLE, TARGET ::  asvf1, asvf2     !< realizations of svf array
1133    TYPE(t_csf), DIMENSION(:), ALLOCATABLE, TARGET ::  acsf1, acsf2     !< realizations of csf array
1134    TYPE(t_svf), DIMENSION(:), ALLOCATABLE, TARGET ::  amrtf1, amrtf2   !< realizations of mftf array
1135    INTEGER(iwp)                                   ::  nsvfla           !< dimmension of array allocated for storage of svf in local processor
1136    INTEGER(iwp)                                   ::  ncsfla           !< dimmension of array allocated for storage of csf in local processor
1137    INTEGER(iwp)                                   ::  nmrtfa           !< dimmension of array allocated for storage of mrt
1138    INTEGER(iwp)                                   ::  msvf, mcsf, mmrtf!< mod for swapping the growing array
1139    INTEGER(iwp), PARAMETER                        ::  gasize = 100000_iwp  !< initial size of growing arrays
1140    REAL(wp), PARAMETER                            ::  grow_factor = 1.4_wp !< growth factor of growing arrays
1141    INTEGER(iwp)                                   ::  nsvfl            !< number of svf for local processor
1142    INTEGER(iwp)                                   ::  ncsfl            !< no. of csf in local processor
1143                                                                        !< needed only during calc_svf but must be here because it is
1144                                                                        !< shared between subroutines calc_svf and raytrace
1145    INTEGER(iwp), DIMENSION(:,:,:,:), POINTER      ::  gridsurf         !< reverse index of local surfl[d,k,j,i] (for case rad_angular_discretization)
1146    INTEGER(iwp), DIMENSION(:,:,:), ALLOCATABLE    ::  gridpcbl         !< reverse index of local pcbl[k,j,i]
1147    INTEGER(iwp), PARAMETER                        ::  nsurf_type_u = 6 !< number of urban surf types (used in gridsurf)
1148
1149!-- temporary arrays for calculation of csf in raytracing
1150    INTEGER(iwp)                                   ::  maxboxesg        !< max number of boxes ray can cross in the domain
1151    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  boxes            !< coordinates of gridboxes being crossed by ray
1152    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  crlens           !< array of crossing lengths of ray for particular grid boxes
1153    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  lad_ip           !< array of numbers of process where lad is stored
1154#if defined( __parallel )
1155    INTEGER(kind=MPI_ADDRESS_KIND), &
1156                  DIMENSION(:), ALLOCATABLE        ::  lad_disp         !< array of displaycements of lad in local array of proc lad_ip
1157    INTEGER(iwp)                                   ::  win_lad          !< MPI RMA window for leaf area density
1158    INTEGER(iwp)                                   ::  win_gridsurf     !< MPI RMA window for reverse grid surface index
1159#endif
1160    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  lad_s_ray        !< array of received lad_s for appropriate gridboxes crossed by ray
1161    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  target_surfl
1162    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  rt2_track
1163    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rt2_track_lad
1164    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  rt2_track_dist
1165    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  rt2_dist
1166
1167!-- arrays for time averages
1168    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfradnet_av    !< average of net radiation to local surface including radiation from reflections
1169    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinsw_av      !< average of sw radiation falling to local surface including radiation from reflections
1170    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlw_av      !< average of lw radiation falling to local surface including radiation from reflections
1171    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdir_av   !< average of direct sw radiation falling to local surface
1172    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdif_av   !< average of diffuse sw radiation from sky and model boundary falling to local surface
1173    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwdif_av   !< average of diffuse lw radiation from sky and model boundary falling to local surface
1174    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswref_av   !< average of sw radiation falling to surface from reflections
1175    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwref_av   !< average of lw radiation falling to surface from reflections
1176    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsw_av     !< average of total sw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1177    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutlw_av     !< average of total lw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1178    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfins_av       !< average of array of residua of sw radiation absorbed in surface after last reflection
1179    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinl_av       !< average of array of residua of lw radiation absorbed in surface after last reflection
1180    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinlw_av       !< Average of pcbinlw
1181    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinsw_av       !< Average of pcbinsw
1182    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdir_av    !< Average of pcbinswdir
1183    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdif_av    !< Average of pcbinswdif
1184    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswref_av    !< Average of pcbinswref
1185
1186
1187!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1188!-- Energy balance variables
1189!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1190!-- parameters of the land, roof and wall surfaces
1191    REAL(wp), DIMENSION(:), ALLOCATABLE            :: albedo_surf        !< albedo of the surface
1192    REAL(wp), DIMENSION(:), ALLOCATABLE            :: emiss_surf         !< emissivity of the wall surface
1193
1194
1195    INTERFACE radiation_check_data_output
1196       MODULE PROCEDURE radiation_check_data_output
1197    END INTERFACE radiation_check_data_output
1198
1199    INTERFACE radiation_check_data_output_ts
1200       MODULE PROCEDURE radiation_check_data_output_ts
1201    END INTERFACE radiation_check_data_output_ts
1202
1203    INTERFACE radiation_check_data_output_pr
1204       MODULE PROCEDURE radiation_check_data_output_pr
1205    END INTERFACE radiation_check_data_output_pr
1206 
1207    INTERFACE radiation_check_parameters
1208       MODULE PROCEDURE radiation_check_parameters
1209    END INTERFACE radiation_check_parameters
1210 
1211    INTERFACE radiation_clearsky
1212       MODULE PROCEDURE radiation_clearsky
1213    END INTERFACE radiation_clearsky
1214 
1215    INTERFACE radiation_constant
1216       MODULE PROCEDURE radiation_constant
1217    END INTERFACE radiation_constant
1218 
1219    INTERFACE radiation_control
1220       MODULE PROCEDURE radiation_control
1221    END INTERFACE radiation_control
1222
1223    INTERFACE radiation_3d_data_averaging
1224       MODULE PROCEDURE radiation_3d_data_averaging
1225    END INTERFACE radiation_3d_data_averaging
1226
1227    INTERFACE radiation_data_output_2d
1228       MODULE PROCEDURE radiation_data_output_2d
1229    END INTERFACE radiation_data_output_2d
1230
1231    INTERFACE radiation_data_output_3d
1232       MODULE PROCEDURE radiation_data_output_3d
1233    END INTERFACE radiation_data_output_3d
1234
1235    INTERFACE radiation_data_output_mask
1236       MODULE PROCEDURE radiation_data_output_mask
1237    END INTERFACE radiation_data_output_mask
1238
1239    INTERFACE radiation_define_netcdf_grid
1240       MODULE PROCEDURE radiation_define_netcdf_grid
1241    END INTERFACE radiation_define_netcdf_grid
1242
1243    INTERFACE radiation_header
1244       MODULE PROCEDURE radiation_header
1245    END INTERFACE radiation_header 
1246 
1247    INTERFACE radiation_init
1248       MODULE PROCEDURE radiation_init
1249    END INTERFACE radiation_init
1250
1251    INTERFACE radiation_parin
1252       MODULE PROCEDURE radiation_parin
1253    END INTERFACE radiation_parin
1254   
1255    INTERFACE radiation_rrtmg
1256       MODULE PROCEDURE radiation_rrtmg
1257    END INTERFACE radiation_rrtmg
1258
1259#if defined( __rrtmg )
1260    INTERFACE radiation_tendency
1261       MODULE PROCEDURE radiation_tendency
1262       MODULE PROCEDURE radiation_tendency_ij
1263    END INTERFACE radiation_tendency
1264#endif
1265
1266    INTERFACE radiation_rrd_local
1267       MODULE PROCEDURE radiation_rrd_local
1268    END INTERFACE radiation_rrd_local
1269
1270    INTERFACE radiation_wrd_local
1271       MODULE PROCEDURE radiation_wrd_local
1272    END INTERFACE radiation_wrd_local
1273
1274    INTERFACE radiation_interaction
1275       MODULE PROCEDURE radiation_interaction
1276    END INTERFACE radiation_interaction
1277
1278    INTERFACE radiation_interaction_init
1279       MODULE PROCEDURE radiation_interaction_init
1280    END INTERFACE radiation_interaction_init
1281 
1282    INTERFACE radiation_presimulate_solar_pos
1283       MODULE PROCEDURE radiation_presimulate_solar_pos
1284    END INTERFACE radiation_presimulate_solar_pos
1285
1286    INTERFACE radiation_calc_svf
1287       MODULE PROCEDURE radiation_calc_svf
1288    END INTERFACE radiation_calc_svf
1289
1290    INTERFACE radiation_write_svf
1291       MODULE PROCEDURE radiation_write_svf
1292    END INTERFACE radiation_write_svf
1293
1294    INTERFACE radiation_read_svf
1295       MODULE PROCEDURE radiation_read_svf
1296    END INTERFACE radiation_read_svf
1297
1298
1299    SAVE
1300
1301    PRIVATE
1302
1303!
1304!-- Public functions / NEEDS SORTING
1305    PUBLIC radiation_check_data_output, radiation_check_data_output_pr,        &
1306           radiation_check_data_output_ts,                                     &
1307           radiation_check_parameters, radiation_control,                      &
1308           radiation_header, radiation_init, radiation_parin,                  &
1309           radiation_3d_data_averaging,                                        &
1310           radiation_data_output_2d, radiation_data_output_3d,                 &
1311           radiation_define_netcdf_grid, radiation_wrd_local,                  &
1312           radiation_rrd_local, radiation_data_output_mask,                    &
1313           radiation_calc_svf, radiation_write_svf,                            &
1314           radiation_interaction, radiation_interaction_init,                  &
1315           radiation_read_svf, radiation_presimulate_solar_pos
1316
1317   
1318!
1319!-- Public variables and constants / NEEDS SORTING
1320    PUBLIC albedo, albedo_type, decl_1, decl_2, decl_3, dots_rad, dt_radiation,&
1321           emissivity, force_radiation_call, lat, lon, mrt_geom_human,         &
1322           mrt_include_sw, mrt_nlevels, mrtbl, mrtinsw, mrtinlw, nmrtbl,       &
1323           rad_net_av, radiation, radiation_scheme, rad_lw_in,                 &
1324           rad_lw_in_av, rad_lw_out, rad_lw_out_av,                            &
1325           rad_lw_cs_hr, rad_lw_cs_hr_av, rad_lw_hr, rad_lw_hr_av, rad_sw_in,  &
1326           rad_sw_in_av, rad_sw_out, rad_sw_out_av, rad_sw_cs_hr,              &
1327           rad_sw_cs_hr_av, rad_sw_hr, rad_sw_hr_av, solar_constant,           &
1328           skip_time_do_radiation, time_radiation, unscheduled_radiation_calls,&
1329           cos_zenith, calc_zenith, sun_direction, sun_dir_lat, sun_dir_lon,   &
1330           idir, jdir, kdir, id, iz, iy, ix,                                   &
1331           iup_u, inorth_u, isouth_u, ieast_u, iwest_u,                        &
1332           iup_l, inorth_l, isouth_l, ieast_l, iwest_l,                        &
1333           nsurf_type, nz_urban_b, nz_urban_t, nz_urban, pch, nsurf,                 &
1334           idsvf, ndsvf, idcsf, ndcsf, kdcsf, pct,                             &
1335           radiation_interactions, startwall, startland, endland, endwall,     &
1336           skyvf, skyvft, radiation_interactions_on, average_radiation,        &
1337           rad_sw_in_diff, rad_sw_in_dir
1338
1339
1340#if defined ( __rrtmg )
1341    PUBLIC radiation_tendency, rrtm_aldif, rrtm_aldir, rrtm_asdif, rrtm_asdir
1342#endif
1343
1344 CONTAINS
1345
1346
1347!------------------------------------------------------------------------------!
1348! Description:
1349! ------------
1350!> This subroutine controls the calls of the radiation schemes
1351!------------------------------------------------------------------------------!
1352    SUBROUTINE radiation_control
1353 
1354 
1355       IMPLICIT NONE
1356
1357
1358       IF ( debug_output )  CALL debug_message( 'radiation_control', 'start' )
1359
1360
1361       SELECT CASE ( TRIM( radiation_scheme ) )
1362
1363          CASE ( 'constant' )
1364             CALL radiation_constant
1365         
1366          CASE ( 'clear-sky' ) 
1367             CALL radiation_clearsky
1368       
1369          CASE ( 'rrtmg' )
1370             CALL radiation_rrtmg
1371
1372          CASE DEFAULT
1373
1374       END SELECT
1375
1376       IF ( debug_output )  CALL debug_message( 'radiation_control', 'end' )
1377
1378    END SUBROUTINE radiation_control
1379
1380!------------------------------------------------------------------------------!
1381! Description:
1382! ------------
1383!> Check data output for radiation model
1384!------------------------------------------------------------------------------!
1385    SUBROUTINE radiation_check_data_output( variable, unit, i, ilen, k )
1386 
1387 
1388       USE control_parameters,                                                 &
1389           ONLY: data_output, message_string
1390
1391       IMPLICIT NONE
1392
1393       CHARACTER (LEN=*) ::  unit          !<
1394       CHARACTER (LEN=*) ::  variable      !<
1395
1396       INTEGER(iwp) :: i, k
1397       INTEGER(iwp) :: ilen
1398       CHARACTER(LEN=varnamelength) :: var          !< TRIM(variable)
1399
1400       var = TRIM(variable)
1401
1402!--    first process diractional variables
1403       IF ( var(1:12) == 'rtm_rad_net_'  .OR.  var(1:13) == 'rtm_rad_insw_'  .OR.        &
1404            var(1:13) == 'rtm_rad_inlw_'  .OR.  var(1:16) == 'rtm_rad_inswdir_'  .OR.    &
1405            var(1:16) == 'rtm_rad_inswdif_'  .OR.  var(1:16) == 'rtm_rad_inswref_'  .OR. &
1406            var(1:16) == 'rtm_rad_inlwdif_'  .OR.  var(1:16) == 'rtm_rad_inlwref_'  .OR. &
1407            var(1:14) == 'rtm_rad_outsw_'  .OR.  var(1:14) == 'rtm_rad_outlw_'  .OR.     &
1408            var(1:14) == 'rtm_rad_ressw_'  .OR.  var(1:14) == 'rtm_rad_reslw_'  ) THEN
1409          IF ( .NOT.  radiation ) THEN
1410                message_string = 'output of "' // TRIM( var ) // '" require'&
1411                                 // 's radiation = .TRUE.'
1412                CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1413          ENDIF
1414          unit = 'W/m2'
1415       ELSE IF ( var(1:7) == 'rtm_svf'  .OR.  var(1:7) == 'rtm_dif'  .OR.                &
1416                 var(1:9) == 'rtm_skyvf' .OR. var(1:9) == 'rtm_skyvft'  .OR.             &
1417                 var(1:12) == 'rtm_surfalb_'  .OR.  var(1:13) == 'rtm_surfemis_'  ) THEN
1418          IF ( .NOT.  radiation ) THEN
1419                message_string = 'output of "' // TRIM( var ) // '" require'&
1420                                 // 's radiation = .TRUE.'
1421                CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1422          ENDIF
1423          unit = '1'
1424       ELSE
1425!--       non-directional variables
1426          SELECT CASE ( TRIM( var ) )
1427             CASE ( 'rad_lw_cs_hr', 'rad_lw_hr', 'rad_lw_in', 'rad_lw_out', &
1428                    'rad_sw_cs_hr', 'rad_sw_hr', 'rad_sw_in', 'rad_sw_out'  )
1429                IF (  .NOT.  radiation  .OR.  radiation_scheme /= 'rrtmg' )  THEN
1430                   message_string = '"output of "' // TRIM( var ) // '" requi' // &
1431                                    'res radiation = .TRUE. and ' //              &
1432                                    'radiation_scheme = "rrtmg"'
1433                   CALL message( 'check_parameters', 'PA0406', 1, 2, 0, 6, 0 )
1434                ENDIF
1435                unit = 'K/h'
1436
1437             CASE ( 'rad_net*', 'rrtm_aldif*', 'rrtm_aldir*', 'rrtm_asdif*',      &
1438                    'rrtm_asdir*', 'rad_lw_in*', 'rad_lw_out*', 'rad_sw_in*',     &
1439                    'rad_sw_out*')
1440                IF ( i == 0 .AND. ilen == 0 .AND. k == 0)  THEN
1441                   ! Workaround for masked output (calls with i=ilen=k=0)
1442                   unit = 'illegal'
1443                   RETURN
1444                ENDIF
1445                IF ( k == 0  .OR.  data_output(i)(ilen-2:ilen) /= '_xy' )  THEN
1446                   message_string = 'illegal value for data_output: "' //         &
1447                                    TRIM( var ) // '" & only 2d-horizontal ' //   &
1448                                    'cross sections are allowed for this value'
1449                   CALL message( 'check_parameters', 'PA0111', 1, 2, 0, 6, 0 )
1450                ENDIF
1451                IF (  .NOT.  radiation  .OR.  radiation_scheme /= "rrtmg" )  THEN
1452                   IF ( TRIM( var ) == 'rrtm_aldif*'  .OR.                        &
1453                        TRIM( var ) == 'rrtm_aldir*'  .OR.                        &
1454                        TRIM( var ) == 'rrtm_asdif*'  .OR.                        &
1455                        TRIM( var ) == 'rrtm_asdir*'      )                       &
1456                   THEN
1457                      message_string = 'output of "' // TRIM( var ) // '" require'&
1458                                       // 's radiation = .TRUE. and radiation_sch'&
1459                                       // 'eme = "rrtmg"'
1460                      CALL message( 'check_parameters', 'PA0409', 1, 2, 0, 6, 0 )
1461                   ENDIF
1462                ENDIF
1463
1464                IF ( TRIM( var ) == 'rad_net*'      ) unit = 'W/m2'
1465                IF ( TRIM( var ) == 'rad_lw_in*'    ) unit = 'W/m2'
1466                IF ( TRIM( var ) == 'rad_lw_out*'   ) unit = 'W/m2'
1467                IF ( TRIM( var ) == 'rad_sw_in*'    ) unit = 'W/m2'
1468                IF ( TRIM( var ) == 'rad_sw_out*'   ) unit = 'W/m2'
1469                IF ( TRIM( var ) == 'rad_sw_in'     ) unit = 'W/m2'
1470                IF ( TRIM( var ) == 'rrtm_aldif*'   ) unit = ''
1471                IF ( TRIM( var ) == 'rrtm_aldir*'   ) unit = ''
1472                IF ( TRIM( var ) == 'rrtm_asdif*'   ) unit = ''
1473                IF ( TRIM( var ) == 'rrtm_asdir*'   ) unit = ''
1474
1475             CASE ( 'rtm_rad_pc_inlw', 'rtm_rad_pc_insw', 'rtm_rad_pc_inswdir', &
1476                    'rtm_rad_pc_inswdif', 'rtm_rad_pc_inswref')
1477                IF ( .NOT.  radiation ) THEN
1478                   message_string = 'output of "' // TRIM( var ) // '" require'&
1479                                    // 's radiation = .TRUE.'
1480                   CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1481                ENDIF
1482                unit = 'W'
1483
1484             CASE ( 'rtm_mrt', 'rtm_mrt_sw', 'rtm_mrt_lw'  )
1485                IF ( i == 0 .AND. ilen == 0 .AND. k == 0)  THEN
1486                   ! Workaround for masked output (calls with i=ilen=k=0)
1487                   unit = 'illegal'
1488                   RETURN
1489                ENDIF
1490
1491                IF ( .NOT.  radiation ) THEN
1492                   message_string = 'output of "' // TRIM( var ) // '" require'&
1493                                    // 's radiation = .TRUE.'
1494                   CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1495                ENDIF
1496                IF ( mrt_nlevels == 0 ) THEN
1497                   message_string = 'output of "' // TRIM( var ) // '" require'&
1498                                    // 's mrt_nlevels > 0'
1499                   CALL message( 'check_parameters', 'PA0510', 1, 2, 0, 6, 0 )
1500                ENDIF
1501                IF ( TRIM( var ) == 'rtm_mrt_sw'  .AND.  .NOT. mrt_include_sw ) THEN
1502                   message_string = 'output of "' // TRIM( var ) // '" require'&
1503                                    // 's rtm_mrt_sw = .TRUE.'
1504                   CALL message( 'check_parameters', 'PA0511', 1, 2, 0, 6, 0 )
1505                ENDIF
1506                IF ( TRIM( var ) == 'rtm_mrt' ) THEN
1507                   unit = 'K'
1508                ELSE
1509                   unit = 'W m-2'
1510                ENDIF
1511
1512             CASE DEFAULT
1513                unit = 'illegal'
1514
1515          END SELECT
1516       ENDIF
1517
1518    END SUBROUTINE radiation_check_data_output
1519
1520
1521!------------------------------------------------------------------------------!
1522! Description:
1523! ------------
1524!> Set module-specific timeseries units and labels
1525!------------------------------------------------------------------------------!
1526 SUBROUTINE radiation_check_data_output_ts( dots_max, dots_num )
1527
1528
1529    INTEGER(iwp),      INTENT(IN)     ::  dots_max
1530    INTEGER(iwp),      INTENT(INOUT)  ::  dots_num
1531
1532!
1533!-- Next line is just to avoid compiler warning about unused variable.
1534    IF ( dots_max == 0 )  CONTINUE
1535
1536!
1537!-- Temporary solution to add LSM and radiation time series to the default
1538!-- output
1539    IF ( land_surface  .OR.  radiation )  THEN
1540       IF ( TRIM( radiation_scheme ) == 'rrtmg' )  THEN
1541          dots_num = dots_num + 15
1542       ELSE
1543          dots_num = dots_num + 11
1544       ENDIF
1545    ENDIF
1546
1547
1548 END SUBROUTINE radiation_check_data_output_ts
1549
1550!------------------------------------------------------------------------------!
1551! Description:
1552! ------------
1553!> Check data output of profiles for radiation model
1554!------------------------------------------------------------------------------! 
1555    SUBROUTINE radiation_check_data_output_pr( variable, var_count, unit,      &
1556               dopr_unit )
1557 
1558       USE arrays_3d,                                                          &
1559           ONLY: zu
1560
1561       USE control_parameters,                                                 &
1562           ONLY: data_output_pr, message_string
1563
1564       USE indices
1565
1566       USE profil_parameter
1567
1568       USE statistics
1569
1570       IMPLICIT NONE
1571   
1572       CHARACTER (LEN=*) ::  unit      !<
1573       CHARACTER (LEN=*) ::  variable  !<
1574       CHARACTER (LEN=*) ::  dopr_unit !< local value of dopr_unit
1575 
1576       INTEGER(iwp) ::  var_count     !<
1577
1578       SELECT CASE ( TRIM( variable ) )
1579       
1580         CASE ( 'rad_net' )
1581             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme == 'constant' )&
1582             THEN
1583                message_string = 'data_output_pr = ' //                        &
1584                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1585                                 'not available for radiation = .FALSE. or ' //&
1586                                 'radiation_scheme = "constant"'
1587                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1588             ELSE
1589                dopr_index(var_count) = 99
1590                dopr_unit  = 'W/m2'
1591                hom(:,2,99,:)  = SPREAD( zw, 2, statistic_regions+1 )
1592                unit = dopr_unit
1593             ENDIF
1594
1595          CASE ( 'rad_lw_in' )
1596             IF ( (  .NOT.  radiation)  .OR.  radiation_scheme == 'constant' ) &
1597             THEN
1598                message_string = 'data_output_pr = ' //                        &
1599                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1600                                 'not available for radiation = .FALSE. or ' //&
1601                                 'radiation_scheme = "constant"'
1602                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1603             ELSE
1604                dopr_index(var_count) = 100
1605                dopr_unit  = 'W/m2'
1606                hom(:,2,100,:)  = SPREAD( zw, 2, statistic_regions+1 )
1607                unit = dopr_unit 
1608             ENDIF
1609
1610          CASE ( 'rad_lw_out' )
1611             IF ( (  .NOT. radiation )  .OR.  radiation_scheme == 'constant' ) &
1612             THEN
1613                message_string = 'data_output_pr = ' //                        &
1614                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1615                                 'not available for radiation = .FALSE. or ' //&
1616                                 'radiation_scheme = "constant"'
1617                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1618             ELSE
1619                dopr_index(var_count) = 101
1620                dopr_unit  = 'W/m2'
1621                hom(:,2,101,:)  = SPREAD( zw, 2, statistic_regions+1 )
1622                unit = dopr_unit   
1623             ENDIF
1624
1625          CASE ( 'rad_sw_in' )
1626             IF ( (  .NOT. radiation )  .OR.  radiation_scheme == 'constant' ) &
1627             THEN
1628                message_string = 'data_output_pr = ' //                        &
1629                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1630                                 'not available for radiation = .FALSE. or ' //&
1631                                 'radiation_scheme = "constant"'
1632                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1633             ELSE
1634                dopr_index(var_count) = 102
1635                dopr_unit  = 'W/m2'
1636                hom(:,2,102,:)  = SPREAD( zw, 2, statistic_regions+1 )
1637                unit = dopr_unit
1638             ENDIF
1639
1640          CASE ( 'rad_sw_out')
1641             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme == 'constant' )&
1642             THEN
1643                message_string = 'data_output_pr = ' //                        &
1644                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1645                                 'not available for radiation = .FALSE. or ' //&
1646                                 'radiation_scheme = "constant"'
1647                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1648             ELSE
1649                dopr_index(var_count) = 103
1650                dopr_unit  = 'W/m2'
1651                hom(:,2,103,:)  = SPREAD( zw, 2, statistic_regions+1 )
1652                unit = dopr_unit
1653             ENDIF
1654
1655          CASE ( 'rad_lw_cs_hr' )
1656             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1657             THEN
1658                message_string = 'data_output_pr = ' //                        &
1659                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1660                                 'not available for radiation = .FALSE. or ' //&
1661                                 'radiation_scheme /= "rrtmg"'
1662                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1663             ELSE
1664                dopr_index(var_count) = 104
1665                dopr_unit  = 'K/h'
1666                hom(:,2,104,:)  = SPREAD( zu, 2, statistic_regions+1 )
1667                unit = dopr_unit
1668             ENDIF
1669
1670          CASE ( 'rad_lw_hr' )
1671             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1672             THEN
1673                message_string = 'data_output_pr = ' //                        &
1674                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1675                                 'not available for radiation = .FALSE. or ' //&
1676                                 'radiation_scheme /= "rrtmg"'
1677                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1678             ELSE
1679                dopr_index(var_count) = 105
1680                dopr_unit  = 'K/h'
1681                hom(:,2,105,:)  = SPREAD( zu, 2, statistic_regions+1 )
1682                unit = dopr_unit
1683             ENDIF
1684
1685          CASE ( 'rad_sw_cs_hr' )
1686             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1687             THEN
1688                message_string = 'data_output_pr = ' //                        &
1689                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1690                                 'not available for radiation = .FALSE. or ' //&
1691                                 'radiation_scheme /= "rrtmg"'
1692                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1693             ELSE
1694                dopr_index(var_count) = 106
1695                dopr_unit  = 'K/h'
1696                hom(:,2,106,:)  = SPREAD( zu, 2, statistic_regions+1 )
1697                unit = dopr_unit
1698             ENDIF
1699
1700          CASE ( 'rad_sw_hr' )
1701             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1702             THEN
1703                message_string = 'data_output_pr = ' //                        &
1704                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1705                                 'not available for radiation = .FALSE. or ' //&
1706                                 'radiation_scheme /= "rrtmg"'
1707                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1708             ELSE
1709                dopr_index(var_count) = 107
1710                dopr_unit  = 'K/h'
1711                hom(:,2,107,:)  = SPREAD( zu, 2, statistic_regions+1 )
1712                unit = dopr_unit
1713             ENDIF
1714
1715
1716          CASE DEFAULT
1717             unit = 'illegal'
1718
1719       END SELECT
1720
1721
1722    END SUBROUTINE radiation_check_data_output_pr
1723 
1724 
1725!------------------------------------------------------------------------------!
1726! Description:
1727! ------------
1728!> Check parameters routine for radiation model
1729!------------------------------------------------------------------------------!
1730    SUBROUTINE radiation_check_parameters
1731
1732       USE control_parameters,                                                 &
1733           ONLY: land_surface, message_string, urban_surface
1734
1735       USE netcdf_data_input_mod,                                              &
1736           ONLY:  input_pids_static                 
1737   
1738       IMPLICIT NONE
1739       
1740!
1741!--    In case no urban-surface or land-surface model is applied, usage of
1742!--    a radiation model make no sense.         
1743       IF ( .NOT. land_surface  .AND.  .NOT. urban_surface )  THEN
1744          message_string = 'Usage of radiation module is only allowed if ' //  &
1745                           'land-surface and/or urban-surface model is applied.'
1746          CALL message( 'check_parameters', 'PA0486', 1, 2, 0, 6, 0 )
1747       ENDIF
1748
1749       IF ( radiation_scheme /= 'constant'   .AND.                             &
1750            radiation_scheme /= 'clear-sky'  .AND.                             &
1751            radiation_scheme /= 'rrtmg' )  THEN
1752          message_string = 'unknown radiation_scheme = '//                     &
1753                           TRIM( radiation_scheme )
1754          CALL message( 'check_parameters', 'PA0405', 1, 2, 0, 6, 0 )
1755       ELSEIF ( radiation_scheme == 'rrtmg' )  THEN
1756#if ! defined ( __rrtmg )
1757          message_string = 'radiation_scheme = "rrtmg" requires ' //           & 
1758                           'compilation of PALM with pre-processor ' //        &
1759                           'directive -D__rrtmg'
1760          CALL message( 'check_parameters', 'PA0407', 1, 2, 0, 6, 0 )
1761#endif
1762#if defined ( __rrtmg ) && ! defined( __netcdf )
1763          message_string = 'radiation_scheme = "rrtmg" requires ' //           & 
1764                           'the use of NetCDF (preprocessor directive ' //     &
1765                           '-D__netcdf'
1766          CALL message( 'check_parameters', 'PA0412', 1, 2, 0, 6, 0 )
1767#endif
1768
1769       ENDIF
1770!
1771!--    Checks performed only if data is given via namelist only.
1772       IF ( .NOT. input_pids_static )  THEN
1773          IF ( albedo_type == 0  .AND.  albedo == 9999999.9_wp  .AND.          &
1774               radiation_scheme == 'clear-sky')  THEN
1775             message_string = 'radiation_scheme = "clear-sky" in combination'//& 
1776                              'with albedo_type = 0 requires setting of'//     &
1777                              'albedo /= 9999999.9'
1778             CALL message( 'check_parameters', 'PA0410', 1, 2, 0, 6, 0 )
1779          ENDIF
1780
1781          IF ( albedo_type == 0  .AND.  radiation_scheme == 'rrtmg'  .AND.     &
1782             ( albedo_lw_dif == 9999999.9_wp .OR. albedo_lw_dir == 9999999.9_wp&
1783          .OR. albedo_sw_dif == 9999999.9_wp .OR. albedo_sw_dir == 9999999.9_wp& 
1784             ) ) THEN
1785             message_string = 'radiation_scheme = "rrtmg" in combination' //   & 
1786                              'with albedo_type = 0 requires setting of ' //   &
1787                              'albedo_lw_dif /= 9999999.9' //                  &
1788                              'albedo_lw_dir /= 9999999.9' //                  &
1789                              'albedo_sw_dif /= 9999999.9 and' //              &
1790                              'albedo_sw_dir /= 9999999.9'
1791             CALL message( 'check_parameters', 'PA0411', 1, 2, 0, 6, 0 )
1792          ENDIF
1793       ENDIF
1794!
1795!--    Parallel rad_angular_discretization without raytrace_mpi_rma is not implemented
1796#if defined( __parallel )     
1797       IF ( rad_angular_discretization  .AND.  .NOT. raytrace_mpi_rma )  THEN
1798          message_string = 'rad_angular_discretization can only be used ' //  &
1799                           'together with raytrace_mpi_rma or when ' //  &
1800                           'no parallelization is applied.'
1801          CALL message( 'check_parameters', 'PA0486', 1, 2, 0, 6, 0 )
1802       ENDIF
1803#endif
1804
1805       IF ( cloud_droplets  .AND.   radiation_scheme == 'rrtmg'  .AND.         &
1806            average_radiation ) THEN
1807          message_string = 'average_radiation = .T. with radiation_scheme'//   & 
1808                           '= "rrtmg" in combination cloud_droplets = .T.'//   &
1809                           'is not implementd'
1810          CALL message( 'check_parameters', 'PA0560', 1, 2, 0, 6, 0 )
1811       ENDIF
1812
1813!
1814!--    Incialize svf normalization reporting histogram
1815       svfnorm_report_num = 1
1816       DO WHILE ( svfnorm_report_thresh(svfnorm_report_num) < 1e20_wp          &
1817                   .AND. svfnorm_report_num <= 30 )
1818          svfnorm_report_num = svfnorm_report_num + 1
1819       ENDDO
1820       svfnorm_report_num = svfnorm_report_num - 1
1821!
1822!--    Check for dt_radiation
1823       IF ( dt_radiation <= 0.0 )  THEN
1824          message_string = 'dt_radiation must be > 0.0' 
1825          CALL message( 'check_parameters', 'PA0591', 1, 2, 0, 6, 0 ) 
1826       ENDIF
1827 
1828    END SUBROUTINE radiation_check_parameters 
1829 
1830 
1831!------------------------------------------------------------------------------!
1832! Description:
1833! ------------
1834!> Initialization of the radiation model
1835!------------------------------------------------------------------------------!
1836    SUBROUTINE radiation_init
1837   
1838       IMPLICIT NONE
1839
1840       INTEGER(iwp) ::  i         !< running index x-direction
1841       INTEGER(iwp) ::  ioff      !< offset in x between surface element reference grid point in atmosphere and actual surface
1842       INTEGER(iwp) ::  j         !< running index y-direction
1843       INTEGER(iwp) ::  joff      !< offset in y between surface element reference grid point in atmosphere and actual surface
1844       INTEGER(iwp) ::  l         !< running index for orientation of vertical surfaces
1845       INTEGER(iwp) ::  m         !< running index for surface elements
1846#if defined( __rrtmg )
1847       INTEGER(iwp) ::  ind_type  !< running index for subgrid-surface tiles
1848#endif
1849
1850
1851       IF ( debug_output )  CALL debug_message( 'radiation_init', 'start' )
1852!
1853!--    Activate radiation_interactions according to the existence of vertical surfaces and/or trees.
1854!--    The namelist parameter radiation_interactions_on can override this behavior.
1855!--    (This check cannot be performed in check_parameters, because vertical_surfaces_exist is first set in
1856!--    init_surface_arrays.)
1857       IF ( radiation_interactions_on )  THEN
1858          IF ( vertical_surfaces_exist  .OR.  plant_canopy )  THEN
1859             radiation_interactions    = .TRUE.
1860             average_radiation         = .TRUE.
1861          ELSE
1862             radiation_interactions_on = .FALSE.   !< reset namelist parameter: no interactions
1863                                                   !< calculations necessary in case of flat surface
1864          ENDIF
1865       ELSEIF ( vertical_surfaces_exist  .OR.  plant_canopy )  THEN
1866          message_string = 'radiation_interactions_on is set to .FALSE. although '     // &
1867                           'vertical surfaces and/or trees exist. The model will run ' // &
1868                           'without RTM (no shadows, no radiation reflections)'
1869          CALL message( 'init_3d_model', 'PA0348', 0, 1, 0, 6, 0 )
1870       ENDIF
1871!
1872!--    If required, initialize radiation interactions between surfaces
1873!--    via sky-view factors. This must be done before radiation is initialized.
1874       IF ( radiation_interactions )  CALL radiation_interaction_init
1875!
1876!--    Allocate array for storing the surface net radiation
1877       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_net )  .AND.                      &
1878                  surf_lsm_h%ns > 0  )   THEN
1879          ALLOCATE( surf_lsm_h%rad_net(1:surf_lsm_h%ns) )
1880          surf_lsm_h%rad_net = 0.0_wp 
1881       ENDIF
1882       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_net )  .AND.                      &
1883                  surf_usm_h%ns > 0  )  THEN
1884          ALLOCATE( surf_usm_h%rad_net(1:surf_usm_h%ns) )
1885          surf_usm_h%rad_net = 0.0_wp 
1886       ENDIF
1887       DO  l = 0, 3
1888          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_net )  .AND.                &
1889                     surf_lsm_v(l)%ns > 0  )  THEN
1890             ALLOCATE( surf_lsm_v(l)%rad_net(1:surf_lsm_v(l)%ns) )
1891             surf_lsm_v(l)%rad_net = 0.0_wp 
1892          ENDIF
1893          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_net )  .AND.                &
1894                     surf_usm_v(l)%ns > 0  )  THEN
1895             ALLOCATE( surf_usm_v(l)%rad_net(1:surf_usm_v(l)%ns) )
1896             surf_usm_v(l)%rad_net = 0.0_wp 
1897          ENDIF
1898       ENDDO
1899
1900
1901!
1902!--    Allocate array for storing the surface longwave (out) radiation change
1903       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_lw_out_change_0 )  .AND.          &
1904                  surf_lsm_h%ns > 0  )   THEN
1905          ALLOCATE( surf_lsm_h%rad_lw_out_change_0(1:surf_lsm_h%ns) )
1906          surf_lsm_h%rad_lw_out_change_0 = 0.0_wp 
1907       ENDIF
1908       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_lw_out_change_0 )  .AND.          &
1909                  surf_usm_h%ns > 0  )  THEN
1910          ALLOCATE( surf_usm_h%rad_lw_out_change_0(1:surf_usm_h%ns) )
1911          surf_usm_h%rad_lw_out_change_0 = 0.0_wp 
1912       ENDIF
1913       DO  l = 0, 3
1914          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_lw_out_change_0 )  .AND.    &
1915                     surf_lsm_v(l)%ns > 0  )  THEN
1916             ALLOCATE( surf_lsm_v(l)%rad_lw_out_change_0(1:surf_lsm_v(l)%ns) )
1917             surf_lsm_v(l)%rad_lw_out_change_0 = 0.0_wp 
1918          ENDIF
1919          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_lw_out_change_0 )  .AND.    &
1920                     surf_usm_v(l)%ns > 0  )  THEN
1921             ALLOCATE( surf_usm_v(l)%rad_lw_out_change_0(1:surf_usm_v(l)%ns) )
1922             surf_usm_v(l)%rad_lw_out_change_0 = 0.0_wp 
1923          ENDIF
1924       ENDDO
1925
1926!
1927!--    Allocate surface arrays for incoming/outgoing short/longwave radiation
1928       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_sw_in )  .AND.                    &
1929                  surf_lsm_h%ns > 0  )   THEN
1930          ALLOCATE( surf_lsm_h%rad_sw_in(1:surf_lsm_h%ns)  )
1931          ALLOCATE( surf_lsm_h%rad_sw_out(1:surf_lsm_h%ns) )
1932          ALLOCATE( surf_lsm_h%rad_sw_dir(1:surf_lsm_h%ns) )
1933          ALLOCATE( surf_lsm_h%rad_sw_dif(1:surf_lsm_h%ns) )
1934          ALLOCATE( surf_lsm_h%rad_sw_ref(1:surf_lsm_h%ns) )
1935          ALLOCATE( surf_lsm_h%rad_sw_res(1:surf_lsm_h%ns) )
1936          ALLOCATE( surf_lsm_h%rad_lw_in(1:surf_lsm_h%ns)  )
1937          ALLOCATE( surf_lsm_h%rad_lw_out(1:surf_lsm_h%ns) )
1938          ALLOCATE( surf_lsm_h%rad_lw_dif(1:surf_lsm_h%ns) )
1939          ALLOCATE( surf_lsm_h%rad_lw_ref(1:surf_lsm_h%ns) )
1940          ALLOCATE( surf_lsm_h%rad_lw_res(1:surf_lsm_h%ns) )
1941          surf_lsm_h%rad_sw_in  = 0.0_wp 
1942          surf_lsm_h%rad_sw_out = 0.0_wp 
1943          surf_lsm_h%rad_sw_dir = 0.0_wp 
1944          surf_lsm_h%rad_sw_dif = 0.0_wp 
1945          surf_lsm_h%rad_sw_ref = 0.0_wp 
1946          surf_lsm_h%rad_sw_res = 0.0_wp 
1947          surf_lsm_h%rad_lw_in  = 0.0_wp 
1948          surf_lsm_h%rad_lw_out = 0.0_wp 
1949          surf_lsm_h%rad_lw_dif = 0.0_wp 
1950          surf_lsm_h%rad_lw_ref = 0.0_wp 
1951          surf_lsm_h%rad_lw_res = 0.0_wp 
1952       ENDIF
1953       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_sw_in )  .AND.                    &
1954                  surf_usm_h%ns > 0  )  THEN
1955          ALLOCATE( surf_usm_h%rad_sw_in(1:surf_usm_h%ns)  )
1956          ALLOCATE( surf_usm_h%rad_sw_out(1:surf_usm_h%ns) )
1957          ALLOCATE( surf_usm_h%rad_sw_dir(1:surf_usm_h%ns) )
1958          ALLOCATE( surf_usm_h%rad_sw_dif(1:surf_usm_h%ns) )
1959          ALLOCATE( surf_usm_h%rad_sw_ref(1:surf_usm_h%ns) )
1960          ALLOCATE( surf_usm_h%rad_sw_res(1:surf_usm_h%ns) )
1961          ALLOCATE( surf_usm_h%rad_lw_in(1:surf_usm_h%ns)  )
1962          ALLOCATE( surf_usm_h%rad_lw_out(1:surf_usm_h%ns) )
1963          ALLOCATE( surf_usm_h%rad_lw_dif(1:surf_usm_h%ns) )
1964          ALLOCATE( surf_usm_h%rad_lw_ref(1:surf_usm_h%ns) )
1965          ALLOCATE( surf_usm_h%rad_lw_res(1:surf_usm_h%ns) )
1966          surf_usm_h%rad_sw_in  = 0.0_wp 
1967          surf_usm_h%rad_sw_out = 0.0_wp 
1968          surf_usm_h%rad_sw_dir = 0.0_wp 
1969          surf_usm_h%rad_sw_dif = 0.0_wp 
1970          surf_usm_h%rad_sw_ref = 0.0_wp 
1971          surf_usm_h%rad_sw_res = 0.0_wp 
1972          surf_usm_h%rad_lw_in  = 0.0_wp 
1973          surf_usm_h%rad_lw_out = 0.0_wp 
1974          surf_usm_h%rad_lw_dif = 0.0_wp 
1975          surf_usm_h%rad_lw_ref = 0.0_wp 
1976          surf_usm_h%rad_lw_res = 0.0_wp 
1977       ENDIF
1978       DO  l = 0, 3
1979          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_sw_in )  .AND.              &
1980                     surf_lsm_v(l)%ns > 0  )  THEN
1981             ALLOCATE( surf_lsm_v(l)%rad_sw_in(1:surf_lsm_v(l)%ns)  )
1982             ALLOCATE( surf_lsm_v(l)%rad_sw_out(1:surf_lsm_v(l)%ns) )
1983             ALLOCATE( surf_lsm_v(l)%rad_sw_dir(1:surf_lsm_v(l)%ns) )
1984             ALLOCATE( surf_lsm_v(l)%rad_sw_dif(1:surf_lsm_v(l)%ns) )
1985             ALLOCATE( surf_lsm_v(l)%rad_sw_ref(1:surf_lsm_v(l)%ns) )
1986             ALLOCATE( surf_lsm_v(l)%rad_sw_res(1:surf_lsm_v(l)%ns) )
1987
1988             ALLOCATE( surf_lsm_v(l)%rad_lw_in(1:surf_lsm_v(l)%ns)  )
1989             ALLOCATE( surf_lsm_v(l)%rad_lw_out(1:surf_lsm_v(l)%ns) )
1990             ALLOCATE( surf_lsm_v(l)%rad_lw_dif(1:surf_lsm_v(l)%ns) )
1991             ALLOCATE( surf_lsm_v(l)%rad_lw_ref(1:surf_lsm_v(l)%ns) )
1992             ALLOCATE( surf_lsm_v(l)%rad_lw_res(1:surf_lsm_v(l)%ns) )
1993
1994             surf_lsm_v(l)%rad_sw_in  = 0.0_wp 
1995             surf_lsm_v(l)%rad_sw_out = 0.0_wp
1996             surf_lsm_v(l)%rad_sw_dir = 0.0_wp
1997             surf_lsm_v(l)%rad_sw_dif = 0.0_wp
1998             surf_lsm_v(l)%rad_sw_ref = 0.0_wp
1999             surf_lsm_v(l)%rad_sw_res = 0.0_wp
2000
2001             surf_lsm_v(l)%rad_lw_in  = 0.0_wp 
2002             surf_lsm_v(l)%rad_lw_out = 0.0_wp 
2003             surf_lsm_v(l)%rad_lw_dif = 0.0_wp 
2004             surf_lsm_v(l)%rad_lw_ref = 0.0_wp 
2005             surf_lsm_v(l)%rad_lw_res = 0.0_wp 
2006          ENDIF
2007          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_sw_in )  .AND.              &
2008                     surf_usm_v(l)%ns > 0  )  THEN
2009             ALLOCATE( surf_usm_v(l)%rad_sw_in(1:surf_usm_v(l)%ns)  )
2010             ALLOCATE( surf_usm_v(l)%rad_sw_out(1:surf_usm_v(l)%ns) )
2011             ALLOCATE( surf_usm_v(l)%rad_sw_dir(1:surf_usm_v(l)%ns) )
2012             ALLOCATE( surf_usm_v(l)%rad_sw_dif(1:surf_usm_v(l)%ns) )
2013             ALLOCATE( surf_usm_v(l)%rad_sw_ref(1:surf_usm_v(l)%ns) )
2014             ALLOCATE( surf_usm_v(l)%rad_sw_res(1:surf_usm_v(l)%ns) )
2015             ALLOCATE( surf_usm_v(l)%rad_lw_in(1:surf_usm_v(l)%ns)  )
2016             ALLOCATE( surf_usm_v(l)%rad_lw_out(1:surf_usm_v(l)%ns) )
2017             ALLOCATE( surf_usm_v(l)%rad_lw_dif(1:surf_usm_v(l)%ns) )
2018             ALLOCATE( surf_usm_v(l)%rad_lw_ref(1:surf_usm_v(l)%ns) )
2019             ALLOCATE( surf_usm_v(l)%rad_lw_res(1:surf_usm_v(l)%ns) )
2020             surf_usm_v(l)%rad_sw_in  = 0.0_wp 
2021             surf_usm_v(l)%rad_sw_out = 0.0_wp
2022             surf_usm_v(l)%rad_sw_dir = 0.0_wp
2023             surf_usm_v(l)%rad_sw_dif = 0.0_wp
2024             surf_usm_v(l)%rad_sw_ref = 0.0_wp
2025             surf_usm_v(l)%rad_sw_res = 0.0_wp
2026             surf_usm_v(l)%rad_lw_in  = 0.0_wp 
2027             surf_usm_v(l)%rad_lw_out = 0.0_wp 
2028             surf_usm_v(l)%rad_lw_dif = 0.0_wp 
2029             surf_usm_v(l)%rad_lw_ref = 0.0_wp 
2030             surf_usm_v(l)%rad_lw_res = 0.0_wp 
2031          ENDIF
2032       ENDDO
2033!
2034!--    Fix net radiation in case of radiation_scheme = 'constant'
2035       IF ( radiation_scheme == 'constant' )  THEN
2036          IF ( ALLOCATED( surf_lsm_h%rad_net ) )                               &
2037             surf_lsm_h%rad_net    = net_radiation
2038          IF ( ALLOCATED( surf_usm_h%rad_net ) )                               &
2039             surf_usm_h%rad_net    = net_radiation
2040!
2041!--       Todo: weight with inclination angle
2042          DO  l = 0, 3
2043             IF ( ALLOCATED( surf_lsm_v(l)%rad_net ) )                         &
2044                surf_lsm_v(l)%rad_net = net_radiation
2045             IF ( ALLOCATED( surf_usm_v(l)%rad_net ) )                         &
2046                surf_usm_v(l)%rad_net = net_radiation
2047          ENDDO
2048!          radiation = .FALSE.
2049!
2050!--    Calculate orbital constants
2051       ELSE
2052          decl_1 = SIN(23.45_wp * pi / 180.0_wp)
2053          decl_2 = 2.0_wp * pi / 365.0_wp
2054          decl_3 = decl_2 * 81.0_wp
2055          lat    = latitude * pi / 180.0_wp
2056          lon    = longitude * pi / 180.0_wp
2057       ENDIF
2058
2059       IF ( radiation_scheme == 'clear-sky'  .OR.                              &
2060            radiation_scheme == 'constant')  THEN
2061
2062
2063!
2064!--       Allocate arrays for incoming/outgoing short/longwave radiation
2065          IF ( .NOT. ALLOCATED ( rad_sw_in ) )  THEN
2066             ALLOCATE ( rad_sw_in(0:0,nysg:nyng,nxlg:nxrg) )
2067          ENDIF
2068          IF ( .NOT. ALLOCATED ( rad_sw_out ) )  THEN
2069             ALLOCATE ( rad_sw_out(0:0,nysg:nyng,nxlg:nxrg) )
2070          ENDIF
2071
2072          IF ( .NOT. ALLOCATED ( rad_lw_in ) )  THEN
2073             ALLOCATE ( rad_lw_in(0:0,nysg:nyng,nxlg:nxrg) )
2074          ENDIF
2075          IF ( .NOT. ALLOCATED ( rad_lw_out ) )  THEN
2076             ALLOCATE ( rad_lw_out(0:0,nysg:nyng,nxlg:nxrg) )
2077          ENDIF
2078
2079!
2080!--       Allocate average arrays for incoming/outgoing short/longwave radiation
2081          IF ( .NOT. ALLOCATED ( rad_sw_in_av ) )  THEN
2082             ALLOCATE ( rad_sw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
2083          ENDIF
2084          IF ( .NOT. ALLOCATED ( rad_sw_out_av ) )  THEN
2085             ALLOCATE ( rad_sw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
2086          ENDIF
2087
2088          IF ( .NOT. ALLOCATED ( rad_lw_in_av ) )  THEN
2089             ALLOCATE ( rad_lw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
2090          ENDIF
2091          IF ( .NOT. ALLOCATED ( rad_lw_out_av ) )  THEN
2092             ALLOCATE ( rad_lw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
2093          ENDIF
2094!
2095!--       Allocate arrays for broadband albedo, and level 1 initialization
2096!--       via namelist paramter, unless not already allocated.
2097          IF ( .NOT. ALLOCATED(surf_lsm_h%albedo) )  THEN
2098             ALLOCATE( surf_lsm_h%albedo(0:2,1:surf_lsm_h%ns)     )
2099             surf_lsm_h%albedo    = albedo
2100          ENDIF
2101          IF ( .NOT. ALLOCATED(surf_usm_h%albedo) )  THEN
2102             ALLOCATE( surf_usm_h%albedo(0:2,1:surf_usm_h%ns)     )
2103             surf_usm_h%albedo    = albedo
2104          ENDIF
2105
2106          DO  l = 0, 3
2107             IF ( .NOT. ALLOCATED( surf_lsm_v(l)%albedo ) )  THEN
2108                ALLOCATE( surf_lsm_v(l)%albedo(0:2,1:surf_lsm_v(l)%ns) )
2109                surf_lsm_v(l)%albedo = albedo
2110             ENDIF
2111             IF ( .NOT. ALLOCATED( surf_usm_v(l)%albedo ) )  THEN
2112                ALLOCATE( surf_usm_v(l)%albedo(0:2,1:surf_usm_v(l)%ns) )
2113                surf_usm_v(l)%albedo = albedo
2114             ENDIF
2115          ENDDO
2116!
2117!--       Level 2 initialization of broadband albedo via given albedo_type.
2118!--       Only if albedo_type is non-zero. In case of urban surface and
2119!--       input data is read from ASCII file, albedo_type will be zero, so that
2120!--       albedo won't be overwritten.
2121          DO  m = 1, surf_lsm_h%ns
2122             IF ( surf_lsm_h%albedo_type(ind_veg_wall,m) /= 0 )                &
2123                surf_lsm_h%albedo(ind_veg_wall,m) =                            &
2124                           albedo_pars(2,surf_lsm_h%albedo_type(ind_veg_wall,m))
2125             IF ( surf_lsm_h%albedo_type(ind_pav_green,m) /= 0 )               &
2126                surf_lsm_h%albedo(ind_pav_green,m) =                           &
2127                           albedo_pars(2,surf_lsm_h%albedo_type(ind_pav_green,m))
2128             IF ( surf_lsm_h%albedo_type(ind_wat_win,m) /= 0 )                 &
2129                surf_lsm_h%albedo(ind_wat_win,m) =                             &
2130                           albedo_pars(2,surf_lsm_h%albedo_type(ind_wat_win,m))
2131          ENDDO
2132          DO  m = 1, surf_usm_h%ns
2133             IF ( surf_usm_h%albedo_type(ind_veg_wall,m) /= 0 )                &
2134                surf_usm_h%albedo(ind_veg_wall,m) =                            &
2135                           albedo_pars(2,surf_usm_h%albedo_type(ind_veg_wall,m))
2136             IF ( surf_usm_h%albedo_type(ind_pav_green,m) /= 0 )               &
2137                surf_usm_h%albedo(ind_pav_green,m) =                           &
2138                           albedo_pars(2,surf_usm_h%albedo_type(ind_pav_green,m))
2139             IF ( surf_usm_h%albedo_type(ind_wat_win,m) /= 0 )                 &
2140                surf_usm_h%albedo(ind_wat_win,m) =                             &
2141                           albedo_pars(2,surf_usm_h%albedo_type(ind_wat_win,m))
2142          ENDDO
2143
2144          DO  l = 0, 3
2145             DO  m = 1, surf_lsm_v(l)%ns
2146                IF ( surf_lsm_v(l)%albedo_type(ind_veg_wall,m) /= 0 )          &
2147                   surf_lsm_v(l)%albedo(ind_veg_wall,m) =                      &
2148                        albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_veg_wall,m))
2149                IF ( surf_lsm_v(l)%albedo_type(ind_pav_green,m) /= 0 )         &
2150                   surf_lsm_v(l)%albedo(ind_pav_green,m) =                     &
2151                        albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_pav_green,m))
2152                IF ( surf_lsm_v(l)%albedo_type(ind_wat_win,m) /= 0 )           &
2153                   surf_lsm_v(l)%albedo(ind_wat_win,m) =                       &
2154                        albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_wat_win,m))
2155             ENDDO
2156             DO  m = 1, surf_usm_v(l)%ns
2157                IF ( surf_usm_v(l)%albedo_type(ind_veg_wall,m) /= 0 )          &
2158                   surf_usm_v(l)%albedo(ind_veg_wall,m) =                      &
2159                        albedo_pars(2,surf_usm_v(l)%albedo_type(ind_veg_wall,m))
2160                IF ( surf_usm_v(l)%albedo_type(ind_pav_green,m) /= 0 )         &
2161                   surf_usm_v(l)%albedo(ind_pav_green,m) =                     &
2162                        albedo_pars(2,surf_usm_v(l)%albedo_type(ind_pav_green,m))
2163                IF ( surf_usm_v(l)%albedo_type(ind_wat_win,m) /= 0 )           &
2164                   surf_usm_v(l)%albedo(ind_wat_win,m) =                       &
2165                        albedo_pars(2,surf_usm_v(l)%albedo_type(ind_wat_win,m))
2166             ENDDO
2167          ENDDO
2168
2169!
2170!--       Level 3 initialization at grid points where albedo type is zero.
2171!--       This case, albedo is taken from file. In case of constant radiation
2172!--       or clear sky, only broadband albedo is given.
2173          IF ( albedo_pars_f%from_file )  THEN
2174!
2175!--          Horizontal surfaces
2176             DO  m = 1, surf_lsm_h%ns
2177                i = surf_lsm_h%i(m)
2178                j = surf_lsm_h%j(m)
2179                IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2180                   IF ( surf_lsm_h%albedo_type(ind_veg_wall,m) == 0 )          &
2181                      surf_lsm_h%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2182                   IF ( surf_lsm_h%albedo_type(ind_pav_green,m) == 0 )         &
2183                      surf_lsm_h%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2184                   IF ( surf_lsm_h%albedo_type(ind_wat_win,m) == 0 )           &
2185                      surf_lsm_h%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2186                ENDIF
2187             ENDDO
2188             DO  m = 1, surf_usm_h%ns
2189                i = surf_usm_h%i(m)
2190                j = surf_usm_h%j(m)
2191                IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2192                   IF ( surf_usm_h%albedo_type(ind_veg_wall,m) == 0 )          &
2193                      surf_usm_h%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2194                   IF ( surf_usm_h%albedo_type(ind_pav_green,m) == 0 )         &
2195                      surf_usm_h%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2196                   IF ( surf_usm_h%albedo_type(ind_wat_win,m) == 0 )           &
2197                      surf_usm_h%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2198                ENDIF
2199             ENDDO 
2200!
2201!--          Vertical surfaces           
2202             DO  l = 0, 3
2203
2204                ioff = surf_lsm_v(l)%ioff
2205                joff = surf_lsm_v(l)%joff
2206                DO  m = 1, surf_lsm_v(l)%ns
2207                   i = surf_lsm_v(l)%i(m) + ioff
2208                   j = surf_lsm_v(l)%j(m) + joff
2209                   IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2210                      IF ( surf_lsm_v(l)%albedo_type(ind_veg_wall,m) == 0 )    &
2211                         surf_lsm_v(l)%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2212                      IF ( surf_lsm_v(l)%albedo_type(ind_pav_green,m) == 0 )   &
2213                         surf_lsm_v(l)%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2214                      IF ( surf_lsm_v(l)%albedo_type(ind_wat_win,m) == 0 )     &
2215                         surf_lsm_v(l)%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2216                   ENDIF
2217                ENDDO
2218
2219                ioff = surf_usm_v(l)%ioff
2220                joff = surf_usm_v(l)%joff
2221                DO  m = 1, surf_usm_v(l)%ns
2222                   i = surf_usm_v(l)%i(m) + joff
2223                   j = surf_usm_v(l)%j(m) + joff
2224                   IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2225                      IF ( surf_usm_v(l)%albedo_type(ind_veg_wall,m) == 0 )    &
2226                         surf_usm_v(l)%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2227                      IF ( surf_usm_v(l)%albedo_type(ind_pav_green,m) == 0 )   &
2228                         surf_usm_v(l)%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2229                      IF ( surf_usm_v(l)%albedo_type(ind_wat_win,m) == 0 )     &
2230                         surf_usm_v(l)%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2231                   ENDIF
2232                ENDDO
2233             ENDDO
2234
2235          ENDIF 
2236!
2237!--    Initialization actions for RRTMG
2238       ELSEIF ( radiation_scheme == 'rrtmg' )  THEN
2239#if defined ( __rrtmg )
2240!
2241!--       Allocate albedos for short/longwave radiation, horizontal surfaces
2242!--       for wall/green/window (USM) or vegetation/pavement/water surfaces
2243!--       (LSM).
2244          ALLOCATE ( surf_lsm_h%aldif(0:2,1:surf_lsm_h%ns)       )
2245          ALLOCATE ( surf_lsm_h%aldir(0:2,1:surf_lsm_h%ns)       )
2246          ALLOCATE ( surf_lsm_h%asdif(0:2,1:surf_lsm_h%ns)       )
2247          ALLOCATE ( surf_lsm_h%asdir(0:2,1:surf_lsm_h%ns)       )
2248          ALLOCATE ( surf_lsm_h%rrtm_aldif(0:2,1:surf_lsm_h%ns)  )
2249          ALLOCATE ( surf_lsm_h%rrtm_aldir(0:2,1:surf_lsm_h%ns)  )
2250          ALLOCATE ( surf_lsm_h%rrtm_asdif(0:2,1:surf_lsm_h%ns)  )
2251          ALLOCATE ( surf_lsm_h%rrtm_asdir(0:2,1:surf_lsm_h%ns)  )
2252
2253          ALLOCATE ( surf_usm_h%aldif(0:2,1:surf_usm_h%ns)       )
2254          ALLOCATE ( surf_usm_h%aldir(0:2,1:surf_usm_h%ns)       )
2255          ALLOCATE ( surf_usm_h%asdif(0:2,1:surf_usm_h%ns)       )
2256          ALLOCATE ( surf_usm_h%asdir(0:2,1:surf_usm_h%ns)       )
2257          ALLOCATE ( surf_usm_h%rrtm_aldif(0:2,1:surf_usm_h%ns)  )
2258          ALLOCATE ( surf_usm_h%rrtm_aldir(0:2,1:surf_usm_h%ns)  )
2259          ALLOCATE ( surf_usm_h%rrtm_asdif(0:2,1:surf_usm_h%ns)  )
2260          ALLOCATE ( surf_usm_h%rrtm_asdir(0:2,1:surf_usm_h%ns)  )
2261
2262!
2263!--       Allocate broadband albedo (temporary for the current radiation
2264!--       implementations)
2265          IF ( .NOT. ALLOCATED(surf_lsm_h%albedo) )                            &
2266             ALLOCATE( surf_lsm_h%albedo(0:2,1:surf_lsm_h%ns)     )
2267          IF ( .NOT. ALLOCATED(surf_usm_h%albedo) )                            &
2268             ALLOCATE( surf_usm_h%albedo(0:2,1:surf_usm_h%ns)     )
2269
2270!
2271!--       Allocate albedos for short/longwave radiation, vertical surfaces
2272          DO  l = 0, 3
2273
2274             ALLOCATE ( surf_lsm_v(l)%aldif(0:2,1:surf_lsm_v(l)%ns)      )
2275             ALLOCATE ( surf_lsm_v(l)%aldir(0:2,1:surf_lsm_v(l)%ns)      )
2276             ALLOCATE ( surf_lsm_v(l)%asdif(0:2,1:surf_lsm_v(l)%ns)      )
2277             ALLOCATE ( surf_lsm_v(l)%asdir(0:2,1:surf_lsm_v(l)%ns)      )
2278
2279             ALLOCATE ( surf_lsm_v(l)%rrtm_aldif(0:2,1:surf_lsm_v(l)%ns) )
2280             ALLOCATE ( surf_lsm_v(l)%rrtm_aldir(0:2,1:surf_lsm_v(l)%ns) )
2281             ALLOCATE ( surf_lsm_v(l)%rrtm_asdif(0:2,1:surf_lsm_v(l)%ns) )
2282             ALLOCATE ( surf_lsm_v(l)%rrtm_asdir(0:2,1:surf_lsm_v(l)%ns) )
2283
2284             ALLOCATE ( surf_usm_v(l)%aldif(0:2,1:surf_usm_v(l)%ns)      )
2285             ALLOCATE ( surf_usm_v(l)%aldir(0:2,1:surf_usm_v(l)%ns)      )
2286             ALLOCATE ( surf_usm_v(l)%asdif(0:2,1:surf_usm_v(l)%ns)      )
2287             ALLOCATE ( surf_usm_v(l)%asdir(0:2,1:surf_usm_v(l)%ns)      )
2288
2289             ALLOCATE ( surf_usm_v(l)%rrtm_aldif(0:2,1:surf_usm_v(l)%ns) )
2290             ALLOCATE ( surf_usm_v(l)%rrtm_aldir(0:2,1:surf_usm_v(l)%ns) )
2291             ALLOCATE ( surf_usm_v(l)%rrtm_asdif(0:2,1:surf_usm_v(l)%ns) )
2292             ALLOCATE ( surf_usm_v(l)%rrtm_asdir(0:2,1:surf_usm_v(l)%ns) )
2293!
2294!--          Allocate broadband albedo (temporary for the current radiation
2295!--          implementations)
2296             IF ( .NOT. ALLOCATED( surf_lsm_v(l)%albedo ) )                    &
2297                ALLOCATE( surf_lsm_v(l)%albedo(0:2,1:surf_lsm_v(l)%ns) )
2298             IF ( .NOT. ALLOCATED( surf_usm_v(l)%albedo ) )                    &
2299                ALLOCATE( surf_usm_v(l)%albedo(0:2,1:surf_usm_v(l)%ns) )
2300
2301          ENDDO
2302!
2303!--       Level 1 initialization of spectral albedos via namelist
2304!--       paramters. Please note, this case all surface tiles are initialized
2305!--       the same.
2306          IF ( surf_lsm_h%ns > 0 )  THEN
2307             surf_lsm_h%aldif  = albedo_lw_dif
2308             surf_lsm_h%aldir  = albedo_lw_dir
2309             surf_lsm_h%asdif  = albedo_sw_dif
2310             surf_lsm_h%asdir  = albedo_sw_dir
2311             surf_lsm_h%albedo = albedo_sw_dif
2312          ENDIF
2313          IF ( surf_usm_h%ns > 0 )  THEN
2314             IF ( surf_usm_h%albedo_from_ascii )  THEN
2315                surf_usm_h%aldif  = surf_usm_h%albedo
2316                surf_usm_h%aldir  = surf_usm_h%albedo
2317                surf_usm_h%asdif  = surf_usm_h%albedo
2318                surf_usm_h%asdir  = surf_usm_h%albedo
2319             ELSE
2320                surf_usm_h%aldif  = albedo_lw_dif
2321                surf_usm_h%aldir  = albedo_lw_dir
2322                surf_usm_h%asdif  = albedo_sw_dif
2323                surf_usm_h%asdir  = albedo_sw_dir
2324                surf_usm_h%albedo = albedo_sw_dif
2325             ENDIF
2326          ENDIF
2327
2328          DO  l = 0, 3
2329
2330             IF ( surf_lsm_v(l)%ns > 0 )  THEN
2331                surf_lsm_v(l)%aldif  = albedo_lw_dif
2332                surf_lsm_v(l)%aldir  = albedo_lw_dir
2333                surf_lsm_v(l)%asdif  = albedo_sw_dif
2334                surf_lsm_v(l)%asdir  = albedo_sw_dir
2335                surf_lsm_v(l)%albedo = albedo_sw_dif
2336             ENDIF
2337
2338             IF ( surf_usm_v(l)%ns > 0 )  THEN
2339                IF ( surf_usm_v(l)%albedo_from_ascii )  THEN
2340                   surf_usm_v(l)%aldif  = surf_usm_v(l)%albedo
2341                   surf_usm_v(l)%aldir  = surf_usm_v(l)%albedo
2342                   surf_usm_v(l)%asdif  = surf_usm_v(l)%albedo
2343                   surf_usm_v(l)%asdir  = surf_usm_v(l)%albedo
2344                ELSE
2345                   surf_usm_v(l)%aldif  = albedo_lw_dif
2346                   surf_usm_v(l)%aldir  = albedo_lw_dir
2347                   surf_usm_v(l)%asdif  = albedo_sw_dif
2348                   surf_usm_v(l)%asdir  = albedo_sw_dir
2349                ENDIF
2350             ENDIF
2351          ENDDO
2352
2353!
2354!--       Level 2 initialization of spectral albedos via albedo_type.
2355!--       Please note, for natural- and urban-type surfaces, a tile approach
2356!--       is applied so that the resulting albedo is calculated via the weighted
2357!--       average of respective surface fractions.
2358          DO  m = 1, surf_lsm_h%ns
2359!
2360!--          Spectral albedos for vegetation/pavement/water surfaces
2361             DO  ind_type = 0, 2
2362                IF ( surf_lsm_h%albedo_type(ind_type,m) /= 0 )  THEN
2363                   surf_lsm_h%aldif(ind_type,m) =                              &
2364                               albedo_pars(0,surf_lsm_h%albedo_type(ind_type,m))
2365                   surf_lsm_h%asdif(ind_type,m) =                              &
2366                               albedo_pars(1,surf_lsm_h%albedo_type(ind_type,m))
2367                   surf_lsm_h%aldir(ind_type,m) =                              &
2368                               albedo_pars(0,surf_lsm_h%albedo_type(ind_type,m))
2369                   surf_lsm_h%asdir(ind_type,m) =                              &
2370                               albedo_pars(1,surf_lsm_h%albedo_type(ind_type,m))
2371                   surf_lsm_h%albedo(ind_type,m) =                             &
2372                               albedo_pars(2,surf_lsm_h%albedo_type(ind_type,m))
2373                ENDIF
2374             ENDDO
2375
2376          ENDDO
2377!
2378!--       For urban surface only if albedo has not been already initialized
2379!--       in the urban-surface model via the ASCII file.
2380          IF ( .NOT. surf_usm_h%albedo_from_ascii )  THEN
2381             DO  m = 1, surf_usm_h%ns
2382!
2383!--             Spectral albedos for wall/green/window surfaces
2384                DO  ind_type = 0, 2
2385                   IF ( surf_usm_h%albedo_type(ind_type,m) /= 0 )  THEN
2386                      surf_usm_h%aldif(ind_type,m) =                           &
2387                               albedo_pars(0,surf_usm_h%albedo_type(ind_type,m))
2388                      surf_usm_h%asdif(ind_type,m) =                           &
2389                               albedo_pars(1,surf_usm_h%albedo_type(ind_type,m))
2390                      surf_usm_h%aldir(ind_type,m) =                           &
2391                               albedo_pars(0,surf_usm_h%albedo_type(ind_type,m))
2392                      surf_usm_h%asdir(ind_type,m) =                           &
2393                               albedo_pars(1,surf_usm_h%albedo_type(ind_type,m))
2394                      surf_usm_h%albedo(ind_type,m) =                          &
2395                               albedo_pars(2,surf_usm_h%albedo_type(ind_type,m))
2396                   ENDIF
2397                ENDDO
2398
2399             ENDDO
2400          ENDIF
2401
2402          DO l = 0, 3
2403
2404             DO  m = 1, surf_lsm_v(l)%ns
2405!
2406!--             Spectral albedos for vegetation/pavement/water surfaces
2407                DO  ind_type = 0, 2
2408                   IF ( surf_lsm_v(l)%albedo_type(ind_type,m) /= 0 )  THEN
2409                      surf_lsm_v(l)%aldif(ind_type,m) =                        &
2410                            albedo_pars(0,surf_lsm_v(l)%albedo_type(ind_type,m))
2411                      surf_lsm_v(l)%asdif(ind_type,m) =                        &
2412                            albedo_pars(1,surf_lsm_v(l)%albedo_type(ind_type,m))
2413                      surf_lsm_v(l)%aldir(ind_type,m) =                        &
2414                            albedo_pars(0,surf_lsm_v(l)%albedo_type(ind_type,m))
2415                      surf_lsm_v(l)%asdir(ind_type,m) =                        &
2416                            albedo_pars(1,surf_lsm_v(l)%albedo_type(ind_type,m))
2417                      surf_lsm_v(l)%albedo(ind_type,m) =                       &
2418                            albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_type,m))
2419                   ENDIF
2420                ENDDO
2421             ENDDO
2422!
2423!--          For urban surface only if albedo has not been already initialized
2424!--          in the urban-surface model via the ASCII file.
2425             IF ( .NOT. surf_usm_v(l)%albedo_from_ascii )  THEN
2426                DO  m = 1, surf_usm_v(l)%ns
2427!
2428!--                Spectral albedos for wall/green/window surfaces
2429                   DO  ind_type = 0, 2
2430                      IF ( surf_usm_v(l)%albedo_type(ind_type,m) /= 0 )  THEN
2431                         surf_usm_v(l)%aldif(ind_type,m) =                     &
2432                            albedo_pars(0,surf_usm_v(l)%albedo_type(ind_type,m))
2433                         surf_usm_v(l)%asdif(ind_type,m) =                     &
2434                            albedo_pars(1,surf_usm_v(l)%albedo_type(ind_type,m))
2435                         surf_usm_v(l)%aldir(ind_type,m) =                     &
2436                            albedo_pars(0,surf_usm_v(l)%albedo_type(ind_type,m))
2437                         surf_usm_v(l)%asdir(ind_type,m) =                     &
2438                            albedo_pars(1,surf_usm_v(l)%albedo_type(ind_type,m))
2439                         surf_usm_v(l)%albedo(ind_type,m) =                    &
2440                            albedo_pars(2,surf_usm_v(l)%albedo_type(ind_type,m))
2441                      ENDIF
2442                   ENDDO
2443
2444                ENDDO
2445             ENDIF
2446          ENDDO
2447!
2448!--       Level 3 initialization at grid points where albedo type is zero.
2449!--       This case, spectral albedos are taken from file if available
2450          IF ( albedo_pars_f%from_file )  THEN
2451!
2452!--          Horizontal
2453             DO  m = 1, surf_lsm_h%ns
2454                i = surf_lsm_h%i(m)
2455                j = surf_lsm_h%j(m)
2456!
2457!--             Spectral albedos for vegetation/pavement/water surfaces
2458                DO  ind_type = 0, 2
2459                   IF ( surf_lsm_h%albedo_type(ind_type,m) == 0 )  THEN
2460                      IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )&
2461                         surf_lsm_h%albedo(ind_type,m) =                       &
2462                                                albedo_pars_f%pars_xy(0,j,i)
2463                      IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2464                         surf_lsm_h%aldir(ind_type,m) =                        &
2465                                                albedo_pars_f%pars_xy(1,j,i)
2466                      IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2467                         surf_lsm_h%aldif(ind_type,m) =                        &
2468                                                albedo_pars_f%pars_xy(1,j,i)
2469                      IF ( albedo_pars_f%pars_xy(2,j,i) /= albedo_pars_f%fill )&
2470                         surf_lsm_h%asdir(ind_type,m) =                        &
2471                                                albedo_pars_f%pars_xy(2,j,i)
2472                      IF ( albedo_pars_f%pars_xy(2,j,i) /= albedo_pars_f%fill )&
2473                         surf_lsm_h%asdif(ind_type,m) =                        &
2474                                                albedo_pars_f%pars_xy(2,j,i)
2475                   ENDIF
2476                ENDDO
2477             ENDDO
2478!
2479!--          For urban surface only if albedo has not been already initialized
2480!--          in the urban-surface model via the ASCII file.
2481             IF ( .NOT. surf_usm_h%albedo_from_ascii )  THEN
2482                DO  m = 1, surf_usm_h%ns
2483                   i = surf_usm_h%i(m)
2484                   j = surf_usm_h%j(m)
2485!
2486!--                Broadband albedos for wall/green/window surfaces
2487                   DO  ind_type = 0, 2
2488                      IF ( surf_usm_h%albedo_type(ind_type,m) == 0 )  THEN
2489                         IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )&
2490                            surf_usm_h%albedo(ind_type,m) =                       &
2491                                                albedo_pars_f%pars_xy(0,j,i)
2492                      ENDIF
2493                   ENDDO
2494!
2495!--                Spectral albedos especially for building wall surfaces
2496                   IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )  THEN
2497                      surf_usm_h%aldir(ind_veg_wall,m) =                       &
2498                                                albedo_pars_f%pars_xy(1,j,i)
2499                      surf_usm_h%aldif(ind_veg_wall,m) =                       &
2500                                                albedo_pars_f%pars_xy(1,j,i)
2501                   ENDIF
2502                   IF ( albedo_pars_f%pars_xy(2,j,i) /= albedo_pars_f%fill )  THEN
2503                      surf_usm_h%asdir(ind_veg_wall,m) =                       &
2504                                                albedo_pars_f%pars_xy(2,j,i)
2505                      surf_usm_h%asdif(ind_veg_wall,m) =                       &
2506                                                albedo_pars_f%pars_xy(2,j,i)
2507                   ENDIF
2508!
2509!--                Spectral albedos especially for building green surfaces
2510                   IF ( albedo_pars_f%pars_xy(3,j,i) /= albedo_pars_f%fill )  THEN
2511                      surf_usm_h%aldir(ind_pav_green,m) =                      &
2512                                                albedo_pars_f%pars_xy(3,j,i)
2513                      surf_usm_h%aldif(ind_pav_green,m) =                      &
2514                                                albedo_pars_f%pars_xy(3,j,i)
2515                   ENDIF
2516                   IF ( albedo_pars_f%pars_xy(4,j,i) /= albedo_pars_f%fill )  THEN
2517                      surf_usm_h%asdir(ind_pav_green,m) =                      &
2518                                                albedo_pars_f%pars_xy(4,j,i)
2519                      surf_usm_h%asdif(ind_pav_green,m) =                      &
2520                                                albedo_pars_f%pars_xy(4,j,i)
2521                   ENDIF
2522!
2523!--                Spectral albedos especially for building window surfaces
2524                   IF ( albedo_pars_f%pars_xy(5,j,i) /= albedo_pars_f%fill )  THEN
2525                      surf_usm_h%aldir(ind_wat_win,m) =                        &
2526                                                albedo_pars_f%pars_xy(5,j,i)
2527                      surf_usm_h%aldif(ind_wat_win,m) =                        &
2528                                                albedo_pars_f%pars_xy(5,j,i)
2529                   ENDIF
2530                   IF ( albedo_pars_f%pars_xy(6,j,i) /= albedo_pars_f%fill )  THEN
2531                      surf_usm_h%asdir(ind_wat_win,m) =                        &
2532                                                albedo_pars_f%pars_xy(6,j,i)
2533                      surf_usm_h%asdif(ind_wat_win,m) =                        &
2534                                                albedo_pars_f%pars_xy(6,j,i)
2535                   ENDIF
2536
2537                ENDDO
2538             ENDIF
2539!
2540!--          Vertical
2541             DO  l = 0, 3
2542                ioff = surf_lsm_v(l)%ioff
2543                joff = surf_lsm_v(l)%joff
2544
2545                DO  m = 1, surf_lsm_v(l)%ns
2546                   i = surf_lsm_v(l)%i(m)
2547                   j = surf_lsm_v(l)%j(m)
2548!
2549!--                Spectral albedos for vegetation/pavement/water surfaces
2550                   DO  ind_type = 0, 2
2551                      IF ( surf_lsm_v(l)%albedo_type(ind_type,m) == 0 )  THEN
2552                         IF ( albedo_pars_f%pars_xy(0,j+joff,i+ioff) /=        &
2553                              albedo_pars_f%fill )                             &
2554                            surf_lsm_v(l)%albedo(ind_type,m) =                 &
2555                                          albedo_pars_f%pars_xy(0,j+joff,i+ioff)
2556                         IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2557                              albedo_pars_f%fill )                             &
2558                            surf_lsm_v(l)%aldir(ind_type,m) =                  &
2559                                          albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2560                         IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2561                              albedo_pars_f%fill )                             &
2562                            surf_lsm_v(l)%aldif(ind_type,m) =                  &
2563                                          albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2564                         IF ( albedo_pars_f%pars_xy(2,j+joff,i+ioff) /=        &
2565                              albedo_pars_f%fill )                             &
2566                            surf_lsm_v(l)%asdir(ind_type,m) =                  &
2567                                          albedo_pars_f%pars_xy(2,j+joff,i+ioff)
2568                         IF ( albedo_pars_f%pars_xy(2,j+joff,i+ioff) /=        &
2569                              albedo_pars_f%fill )                             &
2570                            surf_lsm_v(l)%asdif(ind_type,m) =                  &
2571                                          albedo_pars_f%pars_xy(2,j+joff,i+ioff)
2572                      ENDIF
2573                   ENDDO
2574                ENDDO
2575!
2576!--             For urban surface only if albedo has not been already initialized
2577!--             in the urban-surface model via the ASCII file.
2578                IF ( .NOT. surf_usm_v(l)%albedo_from_ascii )  THEN
2579                   ioff = surf_usm_v(l)%ioff
2580                   joff = surf_usm_v(l)%joff
2581
2582                   DO  m = 1, surf_usm_v(l)%ns
2583                      i = surf_usm_v(l)%i(m)
2584                      j = surf_usm_v(l)%j(m)
2585!
2586!--                   Broadband albedos for wall/green/window surfaces
2587                      DO  ind_type = 0, 2
2588                         IF ( surf_usm_v(l)%albedo_type(ind_type,m) == 0 )  THEN
2589                            IF ( albedo_pars_f%pars_xy(0,j+joff,i+ioff) /=     &
2590                                 albedo_pars_f%fill )                          &
2591                               surf_usm_v(l)%albedo(ind_type,m) =              &
2592                                             albedo_pars_f%pars_xy(0,j+joff,i+ioff)
2593                         ENDIF
2594                      ENDDO
2595!
2596!--                   Spectral albedos especially for building wall surfaces
2597                      IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=           &
2598                           albedo_pars_f%fill )  THEN
2599                         surf_usm_v(l)%aldir(ind_veg_wall,m) =                 &
2600                                         albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2601                         surf_usm_v(l)%aldif(ind_veg_wall,m) =                 &
2602                                         albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2603                      ENDIF
2604                      IF ( albedo_pars_f%pars_xy(2,j+joff,i+ioff) /=           &
2605                           albedo_pars_f%fill )  THEN
2606                         surf_usm_v(l)%asdir(ind_veg_wall,m) =                 &
2607                                         albedo_pars_f%pars_xy(2,j+joff,i+ioff)
2608                         surf_usm_v(l)%asdif(ind_veg_wall,m) =                 &
2609                                         albedo_pars_f%pars_xy(2,j+joff,i+ioff)
2610                      ENDIF
2611!                     
2612!--                   Spectral albedos especially for building green surfaces
2613                      IF ( albedo_pars_f%pars_xy(3,j+joff,i+ioff) /=           &
2614                           albedo_pars_f%fill )  THEN
2615                         surf_usm_v(l)%aldir(ind_pav_green,m) =                &
2616                                         albedo_pars_f%pars_xy(3,j+joff,i+ioff)
2617                         surf_usm_v(l)%aldif(ind_pav_green,m) =                &
2618                                         albedo_pars_f%pars_xy(3,j+joff,i+ioff)
2619                      ENDIF
2620                      IF ( albedo_pars_f%pars_xy(4,j+joff,i+ioff) /=           &
2621                           albedo_pars_f%fill )  THEN
2622                         surf_usm_v(l)%asdir(ind_pav_green,m) =                &
2623                                         albedo_pars_f%pars_xy(4,j+joff,i+ioff)
2624                         surf_usm_v(l)%asdif(ind_pav_green,m) =                &
2625                                         albedo_pars_f%pars_xy(4,j+joff,i+ioff)
2626                      ENDIF
2627!                     
2628!--                   Spectral albedos especially for building window surfaces
2629                      IF ( albedo_pars_f%pars_xy(5,j+joff,i+ioff) /=           &
2630                           albedo_pars_f%fill )  THEN
2631                         surf_usm_v(l)%aldir(ind_wat_win,m) =                  &
2632                                         albedo_pars_f%pars_xy(5,j+joff,i+ioff)
2633                         surf_usm_v(l)%aldif(ind_wat_win,m) =                  &
2634                                         albedo_pars_f%pars_xy(5,j+joff,i+ioff)
2635                      ENDIF
2636                      IF ( albedo_pars_f%pars_xy(6,j+joff,i+ioff) /=           &
2637                           albedo_pars_f%fill )  THEN
2638                         surf_usm_v(l)%asdir(ind_wat_win,m) =                  &
2639                                         albedo_pars_f%pars_xy(6,j+joff,i+ioff)
2640                         surf_usm_v(l)%asdif(ind_wat_win,m) =                  &
2641                                         albedo_pars_f%pars_xy(6,j+joff,i+ioff)
2642                      ENDIF
2643                   ENDDO
2644                ENDIF
2645             ENDDO
2646
2647          ENDIF
2648
2649!
2650!--       Calculate initial values of current (cosine of) the zenith angle and
2651!--       whether the sun is up
2652          CALL calc_zenith
2653!
2654!--       readjust date and time to its initial value
2655          CALL init_date_and_time
2656!
2657!--       Calculate initial surface albedo for different surfaces
2658          IF ( .NOT. constant_albedo )  THEN
2659#if defined( __netcdf )
2660!
2661!--          Horizontally aligned natural and urban surfaces
2662             CALL calc_albedo( surf_lsm_h )
2663             CALL calc_albedo( surf_usm_h )
2664!
2665!--          Vertically aligned natural and urban surfaces
2666             DO  l = 0, 3
2667                CALL calc_albedo( surf_lsm_v(l) )
2668                CALL calc_albedo( surf_usm_v(l) )
2669             ENDDO
2670#endif
2671          ELSE
2672!
2673!--          Initialize sun-inclination independent spectral albedos
2674!--          Horizontal surfaces
2675             IF ( surf_lsm_h%ns > 0 )  THEN
2676                surf_lsm_h%rrtm_aldir = surf_lsm_h%aldir
2677                surf_lsm_h%rrtm_asdir = surf_lsm_h%asdir
2678                surf_lsm_h%rrtm_aldif = surf_lsm_h%aldif
2679                surf_lsm_h%rrtm_asdif = surf_lsm_h%asdif
2680             ENDIF
2681             IF ( surf_usm_h%ns > 0 )  THEN
2682                surf_usm_h%rrtm_aldir = surf_usm_h%aldir
2683                surf_usm_h%rrtm_asdir = surf_usm_h%asdir
2684                surf_usm_h%rrtm_aldif = surf_usm_h%aldif
2685                surf_usm_h%rrtm_asdif = surf_usm_h%asdif
2686             ENDIF
2687!
2688!--          Vertical surfaces
2689             DO  l = 0, 3
2690                IF ( surf_lsm_v(l)%ns > 0 )  THEN
2691                   surf_lsm_v(l)%rrtm_aldir = surf_lsm_v(l)%aldir
2692                   surf_lsm_v(l)%rrtm_asdir = surf_lsm_v(l)%asdir
2693                   surf_lsm_v(l)%rrtm_aldif = surf_lsm_v(l)%aldif
2694                   surf_lsm_v(l)%rrtm_asdif = surf_lsm_v(l)%asdif
2695                ENDIF
2696                IF ( surf_usm_v(l)%ns > 0 )  THEN
2697                   surf_usm_v(l)%rrtm_aldir = surf_usm_v(l)%aldir
2698                   surf_usm_v(l)%rrtm_asdir = surf_usm_v(l)%asdir
2699                   surf_usm_v(l)%rrtm_aldif = surf_usm_v(l)%aldif
2700                   surf_usm_v(l)%rrtm_asdif = surf_usm_v(l)%asdif
2701                ENDIF
2702             ENDDO
2703
2704          ENDIF
2705
2706!
2707!--       Allocate 3d arrays of radiative fluxes and heating rates
2708          IF ( .NOT. ALLOCATED ( rad_sw_in ) )  THEN
2709             ALLOCATE ( rad_sw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2710             rad_sw_in = 0.0_wp
2711          ENDIF
2712
2713          IF ( .NOT. ALLOCATED ( rad_sw_in_av ) )  THEN
2714             ALLOCATE ( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2715          ENDIF
2716
2717          IF ( .NOT. ALLOCATED ( rad_sw_out ) )  THEN
2718             ALLOCATE ( rad_sw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2719             rad_sw_out = 0.0_wp
2720          ENDIF
2721
2722          IF ( .NOT. ALLOCATED ( rad_sw_out_av ) )  THEN
2723             ALLOCATE ( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2724          ENDIF
2725
2726          IF ( .NOT. ALLOCATED ( rad_sw_hr ) )  THEN
2727             ALLOCATE ( rad_sw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2728             rad_sw_hr = 0.0_wp
2729          ENDIF
2730
2731          IF ( .NOT. ALLOCATED ( rad_sw_hr_av ) )  THEN
2732             ALLOCATE ( rad_sw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2733             rad_sw_hr_av = 0.0_wp
2734          ENDIF
2735
2736          IF ( .NOT. ALLOCATED ( rad_sw_cs_hr ) )  THEN
2737             ALLOCATE ( rad_sw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2738             rad_sw_cs_hr = 0.0_wp
2739          ENDIF
2740
2741          IF ( .NOT. ALLOCATED ( rad_sw_cs_hr_av ) )  THEN
2742             ALLOCATE ( rad_sw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2743             rad_sw_cs_hr_av = 0.0_wp
2744          ENDIF
2745
2746          IF ( .NOT. ALLOCATED ( rad_lw_in ) )  THEN
2747             ALLOCATE ( rad_lw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2748             rad_lw_in = 0.0_wp
2749          ENDIF
2750
2751          IF ( .NOT. ALLOCATED ( rad_lw_in_av ) )  THEN
2752             ALLOCATE ( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2753          ENDIF
2754
2755          IF ( .NOT. ALLOCATED ( rad_lw_out ) )  THEN
2756             ALLOCATE ( rad_lw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2757            rad_lw_out = 0.0_wp
2758          ENDIF
2759
2760          IF ( .NOT. ALLOCATED ( rad_lw_out_av ) )  THEN
2761             ALLOCATE ( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2762          ENDIF
2763
2764          IF ( .NOT. ALLOCATED ( rad_lw_hr ) )  THEN
2765             ALLOCATE ( rad_lw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2766             rad_lw_hr = 0.0_wp
2767          ENDIF
2768
2769          IF ( .NOT. ALLOCATED ( rad_lw_hr_av ) )  THEN
2770             ALLOCATE ( rad_lw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2771             rad_lw_hr_av = 0.0_wp
2772          ENDIF
2773
2774          IF ( .NOT. ALLOCATED ( rad_lw_cs_hr ) )  THEN
2775             ALLOCATE ( rad_lw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2776             rad_lw_cs_hr = 0.0_wp
2777          ENDIF
2778
2779          IF ( .NOT. ALLOCATED ( rad_lw_cs_hr_av ) )  THEN
2780             ALLOCATE ( rad_lw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2781             rad_lw_cs_hr_av = 0.0_wp
2782          ENDIF
2783
2784          ALLOCATE ( rad_sw_cs_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2785          ALLOCATE ( rad_sw_cs_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2786          rad_sw_cs_in  = 0.0_wp
2787          rad_sw_cs_out = 0.0_wp
2788
2789          ALLOCATE ( rad_lw_cs_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2790          ALLOCATE ( rad_lw_cs_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2791          rad_lw_cs_in  = 0.0_wp
2792          rad_lw_cs_out = 0.0_wp
2793
2794!
2795!--       Allocate 1-element array for surface temperature
2796!--       (RRTMG anticipates an array as passed argument).
2797          ALLOCATE ( rrtm_tsfc(1) )
2798!
2799!--       Allocate surface emissivity.
2800!--       Values will be given directly before calling rrtm_lw.
2801          ALLOCATE ( rrtm_emis(0:0,1:nbndlw+1) )
2802
2803!
2804!--       Initialize RRTMG, before check if files are existent
2805          INQUIRE( FILE='rrtmg_lw.nc', EXIST=lw_exists )
2806          IF ( .NOT. lw_exists )  THEN
2807             message_string = 'Input file rrtmg_lw.nc' //                &
2808                            '&for rrtmg missing. ' // &
2809                            '&Please provide <jobname>_lsw file in the INPUT directory.'
2810             CALL message( 'radiation_init', 'PA0583', 1, 2, 0, 6, 0 )
2811          ENDIF         
2812          INQUIRE( FILE='rrtmg_sw.nc', EXIST=sw_exists )
2813          IF ( .NOT. sw_exists )  THEN
2814             message_string = 'Input file rrtmg_sw.nc' //                &
2815                            '&for rrtmg missing. ' // &
2816                            '&Please provide <jobname>_rsw file in the INPUT directory.'
2817             CALL message( 'radiation_init', 'PA0584', 1, 2, 0, 6, 0 )
2818          ENDIF         
2819         
2820          IF ( lw_radiation )  CALL rrtmg_lw_ini ( c_p )
2821          IF ( sw_radiation )  CALL rrtmg_sw_ini ( c_p )
2822         
2823!
2824!--       Set input files for RRTMG
2825          INQUIRE(FILE="RAD_SND_DATA", EXIST=snd_exists) 
2826          IF ( .NOT. snd_exists )  THEN
2827             rrtm_input_file = "rrtmg_lw.nc"
2828          ENDIF
2829
2830!
2831!--       Read vertical layers for RRTMG from sounding data
2832!--       The routine provides nzt_rad, hyp_snd(1:nzt_rad),
2833!--       t_snd(nzt+2:nzt_rad), rrtm_play(1:nzt_rad), rrtm_plev(1_nzt_rad+1),
2834!--       rrtm_tlay(nzt+2:nzt_rad), rrtm_tlev(nzt+2:nzt_rad+1)
2835          CALL read_sounding_data
2836
2837!
2838!--       Read trace gas profiles from file. This routine provides
2839!--       the rrtm_ arrays (1:nzt_rad+1)
2840          CALL read_trace_gas_data
2841#endif
2842       ENDIF
2843
2844!
2845!--    Perform user actions if required
2846       CALL user_init_radiation
2847
2848!
2849!--    Calculate radiative fluxes at model start
2850       SELECT CASE ( TRIM( radiation_scheme ) )
2851
2852          CASE ( 'rrtmg' )
2853             CALL radiation_rrtmg
2854
2855          CASE ( 'clear-sky' )
2856             CALL radiation_clearsky
2857
2858          CASE ( 'constant' )
2859             CALL radiation_constant
2860
2861          CASE DEFAULT
2862
2863       END SELECT
2864
2865! readjust date and time to its initial value
2866       CALL init_date_and_time
2867
2868!
2869!--    Find all discretized apparent solar positions for radiation interaction.
2870       IF ( radiation_interactions )  CALL radiation_presimulate_solar_pos
2871
2872!
2873!--    If required, read or calculate and write out the SVF
2874       IF ( radiation_interactions .AND. read_svf)  THEN
2875!
2876!--       Read sky-view factors and further required data from file
2877          CALL radiation_read_svf()
2878
2879       ELSEIF ( radiation_interactions .AND. .NOT. read_svf)  THEN
2880!
2881!--       calculate SFV and CSF
2882          CALL radiation_calc_svf()
2883       ENDIF
2884
2885       IF ( radiation_interactions .AND. write_svf)  THEN
2886!
2887!--       Write svf, csf svfsurf and csfsurf data to file
2888          CALL radiation_write_svf()
2889       ENDIF
2890
2891!
2892!--    Adjust radiative fluxes. In case of urban and land surfaces, also
2893!--    call an initial interaction.
2894       IF ( radiation_interactions )  THEN
2895          CALL radiation_interaction
2896       ENDIF
2897
2898       IF ( debug_output )  CALL debug_message( 'radiation_init', 'end' )
2899
2900       RETURN !todo: remove, I don't see what we need this for here
2901
2902    END SUBROUTINE radiation_init
2903
2904
2905!------------------------------------------------------------------------------!
2906! Description:
2907! ------------
2908!> A simple clear sky radiation model
2909!------------------------------------------------------------------------------!
2910    SUBROUTINE radiation_clearsky
2911
2912
2913       IMPLICIT NONE
2914
2915       INTEGER(iwp) ::  l         !< running index for surface orientation
2916       REAL(wp)     ::  pt1       !< potential temperature at first grid level or mean value at urban layer top
2917       REAL(wp)     ::  pt1_l     !< potential temperature at first grid level or mean value at urban layer top at local subdomain
2918       REAL(wp)     ::  ql1       !< liquid water mixing ratio at first grid level or mean value at urban layer top
2919       REAL(wp)     ::  ql1_l     !< liquid water mixing ratio at first grid level or mean value at urban layer top at local subdomain
2920
2921       TYPE(surf_type), POINTER ::  surf !< pointer on respective surface type, used to generalize routine   
2922
2923!
2924!--    Calculate current zenith angle
2925       CALL calc_zenith
2926
2927!
2928!--    Calculate sky transmissivity
2929       sky_trans = 0.6_wp + 0.2_wp * cos_zenith
2930
2931!
2932!--    Calculate value of the Exner function at model surface
2933!
2934!--    In case averaged radiation is used, calculate mean temperature and
2935!--    liquid water mixing ratio at the urban-layer top.
2936       IF ( average_radiation ) THEN
2937          pt1   = 0.0_wp
2938          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1   = 0.0_wp
2939
2940          pt1_l = SUM( pt(nz_urban_t,nys:nyn,nxl:nxr) )
2941          IF ( bulk_cloud_model  .OR.  cloud_droplets  )  ql1_l = SUM( ql(nz_urban_t,nys:nyn,nxl:nxr) )
2942
2943#if defined( __parallel )     
2944          IF ( collective_wait )  CALL MPI_BARRIER( comm2d, ierr )
2945          CALL MPI_ALLREDUCE( pt1_l, pt1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
2946          IF ( ierr /= 0 ) THEN
2947              WRITE(9,*) 'Error MPI_AllReduce1:', ierr, pt1_l, pt1
2948              FLUSH(9)
2949          ENDIF
2950
2951          IF ( bulk_cloud_model  .OR.  cloud_droplets ) THEN
2952              CALL MPI_ALLREDUCE( ql1_l, ql1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
2953              IF ( ierr /= 0 ) THEN
2954                  WRITE(9,*) 'Error MPI_AllReduce2:', ierr, ql1_l, ql1
2955                  FLUSH(9)
2956              ENDIF
2957          ENDIF
2958#else
2959          pt1 = pt1_l 
2960          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1 = ql1_l
2961#endif
2962
2963          IF ( bulk_cloud_model  .OR.  cloud_droplets  )  pt1 = pt1 + lv_d_cp / exner(nz_urban_t) * ql1
2964!
2965!--       Finally, divide by number of grid points
2966          pt1 = pt1 / REAL( ( nx + 1 ) * ( ny + 1 ), KIND=wp )
2967       ENDIF
2968!
2969!--    Call clear-sky calculation for each surface orientation.
2970!--    First, horizontal surfaces
2971       surf => surf_lsm_h
2972       CALL radiation_clearsky_surf
2973       surf => surf_usm_h
2974       CALL radiation_clearsky_surf
2975!
2976!--    Vertical surfaces
2977       DO  l = 0, 3
2978          surf => surf_lsm_v(l)
2979          CALL radiation_clearsky_surf
2980          surf => surf_usm_v(l)
2981          CALL radiation_clearsky_surf
2982       ENDDO
2983
2984       CONTAINS
2985
2986          SUBROUTINE radiation_clearsky_surf
2987
2988             IMPLICIT NONE
2989
2990             INTEGER(iwp) ::  i         !< index x-direction
2991             INTEGER(iwp) ::  j         !< index y-direction
2992             INTEGER(iwp) ::  k         !< index z-direction
2993             INTEGER(iwp) ::  m         !< running index for surface elements
2994
2995             IF ( surf%ns < 1 )  RETURN
2996
2997!
2998!--          Calculate radiation fluxes and net radiation (rad_net) assuming
2999!--          homogeneous urban radiation conditions.
3000             IF ( average_radiation ) THEN       
3001
3002                k = nz_urban_t
3003
3004                surf%rad_sw_in  = solar_constant * sky_trans * cos_zenith
3005                surf%rad_sw_out = albedo_urb * surf%rad_sw_in
3006               
3007                surf%rad_lw_in  = emissivity_atm_clsky * sigma_sb * (pt1 * exner(k+1))**4
3008
3009                surf%rad_lw_out = emissivity_urb * sigma_sb * (t_rad_urb)**4   &
3010                                    + (1.0_wp - emissivity_urb) * surf%rad_lw_in
3011
3012                surf%rad_net = surf%rad_sw_in - surf%rad_sw_out                &
3013                             + surf%rad_lw_in - surf%rad_lw_out
3014
3015                surf%rad_lw_out_change_0 = 4.0_wp * emissivity_urb * sigma_sb  &
3016                                           * (t_rad_urb)**3
3017
3018!
3019!--          Calculate radiation fluxes and net radiation (rad_net) for each surface
3020!--          element.
3021             ELSE
3022
3023                DO  m = 1, surf%ns
3024                   i = surf%i(m)
3025                   j = surf%j(m)
3026                   k = surf%k(m)
3027
3028                   surf%rad_sw_in(m) = solar_constant * sky_trans * cos_zenith
3029
3030!
3031!--                Weighted average according to surface fraction.
3032!--                ATTENTION: when radiation interactions are switched on the
3033!--                calculated fluxes below are not actually used as they are
3034!--                overwritten in radiation_interaction.
3035                   surf%rad_sw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
3036                                          surf%albedo(ind_veg_wall,m)          &
3037                                        + surf%frac(ind_pav_green,m) *         &
3038                                          surf%albedo(ind_pav_green,m)         &
3039                                        + surf%frac(ind_wat_win,m)   *         &
3040                                          surf%albedo(ind_wat_win,m) )         &
3041                                        * surf%rad_sw_in(m)
3042
3043                   surf%rad_lw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
3044                                          surf%emissivity(ind_veg_wall,m)      &
3045                                        + surf%frac(ind_pav_green,m) *         &
3046                                          surf%emissivity(ind_pav_green,m)     &
3047                                        + surf%frac(ind_wat_win,m)   *         &
3048                                          surf%emissivity(ind_wat_win,m)       &
3049                                        )                                      &
3050                                        * sigma_sb                             &
3051                                        * ( surf%pt_surface(m) * exner(nzb) )**4
3052
3053                   surf%rad_lw_out_change_0(m) =                               &
3054                                      ( surf%frac(ind_veg_wall,m)  *           &
3055                                        surf%emissivity(ind_veg_wall,m)        &
3056                                      + surf%frac(ind_pav_green,m) *           &
3057                                        surf%emissivity(ind_pav_green,m)       &
3058                                      + surf%frac(ind_wat_win,m)   *           &
3059                                        surf%emissivity(ind_wat_win,m)         &
3060                                      ) * 4.0_wp * sigma_sb                    &
3061                                      * ( surf%pt_surface(m) * exner(nzb) )** 3
3062
3063
3064                   IF ( bulk_cloud_model  .OR.  cloud_droplets  )  THEN
3065                      pt1 = pt(k,j,i) + lv_d_cp / exner(k) * ql(k,j,i)
3066                      surf%rad_lw_in(m)  = emissivity_atm_clsky * sigma_sb * (pt1 * exner(k))**4
3067                   ELSE
3068                      surf%rad_lw_in(m)  = emissivity_atm_clsky * sigma_sb * (pt(k,j,i) * exner(k))**4
3069                   ENDIF
3070
3071                   surf%rad_net(m) = surf%rad_sw_in(m) - surf%rad_sw_out(m)    &
3072                                   + surf%rad_lw_in(m) - surf%rad_lw_out(m)
3073
3074                ENDDO
3075
3076             ENDIF
3077
3078!
3079!--          Fill out values in radiation arrays
3080             DO  m = 1, surf%ns
3081                i = surf%i(m)
3082                j = surf%j(m)
3083                rad_sw_in(0,j,i) = surf%rad_sw_in(m)
3084                rad_sw_out(0,j,i) = surf%rad_sw_out(m)
3085                rad_lw_in(0,j,i) = surf%rad_lw_in(m)
3086                rad_lw_out(0,j,i) = surf%rad_lw_out(m)
3087             ENDDO
3088 
3089          END SUBROUTINE radiation_clearsky_surf
3090
3091    END SUBROUTINE radiation_clearsky
3092
3093
3094!------------------------------------------------------------------------------!
3095! Description:
3096! ------------
3097!> This scheme keeps the prescribed net radiation constant during the run
3098!------------------------------------------------------------------------------!
3099    SUBROUTINE radiation_constant
3100
3101
3102       IMPLICIT NONE
3103
3104       INTEGER(iwp) ::  l         !< running index for surface orientation
3105
3106       REAL(wp)     ::  pt1       !< potential temperature at first grid level or mean value at urban layer top
3107       REAL(wp)     ::  pt1_l     !< potential temperature at first grid level or mean value at urban layer top at local subdomain
3108       REAL(wp)     ::  ql1       !< liquid water mixing ratio at first grid level or mean value at urban layer top
3109       REAL(wp)     ::  ql1_l     !< liquid water mixing ratio at first grid level or mean value at urban layer top at local subdomain
3110
3111       TYPE(surf_type), POINTER ::  surf !< pointer on respective surface type, used to generalize routine
3112
3113!
3114!--    In case averaged radiation is used, calculate mean temperature and
3115!--    liquid water mixing ratio at the urban-layer top.
3116       IF ( average_radiation ) THEN   
3117          pt1   = 0.0_wp
3118          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1   = 0.0_wp
3119
3120          pt1_l = SUM( pt(nz_urban_t,nys:nyn,nxl:nxr) )
3121          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1_l = SUM( ql(nz_urban_t,nys:nyn,nxl:nxr) )
3122
3123#if defined( __parallel )     
3124          IF ( collective_wait )  CALL MPI_BARRIER( comm2d, ierr )
3125          CALL MPI_ALLREDUCE( pt1_l, pt1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
3126          IF ( ierr /= 0 ) THEN
3127              WRITE(9,*) 'Error MPI_AllReduce3:', ierr, pt1_l, pt1
3128              FLUSH(9)
3129          ENDIF
3130          IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
3131             CALL MPI_ALLREDUCE( ql1_l, ql1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
3132             IF ( ierr /= 0 ) THEN
3133                 WRITE(9,*) 'Error MPI_AllReduce4:', ierr, ql1_l, ql1
3134                 FLUSH(9)
3135             ENDIF
3136          ENDIF
3137#else
3138          pt1 = pt1_l
3139          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1 = ql1_l
3140#endif
3141          IF ( bulk_cloud_model  .OR.  cloud_droplets )  pt1 = pt1 + lv_d_cp / exner(nz_urban_t+1) * ql1
3142!
3143!--       Finally, divide by number of grid points
3144          pt1 = pt1 / REAL( ( nx + 1 ) * ( ny + 1 ), KIND=wp )
3145       ENDIF
3146
3147!
3148!--    First, horizontal surfaces
3149       surf => surf_lsm_h
3150       CALL radiation_constant_surf
3151       surf => surf_usm_h
3152       CALL radiation_constant_surf
3153!
3154!--    Vertical surfaces
3155       DO  l = 0, 3
3156          surf => surf_lsm_v(l)
3157          CALL radiation_constant_surf
3158          surf => surf_usm_v(l)
3159          CALL radiation_constant_surf
3160       ENDDO
3161
3162       CONTAINS
3163
3164          SUBROUTINE radiation_constant_surf
3165
3166             IMPLICIT NONE
3167
3168             INTEGER(iwp) ::  i         !< index x-direction
3169             INTEGER(iwp) ::  ioff      !< offset between surface element and adjacent grid point along x
3170             INTEGER(iwp) ::  j         !< index y-direction
3171             INTEGER(iwp) ::  joff      !< offset between surface element and adjacent grid point along y
3172             INTEGER(iwp) ::  k         !< index z-direction
3173             INTEGER(iwp) ::  koff      !< offset between surface element and adjacent grid point along z
3174             INTEGER(iwp) ::  m         !< running index for surface elements
3175
3176             IF ( surf%ns < 1 )  RETURN
3177
3178!--          Calculate homogenoeus urban radiation fluxes
3179             IF ( average_radiation ) THEN
3180
3181                surf%rad_net = net_radiation
3182
3183                surf%rad_lw_in  = emissivity_atm_clsky * sigma_sb * (pt1 * exner(nz_urban_t+1))**4
3184
3185                surf%rad_lw_out = emissivity_urb * sigma_sb * (t_rad_urb)**4   &
3186                                    + ( 1.0_wp - emissivity_urb )             & ! shouldn't be this a bulk value -- emissivity_urb?
3187                                    * surf%rad_lw_in
3188
3189                surf%rad_lw_out_change_0 = 4.0_wp * emissivity_urb * sigma_sb  &
3190                                           * t_rad_urb**3
3191
3192                surf%rad_sw_in = ( surf%rad_net - surf%rad_lw_in               &
3193                                     + surf%rad_lw_out )                       &
3194                                     / ( 1.0_wp - albedo_urb )
3195
3196                surf%rad_sw_out =  albedo_urb * surf%rad_sw_in
3197
3198!
3199!--          Calculate radiation fluxes for each surface element
3200             ELSE
3201!
3202!--             Determine index offset between surface element and adjacent
3203!--             atmospheric grid point
3204                ioff = surf%ioff
3205                joff = surf%joff
3206                koff = surf%koff
3207
3208!
3209!--             Prescribe net radiation and estimate the remaining radiative fluxes
3210                DO  m = 1, surf%ns
3211                   i = surf%i(m)
3212                   j = surf%j(m)
3213                   k = surf%k(m)
3214
3215                   surf%rad_net(m) = net_radiation
3216
3217                   IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
3218                      pt1 = pt(k,j,i) + lv_d_cp / exner(k) * ql(k,j,i)
3219                      surf%rad_lw_in(m)  = emissivity_atm_clsky * sigma_sb * (pt1 * exner(k))**4
3220                   ELSE
3221                      surf%rad_lw_in(m)  = emissivity_atm_clsky * sigma_sb *                 &
3222                                             ( pt(k,j,i) * exner(k) )**4
3223                   ENDIF
3224
3225!
3226!--                Weighted average according to surface fraction.
3227                   surf%rad_lw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
3228                                          surf%emissivity(ind_veg_wall,m)      &
3229                                        + surf%frac(ind_pav_green,m) *         &
3230                                          surf%emissivity(ind_pav_green,m)     &
3231                                        + surf%frac(ind_wat_win,m)   *         &
3232                                          surf%emissivity(ind_wat_win,m)       &
3233                                        )                                      &
3234                                      * sigma_sb                               &
3235                                      * ( surf%pt_surface(m) * exner(nzb) )**4
3236
3237                   surf%rad_sw_in(m) = ( surf%rad_net(m) - surf%rad_lw_in(m)   &
3238                                       + surf%rad_lw_out(m) )                  &
3239                                       / ( 1.0_wp -                            &
3240                                          ( surf%frac(ind_veg_wall,m)  *       &
3241                                            surf%albedo(ind_veg_wall,m)        &
3242                                         +  surf%frac(ind_pav_green,m) *       &
3243                                            surf%albedo(ind_pav_green,m)       &
3244                                         +  surf%frac(ind_wat_win,m)   *       &
3245                                            surf%albedo(ind_wat_win,m) )       &
3246                                         )
3247
3248                   surf%rad_sw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
3249                                          surf%albedo(ind_veg_wall,m)          &
3250                                        + surf%frac(ind_pav_green,m) *         &
3251                                          surf%albedo(ind_pav_green,m)         &
3252                                        + surf%frac(ind_wat_win,m)   *         &
3253                                          surf%albedo(ind_wat_win,m) )         &
3254                                      * surf%rad_sw_in(m)
3255
3256                ENDDO
3257
3258             ENDIF
3259
3260!
3261!--          Fill out values in radiation arrays
3262             DO  m = 1, surf%ns
3263                i = surf%i(m)
3264                j = surf%j(m)
3265                rad_sw_in(0,j,i) = surf%rad_sw_in(m)
3266                rad_sw_out(0,j,i) = surf%rad_sw_out(m)
3267                rad_lw_in(0,j,i) = surf%rad_lw_in(m)
3268                rad_lw_out(0,j,i) = surf%rad_lw_out(m)
3269             ENDDO
3270
3271          END SUBROUTINE radiation_constant_surf
3272         
3273
3274    END SUBROUTINE radiation_constant
3275
3276!------------------------------------------------------------------------------!
3277! Description:
3278! ------------
3279!> Header output for radiation model
3280!------------------------------------------------------------------------------!
3281    SUBROUTINE radiation_header ( io )
3282
3283
3284       IMPLICIT NONE
3285 
3286       INTEGER(iwp), INTENT(IN) ::  io            !< Unit of the output file
3287   
3288
3289       
3290!
3291!--    Write radiation model header
3292       WRITE( io, 3 )
3293
3294       IF ( radiation_scheme == "constant" )  THEN
3295          WRITE( io, 4 ) net_radiation
3296       ELSEIF ( radiation_scheme == "clear-sky" )  THEN
3297          WRITE( io, 5 )
3298       ELSEIF ( radiation_scheme == "rrtmg" )  THEN
3299          WRITE( io, 6 )
3300          IF ( .NOT. lw_radiation )  WRITE( io, 10 )
3301          IF ( .NOT. sw_radiation )  WRITE( io, 11 )
3302       ENDIF
3303
3304       IF ( albedo_type_f%from_file  .OR.  vegetation_type_f%from_file  .OR.   &
3305            pavement_type_f%from_file  .OR.  water_type_f%from_file  .OR.      &
3306            building_type_f%from_file )  THEN
3307             WRITE( io, 13 )
3308       ELSE 
3309          IF ( albedo_type == 0 )  THEN
3310             WRITE( io, 7 ) albedo
3311          ELSE
3312             WRITE( io, 8 ) TRIM( albedo_type_name(albedo_type) )
3313          ENDIF
3314       ENDIF
3315       IF ( constant_albedo )  THEN
3316          WRITE( io, 9 )
3317       ENDIF
3318       
3319       WRITE( io, 12 ) dt_radiation
3320 
3321
3322 3 FORMAT (//' Radiation model information:'/                                  &
3323              ' ----------------------------'/)
3324 4 FORMAT ('    --> Using constant net radiation: net_radiation = ', F6.2,     &
3325           // 'W/m**2')
3326 5 FORMAT ('    --> Simple radiation scheme for clear sky is used (no clouds,',&
3327                   ' default)')
3328 6 FORMAT ('    --> RRTMG scheme is used')
3329 7 FORMAT (/'    User-specific surface albedo: albedo =', F6.3)
3330 8 FORMAT (/'    Albedo is set for land surface type: ', A)
3331 9 FORMAT (/'    --> Albedo is fixed during the run')
333210 FORMAT (/'    --> Longwave radiation is disabled')
333311 FORMAT (/'    --> Shortwave radiation is disabled.')
333412 FORMAT  ('    Timestep: dt_radiation = ', F6.2, '  s')
333513 FORMAT (/'    Albedo is set individually for each xy-location, according ', &
3336                 'to given surface type.')
3337
3338
3339    END SUBROUTINE radiation_header
3340   
3341
3342!------------------------------------------------------------------------------!
3343! Description:
3344! ------------
3345!> Parin for &radiation_parameters for radiation model
3346!------------------------------------------------------------------------------!
3347    SUBROUTINE radiation_parin
3348
3349
3350       IMPLICIT NONE
3351
3352       CHARACTER (LEN=80) ::  line  !< dummy string that contains the current line of the parameter file
3353       
3354       NAMELIST /radiation_par/   albedo, albedo_lw_dif, albedo_lw_dir,         &
3355                                  albedo_sw_dif, albedo_sw_dir, albedo_type,    &
3356                                  constant_albedo, dt_radiation, emissivity,    &
3357                                  lw_radiation, max_raytracing_dist,            &
3358                                  min_irrf_value, mrt_geom_human,               &
3359                                  mrt_include_sw, mrt_nlevels,                  &
3360                                  mrt_skip_roof, net_radiation, nrefsteps,      &
3361                                  plant_lw_interact, rad_angular_discretization,&
3362                                  radiation_interactions_on, radiation_scheme,  &
3363                                  raytrace_discrete_azims,                      &
3364                                  raytrace_discrete_elevs, raytrace_mpi_rma,    &
3365                                  skip_time_do_radiation, surface_reflections,  &
3366                                  svfnorm_report_thresh, sw_radiation,          &
3367                                  unscheduled_radiation_calls
3368
3369   
3370       NAMELIST /radiation_parameters/ albedo, albedo_lw_dif, albedo_lw_dir,    &
3371                                  albedo_sw_dif, albedo_sw_dir, albedo_type,    &
3372                                  constant_albedo, dt_radiation, emissivity,    &
3373                                  lw_radiation, max_raytracing_dist,            &
3374                                  min_irrf_value, mrt_geom_human,               &
3375                                  mrt_include_sw, mrt_nlevels,                  &
3376                                  mrt_skip_roof, net_radiation, nrefsteps,      &
3377                                  plant_lw_interact, rad_angular_discretization,&
3378                                  radiation_interactions_on, radiation_scheme,  &
3379                                  raytrace_discrete_azims,                      &
3380                                  raytrace_discrete_elevs, raytrace_mpi_rma,    &
3381                                  skip_time_do_radiation, surface_reflections,  &
3382                                  svfnorm_report_thresh, sw_radiation,          &
3383                                  unscheduled_radiation_calls
3384   
3385       line = ' '
3386       
3387!
3388!--    Try to find radiation model namelist
3389       REWIND ( 11 )
3390       line = ' '
3391       DO WHILE ( INDEX( line, '&radiation_parameters' ) == 0 )
3392          READ ( 11, '(A)', END=12 )  line
3393       ENDDO
3394       BACKSPACE ( 11 )
3395
3396!
3397!--    Read user-defined namelist
3398       READ ( 11, radiation_parameters, ERR = 10 )
3399
3400!
3401!--    Set flag that indicates that the radiation model is switched on
3402       radiation = .TRUE.
3403
3404       GOTO 14
3405
3406 10    BACKSPACE( 11 )
3407       READ( 11 , '(A)') line
3408       CALL parin_fail_message( 'radiation_parameters', line )
3409!
3410!--    Try to find old namelist
3411 12    REWIND ( 11 )
3412       line = ' '
3413       DO WHILE ( INDEX( line, '&radiation_par' ) == 0 )
3414          READ ( 11, '(A)', END=14 )  line
3415       ENDDO
3416       BACKSPACE ( 11 )
3417
3418!
3419!--    Read user-defined namelist
3420       READ ( 11, radiation_par, ERR = 13, END = 14 )
3421
3422       message_string = 'namelist radiation_par is deprecated and will be ' // &
3423                     'removed in near future. Please use namelist ' //         &
3424                     'radiation_parameters instead'
3425       CALL message( 'radiation_parin', 'PA0487', 0, 1, 0, 6, 0 )
3426
3427!
3428!--    Set flag that indicates that the radiation model is switched on
3429       radiation = .TRUE.
3430
3431       IF ( .NOT.  radiation_interactions_on  .AND.  surface_reflections )  THEN
3432          message_string = 'surface_reflections is allowed only when '      // &
3433               'radiation_interactions_on is set to TRUE'
3434          CALL message( 'radiation_parin', 'PA0293',1, 2, 0, 6, 0 )
3435       ENDIF
3436
3437       GOTO 14
3438
3439 13    BACKSPACE( 11 )
3440       READ( 11 , '(A)') line
3441       CALL parin_fail_message( 'radiation_par', line )
3442
3443 14    CONTINUE
3444       
3445    END SUBROUTINE radiation_parin
3446
3447
3448!------------------------------------------------------------------------------!
3449! Description:
3450! ------------
3451!> Implementation of the RRTMG radiation_scheme
3452!------------------------------------------------------------------------------!
3453    SUBROUTINE radiation_rrtmg
3454
3455#if defined ( __rrtmg )
3456       USE indices,                                                            &
3457           ONLY:  nbgp
3458
3459       USE particle_attributes,                                                &
3460           ONLY:  grid_particles, number_of_particles, particles, prt_count
3461
3462       IMPLICIT NONE
3463
3464
3465       INTEGER(iwp) ::  i, j, k, l, m, n !< loop indices
3466       INTEGER(iwp) ::  k_topo     !< topography top index
3467
3468       REAL(wp)     ::  nc_rad, &    !< number concentration of cloud droplets
3469                        s_r2,   &    !< weighted sum over all droplets with r^2
3470                        s_r3         !< weighted sum over all droplets with r^3
3471
3472       REAL(wp), DIMENSION(0:nzt+1) :: pt_av, q_av, ql_av
3473       REAL(wp), DIMENSION(0:0)     :: zenith   !< to provide indexed array
3474!
3475!--    Just dummy arguments
3476       REAL(wp), DIMENSION(:,:,:), ALLOCATABLE :: rrtm_lw_taucld_dum,          &
3477                                                  rrtm_lw_tauaer_dum,          &
3478                                                  rrtm_sw_taucld_dum,          &
3479                                                  rrtm_sw_ssacld_dum,          &
3480                                                  rrtm_sw_asmcld_dum,          &
3481                                                  rrtm_sw_fsfcld_dum,          &
3482                                                  rrtm_sw_tauaer_dum,          &
3483                                                  rrtm_sw_ssaaer_dum,          &
3484                                                  rrtm_sw_asmaer_dum,          &
3485                                                  rrtm_sw_ecaer_dum
3486
3487!
3488!--    Calculate current (cosine of) zenith angle and whether the sun is up
3489       CALL calc_zenith     
3490       zenith(0) = cos_zenith
3491!
3492!--    Calculate surface albedo. In case average radiation is applied,
3493!--    this is not required.
3494#if defined( __netcdf )
3495       IF ( .NOT. constant_albedo )  THEN
3496!
3497!--       Horizontally aligned default, natural and urban surfaces
3498          CALL calc_albedo( surf_lsm_h    )
3499          CALL calc_albedo( surf_usm_h    )
3500!
3501!--       Vertically aligned default, natural and urban surfaces
3502          DO  l = 0, 3
3503             CALL calc_albedo( surf_lsm_v(l) )
3504             CALL calc_albedo( surf_usm_v(l) )
3505          ENDDO
3506       ENDIF
3507#endif
3508
3509!
3510!--    Prepare input data for RRTMG
3511
3512!
3513!--    In case of large scale forcing with surface data, calculate new pressure
3514!--    profile. nzt_rad might be modified by these calls and all required arrays
3515!--    will then be re-allocated
3516       IF ( large_scale_forcing  .AND.  lsf_surf )  THEN
3517          CALL read_sounding_data
3518          CALL read_trace_gas_data
3519       ENDIF
3520
3521
3522       IF ( average_radiation ) THEN
3523
3524          rrtm_asdir(1)  = albedo_urb
3525          rrtm_asdif(1)  = albedo_urb
3526          rrtm_aldir(1)  = albedo_urb
3527          rrtm_aldif(1)  = albedo_urb
3528
3529          rrtm_emis = emissivity_urb
3530!
3531!--       Calculate mean pt profile. Actually, only one height level is required.
3532          CALL calc_mean_profile( pt, 4 )
3533          pt_av = hom(:, 1, 4, 0)
3534         
3535          IF ( humidity )  THEN
3536             CALL calc_mean_profile( q, 41 )
3537             q_av  = hom(:, 1, 41, 0)
3538          ENDIF
3539!
3540!--       Prepare profiles of temperature and H2O volume mixing ratio
3541          rrtm_tlev(0,nzb+1) = t_rad_urb
3542
3543          IF ( bulk_cloud_model )  THEN
3544
3545             CALL calc_mean_profile( ql, 54 )
3546             ! average ql is now in hom(:, 1, 54, 0)
3547             ql_av = hom(:, 1, 54, 0)
3548             
3549             DO k = nzb+1, nzt+1
3550                rrtm_tlay(0,k) = pt_av(k) * ( (hyp(k) ) / 100000._wp       &
3551                                 )**.286_wp + lv_d_cp * ql_av(k)
3552                rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * (q_av(k) - ql_av(k))
3553             ENDDO
3554          ELSE
3555             DO k = nzb+1, nzt+1
3556                rrtm_tlay(0,k) = pt_av(k) * ( (hyp(k) ) / 100000._wp       &
3557                                 )**.286_wp
3558             ENDDO
3559
3560             IF ( humidity )  THEN
3561                DO k = nzb+1, nzt+1
3562                   rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * q_av(k)
3563                ENDDO
3564             ELSE
3565                rrtm_h2ovmr(0,nzb+1:nzt+1) = 0.0_wp
3566             ENDIF
3567          ENDIF
3568
3569!
3570!--       Avoid temperature/humidity jumps at the top of the PALM domain by
3571!--       linear interpolation from nzt+2 to nzt+7. Jumps are induced by
3572!--       discrepancies between the values in the  domain and those above that
3573!--       are prescribed in RRTMG
3574          DO k = nzt+2, nzt+7
3575             rrtm_tlay(0,k) = rrtm_tlay(0,nzt+1)                            &
3576                           + ( rrtm_tlay(0,nzt+8) - rrtm_tlay(0,nzt+1) )    &
3577                           / ( rrtm_play(0,nzt+8) - rrtm_play(0,nzt+1) )    &
3578                           * ( rrtm_play(0,k) - rrtm_play(0,nzt+1) )
3579
3580             rrtm_h2ovmr(0,k) = rrtm_h2ovmr(0,nzt+1)                        &
3581                           + ( rrtm_h2ovmr(0,nzt+8) - rrtm_h2ovmr(0,nzt+1) )&
3582                           / ( rrtm_play(0,nzt+8)   - rrtm_play(0,nzt+1)   )&
3583                           * ( rrtm_play(0,k) - rrtm_play(0,nzt+1) )
3584
3585          ENDDO
3586
3587!--       Linear interpolate to zw grid. Loop reaches one level further up
3588!--       due to the staggered grid in RRTMG
3589          DO k = nzb+2, nzt+8
3590             rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k) -        &
3591                                rrtm_tlay(0,k-1))                           &
3592                                / ( rrtm_play(0,k) - rrtm_play(0,k-1) )     &
3593                                * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
3594          ENDDO
3595
3596
3597!
3598!--       Calculate liquid water path and cloud fraction for each column.
3599!--       Note that LWP is required in g/m2 instead of kg/kg m.
3600          rrtm_cldfr  = 0.0_wp
3601          rrtm_reliq  = 0.0_wp
3602          rrtm_cliqwp = 0.0_wp
3603          rrtm_icld   = 0
3604
3605          IF ( bulk_cloud_model )  THEN
3606             DO k = nzb+1, nzt+1
3607                rrtm_cliqwp(0,k) =  ql_av(k) * 1000._wp *                   &
3608                                    (rrtm_plev(0,k) - rrtm_plev(0,k+1))     &
3609                                    * 100._wp / g 
3610
3611                IF ( rrtm_cliqwp(0,k) > 0._wp )  THEN
3612                   rrtm_cldfr(0,k) = 1._wp
3613                   IF ( rrtm_icld == 0 )  rrtm_icld = 1
3614
3615!
3616!--                Calculate cloud droplet effective radius
3617                   rrtm_reliq(0,k) = 1.0E6_wp * ( 3.0_wp * ql_av(k)         &
3618                                     * rho_surface                          &
3619                                     / ( 4.0_wp * pi * nc_const * rho_l )   &
3620                                     )**0.33333333333333_wp                 &
3621                                     * EXP( LOG( sigma_gc )**2 )
3622!
3623!--                Limit effective radius
3624                   IF ( rrtm_reliq(0,k) > 0.0_wp )  THEN
3625                      rrtm_reliq(0,k) = MAX(rrtm_reliq(0,k),2.5_wp)
3626                      rrtm_reliq(0,k) = MIN(rrtm_reliq(0,k),60.0_wp)
3627                   ENDIF
3628                ENDIF
3629             ENDDO
3630          ENDIF
3631
3632!
3633!--       Set surface temperature
3634          rrtm_tsfc = t_rad_urb
3635         
3636          IF ( lw_radiation )  THEN       
3637         
3638             CALL rrtmg_lw( 1, nzt_rad      , rrtm_icld    , rrtm_idrv      ,&
3639             rrtm_play       , rrtm_plev    , rrtm_tlay    , rrtm_tlev      ,&
3640             rrtm_tsfc       , rrtm_h2ovmr  , rrtm_o3vmr   , rrtm_co2vmr    ,&
3641             rrtm_ch4vmr     , rrtm_n2ovmr  , rrtm_o2vmr   , rrtm_cfc11vmr  ,&
3642             rrtm_cfc12vmr   , rrtm_cfc22vmr, rrtm_ccl4vmr , rrtm_emis      ,&
3643             rrtm_inflglw    , rrtm_iceflglw, rrtm_liqflglw, rrtm_cldfr     ,&
3644             rrtm_lw_taucld  , rrtm_cicewp  , rrtm_cliqwp  , rrtm_reice     ,& 
3645             rrtm_reliq      , rrtm_lw_tauaer,                               &
3646             rrtm_lwuflx     , rrtm_lwdflx  , rrtm_lwhr  ,                   &
3647             rrtm_lwuflxc    , rrtm_lwdflxc , rrtm_lwhrc ,                   &
3648             rrtm_lwuflx_dt  ,  rrtm_lwuflxc_dt )
3649
3650!
3651!--          Save fluxes
3652             DO k = nzb, nzt+1
3653                rad_lw_in(k,:,:)  = rrtm_lwdflx(0,k)
3654                rad_lw_out(k,:,:) = rrtm_lwuflx(0,k)
3655             ENDDO
3656             rad_lw_in_diff(:,:) = rad_lw_in(0,:,:)
3657!
3658!--          Save heating rates (convert from K/d to K/h).
3659!--          Further, even though an aggregated radiation is computed, map
3660!--          signle-column profiles on top of any topography, in order to
3661!--          obtain correct near surface radiation heating/cooling rates.
3662             DO  i = nxl, nxr
3663                DO  j = nys, nyn
3664                   k_topo = get_topography_top_index_ji( j, i, 's' )
3665                   DO k = k_topo+1, nzt+1
3666                      rad_lw_hr(k,j,i)     = rrtm_lwhr(0,k-k_topo)  * d_hours_day
3667                      rad_lw_cs_hr(k,j,i)  = rrtm_lwhrc(0,k-k_topo) * d_hours_day
3668                   ENDDO
3669                ENDDO
3670             ENDDO
3671
3672          ENDIF
3673
3674          IF ( sw_radiation .AND. sun_up )  THEN
3675             CALL rrtmg_sw( 1, nzt_rad      , rrtm_icld     , rrtm_iaer      ,&
3676             rrtm_play      , rrtm_plev     , rrtm_tlay     , rrtm_tlev      ,&
3677             rrtm_tsfc      , rrtm_h2ovmr   , rrtm_o3vmr    , rrtm_co2vmr    ,&
3678             rrtm_ch4vmr    , rrtm_n2ovmr   , rrtm_o2vmr    , rrtm_asdir     ,&
3679             rrtm_asdif     , rrtm_aldir    , rrtm_aldif    , zenith         ,&
3680             0.0_wp         , day_of_year   , solar_constant, rrtm_inflgsw   ,&
3681             rrtm_iceflgsw  , rrtm_liqflgsw , rrtm_cldfr    , rrtm_sw_taucld ,&
3682             rrtm_sw_ssacld , rrtm_sw_asmcld, rrtm_sw_fsfcld, rrtm_cicewp    ,&
3683             rrtm_cliqwp    , rrtm_reice    , rrtm_reliq    , rrtm_sw_tauaer ,&
3684             rrtm_sw_ssaaer , rrtm_sw_asmaer, rrtm_sw_ecaer , rrtm_swuflx    ,&
3685             rrtm_swdflx    , rrtm_swhr     , rrtm_swuflxc  , rrtm_swdflxc   ,&
3686             rrtm_swhrc     , rrtm_dirdflux , rrtm_difdflux )
3687 
3688!
3689!--          Save fluxes:
3690!--          - whole domain
3691             DO k = nzb, nzt+1
3692                rad_sw_in(k,:,:)  = rrtm_swdflx(0,k)
3693                rad_sw_out(k,:,:) = rrtm_swuflx(0,k)
3694             ENDDO
3695!--          - direct and diffuse SW at urban-surface-layer (required by RTM)
3696             rad_sw_in_dir(:,:) = rrtm_dirdflux(0,nzb)
3697             rad_sw_in_diff(:,:) = rrtm_difdflux(0,nzb)
3698
3699!
3700!--          Save heating rates (convert from K/d to K/s)
3701             DO k = nzb+1, nzt+1
3702                rad_sw_hr(k,:,:)     = rrtm_swhr(0,k)  * d_hours_day
3703                rad_sw_cs_hr(k,:,:)  = rrtm_swhrc(0,k) * d_hours_day
3704             ENDDO
3705!
3706!--       Solar radiation is zero during night
3707          ELSE
3708             rad_sw_in  = 0.0_wp
3709             rad_sw_out = 0.0_wp
3710             rad_sw_in_dir(:,:) = 0.0_wp
3711             rad_sw_in_diff(:,:) = 0.0_wp
3712          ENDIF
3713!
3714!--    RRTMG is called for each (j,i) grid point separately, starting at the
3715!--    highest topography level. Here no RTM is used since average_radiation is false
3716       ELSE
3717!
3718!--       Loop over all grid points
3719          DO i = nxl, nxr
3720             DO j = nys, nyn
3721
3722!
3723!--             Prepare profiles of temperature and H2O volume mixing ratio
3724                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
3725                   rrtm_tlev(0,nzb+1) = surf_lsm_h%pt_surface(m) * exner(nzb)
3726                ENDDO
3727                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
3728                   rrtm_tlev(0,nzb+1) = surf_usm_h%pt_surface(m) * exner(nzb)
3729                ENDDO
3730
3731
3732                IF ( bulk_cloud_model )  THEN
3733                   DO k = nzb+1, nzt+1
3734                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)                    &
3735                                        + lv_d_cp * ql(k,j,i)
3736                      rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * (q(k,j,i) - ql(k,j,i))
3737                   ENDDO
3738                ELSEIF ( cloud_droplets )  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) 
3743                   ENDDO
3744                ELSE
3745                   DO k = nzb+1, nzt+1
3746                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)
3747                   ENDDO
3748
3749                   IF ( humidity )  THEN
3750                      DO k = nzb+1, nzt+1
3751                         rrtm_h2ovmr(0,k) =  mol_mass_air_d_wv * q(k,j,i)
3752                      ENDDO   
3753                   ELSE
3754                      rrtm_h2ovmr(0,nzb+1:nzt+1) = 0.0_wp
3755                   ENDIF
3756                ENDIF
3757
3758!
3759!--             Avoid temperature/humidity jumps at the top of the LES domain by
3760!--             linear interpolation from nzt+2 to nzt+7
3761                DO k = nzt+2, nzt+7
3762                   rrtm_tlay(0,k) = rrtm_tlay(0,nzt+1)                         &
3763                                 + ( rrtm_tlay(0,nzt+8) - rrtm_tlay(0,nzt+1) ) &
3764                                 / ( rrtm_play(0,nzt+8) - rrtm_play(0,nzt+1) ) &
3765                                 * ( rrtm_play(0,k)     - rrtm_play(0,nzt+1) )
3766
3767                   rrtm_h2ovmr(0,k) = rrtm_h2ovmr(0,nzt+1)                     &
3768                              + ( rrtm_h2ovmr(0,nzt+8) - rrtm_h2ovmr(0,nzt+1) )&
3769                              / ( rrtm_play(0,nzt+8)   - rrtm_play(0,nzt+1)   )&
3770                              * ( rrtm_play(0,k)       - rrtm_play(0,nzt+1) )
3771
3772                ENDDO
3773
3774!--             Linear interpolate to zw grid
3775                DO k = nzb+2, nzt+8
3776                   rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k) -     &
3777                                      rrtm_tlay(0,k-1))                        &
3778                                      / ( rrtm_play(0,k) - rrtm_play(0,k-1) )  &
3779                                      * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
3780                ENDDO
3781
3782
3783!
3784!--             Calculate liquid water path and cloud fraction for each column.
3785!--             Note that LWP is required in g/m2 instead of kg/kg m.
3786                rrtm_cldfr  = 0.0_wp
3787                rrtm_reliq  = 0.0_wp
3788                rrtm_cliqwp = 0.0_wp
3789                rrtm_icld   = 0
3790
3791                IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
3792                   DO k = nzb+1, nzt+1
3793                      rrtm_cliqwp(0,k) =  ql(k,j,i) * 1000.0_wp *              &
3794                                          (rrtm_plev(0,k) - rrtm_plev(0,k+1))  &
3795                                          * 100.0_wp / g 
3796
3797                      IF ( rrtm_cliqwp(0,k) > 0.0_wp )  THEN
3798                         rrtm_cldfr(0,k) = 1.0_wp
3799                         IF ( rrtm_icld == 0 )  rrtm_icld = 1
3800
3801!
3802!--                      Calculate cloud droplet effective radius
3803                         IF ( bulk_cloud_model )  THEN
3804!
3805!--                         Calculete effective droplet radius. In case of using
3806!--                         cloud_scheme = 'morrison' and a non reasonable number
3807!--                         of cloud droplets the inital aerosol number 
3808!--                         concentration is considered.
3809                            IF ( microphysics_morrison )  THEN
3810                               IF ( nc(k,j,i) > 1.0E-20_wp )  THEN
3811                                  nc_rad = nc(k,j,i)
3812                               ELSE
3813                                  nc_rad = na_init
3814                               ENDIF
3815                            ELSE
3816                               nc_rad = nc_const
3817                            ENDIF 
3818
3819                            rrtm_reliq(0,k) = 1.0E6_wp * ( 3.0_wp * ql(k,j,i)     &
3820                                              * rho_surface                       &
3821                                              / ( 4.0_wp * pi * nc_rad * rho_l )  &
3822                                              )**0.33333333333333_wp              &
3823                                              * EXP( LOG( sigma_gc )**2 )
3824
3825                         ELSEIF ( cloud_droplets )  THEN
3826                            number_of_particles = prt_count(k,j,i)
3827
3828                            IF (number_of_particles <= 0)  CYCLE
3829                            particles => grid_particles(k,j,i)%particles(1:number_of_particles)
3830                            s_r2 = 0.0_wp
3831                            s_r3 = 0.0_wp
3832
3833                            DO  n = 1, number_of_particles
3834                               IF ( particles(n)%particle_mask )  THEN
3835                                  s_r2 = s_r2 + particles(n)%radius**2 *       &
3836                                         particles(n)%weight_factor
3837                                  s_r3 = s_r3 + particles(n)%radius**3 *       &
3838                                         particles(n)%weight_factor
3839                               ENDIF
3840                            ENDDO
3841
3842                            IF ( s_r2 > 0.0_wp )  rrtm_reliq(0,k) = s_r3 / s_r2
3843
3844                         ENDIF
3845
3846!
3847!--                      Limit effective radius
3848                         IF ( rrtm_reliq(0,k) > 0.0_wp )  THEN
3849                            rrtm_reliq(0,k) = MAX(rrtm_reliq(0,k),2.5_wp)
3850                            rrtm_reliq(0,k) = MIN(rrtm_reliq(0,k),60.0_wp)
3851                        ENDIF
3852                      ENDIF
3853                   ENDDO
3854                ENDIF
3855
3856!
3857!--             Write surface emissivity and surface temperature at current
3858!--             surface element on RRTMG-shaped array.
3859!--             Please note, as RRTMG is a single column model, surface attributes
3860!--             are only obtained from horizontally aligned surfaces (for
3861!--             simplicity). Taking surface attributes from horizontal and
3862!--             vertical walls would lead to multiple solutions. 
3863!--             Moreover, for natural- and urban-type surfaces, several surface
3864!--             classes can exist at a surface element next to each other.
3865!--             To obtain bulk parameters, apply a weighted average for these
3866!--             surfaces.
3867                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
3868                   rrtm_emis = surf_lsm_h%frac(ind_veg_wall,m)  *              &
3869                               surf_lsm_h%emissivity(ind_veg_wall,m)  +        &
3870                               surf_lsm_h%frac(ind_pav_green,m) *              &
3871                               surf_lsm_h%emissivity(ind_pav_green,m) +        & 
3872                               surf_lsm_h%frac(ind_wat_win,m)   *              &
3873                               surf_lsm_h%emissivity(ind_wat_win,m)
3874                   rrtm_tsfc = surf_lsm_h%pt_surface(m) * exner(nzb)
3875                ENDDO             
3876                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
3877                   rrtm_emis = surf_usm_h%frac(ind_veg_wall,m)  *              &
3878                               surf_usm_h%emissivity(ind_veg_wall,m)  +        &
3879                               surf_usm_h%frac(ind_pav_green,m) *              &
3880                               surf_usm_h%emissivity(ind_pav_green,m) +        & 
3881                               surf_usm_h%frac(ind_wat_win,m)   *              &
3882                               surf_usm_h%emissivity(ind_wat_win,m)
3883                   rrtm_tsfc = surf_usm_h%pt_surface(m) * exner(nzb)
3884                ENDDO
3885!
3886!--             Obtain topography top index (lower bound of RRTMG)
3887                k_topo = get_topography_top_index_ji( j, i, 's' )
3888
3889                IF ( lw_radiation )  THEN
3890!
3891!--                Due to technical reasons, copy optical depth to dummy arguments
3892!--                which are allocated on the exact size as the rrtmg_lw is called.
3893!--                As one dimesion is allocated with zero size, compiler complains
3894!--                that rank of the array does not match that of the
3895!--                assumed-shaped arguments in the RRTMG library. In order to
3896!--                avoid this, write to dummy arguments and give pass the entire
3897!--                dummy array. Seems to be the only existing work-around. 
3898                   ALLOCATE( rrtm_lw_taucld_dum(1:nbndlw+1,0:0,k_topo+1:nzt_rad+1) )
3899                   ALLOCATE( rrtm_lw_tauaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndlw+1) )
3900
3901                   rrtm_lw_taucld_dum =                                        &
3902                               rrtm_lw_taucld(1:nbndlw+1,0:0,k_topo+1:nzt_rad+1)
3903                   rrtm_lw_tauaer_dum =                                        &
3904                               rrtm_lw_tauaer(0:0,k_topo+1:nzt_rad+1,1:nbndlw+1)
3905
3906                   CALL rrtmg_lw( 1,                                           &                                       
3907                                  nzt_rad-k_topo,                              &
3908                                  rrtm_icld,                                   &
3909                                  rrtm_idrv,                                   &
3910                                  rrtm_play(:,k_topo+1:nzt_rad+1),             &
3911                                  rrtm_plev(:,k_topo+1:nzt_rad+2),             &
3912                                  rrtm_tlay(:,k_topo+1:nzt_rad+1),             &
3913                                  rrtm_tlev(:,k_topo+1:nzt_rad+2),             &
3914                                  rrtm_tsfc,                                   &
3915                                  rrtm_h2ovmr(:,k_topo+1:nzt_rad+1),           &
3916                                  rrtm_o3vmr(:,k_topo+1:nzt_rad+1),            &
3917                                  rrtm_co2vmr(:,k_topo+1:nzt_rad+1),           &
3918                                  rrtm_ch4vmr(:,k_topo+1:nzt_rad+1),           &
3919                                  rrtm_n2ovmr(:,k_topo+1:nzt_rad+1),           &
3920                                  rrtm_o2vmr(:,k_topo+1:nzt_rad+1),            &
3921                                  rrtm_cfc11vmr(:,k_topo+1:nzt_rad+1),         &
3922                                  rrtm_cfc12vmr(:,k_topo+1:nzt_rad+1),         &
3923                                  rrtm_cfc22vmr(:,k_topo+1:nzt_rad+1),         &
3924                                  rrtm_ccl4vmr(:,k_topo+1:nzt_rad+1),          &
3925                                  rrtm_emis,                                   &
3926                                  rrtm_inflglw,                                &
3927                                  rrtm_iceflglw,                               &
3928                                  rrtm_liqflglw,                               &
3929                                  rrtm_cldfr(:,k_topo+1:nzt_rad+1),            &
3930                                  rrtm_lw_taucld_dum,                          &
3931                                  rrtm_cicewp(:,k_topo+1:nzt_rad+1),           &
3932                                  rrtm_cliqwp(:,k_topo+1:nzt_rad+1),           &
3933                                  rrtm_reice(:,k_topo+1:nzt_rad+1),            & 
3934                                  rrtm_reliq(:,k_topo+1:nzt_rad+1),            &
3935                                  rrtm_lw_tauaer_dum,                          &
3936                                  rrtm_lwuflx(:,k_topo:nzt_rad+1),             &
3937                                  rrtm_lwdflx(:,k_topo:nzt_rad+1),             &
3938                                  rrtm_lwhr(:,k_topo+1:nzt_rad+1),             &
3939                                  rrtm_lwuflxc(:,k_topo:nzt_rad+1),            &
3940                                  rrtm_lwdflxc(:,k_topo:nzt_rad+1),            &
3941                                  rrtm_lwhrc(:,k_topo+1:nzt_rad+1),            &
3942                                  rrtm_lwuflx_dt(:,k_topo:nzt_rad+1),          &
3943                                  rrtm_lwuflxc_dt(:,k_topo:nzt_rad+1) )
3944
3945                   DEALLOCATE ( rrtm_lw_taucld_dum )
3946                   DEALLOCATE ( rrtm_lw_tauaer_dum )
3947!
3948!--                Save fluxes
3949                   DO k = k_topo, nzt+1
3950                      rad_lw_in(k,j,i)  = rrtm_lwdflx(0,k)
3951                      rad_lw_out(k,j,i) = rrtm_lwuflx(0,k)
3952                   ENDDO
3953
3954!
3955!--                Save heating rates (convert from K/d to K/h)
3956                   DO k = k_topo+1, nzt+1
3957                      rad_lw_hr(k,j,i)     = rrtm_lwhr(0,k-k_topo)  * d_hours_day
3958                      rad_lw_cs_hr(k,j,i)  = rrtm_lwhrc(0,k-k_topo) * d_hours_day
3959                   ENDDO
3960
3961!
3962!--                Save surface radiative fluxes and change in LW heating rate
3963!--                onto respective surface elements
3964!--                Horizontal surfaces
3965                   DO  m = surf_lsm_h%start_index(j,i),                        &
3966                           surf_lsm_h%end_index(j,i)
3967                      surf_lsm_h%rad_lw_in(m)           = rrtm_lwdflx(0,k_topo)
3968                      surf_lsm_h%rad_lw_out(m)          = rrtm_lwuflx(0,k_topo)
3969                      surf_lsm_h%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k_topo)
3970                   ENDDO             
3971                   DO  m = surf_usm_h%start_index(j,i),                        &
3972                           surf_usm_h%end_index(j,i)
3973                      surf_usm_h%rad_lw_in(m)           = rrtm_lwdflx(0,k_topo)
3974                      surf_usm_h%rad_lw_out(m)          = rrtm_lwuflx(0,k_topo)
3975                      surf_usm_h%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k_topo)
3976                   ENDDO 
3977!
3978!--                Vertical surfaces. Fluxes are obtain at vertical level of the
3979!--                respective surface element
3980                   DO  l = 0, 3
3981                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
3982                              surf_lsm_v(l)%end_index(j,i)
3983                         k                                    = surf_lsm_v(l)%k(m)
3984                         surf_lsm_v(l)%rad_lw_in(m)           = rrtm_lwdflx(0,k)
3985                         surf_lsm_v(l)%rad_lw_out(m)          = rrtm_lwuflx(0,k)
3986                         surf_lsm_v(l)%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k)
3987                      ENDDO             
3988                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
3989                              surf_usm_v(l)%end_index(j,i)
3990                         k                                    = surf_usm_v(l)%k(m)
3991                         surf_usm_v(l)%rad_lw_in(m)           = rrtm_lwdflx(0,k)
3992                         surf_usm_v(l)%rad_lw_out(m)          = rrtm_lwuflx(0,k)
3993                         surf_usm_v(l)%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k)
3994                      ENDDO 
3995                   ENDDO
3996
3997                ENDIF
3998
3999                IF ( sw_radiation .AND. sun_up )  THEN
4000!
4001!--                Get albedo for direct/diffusive long/shortwave radiation at
4002!--                current (y,x)-location from surface variables.
4003!--                Only obtain it from horizontal surfaces, as RRTMG is a single
4004!--                column model
4005!--                (Please note, only one loop will entered, controlled by
4006!--                start-end index.)
4007                   DO  m = surf_lsm_h%start_index(j,i),                        &
4008                           surf_lsm_h%end_index(j,i)
4009                      rrtm_asdir(1)  = SUM( surf_lsm_h%frac(:,m) *             &
4010                                            surf_lsm_h%rrtm_asdir(:,m) )
4011                      rrtm_asdif(1)  = SUM( surf_lsm_h%frac(:,m) *             &
4012                                            surf_lsm_h%rrtm_asdif(:,m) )
4013                      rrtm_aldir(1)  = SUM( surf_lsm_h%frac(:,m) *             &
4014                                            surf_lsm_h%rrtm_aldir(:,m) )
4015                      rrtm_aldif(1)  = SUM( surf_lsm_h%frac(:,m) *             &
4016                                            surf_lsm_h%rrtm_aldif(:,m) )
4017                   ENDDO             
4018                   DO  m = surf_usm_h%start_index(j,i),                        &
4019                           surf_usm_h%end_index(j,i)
4020                      rrtm_asdir(1)  = SUM( surf_usm_h%frac(:,m) *             &
4021                                            surf_usm_h%rrtm_asdir(:,m) )
4022                      rrtm_asdif(1)  = SUM( surf_usm_h%frac(:,m) *             &
4023                                            surf_usm_h%rrtm_asdif(:,m) )
4024                      rrtm_aldir(1)  = SUM( surf_usm_h%frac(:,m) *             &
4025                                            surf_usm_h%rrtm_aldir(:,m) )
4026                      rrtm_aldif(1)  = SUM( surf_usm_h%frac(:,m) *             &
4027                                            surf_usm_h%rrtm_aldif(:,m) )
4028                   ENDDO
4029!
4030!--                Due to technical reasons, copy optical depths and other
4031!--                to dummy arguments which are allocated on the exact size as the
4032!--                rrtmg_sw is called.
4033!--                As one dimesion is allocated with zero size, compiler complains
4034!--                that rank of the array does not match that of the
4035!--                assumed-shaped arguments in the RRTMG library. In order to
4036!--                avoid this, write to dummy arguments and give pass the entire
4037!--                dummy array. Seems to be the only existing work-around. 
4038                   ALLOCATE( rrtm_sw_taucld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
4039                   ALLOCATE( rrtm_sw_ssacld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
4040                   ALLOCATE( rrtm_sw_asmcld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
4041                   ALLOCATE( rrtm_sw_fsfcld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
4042                   ALLOCATE( rrtm_sw_tauaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
4043                   ALLOCATE( rrtm_sw_ssaaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
4044                   ALLOCATE( rrtm_sw_asmaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
4045                   ALLOCATE( rrtm_sw_ecaer_dum(0:0,k_topo+1:nzt_rad+1,1:naerec+1)  )
4046     
4047                   rrtm_sw_taucld_dum = rrtm_sw_taucld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
4048                   rrtm_sw_ssacld_dum = rrtm_sw_ssacld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
4049                   rrtm_sw_asmcld_dum = rrtm_sw_asmcld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
4050                   rrtm_sw_fsfcld_dum = rrtm_sw_fsfcld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
4051                   rrtm_sw_tauaer_dum = rrtm_sw_tauaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
4052                   rrtm_sw_ssaaer_dum = rrtm_sw_ssaaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
4053                   rrtm_sw_asmaer_dum = rrtm_sw_asmaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
4054                   rrtm_sw_ecaer_dum  = rrtm_sw_ecaer(0:0,k_topo+1:nzt_rad+1,1:naerec+1)
4055
4056                   CALL rrtmg_sw( 1,                                           &
4057                                  nzt_rad-k_topo,                              &
4058                                  rrtm_icld,                                   &
4059                                  rrtm_iaer,                                   &
4060                                  rrtm_play(:,k_topo+1:nzt_rad+1),             &
4061                                  rrtm_plev(:,k_topo+1:nzt_rad+2),             &
4062                                  rrtm_tlay(:,k_topo+1:nzt_rad+1),             &
4063                                  rrtm_tlev(:,k_topo+1:nzt_rad+2),             &
4064                                  rrtm_tsfc,                                   &
4065                                  rrtm_h2ovmr(:,k_topo+1:nzt_rad+1),           &                               
4066                                  rrtm_o3vmr(:,k_topo+1:nzt_rad+1),            &       
4067                                  rrtm_co2vmr(:,k_topo+1:nzt_rad+1),           &
4068                                  rrtm_ch4vmr(:,k_topo+1:nzt_rad+1),           &
4069                                  rrtm_n2ovmr(:,k_topo+1:nzt_rad+1),           &
4070                                  rrtm_o2vmr(:,k_topo+1:nzt_rad+1),            &
4071                                  rrtm_asdir,                                  & 
4072                                  rrtm_asdif,                                  &
4073                                  rrtm_aldir,                                  &
4074                                  rrtm_aldif,                                  &
4075                                  zenith,                                      &
4076                                  0.0_wp,                                      &
4077                                  day_of_year,                                 &
4078                                  solar_constant,                              &
4079                                  rrtm_inflgsw,                                &
4080                                  rrtm_iceflgsw,                               &
4081                                  rrtm_liqflgsw,                               &
4082                                  rrtm_cldfr(:,k_topo+1:nzt_rad+1),            &
4083                                  rrtm_sw_taucld_dum,                          &
4084                                  rrtm_sw_ssacld_dum,                          &
4085                                  rrtm_sw_asmcld_dum,                          &
4086                                  rrtm_sw_fsfcld_dum,                          &
4087                                  rrtm_cicewp(:,k_topo+1:nzt_rad+1),           &
4088                                  rrtm_cliqwp(:,k_topo+1:nzt_rad+1),           &
4089                                  rrtm_reice(:,k_topo+1:nzt_rad+1),            &
4090                                  rrtm_reliq(:,k_topo+1:nzt_rad+1),            &
4091                                  rrtm_sw_tauaer_dum,                          &
4092                                  rrtm_sw_ssaaer_dum,                          &
4093                                  rrtm_sw_asmaer_dum,                          &
4094                                  rrtm_sw_ecaer_dum,                           &
4095                                  rrtm_swuflx(:,k_topo:nzt_rad+1),             & 
4096                                  rrtm_swdflx(:,k_topo:nzt_rad+1),             & 
4097                                  rrtm_swhr(:,k_topo+1:nzt_rad+1),             & 
4098                                  rrtm_swuflxc(:,k_topo:nzt_rad+1),            & 
4099                                  rrtm_swdflxc(:,k_topo:nzt_rad+1),            &
4100                                  rrtm_swhrc(:,k_topo+1:nzt_rad+1),            &
4101                                  rrtm_dirdflux(:,k_topo:nzt_rad+1),           &
4102                                  rrtm_difdflux(:,k_topo:nzt_rad+1) )
4103
4104                   DEALLOCATE( rrtm_sw_taucld_dum )
4105                   DEALLOCATE( rrtm_sw_ssacld_dum )
4106                   DEALLOCATE( rrtm_sw_asmcld_dum )
4107                   DEALLOCATE( rrtm_sw_fsfcld_dum )
4108                   DEALLOCATE( rrtm_sw_tauaer_dum )
4109                   DEALLOCATE( rrtm_sw_ssaaer_dum )
4110                   DEALLOCATE( rrtm_sw_asmaer_dum )
4111                   DEALLOCATE( rrtm_sw_ecaer_dum )
4112!
4113!--                Save fluxes
4114                   DO k = nzb, nzt+1
4115                      rad_sw_in(k,j,i)  = rrtm_swdflx(0,k)
4116                      rad_sw_out(k,j,i) = rrtm_swuflx(0,k)
4117                   ENDDO
4118!
4119!--                Save heating rates (convert from K/d to K/s)
4120                   DO k = nzb+1, nzt+1
4121                      rad_sw_hr(k,j,i)     = rrtm_swhr(0,k)  * d_hours_day
4122                      rad_sw_cs_hr(k,j,i)  = rrtm_swhrc(0,k) * d_hours_day
4123                   ENDDO
4124
4125!
4126!--                Save surface radiative fluxes onto respective surface elements
4127!--                Horizontal surfaces
4128                   DO  m = surf_lsm_h%start_index(j,i),                        &
4129                           surf_lsm_h%end_index(j,i)
4130                      surf_lsm_h%rad_sw_in(m)     = rrtm_swdflx(0,k_topo)
4131                      surf_lsm_h%rad_sw_out(m)    = rrtm_swuflx(0,k_topo)
4132                   ENDDO             
4133                   DO  m = surf_usm_h%start_index(j,i),                        &
4134                           surf_usm_h%end_index(j,i)
4135                      surf_usm_h%rad_sw_in(m)     = rrtm_swdflx(0,k_topo)
4136                      surf_usm_h%rad_sw_out(m)    = rrtm_swuflx(0,k_topo)
4137                   ENDDO 
4138!
4139!--                Vertical surfaces. Fluxes are obtain at respective vertical
4140!--                level of the surface element
4141                   DO  l = 0, 3
4142                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
4143                              surf_lsm_v(l)%end_index(j,i)
4144                         k                           = surf_lsm_v(l)%k(m)
4145                         surf_lsm_v(l)%rad_sw_in(m)  = rrtm_swdflx(0,k)
4146                         surf_lsm_v(l)%rad_sw_out(m) = rrtm_swuflx(0,k)
4147                      ENDDO             
4148                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
4149                              surf_usm_v(l)%end_index(j,i)
4150                         k                           = surf_usm_v(l)%k(m)
4151                         surf_usm_v(l)%rad_sw_in(m)  = rrtm_swdflx(0,k)
4152                         surf_usm_v(l)%rad_sw_out(m) = rrtm_swuflx(0,k)
4153                      ENDDO 
4154                   ENDDO
4155!
4156!--             Solar radiation is zero during night
4157                ELSE
4158                   rad_sw_in  = 0.0_wp
4159                   rad_sw_out = 0.0_wp
4160!--             !!!!!!!! ATTENSION !!!!!!!!!!!!!!!
4161!--             Surface radiative fluxes should be also set to zero here                 
4162!--                Save surface radiative fluxes onto respective surface elements
4163!--                Horizontal surfaces
4164                   DO  m = surf_lsm_h%start_index(j,i),                        &
4165                           surf_lsm_h%end_index(j,i)
4166                      surf_lsm_h%rad_sw_in(m)     = 0.0_wp
4167                      surf_lsm_h%rad_sw_out(m)    = 0.0_wp
4168                   ENDDO             
4169                   DO  m = surf_usm_h%start_index(j,i),                        &
4170                           surf_usm_h%end_index(j,i)
4171                      surf_usm_h%rad_sw_in(m)     = 0.0_wp
4172                      surf_usm_h%rad_sw_out(m)    = 0.0_wp
4173                   ENDDO 
4174!
4175!--                Vertical surfaces. Fluxes are obtain at respective vertical
4176!--                level of the surface element
4177                   DO  l = 0, 3
4178                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
4179                              surf_lsm_v(l)%end_index(j,i)
4180                         k                           = surf_lsm_v(l)%k(m)
4181                         surf_lsm_v(l)%rad_sw_in(m)  = 0.0_wp
4182                         surf_lsm_v(l)%rad_sw_out(m) = 0.0_wp
4183                      ENDDO             
4184                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
4185                              surf_usm_v(l)%end_index(j,i)
4186                         k                           = surf_usm_v(l)%k(m)
4187                         surf_usm_v(l)%rad_sw_in(m)  = 0.0_wp
4188                         surf_usm_v(l)%rad_sw_out(m) = 0.0_wp
4189                      ENDDO 
4190                   ENDDO
4191                ENDIF
4192
4193             ENDDO
4194          ENDDO
4195
4196       ENDIF
4197!
4198!--    Finally, calculate surface net radiation for surface elements.
4199       IF (  .NOT.  radiation_interactions  ) THEN
4200!--       First, for horizontal surfaces   
4201          DO  m = 1, surf_lsm_h%ns
4202             surf_lsm_h%rad_net(m) = surf_lsm_h%rad_sw_in(m)                   &
4203                                   - surf_lsm_h%rad_sw_out(m)                  &
4204                                   + surf_lsm_h%rad_lw_in(m)                   &
4205                                   - surf_lsm_h%rad_lw_out(m)
4206          ENDDO
4207          DO  m = 1, surf_usm_h%ns
4208             surf_usm_h%rad_net(m) = surf_usm_h%rad_sw_in(m)                   &
4209                                   - surf_usm_h%rad_sw_out(m)                  &
4210                                   + surf_usm_h%rad_lw_in(m)                   &
4211                                   - surf_usm_h%rad_lw_out(m)
4212          ENDDO
4213!
4214!--       Vertical surfaces.
4215!--       Todo: weight with azimuth and zenith angle according to their orientation!
4216          DO  l = 0, 3     
4217             DO  m = 1, surf_lsm_v(l)%ns
4218                surf_lsm_v(l)%rad_net(m) = surf_lsm_v(l)%rad_sw_in(m)          &
4219                                         - surf_lsm_v(l)%rad_sw_out(m)         &
4220                                         + surf_lsm_v(l)%rad_lw_in(m)          &
4221                                         - surf_lsm_v(l)%rad_lw_out(m)
4222             ENDDO
4223             DO  m = 1, surf_usm_v(l)%ns
4224                surf_usm_v(l)%rad_net(m) = surf_usm_v(l)%rad_sw_in(m)          &
4225                                         - surf_usm_v(l)%rad_sw_out(m)         &
4226                                         + surf_usm_v(l)%rad_lw_in(m)          &
4227                                         - surf_usm_v(l)%rad_lw_out(m)
4228             ENDDO
4229          ENDDO
4230       ENDIF
4231
4232
4233       CALL exchange_horiz( rad_lw_in,  nbgp )
4234       CALL exchange_horiz( rad_lw_out, nbgp )
4235       CALL exchange_horiz( rad_lw_hr,    nbgp )
4236       CALL exchange_horiz( rad_lw_cs_hr, nbgp )
4237
4238       CALL exchange_horiz( rad_sw_in,  nbgp )
4239       CALL exchange_horiz( rad_sw_out, nbgp ) 
4240       CALL exchange_horiz( rad_sw_hr,    nbgp )
4241       CALL exchange_horiz( rad_sw_cs_hr, nbgp )
4242
4243#endif
4244
4245    END SUBROUTINE radiation_rrtmg
4246
4247
4248!------------------------------------------------------------------------------!
4249! Description:
4250! ------------
4251!> Calculate the cosine of the zenith angle (variable is called zenith)
4252!------------------------------------------------------------------------------!
4253    SUBROUTINE calc_zenith
4254
4255       IMPLICIT NONE
4256
4257       REAL(wp) ::  declination,  & !< solar declination angle
4258                    hour_angle      !< solar hour angle
4259!
4260!--    Calculate current day and time based on the initial values and simulation
4261!--    time
4262       CALL calc_date_and_time
4263
4264!
4265!--    Calculate solar declination and hour angle   
4266       declination = ASIN( decl_1 * SIN(decl_2 * REAL(day_of_year, KIND=wp) - decl_3) )
4267       hour_angle  = 2.0_wp * pi * (time_utc / 86400.0_wp) + lon - pi
4268
4269!
4270!--    Calculate cosine of solar zenith angle
4271       cos_zenith = SIN(lat) * SIN(declination) + COS(lat) * COS(declination)   &
4272                                            * COS(hour_angle)
4273       cos_zenith = MAX(0.0_wp,cos_zenith)
4274
4275!
4276!--    Calculate solar directional vector
4277       IF ( sun_direction )  THEN
4278
4279!
4280!--       Direction in longitudes equals to sin(solar_azimuth) * sin(zenith)
4281          sun_dir_lon = -SIN(hour_angle) * COS(declination)
4282
4283!
4284!--       Direction in latitues equals to cos(solar_azimuth) * sin(zenith)
4285          sun_dir_lat = SIN(declination) * COS(lat) - COS(hour_angle) &
4286                              * COS(declination) * SIN(lat)
4287       ENDIF
4288
4289!
4290!--    Check if the sun is up (otheriwse shortwave calculations can be skipped)
4291       IF ( cos_zenith > 0.0_wp )  THEN
4292          sun_up = .TRUE.
4293       ELSE
4294          sun_up = .FALSE.
4295       END IF
4296
4297    END SUBROUTINE calc_zenith
4298
4299#if defined ( __rrtmg ) && defined ( __netcdf )
4300!------------------------------------------------------------------------------!
4301! Description:
4302! ------------
4303!> Calculates surface albedo components based on Briegleb (1992) and
4304!> Briegleb et al. (1986)
4305!------------------------------------------------------------------------------!
4306    SUBROUTINE calc_albedo( surf )
4307
4308        IMPLICIT NONE
4309
4310        INTEGER(iwp)    ::  ind_type !< running index surface tiles
4311        INTEGER(iwp)    ::  m        !< running index surface elements
4312
4313        TYPE(surf_type) ::  surf !< treated surfaces
4314
4315        IF ( sun_up  .AND.  .NOT. average_radiation )  THEN
4316
4317           DO  m = 1, surf%ns
4318!
4319!--           Loop over surface elements
4320              DO  ind_type = 0, SIZE( surf%albedo_type, 1 ) - 1
4321           
4322!
4323!--              Ocean
4324                 IF ( surf%albedo_type(ind_type,m) == 1 )  THEN
4325                    surf%rrtm_aldir(ind_type,m) = 0.026_wp /                    &
4326                                                ( cos_zenith**1.7_wp + 0.065_wp )&
4327                                     + 0.15_wp * ( cos_zenith - 0.1_wp )         &
4328                                               * ( cos_zenith - 0.5_wp )         &
4329                                               * ( cos_zenith - 1.0_wp )
4330                    surf%rrtm_asdir(ind_type,m) = surf%rrtm_aldir(ind_type,m)
4331!
4332!--              Snow
4333                 ELSEIF ( surf%albedo_type(ind_type,m) == 16 )  THEN
4334                    IF ( cos_zenith < 0.5_wp )  THEN
4335                       surf%rrtm_aldir(ind_type,m) =                           &
4336                                 0.5_wp * ( 1.0_wp - surf%aldif(ind_type,m) )  &
4337                                        * ( 3.0_wp / ( 1.0_wp + 4.0_wp         &
4338                                        * cos_zenith ) ) - 1.0_wp
4339                       surf%rrtm_asdir(ind_type,m) =                           &
4340                                 0.5_wp * ( 1.0_wp - surf%asdif(ind_type,m) )  &
4341                                        * ( 3.0_wp / ( 1.0_wp + 4.0_wp         &
4342                                        * cos_zenith ) ) - 1.0_wp
4343
4344                       surf%rrtm_aldir(ind_type,m) =                           &
4345                                       MIN(0.98_wp, surf%rrtm_aldir(ind_type,m))
4346                       surf%rrtm_asdir(ind_type,m) =                           &
4347                                       MIN(0.98_wp, surf%rrtm_asdir(ind_type,m))
4348                    ELSE
4349                       surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4350                       surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4351                    ENDIF
4352!
4353!--              Sea ice
4354                 ELSEIF ( surf%albedo_type(ind_type,m) == 15 )  THEN
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
4358!
4359!--              Asphalt
4360                 ELSEIF ( surf%albedo_type(ind_type,m) == 17 )  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!
4366!--              Bare soil
4367                 ELSEIF ( surf%albedo_type(ind_type,m) == 18 )  THEN
4368                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4369                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4370
4371!
4372!--              Land surfaces
4373                 ELSE
4374                    SELECT CASE ( surf%albedo_type(ind_type,m) )
4375
4376!
4377!--                    Surface types with strong zenith dependence
4378                       CASE ( 1, 2, 3, 4, 11, 12, 13 )
4379                          surf%rrtm_aldir(ind_type,m) =                        &
4380                                surf%aldif(ind_type,m) * 1.4_wp /              &
4381                                           ( 1.0_wp + 0.8_wp * cos_zenith )
4382                          surf%rrtm_asdir(ind_type,m) =                        &
4383                                surf%asdif(ind_type,m) * 1.4_wp /              &
4384                                           ( 1.0_wp + 0.8_wp * cos_zenith )
4385!
4386!--                    Surface types with weak zenith dependence
4387                       CASE ( 5, 6, 7, 8, 9, 10, 14 )
4388                          surf%rrtm_aldir(ind_type,m) =                        &
4389                                surf%aldif(ind_type,m) * 1.1_wp /              &
4390                                           ( 1.0_wp + 0.2_wp * cos_zenith )
4391                          surf%rrtm_asdir(ind_type,m) =                        &
4392                                surf%asdif(ind_type,m) * 1.1_wp /              &
4393                                           ( 1.0_wp + 0.2_wp * cos_zenith )
4394
4395                       CASE DEFAULT
4396
4397                    END SELECT
4398                 ENDIF
4399!
4400!--              Diffusive albedo is taken from Table 2
4401                 surf%rrtm_aldif(ind_type,m) = surf%aldif(ind_type,m)
4402                 surf%rrtm_asdif(ind_type,m) = surf%asdif(ind_type,m)
4403              ENDDO
4404           ENDDO
4405!
4406!--     Set albedo in case of average radiation
4407        ELSEIF ( sun_up  .AND.  average_radiation )  THEN
4408           surf%rrtm_asdir = albedo_urb
4409           surf%rrtm_asdif = albedo_urb
4410           surf%rrtm_aldir = albedo_urb
4411           surf%rrtm_aldif = albedo_urb 
4412!
4413!--     Darkness
4414        ELSE
4415           surf%rrtm_aldir = 0.0_wp
4416           surf%rrtm_asdir = 0.0_wp
4417           surf%rrtm_aldif = 0.0_wp
4418           surf%rrtm_asdif = 0.0_wp
4419        ENDIF
4420
4421    END SUBROUTINE calc_albedo
4422
4423!------------------------------------------------------------------------------!
4424! Description:
4425! ------------
4426!> Read sounding data (pressure and temperature) from RADIATION_DATA.
4427!------------------------------------------------------------------------------!
4428    SUBROUTINE read_sounding_data
4429
4430       IMPLICIT NONE
4431
4432       INTEGER(iwp) :: id,           & !< NetCDF id of input file
4433                       id_dim_zrad,  & !< pressure level id in the NetCDF file
4434                       id_var,       & !< NetCDF variable id
4435                       k,            & !< loop index
4436                       nz_snd,       & !< number of vertical levels in the sounding data
4437                       nz_snd_start, & !< start vertical index for sounding data to be used
4438                       nz_snd_end      !< end vertical index for souding data to be used
4439
4440       REAL(wp) :: t_surface           !< actual surface temperature
4441
4442       REAL(wp), DIMENSION(:), ALLOCATABLE ::  hyp_snd_tmp, & !< temporary hydrostatic pressure profile (sounding)
4443                                               t_snd_tmp      !< temporary temperature profile (sounding)
4444
4445!
4446!--    In case of updates, deallocate arrays first (sufficient to check one
4447!--    array as the others are automatically allocated). This is required
4448!--    because nzt_rad might change during the update
4449       IF ( ALLOCATED ( hyp_snd ) )  THEN
4450          DEALLOCATE( hyp_snd )
4451          DEALLOCATE( t_snd )
4452          DEALLOCATE ( rrtm_play )
4453          DEALLOCATE ( rrtm_plev )
4454          DEALLOCATE ( rrtm_tlay )
4455          DEALLOCATE ( rrtm_tlev )
4456
4457          DEALLOCATE ( rrtm_cicewp )
4458          DEALLOCATE ( rrtm_cldfr )
4459          DEALLOCATE ( rrtm_cliqwp )
4460          DEALLOCATE ( rrtm_reice )
4461          DEALLOCATE ( rrtm_reliq )
4462          DEALLOCATE ( rrtm_lw_taucld )
4463          DEALLOCATE ( rrtm_lw_tauaer )
4464
4465          DEALLOCATE ( rrtm_lwdflx  )
4466          DEALLOCATE ( rrtm_lwdflxc )
4467          DEALLOCATE ( rrtm_lwuflx  )
4468          DEALLOCATE ( rrtm_lwuflxc )
4469          DEALLOCATE ( rrtm_lwuflx_dt )
4470          DEALLOCATE ( rrtm_lwuflxc_dt )
4471          DEALLOCATE ( rrtm_lwhr  )
4472          DEALLOCATE ( rrtm_lwhrc )
4473
4474          DEALLOCATE ( rrtm_sw_taucld )
4475          DEALLOCATE ( rrtm_sw_ssacld )
4476          DEALLOCATE ( rrtm_sw_asmcld )
4477          DEALLOCATE ( rrtm_sw_fsfcld )
4478          DEALLOCATE ( rrtm_sw_tauaer )
4479          DEALLOCATE ( rrtm_sw_ssaaer )
4480          DEALLOCATE ( rrtm_sw_asmaer ) 
4481          DEALLOCATE ( rrtm_sw_ecaer )   
4482 
4483          DEALLOCATE ( rrtm_swdflx  )
4484          DEALLOCATE ( rrtm_swdflxc )
4485          DEALLOCATE ( rrtm_swuflx  )
4486          DEALLOCATE ( rrtm_swuflxc )
4487          DEALLOCATE ( rrtm_swhr  )
4488          DEALLOCATE ( rrtm_swhrc )
4489          DEALLOCATE ( rrtm_dirdflux )
4490          DEALLOCATE ( rrtm_difdflux )
4491
4492       ENDIF
4493
4494!
4495!--    Open file for reading
4496       nc_stat = NF90_OPEN( rrtm_input_file, NF90_NOWRITE, id )
4497       CALL netcdf_handle_error_rad( 'read_sounding_data', 549 )
4498
4499!
4500!--    Inquire dimension of z axis and save in nz_snd
4501       nc_stat = NF90_INQ_DIMID( id, "Pressure", id_dim_zrad )
4502       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim_zrad, len = nz_snd )
4503       CALL netcdf_handle_error_rad( 'read_sounding_data', 551 )
4504
4505!
4506! !--    Allocate temporary array for storing pressure data
4507       ALLOCATE( hyp_snd_tmp(1:nz_snd) )
4508       hyp_snd_tmp = 0.0_wp
4509
4510
4511!--    Read pressure from file
4512       nc_stat = NF90_INQ_VARID( id, "Pressure", id_var )
4513       nc_stat = NF90_GET_VAR( id, id_var, hyp_snd_tmp(:), start = (/1/),      &
4514                               count = (/nz_snd/) )
4515       CALL netcdf_handle_error_rad( 'read_sounding_data', 552 )
4516
4517!
4518!--    Allocate temporary array for storing temperature data
4519       ALLOCATE( t_snd_tmp(1:nz_snd) )
4520       t_snd_tmp = 0.0_wp
4521
4522!
4523!--    Read temperature from file
4524       nc_stat = NF90_INQ_VARID( id, "ReferenceTemperature", id_var )
4525       nc_stat = NF90_GET_VAR( id, id_var, t_snd_tmp(:), start = (/1/),        &
4526                               count = (/nz_snd/) )
4527       CALL netcdf_handle_error_rad( 'read_sounding_data', 553 )
4528
4529!
4530!--    Calculate start of sounding data
4531       nz_snd_start = nz_snd + 1
4532       nz_snd_end   = nz_snd + 1
4533
4534!
4535!--    Start filling vertical dimension at 10hPa above the model domain (hyp is
4536!--    in Pa, hyp_snd in hPa).
4537       DO  k = 1, nz_snd
4538          IF ( hyp_snd_tmp(k) < ( hyp(nzt+1) - 1000.0_wp) * 0.01_wp )  THEN
4539             nz_snd_start = k
4540             EXIT
4541          END IF
4542       END DO
4543
4544       IF ( nz_snd_start <= nz_snd )  THEN
4545          nz_snd_end = nz_snd
4546       END IF
4547
4548
4549!
4550!--    Calculate of total grid points for RRTMG calculations
4551       nzt_rad = nzt + nz_snd_end - nz_snd_start + 1
4552
4553!
4554!--    Save data above LES domain in hyp_snd, t_snd
4555       ALLOCATE( hyp_snd(nzb+1:nzt_rad) )
4556       ALLOCATE( t_snd(nzb+1:nzt_rad)   )
4557       hyp_snd = 0.0_wp
4558       t_snd = 0.0_wp
4559
4560       hyp_snd(nzt+2:nzt_rad) = hyp_snd_tmp(nz_snd_start+1:nz_snd_end)
4561       t_snd(nzt+2:nzt_rad)   = t_snd_tmp(nz_snd_start+1:nz_snd_end)
4562
4563       nc_stat = NF90_CLOSE( id )
4564
4565!
4566!--    Calculate pressure levels on zu and zw grid. Sounding data is added at
4567!--    top of the LES domain. This routine does not consider horizontal or
4568!--    vertical variability of pressure and temperature
4569       ALLOCATE ( rrtm_play(0:0,nzb+1:nzt_rad+1)   )
4570       ALLOCATE ( rrtm_plev(0:0,nzb+1:nzt_rad+2)   )
4571
4572       t_surface = pt_surface * exner(nzb)
4573       DO k = nzb+1, nzt+1
4574          rrtm_play(0,k) = hyp(k) * 0.01_wp
4575          rrtm_plev(0,k) = barometric_formula(zw(k-1),                         &
4576                              pt_surface * exner(nzb), &
4577                              surface_pressure )
4578       ENDDO
4579
4580       DO k = nzt+2, nzt_rad
4581          rrtm_play(0,k) = hyp_snd(k)
4582          rrtm_plev(0,k) = 0.5_wp * ( rrtm_play(0,k) + rrtm_play(0,k-1) )
4583       ENDDO
4584       rrtm_plev(0,nzt_rad+1) = MAX( 0.5 * hyp_snd(nzt_rad),                   &
4585                                   1.5 * hyp_snd(nzt_rad)                      &
4586                                 - 0.5 * hyp_snd(nzt_rad-1) )
4587       rrtm_plev(0,nzt_rad+2)  = MIN( 1.0E-4_wp,                               &
4588                                      0.25_wp * rrtm_plev(0,nzt_rad+1) )
4589
4590       rrtm_play(0,nzt_rad+1) = 0.5 * rrtm_plev(0,nzt_rad+1)
4591
4592!
4593!--    Calculate temperature/humidity levels at top of the LES domain.
4594!--    Currently, the temperature is taken from sounding data (might lead to a
4595!--    temperature jump at interface. To do: Humidity is currently not
4596!--    calculated above the LES domain.
4597       ALLOCATE ( rrtm_tlay(0:0,nzb+1:nzt_rad+1)   )
4598       ALLOCATE ( rrtm_tlev(0:0,nzb+1:nzt_rad+2)   )
4599
4600       DO k = nzt+8, nzt_rad
4601          rrtm_tlay(0,k)   = t_snd(k)
4602       ENDDO
4603       rrtm_tlay(0,nzt_rad+1) = 2.0_wp * rrtm_tlay(0,nzt_rad)                  &
4604                                - rrtm_tlay(0,nzt_rad-1)
4605       DO k = nzt+9, nzt_rad+1
4606          rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k)                &
4607                             - rrtm_tlay(0,k-1))                               &
4608                             / ( rrtm_play(0,k) - rrtm_play(0,k-1) )           &
4609                             * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
4610       ENDDO
4611
4612       rrtm_tlev(0,nzt_rad+2)   = 2.0_wp * rrtm_tlay(0,nzt_rad+1)              &
4613                                  - rrtm_tlev(0,nzt_rad)
4614!
4615!--    Allocate remaining RRTMG arrays
4616       ALLOCATE ( rrtm_cicewp(0:0,nzb+1:nzt_rad+1) )
4617       ALLOCATE ( rrtm_cldfr(0:0,nzb+1:nzt_rad+1) )
4618       ALLOCATE ( rrtm_cliqwp(0:0,nzb+1:nzt_rad+1) )
4619       ALLOCATE ( rrtm_reice(0:0,nzb+1:nzt_rad+1) )
4620       ALLOCATE ( rrtm_reliq(0:0,nzb+1:nzt_rad+1) )
4621       ALLOCATE ( rrtm_lw_taucld(1:nbndlw+1,0:0,nzb+1:nzt_rad+1) )
4622       ALLOCATE ( rrtm_lw_tauaer(0:0,nzb+1:nzt_rad+1,1:nbndlw+1) )
4623       ALLOCATE ( rrtm_sw_taucld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4624       ALLOCATE ( rrtm_sw_ssacld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4625       ALLOCATE ( rrtm_sw_asmcld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4626       ALLOCATE ( rrtm_sw_fsfcld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4627       ALLOCATE ( rrtm_sw_tauaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) )
4628       ALLOCATE ( rrtm_sw_ssaaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) )
4629       ALLOCATE ( rrtm_sw_asmaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) ) 
4630       ALLOCATE ( rrtm_sw_ecaer(0:0,nzb+1:nzt_rad+1,1:naerec+1) )   
4631
4632!
4633!--    The ice phase is currently not considered in PALM
4634       rrtm_cicewp = 0.0_wp
4635       rrtm_reice  = 0.0_wp
4636
4637!
4638!--    Set other parameters (move to NAMELIST parameters in the future)
4639       rrtm_lw_tauaer = 0.0_wp
4640       rrtm_lw_taucld = 0.0_wp
4641       rrtm_sw_taucld = 0.0_wp
4642       rrtm_sw_ssacld = 0.0_wp
4643       rrtm_sw_asmcld = 0.0_wp
4644       rrtm_sw_fsfcld = 0.0_wp
4645       rrtm_sw_tauaer = 0.0_wp
4646       rrtm_sw_ssaaer = 0.0_wp
4647       rrtm_sw_asmaer = 0.0_wp
4648       rrtm_sw_ecaer  = 0.0_wp
4649
4650
4651       ALLOCATE ( rrtm_swdflx(0:0,nzb:nzt_rad+1)  )
4652       ALLOCATE ( rrtm_swuflx(0:0,nzb:nzt_rad+1)  )
4653       ALLOCATE ( rrtm_swhr(0:0,nzb+1:nzt_rad+1)  )
4654       ALLOCATE ( rrtm_swuflxc(0:0,nzb:nzt_rad+1) )
4655       ALLOCATE ( rrtm_swdflxc(0:0,nzb:nzt_rad+1) )
4656       ALLOCATE ( rrtm_swhrc(0:0,nzb+1:nzt_rad+1) )
4657       ALLOCATE ( rrtm_dirdflux(0:0,nzb:nzt_rad+1) )
4658       ALLOCATE ( rrtm_difdflux(0:0,nzb:nzt_rad+1) )
4659
4660       rrtm_swdflx  = 0.0_wp
4661       rrtm_swuflx  = 0.0_wp
4662       rrtm_swhr    = 0.0_wp 
4663       rrtm_swuflxc = 0.0_wp
4664       rrtm_swdflxc = 0.0_wp
4665       rrtm_swhrc   = 0.0_wp
4666       rrtm_dirdflux = 0.0_wp
4667       rrtm_difdflux = 0.0_wp
4668
4669       ALLOCATE ( rrtm_lwdflx(0:0,nzb:nzt_rad+1)  )
4670       ALLOCATE ( rrtm_lwuflx(0:0,nzb:nzt_rad+1)  )
4671       ALLOCATE ( rrtm_lwhr(0:0,nzb+1:nzt_rad+1)  )
4672       ALLOCATE ( rrtm_lwuflxc(0:0,nzb:nzt_rad+1) )
4673       ALLOCATE ( rrtm_lwdflxc(0:0,nzb:nzt_rad+1) )
4674       ALLOCATE ( rrtm_lwhrc(0:0,nzb+1:nzt_rad+1) )
4675
4676       rrtm_lwdflx  = 0.0_wp
4677       rrtm_lwuflx  = 0.0_wp
4678       rrtm_lwhr    = 0.0_wp 
4679       rrtm_lwuflxc = 0.0_wp
4680       rrtm_lwdflxc = 0.0_wp
4681       rrtm_lwhrc   = 0.0_wp
4682
4683       ALLOCATE ( rrtm_lwuflx_dt(0:0,nzb:nzt_rad+1) )
4684       ALLOCATE ( rrtm_lwuflxc_dt(0:0,nzb:nzt_rad+1) )
4685
4686       rrtm_lwuflx_dt = 0.0_wp
4687       rrtm_lwuflxc_dt = 0.0_wp
4688
4689    END SUBROUTINE read_sounding_data
4690
4691
4692!------------------------------------------------------------------------------!
4693! Description:
4694! ------------
4695!> Read trace gas data from file and convert into trace gas paths / volume
4696!> mixing ratios. If a user-defined input file is provided it needs to follow
4697!> the convections used in RRTMG (see respective netCDF files shipped with
4698!> RRTMG)
4699!------------------------------------------------------------------------------!
4700    SUBROUTINE read_trace_gas_data
4701
4702       USE rrsw_ncpar
4703
4704       IMPLICIT NONE
4705
4706       INTEGER(iwp), PARAMETER :: num_trace_gases = 10 !< number of trace gases (absorbers)
4707
4708       CHARACTER(LEN=5), DIMENSION(num_trace_gases), PARAMETER ::              & !< trace gas names
4709           trace_names = (/'O3   ', 'CO2  ', 'CH4  ', 'N2O  ', 'O2   ',        &
4710                           'CFC11', 'CFC12', 'CFC22', 'CCL4 ', 'H2O  '/)
4711
4712       INTEGER(iwp) :: id,     & !< NetCDF id
4713                       k,      & !< loop index
4714                       m,      & !< loop index
4715                       n,      & !< loop index
4716                       nabs,   & !< number of absorbers
4717                       np,     & !< number of pressure levels
4718                       id_abs, & !< NetCDF id of the respective absorber
4719                       id_dim, & !< NetCDF id of asborber's dimension
4720                       id_var    !< NetCDf id ot the absorber
4721
4722       REAL(wp) :: p_mls_l, &    !< pressure lower limit for interpolation
4723                   p_mls_u, &    !< pressure upper limit for interpolation
4724                   p_wgt_l, &    !< pressure weight lower limit for interpolation
4725                   p_wgt_u, &    !< pressure weight upper limit for interpolation
4726                   p_mls_m       !< mean pressure between upper and lower limits
4727
4728
4729       REAL(wp), DIMENSION(:), ALLOCATABLE   ::  p_mls,          & !< pressure levels for the absorbers
4730                                                 rrtm_play_tmp,  & !< temporary array for pressure zu-levels
4731                                                 rrtm_plev_tmp,  & !< temporary array for pressure zw-levels
4732                                                 trace_path_tmp    !< temporary array for storing trace gas path data
4733
4734       REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  trace_mls,      & !< array for storing the absorber amounts
4735                                                 trace_mls_path, & !< array for storing trace gas path data
4736                                                 trace_mls_tmp     !< temporary array for storing trace gas data
4737
4738
4739!
4740!--    In case of updates, deallocate arrays first (sufficient to check one
4741!--    array as the others are automatically allocated)
4742       IF ( ALLOCATED ( rrtm_o3vmr ) )  THEN
4743          DEALLOCATE ( rrtm_o3vmr  )
4744          DEALLOCATE ( rrtm_co2vmr )
4745          DEALLOCATE ( rrtm_ch4vmr )
4746          DEALLOCATE ( rrtm_n2ovmr )
4747          DEALLOCATE ( rrtm_o2vmr  )
4748          DEALLOCATE ( rrtm_cfc11vmr )
4749          DEALLOCATE ( rrtm_cfc12vmr )
4750          DEALLOCATE ( rrtm_cfc22vmr )
4751          DEALLOCATE ( rrtm_ccl4vmr  )
4752          DEALLOCATE ( rrtm_h2ovmr  )     
4753       ENDIF
4754
4755!
4756!--    Allocate trace gas profiles
4757       ALLOCATE ( rrtm_o3vmr(0:0,1:nzt_rad+1)  )
4758       ALLOCATE ( rrtm_co2vmr(0:0,1:nzt_rad+1) )
4759       ALLOCATE ( rrtm_ch4vmr(0:0,1:nzt_rad+1) )
4760       ALLOCATE ( rrtm_n2ovmr(0:0,1:nzt_rad+1) )
4761       ALLOCATE ( rrtm_o2vmr(0:0,1:nzt_rad+1)  )
4762       ALLOCATE ( rrtm_cfc11vmr(0:0,1:nzt_rad+1) )
4763       ALLOCATE ( rrtm_cfc12vmr(0:0,1:nzt_rad+1) )
4764       ALLOCATE ( rrtm_cfc22vmr(0:0,1:nzt_rad+1) )
4765       ALLOCATE ( rrtm_ccl4vmr(0:0,1:nzt_rad+1)  )
4766       ALLOCATE ( rrtm_h2ovmr(0:0,1:nzt_rad+1)  )
4767
4768!
4769!--    Open file for reading
4770       nc_stat = NF90_OPEN( rrtm_input_file, NF90_NOWRITE, id )
4771       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 549 )
4772!
4773!--    Inquire dimension ids and dimensions
4774       nc_stat = NF90_INQ_DIMID( id, "Pressure", id_dim )
4775       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4776       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim, len = np) 
4777       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4778
4779       nc_stat = NF90_INQ_DIMID( id, "Absorber", id_dim )
4780       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4781       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim, len = nabs ) 
4782       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4783   
4784
4785!
4786!--    Allocate pressure, and trace gas arrays     
4787       ALLOCATE( p_mls(1:np) )
4788       ALLOCATE( trace_mls(1:num_trace_gases,1:np) ) 
4789       ALLOCATE( trace_mls_tmp(1:nabs,1:np) ) 
4790
4791
4792       nc_stat = NF90_INQ_VARID( id, "Pressure", id_var )
4793       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4794       nc_stat = NF90_GET_VAR( id, id_var, p_mls )
4795       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4796
4797       nc_stat = NF90_INQ_VARID( id, "AbsorberAmountMLS", id_var )
4798       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4799       nc_stat = NF90_GET_VAR( id, id_var, trace_mls_tmp )
4800       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4801
4802
4803!
4804!--    Write absorber amounts (mls) to trace_mls
4805       DO n = 1, num_trace_gases
4806          CALL getAbsorberIndex( TRIM( trace_names(n) ), id_abs )
4807
4808          trace_mls(n,1:np) = trace_mls_tmp(id_abs,1:np)
4809
4810!
4811!--       Replace missing values by zero
4812          WHERE ( trace_mls(n,:) > 2.0_wp ) 
4813             trace_mls(n,:) = 0.0_wp
4814          END WHERE
4815       END DO
4816
4817       DEALLOCATE ( trace_mls_tmp )
4818
4819       nc_stat = NF90_CLOSE( id )
4820       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 551 )
4821
4822!
4823!--    Add extra pressure level for calculations of the trace gas paths
4824       ALLOCATE ( rrtm_play_tmp(1:nzt_rad+1) )
4825       ALLOCATE ( rrtm_plev_tmp(1:nzt_rad+2) )
4826
4827       rrtm_play_tmp(1:nzt_rad)   = rrtm_play(0,1:nzt_rad) 
4828       rrtm_plev_tmp(1:nzt_rad+1) = rrtm_plev(0,1:nzt_rad+1)
4829       rrtm_play_tmp(nzt_rad+1)   = rrtm_plev(0,nzt_rad+1) * 0.5_wp
4830       rrtm_plev_tmp(nzt_rad+2)   = MIN( 1.0E-4_wp, 0.25_wp                    &
4831                                         * rrtm_plev(0,nzt_rad+1) )
4832 
4833!
4834!--    Calculate trace gas path (zero at surface) with interpolation to the
4835!--    sounding levels
4836       ALLOCATE ( trace_mls_path(1:nzt_rad+2,1:num_trace_gases) )
4837
4838       trace_mls_path(nzb+1,:) = 0.0_wp
4839       
4840       DO k = nzb+2, nzt_rad+2
4841          DO m = 1, num_trace_gases
4842             trace_mls_path(k,m) = trace_mls_path(k-1,m)
4843
4844!
4845!--          When the pressure level is higher than the trace gas pressure
4846!--          level, assume that
4847             IF ( rrtm_plev_tmp(k-1) > p_mls(1) )  THEN             
4848               
4849                trace_mls_path(k,m) = trace_mls_path(k,m) + trace_mls(m,1)     &
4850                                      * ( rrtm_plev_tmp(k-1)                   &
4851                                          - MAX( p_mls(1), rrtm_plev_tmp(k) )  &
4852                                        ) / g
4853             ENDIF
4854
4855!
4856!--          Integrate for each sounding level from the contributing p_mls
4857!--          levels
4858             DO n = 2, np
4859!
4860!--             Limit p_mls so that it is within the model level
4861                p_mls_u = MIN( rrtm_plev_tmp(k-1),                             &
4862                          MAX( rrtm_plev_tmp(k), p_mls(n) ) )
4863                p_mls_l = MIN( rrtm_plev_tmp(k-1),                             &
4864                          MAX( rrtm_plev_tmp(k), p_mls(n-1) ) )
4865
4866                IF ( p_mls_l > p_mls_u )  THEN
4867
4868!
4869!--                Calculate weights for interpolation
4870                   p_mls_m = 0.5_wp * (p_mls_l + p_mls_u)
4871                   p_wgt_u = (p_mls(n-1) - p_mls_m) / (p_mls(n-1) - p_mls(n))
4872                   p_wgt_l = (p_mls_m - p_mls(n))   / (p_mls(n-1) - p_mls(n))
4873
4874!
4875!--                Add level to trace gas path
4876                   trace_mls_path(k,m) = trace_mls_path(k,m)                   &
4877                                         +  ( p_wgt_u * trace_mls(m,n)         &
4878                                            + p_wgt_l * trace_mls(m,n-1) )     &
4879                                         * (p_mls_l - p_mls_u) / g
4880                ENDIF
4881             ENDDO
4882
4883             IF ( rrtm_plev_tmp(k) < p_mls(np) )  THEN
4884                trace_mls_path(k,m) = trace_mls_path(k,m) + trace_mls(m,np)    &
4885                                      * ( MIN( rrtm_plev_tmp(k-1), p_mls(np) ) &
4886                                          - rrtm_plev_tmp(k)                   &
4887                                        ) / g 
4888             ENDIF 
4889          ENDDO
4890       ENDDO
4891
4892
4893!
4894!--    Prepare trace gas path profiles
4895       ALLOCATE ( trace_path_tmp(1:nzt_rad+1) )
4896
4897       DO m = 1, num_trace_gases
4898
4899          trace_path_tmp(1:nzt_rad+1) = ( trace_mls_path(2:nzt_rad+2,m)        &
4900                                       - trace_mls_path(1:nzt_rad+1,m) ) * g   &
4901                                       / ( rrtm_plev_tmp(1:nzt_rad+1)          &
4902                                       - rrtm_plev_tmp(2:nzt_rad+2) )
4903
4904!
4905!--       Save trace gas paths to the respective arrays
4906          SELECT CASE ( TRIM( trace_names(m) ) )
4907
4908             CASE ( 'O3' )
4909
4910                rrtm_o3vmr(0,:) = trace_path_tmp(:)
4911
4912             CASE ( 'CO2' )
4913
4914                rrtm_co2vmr(0,:) = trace_path_tmp(:)
4915
4916             CASE ( 'CH4' )
4917
4918                rrtm_ch4vmr(0,:) = trace_path_tmp(:)
4919
4920             CASE ( 'N2O' )
4921
4922                rrtm_n2ovmr(0,:) = trace_path_tmp(:)
4923
4924             CASE ( 'O2' )
4925
4926                rrtm_o2vmr(0,:) = trace_path_tmp(:)
4927
4928             CASE ( 'CFC11' )
4929
4930                rrtm_cfc11vmr(0,:) = trace_path_tmp(:)
4931
4932             CASE ( 'CFC12' )
4933
4934                rrtm_cfc12vmr(0,:) = trace_path_tmp(:)
4935
4936             CASE ( 'CFC22' )
4937
4938                rrtm_cfc22vmr(0,:) = trace_path_tmp(:)
4939
4940             CASE ( 'CCL4' )
4941
4942                rrtm_ccl4vmr(0,:) = trace_path_tmp(:)
4943
4944             CASE ( 'H2O' )
4945
4946                rrtm_h2ovmr(0,:) = trace_path_tmp(:)
4947               
4948             CASE DEFAULT
4949
4950          END SELECT
4951
4952       ENDDO
4953
4954       DEALLOCATE ( trace_path_tmp )
4955       DEALLOCATE ( trace_mls_path )
4956       DEALLOCATE ( rrtm_play_tmp )
4957       DEALLOCATE ( rrtm_plev_tmp )
4958       DEALLOCATE ( trace_mls )
4959       DEALLOCATE ( p_mls )
4960
4961    END SUBROUTINE read_trace_gas_data
4962
4963
4964    SUBROUTINE netcdf_handle_error_rad( routine_name, errno )
4965
4966       USE control_parameters,                                                 &
4967           ONLY:  message_string
4968
4969       USE NETCDF
4970
4971       USE pegrid
4972
4973       IMPLICIT NONE
4974
4975       CHARACTER(LEN=6) ::  message_identifier
4976       CHARACTER(LEN=*) ::  routine_name
4977
4978       INTEGER(iwp) ::  errno
4979
4980       IF ( nc_stat /= NF90_NOERR )  THEN
4981
4982          WRITE( message_identifier, '(''NC'',I4.4)' )  errno
4983          message_string = TRIM( NF90_STRERROR( nc_stat ) )
4984
4985          CALL message( routine_name, message_identifier, 2, 2, 0, 6, 1 )
4986
4987       ENDIF
4988
4989    END SUBROUTINE netcdf_handle_error_rad
4990#endif
4991
4992
4993!------------------------------------------------------------------------------!
4994! Description:
4995! ------------
4996!> Calculate temperature tendency due to radiative cooling/heating.
4997!> Cache-optimized version.
4998!------------------------------------------------------------------------------!
4999#if defined( __rrtmg )
5000 SUBROUTINE radiation_tendency_ij ( i, j, tend )
5001
5002    IMPLICIT NONE
5003
5004    INTEGER(iwp) :: i, j, k !< loop indices
5005
5006    REAL(wp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg) :: tend !< pt tendency term
5007
5008    IF ( radiation_scheme == 'rrtmg' )  THEN
5009!
5010!--    Calculate tendency based on heating rate
5011       DO k = nzb+1, nzt+1
5012          tend(k,j,i) = tend(k,j,i) + (rad_lw_hr(k,j,i) + rad_sw_hr(k,j,i))    &
5013                                         * d_exner(k) * d_seconds_hour
5014       ENDDO
5015
5016    ENDIF
5017
5018 END SUBROUTINE radiation_tendency_ij
5019#endif
5020
5021
5022!------------------------------------------------------------------------------!
5023! Description:
5024! ------------
5025!> Calculate temperature tendency due to radiative cooling/heating.
5026!> Vector-optimized version
5027!------------------------------------------------------------------------------!
5028#if defined( __rrtmg )
5029 SUBROUTINE radiation_tendency ( tend )
5030
5031    USE indices,                                                               &
5032        ONLY:  nxl, nxr, nyn, nys
5033
5034    IMPLICIT NONE
5035
5036    INTEGER(iwp) :: i, j, k !< loop indices
5037
5038    REAL(wp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg) :: tend !< pt tendency term
5039
5040    IF ( radiation_scheme == 'rrtmg' )  THEN
5041!
5042!--    Calculate tendency based on heating rate
5043       DO  i = nxl, nxr
5044          DO  j = nys, nyn
5045             DO k = nzb+1, nzt+1
5046                tend(k,j,i) = tend(k,j,i) + ( rad_lw_hr(k,j,i)                 &
5047                                          +  rad_sw_hr(k,j,i) ) * d_exner(k)   &
5048                                          * d_seconds_hour
5049             ENDDO
5050          ENDDO
5051       ENDDO
5052    ENDIF
5053
5054 END SUBROUTINE radiation_tendency
5055#endif
5056
5057!------------------------------------------------------------------------------!
5058! Description:
5059! ------------
5060!> This subroutine calculates interaction of the solar radiation
5061!> with urban and land surfaces and updates all surface heatfluxes.
5062!> It calculates also the required parameters for RRTMG lower BC.
5063!>
5064!> For more info. see Resler et al. 2017
5065!>
5066!> The new version 2.0 was radically rewriten, the discretization scheme
5067!> has been changed. This new version significantly improves effectivity
5068!> of the paralelization and the scalability of the model.
5069!------------------------------------------------------------------------------!
5070
5071 SUBROUTINE radiation_interaction
5072
5073     IMPLICIT NONE
5074
5075     INTEGER(iwp)                      :: i, j, k, kk, d, refstep, m, mm, l, ll
5076     INTEGER(iwp)                      :: isurf, isurfsrc, isvf, icsf, ipcgb
5077     INTEGER(iwp)                      :: imrt, imrtf
5078     INTEGER(iwp)                      :: isd                !< solar direction number
5079     INTEGER(iwp)                      :: pc_box_dimshift    !< transform for best accuracy
5080     INTEGER(iwp), DIMENSION(0:3)      :: reorder = (/ 1, 0, 3, 2 /)
5081     
5082     REAL(wp), DIMENSION(3,3)          :: mrot               !< grid rotation matrix (zyx)
5083     REAL(wp), DIMENSION(3,0:nsurf_type):: vnorm             !< face direction normal vectors (zyx)
5084     REAL(wp), DIMENSION(3)            :: sunorig            !< grid rotated solar direction unit vector (zyx)
5085     REAL(wp), DIMENSION(3)            :: sunorig_grid       !< grid squashed solar direction unit vector (zyx)
5086     REAL(wp), DIMENSION(0:nsurf_type) :: costheta           !< direct irradiance factor of solar angle
5087     REAL(wp), DIMENSION(nz_urban_b:nz_urban_t)    :: pchf_prep          !< precalculated factor for canopy temperature tendency
5088     REAL(wp), PARAMETER               :: alpha = 0._wp      !< grid rotation (TODO: synchronize with rotation_angle
5089                                                             !< from netcdf_data_input_mod)
5090     REAL(wp)                          :: pc_box_area, pc_abs_frac, pc_abs_eff
5091     REAL(wp)                          :: asrc               !< area of source face
5092     REAL(wp)                          :: pcrad              !< irradiance from plant canopy
5093     REAL(wp)                          :: pabsswl  = 0.0_wp  !< total absorbed SW radiation energy in local processor (W)
5094     REAL(wp)                          :: pabssw   = 0.0_wp  !< total absorbed SW radiation energy in all processors (W)
5095     REAL(wp)                          :: pabslwl  = 0.0_wp  !< total absorbed LW radiation energy in local processor (W)
5096     REAL(wp)                          :: pabslw   = 0.0_wp  !< total absorbed LW radiation energy in all processors (W)
5097     REAL(wp)                          :: pemitlwl = 0.0_wp  !< total emitted LW radiation energy in all processors (W)
5098     REAL(wp)                          :: pemitlw  = 0.0_wp  !< total emitted LW radiation energy in all processors (W)
5099     REAL(wp)                          :: pinswl   = 0.0_wp  !< total received SW radiation energy in local processor (W)
5100     REAL(wp)                          :: pinsw    = 0.0_wp  !< total received SW radiation energy in all processor (W)
5101     REAL(wp)                          :: pinlwl   = 0.0_wp  !< total received LW radiation energy in local processor (W)
5102     REAL(wp)                          :: pinlw    = 0.0_wp  !< total received LW radiation energy in all processor (W)
5103     REAL(wp)                          :: emiss_sum_surfl    !< sum of emissisivity of surfaces in local processor
5104     REAL(wp)                          :: emiss_sum_surf     !< sum of emissisivity of surfaces in all processor
5105     REAL(wp)                          :: area_surfl         !< total area of surfaces in local processor
5106     REAL(wp)                          :: area_surf          !< total area of surfaces in all processor
5107     REAL(wp)                          :: area_hor           !< total horizontal area of domain in all processor
5108
5109
5110     IF ( debug_output )  CALL debug_message( 'radiation_interaction', 'start' )
5111
5112     IF ( plant_canopy )  THEN
5113         pchf_prep(:) = r_d * exner(nz_urban_b:nz_urban_t)                                 &
5114                     / (c_p * hyp(nz_urban_b:nz_urban_t) * dx*dy*dz(1)) !< equals to 1 / (rho * c_p * Vbox * T)
5115     ENDIF
5116
5117     sun_direction = .TRUE.
5118     CALL calc_zenith  !< required also for diffusion radiation
5119
5120!--     prepare rotated normal vectors and irradiance factor
5121     vnorm(1,:) = kdir(:)
5122     vnorm(2,:) = jdir(:)
5123     vnorm(3,:) = idir(:)
5124     mrot(1, :) = (/ 1._wp,  0._wp,      0._wp      /)
5125     mrot(2, :) = (/ 0._wp,  COS(alpha), SIN(alpha) /)
5126     mrot(3, :) = (/ 0._wp, -SIN(alpha), COS(alpha) /)
5127     sunorig = (/ cos_zenith, sun_dir_lat, sun_dir_lon /)
5128     sunorig = MATMUL(mrot, sunorig)
5129     DO d = 0, nsurf_type
5130         costheta(d) = DOT_PRODUCT(sunorig, vnorm(:,d))
5131     ENDDO
5132
5133     IF ( cos_zenith > 0 )  THEN
5134!--      now we will "squash" the sunorig vector by grid box size in
5135!--      each dimension, so that this new direction vector will allow us
5136!--      to traverse the ray path within grid coordinates directly
5137         sunorig_grid = (/ sunorig(1)/dz(1), sunorig(2)/dy, sunorig(3)/dx /)
5138!--      sunorig_grid = sunorig_grid / norm2(sunorig_grid)
5139         sunorig_grid = sunorig_grid / SQRT(SUM(sunorig_grid**2))
5140
5141         IF ( npcbl > 0 )  THEN
5142!--         precompute effective box depth with prototype Leaf Area Density
5143            pc_box_dimshift = MAXLOC(ABS(sunorig), 1) - 1
5144            CALL box_absorb(CSHIFT((/dz(1),dy,dx/), pc_box_dimshift),       &
5145                                60, prototype_lad,                          &
5146                                CSHIFT(ABS(sunorig), pc_box_dimshift),      &
5147                                pc_box_area, pc_abs_frac)
5148            pc_box_area = pc_box_area * ABS(sunorig(pc_box_dimshift+1)      &
5149                          / sunorig(1))
5150            pc_abs_eff = LOG(1._wp - pc_abs_frac) / prototype_lad
5151         ENDIF
5152     ENDIF
5153
5154!--  if radiation scheme is not RRTMG, split diffusion and direct part of the solar downward radiation
5155!--  comming from radiation model and store it in 2D arrays
5156     IF (  radiation_scheme /= 'rrtmg'  )  CALL calc_diffusion_radiation
5157
5158!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5159!--     First pass: direct + diffuse irradiance + thermal
5160!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5161     surfinswdir   = 0._wp !nsurfl
5162     surfins       = 0._wp !nsurfl
5163     surfinl       = 0._wp !nsurfl
5164     surfoutsl(:)  = 0.0_wp !start-end
5165     surfoutll(:)  = 0.0_wp !start-end
5166     IF ( nmrtbl > 0 )  THEN
5167        mrtinsw(:) = 0._wp
5168        mrtinlw(:) = 0._wp
5169     ENDIF
5170     surfinlg(:)  = 0._wp !global
5171
5172
5173!--  Set up thermal radiation from surfaces
5174!--  emiss_surf is defined only for surfaces for which energy balance is calculated
5175!--  Workaround: reorder surface data type back on 1D array including all surfaces,
5176!--  which implies to reorder horizontal and vertical surfaces
5177!
5178!--  Horizontal walls
5179     mm = 1
5180     DO  i = nxl, nxr
5181        DO  j = nys, nyn
5182!--           urban
5183           DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
5184              surfoutll(mm) = SUM ( surf_usm_h%frac(:,m) *                  &
5185                                    surf_usm_h%emissivity(:,m) )            &
5186                                  * sigma_sb                                &
5187                                  * surf_usm_h%pt_surface(m)**4
5188              albedo_surf(mm) = SUM ( surf_usm_h%frac(:,m) *                &
5189                                      surf_usm_h%albedo(:,m) )
5190              emiss_surf(mm)  = SUM ( surf_usm_h%frac(:,m) *                &
5191                                      surf_usm_h%emissivity(:,m) )
5192              mm = mm + 1
5193           ENDDO
5194!--           land
5195           DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
5196              surfoutll(mm) = SUM ( surf_lsm_h%frac(:,m) *                  &
5197                                    surf_lsm_h%emissivity(:,m) )            &
5198                                  * sigma_sb                                &
5199                                  * surf_lsm_h%pt_surface(m)**4
5200              albedo_surf(mm) = SUM ( surf_lsm_h%frac(:,m) *                &
5201                                      surf_lsm_h%albedo(:,m) )
5202              emiss_surf(mm)  = SUM ( surf_lsm_h%frac(:,m) *                &
5203                                      surf_lsm_h%emissivity(:,m) )
5204              mm = mm + 1
5205           ENDDO
5206        ENDDO
5207     ENDDO
5208!
5209!--     Vertical walls
5210     DO  i = nxl, nxr
5211        DO  j = nys, nyn
5212           DO  ll = 0, 3
5213              l = reorder(ll)
5214!--              urban
5215              DO  m = surf_usm_v(l)%start_index(j,i),                       &
5216                      surf_usm_v(l)%end_index(j,i)
5217                 surfoutll(mm) = SUM ( surf_usm_v(l)%frac(:,m) *            &
5218                                       surf_usm_v(l)%emissivity(:,m) )      &
5219                                  * sigma_sb                                &
5220                                  * surf_usm_v(l)%pt_surface(m)**4
5221                 albedo_surf(mm) = SUM ( surf_usm_v(l)%frac(:,m) *          &
5222                                         surf_usm_v(l)%albedo(:,m) )
5223                 emiss_surf(mm)  = SUM ( surf_usm_v(l)%frac(:,m) *          &
5224                                         surf_usm_v(l)%emissivity(:,m) )
5225                 mm = mm + 1
5226              ENDDO
5227!--              land
5228              DO  m = surf_lsm_v(l)%start_index(j,i),                       &
5229                      surf_lsm_v(l)%end_index(j,i)
5230                 surfoutll(mm) = SUM ( surf_lsm_v(l)%frac(:,m) *            &
5231                                       surf_lsm_v(l)%emissivity(:,m) )      &
5232                                  * sigma_sb                                &
5233                                  * surf_lsm_v(l)%pt_surface(m)**4
5234                 albedo_surf(mm) = SUM ( surf_lsm_v(l)%frac(:,m) *          &
5235                                         surf_lsm_v(l)%albedo(:,m) )
5236                 emiss_surf(mm)  = SUM ( surf_lsm_v(l)%frac(:,m) *          &
5237                                         surf_lsm_v(l)%emissivity(:,m) )
5238                 mm = mm + 1
5239              ENDDO
5240           ENDDO
5241        ENDDO
5242     ENDDO
5243
5244#if defined( __parallel )
5245!--     might be optimized and gather only values relevant for current processor
5246     CALL MPI_AllGatherv(surfoutll, nsurfl, MPI_REAL, &
5247                         surfoutl, nsurfs, surfstart, MPI_REAL, comm2d, ierr) !nsurf global
5248     IF ( ierr /= 0 ) THEN
5249         WRITE(9,*) 'Error MPI_AllGatherv1:', ierr, SIZE(surfoutll), nsurfl, &
5250                     SIZE(surfoutl), nsurfs, surfstart
5251         FLUSH(9)
5252     ENDIF
5253#else
5254     surfoutl(:) = surfoutll(:) !nsurf global
5255#endif
5256
5257     IF ( surface_reflections)  THEN
5258        DO  isvf = 1, nsvfl
5259           isurf = svfsurf(1, isvf)
5260           k     = surfl(iz, isurf)
5261           j     = surfl(iy, isurf)
5262           i     = surfl(ix, isurf)
5263           isurfsrc = svfsurf(2, isvf)
5264!
5265!--        For surface-to-surface factors we calculate thermal radiation in 1st pass
5266           IF ( plant_lw_interact )  THEN
5267              surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * svf(2,isvf) * surfoutl(isurfsrc)
5268           ELSE
5269              surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * surfoutl(isurfsrc)
5270           ENDIF
5271        ENDDO
5272     ENDIF
5273!
5274!--  diffuse radiation using sky view factor
5275     DO isurf = 1, nsurfl
5276        j = surfl(iy, isurf)
5277        i = surfl(ix, isurf)
5278        surfinswdif(isurf) = rad_sw_in_diff(j,i) * skyvft(isurf)
5279        IF ( plant_lw_interact )  THEN
5280           surfinlwdif(isurf) = rad_lw_in_diff(j,i) * skyvft(isurf)
5281        ELSE
5282           surfinlwdif(isurf) = rad_lw_in_diff(j,i) * skyvf(isurf)
5283        ENDIF
5284     ENDDO
5285!
5286!--  MRT diffuse irradiance
5287     DO  imrt = 1, nmrtbl
5288        j = mrtbl(iy, imrt)
5289        i = mrtbl(ix, imrt)
5290        mrtinsw(imrt) = mrtskyt(imrt) * rad_sw_in_diff(j,i)
5291        mrtinlw(imrt) = mrtsky(imrt) * rad_lw_in_diff(j,i)
5292     ENDDO
5293
5294     !-- direct radiation
5295     IF ( cos_zenith > 0 )  THEN
5296        !--Identify solar direction vector (discretized number) 1)
5297        !--
5298        j = FLOOR(ACOS(cos_zenith) / pi * raytrace_discrete_elevs)
5299        i = MODULO(NINT(ATAN2(sun_dir_lon, sun_dir_lat)               &
5300                        / (2._wp*pi) * raytrace_discrete_azims-.5_wp, iwp), &
5301                   raytrace_discrete_azims)
5302        isd = dsidir_rev(j, i)
5303!-- TODO: check if isd = -1 to report that this solar position is not precalculated
5304        DO isurf = 1, nsurfl
5305           j = surfl(iy, isurf)
5306           i = surfl(ix, isurf)
5307           surfinswdir(isurf) = rad_sw_in_dir(j,i) *                        &
5308                costheta(surfl(id, isurf)) * dsitrans(isurf, isd) / cos_zenith
5309        ENDDO
5310!
5311!--     MRT direct irradiance
5312        DO  imrt = 1, nmrtbl
5313           j = mrtbl(iy, imrt)
5314           i = mrtbl(ix, imrt)
5315           mrtinsw(imrt) = mrtinsw(imrt) + mrtdsit(imrt, isd) * rad_sw_in_dir(j,i) &
5316                                     / cos_zenith / 4._wp ! normal to sphere
5317        ENDDO
5318     ENDIF
5319!
5320!--  MRT first pass thermal
5321     DO  imrtf = 1, nmrtf
5322        imrt = mrtfsurf(1, imrtf)
5323        isurfsrc = mrtfsurf(2, imrtf)
5324        mrtinlw(imrt) = mrtinlw(imrt) + mrtf(imrtf) * surfoutl(isurfsrc)
5325     ENDDO
5326!
5327!--  Absorption in each local plant canopy grid box from the first atmospheric
5328!--  pass of radiation
5329     IF ( npcbl > 0 )  THEN
5330
5331         pcbinswdir(:) = 0._wp
5332         pcbinswdif(:) = 0._wp
5333         pcbinlw(:) = 0._wp
5334
5335         DO icsf = 1, ncsfl
5336             ipcgb = csfsurf(1, icsf)
5337             i = pcbl(ix,ipcgb)
5338             j = pcbl(iy,ipcgb)
5339             k = pcbl(iz,ipcgb)
5340             isurfsrc = csfsurf(2, icsf)
5341
5342             IF ( isurfsrc == -1 )  THEN
5343!
5344!--             Diffuse radiation from sky
5345                pcbinswdif(ipcgb) = csf(1,icsf) * rad_sw_in_diff(j,i)
5346!
5347!--             Absorbed diffuse LW radiation from sky minus emitted to sky
5348                IF ( plant_lw_interact )  THEN
5349                   pcbinlw(ipcgb) = csf(1,icsf)                                  &
5350                                       * (rad_lw_in_diff(j, i)                   &
5351                                          - sigma_sb * (pt(k,j,i)*exner(k))**4)
5352                ENDIF
5353!
5354!--             Direct solar radiation
5355                IF ( cos_zenith > 0 )  THEN
5356!--                Estimate directed box absorption
5357                   pc_abs_frac = 1._wp - exp(pc_abs_eff * lad_s(k,j,i))
5358!
5359!--                isd has already been established, see 1)
5360                   pcbinswdir(ipcgb) = rad_sw_in_dir(j, i) * pc_box_area &
5361                                       * pc_abs_frac * dsitransc(ipcgb, isd)
5362                ENDIF
5363             ELSE
5364                IF ( plant_lw_interact )  THEN
5365!
5366!--                Thermal emission from plan canopy towards respective face
5367                   pcrad = sigma_sb * (pt(k,j,i) * exner(k))**4 * csf(1,icsf)
5368                   surfinlg(isurfsrc) = surfinlg(isurfsrc) + pcrad
5369!
5370!--                Remove the flux above + absorb LW from first pass from surfaces
5371                   asrc = facearea(surf(id, isurfsrc))
5372                   pcbinlw(ipcgb) = pcbinlw(ipcgb)                      &
5373                                    + (csf(1,icsf) * surfoutl(isurfsrc) & ! Absorb from first pass surf emit
5374                                       - pcrad)                         & ! Remove emitted heatflux
5375                                    * asrc
5376                ENDIF
5377             ENDIF
5378         ENDDO
5379
5380         pcbinsw(:) = pcbinswdir(:) + pcbinswdif(:)
5381     ENDIF
5382
5383     IF ( plant_lw_interact )  THEN
5384!
5385!--     Exchange incoming lw radiation from plant canopy
5386#if defined( __parallel )
5387        CALL MPI_Allreduce(MPI_IN_PLACE, surfinlg, nsurf, MPI_REAL, MPI_SUM, comm2d, ierr)
5388        IF ( ierr /= 0 )  THEN
5389           WRITE (9,*) 'Error MPI_Allreduce:', ierr
5390           FLUSH(9)
5391        ENDIF
5392        surfinl(:) = surfinl(:) + surfinlg(surfstart(myid)+1:surfstart(myid+1))
5393#else
5394        surfinl(:) = surfinl(:) + surfinlg(:)
5395#endif
5396     ENDIF
5397
5398     surfins = surfinswdir + surfinswdif
5399     surfinl = surfinl + surfinlwdif
5400     surfinsw = surfins
5401     surfinlw = surfinl
5402     surfoutsw = 0.0_wp
5403     surfoutlw = surfoutll
5404     surfemitlwl = surfoutll
5405
5406     IF ( .NOT.  surface_reflections )  THEN
5407!
5408!--     Set nrefsteps to 0 to disable reflections       
5409        nrefsteps = 0
5410        surfoutsl = albedo_surf * surfins
5411        surfoutll = (1._wp - emiss_surf) * surfinl
5412        surfoutsw = surfoutsw + surfoutsl
5413        surfoutlw = surfoutlw + surfoutll
5414     ENDIF
5415
5416!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5417!--     Next passes - reflections
5418!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5419     DO refstep = 1, nrefsteps
5420
5421         surfoutsl = albedo_surf * surfins
5422!
5423!--      for non-transparent surfaces, longwave albedo is 1 - emissivity
5424         surfoutll = (1._wp - emiss_surf) * surfinl
5425
5426#if defined( __parallel )
5427         CALL MPI_AllGatherv(surfoutsl, nsurfl, MPI_REAL, &
5428             surfouts, nsurfs, surfstart, MPI_REAL, comm2d, ierr)
5429         IF ( ierr /= 0 )  THEN
5430             WRITE(9,*) 'Error MPI_AllGatherv2:', ierr, SIZE(surfoutsl), nsurfl, &
5431                        SIZE(surfouts), nsurfs, surfstart
5432             FLUSH(9)
5433         ENDIF
5434
5435         CALL MPI_AllGatherv(surfoutll, nsurfl, MPI_REAL, &
5436             surfoutl, nsurfs, surfstart, MPI_REAL, comm2d, ierr)
5437         IF ( ierr /= 0 )  THEN
5438             WRITE(9,*) 'Error MPI_AllGatherv3:', ierr, SIZE(surfoutll), nsurfl, &
5439                        SIZE(surfoutl), nsurfs, surfstart
5440             FLUSH(9)
5441         ENDIF
5442
5443#else
5444         surfouts = surfoutsl
5445         surfoutl = surfoutll
5446#endif
5447!
5448!--      Reset for the input from next reflective pass
5449         surfins = 0._wp
5450         surfinl = 0._wp
5451!
5452!--      Reflected radiation
5453         DO isvf = 1, nsvfl
5454             isurf = svfsurf(1, isvf)
5455             isurfsrc = svfsurf(2, isvf)
5456             surfins(isurf) = surfins(isurf) + svf(1,isvf) * svf(2,isvf) * surfouts(isurfsrc)
5457             IF ( plant_lw_interact )  THEN
5458                surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * svf(2,isvf) * surfoutl(isurfsrc)
5459             ELSE
5460                surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * surfoutl(isurfsrc)
5461             ENDIF
5462         ENDDO
5463!
5464!--      NOTE: PC absorbtion and MRT from reflected can both be done at once
5465!--      after all reflections if we do one more MPI_ALLGATHERV on surfout.
5466!--      Advantage: less local computation. Disadvantage: one more collective
5467!--      MPI call.
5468!
5469!--      Radiation absorbed by plant canopy
5470         DO  icsf = 1, ncsfl
5471             ipcgb = csfsurf(1, icsf)
5472             isurfsrc = csfsurf(2, icsf)
5473             IF ( isurfsrc == -1 )  CYCLE ! sky->face only in 1st pass, not here
5474!
5475!--          Calculate source surface area. If the `surf' array is removed
5476!--          before timestepping starts (future version), then asrc must be
5477!--          stored within `csf'
5478             asrc = facearea(surf(id, isurfsrc))
5479             pcbinsw(ipcgb) = pcbinsw(ipcgb) + csf(1,icsf) * surfouts(isurfsrc) * asrc
5480             IF ( plant_lw_interact )  THEN
5481                pcbinlw(ipcgb) = pcbinlw(ipcgb) + csf(1,icsf) * surfoutl(isurfsrc) * asrc
5482             ENDIF
5483         ENDDO
5484!
5485!--      MRT reflected
5486         DO  imrtf = 1, nmrtf
5487            imrt = mrtfsurf(1, imrtf)
5488            isurfsrc = mrtfsurf(2, imrtf)
5489            mrtinsw(imrt) = mrtinsw(imrt) + mrtft(imrtf) * surfouts(isurfsrc)
5490            mrtinlw(imrt) = mrtinlw(imrt) + mrtf(imrtf) * surfoutl(isurfsrc)
5491         ENDDO
5492
5493         surfinsw = surfinsw  + surfins
5494         surfinlw = surfinlw  + surfinl
5495         surfoutsw = surfoutsw + surfoutsl
5496         surfoutlw = surfoutlw + surfoutll
5497
5498     ENDDO ! refstep
5499
5500!--  push heat flux absorbed by plant canopy to respective 3D arrays
5501     IF ( npcbl > 0 )  THEN
5502         pc_heating_rate(:,:,:) = 0.0_wp
5503         DO ipcgb = 1, npcbl
5504             j = pcbl(iy, ipcgb)
5505             i = pcbl(ix, ipcgb)
5506             k = pcbl(iz, ipcgb)
5507!
5508!--          Following expression equals former kk = k - nzb_s_inner(j,i)
5509             kk = k - get_topography_top_index_ji( j, i, 's' )  !- lad arrays are defined flat
5510             pc_heating_rate(kk, j, i) = (pcbinsw(ipcgb) + pcbinlw(ipcgb)) &
5511                 * pchf_prep(k) * pt(k, j, i) !-- = dT/dt
5512         ENDDO
5513
5514         IF ( humidity .AND. plant_canopy_transpiration ) THEN
5515!--          Calculation of plant canopy transpiration rate and correspondidng latent heat rate
5516             pc_transpiration_rate(:,:,:) = 0.0_wp
5517             pc_latent_rate(:,:,:) = 0.0_wp
5518             DO ipcgb = 1, npcbl
5519                 i = pcbl(ix, ipcgb)
5520                 j = pcbl(iy, ipcgb)
5521                 k = pcbl(iz, ipcgb)
5522                 kk = k - get_topography_top_index_ji( j, i, 's' )  !- lad arrays are defined flat
5523                 CALL pcm_calc_transpiration_rate( i, j, k, kk, pcbinsw(ipcgb), pcbinlw(ipcgb), &
5524                                                   pc_transpiration_rate(kk,j,i), pc_latent_rate(kk,j,i) )
5525              ENDDO
5526         ENDIF
5527     ENDIF
5528!
5529!--  Calculate black body MRT (after all reflections)
5530     IF ( nmrtbl > 0 )  THEN
5531        IF ( mrt_include_sw )  THEN
5532           mrt(:) = ((mrtinsw(:) + mrtinlw(:)) / sigma_sb) ** .25_wp
5533        ELSE
5534           mrt(:) = (mrtinlw(:) / sigma_sb) ** .25_wp
5535        ENDIF
5536     ENDIF
5537!
5538!--     Transfer radiation arrays required for energy balance to the respective data types
5539     DO  i = 1, nsurfl
5540        m  = surfl(im,i)
5541!
5542!--     (1) Urban surfaces
5543!--     upward-facing
5544        IF ( surfl(1,i) == iup_u )  THEN
5545           surf_usm_h%rad_sw_in(m)  = surfinsw(i)
5546           surf_usm_h%rad_sw_out(m) = surfoutsw(i)
5547           surf_usm_h%rad_sw_dir(m) = surfinswdir(i)
5548           surf_usm_h%rad_sw_dif(m) = surfinswdif(i)
5549           surf_usm_h%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -        &
5550                                      surfinswdif(i)
5551           surf_usm_h%rad_sw_res(m) = surfins(i)
5552           surf_usm_h%rad_lw_in(m)  = surfinlw(i)
5553           surf_usm_h%rad_lw_out(m) = surfoutlw(i)
5554           surf_usm_h%rad_net(m)    = surfinsw(i) - surfoutsw(i) +          &
5555                                      surfinlw(i) - surfoutlw(i)
5556           surf_usm_h%rad_net_l(m)  = surf_usm_h%rad_net(m)
5557           surf_usm_h%rad_lw_dif(m) = surfinlwdif(i)
5558           surf_usm_h%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5559           surf_usm_h%rad_lw_res(m) = surfinl(i)
5560!
5561!--     northward-facding
5562        ELSEIF ( surfl(1,i) == inorth_u )  THEN
5563           surf_usm_v(0)%rad_sw_in(m)  = surfinsw(i)
5564           surf_usm_v(0)%rad_sw_out(m) = surfoutsw(i)
5565           surf_usm_v(0)%rad_sw_dir(m) = surfinswdir(i)
5566           surf_usm_v(0)%rad_sw_dif(m) = surfinswdif(i)
5567           surf_usm_v(0)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5568                                         surfinswdif(i)
5569           surf_usm_v(0)%rad_sw_res(m) = surfins(i)
5570           surf_usm_v(0)%rad_lw_in(m)  = surfinlw(i)
5571           surf_usm_v(0)%rad_lw_out(m) = surfoutlw(i)
5572           surf_usm_v(0)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5573                                         surfinlw(i) - surfoutlw(i)
5574           surf_usm_v(0)%rad_net_l(m)  = surf_usm_v(0)%rad_net(m)
5575           surf_usm_v(0)%rad_lw_dif(m) = surfinlwdif(i)
5576           surf_usm_v(0)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5577           surf_usm_v(0)%rad_lw_res(m) = surfinl(i)
5578!
5579!--     southward-facding
5580        ELSEIF ( surfl(1,i) == isouth_u )  THEN
5581           surf_usm_v(1)%rad_sw_in(m)  = surfinsw(i)
5582           surf_usm_v(1)%rad_sw_out(m) = surfoutsw(i)
5583           surf_usm_v(1)%rad_sw_dir(m) = surfinswdir(i)
5584           surf_usm_v(1)%rad_sw_dif(m) = surfinswdif(i)
5585           surf_usm_v(1)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5586                                         surfinswdif(i)
5587           surf_usm_v(1)%rad_sw_res(m) = surfins(i)
5588           surf_usm_v(1)%rad_lw_in(m)  = surfinlw(i)
5589           surf_usm_v(1)%rad_lw_out(m) = surfoutlw(i)
5590           surf_usm_v(1)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5591                                         surfinlw(i) - surfoutlw(i)
5592           surf_usm_v(1)%rad_net_l(m)  = surf_usm_v(1)%rad_net(m)
5593           surf_usm_v(1)%rad_lw_dif(m) = surfinlwdif(i)
5594           surf_usm_v(1)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5595           surf_usm_v(1)%rad_lw_res(m) = surfinl(i)
5596!
5597!--     eastward-facing
5598        ELSEIF ( surfl(1,i) == ieast_u )  THEN
5599           surf_usm_v(2)%rad_sw_in(m)  = surfinsw(i)
5600           surf_usm_v(2)%rad_sw_out(m) = surfoutsw(i)
5601           surf_usm_v(2)%rad_sw_dir(m) = surfinswdir(i)
5602           surf_usm_v(2)%rad_sw_dif(m) = surfinswdif(i)
5603           surf_usm_v(2)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5604                                         surfinswdif(i)
5605           surf_usm_v(2)%rad_sw_res(m) = surfins(i)
5606           surf_usm_v(2)%rad_lw_in(m)  = surfinlw(i)
5607           surf_usm_v(2)%rad_lw_out(m) = surfoutlw(i)
5608           surf_usm_v(2)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5609                                         surfinlw(i) - surfoutlw(i)
5610           surf_usm_v(2)%rad_net_l(m)  = surf_usm_v(2)%rad_net(m)
5611           surf_usm_v(2)%rad_lw_dif(m) = surfinlwdif(i)
5612           surf_usm_v(2)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5613           surf_usm_v(2)%rad_lw_res(m) = surfinl(i)
5614!
5615!--     westward-facding
5616        ELSEIF ( surfl(1,i) == iwest_u )  THEN
5617           surf_usm_v(3)%rad_sw_in(m)  = surfinsw(i)
5618           surf_usm_v(3)%rad_sw_out(m) = surfoutsw(i)
5619           surf_usm_v(3)%rad_sw_dir(m) = surfinswdir(i)
5620           surf_usm_v(3)%rad_sw_dif(m) = surfinswdif(i)
5621           surf_usm_v(3)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5622                                         surfinswdif(i)
5623           surf_usm_v(3)%rad_sw_res(m) = surfins(i)
5624           surf_usm_v(3)%rad_lw_in(m)  = surfinlw(i)
5625           surf_usm_v(3)%rad_lw_out(m) = surfoutlw(i)
5626           surf_usm_v(3)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5627                                         surfinlw(i) - surfoutlw(i)
5628           surf_usm_v(3)%rad_net_l(m)  = surf_usm_v(3)%rad_net(m)
5629           surf_usm_v(3)%rad_lw_dif(m) = surfinlwdif(i)
5630           surf_usm_v(3)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5631           surf_usm_v(3)%rad_lw_res(m) = surfinl(i)
5632!
5633!--     (2) land surfaces
5634!--     upward-facing
5635        ELSEIF ( surfl(1,i) == iup_l )  THEN
5636           surf_lsm_h%rad_sw_in(m)  = surfinsw(i)
5637           surf_lsm_h%rad_sw_out(m) = surfoutsw(i)
5638           surf_lsm_h%rad_sw_dir(m) = surfinswdir(i)
5639           surf_lsm_h%rad_sw_dif(m) = surfinswdif(i)
5640           surf_lsm_h%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -        &
5641                                         surfinswdif(i)
5642           surf_lsm_h%rad_sw_res(m) = surfins(i)
5643           surf_lsm_h%rad_lw_in(m)  = surfinlw(i)
5644           surf_lsm_h%rad_lw_out(m) = surfoutlw(i)
5645           surf_lsm_h%rad_net(m)    = surfinsw(i) - surfoutsw(i) +          &
5646                                      surfinlw(i) - surfoutlw(i)
5647           surf_lsm_h%rad_lw_dif(m) = surfinlwdif(i)
5648           surf_lsm_h%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5649           surf_lsm_h%rad_lw_res(m) = surfinl(i)
5650!
5651!--     northward-facding
5652        ELSEIF ( surfl(1,i) == inorth_l )  THEN
5653           surf_lsm_v(0)%rad_sw_in(m)  = surfinsw(i)
5654           surf_lsm_v(0)%rad_sw_out(m) = surfoutsw(i)
5655           surf_lsm_v(0)%rad_sw_dir(m) = surfinswdir(i)
5656           surf_lsm_v(0)%rad_sw_dif(m) = surfinswdif(i)
5657           surf_lsm_v(0)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5658                                         surfinswdif(i)
5659           surf_lsm_v(0)%rad_sw_res(m) = surfins(i)
5660           surf_lsm_v(0)%rad_lw_in(m)  = surfinlw(i)
5661           surf_lsm_v(0)%rad_lw_out(m) = surfoutlw(i)
5662           surf_lsm_v(0)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5663                                         surfinlw(i) - surfoutlw(i)
5664           surf_lsm_v(0)%rad_lw_dif(m) = surfinlwdif(i)
5665           surf_lsm_v(0)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5666           surf_lsm_v(0)%rad_lw_res(m) = surfinl(i)
5667!
5668!--     southward-facding
5669        ELSEIF ( surfl(1,i) == isouth_l )  THEN
5670           surf_lsm_v(1)%rad_sw_in(m)  = surfinsw(i)
5671           surf_lsm_v(1)%rad_sw_out(m) = surfoutsw(i)
5672           surf_lsm_v(1)%rad_sw_dir(m) = surfinswdir(i)
5673           surf_lsm_v(1)%rad_sw_dif(m) = surfinswdif(i)
5674           surf_lsm_v(1)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5675                                         surfinswdif(i)
5676           surf_lsm_v(1)%rad_sw_res(m) = surfins(i)
5677           surf_lsm_v(1)%rad_lw_in(m)  = surfinlw(i)
5678           surf_lsm_v(1)%rad_lw_out(m) = surfoutlw(i)
5679           surf_lsm_v(1)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5680                                         surfinlw(i) - surfoutlw(i)
5681           surf_lsm_v(1)%rad_lw_dif(m) = surfinlwdif(i)
5682           surf_lsm_v(1)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5683           surf_lsm_v(1)%rad_lw_res(m) = surfinl(i)
5684!
5685!--     eastward-facing
5686        ELSEIF ( surfl(1,i) == ieast_l )  THEN
5687           surf_lsm_v(2)%rad_sw_in(m)  = surfinsw(i)
5688           surf_lsm_v(2)%rad_sw_out(m) = surfoutsw(i)
5689           surf_lsm_v(2)%rad_sw_dir(m) = surfinswdir(i)
5690           surf_lsm_v(2)%rad_sw_dif(m) = surfinswdif(i)
5691           surf_lsm_v(2)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5692                                         surfinswdif(i)
5693           surf_lsm_v(2)%rad_sw_res(m) = surfins(i)
5694           surf_lsm_v(2)%rad_lw_in(m)  = surfinlw(i)
5695           surf_lsm_v(2)%rad_lw_out(m) = surfoutlw(i)
5696           surf_lsm_v(2)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5697                                         surfinlw(i) - surfoutlw(i)
5698           surf_lsm_v(2)%rad_lw_dif(m) = surfinlwdif(i)
5699           surf_lsm_v(2)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5700           surf_lsm_v(2)%rad_lw_res(m) = surfinl(i)
5701!
5702!--     westward-facing
5703        ELSEIF ( surfl(1,i) == iwest_l )  THEN
5704           surf_lsm_v(3)%rad_sw_in(m)  = surfinsw(i)
5705           surf_lsm_v(3)%rad_sw_out(m) = surfoutsw(i)
5706           surf_lsm_v(3)%rad_sw_dir(m) = surfinswdir(i)
5707           surf_lsm_v(3)%rad_sw_dif(m) = surfinswdif(i)
5708           surf_lsm_v(3)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5709                                         surfinswdif(i)
5710           surf_lsm_v(3)%rad_sw_res(m) = surfins(i)
5711           surf_lsm_v(3)%rad_lw_in(m)  = surfinlw(i)
5712           surf_lsm_v(3)%rad_lw_out(m) = surfoutlw(i)
5713           surf_lsm_v(3)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5714                                         surfinlw(i) - surfoutlw(i)
5715           surf_lsm_v(3)%rad_lw_dif(m) = surfinlwdif(i)
5716           surf_lsm_v(3)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5717           surf_lsm_v(3)%rad_lw_res(m) = surfinl(i)
5718        ENDIF
5719
5720     ENDDO
5721
5722     DO  m = 1, surf_usm_h%ns
5723        surf_usm_h%surfhf(m) = surf_usm_h%rad_sw_in(m)  +                   &
5724                               surf_usm_h%rad_lw_in(m)  -                   &
5725                               surf_usm_h%rad_sw_out(m) -                   &
5726                               surf_usm_h%rad_lw_out(m)
5727     ENDDO
5728     DO  m = 1, surf_lsm_h%ns
5729        surf_lsm_h%surfhf(m) = surf_lsm_h%rad_sw_in(m)  +                   &
5730                               surf_lsm_h%rad_lw_in(m)  -                   &
5731                               surf_lsm_h%rad_sw_out(m) -                   &
5732                               surf_lsm_h%rad_lw_out(m)
5733     ENDDO
5734
5735     DO  l = 0, 3
5736!--     urban
5737        DO  m = 1, surf_usm_v(l)%ns
5738           surf_usm_v(l)%surfhf(m) = surf_usm_v(l)%rad_sw_in(m)  +          &
5739                                     surf_usm_v(l)%rad_lw_in(m)  -          &
5740                                     surf_usm_v(l)%rad_sw_out(m) -          &
5741                                     surf_usm_v(l)%rad_lw_out(m)
5742        ENDDO
5743!--     land
5744        DO  m = 1, surf_lsm_v(l)%ns
5745           surf_lsm_v(l)%surfhf(m) = surf_lsm_v(l)%rad_sw_in(m)  +          &
5746                                     surf_lsm_v(l)%rad_lw_in(m)  -          &
5747                                     surf_lsm_v(l)%rad_sw_out(m) -          &
5748                                     surf_lsm_v(l)%rad_lw_out(m)
5749
5750        ENDDO
5751     ENDDO
5752!
5753!--  Calculate the average temperature, albedo, and emissivity for urban/land
5754!--  domain when using average_radiation in the respective radiation model
5755
5756!--  calculate horizontal area
5757! !!! ATTENTION!!! uniform grid is assumed here
5758     area_hor = (nx+1) * (ny+1) * dx * dy
5759!
5760!--  absorbed/received SW & LW and emitted LW energy of all physical
5761!--  surfaces (land and urban) in local processor
5762     pinswl = 0._wp
5763     pinlwl = 0._wp
5764     pabsswl = 0._wp
5765     pabslwl = 0._wp
5766     pemitlwl = 0._wp
5767     emiss_sum_surfl = 0._wp
5768     area_surfl = 0._wp
5769     DO  i = 1, nsurfl
5770        d = surfl(id, i)
5771!--  received SW & LW
5772        pinswl = pinswl + (surfinswdir(i) + surfinswdif(i)) * facearea(d)
5773        pinlwl = pinlwl + surfinlwdif(i) * facearea(d)
5774!--   absorbed SW & LW
5775        pabsswl = pabsswl + (1._wp - albedo_surf(i)) *                   &
5776                                                surfinsw(i) * facearea(d)
5777        pabslwl = pabslwl + emiss_surf(i) * surfinlw(i) * facearea(d)
5778!--   emitted LW
5779        pemitlwl = pemitlwl + surfemitlwl(i) * facearea(d)
5780!--   emissivity and area sum
5781        emiss_sum_surfl = emiss_sum_surfl + emiss_surf(i) * facearea(d)
5782        area_surfl = area_surfl + facearea(d)
5783     END DO
5784!
5785!--  add the absorbed SW energy by plant canopy
5786     IF ( npcbl > 0 )  THEN
5787        pabsswl = pabsswl + SUM(pcbinsw)
5788        pabslwl = pabslwl + SUM(pcbinlw)
5789        pinswl = pinswl + SUM(pcbinswdir) + SUM(pcbinswdif)
5790     ENDIF
5791!
5792!--  gather all rad flux energy in all processors
5793#if defined( __parallel )
5794     CALL MPI_ALLREDUCE( pinswl, pinsw, 1, MPI_REAL, MPI_SUM, comm2d, ierr)
5795     IF ( ierr /= 0 ) THEN
5796         WRITE(9,*) 'Error MPI_AllReduce5:', ierr, pinswl, pinsw
5797         FLUSH(9)
5798     ENDIF
5799     CALL MPI_ALLREDUCE( pinlwl, pinlw, 1, MPI_REAL, MPI_SUM, comm2d, ierr)
5800     IF ( ierr /= 0 ) THEN
5801         WRITE(9,*) 'Error MPI_AllReduce6:', ierr, pinlwl, pinlw
5802         FLUSH(9)
5803     ENDIF
5804     CALL MPI_ALLREDUCE( pabsswl, pabssw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5805     IF ( ierr /= 0 ) THEN
5806         WRITE(9,*) 'Error MPI_AllReduce7:', ierr, pabsswl, pabssw
5807         FLUSH(9)
5808     ENDIF
5809     CALL MPI_ALLREDUCE( pabslwl, pabslw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5810     IF ( ierr /= 0 ) THEN
5811         WRITE(9,*) 'Error MPI_AllReduce8:', ierr, pabslwl, pabslw
5812         FLUSH(9)
5813     ENDIF
5814     CALL MPI_ALLREDUCE( pemitlwl, pemitlw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5815     IF ( ierr /= 0 ) THEN
5816         WRITE(9,*) 'Error MPI_AllReduce8:', ierr, pemitlwl, pemitlw
5817         FLUSH(9)
5818     ENDIF
5819     CALL MPI_ALLREDUCE( emiss_sum_surfl, emiss_sum_surf, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5820     IF ( ierr /= 0 ) THEN
5821         WRITE(9,*) 'Error MPI_AllReduce9:', ierr, emiss_sum_surfl, emiss_sum_surf
5822         FLUSH(9)
5823     ENDIF
5824     CALL MPI_ALLREDUCE( area_surfl, area_surf, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5825     IF ( ierr /= 0 ) THEN
5826         WRITE(9,*) 'Error MPI_AllReduce10:', ierr, area_surfl, area_surf
5827         FLUSH(9)
5828     ENDIF
5829#else
5830     pinsw = pinswl
5831     pinlw = pinlwl
5832     pabssw = pabsswl
5833     pabslw = pabslwl
5834     pemitlw = pemitlwl
5835     emiss_sum_surf = emiss_sum_surfl
5836     area_surf = area_surfl
5837#endif
5838
5839!--  (1) albedo
5840     IF ( pinsw /= 0.0_wp )  &
5841          albedo_urb = (pinsw - pabssw) / pinsw
5842!--  (2) average emmsivity
5843     IF ( area_surf /= 0.0_wp ) &
5844          emissivity_urb = emiss_sum_surf / area_surf
5845!
5846!--  Temporally comment out calculation of effective radiative temperature.
5847!--  See below for more explanation.
5848!--  (3) temperature
5849!--   first we calculate an effective horizontal area to account for
5850!--   the effect of vertical surfaces (which contributes to LW emission)
5851!--   We simply use the ratio of the total LW to the incoming LW flux
5852      area_hor = pinlw/rad_lw_in_diff(nyn,nxl)
5853      t_rad_urb = ( (pemitlw - pabslw + emissivity_urb*pinlw) / &
5854           (emissivity_urb*sigma_sb * area_hor) )**0.25_wp
5855
5856     IF ( debug_output )  CALL debug_message( 'radiation_interaction', 'end' )
5857
5858
5859    CONTAINS
5860
5861!------------------------------------------------------------------------------!
5862!> Calculates radiation absorbed by box with given size and LAD.
5863!>
5864!> Simulates resol**2 rays (by equally spacing a bounding horizontal square
5865!> conatining all possible rays that would cross the box) and calculates
5866!> average transparency per ray. Returns fraction of absorbed radiation flux
5867!> and area for which this fraction is effective.
5868!------------------------------------------------------------------------------!
5869    PURE SUBROUTINE box_absorb(boxsize, resol, dens, uvec, area, absorb)
5870       IMPLICIT NONE
5871
5872       REAL(wp), DIMENSION(3), INTENT(in) :: &
5873            boxsize, &      !< z, y, x size of box in m
5874            uvec            !< z, y, x unit vector of incoming flux
5875       INTEGER(iwp), INTENT(in) :: &
5876            resol           !< No. of rays in x and y dimensions
5877       REAL(wp), INTENT(in) :: &
5878            dens            !< box density (e.g. Leaf Area Density)
5879       REAL(wp), INTENT(out) :: &
5880            area, &         !< horizontal area for flux absorbtion
5881            absorb          !< fraction of absorbed flux
5882       REAL(wp) :: &
5883            xshift, yshift, &
5884            xmin, xmax, ymin, ymax, &
5885            xorig, yorig, &
5886            dx1, dy1, dz1, dx2, dy2, dz2, &
5887            crdist, &
5888            transp
5889       INTEGER(iwp) :: &
5890            i, j
5891
5892       xshift = uvec(3) / uvec(1) * boxsize(1)
5893       xmin = min(0._wp, -xshift)
5894       xmax = boxsize(3) + max(0._wp, -xshift)
5895       yshift = uvec(2) / uvec(1) * boxsize(1)
5896       ymin = min(0._wp, -yshift)
5897       ymax = boxsize(2) + max(0._wp, -yshift)
5898
5899       transp = 0._wp
5900       DO i = 1, resol
5901          xorig = xmin + (xmax-xmin) * (i-.5_wp) / resol
5902          DO j = 1, resol
5903             yorig = ymin + (ymax-ymin) * (j-.5_wp) / resol
5904
5905             dz1 = 0._wp
5906             dz2 = boxsize(1)/uvec(1)
5907
5908             IF ( uvec(2) > 0._wp )  THEN
5909                dy1 = -yorig             / uvec(2) !< crossing with y=0
5910                dy2 = (boxsize(2)-yorig) / uvec(2) !< crossing with y=boxsize(2)
5911             ELSE !uvec(2)==0
5912                dy1 = -huge(1._wp)
5913                dy2 = huge(1._wp)
5914             ENDIF
5915
5916             IF ( uvec(3) > 0._wp )  THEN
5917                dx1 = -xorig             / uvec(3) !< crossing with x=0
5918                dx2 = (boxsize(3)-xorig) / uvec(3) !< crossing with x=boxsize(3)
5919             ELSE !uvec(3)==0
5920                dx1 = -huge(1._wp)
5921                dx2 = huge(1._wp)
5922             ENDIF
5923
5924             crdist = max(0._wp, (min(dz2, dy2, dx2) - max(dz1, dy1, dx1)))
5925             transp = transp + exp(-ext_coef * dens * crdist)
5926          ENDDO
5927       ENDDO
5928       transp = transp / resol**2
5929       area = (boxsize(3)+xshift)*(boxsize(2)+yshift)
5930       absorb = 1._wp - transp
5931
5932    END SUBROUTINE box_absorb
5933
5934!------------------------------------------------------------------------------!
5935! Description:
5936! ------------
5937!> This subroutine splits direct and diffusion dw radiation
5938!> It sould not be called in case the radiation model already does it
5939!> It follows Boland, Ridley & Brown (2008)
5940!------------------------------------------------------------------------------!
5941    SUBROUTINE calc_diffusion_radiation 
5942   
5943        REAL(wp), PARAMETER                          :: lowest_solarUp = 0.1_wp  !< limit the sun elevation to protect stability of the calculation
5944        INTEGER(iwp)                                 :: i, j
5945        REAL(wp)                                     ::  year_angle              !< angle
5946        REAL(wp)                                     ::  etr                     !< extraterestrial radiation
5947        REAL(wp)                                     ::  corrected_solarUp       !< corrected solar up radiation
5948        REAL(wp)                                     ::  horizontalETR           !< horizontal extraterestrial radiation
5949        REAL(wp)                                     ::  clearnessIndex          !< clearness index
5950        REAL(wp)                                     ::  diff_frac               !< diffusion fraction of the radiation
5951
5952       
5953!--     Calculate current day and time based on the initial values and simulation time
5954        year_angle = ( (day_of_year_init * 86400) + time_utc_init              &
5955                        + time_since_reference_point )  * d_seconds_year       &
5956                        * 2.0_wp * pi
5957       
5958        etr = solar_constant * (1.00011_wp +                                   &
5959                          0.034221_wp * cos(year_angle) +                      &
5960                          0.001280_wp * sin(year_angle) +                      &
5961                          0.000719_wp * cos(2.0_wp * year_angle) +             &
5962                          0.000077_wp * sin(2.0_wp * year_angle))
5963       
5964!--   
5965!--     Under a very low angle, we keep extraterestrial radiation at
5966!--     the last small value, therefore the clearness index will be pushed
5967!--     towards 0 while keeping full continuity.
5968!--   
5969        IF ( cos_zenith <= lowest_solarUp )  THEN
5970            corrected_solarUp = lowest_solarUp
5971        ELSE
5972            corrected_solarUp = cos_zenith
5973        ENDIF
5974       
5975        horizontalETR = etr * corrected_solarUp
5976       
5977        DO i = nxl, nxr
5978            DO j = nys, nyn
5979                clearnessIndex = rad_sw_in(0,j,i) / horizontalETR
5980                diff_frac = 1.0_wp / (1.0_wp + exp(-5.0033_wp + 8.6025_wp * clearnessIndex))
5981                rad_sw_in_diff(j,i) = rad_sw_in(0,j,i) * diff_frac
5982                rad_sw_in_dir(j,i)  = rad_sw_in(0,j,i) * (1.0_wp - diff_frac)
5983                rad_lw_in_diff(j,i) = rad_lw_in(0,j,i)
5984            ENDDO
5985        ENDDO
5986       
5987    END SUBROUTINE calc_diffusion_radiation
5988
5989 END SUBROUTINE radiation_interaction
5990   
5991!------------------------------------------------------------------------------!
5992! Description:
5993! ------------
5994!> This subroutine initializes structures needed for radiative transfer
5995!> model. This model calculates transformation processes of the
5996!> radiation inside urban and land canopy layer. The module includes also
5997!> the interaction of the radiation with the resolved plant canopy.
5998!>
5999!> For more info. see Resler et al. 2017
6000!>
6001!> The new version 2.0 was radically rewriten, the discretization scheme
6002!> has been changed. This new version significantly improves effectivity
6003!> of the paralelization and the scalability of the model.
6004!>
6005!------------------------------------------------------------------------------!
6006    SUBROUTINE radiation_interaction_init
6007
6008       USE control_parameters,                                                 &
6009           ONLY:  dz_stretch_level_start
6010           
6011       USE netcdf_data_input_mod,                                              &
6012           ONLY:  leaf_area_density_f
6013
6014       USE plant_canopy_model_mod,                                             &
6015           ONLY:  pch_index, lad_s
6016
6017       IMPLICIT NONE
6018
6019       INTEGER(iwp) :: i, j, k, l, m, d
6020       INTEGER(iwp) :: k_topo     !< vertical index indicating topography top for given (j,i)
6021       INTEGER(iwp) :: nzptl, nzubl, nzutl, isurf, ipcgb, imrt
6022       REAL(wp)     :: mrl
6023#if defined( __parallel )
6024       INTEGER(iwp), DIMENSION(:), POINTER, SAVE ::  gridsurf_rma   !< fortran pointer, but lower bounds are 1
6025       TYPE(c_ptr)                               ::  gridsurf_rma_p !< allocated c pointer
6026       INTEGER(iwp)                              ::  minfo          !< MPI RMA window info handle
6027#endif
6028
6029!
6030!--     precalculate face areas for different face directions using normal vector
6031        DO d = 0, nsurf_type
6032            facearea(d) = 1._wp
6033            IF ( idir(d) == 0 ) facearea(d) = facearea(d) * dx
6034            IF ( jdir(d) == 0 ) facearea(d) = facearea(d) * dy
6035            IF ( kdir(d) == 0 ) facearea(d) = facearea(d) * dz(1)
6036        ENDDO
6037!
6038!--    Find nz_urban_b, nz_urban_t, nz_urban via wall_flag_0 array (nzb_s_inner will be
6039!--    removed later). The following contruct finds the lowest / largest index
6040!--    for any upward-facing wall (see bit 12).
6041       nzubl = MINVAL( get_topography_top_index( 's' ) )
6042       nzutl = MAXVAL( get_topography_top_index( 's' ) )
6043
6044       nzubl = MAX( nzubl, nzb )
6045
6046       IF ( plant_canopy )  THEN
6047!--        allocate needed arrays
6048           ALLOCATE( pct(nys:nyn,nxl:nxr) )
6049           ALLOCATE( pch(nys:nyn,nxl:nxr) )
6050
6051!--        calculate plant canopy height
6052           npcbl = 0
6053           pct   = 0
6054           pch   = 0
6055           DO i = nxl, nxr
6056               DO j = nys, nyn
6057!
6058!--                Find topography top index
6059                   k_topo = get_topography_top_index_ji( j, i, 's' )
6060
6061                   DO k = nzt+1, 0, -1
6062                       IF ( lad_s(k,j,i) /= 0.0_wp )  THEN
6063!--                        we are at the top of the pcs
6064                           pct(j,i) = k + k_topo
6065                           pch(j,i) = k
6066                           npcbl = npcbl + pch(j,i)
6067                           EXIT
6068                       ENDIF
6069                   ENDDO
6070               ENDDO
6071           ENDDO
6072
6073           nzutl = MAX( nzutl, MAXVAL( pct ) )
6074           nzptl = MAXVAL( pct )
6075!--        code of plant canopy model uses parameter pch_index
6076!--        we need to setup it here to right value
6077!--        (pch_index, lad_s and other arrays in PCM are defined flat)
6078           pch_index = MERGE( leaf_area_density_f%nz - 1, MAXVAL( pch ),       &
6079                              leaf_area_density_f%from_file )
6080
6081           prototype_lad = MAXVAL( lad_s ) * .9_wp  !< better be *1.0 if lad is either 0 or maxval(lad) everywhere
6082           IF ( prototype_lad <= 0._wp ) prototype_lad = .3_wp
6083           !WRITE(message_string, '(a,f6.3)') 'Precomputing effective box optical ' &
6084           !    // 'depth using prototype leaf area density = ', prototype_lad
6085           !CALL message('radiation_interaction_init', 'PA0520', 0, 0, -1, 6, 0)
6086       ENDIF
6087
6088       nzutl = MIN( nzutl + nzut_free, nzt )
6089
6090#if defined( __parallel )
6091       CALL MPI_AllReduce(nzubl, nz_urban_b, 1, MPI_INTEGER, MPI_MIN, comm2d, ierr )
6092       IF ( ierr /= 0 ) THEN
6093           WRITE(9,*) 'Error MPI_AllReduce11:', ierr, nzubl, nz_urban_b
6094           FLUSH(9)
6095       ENDIF
6096       CALL MPI_AllReduce(nzutl, nz_urban_t, 1, MPI_INTEGER, MPI_MAX, comm2d, ierr )
6097       IF ( ierr /= 0 ) THEN
6098           WRITE(9,*) 'Error MPI_AllReduce12:', ierr, nzutl, nz_urban_t
6099           FLUSH(9)
6100       ENDIF
6101       CALL MPI_AllReduce(nzptl, nz_plant_t, 1, MPI_INTEGER, MPI_MAX, comm2d, ierr )
6102       IF ( ierr /= 0 ) THEN
6103           WRITE(9,*) 'Error MPI_AllReduce13:', ierr, nzptl, nz_plant_t
6104           FLUSH(9)
6105       ENDIF
6106#else
6107       nz_urban_b = nzubl
6108       nz_urban_t = nzutl
6109       nz_plant_t = nzptl
6110#endif
6111!
6112!--    Stretching (non-uniform grid spacing) is not considered in the radiation
6113!--    model. Therefore, vertical stretching has to be applied above the area
6114!--    where the parts of the radiation model which assume constant grid spacing
6115!--    are active. ABS (...) is required because the default value of
6116!--    dz_stretch_level_start is -9999999.9_wp (negative).
6117       IF ( ABS( dz_stretch_level_start(1) ) <= zw(nz_urban_t) ) THEN
6118          WRITE( message_string, * ) 'The lowest level where vertical ',       &
6119                                     'stretching is applied have to be ',      &
6120                                     'greater than ', zw(nz_urban_t)
6121          CALL message( 'radiation_interaction_init', 'PA0496', 1, 2, 0, 6, 0 )
6122       ENDIF 
6123!
6124!--    global number of urban and plant layers
6125       nz_urban = nz_urban_t - nz_urban_b + 1
6126       nz_plant = nz_plant_t - nz_urban_b + 1
6127!
6128!--    check max_raytracing_dist relative to urban surface layer height
6129       mrl = 2.0_wp * nz_urban * dz(1)
6130!--    set max_raytracing_dist to double the urban surface layer height, if not set
6131       IF ( max_raytracing_dist == -999.0_wp ) THEN
6132          max_raytracing_dist = mrl
6133       ENDIF
6134!--    check if max_raytracing_dist set too low (here we only warn the user. Other
6135!      option is to correct the value again to double the urban surface layer height)
6136       IF ( max_raytracing_dist  <  mrl ) THEN
6137          WRITE(message_string, '(a,f6.1)') 'Max_raytracing_dist is set less than ', &
6138               'double the urban surface layer height, i.e. ', mrl
6139          CALL message('radiation_interaction_init', 'PA0521', 0, 0, -1, 6, 0)
6140       ENDIF
6141!        IF ( max_raytracing_dist <= mrl ) THEN
6142!           IF ( max_raytracing_dist /= -999.0_wp ) THEN
6143! !--          max_raytracing_dist too low
6144!              WRITE(message_string, '(a,f6.1)') 'Max_raytracing_dist too low, ' &
6145!                    // 'override to value ', mrl
6146!              CALL message('radiation_interaction_init', 'PA0521', 0, 0, -1, 6, 0)
6147!           ENDIF
6148!           max_raytracing_dist = mrl
6149!        ENDIF
6150!
6151!--    allocate urban surfaces grid
6152!--    calc number of surfaces in local proc
6153       IF ( debug_output )  CALL debug_message( 'calculation of indices for surfaces', 'info' )
6154
6155       nsurfl = 0
6156!
6157!--    Number of horizontal surfaces including land- and roof surfaces in both USM and LSM. Note that
6158!--    All horizontal surface elements are already counted in surface_mod.
6159       startland = 1
6160       nsurfl    = surf_usm_h%ns + surf_lsm_h%ns
6161       endland   = nsurfl
6162       nlands    = endland - startland + 1
6163
6164!
6165!--    Number of vertical surfaces in both USM and LSM. Note that all vertical surface elements are
6166!--    already counted in surface_mod.
6167       startwall = nsurfl+1
6168       DO  i = 0,3
6169          nsurfl = nsurfl + surf_usm_v(i)%ns + surf_lsm_v(i)%ns
6170       ENDDO
6171       endwall = nsurfl
6172       nwalls  = endwall - startwall + 1
6173       dirstart = (/ startland, startwall, startwall, startwall, startwall /)
6174       dirend = (/ endland, endwall, endwall, endwall, endwall /)
6175
6176!--    fill gridpcbl and pcbl
6177       IF ( npcbl > 0 )  THEN
6178           ALLOCATE( pcbl(iz:ix, 1:npcbl) )
6179           ALLOCATE( gridpcbl(nz_urban_b:nz_plant_t,nys:nyn,nxl:nxr) )
6180           pcbl = -1
6181           gridpcbl(:,:,:) = 0
6182           ipcgb = 0
6183           DO i = nxl, nxr
6184               DO j = nys, nyn
6185!
6186!--                Find topography top index
6187                   k_topo = get_topography_top_index_ji( j, i, 's' )
6188
6189                   DO k = k_topo + 1, pct(j,i)
6190                       ipcgb = ipcgb + 1
6191                       gridpcbl(k,j,i) = ipcgb
6192                       pcbl(:,ipcgb) = (/ k, j, i /)
6193                   ENDDO
6194               ENDDO
6195           ENDDO
6196           ALLOCATE( pcbinsw( 1:npcbl ) )
6197           ALLOCATE( pcbinswdir( 1:npcbl ) )
6198           ALLOCATE( pcbinswdif( 1:npcbl ) )
6199           ALLOCATE( pcbinlw( 1:npcbl ) )
6200       ENDIF
6201
6202!
6203!--    Fill surfl (the ordering of local surfaces given by the following
6204!--    cycles must not be altered, certain file input routines may depend
6205!--    on it).
6206!
6207!--    We allocate the array as linear and then use a two-dimensional pointer
6208!--    into it, because some MPI implementations crash with 2D-allocated arrays.
6209       ALLOCATE(surfl_linear(nidx_surf*nsurfl))
6210       surfl(1:nidx_surf,1:nsurfl) => surfl_linear(1:nidx_surf*nsurfl)
6211       isurf = 0
6212       IF ( rad_angular_discretization )  THEN
6213!
6214!--       Allocate and fill the reverse indexing array gridsurf
6215#if defined( __parallel )
6216!
6217!--       raytrace_mpi_rma is asserted
6218
6219          CALL MPI_Info_create(minfo, ierr)
6220          IF ( ierr /= 0 ) THEN
6221              WRITE(9,*) 'Error MPI_Info_create1:', ierr
6222              FLUSH(9)
6223          ENDIF
6224          CALL MPI_Info_set(minfo, 'accumulate_ordering', '', ierr)
6225          IF ( ierr /= 0 ) THEN
6226              WRITE(9,*) 'Error MPI_Info_set1:', ierr
6227              FLUSH(9)
6228          ENDIF
6229          CALL MPI_Info_set(minfo, 'accumulate_ops', 'same_op', ierr)
6230          IF ( ierr /= 0 ) THEN
6231              WRITE(9,*) 'Error MPI_Info_set2:', ierr
6232              FLUSH(9)
6233          ENDIF
6234          CALL MPI_Info_set(minfo, 'same_size', 'true', ierr)
6235          IF ( ierr /= 0 ) THEN
6236              WRITE(9,*) 'Error MPI_Info_set3:', ierr
6237              FLUSH(9)
6238          ENDIF
6239          CALL MPI_Info_set(minfo, 'same_disp_unit', 'true', ierr)
6240          IF ( ierr /= 0 ) THEN
6241              WRITE(9,*) 'Error MPI_Info_set4:', ierr
6242              FLUSH(9)
6243          ENDIF
6244
6245          CALL MPI_Win_allocate(INT(STORAGE_SIZE(1_iwp)/8*nsurf_type_u*nz_urban*nny*nnx, &
6246                                    kind=MPI_ADDRESS_KIND), STORAGE_SIZE(1_iwp)/8,  &
6247                                minfo, comm2d, gridsurf_rma_p, win_gridsurf, ierr)
6248          IF ( ierr /= 0 ) THEN
6249              WRITE(9,*) 'Error MPI_Win_allocate1:', ierr, &
6250                 INT(STORAGE_SIZE(1_iwp)/8*nsurf_type_u*nz_urban*nny*nnx,kind=MPI_ADDRESS_KIND), &
6251                 STORAGE_SIZE(1_iwp)/8, win_gridsurf
6252              FLUSH(9)
6253          ENDIF
6254
6255          CALL MPI_Info_free(minfo, ierr)
6256          IF ( ierr /= 0 ) THEN
6257              WRITE(9,*) 'Error MPI_Info_free1:', ierr
6258              FLUSH(9)
6259          ENDIF
6260
6261!
6262!--       On Intel compilers, calling c_f_pointer to transform a C pointer
6263!--       directly to a multi-dimensional Fotran pointer leads to strange
6264!--       errors on dimension boundaries. However, transforming to a 1D
6265!--       pointer and then redirecting a multidimensional pointer to it works
6266!--       fine.
6267          CALL c_f_pointer(gridsurf_rma_p, gridsurf_rma, (/ nsurf_type_u*nz_urban*nny*nnx /))
6268          gridsurf(0:nsurf_type_u-1, nz_urban_b:nz_urban_t, nys:nyn, nxl:nxr) =>                &
6269                     gridsurf_rma(1:nsurf_type_u*nz_urban*nny*nnx)
6270#else
6271          ALLOCATE(gridsurf(0:nsurf_type_u-1,nz_urban_b:nz_urban_t,nys:nyn,nxl:nxr) )
6272#endif
6273          gridsurf(:,:,:,:) = -999
6274       ENDIF
6275
6276!--    add horizontal surface elements (land and urban surfaces)
6277!--    TODO: add urban overhanging surfaces (idown_u)
6278       DO i = nxl, nxr
6279           DO j = nys, nyn
6280              DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
6281                 k = surf_usm_h%k(m)
6282                 isurf = isurf + 1
6283                 surfl(:,isurf) = (/iup_u,k,j,i,m/)
6284                 IF ( rad_angular_discretization ) THEN
6285                    gridsurf(iup_u,k,j,i) = isurf
6286                 ENDIF
6287              ENDDO
6288
6289              DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6290                 k = surf_lsm_h%k(m)
6291                 isurf = isurf + 1
6292                 surfl(:,isurf) = (/iup_l,k,j,i,m/)
6293                 IF ( rad_angular_discretization ) THEN
6294                    gridsurf(iup_u,k,j,i) = isurf
6295                 ENDIF
6296              ENDDO
6297
6298           ENDDO
6299       ENDDO
6300
6301!--    add vertical surface elements (land and urban surfaces)
6302!--    TODO: remove the hard coding of l = 0 to l = idirection
6303       DO i = nxl, nxr
6304           DO j = nys, nyn
6305              l = 0
6306              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6307                 k = surf_usm_v(l)%k(m)
6308                 isurf = isurf + 1
6309                 surfl(:,isurf) = (/inorth_u,k,j,i,m/)
6310                 IF ( rad_angular_discretization ) THEN
6311                    gridsurf(inorth_u,k,j,i) = isurf
6312                 ENDIF
6313              ENDDO
6314              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6315                 k = surf_lsm_v(l)%k(m)
6316                 isurf = isurf + 1
6317                 surfl(:,isurf) = (/inorth_l,k,j,i,m/)
6318                 IF ( rad_angular_discretization ) THEN
6319                    gridsurf(inorth_u,k,j,i) = isurf
6320                 ENDIF
6321              ENDDO
6322
6323              l = 1
6324              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6325                 k = surf_usm_v(l)%k(m)
6326                 isurf = isurf + 1
6327                 surfl(:,isurf) = (/isouth_u,k,j,i,m/)
6328                 IF ( rad_angular_discretization ) THEN
6329                    gridsurf(isouth_u,k,j,i) = isurf
6330                 ENDIF
6331              ENDDO
6332              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6333                 k = surf_lsm_v(l)%k(m)
6334                 isurf = isurf + 1
6335                 surfl(:,isurf) = (/isouth_l,k,j,i,m/)
6336                 IF ( rad_angular_discretization ) THEN
6337                    gridsurf(isouth_u,k,j,i) = isurf
6338                 ENDIF
6339              ENDDO
6340
6341              l = 2
6342              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6343                 k = surf_usm_v(l)%k(m)
6344                 isurf = isurf + 1
6345                 surfl(:,isurf) = (/ieast_u,k,j,i,m/)
6346                 IF ( rad_angular_discretization ) THEN
6347                    gridsurf(ieast_u,k,j,i) = isurf
6348                 ENDIF
6349              ENDDO
6350              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6351                 k = surf_lsm_v(l)%k(m)
6352                 isurf = isurf + 1
6353                 surfl(:,isurf) = (/ieast_l,k,j,i,m/)
6354                 IF ( rad_angular_discretization ) THEN
6355                    gridsurf(ieast_u,k,j,i) = isurf
6356                 ENDIF
6357              ENDDO
6358
6359              l = 3
6360              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6361                 k = surf_usm_v(l)%k(m)
6362                 isurf = isurf + 1
6363                 surfl(:,isurf) = (/iwest_u,k,j,i,m/)
6364                 IF ( rad_angular_discretization ) THEN
6365                    gridsurf(iwest_u,k,j,i) = isurf
6366                 ENDIF
6367              ENDDO
6368              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6369                 k = surf_lsm_v(l)%k(m)
6370                 isurf = isurf + 1
6371                 surfl(:,isurf) = (/iwest_l,k,j,i,m/)
6372                 IF ( rad_angular_discretization ) THEN
6373                    gridsurf(iwest_u,k,j,i) = isurf
6374                 ENDIF
6375              ENDDO
6376           ENDDO
6377       ENDDO
6378!
6379!--    Add local MRT boxes for specified number of levels
6380       nmrtbl = 0
6381       IF ( mrt_nlevels > 0 )  THEN
6382          DO  i = nxl, nxr
6383             DO  j = nys, nyn
6384                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
6385!
6386!--                Skip roof if requested
6387                   IF ( mrt_skip_roof  .AND.  surf_usm_h%isroof_surf(m) )  CYCLE
6388!
6389!--                Cycle over specified no of levels
6390                   nmrtbl = nmrtbl + mrt_nlevels
6391                ENDDO
6392!
6393!--             Dtto for LSM
6394                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6395                   nmrtbl = nmrtbl + mrt_nlevels
6396                ENDDO
6397             ENDDO
6398          ENDDO
6399
6400          ALLOCATE( mrtbl(iz:ix,nmrtbl), mrtsky(nmrtbl), mrtskyt(nmrtbl), &
6401                    mrtinsw(nmrtbl), mrtinlw(nmrtbl), mrt(nmrtbl) )
6402
6403          imrt = 0
6404          DO  i = nxl, nxr
6405             DO  j = nys, nyn
6406                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
6407!
6408!--                Skip roof if requested
6409                   IF ( mrt_skip_roof  .AND.  surf_usm_h%isroof_surf(m) )  CYCLE
6410!
6411!--                Cycle over specified no of levels
6412                   l = surf_usm_h%k(m)
6413                   DO  k = l, l + mrt_nlevels - 1
6414                      imrt = imrt + 1
6415                      mrtbl(:,imrt) = (/k,j,i/)
6416                   ENDDO
6417                ENDDO
6418!
6419!--             Dtto for LSM
6420                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6421                   l = surf_lsm_h%k(m)
6422                   DO  k = l, l + mrt_nlevels - 1
6423                      imrt = imrt + 1
6424                      mrtbl(:,imrt) = (/k,j,i/)
6425                   ENDDO
6426                ENDDO
6427             ENDDO
6428          ENDDO
6429       ENDIF
6430
6431!
6432!--    broadband albedo of the land, roof and wall surface
6433!--    for domain border and sky set artifically to 1.0
6434!--    what allows us to calculate heat flux leaving over
6435!--    side and top borders of the domain
6436       ALLOCATE ( albedo_surf(nsurfl) )
6437       albedo_surf = 1.0_wp
6438!
6439!--    Also allocate further array for emissivity with identical order of
6440!--    surface elements as radiation arrays.
6441       ALLOCATE ( emiss_surf(nsurfl)  )
6442
6443
6444!
6445!--    global array surf of indices of surfaces and displacement index array surfstart
6446       ALLOCATE(nsurfs(0:numprocs-1))
6447
6448#if defined( __parallel )
6449       CALL MPI_Allgather(nsurfl,1,MPI_INTEGER,nsurfs,1,MPI_INTEGER,comm2d,ierr)
6450       IF ( ierr /= 0 ) THEN
6451         WRITE(9,*) 'Error MPI_AllGather1:', ierr, nsurfl, nsurfs
6452         FLUSH(9)
6453     ENDIF
6454
6455#else
6456       nsurfs(0) = nsurfl
6457#endif
6458       ALLOCATE(surfstart(0:numprocs))
6459       k = 0
6460       DO i=0,numprocs-1
6461           surfstart(i) = k
6462           k = k+nsurfs(i)
6463       ENDDO
6464       surfstart(numprocs) = k
6465       nsurf = k
6466!
6467!--    We allocate the array as linear and then use a two-dimensional pointer
6468!--    into it, because some MPI implementations crash with 2D-allocated arrays.
6469       ALLOCATE(surf_linear(nidx_surf*nsurf))
6470       surf(1:nidx_surf,1:nsurf) => surf_linear(1:nidx_surf*nsurf)
6471
6472#if defined( __parallel )
6473       CALL MPI_AllGatherv(surfl_linear, nsurfl*nidx_surf, MPI_INTEGER,    &
6474                           surf_linear, nsurfs*nidx_surf,                  &
6475                           surfstart(0:numprocs-1)*nidx_surf, MPI_INTEGER, &
6476                           comm2d, ierr)
6477       IF ( ierr /= 0 ) THEN
6478           WRITE(9,*) 'Error MPI_AllGatherv4:', ierr, SIZE(surfl_linear),    &
6479                      nsurfl*nidx_surf, SIZE(surf_linear), nsurfs*nidx_surf, &
6480                      surfstart(0:numprocs-1)*nidx_surf
6481           FLUSH(9)
6482       ENDIF
6483#else
6484       surf = surfl
6485#endif
6486
6487!--
6488!--    allocation of the arrays for direct and diffusion radiation
6489       IF ( debug_output )  CALL debug_message( 'allocation of radiation arrays', 'info' )
6490!--    rad_sw_in, rad_lw_in are computed in radiation model,
6491!--    splitting of direct and diffusion part is done
6492!--    in calc_diffusion_radiation for now
6493
6494       ALLOCATE( rad_sw_in_dir(nysg:nyng,nxlg:nxrg) )
6495       ALLOCATE( rad_sw_in_diff(nysg:nyng,nxlg:nxrg) )
6496       ALLOCATE( rad_lw_in_diff(nysg:nyng,nxlg:nxrg) )
6497       rad_sw_in_dir  = 0.0_wp
6498       rad_sw_in_diff = 0.0_wp
6499       rad_lw_in_diff = 0.0_wp
6500
6501!--    allocate radiation arrays
6502       ALLOCATE( surfins(nsurfl) )
6503       ALLOCATE( surfinl(nsurfl) )
6504       ALLOCATE( surfinsw(nsurfl) )
6505       ALLOCATE( surfinlw(nsurfl) )
6506       ALLOCATE( surfinswdir(nsurfl) )
6507       ALLOCATE( surfinswdif(nsurfl) )
6508       ALLOCATE( surfinlwdif(nsurfl) )
6509       ALLOCATE( surfoutsl(nsurfl) )
6510       ALLOCATE( surfoutll(nsurfl) )
6511       ALLOCATE( surfoutsw(nsurfl) )
6512       ALLOCATE( surfoutlw(nsurfl) )
6513       ALLOCATE( surfouts(nsurf) )
6514       ALLOCATE( surfoutl(nsurf) )
6515       ALLOCATE( surfinlg(nsurf) )
6516       ALLOCATE( skyvf(nsurfl) )
6517       ALLOCATE( skyvft(nsurfl) )
6518       ALLOCATE( surfemitlwl(nsurfl) )
6519
6520!
6521!--    In case of average_radiation, aggregated surface albedo and emissivity,
6522!--    also set initial value for t_rad_urb.
6523!--    For now set an arbitrary initial value.
6524       IF ( average_radiation )  THEN
6525          albedo_urb = 0.1_wp
6526          emissivity_urb = 0.9_wp
6527          t_rad_urb = pt_surface
6528       ENDIF
6529
6530    END SUBROUTINE radiation_interaction_init
6531
6532!------------------------------------------------------------------------------!
6533! Description:
6534! ------------
6535!> Calculates shape view factors (SVF), plant sink canopy factors (PCSF),
6536!> sky-view factors, discretized path for direct solar radiation, MRT factors
6537!> and other preprocessed data needed for radiation_interaction.
6538!------------------------------------------------------------------------------!
6539    SUBROUTINE radiation_calc_svf
6540   
6541        IMPLICIT NONE
6542       
6543        INTEGER(iwp)                                  :: i, j, k, d, ip, jp
6544        INTEGER(iwp)                                  :: isvf, ksvf, icsf, kcsf, npcsfl, isvf_surflt, imrt, imrtf, ipcgb
6545        INTEGER(iwp)                                  :: sd, td
6546        INTEGER(iwp)                                  :: iaz, izn      !< azimuth, zenith counters
6547        INTEGER(iwp)                                  :: naz, nzn      !< azimuth, zenith num of steps
6548        REAL(wp)                                      :: az0, zn0      !< starting azimuth/zenith
6549        REAL(wp)                                      :: azs, zns      !< azimuth/zenith cycle step
6550        REAL(wp)                                      :: az1, az2      !< relative azimuth of section borders
6551        REAL(wp)                                      :: azmid         !< ray (center) azimuth
6552        REAL(wp)                                      :: yxlen         !< |yxdir|
6553        REAL(wp), DIMENSION(2)                        :: yxdir         !< y,x *unit* vector of ray direction (in grid units)
6554        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zdirs         !< directions in z (tangent of elevation)
6555        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zcent         !< zenith angle centers
6556        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zbdry         !< zenith angle boundaries
6557        REAL(wp), DIMENSION(:), ALLOCATABLE           :: vffrac        !< view factor fractions for individual rays
6558        REAL(wp), DIMENSION(:), ALLOCATABLE           :: vffrac0       !< dtto (original values)
6559        REAL(wp), DIMENSION(:), ALLOCATABLE           :: ztransp       !< array of transparency in z steps
6560        INTEGER(iwp)                                  :: lowest_free_ray !< index into zdirs
6561        INTEGER(iwp), DIMENSION(:), ALLOCATABLE       :: itarget       !< face indices of detected obstacles
6562        INTEGER(iwp)                                  :: itarg0, itarg1
6563
6564        INTEGER(iwp)                                  :: udim
6565        INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET:: nzterrl_l
6566        INTEGER(iwp), DIMENSION(:,:), POINTER         :: nzterrl
6567        REAL(wp),     DIMENSION(:), ALLOCATABLE,TARGET:: csflt_l, pcsflt_l
6568        REAL(wp),     DIMENSION(:,:), POINTER         :: csflt, pcsflt
6569        INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET:: kcsflt_l,kpcsflt_l
6570        INTEGER(iwp), DIMENSION(:,:), POINTER         :: kcsflt,kpcsflt
6571        INTEGER(iwp), DIMENSION(:), ALLOCATABLE       :: icsflt,dcsflt,ipcsflt,dpcsflt
6572        REAL(wp), DIMENSION(3)                        :: uv
6573        LOGICAL                                       :: visible
6574        REAL(wp), DIMENSION(3)                        :: sa, ta          !< real coordinates z,y,x of source and target
6575        REAL(wp)                                      :: difvf           !< differential view factor
6576        REAL(wp)                                      :: transparency, rirrf, sqdist, svfsum
6577        INTEGER(iwp)                                  :: isurflt, isurfs, isurflt_prev
6578        INTEGER(idp)                                  :: ray_skip_maxdist, ray_skip_minval !< skipped raytracing counts
6579        INTEGER(iwp)                                  :: max_track_len !< maximum 2d track length
6580        INTEGER(iwp)                                  :: minfo
6581        REAL(wp), DIMENSION(:), POINTER, SAVE         :: lad_s_rma       !< fortran 1D pointer
6582        TYPE(c_ptr)                                   :: lad_s_rma_p     !< allocated c pointer
6583#if defined( __parallel )
6584        INTEGER(kind=MPI_ADDRESS_KIND)                :: size_lad_rma
6585#endif
6586!   
6587        INTEGER(iwp), DIMENSION(0:svfnorm_report_num) :: svfnorm_counts
6588
6589
6590!--     calculation of the SVF
6591        CALL location_message( 'calculating view factors for radiation interaction', 'start' )
6592
6593!--     initialize variables and temporary arrays for calculation of svf and csf
6594        nsvfl  = 0
6595        ncsfl  = 0
6596        nsvfla = gasize
6597        msvf   = 1
6598        ALLOCATE( asvf1(nsvfla) )
6599        asvf => asvf1
6600        IF ( plant_canopy )  THEN
6601            ncsfla = gasize
6602            mcsf   = 1
6603            ALLOCATE( acsf1(ncsfla) )
6604            acsf => acsf1
6605        ENDIF
6606        nmrtf = 0
6607        IF ( mrt_nlevels > 0 )  THEN
6608           nmrtfa = gasize
6609           mmrtf = 1
6610           ALLOCATE ( amrtf1(nmrtfa) )
6611           amrtf => amrtf1
6612        ENDIF
6613        ray_skip_maxdist = 0
6614        ray_skip_minval = 0
6615       
6616!--     initialize temporary terrain and plant canopy height arrays (global 2D array!)
6617        ALLOCATE( nzterr(0:(nx+1)*(ny+1)-1) )
6618#if defined( __parallel )
6619        !ALLOCATE( nzterrl(nys:nyn,nxl:nxr) )
6620        ALLOCATE( nzterrl_l((nyn-nys+1)*(nxr-nxl+1)) )
6621        nzterrl(nys:nyn,nxl:nxr) => nzterrl_l(1:(nyn-nys+1)*(nxr-nxl+1))
6622        nzterrl = get_topography_top_index( 's' )
6623        CALL MPI_AllGather( nzterrl_l, nnx*nny, MPI_INTEGER, &
6624                            nzterr, nnx*nny, MPI_INTEGER, comm2d, ierr )
6625        IF ( ierr /= 0 ) THEN
6626            WRITE(9,*) 'Error MPI_AllGather1:', ierr, SIZE(nzterrl_l), nnx*nny, &
6627                       SIZE(nzterr), nnx*nny
6628            FLUSH(9)
6629        ENDIF
6630        DEALLOCATE(nzterrl_l)
6631#else
6632        nzterr = RESHAPE( get_topography_top_index( 's' ), (/(nx+1)*(ny+1)/) )
6633#endif
6634        IF ( plant_canopy )  THEN
6635            ALLOCATE( plantt(0:(nx+1)*(ny+1)-1) )
6636            maxboxesg = nx + ny + nz_plant + 1
6637            max_track_len = nx + ny + 1
6638!--         temporary arrays storing values for csf calculation during raytracing
6639            ALLOCATE( boxes(3, maxboxesg) )
6640            ALLOCATE( crlens(maxboxesg) )
6641
6642#if defined( __parallel )
6643            CALL MPI_AllGather( pct, nnx*nny, MPI_INTEGER, &
6644                                plantt, nnx*nny, MPI_INTEGER, comm2d, ierr )
6645            IF ( ierr /= 0 ) THEN
6646                WRITE(9,*) 'Error MPI_AllGather2:', ierr, SIZE(pct), nnx*nny, &
6647                           SIZE(plantt), nnx*nny
6648                FLUSH(9)
6649            ENDIF
6650
6651!--         temporary arrays storing values for csf calculation during raytracing
6652            ALLOCATE( lad_ip(maxboxesg) )
6653            ALLOCATE( lad_disp(maxboxesg) )
6654
6655            IF ( raytrace_mpi_rma )  THEN
6656                ALLOCATE( lad_s_ray(maxboxesg) )
6657               
6658                ! set conditions for RMA communication
6659                CALL MPI_Info_create(minfo, ierr)
6660                IF ( ierr /= 0 ) THEN
6661                    WRITE(9,*) 'Error MPI_Info_create2:', ierr
6662                    FLUSH(9)
6663                ENDIF
6664                CALL MPI_Info_set(minfo, 'accumulate_ordering', '', ierr)
6665                IF ( ierr /= 0 ) THEN
6666                    WRITE(9,*) 'Error MPI_Info_set5:', ierr
6667                    FLUSH(9)
6668                ENDIF
6669                CALL MPI_Info_set(minfo, 'accumulate_ops', 'same_op', ierr)
6670                IF ( ierr /= 0 ) THEN
6671                    WRITE(9,*) 'Error MPI_Info_set6:', ierr
6672                    FLUSH(9)
6673                ENDIF
6674                CALL MPI_Info_set(minfo, 'same_size', 'true', ierr)
6675                IF ( ierr /= 0 ) THEN
6676                    WRITE(9,*) 'Error MPI_Info_set7:', ierr
6677                    FLUSH(9)
6678                ENDIF
6679                CALL MPI_Info_set(minfo, 'same_disp_unit', 'true', ierr)
6680                IF ( ierr /= 0 ) THEN
6681                    WRITE(9,*) 'Error MPI_Info_set8:', ierr
6682                    FLUSH(9)
6683                ENDIF
6684
6685!--             Allocate and initialize the MPI RMA window
6686!--             must be in accordance with allocation of lad_s in plant_canopy_model
6687!--             optimization of memory should be done
6688!--             Argument X of function STORAGE_SIZE(X) needs arbitrary REAL(wp) value, set to 1.0_wp for now
6689                size_lad_rma = STORAGE_SIZE(1.0_wp)/8*nnx*nny*nz_plant
6690                CALL MPI_Win_allocate(size_lad_rma, STORAGE_SIZE(1.0_wp)/8, minfo, comm2d, &
6691                                        lad_s_rma_p, win_lad, ierr)
6692                IF ( ierr /= 0 ) THEN
6693                    WRITE(9,*) 'Error MPI_Win_allocate2:', ierr, size_lad_rma, &
6694                                STORAGE_SIZE(1.0_wp)/8, win_lad
6695                    FLUSH(9)
6696                ENDIF
6697                CALL c_f_pointer(lad_s_rma_p, lad_s_rma, (/ nz_plant*nny*nnx /))
6698                sub_lad(nz_urban_b:nz_plant_t, nys:nyn, nxl:nxr) => lad_s_rma(1:nz_plant*nny*nnx)
6699            ELSE
6700                ALLOCATE(sub_lad(nz_urban_b:nz_plant_t, nys:nyn, nxl:nxr))
6701            ENDIF
6702#else
6703            plantt = RESHAPE( pct(nys:nyn,nxl:nxr), (/(nx+1)*(ny+1)/) )
6704            ALLOCATE(sub_lad(nz_urban_b:nz_plant_t, nys:nyn, nxl:nxr))
6705#endif
6706            plantt_max = MAXVAL(plantt)
6707            ALLOCATE( rt2_track(2, max_track_len), rt2_track_lad(nz_urban_b:plantt_max, max_track_len), &
6708                      rt2_track_dist(0:max_track_len), rt2_dist(plantt_max-nz_urban_b+2) )
6709
6710            sub_lad(:,:,:) = 0._wp
6711            DO i = nxl, nxr
6712                DO j = nys, nyn
6713                    k = get_topography_top_index_ji( j, i, 's' )
6714
6715                    sub_lad(k:nz_plant_t, j, i) = lad_s(0:nz_plant_t-k, j, i)
6716                ENDDO
6717            ENDDO
6718
6719#if defined( __parallel )
6720            IF ( raytrace_mpi_rma )  THEN
6721                CALL MPI_Info_free(minfo, ierr)
6722                IF ( ierr /= 0 ) THEN
6723                    WRITE(9,*) 'Error MPI_Info_free2:', ierr
6724                    FLUSH(9)
6725                ENDIF
6726                CALL MPI_Win_lock_all(0, win_lad, ierr)
6727                IF ( ierr /= 0 ) THEN
6728                    WRITE(9,*) 'Error MPI_Win_lock_all1:', ierr, win_lad
6729                    FLUSH(9)
6730                ENDIF
6731               
6732            ELSE
6733                ALLOCATE( sub_lad_g(0:(nx+1)*(ny+1)*nz_plant-1) )
6734                CALL MPI_AllGather( sub_lad, nnx*nny*nz_plant, MPI_REAL, &
6735                                    sub_lad_g, nnx*nny*nz_plant, MPI_REAL, comm2d, ierr )
6736                IF ( ierr /= 0 ) THEN
6737                    WRITE(9,*) 'Error MPI_AllGather3:', ierr, SIZE(sub_lad), &
6738                                nnx*nny*nz_plant, SIZE(sub_lad_g), nnx*nny*nz_plant
6739                    FLUSH(9)
6740                ENDIF
6741            ENDIF
6742#endif
6743        ENDIF
6744
6745!--     prepare the MPI_Win for collecting the surface indices
6746!--     from the reverse index arrays gridsurf from processors of target surfaces
6747#if defined( __parallel )
6748        IF ( rad_angular_discretization )  THEN
6749!
6750!--         raytrace_mpi_rma is asserted
6751            CALL MPI_Win_lock_all(0, win_gridsurf, ierr)
6752            IF ( ierr /= 0 ) THEN
6753                WRITE(9,*) 'Error MPI_Win_lock_all2:', ierr, win_gridsurf
6754                FLUSH(9)
6755            ENDIF
6756        ENDIF
6757#endif
6758
6759
6760        !--Directions opposite to face normals are not even calculated,
6761        !--they must be preset to 0
6762        !--
6763        dsitrans(:,:) = 0._wp
6764       
6765        DO isurflt = 1, nsurfl
6766!--         determine face centers
6767            td = surfl(id, isurflt)
6768            ta = (/ REAL(surfl(iz, isurflt), wp) - 0.5_wp * kdir(td),  &
6769                      REAL(surfl(iy, isurflt), wp) - 0.5_wp * jdir(td),  &
6770                      REAL(surfl(ix, isurflt), wp) - 0.5_wp * idir(td)  /)
6771
6772            !--Calculate sky view factor and raytrace DSI paths
6773            skyvf(isurflt) = 0._wp
6774            skyvft(isurflt) = 0._wp
6775
6776            !--Select a proper half-sphere for 2D raytracing
6777            SELECT CASE ( td )
6778               CASE ( iup_u, iup_l )
6779                  az0 = 0._wp
6780                  naz = raytrace_discrete_azims
6781                  azs = 2._wp * pi / REAL(naz, wp)
6782                  zn0 = 0._wp
6783                  nzn = raytrace_discrete_elevs / 2
6784                  zns = pi / 2._wp / REAL(nzn, wp)
6785               CASE ( isouth_u, isouth_l )
6786                  az0 = pi / 2._wp
6787                  naz = raytrace_discrete_azims / 2
6788                  azs = pi / REAL(naz, wp)
6789                  zn0 = 0._wp
6790                  nzn = raytrace_discrete_elevs
6791                  zns = pi / REAL(nzn, wp)
6792               CASE ( inorth_u, inorth_l )
6793                  az0 = - pi / 2._wp
6794                  naz = raytrace_discrete_azims / 2
6795                  azs = pi / REAL(naz, wp)
6796                  zn0 = 0._wp
6797                  nzn = raytrace_discrete_elevs
6798                  zns = pi / REAL(nzn, wp)
6799               CASE ( iwest_u, iwest_l )
6800                  az0 = pi
6801                  naz = raytrace_discrete_azims / 2
6802                  azs = pi / REAL(naz, wp)
6803                  zn0 = 0._wp
6804                  nzn = raytrace_discrete_elevs
6805                  zns = pi / REAL(nzn, wp)
6806               CASE ( ieast_u, ieast_l )
6807                  az0 = 0._wp
6808                  naz = raytrace_discrete_azims / 2
6809                  azs = pi / REAL(naz, wp)
6810                  zn0 = 0._wp
6811                  nzn = raytrace_discrete_elevs
6812                  zns = pi / REAL(nzn, wp)
6813               CASE DEFAULT
6814                  WRITE(message_string, *) 'ERROR: the surface type ', td,     &
6815                                           ' is not supported for calculating',&
6816                                           ' SVF'
6817                  CALL message( 'radiation_calc_svf', 'PA0488', 1, 2, 0, 6, 0 )
6818            END SELECT
6819
6820            ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), zbdry(0:nzn), vffrac(1:nzn*naz), &
6821                       ztransp(1:nzn*naz), itarget(1:nzn*naz) )   !FIXME allocate itarget only
6822                                                                  !in case of rad_angular_discretization
6823
6824            itarg0 = 1
6825            itarg1 = nzn
6826            zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
6827            zbdry(:) = (/( zn0+REAL(izn,wp)*zns, izn=0, nzn )/)
6828            IF ( td == iup_u  .OR.  td == iup_l )  THEN
6829               vffrac(1:nzn) = (COS(2 * zbdry(0:nzn-1)) - COS(2 * zbdry(1:nzn))) / 2._wp / REAL(naz, wp)
6830!
6831!--            For horizontal target, vf fractions are constant per azimuth
6832               DO iaz = 1, naz-1
6833                  vffrac(iaz*nzn+1:(iaz+1)*nzn) = vffrac(1:nzn)
6834               ENDDO
6835!--            sum of whole vffrac equals 1, verified
6836            ENDIF
6837!
6838!--         Calculate sky-view factor and direct solar visibility using 2D raytracing
6839            DO iaz = 1, naz
6840               azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
6841               IF ( td /= iup_u  .AND.  td /= iup_l )  THEN
6842                  az2 = REAL(iaz, wp) * azs - pi/2._wp
6843                  az1 = az2 - azs
6844                  !TODO precalculate after 1st line
6845                  vffrac(itarg0:itarg1) = (SIN(az2) - SIN(az1))               &
6846                              * (zbdry(1:nzn) - zbdry(0:nzn-1)                &
6847                                 + SIN(zbdry(0:nzn-1))*COS(zbdry(0:nzn-1))    &
6848                                 - SIN(zbdry(1:nzn))*COS(zbdry(1:nzn)))       &
6849                              / (2._wp * pi)
6850!--               sum of whole vffrac equals 1, verified
6851               ENDIF
6852               yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
6853               yxlen = SQRT(SUM(yxdir(:)**2))
6854               zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
6855               yxdir(:) = yxdir(:) / yxlen
6856
6857               CALL raytrace_2d(ta, yxdir, nzn, zdirs,                        &
6858                                    surfstart(myid) + isurflt, facearea(td),  &
6859                                    vffrac(itarg0:itarg1), .TRUE., .TRUE.,    &
6860                                    .FALSE., lowest_free_ray,                 &
6861                                    ztransp(itarg0:itarg1),                   &
6862                                    itarget(itarg0:itarg1))
6863
6864               skyvf(isurflt) = skyvf(isurflt) + &
6865                                SUM(vffrac(itarg0:itarg0+lowest_free_ray-1))
6866               skyvft(isurflt) = skyvft(isurflt) + &
6867                                 SUM(ztransp(itarg0:itarg0+lowest_free_ray-1) &
6868                                             * vffrac(itarg0:itarg0+lowest_free_ray-1))
6869 
6870!--            Save direct solar transparency
6871               j = MODULO(NINT(azmid/                                          &
6872                               (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
6873                          raytrace_discrete_azims)
6874
6875               DO k = 1, raytrace_discrete_elevs/2
6876                  i = dsidir_rev(k-1, j)
6877                  IF ( i /= -1  .AND.  k <= lowest_free_ray )  &
6878                     dsitrans(isurflt, i) = ztransp(itarg0+k-1)
6879               ENDDO
6880
6881!
6882!--            Advance itarget indices
6883               itarg0 = itarg1 + 1
6884               itarg1 = itarg1 + nzn
6885            ENDDO
6886
6887            IF ( rad_angular_discretization )  THEN
6888!--            sort itarget by face id
6889               CALL quicksort_itarget(itarget,vffrac,ztransp,1,nzn*naz)
6890!
6891!--            For aggregation, we need fractions multiplied by transmissivities
6892               ztransp(:) = vffrac(:) * ztransp(:)
6893!
6894!--            find the first valid position
6895               itarg0 = 1
6896               DO WHILE ( itarg0 <= nzn*naz )
6897                  IF ( itarget(itarg0) /= -1 )  EXIT
6898                  itarg0 = itarg0 + 1
6899               ENDDO
6900
6901               DO  i = itarg0, nzn*naz
6902!
6903!--               For duplicate values, only sum up vf fraction value
6904                  IF ( i < nzn*naz )  THEN
6905                     IF ( itarget(i+1) == itarget(i) )  THEN
6906                        vffrac(i+1) = vffrac(i+1) + vffrac(i)
6907                        ztransp(i+1) = ztransp(i+1) + ztransp(i)
6908                        CYCLE
6909                     ENDIF
6910                  ENDIF
6911!
6912!--               write to the svf array
6913                  nsvfl = nsvfl + 1
6914!--               check dimmension of asvf array and enlarge it if needed
6915                  IF ( nsvfla < nsvfl )  THEN
6916                     k = CEILING(REAL(nsvfla, kind=wp) * grow_factor)
6917                     IF ( msvf == 0 )  THEN
6918                        msvf = 1
6919                        ALLOCATE( asvf1(k) )
6920                        asvf => asvf1
6921                        asvf1(1:nsvfla) = asvf2
6922                        DEALLOCATE( asvf2 )
6923                     ELSE
6924                        msvf = 0
6925                        ALLOCATE( asvf2(k) )
6926                        asvf => asvf2
6927                        asvf2(1:nsvfla) = asvf1
6928                        DEALLOCATE( asvf1 )
6929                     ENDIF
6930
6931                     IF ( debug_output )  THEN
6932                        WRITE( debug_string, '(A,3I12)' ) 'Grow asvf:', nsvfl, nsvfla, k
6933                        CALL debug_message( debug_string, 'info' )
6934                     ENDIF
6935                     
6936                     nsvfla = k
6937                  ENDIF
6938!--               write svf values into the array
6939                  asvf(nsvfl)%isurflt = isurflt
6940                  asvf(nsvfl)%isurfs = itarget(i)
6941                  asvf(nsvfl)%rsvf = vffrac(i)
6942                  asvf(nsvfl)%rtransp = ztransp(i) / vffrac(i)
6943               END DO
6944
6945            ENDIF ! rad_angular_discretization
6946
6947            DEALLOCATE ( zdirs, zcent, zbdry, vffrac, ztransp, itarget ) !FIXME itarget shall be allocated only
6948                                                                  !in case of rad_angular_discretization
6949!
6950!--         Following calculations only required for surface_reflections
6951            IF ( surface_reflections  .AND.  .NOT. rad_angular_discretization )  THEN
6952
6953               DO  isurfs = 1, nsurf
6954                  IF ( .NOT.  surface_facing(surfl(ix, isurflt), surfl(iy, isurflt), &
6955                     surfl(iz, isurflt), surfl(id, isurflt), &
6956                     surf(ix, isurfs), surf(iy, isurfs), &
6957                     surf(iz, isurfs), surf(id, isurfs)) )  THEN
6958                     CYCLE
6959                  ENDIF
6960                 
6961                  sd = surf(id, isurfs)
6962                  sa = (/ REAL(surf(iz, isurfs), wp) - 0.5_wp * kdir(sd),  &
6963                          REAL(surf(iy, isurfs), wp) - 0.5_wp * jdir(sd),  &
6964                          REAL(surf(ix, isurfs), wp) - 0.5_wp * idir(sd)  /)
6965
6966!--               unit vector source -> target
6967                  uv = (/ (ta(1)-sa(1))*dz(1), (ta(2)-sa(2))*dy, (ta(3)-sa(3))*dx /)
6968                  sqdist = SUM(uv(:)**2)
6969                  uv = uv / SQRT(sqdist)
6970
6971!--               reject raytracing above max distance
6972                  IF ( SQRT(sqdist) > max_raytracing_dist ) THEN
6973                     ray_skip_maxdist = ray_skip_maxdist + 1
6974                     CYCLE
6975                  ENDIF
6976                 
6977                  difvf = dot_product((/ kdir(sd), jdir(sd), idir(sd) /), uv) & ! cosine of source normal and direction
6978                      * dot_product((/ kdir(td), jdir(td), idir(td) /), -uv) &  ! cosine of target normal and reverse direction
6979                      / (pi * sqdist) ! square of distance between centers
6980!
6981!--               irradiance factor (our unshaded shape view factor) = view factor per differential target area * source area
6982                  rirrf = difvf * facearea(sd)
6983
6984!--               reject raytracing for potentially too small view factor values
6985                  IF ( rirrf < min_irrf_value ) THEN
6986                      ray_skip_minval = ray_skip_minval + 1
6987                      CYCLE
6988                  ENDIF
6989
6990!--               raytrace + process plant canopy sinks within
6991                  CALL raytrace(sa, ta, isurfs, difvf, facearea(td), .TRUE., &
6992                                visible, transparency)
6993
6994                  IF ( .NOT.  visible ) CYCLE
6995                 ! rsvf = rirrf * transparency
6996
6997!--               write to the svf array
6998                  nsvfl = nsvfl + 1
6999!--               check dimmension of asvf array and enlarge it if needed
7000                  IF ( nsvfla < nsvfl )  THEN
7001                     k = CEILING(REAL(nsvfla, kind=wp) * grow_factor)
7002                     IF ( msvf == 0 )  THEN
7003                        msvf = 1
7004                        ALLOCATE( asvf1(k) )
7005                        asvf => asvf1
7006                        asvf1(1:nsvfla) = asvf2
7007                        DEALLOCATE( asvf2 )
7008                     ELSE
7009                        msvf = 0
7010                        ALLOCATE( asvf2(k) )
7011                        asvf => asvf2
7012                        asvf2(1:nsvfla) = asvf1
7013                        DEALLOCATE( asvf1 )
7014                     ENDIF
7015
7016                     IF ( debug_output )  THEN
7017                        WRITE( debug_string, '(A,3I12)' ) 'Grow asvf:', nsvfl, nsvfla, k
7018                        CALL debug_message( debug_string, 'info' )
7019                     ENDIF
7020                     
7021                     nsvfla = k
7022                  ENDIF
7023!--               write svf values into the array
7024                  asvf(nsvfl)%isurflt = isurflt
7025                  asvf(nsvfl)%isurfs = isurfs
7026                  asvf(nsvfl)%rsvf = rirrf !we postopne multiplication by transparency
7027                  asvf(nsvfl)%rtransp = transparency !a.k.a. Direct Irradiance Factor
7028               ENDDO
7029            ENDIF
7030        ENDDO
7031
7032!--
7033!--     Raytrace to canopy boxes to fill dsitransc TODO optimize
7034        dsitransc(:,:) = 0._wp
7035        az0 = 0._wp
7036        naz = raytrace_discrete_azims
7037        azs = 2._wp * pi / REAL(naz, wp)
7038        zn0 = 0._wp
7039        nzn = raytrace_discrete_elevs / 2
7040        zns = pi / 2._wp / REAL(nzn, wp)
7041        ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), vffrac(1:nzn), ztransp(1:nzn), &
7042               itarget(1:nzn) )
7043        zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
7044        vffrac(:) = 0._wp
7045
7046        DO  ipcgb = 1, npcbl
7047           ta = (/ REAL(pcbl(iz, ipcgb), wp),  &
7048                   REAL(pcbl(iy, ipcgb), wp),  &
7049                   REAL(pcbl(ix, ipcgb), wp) /)
7050!--        Calculate direct solar visibility using 2D raytracing
7051           DO  iaz = 1, naz
7052              azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
7053              yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
7054              yxlen = SQRT(SUM(yxdir(:)**2))
7055              zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
7056              yxdir(:) = yxdir(:) / yxlen
7057              CALL raytrace_2d(ta, yxdir, nzn, zdirs,                                &
7058                                   -999, -999._wp, vffrac, .FALSE., .FALSE., .TRUE., &
7059                                   lowest_free_ray, ztransp, itarget)
7060
7061!--           Save direct solar transparency
7062              j = MODULO(NINT(azmid/                                         &
7063                             (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
7064                         raytrace_discrete_azims)
7065              DO  k = 1, raytrace_discrete_elevs/2
7066                 i = dsidir_rev(k-1, j)
7067                 IF ( i /= -1  .AND.  k <= lowest_free_ray ) &
7068                    dsitransc(ipcgb, i) = ztransp(k)
7069              ENDDO
7070           ENDDO
7071        ENDDO
7072        DEALLOCATE ( zdirs, zcent, vffrac, ztransp, itarget )
7073!--
7074!--     Raytrace to MRT boxes
7075        IF ( nmrtbl > 0 )  THEN
7076           mrtdsit(:,:) = 0._wp
7077           mrtsky(:) = 0._wp
7078           mrtskyt(:) = 0._wp
7079           az0 = 0._wp
7080           naz = raytrace_discrete_azims
7081           azs = 2._wp * pi / REAL(naz, wp)
7082           zn0 = 0._wp
7083           nzn = raytrace_discrete_elevs
7084           zns = pi / REAL(nzn, wp)
7085           ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), zbdry(0:nzn), vffrac(1:nzn*naz), vffrac0(1:nzn), &
7086                      ztransp(1:nzn*naz), itarget(1:nzn*naz) )   !FIXME allocate itarget only
7087                                                                 !in case of rad_angular_discretization
7088
7089           zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
7090           zbdry(:) = (/( zn0+REAL(izn,wp)*zns, izn=0, nzn )/)
7091           vffrac0(:) = (COS(zbdry(0:nzn-1)) - COS(zbdry(1:nzn))) / 2._wp / REAL(naz, wp)
7092           !
7093           !--Modify direction weights to simulate human body (lower weight for top-down)
7094           IF ( mrt_geom_human )  THEN
7095              vffrac0(:) = vffrac0(:) * MAX(0._wp, SIN(zcent(:))*0.88_wp + COS(zcent(:))*0.12_wp)
7096              vffrac0(:) = vffrac0(:) / (SUM(vffrac0) * REAL(naz, wp))
7097           ENDIF
7098
7099           DO  imrt = 1, nmrtbl
7100              ta = (/ REAL(mrtbl(iz, imrt), wp),  &
7101                      REAL(mrtbl(iy, imrt), wp),  &
7102                      REAL(mrtbl(ix, imrt), wp) /)
7103!
7104!--           vf fractions are constant per azimuth
7105              DO iaz = 0, naz-1
7106                 vffrac(iaz*nzn+1:(iaz+1)*nzn) = vffrac0(:)
7107              ENDDO
7108!--           sum of whole vffrac equals 1, verified
7109              itarg0 = 1
7110              itarg1 = nzn
7111!
7112!--           Calculate sky-view factor and direct solar visibility using 2D raytracing
7113              DO  iaz = 1, naz
7114                 azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
7115                 yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
7116                 yxlen = SQRT(SUM(yxdir(:)**2))
7117                 zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
7118                 yxdir(:) = yxdir(:) / yxlen
7119
7120                 CALL raytrace_2d(ta, yxdir, nzn, zdirs,                         &
7121                                  -999, -999._wp, vffrac(itarg0:itarg1), .TRUE., &
7122                                  .FALSE., .TRUE., lowest_free_ray,              &
7123                                  ztransp(itarg0:itarg1),                        &
7124                                  itarget(itarg0:itarg1))
7125
7126!--              Sky view factors for MRT
7127                 mrtsky(imrt) = mrtsky(imrt) + &
7128                                  SUM(vffrac(itarg0:itarg0+lowest_free_ray-1))
7129                 mrtskyt(imrt) = mrtskyt(imrt) + &
7130                                   SUM(ztransp(itarg0:itarg0+lowest_free_ray-1) &
7131                                               * vffrac(itarg0:itarg0+lowest_free_ray-1))
7132!--              Direct solar transparency for MRT
7133                 j = MODULO(NINT(azmid/                                         &
7134                                (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
7135                            raytrace_discrete_azims)
7136                 DO  k = 1, raytrace_discrete_elevs/2
7137                    i = dsidir_rev(k-1, j)
7138                    IF ( i /= -1  .AND.  k <= lowest_free_ray ) &
7139                       mrtdsit(imrt, i) = ztransp(itarg0+k-1)
7140                 ENDDO
7141!
7142!--              Advance itarget indices
7143                 itarg0 = itarg1 + 1
7144                 itarg1 = itarg1 + nzn
7145              ENDDO
7146
7147!--           sort itarget by face id
7148              CALL quicksort_itarget(itarget,vffrac,ztransp,1,nzn*naz)
7149!
7150!--           find the first valid position
7151              itarg0 = 1
7152              DO WHILE ( itarg0 <= nzn*naz )
7153                 IF ( itarget(itarg0) /= -1 )  EXIT
7154                 itarg0 = itarg0 + 1
7155              ENDDO
7156
7157              DO  i = itarg0, nzn*naz
7158!
7159!--              For duplicate values, only sum up vf fraction value
7160                 IF ( i < nzn*naz )  THEN
7161                    IF ( itarget(i+1) == itarget(i) )  THEN
7162                       vffrac(i+1) = vffrac(i+1) + vffrac(i)
7163                       CYCLE
7164                    ENDIF
7165                 ENDIF
7166!
7167!--              write to the mrtf array
7168                 nmrtf = nmrtf + 1
7169!--              check dimmension of mrtf array and enlarge it if needed
7170                 IF ( nmrtfa < nmrtf )  THEN
7171                    k = CEILING(REAL(nmrtfa, kind=wp) * grow_factor)
7172                    IF ( mmrtf == 0 )  THEN
7173                       mmrtf = 1
7174                       ALLOCATE( amrtf1(k) )
7175                       amrtf => amrtf1
7176                       amrtf1(1:nmrtfa) = amrtf2
7177                       DEALLOCATE( amrtf2 )
7178                    ELSE
7179                       mmrtf = 0
7180                       ALLOCATE( amrtf2(k) )
7181                       amrtf => amrtf2
7182                       amrtf2(1:nmrtfa) = amrtf1
7183                       DEALLOCATE( amrtf1 )
7184                    ENDIF
7185
7186                    IF ( debug_output )  THEN
7187                       WRITE( debug_string, '(A,3I12)' ) 'Grow amrtf:', nmrtf, nmrtfa, k
7188                       CALL debug_message( debug_string, 'info' )
7189                    ENDIF
7190
7191                    nmrtfa = k
7192                 ENDIF
7193!--              write mrtf values into the array
7194                 amrtf(nmrtf)%isurflt = imrt
7195                 amrtf(nmrtf)%isurfs = itarget(i)
7196                 amrtf(nmrtf)%rsvf = vffrac(i)
7197                 amrtf(nmrtf)%rtransp = ztransp(i)
7198              ENDDO ! itarg
7199
7200           ENDDO ! imrt
7201           DEALLOCATE ( zdirs, zcent, zbdry, vffrac, vffrac0, ztransp, itarget )
7202!
7203!--        Move MRT factors to final arrays
7204           ALLOCATE ( mrtf(nmrtf), mrtft(nmrtf), mrtfsurf(2,nmrtf) )
7205           DO  imrtf = 1, nmrtf
7206              mrtf(imrtf) = amrtf(imrtf)%rsvf
7207              mrtft(imrtf) = amrtf(imrtf)%rsvf * amrtf(imrtf)%rtransp
7208              mrtfsurf(:,imrtf) = (/amrtf(imrtf)%isurflt, amrtf(imrtf)%isurfs /)
7209           ENDDO
7210           IF ( ALLOCATED(amrtf1) )  DEALLOCATE( amrtf1 )
7211           IF ( ALLOCATED(amrtf2) )  DEALLOCATE( amrtf2 )
7212        ENDIF ! nmrtbl > 0
7213
7214        IF ( rad_angular_discretization )  THEN
7215#if defined( __parallel )
7216!--        finalize MPI_RMA communication established to get global index of the surface from grid indices
7217!--        flush all MPI window pending requests
7218           CALL MPI_Win_flush_all(win_gridsurf, ierr)
7219           IF ( ierr /= 0 ) THEN
7220               WRITE(9,*) 'Error MPI_Win_flush_all1:', ierr, win_gridsurf
7221               FLUSH(9)
7222           ENDIF
7223!--        unlock MPI window
7224           CALL MPI_Win_unlock_all(win_gridsurf, ierr)
7225           IF ( ierr /= 0 ) THEN
7226               WRITE(9,*) 'Error MPI_Win_unlock_all1:', ierr, win_gridsurf
7227               FLUSH(9)
7228           ENDIF
7229!--        free MPI window
7230           CALL MPI_Win_free(win_gridsurf, ierr)
7231           IF ( ierr /= 0 ) THEN
7232               WRITE(9,*) 'Error MPI_Win_free1:', ierr, win_gridsurf
7233               FLUSH(9)
7234           ENDIF
7235#else
7236           DEALLOCATE ( gridsurf )
7237#endif
7238        ENDIF
7239
7240        IF ( debug_output )  CALL debug_message( 'waiting for completion of SVF and CSF calculation in all processes', 'info' )
7241
7242!--     deallocate temporary global arrays
7243        DEALLOCATE(nzterr)
7244       
7245        IF ( plant_canopy )  THEN
7246!--         finalize mpi_rma communication and deallocate temporary arrays
7247#if defined( __parallel )
7248            IF ( raytrace_mpi_rma )  THEN
7249                CALL MPI_Win_flush_all(win_lad, ierr)
7250                IF ( ierr /= 0 ) THEN
7251                    WRITE(9,*) 'Error MPI_Win_flush_all2:', ierr, win_lad
7252                    FLUSH(9)
7253                ENDIF
7254!--             unlock MPI window
7255                CALL MPI_Win_unlock_all(win_lad, ierr)
7256                IF ( ierr /= 0 ) THEN
7257                    WRITE(9,*) 'Error MPI_Win_unlock_all2:', ierr, win_lad
7258                    FLUSH(9)
7259                ENDIF
7260!--             free MPI window
7261                CALL MPI_Win_free(win_lad, ierr)
7262                IF ( ierr /= 0 ) THEN
7263                    WRITE(9,*) 'Error MPI_Win_free2:', ierr, win_lad
7264                    FLUSH(9)
7265                ENDIF
7266!--             deallocate temporary arrays storing values for csf calculation during raytracing
7267                DEALLOCATE( lad_s_ray )
7268!--             sub_lad is the pointer to lad_s_rma in case of raytrace_mpi_rma
7269!--             and must not be deallocated here
7270            ELSE
7271                DEALLOCATE(sub_lad)
7272                DEALLOCATE(sub_lad_g)
7273            ENDIF
7274#else
7275            DEALLOCATE(sub_lad)
7276#endif
7277            DEALLOCATE( boxes )
7278            DEALLOCATE( crlens )
7279            DEALLOCATE( plantt )
7280            DEALLOCATE( rt2_track, rt2_track_lad, rt2_track_dist, rt2_dist )
7281        ENDIF
7282
7283        IF ( debug_output )  CALL debug_message( 'calculation of the complete SVF array', 'info' )
7284
7285        IF ( rad_angular_discretization )  THEN
7286           IF ( debug_output )  CALL debug_message( 'Load svf from the structure array to plain arrays', 'info' )
7287           ALLOCATE( svf(ndsvf,nsvfl) )
7288           ALLOCATE( svfsurf(idsvf,nsvfl) )
7289
7290           DO isvf = 1, nsvfl
7291               svf(:, isvf) = (/ asvf(isvf)%rsvf, asvf(isvf)%rtransp /)
7292               svfsurf(:, isvf) = (/ asvf(isvf)%isurflt, asvf(isvf)%isurfs /)
7293           ENDDO
7294        ELSE
7295           IF ( debug_output )  CALL debug_message( 'Start SVF sort', 'info' )
7296!--        sort svf ( a version of quicksort )
7297           CALL quicksort_svf(asvf,1,nsvfl)
7298
7299           !< load svf from the structure array to plain arrays
7300           IF ( debug_output )  CALL debug_message( 'Load svf from the structure array to plain arrays', 'info' )
7301           ALLOCATE( svf(ndsvf,nsvfl) )
7302           ALLOCATE( svfsurf(idsvf,nsvfl) )
7303           svfnorm_counts(:) = 0._wp
7304           isurflt_prev = -1
7305           ksvf = 1
7306           svfsum = 0._wp
7307           DO isvf = 1, nsvfl
7308!--            normalize svf per target face
7309               IF ( asvf(ksvf)%isurflt /= isurflt_prev )  THEN
7310                   IF ( isurflt_prev /= -1  .AND.  svfsum /= 0._wp )  THEN
7311                       !< update histogram of logged svf normalization values
7312                       i = searchsorted(svfnorm_report_thresh, svfsum / (1._wp-skyvf(isurflt_prev)))
7313                       svfnorm_counts(i) = svfnorm_counts(i) + 1
7314
7315                       svf(1, isvf_surflt:isvf-1) = svf(1, isvf_surflt:isvf-1) / svfsum * (1._wp-skyvf(isurflt_prev))
7316                   ENDIF
7317                   isurflt_prev = asvf(ksvf)%isurflt
7318                   isvf_surflt = isvf
7319                   svfsum = asvf(ksvf)%rsvf !?? / asvf(ksvf)%rtransp
7320               ELSE
7321                   svfsum = svfsum + asvf(ksvf)%rsvf !?? / asvf(ksvf)%rtransp
7322               ENDIF
7323
7324               svf(:, isvf) = (/ asvf(ksvf)%rsvf, asvf(ksvf)%rtransp /)
7325               svfsurf(:, isvf) = (/ asvf(ksvf)%isurflt, asvf(ksvf)%isurfs /)
7326
7327!--            next element
7328               ksvf = ksvf + 1
7329           ENDDO
7330
7331           IF ( isurflt_prev /= -1  .AND.  svfsum /= 0._wp )  THEN
7332               i = searchsorted(svfnorm_report_thresh, svfsum / (1._wp-skyvf(isurflt_prev)))
7333               svfnorm_counts(i) = svfnorm_counts(i) + 1
7334
7335               svf(1, isvf_surflt:nsvfl) = svf(1, isvf_surflt:nsvfl) / svfsum * (1._wp-skyvf(isurflt_prev))
7336           ENDIF
7337           WRITE(9, *) 'SVF normalization histogram:', svfnorm_counts,  &
7338                       'on thresholds:', svfnorm_report_thresh(1:svfnorm_report_num), '(val < thresh <= val)'
7339           !TODO we should be able to deallocate skyvf, from now on we only need skyvft
7340        ENDIF ! rad_angular_discretization
7341
7342!--     deallocate temporary asvf array
7343!--     DEALLOCATE(asvf) - ifort has a problem with deallocation of allocatable target
7344!--     via pointing pointer - we need to test original targets
7345        IF ( ALLOCATED(asvf1) )  THEN
7346            DEALLOCATE(asvf1)
7347        ENDIF
7348        IF ( ALLOCATED(asvf2) )  THEN
7349            DEALLOCATE(asvf2)
7350        ENDIF
7351
7352        npcsfl = 0
7353        IF ( plant_canopy )  THEN
7354
7355            IF ( debug_output )  CALL debug_message( 'Calculation of the complete CSF array', 'info' )
7356!--         sort and merge csf for the last time, keeping the array size to minimum
7357            CALL merge_and_grow_csf(-1)
7358           
7359!--         aggregate csb among processors
7360!--         allocate necessary arrays
7361            udim = max(ncsfl,1)
7362            ALLOCATE( csflt_l(ndcsf*udim) )
7363            csflt(1:ndcsf,1:udim) => csflt_l(1:ndcsf*udim)
7364            ALLOCATE( kcsflt_l(kdcsf*udim) )
7365            kcsflt(1:kdcsf,1:udim) => kcsflt_l(1:kdcsf*udim)
7366            ALLOCATE( icsflt(0:numprocs-1) )
7367            ALLOCATE( dcsflt(0:numprocs-1) )
7368            ALLOCATE( ipcsflt(0:numprocs-1) )
7369            ALLOCATE( dpcsflt(0:numprocs-1) )
7370           
7371!--         fill out arrays of csf values and
7372!--         arrays of number of elements and displacements
7373!--         for particular precessors
7374            icsflt = 0
7375            dcsflt = 0
7376            ip = -1
7377            j = -1
7378            d = 0
7379            DO kcsf = 1, ncsfl
7380                j = j+1
7381                IF ( acsf(kcsf)%ip /= ip )  THEN
7382!--                 new block of the processor
7383!--                 number of elements of previous block
7384                    IF ( ip>=0) icsflt(ip) = j
7385                    d = d+j
7386!--                 blank blocks
7387                    DO jp = ip+1, acsf(kcsf)%ip-1
7388!--                     number of elements is zero, displacement is equal to previous
7389                        icsflt(jp) = 0
7390                        dcsflt(jp) = d
7391                    ENDDO
7392!--                 the actual block
7393                    ip = acsf(kcsf)%ip
7394                    dcsflt(ip) = d
7395                    j = 0
7396                ENDIF
7397                csflt(1,kcsf) = acsf(kcsf)%rcvf
7398!--             fill out integer values of itz,ity,itx,isurfs
7399                kcsflt(1,kcsf) = acsf(kcsf)%itz
7400                kcsflt(2,kcsf) = acsf(kcsf)%ity
7401                kcsflt(3,kcsf) = acsf(kcsf)%itx
7402                kcsflt(4,kcsf) = acsf(kcsf)%isurfs
7403            ENDDO
7404!--         last blank blocks at the end of array
7405            j = j+1
7406            IF ( ip>=0 ) icsflt(ip) = j
7407            d = d+j
7408            DO jp = ip+1, numprocs-1
7409!--             number of elements is zero, displacement is equal to previous
7410                icsflt(jp) = 0
7411                dcsflt(jp) = d
7412            ENDDO
7413           
7414!--         deallocate temporary acsf array
7415!--         DEALLOCATE(acsf) - ifort has a problem with deallocation of allocatable target
7416!--         via pointing pointer - we need to test original targets
7417            IF ( ALLOCATED(acsf1) )  THEN
7418                DEALLOCATE(acsf1)
7419            ENDIF
7420            IF ( ALLOCATED(acsf2) )  THEN
7421                DEALLOCATE(acsf2)
7422            ENDIF
7423                   
7424#if defined( __parallel )
7425!--         scatter and gather the number of elements to and from all processor
7426!--         and calculate displacements
7427            IF ( debug_output )  CALL debug_message( 'Scatter and gather the number of elements to and from all processor', 'info' )
7428
7429            CALL MPI_AlltoAll(icsflt,1,MPI_INTEGER,ipcsflt,1,MPI_INTEGER,comm2d, ierr)
7430
7431            IF ( ierr /= 0 ) THEN
7432                WRITE(9,*) 'Error MPI_AlltoAll1:', ierr, SIZE(icsflt), SIZE(ipcsflt)
7433                FLUSH(9)
7434            ENDIF
7435
7436            npcsfl = SUM(ipcsflt)
7437            d = 0
7438            DO i = 0, numprocs-1
7439                dpcsflt(i) = d
7440                d = d + ipcsflt(i)
7441            ENDDO
7442
7443!--         exchange csf fields between processors
7444            IF ( debug_output )  CALL debug_message( 'Exchange csf fields between processors', 'info' )
7445            udim = max(npcsfl,1)
7446            ALLOCATE( pcsflt_l(ndcsf*udim) )
7447            pcsflt(1:ndcsf,1:udim) => pcsflt_l(1:ndcsf*udim)
7448            ALLOCATE( kpcsflt_l(kdcsf*udim) )
7449            kpcsflt(1:kdcsf,1:udim) => kpcsflt_l(1:kdcsf*udim)
7450            CALL MPI_AlltoAllv(csflt_l, ndcsf*icsflt, ndcsf*dcsflt, MPI_REAL, &
7451                pcsflt_l, ndcsf*ipcsflt, ndcsf*dpcsflt, MPI_REAL, comm2d, ierr)
7452            IF ( ierr /= 0 ) THEN
7453                WRITE(9,*) 'Error MPI_AlltoAllv1:', ierr, SIZE(ipcsflt), ndcsf*icsflt, &
7454                            ndcsf*dcsflt, SIZE(pcsflt_l),ndcsf*ipcsflt, ndcsf*dpcsflt
7455                FLUSH(9)
7456            ENDIF
7457
7458            CALL MPI_AlltoAllv(kcsflt_l, kdcsf*icsflt, kdcsf*dcsflt, MPI_INTEGER, &
7459                kpcsflt_l, kdcsf*ipcsflt, kdcsf*dpcsflt, MPI_INTEGER, comm2d, ierr)
7460            IF ( ierr /= 0 ) THEN
7461                WRITE(9,*) 'Error MPI_AlltoAllv2:', ierr, SIZE(kcsflt_l),kdcsf*icsflt, &
7462                           kdcsf*dcsflt, SIZE(kpcsflt_l), kdcsf*ipcsflt, kdcsf*dpcsflt
7463                FLUSH(9)
7464            ENDIF
7465           
7466#else
7467            npcsfl = ncsfl
7468            ALLOCATE( pcsflt(ndcsf,max(npcsfl,ndcsf)) )
7469            ALLOCATE( kpcsflt(kdcsf,max(npcsfl,kdcsf)) )
7470            pcsflt = csflt
7471            kpcsflt = kcsflt
7472#endif
7473
7474!--         deallocate temporary arrays
7475            DEALLOCATE( csflt_l )
7476            DEALLOCATE( kcsflt_l )
7477            DEALLOCATE( icsflt )
7478            DEALLOCATE( dcsflt )
7479            DEALLOCATE( ipcsflt )
7480            DEALLOCATE( dpcsflt )
7481
7482!--         sort csf ( a version of quicksort )
7483            IF ( debug_output )  CALL debug_message( 'Sort csf', 'info' )
7484            CALL quicksort_csf2(kpcsflt, pcsflt, 1, npcsfl)
7485
7486!--         aggregate canopy sink factor records with identical box & source
7487!--         againg across all values from all processors
7488            IF ( debug_output )  CALL debug_message( 'Aggregate canopy sink factor records with identical box', 'info' )
7489
7490            IF ( npcsfl > 0 )  THEN
7491                icsf = 1 !< reading index
7492                kcsf = 1 !< writing index
7493                DO WHILE (icsf < npcsfl)
7494!--                 here kpcsf(kcsf) already has values from kpcsf(icsf)
7495                    IF ( kpcsflt(3,icsf) == kpcsflt(3,icsf+1)  .AND.  &
7496                         kpcsflt(2,icsf) == kpcsflt(2,icsf+1)  .AND.  &
7497                         kpcsflt(1,icsf) == kpcsflt(1,icsf+1)  .AND.  &
7498                         kpcsflt(4,icsf) == kpcsflt(4,icsf+1) )  THEN
7499
7500                        pcsflt(1,kcsf) = pcsflt(1,kcsf) + pcsflt(1,icsf+1)
7501
7502!--                     advance reading index, keep writing index
7503                        icsf = icsf + 1
7504                    ELSE
7505!--                     not identical, just advance and copy
7506                        icsf = icsf + 1
7507                        kcsf = kcsf + 1
7508                        kpcsflt(:,kcsf) = kpcsflt(:,icsf)
7509                        pcsflt(:,kcsf) = pcsflt(:,icsf)
7510                    ENDIF
7511                ENDDO
7512!--             last written item is now also the last item in valid part of array
7513                npcsfl = kcsf
7514            ENDIF
7515
7516            ncsfl = npcsfl
7517            IF ( ncsfl > 0 )  THEN
7518                ALLOCATE( csf(ndcsf,ncsfl) )
7519                ALLOCATE( csfsurf(idcsf,ncsfl) )
7520                DO icsf = 1, ncsfl
7521                    csf(:,icsf) = pcsflt(:,icsf)
7522                    csfsurf(1,icsf) =  gridpcbl(kpcsflt(1,icsf),kpcsflt(2,icsf),kpcsflt(3,icsf))
7523                    csfsurf(2,icsf) =  kpcsflt(4,icsf)
7524                ENDDO
7525            ENDIF
7526           
7527!--         deallocation of temporary arrays
7528            IF ( npcbl > 0 )  DEALLOCATE( gridpcbl )
7529            DEALLOCATE( pcsflt_l )
7530            DEALLOCATE( kpcsflt_l )
7531            IF ( debug_output )  CALL debug_message( 'End of aggregate csf', 'info' )
7532           
7533        ENDIF
7534
7535#if defined( __parallel )
7536        CALL MPI_BARRIER( comm2d, ierr )
7537#endif
7538        CALL location_message( 'calculating view factors for radiation interaction', 'finished' )
7539
7540        RETURN  !todo: remove
7541       
7542!        WRITE( message_string, * )  &
7543!            'I/O error when processing shape view factors / ',  &
7544!            'plant canopy sink factors / direct irradiance factors.'
7545!        CALL message( 'init_urban_surface', 'PA0502', 2, 2, 0, 6, 0 )
7546       
7547    END SUBROUTINE radiation_calc_svf
7548
7549   
7550!------------------------------------------------------------------------------!
7551! Description:
7552! ------------
7553!> Raytracing for detecting obstacles and calculating compound canopy sink
7554!> factors. (A simple obstacle detection would only need to process faces in
7555!> 3 dimensions without any ordering.)
7556!> Assumtions:
7557!> -----------
7558!> 1. The ray always originates from a face midpoint (only one coordinate equals
7559!>    *.5, i.e. wall) and doesn't travel parallel to the surface (that would mean
7560!>    shape factor=0). Therefore, the ray may never travel exactly along a face
7561!>    or an edge.
7562!> 2. From grid bottom to urban surface top the grid has to be *equidistant*
7563!>    within each of the dimensions, including vertical (but the resolution
7564!>    doesn't need to be the same in all three dimensions).
7565!------------------------------------------------------------------------------!
7566    SUBROUTINE raytrace(src, targ, isrc, difvf, atarg, create_csf, visible, transparency)
7567        IMPLICIT NONE
7568
7569        REAL(wp), DIMENSION(3), INTENT(in)     :: src, targ    !< real coordinates z,y,x
7570        INTEGER(iwp), INTENT(in)               :: isrc         !< index of source face for csf
7571        REAL(wp), INTENT(in)                   :: difvf        !< differential view factor for csf
7572        REAL(wp), INTENT(in)                   :: atarg        !< target surface area for csf
7573        LOGICAL, INTENT(in)                    :: create_csf   !< whether to generate new CSFs during raytracing
7574        LOGICAL, INTENT(out)                   :: visible
7575        REAL(wp), INTENT(out)                  :: transparency !< along whole path
7576        INTEGER(iwp)                           :: i, k, d
7577        INTEGER(iwp)                           :: seldim       !< dimension to be incremented
7578        INTEGER(iwp)                           :: ncsb         !< no of written plant canopy sinkboxes
7579        INTEGER(iwp)                           :: maxboxes     !< max no of gridboxes visited
7580        REAL(wp)                               :: distance     !< euclidean along path
7581        REAL(wp)                               :: crlen        !< length of gridbox crossing
7582        REAL(wp)                               :: lastdist     !< beginning of current crossing
7583        REAL(wp)                               :: nextdist     !< end of current crossing
7584        REAL(wp)                               :: realdist     !< distance in meters per unit distance
7585        REAL(wp)                               :: crmid        !< midpoint of crossing
7586        REAL(wp)                               :: cursink      !< sink factor for current canopy box
7587        REAL(wp), DIMENSION(3)                 :: delta        !< path vector
7588        REAL(wp), DIMENSION(3)                 :: uvect        !< unit vector
7589        REAL(wp), DIMENSION(3)                 :: dimnextdist  !< distance for each dimension increments
7590        INTEGER(iwp), DIMENSION(3)             :: box          !< gridbox being crossed
7591        INTEGER(iwp), DIMENSION(3)             :: dimnext      !< next dimension increments along path
7592        INTEGER(iwp), DIMENSION(3)             :: dimdelta     !< dimension direction = +- 1
7593        INTEGER(iwp)                           :: px, py       !< number of processors in x and y dir before
7594                                                               !< the processor in the question
7595        INTEGER(iwp)                           :: ip           !< number of processor where gridbox reside
7596        INTEGER(iwp)                           :: ig           !< 1D index of gridbox in global 2D array
7597       
7598        REAL(wp)                               :: eps = 1E-10_wp !< epsilon for value comparison
7599        REAL(wp)                               :: lad_s_target   !< recieved lad_s of particular grid box
7600
7601!
7602!--     Maximum number of gridboxes visited equals to maximum number of boundaries crossed in each dimension plus one. That's also
7603!--     the maximum number of plant canopy boxes written. We grow the acsf array accordingly using exponential factor.
7604        maxboxes = SUM(ABS(NINT(targ, iwp) - NINT(src, iwp))) + 1
7605        IF ( plant_canopy  .AND.  ncsfl + maxboxes > ncsfla )  THEN
7606!--         use this code for growing by fixed exponential increments (equivalent to case where ncsfl always increases by 1)
7607!--         k = CEILING(grow_factor ** real(CEILING(log(real(ncsfl + maxboxes, kind=wp)) &
7608!--                                                / log(grow_factor)), kind=wp))
7609!--         or use this code to simply always keep some extra space after growing
7610            k = CEILING(REAL(ncsfl + maxboxes, kind=wp) * grow_factor)
7611
7612            CALL merge_and_grow_csf(k)
7613        ENDIF
7614       
7615        transparency = 1._wp
7616        ncsb = 0
7617
7618        delta(:) = targ(:) - src(:)
7619        distance = SQRT(SUM(delta(:)**2))
7620        IF ( distance == 0._wp )  THEN
7621            visible = .TRUE.
7622            RETURN
7623        ENDIF
7624        uvect(:) = delta(:) / distance
7625        realdist = SQRT(SUM( (uvect(:)*(/dz(1),dy,dx/))**2 ))
7626
7627        lastdist = 0._wp
7628
7629!--     Since all face coordinates have values *.5 and we'd like to use
7630!--     integers, all these have .5 added
7631        DO d = 1, 3
7632            IF ( uvect(d) == 0._wp )  THEN
7633                dimnext(d) = 999999999
7634                dimdelta(d) = 999999999
7635                dimnextdist(d) = 1.0E20_wp
7636            ELSE IF ( uvect(d) > 0._wp )  THEN
7637                dimnext(d) = CEILING(src(d) + .5_wp)
7638                dimdelta(d) = 1
7639                dimnextdist(d) = (dimnext(d) - .5_wp - src(d)) / uvect(d)
7640            ELSE
7641                dimnext(d) = FLOOR(src(d) + .5_wp)
7642                dimdelta(d) = -1
7643                dimnextdist(d) = (dimnext(d) - .5_wp - src(d)) / uvect(d)
7644            ENDIF
7645        ENDDO
7646
7647        DO
7648!--         along what dimension will the next wall crossing be?
7649            seldim = minloc(dimnextdist, 1)
7650            nextdist = dimnextdist(seldim)
7651            IF ( nextdist > distance ) nextdist = distance
7652
7653            crlen = nextdist - lastdist
7654            IF ( crlen > .001_wp )  THEN
7655                crmid = (lastdist + nextdist) * .5_wp
7656                box = NINT(src(:) + uvect(:) * crmid, iwp)
7657
7658!--             calculate index of the grid with global indices (box(2),box(3))
7659!--             in the array nzterr and plantt and id of the coresponding processor
7660                px = box(3)/nnx
7661                py = box(2)/nny
7662                ip = px*pdims(2)+py
7663                ig = ip*nnx*nny + (box(3)-px*nnx)*nny + box(2)-py*nny
7664                IF ( box(1) <= nzterr(ig) )  THEN
7665                    visible = .FALSE.
7666                    RETURN
7667                ENDIF
7668
7669                IF ( plant_canopy )  THEN
7670                    IF ( box(1) <= plantt(ig) )  THEN
7671                        ncsb = ncsb + 1
7672                        boxes(:,ncsb) = box
7673                        crlens(ncsb) = crlen
7674#if defined( __parallel )
7675                        lad_ip(ncsb) = ip
7676                        lad_disp(ncsb) = (box(3)-px*nnx)*(nny*nz_plant) + (box(2)-py*nny)*nz_plant + box(1)-nz_urban_b
7677#endif
7678                    ENDIF
7679                ENDIF
7680            ENDIF
7681
7682            IF ( ABS(distance - nextdist) < eps )  EXIT
7683            lastdist = nextdist
7684            dimnext(seldim) = dimnext(seldim) + dimdelta(seldim)
7685            dimnextdist(seldim) = (dimnext(seldim) - .5_wp - src(seldim)) / uvect(seldim)
7686        ENDDO
7687       
7688        IF ( plant_canopy )  THEN
7689#if defined( __parallel )
7690            IF ( raytrace_mpi_rma )  THEN
7691!--             send requests for lad_s to appropriate processor
7692                CALL cpu_log( log_point_s(77), 'rad_rma_lad', 'start' )
7693                DO i = 1, ncsb
7694                    CALL MPI_Get(lad_s_ray(i), 1, MPI_REAL, lad_ip(i), lad_disp(i), &
7695                                 1, MPI_REAL, win_lad, ierr)
7696                    IF ( ierr /= 0 )  THEN
7697                        WRITE(9,*) 'Error MPI_Get1:', ierr, lad_s_ray(i), &
7698                                   lad_ip(i), lad_disp(i), win_lad
7699                        FLUSH(9)
7700                    ENDIF
7701                ENDDO
7702               
7703!--             wait for all pending local requests complete
7704                CALL MPI_Win_flush_local_all(win_lad, ierr)
7705                IF ( ierr /= 0 )  THEN
7706                    WRITE(9,*) 'Error MPI_Win_flush_local_all1:', ierr, win_lad
7707                    FLUSH(9)
7708                ENDIF
7709                CALL cpu_log( log_point_s(77), 'rad_rma_lad', 'stop' )
7710               
7711            ENDIF
7712#endif
7713
7714!--         calculate csf and transparency
7715            DO i = 1, ncsb
7716#if defined( __parallel )
7717                IF ( raytrace_mpi_rma )  THEN
7718                    lad_s_target = lad_s_ray(i)
7719                ELSE
7720                    lad_s_target = sub_lad_g(lad_ip(i)*nnx*nny*nz_plant + lad_disp(i))
7721                ENDIF
7722#else
7723                lad_s_target = sub_lad(boxes(1,i),boxes(2,i),boxes(3,i))
7724#endif
7725                cursink = 1._wp - exp(-ext_coef * lad_s_target * crlens(i)*realdist)
7726
7727                IF ( create_csf )  THEN
7728!--                 write svf values into the array
7729                    ncsfl = ncsfl + 1
7730                    acsf(ncsfl)%ip = lad_ip(i)
7731                    acsf(ncsfl)%itx = boxes(3,i)
7732                    acsf(ncsfl)%ity = boxes(2,i)
7733                    acsf(ncsfl)%itz = boxes(1,i)
7734                    acsf(ncsfl)%isurfs = isrc
7735                    acsf(ncsfl)%rcvf = cursink*transparency*difvf*atarg
7736                ENDIF  !< create_csf
7737
7738                transparency = transparency * (1._wp - cursink)
7739               
7740            ENDDO
7741        ENDIF
7742       
7743        visible = .TRUE.
7744
7745    END SUBROUTINE raytrace
7746   
7747 
7748!------------------------------------------------------------------------------!
7749! Description:
7750! ------------
7751!> A new, more efficient version of ray tracing algorithm that processes a whole
7752!> arc instead of a single ray.
7753!>
7754!> In all comments, horizon means tangent of horizon angle, i.e.
7755!> vertical_delta / horizontal_distance
7756!------------------------------------------------------------------------------!
7757   SUBROUTINE raytrace_2d(origin, yxdir, nrays, zdirs, iorig, aorig, vffrac,  &
7758                              calc_svf, create_csf, skip_1st_pcb,             &
7759                              lowest_free_ray, transparency, itarget)
7760      IMPLICIT NONE
7761
7762      REAL(wp), DIMENSION(3), INTENT(IN)     ::  origin        !< z,y,x coordinates of ray origin
7763      REAL(wp), DIMENSION(2), INTENT(IN)     ::  yxdir         !< y,x *unit* vector of ray direction (in grid units)
7764      INTEGER(iwp)                           ::  nrays         !< number of rays (z directions) to raytrace
7765      REAL(wp), DIMENSION(nrays), INTENT(IN) ::  zdirs         !< list of z directions to raytrace (z/hdist, grid, zenith->nadir)
7766      INTEGER(iwp), INTENT(in)               ::  iorig         !< index of origin face for csf
7767      REAL(wp), INTENT(in)                   ::  aorig         !< origin face area for csf
7768      REAL(wp), DIMENSION(nrays), INTENT(in) ::  vffrac        !< view factor fractions of each ray for csf
7769      LOGICAL, INTENT(in)                    ::  calc_svf      !< whether to calculate SFV (identify obstacle surfaces)
7770      LOGICAL, INTENT(in)                    ::  create_csf    !< whether to create canopy sink factors
7771      LOGICAL, INTENT(in)                    ::  skip_1st_pcb  !< whether to skip first plant canopy box during raytracing
7772      INTEGER(iwp), INTENT(out)              ::  lowest_free_ray !< index into zdirs
7773      REAL(wp), DIMENSION(nrays), INTENT(OUT) ::  transparency !< transparencies of zdirs paths
7774      INTEGER(iwp), DIMENSION(nrays), INTENT(OUT) ::  itarget  !< global indices of target faces for zdirs
7775
7776      INTEGER(iwp), DIMENSION(nrays)         ::  target_procs
7777      REAL(wp)                               ::  horizon       !< highest horizon found after raytracing (z/hdist)
7778      INTEGER(iwp)                           ::  i, k, l, d
7779      INTEGER(iwp)                           ::  seldim       !< dimension to be incremented
7780      REAL(wp), DIMENSION(2)                 ::  yxorigin     !< horizontal copy of origin (y,x)
7781      REAL(wp)                               ::  distance     !< euclidean along path
7782      REAL(wp)                               ::  lastdist     !< beginning of current crossing
7783      REAL(wp)                               ::  nextdist     !< end of current crossing
7784      REAL(wp)                               ::  crmid        !< midpoint of crossing
7785      REAL(wp)                               ::  horz_entry   !< horizon at entry to column
7786      REAL(wp)                               ::  horz_exit    !< horizon at exit from column
7787      REAL(wp)                               ::  bdydim       !< boundary for current dimension
7788      REAL(wp), DIMENSION(2)                 ::  crossdist    !< distances to boundary for dimensions
7789      REAL(wp), DIMENSION(2)                 ::  dimnextdist  !< distance for each dimension increments
7790      INTEGER(iwp), DIMENSION(2)             ::  column       !< grid column being crossed
7791      INTEGER(iwp), DIMENSION(2)             ::  dimnext      !< next dimension increments along path
7792      INTEGER(iwp), DIMENSION(2)             ::  dimdelta     !< dimension direction = +- 1
7793      INTEGER(iwp)                           ::  px, py       !< number of processors in x and y dir before
7794                                                              !< the processor in the question
7795      INTEGER(iwp)                           ::  ip           !< number of processor where gridbox reside
7796      INTEGER(iwp)                           ::  ig           !< 1D index of gridbox in global 2D array
7797      INTEGER(iwp)                           ::  wcount       !< RMA window item count
7798      INTEGER(iwp)                           ::  maxboxes     !< max no of CSF created
7799      INTEGER(iwp)                           ::  nly          !< maximum  plant canopy height
7800      INTEGER(iwp)                           ::  ntrack
7801     
7802      INTEGER(iwp)                           ::  zb0
7803      INTEGER(iwp)                           ::  zb1
7804      INTEGER(iwp)                           ::  nz
7805      INTEGER(iwp)                           ::  iz
7806      INTEGER(iwp)                           ::  zsgn
7807      INTEGER(iwp)                           ::  lowest_lad   !< lowest column cell for which we need LAD
7808      INTEGER(iwp)                           ::  lastdir      !< wall direction before hitting this column
7809      INTEGER(iwp), DIMENSION(2)             ::  lastcolumn
7810
7811#if defined( __parallel )
7812      INTEGER(MPI_ADDRESS_KIND)              ::  wdisp        !< RMA window displacement
7813#endif
7814     
7815      REAL(wp)                               ::  eps = 1E-10_wp !< epsilon for value comparison
7816      REAL(wp)                               ::  zbottom, ztop !< urban surface boundary in real numbers
7817      REAL(wp)                               ::  zorig         !< z coordinate of ray column entry
7818      REAL(wp)                               ::  zexit         !< z coordinate of ray column exit
7819      REAL(wp)                               ::  qdist         !< ratio of real distance to z coord difference
7820      REAL(wp)                               ::  dxxyy         !< square of real horizontal distance
7821      REAL(wp)                               ::  curtrans      !< transparency of current PC box crossing
7822     
7823
7824     
7825      yxorigin(:) = origin(2:3)
7826      transparency(:) = 1._wp !-- Pre-set the all rays to transparent before reducing
7827      horizon = -HUGE(1._wp)
7828      lowest_free_ray = nrays
7829      IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7830         ALLOCATE(target_surfl(nrays))
7831         target_surfl(:) = -1
7832         lastdir = -999
7833         lastcolumn(:) = -999
7834      ENDIF
7835
7836!--   Determine distance to boundary (in 2D xy)
7837      IF ( yxdir(1) > 0._wp )  THEN
7838         bdydim = ny + .5_wp !< north global boundary
7839         crossdist(1) = (bdydim - yxorigin(1)) / yxdir(1)
7840      ELSEIF ( yxdir(1) == 0._wp )  THEN
7841         crossdist(1) = HUGE(1._wp)
7842      ELSE
7843          bdydim = -.5_wp !< south global boundary
7844          crossdist(1) = (bdydim - yxorigin(1)) / yxdir(1)
7845      ENDIF
7846
7847      IF ( yxdir(2) > 0._wp )  THEN
7848          bdydim = nx + .5_wp !< east global boundary
7849          crossdist(2) = (bdydim - yxorigin(2)) / yxdir(2)
7850      ELSEIF ( yxdir(2) == 0._wp )  THEN
7851         crossdist(2) = HUGE(1._wp)
7852      ELSE
7853          bdydim = -.5_wp !< west global boundary
7854          crossdist(2) = (bdydim - yxorigin(2)) / yxdir(2)
7855      ENDIF
7856      distance = minval(crossdist, 1)
7857
7858      IF ( plant_canopy )  THEN
7859         rt2_track_dist(0) = 0._wp
7860         rt2_track_lad(:,:) = 0._wp
7861         nly = plantt_max - nz_urban_b + 1
7862      ENDIF
7863
7864      lastdist = 0._wp
7865
7866!--   Since all face coordinates have values *.5 and we'd like to use
7867!--   integers, all these have .5 added
7868      DO  d = 1, 2
7869          IF ( yxdir(d) == 0._wp )  THEN
7870              dimnext(d) = HUGE(1_iwp)
7871              dimdelta(d) = HUGE(1_iwp)
7872              dimnextdist(d) = HUGE(1._wp)
7873          ELSE IF ( yxdir(d) > 0._wp )  THEN
7874              dimnext(d) = FLOOR(yxorigin(d) + .5_wp) + 1
7875              dimdelta(d) = 1
7876              dimnextdist(d) = (dimnext(d) - .5_wp - yxorigin(d)) / yxdir(d)
7877          ELSE
7878              dimnext(d) = CEILING(yxorigin(d) + .5_wp) - 1
7879              dimdelta(d) = -1
7880              dimnextdist(d) = (dimnext(d) - .5_wp - yxorigin(d)) / yxdir(d)
7881          ENDIF
7882      ENDDO
7883
7884      ntrack = 0
7885      DO
7886!--      along what dimension will the next wall crossing be?
7887         seldim = minloc(dimnextdist, 1)
7888         nextdist = dimnextdist(seldim)
7889         IF ( nextdist > distance )  nextdist = distance
7890
7891         IF ( nextdist > lastdist )  THEN
7892            ntrack = ntrack + 1
7893            crmid = (lastdist + nextdist) * .5_wp
7894            column = NINT(yxorigin(:) + yxdir(:) * crmid, iwp)
7895
7896!--         calculate index of the grid with global indices (column(1),column(2))
7897!--         in the array nzterr and plantt and id of the coresponding processor
7898            px = column(2)/nnx
7899            py = column(1)/nny
7900            ip = px*pdims(2)+py
7901            ig = ip*nnx*nny + (column(2)-px*nnx)*nny + column(1)-py*nny
7902
7903            IF ( lastdist == 0._wp )  THEN
7904               horz_entry = -HUGE(1._wp)
7905            ELSE
7906               horz_entry = (REAL(nzterr(ig), wp) + .5_wp - origin(1)) / lastdist
7907            ENDIF
7908            horz_exit = (REAL(nzterr(ig), wp) + .5_wp - origin(1)) / nextdist
7909
7910            IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7911!
7912!--            Identify vertical obstacles hit by rays in current column
7913               DO WHILE ( lowest_free_ray > 0 )
7914                  IF ( zdirs(lowest_free_ray) > horz_entry )  EXIT
7915!
7916!--               This may only happen after 1st column, so lastdir and lastcolumn are valid
7917                  CALL request_itarget(lastdir,                                         &
7918                        CEILING(-0.5_wp + origin(1) + zdirs(lowest_free_ray)*lastdist), &
7919                        lastcolumn(1), lastcolumn(2),                                   &
7920                        target_surfl(lowest_free_ray), target_procs(lowest_free_ray))
7921                  lowest_free_ray = lowest_free_ray - 1
7922               ENDDO
7923!
7924!--            Identify horizontal obstacles hit by rays in current column
7925               DO WHILE ( lowest_free_ray > 0 )
7926                  IF ( zdirs(lowest_free_ray) > horz_exit )  EXIT
7927                  CALL request_itarget(iup_u, nzterr(ig)+1, column(1), column(2), &
7928                                       target_surfl(lowest_free_ray),           &
7929                                       target_procs(lowest_free_ray))
7930                  lowest_free_ray = lowest_free_ray - 1
7931               ENDDO
7932            ENDIF
7933
7934            horizon = MAX(horizon, horz_entry, horz_exit)
7935
7936            IF ( plant_canopy )  THEN
7937               rt2_track(:, ntrack) = column(:)
7938               rt2_track_dist(ntrack) = nextdist
7939            ENDIF
7940         ENDIF
7941
7942         IF ( nextdist + eps >= distance )  EXIT
7943
7944         IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7945!
7946!--         Save wall direction of coming building column (= this air column)
7947            IF ( seldim == 1 )  THEN
7948               IF ( dimdelta(seldim) == 1 )  THEN
7949                  lastdir = isouth_u
7950               ELSE
7951                  lastdir = inorth_u
7952               ENDIF
7953            ELSE
7954               IF ( dimdelta(seldim) == 1 )  THEN
7955                  lastdir = iwest_u
7956               ELSE
7957                  lastdir = ieast_u
7958               ENDIF
7959            ENDIF
7960            lastcolumn = column
7961         ENDIF
7962         lastdist = nextdist
7963         dimnext(seldim) = dimnext(seldim) + dimdelta(seldim)
7964         dimnextdist(seldim) = (dimnext(seldim) - .5_wp - yxorigin(seldim)) / yxdir(seldim)
7965      ENDDO
7966
7967      IF ( plant_canopy )  THEN
7968!--      Request LAD WHERE applicable
7969!--     
7970#if defined( __parallel )
7971         IF ( raytrace_mpi_rma )  THEN
7972!--         send requests for lad_s to appropriate processor
7973            !CALL cpu_log( log_point_s(77), 'usm_init_rma', 'start' )
7974            DO  i = 1, ntrack
7975               px = rt2_track(2,i)/nnx
7976               py = rt2_track(1,i)/nny
7977               ip = px*pdims(2)+py
7978               ig = ip*nnx*nny + (rt2_track(2,i)-px*nnx)*nny + rt2_track(1,i)-py*nny
7979
7980               IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7981!
7982!--               For fixed view resolution, we need plant canopy even for rays
7983!--               to opposing surfaces
7984                  lowest_lad = nzterr(ig) + 1
7985               ELSE
7986!
7987!--               We only need LAD for rays directed above horizon (to sky)
7988                  lowest_lad = CEILING( -0.5_wp + origin(1) +            &
7989                                    MIN( horizon * rt2_track_dist(i-1),  & ! entry
7990                                         horizon * rt2_track_dist(i)   ) ) ! exit
7991               ENDIF
7992!
7993!--            Skip asking for LAD where all plant canopy is under requested level
7994               IF ( plantt(ig) < lowest_lad )  CYCLE
7995
7996               wdisp = (rt2_track(2,i)-px*nnx)*(nny*nz_plant) + (rt2_track(1,i)-py*nny)*nz_plant + lowest_lad-nz_urban_b
7997               wcount = plantt(ig)-lowest_lad+1
7998               ! TODO send request ASAP - even during raytracing
7999               CALL MPI_Get(rt2_track_lad(lowest_lad:plantt(ig), i), wcount, MPI_REAL, ip,    &
8000                            wdisp, wcount, MPI_REAL, win_lad, ierr)
8001               IF ( ierr /= 0 )  THEN
8002                  WRITE(9,*) 'Error MPI_Get2:', ierr, rt2_track_lad(lowest_lad:plantt(ig), i), &
8003                             wcount, ip, wdisp, win_lad
8004                  FLUSH(9)
8005               ENDIF
8006            ENDDO
8007
8008!--         wait for all pending local requests complete
8009            ! TODO WAIT selectively for each column later when needed
8010            CALL MPI_Win_flush_local_all(win_lad, ierr)
8011            IF ( ierr /= 0 )  THEN
8012               WRITE(9,*) 'Error MPI_Win_flush_local_all2:', ierr, win_lad
8013               FLUSH(9)
8014            ENDIF
8015            !CALL cpu_log( log_point_s(77), 'usm_init_rma', 'stop' )
8016
8017         ELSE ! raytrace_mpi_rma = .F.
8018            DO  i = 1, ntrack
8019               px = rt2_track(2,i)/nnx
8020               py = rt2_track(1,i)/nny
8021               ip = px*pdims(2)+py
8022               ig = ip*nnx*nny*nz_plant + (rt2_track(2,i)-px*nnx)*(nny*nz_plant) + (rt2_track(1,i)-py*nny)*nz_plant
8023               rt2_track_lad(nz_urban_b:plantt_max, i) = sub_lad_g(ig:ig+nly-1)
8024            ENDDO
8025         ENDIF
8026#else
8027         DO  i = 1, ntrack
8028            rt2_track_lad(nz_urban_b:plantt_max, i) = sub_lad(rt2_track(1,i), rt2_track(2,i), nz_urban_b:plantt_max)
8029         ENDDO
8030#endif
8031      ENDIF ! plant_canopy
8032
8033      IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
8034#if defined( __parallel )
8035!--      wait for all gridsurf requests to complete
8036         CALL MPI_Win_flush_local_all(win_gridsurf, ierr)
8037         IF ( ierr /= 0 )  THEN
8038            WRITE(9,*) 'Error MPI_Win_flush_local_all3:', ierr, win_gridsurf
8039            FLUSH(9)
8040         ENDIF
8041#endif
8042!
8043!--      recalculate local surf indices into global ones
8044         DO i = 1, nrays
8045            IF ( target_surfl(i) == -1 )  THEN
8046               itarget(i) = -1
8047            ELSE
8048               itarget(i) = target_surfl(i) + surfstart(target_procs(i))
8049            ENDIF
8050         ENDDO
8051         
8052         DEALLOCATE( target_surfl )
8053         
8054      ELSE
8055         itarget(:) = -1
8056      ENDIF ! rad_angular_discretization
8057
8058      IF ( plant_canopy )  THEN
8059!--      Skip the PCB around origin if requested (for MRT, the PCB might not be there)
8060!--     
8061         IF ( skip_1st_pcb  .AND.  NINT(origin(1)) <= plantt_max )  THEN
8062            rt2_track_lad(NINT(origin(1), iwp), 1) = 0._wp
8063         ENDIF
8064
8065!--      Assert that we have space allocated for CSFs
8066!--     
8067         maxboxes = (ntrack + MAX(CEILING(origin(1)-.5_wp) - nz_urban_b,          &
8068                                  nz_urban_t - CEILING(origin(1)-.5_wp))) * nrays
8069         IF ( ncsfl + maxboxes > ncsfla )  THEN
8070!--         use this code for growing by fixed exponential increments (equivalent to case where ncsfl always increases by 1)
8071!--         k = CEILING(grow_factor ** real(CEILING(log(real(ncsfl + maxboxes, kind=wp)) &
8072!--                                                / log(grow_factor)), kind=wp))
8073!--         or use this code to simply always keep some extra space after growing
8074            k = CEILING(REAL(ncsfl + maxboxes, kind=wp) * grow_factor)
8075            CALL merge_and_grow_csf(k)
8076         ENDIF
8077
8078!--      Calculate transparencies and store new CSFs
8079!--     
8080         zbottom = REAL(nz_urban_b, wp) - .5_wp
8081         ztop = REAL(plantt_max, wp) + .5_wp
8082
8083!--      Reverse direction of radiation (face->sky), only when calc_svf
8084!--     
8085         IF ( calc_svf )  THEN
8086            DO  i = 1, ntrack ! for each column
8087               dxxyy = ((dy*yxdir(1))**2 + (dx*yxdir(2))**2) * (rt2_track_dist(i)-rt2_track_dist(i-1))**2
8088               px = rt2_track(2,i)/nnx
8089               py = rt2_track(1,i)/nny
8090               ip = px*pdims(2)+py
8091
8092               DO  k = 1, nrays ! for each ray
8093!
8094!--               NOTE 6778:
8095!--               With traditional svf discretization, CSFs under the horizon
8096!--               (i.e. for surface to surface radiation)  are created in
8097!--               raytrace(). With rad_angular_discretization, we must create
8098!--               CSFs under horizon only for one direction, otherwise we would
8099!--               have duplicate amount of energy. Although we could choose
8100!--               either of the two directions (they differ only by
8101!--               discretization error with no bias), we choose the the backward
8102!--               direction, because it tends to cumulate high canopy sink
8103!--               factors closer to raytrace origin, i.e. it should potentially
8104!--               cause less moiree.
8105                  IF ( .NOT. rad_angular_discretization )  THEN
8106                     IF ( zdirs(k) <= horizon )  CYCLE
8107                  ENDIF
8108
8109                  zorig = origin(1) + zdirs(k) * rt2_track_dist(i-1)
8110                  IF ( zorig <= zbottom  .OR.  zorig >= ztop )  CYCLE
8111
8112                  zsgn = INT(SIGN(1._wp, zdirs(k)), iwp)
8113                  rt2_dist(1) = 0._wp
8114                  IF ( zdirs(k) == 0._wp )  THEN ! ray is exactly horizontal
8115                     nz = 2
8116                     rt2_dist(nz) = SQRT(dxxyy)
8117                     iz = CEILING(-.5_wp + zorig, iwp)
8118                  ELSE
8119                     zexit = MIN(MAX(origin(1) + zdirs(k) * rt2_track_dist(i), zbottom), ztop)
8120
8121                     zb0 = FLOOR(  zorig * zsgn - .5_wp) + 1  ! because it must be greater than orig
8122                     zb1 = CEILING(zexit * zsgn - .5_wp) - 1  ! because it must be smaller than exit
8123                     nz = MAX(zb1 - zb0 + 3, 2)
8124                     rt2_dist(nz) = SQRT(((zexit-zorig)*dz(1))**2 + dxxyy)
8125                     qdist = rt2_dist(nz) / (zexit-zorig)
8126                     rt2_dist(2:nz-1) = (/( ((REAL(l, wp) + .5_wp) * zsgn - zorig) * qdist , l = zb0, zb1 )/)
8127                     iz = zb0 * zsgn
8128                  ENDIF
8129
8130                  DO  l = 2, nz
8131                     IF ( rt2_track_lad(iz, i) > 0._wp )  THEN
8132                        curtrans = exp(-ext_coef * rt2_track_lad(iz, i) * (rt2_dist(l)-rt2_dist(l-1)))
8133
8134                        IF ( create_csf )  THEN
8135                           ncsfl = ncsfl + 1
8136                           acsf(ncsfl)%ip = ip
8137                           acsf(ncsfl)%itx = rt2_track(2,i)
8138                           acsf(ncsfl)%ity = rt2_track(1,i)
8139                           acsf(ncsfl)%itz = iz
8140                           acsf(ncsfl)%isurfs = iorig
8141                           acsf(ncsfl)%rcvf = (1._wp - curtrans)*transparency(k)*vffrac(k)
8142                        ENDIF
8143
8144                        transparency(k) = transparency(k) * curtrans
8145                     ENDIF
8146                     iz = iz + zsgn
8147                  ENDDO ! l = 1, nz - 1
8148               ENDDO ! k = 1, nrays
8149            ENDDO ! i = 1, ntrack
8150
8151            transparency(1:lowest_free_ray) = 1._wp !-- Reset rays above horizon to transparent (see NOTE 6778)
8152         ENDIF
8153
8154!--      Forward direction of radiation (sky->face), always
8155!--     
8156         DO  i = ntrack, 1, -1 ! for each column backwards
8157            dxxyy = ((dy*yxdir(1))**2 + (dx*yxdir(2))**2) * (rt2_track_dist(i)-rt2_track_dist(i-1))**2
8158            px = rt2_track(2,i)/nnx
8159            py = rt2_track(1,i)/nny
8160            ip = px*pdims(2)+py
8161
8162            DO  k = 1, nrays ! for each ray
8163!
8164!--            See NOTE 6778 above
8165               IF ( zdirs(k) <= horizon )  CYCLE
8166
8167               zexit = origin(1) + zdirs(k) * rt2_track_dist(i-1)
8168               IF ( zexit <= zbottom  .OR.  zexit >= ztop )  CYCLE
8169
8170               zsgn = -INT(SIGN(1._wp, zdirs(k)), iwp)
8171               rt2_dist(1) = 0._wp
8172               IF ( zdirs(k) == 0._wp )  THEN ! ray is exactly horizontal
8173                  nz = 2
8174                  rt2_dist(nz) = SQRT(dxxyy)
8175                  iz = NINT(zexit, iwp)
8176               ELSE
8177                  zorig = MIN(MAX(origin(1) + zdirs(k) * rt2_track_dist(i), zbottom), ztop)
8178
8179                  zb0 = FLOOR(  zorig * zsgn - .5_wp) + 1  ! because it must be greater than orig
8180                  zb1 = CEILING(zexit * zsgn - .5_wp) - 1  ! because it must be smaller than exit
8181                  nz = MAX(zb1 - zb0 + 3, 2)
8182                  rt2_dist(nz) = SQRT(((zexit-zorig)*dz(1))**2 + dxxyy)
8183                  qdist = rt2_dist(nz) / (zexit-zorig)
8184                  rt2_dist(2:nz-1) = (/( ((REAL(l, wp) + .5_wp) * zsgn - zorig) * qdist , l = zb0, zb1 )/)
8185                  iz = zb0 * zsgn
8186               ENDIF
8187
8188               DO  l = 2, nz
8189                  IF ( rt2_track_lad(iz, i) > 0._wp )  THEN
8190                     curtrans = exp(-ext_coef * rt2_track_lad(iz, i) * (rt2_dist(l)-rt2_dist(l-1)))
8191
8192                     IF ( create_csf )  THEN
8193                        ncsfl = ncsfl + 1
8194                        acsf(ncsfl)%ip = ip
8195                        acsf(ncsfl)%itx = rt2_track(2,i)
8196                        acsf(ncsfl)%ity = rt2_track(1,i)
8197                        acsf(ncsfl)%itz = iz
8198                        IF ( itarget(k) /= -1 ) STOP 1 !FIXME remove after test
8199                        acsf(ncsfl)%isurfs = -1
8200                        acsf(ncsfl)%rcvf = (1._wp - curtrans)*transparency(k)*aorig*vffrac(k)
8201                     ENDIF  ! create_csf
8202
8203                     transparency(k) = transparency(k) * curtrans
8204                  ENDIF
8205                  iz = iz + zsgn
8206               ENDDO ! l = 1, nz - 1
8207            ENDDO ! k = 1, nrays
8208         ENDDO ! i = 1, ntrack
8209      ENDIF ! plant_canopy
8210
8211      IF ( .NOT. (rad_angular_discretization  .AND.  calc_svf) )  THEN
8212!
8213!--      Just update lowest_free_ray according to horizon
8214         DO WHILE ( lowest_free_ray > 0 )
8215            IF ( zdirs(lowest_free_ray) > horizon )  EXIT
8216            lowest_free_ray = lowest_free_ray - 1
8217         ENDDO
8218      ENDIF
8219
8220   CONTAINS
8221
8222      SUBROUTINE request_itarget( d, z, y, x, isurfl, iproc )
8223
8224         INTEGER(iwp), INTENT(in)            ::  d, z, y, x
8225         INTEGER(iwp), TARGET, INTENT(out)   ::  isurfl
8226         INTEGER(iwp), INTENT(out)           ::  iproc
8227#if defined( __parallel )
8228#else
8229         INTEGER(iwp)                        ::  target_displ  !< index of the grid in the local gridsurf array
8230#endif
8231         INTEGER(iwp)                        ::  px, py        !< number of processors in x and y direction
8232                                                               !< before the processor in the question
8233#if defined( __parallel )
8234         INTEGER(KIND=MPI_ADDRESS_KIND)      ::  target_displ  !< index of the grid in the local gridsurf array
8235
8236!
8237!--      Calculate target processor and index in the remote local target gridsurf array
8238         px = x / nnx
8239         py = y / nny
8240         iproc = px * pdims(2) + py
8241         target_displ = ((x-px*nnx) * nny + y - py*nny ) * nz_urban * nsurf_type_u +&
8242                        ( z-nz_urban_b ) * nsurf_type_u + d
8243!
8244!--      Send MPI_Get request to obtain index target_surfl(i)
8245         CALL MPI_GET( isurfl, 1, MPI_INTEGER, iproc, target_displ,            &
8246                       1, MPI_INTEGER, win_gridsurf, ierr)
8247         IF ( ierr /= 0 )  THEN
8248            WRITE( 9,* ) 'Error MPI_Get3:', ierr, isurfl, iproc, target_displ, &
8249                         win_gridsurf
8250            FLUSH( 9 )
8251         ENDIF
8252#else
8253!--      set index target_surfl(i)
8254         isurfl = gridsurf(d,z,y,x)
8255#endif
8256
8257      END SUBROUTINE request_itarget
8258
8259   END SUBROUTINE raytrace_2d
8260 
8261
8262!------------------------------------------------------------------------------!
8263!
8264! Description:
8265! ------------
8266!> Calculates apparent solar positions for all timesteps and stores discretized
8267!> positions.
8268!------------------------------------------------------------------------------!
8269   SUBROUTINE radiation_presimulate_solar_pos
8270
8271      IMPLICIT NONE
8272
8273      INTEGER(iwp)                              ::  it, i, j
8274      INTEGER(iwp)                              ::  day_of_month_prev,month_of_year_prev
8275      REAL(wp)                                  ::  tsrp_prev
8276      REAL(wp)                                  ::  simulated_time_prev
8277      REAL(wp), DIMENSION(:,:), ALLOCATABLE     ::  dsidir_tmp       !< dsidir_tmp[:,i] = unit vector of i-th
8278                                                                     !< appreant solar direction
8279
8280      ALLOCATE ( dsidir_rev(0:raytrace_discrete_elevs/2-1,                 &
8281                            0:raytrace_discrete_azims-1) )
8282      dsidir_rev(:,:) = -1
8283      ALLOCATE ( dsidir_tmp(3,                                             &
8284                     raytrace_discrete_elevs/2*raytrace_discrete_azims) )
8285      ndsidir = 0
8286
8287!
8288!--   We will artificialy update time_since_reference_point and return to
8289!--   true value later
8290      tsrp_prev = time_since_reference_point
8291      simulated_time_prev = simulated_time
8292      day_of_month_prev = day_of_month
8293      month_of_year_prev = month_of_year
8294      sun_direction = .TRUE.
8295
8296!
8297!--   initialize the simulated_time
8298      simulated_time = 0._wp
8299!
8300!--   Process spinup time if configured
8301      IF ( spinup_time > 0._wp )  THEN
8302         DO  it = 0, CEILING(spinup_time / dt_spinup)
8303            time_since_reference_point = -spinup_time + REAL(it, wp) * dt_spinup
8304            simulated_time = simulated_time + dt_spinup
8305            CALL simulate_pos
8306         ENDDO
8307      ENDIF
8308!
8309!--   Process simulation time
8310      DO  it = 0, CEILING(( end_time - spinup_time ) / dt_radiation)
8311         time_since_reference_point = REAL(it, wp) * dt_radiation
8312         simulated_time = simulated_time + dt_radiation
8313         CALL simulate_pos
8314      ENDDO
8315!
8316!--   Return date and time to its original values
8317      time_since_reference_point = tsrp_prev
8318      simulated_time = simulated_time_prev
8319      day_of_month = day_of_month_prev
8320      month_of_year = month_of_year_prev
8321      CALL init_date_and_time
8322
8323!--   Allocate global vars which depend on ndsidir
8324      ALLOCATE ( dsidir ( 3, ndsidir ) )
8325      dsidir(:,:) = dsidir_tmp(:, 1:ndsidir)
8326      DEALLOCATE ( dsidir_tmp )
8327
8328      ALLOCATE ( dsitrans(nsurfl, ndsidir) )
8329      ALLOCATE ( dsitransc(npcbl, ndsidir) )
8330      IF ( nmrtbl > 0 )  ALLOCATE ( mrtdsit(nmrtbl, ndsidir) )
8331
8332      WRITE ( message_string, * ) 'Precalculated', ndsidir, ' solar positions', &
8333                                  'from', it, ' timesteps.'
8334      CALL message( 'radiation_presimulate_solar_pos', 'UI0013', 0, 0, 0, 6, 0 )
8335
8336      CONTAINS
8337
8338      !------------------------------------------------------------------------!
8339      ! Description:
8340      ! ------------
8341      !> Simuates a single position
8342      !------------------------------------------------------------------------!
8343      SUBROUTINE simulate_pos
8344         IMPLICIT NONE
8345!
8346!--      Update apparent solar position based on modified t_s_r_p
8347         CALL calc_zenith
8348         IF ( cos_zenith > 0 )  THEN
8349!--         
8350!--         Identify solar direction vector (discretized number) 1)
8351            i = MODULO(NINT(ATAN2(sun_dir_lon, sun_dir_lat)               &
8352                            / (2._wp*pi) * raytrace_discrete_azims-.5_wp, iwp), &
8353                       raytrace_discrete_azims)
8354            j = FLOOR(ACOS(cos_zenith) / pi * raytrace_discrete_elevs)
8355            IF ( dsidir_rev(j, i) == -1 )  THEN
8356               ndsidir = ndsidir + 1
8357               dsidir_tmp(:, ndsidir) =                                              &
8358                     (/ COS((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs), &
8359                        SIN((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs)  &
8360                      * COS((REAL(i,wp)+.5_wp) * 2_wp*pi / raytrace_discrete_azims), &
8361                        SIN((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs)  &
8362                      * SIN((REAL(i,wp)+.5_wp) * 2_wp*pi / raytrace_discrete_azims) /)
8363               dsidir_rev(j, i) = ndsidir
8364            ENDIF
8365         ENDIF
8366      END SUBROUTINE simulate_pos
8367
8368   END SUBROUTINE radiation_presimulate_solar_pos
8369
8370
8371
8372!------------------------------------------------------------------------------!
8373! Description:
8374! ------------
8375!> Determines whether two faces are oriented towards each other. Since the
8376!> surfaces follow the gird box surfaces, it checks first whether the two surfaces
8377!> are directed in the same direction, then it checks if the two surfaces are
8378!> located in confronted direction but facing away from each other, e.g. <--| |-->
8379!------------------------------------------------------------------------------!
8380    PURE LOGICAL FUNCTION surface_facing(x, y, z, d, x2, y2, z2, d2)
8381        IMPLICIT NONE
8382        INTEGER(iwp),   INTENT(in)  :: x, y, z, d, x2, y2, z2, d2
8383     
8384        surface_facing = .FALSE.
8385
8386!-- first check: are the two surfaces directed in the same direction
8387        IF ( (d==iup_u  .OR.  d==iup_l )                             &
8388             .AND. (d2==iup_u  .OR. d2==iup_l) ) RETURN
8389        IF ( (d==isouth_u  .OR.  d==isouth_l ) &
8390             .AND.  (d2==isouth_u  .OR.  d2==isouth_l) ) RETURN
8391        IF ( (d==inorth_u  .OR.  d==inorth_l ) &
8392             .AND.  (d2==inorth_u  .OR.  d2==inorth_l) ) RETURN
8393        IF ( (d==iwest_u  .OR.  d==iwest_l )     &
8394             .AND.  (d2==iwest_u  .OR.  d2==iwest_l ) ) RETURN
8395        IF ( (d==ieast_u  .OR.  d==ieast_l )     &
8396             .AND.  (d2==ieast_u  .OR.  d2==ieast_l ) ) RETURN
8397
8398!-- second check: are surfaces facing away from each other
8399        SELECT CASE (d)
8400            CASE (iup_u, iup_l)                     !< upward facing surfaces
8401                IF ( z2 < z ) RETURN
8402            CASE (isouth_u, isouth_l)               !< southward facing surfaces
8403                IF ( y2 > y ) RETURN
8404            CASE (inorth_u, inorth_l)               !< northward facing surfaces
8405                IF ( y2 < y ) RETURN
8406            CASE (iwest_u, iwest_l)                 !< westward facing surfaces
8407                IF ( x2 > x ) RETURN
8408            CASE (ieast_u, ieast_l)                 !< eastward facing surfaces
8409                IF ( x2 < x ) RETURN
8410        END SELECT
8411
8412        SELECT CASE (d2)
8413            CASE (iup_u)                            !< ground, roof
8414                IF ( z < z2 ) RETURN
8415            CASE (isouth_u, isouth_l)               !< south facing
8416                IF ( y > y2 ) RETURN
8417            CASE (inorth_u, inorth_l)               !< north facing
8418                IF ( y < y2 ) RETURN
8419            CASE (iwest_u, iwest_l)                 !< west facing
8420                IF ( x > x2 ) RETURN
8421            CASE (ieast_u, ieast_l)                 !< east facing
8422                IF ( x < x2 ) RETURN
8423            CASE (-1)
8424                CONTINUE
8425        END SELECT
8426
8427        surface_facing = .TRUE.
8428       
8429    END FUNCTION surface_facing
8430
8431
8432!------------------------------------------------------------------------------!
8433!
8434! Description:
8435! ------------
8436!> Reads svf, svfsurf, csf, csfsurf and mrt factors data from saved file
8437!> SVF means sky view factors and CSF means canopy sink factors
8438!------------------------------------------------------------------------------!
8439    SUBROUTINE radiation_read_svf
8440
8441       IMPLICIT NONE
8442       
8443       CHARACTER(rad_version_len)   :: rad_version_field
8444       
8445       INTEGER(iwp)                 :: i
8446       INTEGER(iwp)                 :: ndsidir_from_file = 0
8447       INTEGER(iwp)                 :: npcbl_from_file = 0
8448       INTEGER(iwp)                 :: nsurfl_from_file = 0
8449       INTEGER(iwp)                 :: nmrtbl_from_file = 0
8450
8451
8452       CALL location_message( 'reading view factors for radiation interaction', 'start' )
8453
8454       DO  i = 0, io_blocks-1
8455          IF ( i == io_group )  THEN
8456
8457!
8458!--          numprocs_previous_run is only known in case of reading restart
8459!--          data. If a new initial run which reads svf data is started the
8460!--          following query will be skipped
8461             IF ( initializing_actions == 'read_restart_data' ) THEN
8462
8463                IF ( numprocs_previous_run /= numprocs ) THEN
8464                   WRITE( message_string, * ) 'A different number of ',        &
8465                                              'processors between the run ',   &
8466                                              'that has written the svf data ',&
8467                                              'and the one that will read it ',&
8468                                              'is not allowed' 
8469                   CALL message( 'check_open', 'PA0491', 1, 2, 0, 6, 0 )
8470                ENDIF
8471
8472             ENDIF
8473             
8474!
8475!--          Open binary file
8476             CALL check_open( 88 )
8477
8478!
8479!--          read and check version
8480             READ ( 88 ) rad_version_field
8481             IF ( TRIM(rad_version_field) /= TRIM(rad_version) )  THEN
8482                 WRITE( message_string, * ) 'Version of binary SVF file "',    &
8483                             TRIM(rad_version_field), '" does not match ',     &
8484                             'the version of model "', TRIM(rad_version), '"'
8485                 CALL message( 'radiation_read_svf', 'PA0482', 1, 2, 0, 6, 0 )
8486             ENDIF
8487             
8488!
8489!--          read nsvfl, ncsfl, nsurfl, nmrtf
8490             READ ( 88 ) nsvfl, ncsfl, nsurfl_from_file, npcbl_from_file,      &
8491                         ndsidir_from_file, nmrtbl_from_file, nmrtf
8492             
8493             IF ( nsvfl < 0  .OR.  ncsfl < 0 )  THEN
8494                 WRITE( message_string, * ) 'Wrong number of SVF or CSF'
8495                 CALL message( 'radiation_read_svf', 'PA0483', 1, 2, 0, 6, 0 )
8496             ELSE
8497                 WRITE(debug_string,*)   'Number of SVF, CSF, and nsurfl ',    &
8498                                         'to read', nsvfl, ncsfl,              &
8499                                         nsurfl_from_file
8500                 IF ( debug_output )  CALL debug_message( debug_string, 'info' )
8501             ENDIF
8502             
8503             IF ( nsurfl_from_file /= nsurfl )  THEN
8504                 WRITE( message_string, * ) 'nsurfl from SVF file does not ',  &
8505                                            'match calculated nsurfl from ',   &
8506                                            'radiation_interaction_init'
8507                 CALL message( 'radiation_read_svf', 'PA0490', 1, 2, 0, 6, 0 )
8508             ENDIF
8509             
8510             IF ( npcbl_from_file /= npcbl )  THEN
8511                 WRITE( message_string, * ) 'npcbl from SVF file does not ',   &
8512                                            'match calculated npcbl from ',    &
8513                                            'radiation_interaction_init'
8514                 CALL message( 'radiation_read_svf', 'PA0493', 1, 2, 0, 6, 0 )
8515             ENDIF
8516             
8517             IF ( ndsidir_from_file /= ndsidir )  THEN
8518                 WRITE( message_string, * ) 'ndsidir from SVF file does not ', &
8519                                            'match calculated ndsidir from ',  &
8520                                            'radiation_presimulate_solar_pos'
8521                 CALL message( 'radiation_read_svf', 'PA0494', 1, 2, 0, 6, 0 )
8522             ENDIF
8523             IF ( nmrtbl_from_file /= nmrtbl )  THEN
8524                 WRITE( message_string, * ) 'nmrtbl from SVF file does not ',  &
8525                                            'match calculated nmrtbl from ',   &
8526                                            'radiation_interaction_init'
8527                 CALL message( 'radiation_read_svf', 'PA0494', 1, 2, 0, 6, 0 )
8528             ELSE
8529                 WRITE(debug_string,*) 'Number of nmrtf to read ', nmrtf
8530                 IF ( debug_output )  CALL debug_message( debug_string, 'info' )
8531             ENDIF
8532             
8533!
8534!--          Arrays skyvf, skyvft, dsitrans and dsitransc are allready
8535!--          allocated in radiation_interaction_init and
8536!--          radiation_presimulate_solar_pos
8537             IF ( nsurfl > 0 )  THEN
8538                READ(88) skyvf
8539                READ(88) skyvft
8540                READ(88) dsitrans 
8541             ENDIF
8542             
8543             IF ( plant_canopy  .AND.  npcbl > 0 ) THEN
8544                READ ( 88 )  dsitransc
8545             ENDIF
8546             
8547!
8548!--          The allocation of svf, svfsurf, csf, csfsurf, mrtf, mrtft, and
8549!--          mrtfsurf happens in routine radiation_calc_svf which is not
8550!--          called if the program enters radiation_read_svf. Therefore
8551!--          these arrays has to allocate in the following
8552             IF ( nsvfl > 0 )  THEN
8553                ALLOCATE( svf(ndsvf,nsvfl) )
8554                ALLOCATE( svfsurf(idsvf,nsvfl) )
8555                READ(88) svf
8556                READ(88) svfsurf
8557             ENDIF
8558
8559             IF ( plant_canopy  .AND.  ncsfl > 0 )  THEN
8560                ALLOCATE( csf(ndcsf,ncsfl) )
8561                ALLOCATE( csfsurf(idcsf,ncsfl) )
8562                READ(88) csf
8563                READ(88) csfsurf
8564             ENDIF
8565
8566             IF ( nmrtbl > 0 )  THEN
8567                READ(88) mrtsky
8568                READ(88) mrtskyt
8569                READ(88) mrtdsit
8570             ENDIF
8571
8572             IF ( nmrtf > 0 )  THEN
8573                ALLOCATE ( mrtf(nmrtf) )
8574                ALLOCATE ( mrtft(nmrtf) )
8575                ALLOCATE ( mrtfsurf(2,nmrtf) )
8576                READ(88) mrtf
8577                READ(88) mrtft
8578                READ(88) mrtfsurf
8579             ENDIF
8580             
8581!
8582!--          Close binary file                 
8583             CALL close_file( 88 )
8584               
8585          ENDIF
8586#if defined( __parallel )
8587          CALL MPI_BARRIER( comm2d, ierr )
8588#endif
8589       ENDDO
8590
8591       CALL location_message( 'reading view factors for radiation interaction', 'finished' )
8592
8593
8594    END SUBROUTINE radiation_read_svf
8595
8596
8597!------------------------------------------------------------------------------!
8598!
8599! Description:
8600! ------------
8601!> Subroutine stores svf, svfsurf, csf, csfsurf and mrt data to a file.
8602!------------------------------------------------------------------------------!
8603    SUBROUTINE radiation_write_svf
8604
8605       IMPLICIT NONE
8606       
8607       INTEGER(iwp)        :: i
8608
8609
8610       CALL location_message( 'writing view factors for radiation interaction', 'start' )
8611
8612       DO  i = 0, io_blocks-1
8613          IF ( i == io_group )  THEN
8614!
8615!--          Open binary file
8616             CALL check_open( 89 )
8617
8618             WRITE ( 89 )  rad_version
8619             WRITE ( 89 )  nsvfl, ncsfl, nsurfl, npcbl, ndsidir, nmrtbl, nmrtf
8620             IF ( nsurfl > 0 ) THEN
8621                WRITE ( 89 )  skyvf
8622                WRITE ( 89 )  skyvft
8623                WRITE ( 89 )  dsitrans
8624             ENDIF
8625             IF ( npcbl > 0 ) THEN
8626                WRITE ( 89 )  dsitransc
8627             ENDIF
8628             IF ( nsvfl > 0 ) THEN
8629                WRITE ( 89 )  svf
8630                WRITE ( 89 )  svfsurf
8631             ENDIF
8632             IF ( plant_canopy  .AND.  ncsfl > 0 )  THEN
8633                 WRITE ( 89 )  csf
8634                 WRITE ( 89 )  csfsurf
8635             ENDIF
8636             IF ( nmrtbl > 0 )  THEN
8637                WRITE ( 89 ) mrtsky
8638                WRITE ( 89 ) mrtskyt
8639                WRITE ( 89 ) mrtdsit
8640             ENDIF
8641             IF ( nmrtf > 0 )  THEN
8642                 WRITE ( 89 )  mrtf
8643                 WRITE ( 89 )  mrtft               
8644                 WRITE ( 89 )  mrtfsurf
8645             ENDIF
8646!
8647!--          Close binary file                 
8648             CALL close_file( 89 )
8649
8650          ENDIF
8651#if defined( __parallel )
8652          CALL MPI_BARRIER( comm2d, ierr )
8653#endif
8654       ENDDO
8655
8656       CALL location_message( 'writing view factors for radiation interaction', 'finished' )
8657
8658
8659    END SUBROUTINE radiation_write_svf
8660
8661
8662!------------------------------------------------------------------------------!
8663!
8664! Description:
8665! ------------
8666!> Block of auxiliary subroutines:
8667!> 1. quicksort and corresponding comparison
8668!> 2. merge_and_grow_csf for implementation of "dynamical growing"
8669!>    array for csf
8670!------------------------------------------------------------------------------!
8671!-- quicksort.f -*-f90-*-
8672!-- Author: t-nissie, adaptation J.Resler
8673!-- License: GPLv3
8674!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8675    RECURSIVE SUBROUTINE quicksort_itarget(itarget, vffrac, ztransp, first, last)
8676        IMPLICIT NONE
8677        INTEGER(iwp), DIMENSION(:), INTENT(INOUT)   :: itarget
8678        REAL(wp), DIMENSION(:), INTENT(INOUT)       :: vffrac, ztransp
8679        INTEGER(iwp), INTENT(IN)                    :: first, last
8680        INTEGER(iwp)                                :: x, t
8681        INTEGER(iwp)                                :: i, j
8682        REAL(wp)                                    :: tr
8683
8684        IF ( first>=last ) RETURN
8685        x = itarget((first+last)/2)
8686        i = first
8687        j = last
8688        DO
8689            DO WHILE ( itarget(i) < x )
8690               i=i+1
8691            ENDDO
8692            DO WHILE ( x < itarget(j) )
8693                j=j-1
8694            ENDDO
8695            IF ( i >= j ) EXIT
8696            t = itarget(i);  itarget(i) = itarget(j);  itarget(j) = t
8697            tr = vffrac(i);  vffrac(i) = vffrac(j);  vffrac(j) = tr
8698            tr = ztransp(i);  ztransp(i) = ztransp(j);  ztransp(j) = tr
8699            i=i+1
8700            j=j-1
8701        ENDDO
8702        IF ( first < i-1 ) CALL quicksort_itarget(itarget, vffrac, ztransp, first, i-1)
8703        IF ( j+1 < last )  CALL quicksort_itarget(itarget, vffrac, ztransp, j+1, last)
8704    END SUBROUTINE quicksort_itarget
8705
8706    PURE FUNCTION svf_lt(svf1,svf2) result (res)
8707      TYPE (t_svf), INTENT(in) :: svf1,svf2
8708      LOGICAL                  :: res
8709      IF ( svf1%isurflt < svf2%isurflt  .OR.    &
8710          (svf1%isurflt == svf2%isurflt  .AND.  svf1%isurfs < svf2%isurfs) )  THEN
8711          res = .TRUE.
8712      ELSE
8713          res = .FALSE.
8714      ENDIF
8715    END FUNCTION svf_lt
8716
8717
8718!-- quicksort.f -*-f90-*-
8719!-- Author: t-nissie, adaptation J.Resler
8720!-- License: GPLv3
8721!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8722    RECURSIVE SUBROUTINE quicksort_svf(svfl, first, last)
8723        IMPLICIT NONE
8724        TYPE(t_svf), DIMENSION(:), INTENT(INOUT)  :: svfl
8725        INTEGER(iwp), INTENT(IN)                  :: first, last
8726        TYPE(t_svf)                               :: x, t
8727        INTEGER(iwp)                              :: i, j
8728
8729        IF ( first>=last ) RETURN
8730        x = svfl( (first+last) / 2 )
8731        i = first
8732        j = last
8733        DO
8734            DO while ( svf_lt(svfl(i),x) )
8735               i=i+1
8736            ENDDO
8737            DO while ( svf_lt(x,svfl(j)) )
8738                j=j-1
8739            ENDDO
8740            IF ( i >= j ) EXIT
8741            t = svfl(i);  svfl(i) = svfl(j);  svfl(j) = t
8742            i=i+1
8743            j=j-1
8744        ENDDO
8745        IF ( first < i-1 ) CALL quicksort_svf(svfl, first, i-1)
8746        IF ( j+1 < last )  CALL quicksort_svf(svfl, j+1, last)
8747    END SUBROUTINE quicksort_svf
8748
8749    PURE FUNCTION csf_lt(csf1,csf2) result (res)
8750      TYPE (t_csf), INTENT(in) :: csf1,csf2
8751      LOGICAL                  :: res
8752      IF ( csf1%ip < csf2%ip  .OR.    &
8753           (csf1%ip == csf2%ip  .AND.  csf1%itx < csf2%itx)  .OR.  &
8754           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity < csf2%ity)  .OR.  &
8755           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity == csf2%ity  .AND.   &
8756            csf1%itz < csf2%itz)  .OR.  &
8757           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity == csf2%ity  .AND.   &
8758            csf1%itz == csf2%itz  .AND.  csf1%isurfs < csf2%isurfs) )  THEN
8759          res = .TRUE.
8760      ELSE
8761          res = .FALSE.
8762      ENDIF
8763    END FUNCTION csf_lt
8764
8765
8766!-- quicksort.f -*-f90-*-
8767!-- Author: t-nissie, adaptation J.Resler
8768!-- License: GPLv3
8769!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8770    RECURSIVE SUBROUTINE quicksort_csf(csfl, first, last)
8771        IMPLICIT NONE
8772        TYPE(t_csf), DIMENSION(:), INTENT(INOUT)  :: csfl
8773        INTEGER(iwp), INTENT(IN)                  :: first, last
8774        TYPE(t_csf)                               :: x, t
8775        INTEGER(iwp)                              :: i, j
8776
8777        IF ( first>=last ) RETURN
8778        x = csfl( (first+last)/2 )
8779        i = first
8780        j = last
8781        DO
8782            DO while ( csf_lt(csfl(i),x) )
8783                i=i+1
8784            ENDDO
8785            DO while ( csf_lt(x,csfl(j)) )
8786                j=j-1
8787            ENDDO
8788            IF ( i >= j ) EXIT
8789            t = csfl(i);  csfl(i) = csfl(j);  csfl(j) = t
8790            i=i+1
8791            j=j-1
8792        ENDDO
8793        IF ( first < i-1 ) CALL quicksort_csf(csfl, first, i-1)
8794        IF ( j+1 < last )  CALL quicksort_csf(csfl, j+1, last)
8795    END SUBROUTINE quicksort_csf
8796
8797   
8798!------------------------------------------------------------------------------!
8799!
8800! Description:
8801! ------------
8802!> Grows the CSF array exponentially after it is full. During that, the ray
8803!> canopy sink factors with common source face and target plant canopy grid
8804!> cell are merged together so that the size doesn't grow out of control.
8805!------------------------------------------------------------------------------!
8806    SUBROUTINE merge_and_grow_csf(newsize)
8807        INTEGER(iwp), INTENT(in)                :: newsize  !< new array size after grow, must be >= ncsfl
8808                                                            !< or -1 to shrink to minimum
8809        INTEGER(iwp)                            :: iread, iwrite
8810        TYPE(t_csf), DIMENSION(:), POINTER      :: acsfnew
8811
8812
8813        IF ( newsize == -1 )  THEN
8814!--         merge in-place
8815            acsfnew => acsf
8816        ELSE
8817!--         allocate new array
8818            IF ( mcsf == 0 )  THEN
8819                ALLOCATE( acsf1(newsize) )
8820                acsfnew => acsf1
8821            ELSE
8822                ALLOCATE( acsf2(newsize) )
8823                acsfnew => acsf2
8824            ENDIF
8825        ENDIF
8826
8827        IF ( ncsfl >= 1 )  THEN
8828!--         sort csf in place (quicksort)
8829            CALL quicksort_csf(acsf,1,ncsfl)
8830
8831!--         while moving to a new array, aggregate canopy sink factor records with identical box & source
8832            acsfnew(1) = acsf(1)
8833            iwrite = 1
8834            DO iread = 2, ncsfl
8835!--             here acsf(kcsf) already has values from acsf(icsf)
8836                IF ( acsfnew(iwrite)%itx == acsf(iread)%itx &
8837                         .AND.  acsfnew(iwrite)%ity == acsf(iread)%ity &
8838                         .AND.  acsfnew(iwrite)%itz == acsf(iread)%itz &
8839                         .AND.  acsfnew(iwrite)%isurfs == acsf(iread)%isurfs )  THEN
8840
8841                    acsfnew(iwrite)%rcvf = acsfnew(iwrite)%rcvf + acsf(iread)%rcvf
8842!--                 advance reading index, keep writing index
8843                ELSE
8844!--                 not identical, just advance and copy
8845                    iwrite = iwrite + 1
8846                    acsfnew(iwrite) = acsf(iread)
8847                ENDIF
8848            ENDDO
8849            ncsfl = iwrite
8850        ENDIF
8851
8852        IF ( newsize == -1 )  THEN
8853!--         allocate new array and copy shrinked data
8854            IF ( mcsf == 0 )  THEN
8855                ALLOCATE( acsf1(ncsfl) )
8856                acsf1(1:ncsfl) = acsf2(1:ncsfl)
8857            ELSE
8858                ALLOCATE( acsf2(ncsfl) )
8859                acsf2(1:ncsfl) = acsf1(1:ncsfl)
8860            ENDIF
8861        ENDIF
8862
8863!--     deallocate old array
8864        IF ( mcsf == 0 )  THEN
8865            mcsf = 1
8866            acsf => acsf1
8867            DEALLOCATE( acsf2 )
8868        ELSE
8869            mcsf = 0
8870            acsf => acsf2
8871            DEALLOCATE( acsf1 )
8872        ENDIF
8873        ncsfla = newsize
8874
8875        IF ( debug_output )  THEN
8876           WRITE( debug_string, '(A,2I12)' ) 'Grow acsf2:', ncsfl, ncsfla
8877           CALL debug_message( debug_string, 'info' )
8878        ENDIF
8879
8880    END SUBROUTINE merge_and_grow_csf
8881
8882   
8883!-- quicksort.f -*-f90-*-
8884!-- Author: t-nissie, adaptation J.Resler
8885!-- License: GPLv3
8886!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8887    RECURSIVE SUBROUTINE quicksort_csf2(kpcsflt, pcsflt, first, last)
8888        IMPLICIT NONE
8889        INTEGER(iwp), DIMENSION(:,:), INTENT(INOUT)  :: kpcsflt
8890        REAL(wp), DIMENSION(:,:), INTENT(INOUT)      :: pcsflt
8891        INTEGER(iwp), INTENT(IN)                     :: first, last
8892        REAL(wp), DIMENSION(ndcsf)                   :: t2
8893        INTEGER(iwp), DIMENSION(kdcsf)               :: x, t1
8894        INTEGER(iwp)                                 :: i, j
8895
8896        IF ( first>=last ) RETURN
8897        x = kpcsflt(:, (first+last)/2 )
8898        i = first
8899        j = last
8900        DO
8901            DO while ( csf_lt2(kpcsflt(:,i),x) )
8902                i=i+1
8903            ENDDO
8904            DO while ( csf_lt2(x,kpcsflt(:,j)) )
8905                j=j-1
8906            ENDDO
8907            IF ( i >= j ) EXIT
8908            t1 = kpcsflt(:,i);  kpcsflt(:,i) = kpcsflt(:,j);  kpcsflt(:,j) = t1
8909            t2 = pcsflt(:,i);  pcsflt(:,i) = pcsflt(:,j);  pcsflt(:,j) = t2
8910            i=i+1
8911            j=j-1
8912        ENDDO
8913        IF ( first < i-1 ) CALL quicksort_csf2(kpcsflt, pcsflt, first, i-1)
8914        IF ( j+1 < last )  CALL quicksort_csf2(kpcsflt, pcsflt, j+1, last)
8915    END SUBROUTINE quicksort_csf2
8916   
8917
8918    PURE FUNCTION csf_lt2(item1, item2) result(res)
8919        INTEGER(iwp), DIMENSION(kdcsf), INTENT(in)  :: item1, item2
8920        LOGICAL                                     :: res
8921        res = ( (item1(3) < item2(3))                                                        &
8922             .OR.  (item1(3) == item2(3)  .AND.  item1(2) < item2(2))                            &
8923             .OR.  (item1(3) == item2(3)  .AND.  item1(2) == item2(2)  .AND.  item1(1) < item2(1)) &
8924             .OR.  (item1(3) == item2(3)  .AND.  item1(2) == item2(2)  .AND.  item1(1) == item2(1) &
8925                 .AND.  item1(4) < item2(4)) )
8926    END FUNCTION csf_lt2
8927
8928    PURE FUNCTION searchsorted(athresh, val) result(ind)
8929        REAL(wp), DIMENSION(:), INTENT(IN)  :: athresh
8930        REAL(wp), INTENT(IN)                :: val
8931        INTEGER(iwp)                        :: ind
8932        INTEGER(iwp)                        :: i
8933
8934        DO i = LBOUND(athresh, 1), UBOUND(athresh, 1)
8935            IF ( val < athresh(i) ) THEN
8936                ind = i - 1
8937                RETURN
8938            ENDIF
8939        ENDDO
8940        ind = UBOUND(athresh, 1)
8941    END FUNCTION searchsorted
8942
8943
8944!------------------------------------------------------------------------------!
8945!
8946! Description:
8947! ------------
8948!> Subroutine for averaging 3D data
8949!------------------------------------------------------------------------------!
8950SUBROUTINE radiation_3d_data_averaging( mode, variable )
8951 
8952
8953    USE control_parameters
8954
8955    USE indices
8956
8957    USE kinds
8958
8959    IMPLICIT NONE
8960
8961    CHARACTER (LEN=*) ::  mode    !<
8962    CHARACTER (LEN=*) :: variable !<
8963
8964    LOGICAL      ::  match_lsm !< flag indicating natural-type surface
8965    LOGICAL      ::  match_usm !< flag indicating urban-type surface
8966   
8967    INTEGER(iwp) ::  i !<
8968    INTEGER(iwp) ::  j !<
8969    INTEGER(iwp) ::  k !<
8970    INTEGER(iwp) ::  l, m !< index of current surface element
8971
8972    INTEGER(iwp)                                       :: ids, idsint_u, idsint_l, isurf
8973    CHARACTER(LEN=varnamelength)                       :: var
8974
8975!-- find the real name of the variable
8976    ids = -1
8977    l = -1
8978    var = TRIM(variable)
8979    DO i = 0, nd-1
8980        k = len(TRIM(var))
8981        j = len(TRIM(dirname(i)))
8982        IF ( k-j+1 >= 1_iwp ) THEN
8983           IF ( TRIM(var(k-j+1:k)) == TRIM(dirname(i)) )  THEN
8984               ids = i
8985               idsint_u = dirint_u(ids)
8986               idsint_l = dirint_l(ids)
8987               var = var(:k-j)
8988               EXIT
8989           ENDIF
8990        ENDIF
8991    ENDDO
8992    IF ( ids == -1 )  THEN
8993        var = TRIM(variable)
8994    ENDIF
8995
8996    IF ( mode == 'allocate' )  THEN
8997
8998       SELECT CASE ( TRIM( var ) )
8999!--          block of large scale (e.g. RRTMG) radiation output variables
9000             CASE ( 'rad_net*' )
9001                IF ( .NOT. ALLOCATED( rad_net_av ) )  THEN
9002                   ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
9003                ENDIF
9004                rad_net_av = 0.0_wp
9005             
9006             CASE ( 'rad_lw_in*' )
9007                IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) )  THEN
9008                   ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
9009                ENDIF
9010                rad_lw_in_xy_av = 0.0_wp
9011               
9012             CASE ( 'rad_lw_out*' )
9013                IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) )  THEN
9014                   ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
9015                ENDIF
9016                rad_lw_out_xy_av = 0.0_wp
9017               
9018             CASE ( 'rad_sw_in*' )
9019                IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) )  THEN
9020                   ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
9021                ENDIF
9022                rad_sw_in_xy_av = 0.0_wp
9023               
9024             CASE ( 'rad_sw_out*' )
9025                IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) )  THEN
9026                   ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
9027                ENDIF
9028                rad_sw_out_xy_av = 0.0_wp               
9029
9030             CASE ( 'rad_lw_in' )
9031                IF ( .NOT. ALLOCATED( rad_lw_in_av ) )  THEN
9032                   ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9033                ENDIF
9034                rad_lw_in_av = 0.0_wp
9035
9036             CASE ( 'rad_lw_out' )
9037                IF ( .NOT. ALLOCATED( rad_lw_out_av ) )  THEN
9038                   ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9039                ENDIF
9040                rad_lw_out_av = 0.0_wp
9041
9042             CASE ( 'rad_lw_cs_hr' )
9043                IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) )  THEN
9044                   ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9045                ENDIF
9046                rad_lw_cs_hr_av = 0.0_wp
9047
9048             CASE ( 'rad_lw_hr' )
9049                IF ( .NOT. ALLOCATED( rad_lw_hr_av ) )  THEN
9050                   ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9051                ENDIF
9052                rad_lw_hr_av = 0.0_wp
9053
9054             CASE ( 'rad_sw_in' )
9055                IF ( .NOT. ALLOCATED( rad_sw_in_av ) )  THEN
9056                   ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9057                ENDIF
9058                rad_sw_in_av = 0.0_wp
9059
9060             CASE ( 'rad_sw_out' )
9061                IF ( .NOT. ALLOCATED( rad_sw_out_av ) )  THEN
9062                   ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9063                ENDIF
9064                rad_sw_out_av = 0.0_wp
9065
9066             CASE ( 'rad_sw_cs_hr' )
9067                IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) )  THEN
9068                   ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9069                ENDIF
9070                rad_sw_cs_hr_av = 0.0_wp
9071
9072             CASE ( 'rad_sw_hr' )
9073                IF ( .NOT. ALLOCATED( rad_sw_hr_av ) )  THEN
9074                   ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9075                ENDIF
9076                rad_sw_hr_av = 0.0_wp
9077
9078!--          block of RTM output variables
9079             CASE ( 'rtm_rad_net' )
9080!--              array of complete radiation balance
9081                 IF ( .NOT.  ALLOCATED(surfradnet_av) )  THEN
9082                     ALLOCATE( surfradnet_av(nsurfl) )
9083                     surfradnet_av = 0.0_wp
9084                 ENDIF
9085
9086             CASE ( 'rtm_rad_insw' )
9087!--                 array of sw radiation falling to surface after i-th reflection
9088                 IF ( .NOT.  ALLOCATED(surfinsw_av) )  THEN
9089                     ALLOCATE( surfinsw_av(nsurfl) )
9090                     surfinsw_av = 0.0_wp
9091                 ENDIF
9092
9093             CASE ( 'rtm_rad_inlw' )
9094!--                 array of lw radiation falling to surface after i-th reflection
9095                 IF ( .NOT.  ALLOCATED(surfinlw_av) )  THEN
9096                     ALLOCATE( surfinlw_av(nsurfl) )
9097                     surfinlw_av = 0.0_wp
9098                 ENDIF
9099
9100             CASE ( 'rtm_rad_inswdir' )
9101!--                 array of direct sw radiation falling to surface from sun
9102                 IF ( .NOT.  ALLOCATED(surfinswdir_av) )  THEN
9103                     ALLOCATE( surfinswdir_av(nsurfl) )
9104                     surfinswdir_av = 0.0_wp
9105                 ENDIF
9106
9107             CASE ( 'rtm_rad_inswdif' )
9108!--                 array of difusion sw radiation falling to surface from sky and borders of the domain
9109                 IF ( .NOT.  ALLOCATED(surfinswdif_av) )  THEN
9110                     ALLOCATE( surfinswdif_av(nsurfl) )
9111                     surfinswdif_av = 0.0_wp
9112                 ENDIF
9113
9114             CASE ( 'rtm_rad_inswref' )
9115!--                 array of sw radiation falling to surface from reflections
9116                 IF ( .NOT.  ALLOCATED(surfinswref_av) )  THEN
9117                     ALLOCATE( surfinswref_av(nsurfl) )
9118                     surfinswref_av = 0.0_wp
9119                 ENDIF
9120
9121             CASE ( 'rtm_rad_inlwdif' )
9122!--                 array of sw radiation falling to surface after i-th reflection
9123                IF ( .NOT.  ALLOCATED(surfinlwdif_av) )  THEN
9124                     ALLOCATE( surfinlwdif_av(nsurfl) )
9125                     surfinlwdif_av = 0.0_wp
9126                 ENDIF
9127
9128             CASE ( 'rtm_rad_inlwref' )
9129!--                 array of lw radiation falling to surface from reflections
9130                 IF ( .NOT.  ALLOCATED(surfinlwref_av) )  THEN
9131                     ALLOCATE( surfinlwref_av(nsurfl) )
9132                     surfinlwref_av = 0.0_wp
9133                 ENDIF
9134
9135             CASE ( 'rtm_rad_outsw' )
9136!--                 array of sw radiation emitted from surface after i-th reflection
9137                 IF ( .NOT.  ALLOCATED(surfoutsw_av) )  THEN
9138                     ALLOCATE( surfoutsw_av(nsurfl) )
9139                     surfoutsw_av = 0.0_wp
9140                 ENDIF
9141
9142             CASE ( 'rtm_rad_outlw' )
9143!--                 array of lw radiation emitted from surface after i-th reflection
9144                 IF ( .NOT.  ALLOCATED(surfoutlw_av) )  THEN
9145                     ALLOCATE( surfoutlw_av(nsurfl) )
9146                     surfoutlw_av = 0.0_wp
9147                 ENDIF
9148             CASE ( 'rtm_rad_ressw' )
9149!--                 array of residua of sw radiation absorbed in surface after last reflection
9150                 IF ( .NOT.  ALLOCATED(surfins_av) )  THEN
9151                     ALLOCATE( surfins_av(nsurfl) )
9152                     surfins_av = 0.0_wp
9153                 ENDIF
9154
9155             CASE ( 'rtm_rad_reslw' )
9156!--                 array of residua of lw radiation absorbed in surface after last reflection
9157                 IF ( .NOT.  ALLOCATED(surfinl_av) )  THEN
9158                     ALLOCATE( surfinl_av(nsurfl) )
9159                     surfinl_av = 0.0_wp
9160                 ENDIF
9161
9162             CASE ( 'rtm_rad_pc_inlw' )
9163!--                 array of of lw radiation absorbed in plant canopy
9164                 IF ( .NOT.  ALLOCATED(pcbinlw_av) )  THEN
9165                     ALLOCATE( pcbinlw_av(1:npcbl) )
9166                     pcbinlw_av = 0.0_wp
9167                 ENDIF
9168
9169             CASE ( 'rtm_rad_pc_insw' )
9170!--                 array of of sw radiation absorbed in plant canopy
9171                 IF ( .NOT.  ALLOCATED(pcbinsw_av) )  THEN
9172                     ALLOCATE( pcbinsw_av(1:npcbl) )
9173                     pcbinsw_av = 0.0_wp
9174                 ENDIF
9175
9176             CASE ( 'rtm_rad_pc_inswdir' )
9177!--                 array of of direct sw radiation absorbed in plant canopy
9178                 IF ( .NOT.  ALLOCATED(pcbinswdir_av) )  THEN
9179                     ALLOCATE( pcbinswdir_av(1:npcbl) )
9180                     pcbinswdir_av = 0.0_wp
9181                 ENDIF
9182
9183             CASE ( 'rtm_rad_pc_inswdif' )
9184!--                 array of of diffuse sw radiation absorbed in plant canopy
9185                 IF ( .NOT.  ALLOCATED(pcbinswdif_av) )  THEN
9186                     ALLOCATE( pcbinswdif_av(1:npcbl) )
9187                     pcbinswdif_av = 0.0_wp
9188                 ENDIF
9189
9190             CASE ( 'rtm_rad_pc_inswref' )
9191!--                 array of of reflected sw radiation absorbed in plant canopy
9192                 IF ( .NOT.  ALLOCATED(pcbinswref_av) )  THEN
9193                     ALLOCATE( pcbinswref_av(1:npcbl) )
9194                     pcbinswref_av = 0.0_wp
9195                 ENDIF
9196
9197             CASE ( 'rtm_mrt_sw' )
9198                IF ( .NOT. ALLOCATED( mrtinsw_av ) )  THEN
9199                   ALLOCATE( mrtinsw_av(nmrtbl) )
9200                ENDIF
9201                mrtinsw_av = 0.0_wp
9202
9203             CASE ( 'rtm_mrt_lw' )
9204                IF ( .NOT. ALLOCATED( mrtinlw_av ) )  THEN
9205                   ALLOCATE( mrtinlw_av(nmrtbl) )
9206                ENDIF
9207                mrtinlw_av = 0.0_wp
9208
9209             CASE ( 'rtm_mrt' )
9210                IF ( .NOT. ALLOCATED( mrt_av ) )  THEN
9211                   ALLOCATE( mrt_av(nmrtbl) )
9212                ENDIF
9213                mrt_av = 0.0_wp
9214
9215          CASE DEFAULT
9216             CONTINUE
9217
9218       END SELECT
9219
9220    ELSEIF ( mode == 'sum' )  THEN
9221
9222       SELECT CASE ( TRIM( var ) )
9223!--       block of large scale (e.g. RRTMG) radiation output variables
9224          CASE ( 'rad_net*' )
9225             IF ( ALLOCATED( rad_net_av ) ) THEN
9226                DO  i = nxl, nxr
9227                   DO  j = nys, nyn
9228                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9229                                  surf_lsm_h%end_index(j,i)
9230                      match_usm = surf_usm_h%start_index(j,i) <=               &
9231                                  surf_usm_h%end_index(j,i)
9232
9233                     IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9234                         m = surf_lsm_h%end_index(j,i)
9235                         rad_net_av(j,i) = rad_net_av(j,i) +                   &
9236                                         surf_lsm_h%rad_net(m)
9237                      ELSEIF ( match_usm )  THEN
9238                         m = surf_usm_h%end_index(j,i)
9239                         rad_net_av(j,i) = rad_net_av(j,i) +                   &
9240                                         surf_usm_h%rad_net(m)
9241                      ENDIF
9242                   ENDDO
9243                ENDDO
9244             ENDIF
9245
9246          CASE ( 'rad_lw_in*' )
9247             IF ( ALLOCATED( rad_lw_in_xy_av ) ) THEN
9248                DO  i = nxl, nxr
9249                   DO  j = nys, nyn
9250                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9251                                  surf_lsm_h%end_index(j,i)
9252                      match_usm = surf_usm_h%start_index(j,i) <=               &
9253                                  surf_usm_h%end_index(j,i)
9254
9255                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9256                         m = surf_lsm_h%end_index(j,i)
9257                         rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i) +         &
9258                                         surf_lsm_h%rad_lw_in(m)
9259                      ELSEIF ( match_usm )  THEN
9260                         m = surf_usm_h%end_index(j,i)
9261                         rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i) +         &
9262                                         surf_usm_h%rad_lw_in(m)
9263                      ENDIF
9264                   ENDDO
9265                ENDDO
9266             ENDIF
9267             
9268          CASE ( 'rad_lw_out*' )
9269             IF ( ALLOCATED( rad_lw_out_xy_av ) ) THEN
9270                DO  i = nxl, nxr
9271                   DO  j = nys, nyn
9272                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9273                                  surf_lsm_h%end_index(j,i)
9274                      match_usm = surf_usm_h%start_index(j,i) <=               &
9275                                  surf_usm_h%end_index(j,i)
9276
9277                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9278                         m = surf_lsm_h%end_index(j,i)
9279                         rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i) +       &
9280                                                 surf_lsm_h%rad_lw_out(m)
9281                      ELSEIF ( match_usm )  THEN
9282                         m = surf_usm_h%end_index(j,i)
9283                         rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i) +       &
9284                                                 surf_usm_h%rad_lw_out(m)
9285                      ENDIF
9286                   ENDDO
9287                ENDDO
9288             ENDIF
9289             
9290          CASE ( 'rad_sw_in*' )
9291             IF ( ALLOCATED( rad_sw_in_xy_av ) ) THEN
9292                DO  i = nxl, nxr
9293                   DO  j = nys, nyn
9294                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9295                                  surf_lsm_h%end_index(j,i)
9296                      match_usm = surf_usm_h%start_index(j,i) <=               &
9297                                  surf_usm_h%end_index(j,i)
9298
9299                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9300                         m = surf_lsm_h%end_index(j,i)
9301                         rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i) +         &
9302                                                surf_lsm_h%rad_sw_in(m)
9303                      ELSEIF ( match_usm )  THEN
9304                         m = surf_usm_h%end_index(j,i)
9305                         rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i) +         &
9306                                                surf_usm_h%rad_sw_in(m)
9307                      ENDIF
9308                   ENDDO
9309                ENDDO
9310             ENDIF
9311             
9312          CASE ( 'rad_sw_out*' )
9313             IF ( ALLOCATED( rad_sw_out_xy_av ) ) THEN
9314                DO  i = nxl, nxr
9315                   DO  j = nys, nyn
9316                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9317                                  surf_lsm_h%end_index(j,i)
9318                      match_usm = surf_usm_h%start_index(j,i) <=               &
9319                                  surf_usm_h%end_index(j,i)
9320
9321                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9322                         m = surf_lsm_h%end_index(j,i)
9323                         rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i) +       &
9324                                                 surf_lsm_h%rad_sw_out(m)
9325                      ELSEIF ( match_usm )  THEN
9326                         m = surf_usm_h%end_index(j,i)
9327                         rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i) +       &
9328                                                 surf_usm_h%rad_sw_out(m)
9329                      ENDIF
9330                   ENDDO
9331                ENDDO
9332             ENDIF
9333             
9334          CASE ( 'rad_lw_in' )
9335             IF ( ALLOCATED( rad_lw_in_av ) ) THEN
9336                DO  i = nxlg, nxrg
9337                   DO  j = nysg, nyng
9338                      DO  k = nzb, nzt+1
9339                         rad_lw_in_av(k,j,i) = rad_lw_in_av(k,j,i)             &
9340                                               + rad_lw_in(k,j,i)
9341                      ENDDO
9342                   ENDDO
9343                ENDDO
9344             ENDIF
9345
9346          CASE ( 'rad_lw_out' )
9347             IF ( ALLOCATED( rad_lw_out_av ) ) THEN
9348                DO  i = nxlg, nxrg
9349                   DO  j = nysg, nyng
9350                      DO  k = nzb, nzt+1
9351                         rad_lw_out_av(k,j,i) = rad_lw_out_av(k,j,i)           &
9352                                                + rad_lw_out(k,j,i)
9353                      ENDDO
9354                   ENDDO
9355                ENDDO
9356             ENDIF
9357
9358          CASE ( 'rad_lw_cs_hr' )
9359             IF ( ALLOCATED( rad_lw_cs_hr_av ) ) THEN
9360                DO  i = nxlg, nxrg
9361                   DO  j = nysg, nyng
9362                      DO  k = nzb, nzt+1
9363                         rad_lw_cs_hr_av(k,j,i) = rad_lw_cs_hr_av(k,j,i)       &
9364                                                  + rad_lw_cs_hr(k,j,i)
9365                      ENDDO
9366                   ENDDO
9367                ENDDO
9368             ENDIF
9369
9370          CASE ( 'rad_lw_hr' )
9371             IF ( ALLOCATED( rad_lw_hr_av ) ) THEN
9372                DO  i = nxlg, nxrg
9373                   DO  j = nysg, nyng
9374                      DO  k = nzb, nzt+1
9375                         rad_lw_hr_av(k,j,i) = rad_lw_hr_av(k,j,i)             &
9376                                               + rad_lw_hr(k,j,i)
9377                      ENDDO
9378                   ENDDO
9379                ENDDO
9380             ENDIF
9381
9382          CASE ( 'rad_sw_in' )
9383             IF ( ALLOCATED( rad_sw_in_av ) ) THEN
9384                DO  i = nxlg, nxrg
9385                   DO  j = nysg, nyng
9386                      DO  k = nzb, nzt+1
9387                         rad_sw_in_av(k,j,i) = rad_sw_in_av(k,j,i)             &
9388                                               + rad_sw_in(k,j,i)
9389                      ENDDO
9390                   ENDDO
9391                ENDDO
9392             ENDIF
9393
9394          CASE ( 'rad_sw_out' )
9395             IF ( ALLOCATED( rad_sw_out_av ) ) THEN
9396                DO  i = nxlg, nxrg
9397                   DO  j = nysg, nyng
9398                      DO  k = nzb, nzt+1
9399                         rad_sw_out_av(k,j,i) = rad_sw_out_av(k,j,i)           &
9400                                                + rad_sw_out(k,j,i)
9401                      ENDDO
9402                   ENDDO
9403                ENDDO
9404             ENDIF
9405
9406          CASE ( 'rad_sw_cs_hr' )
9407             IF ( ALLOCATED( rad_sw_cs_hr_av ) ) THEN
9408                DO  i = nxlg, nxrg
9409                   DO  j = nysg, nyng
9410                      DO  k = nzb, nzt+1
9411                         rad_sw_cs_hr_av(k,j,i) = rad_sw_cs_hr_av(k,j,i)       &
9412                                                  + rad_sw_cs_hr(k,j,i)
9413                      ENDDO
9414                   ENDDO
9415                ENDDO
9416             ENDIF
9417
9418          CASE ( 'rad_sw_hr' )
9419             IF ( ALLOCATED( rad_sw_hr_av ) ) THEN
9420                DO  i = nxlg, nxrg
9421                   DO  j = nysg, nyng
9422                      DO  k = nzb, nzt+1
9423                         rad_sw_hr_av(k,j,i) = rad_sw_hr_av(k,j,i)             &
9424                                               + rad_sw_hr(k,j,i)
9425                      ENDDO
9426                   ENDDO
9427                ENDDO
9428             ENDIF
9429
9430!--       block of RTM output variables
9431          CASE ( 'rtm_rad_net' )
9432!--           array of complete radiation balance
9433              DO isurf = dirstart(ids), dirend(ids)
9434                 IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9435                    surfradnet_av(isurf) = surfinsw(isurf) - surfoutsw(isurf) +  surfinlw(isurf) - surfoutlw(isurf)
9436                 ENDIF
9437              ENDDO
9438
9439          CASE ( 'rtm_rad_insw' )
9440!--           array of sw radiation falling to surface after i-th reflection
9441              DO isurf = dirstart(ids), dirend(ids)
9442                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9443                      surfinsw_av(isurf) = surfinsw_av(isurf) + surfinsw(isurf)
9444                  ENDIF
9445              ENDDO
9446
9447          CASE ( 'rtm_rad_inlw' )
9448!--           array of lw radiation falling to surface after i-th reflection
9449              DO isurf = dirstart(ids), dirend(ids)
9450                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9451                      surfinlw_av(isurf) = surfinlw_av(isurf) + surfinlw(isurf)
9452                  ENDIF
9453              ENDDO
9454
9455          CASE ( 'rtm_rad_inswdir' )
9456!--           array of direct sw radiation falling to surface from sun
9457              DO isurf = dirstart(ids), dirend(ids)
9458                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9459                      surfinswdir_av(isurf) = surfinswdir_av(isurf) + surfinswdir(isurf)
9460                  ENDIF
9461              ENDDO
9462
9463          CASE ( 'rtm_rad_inswdif' )
9464!--           array of difusion sw radiation falling to surface from sky and borders of the domain
9465              DO isurf = dirstart(ids), dirend(ids)
9466                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9467                      surfinswdif_av(isurf) = surfinswdif_av(isurf) + surfinswdif(isurf)
9468                  ENDIF
9469              ENDDO
9470
9471          CASE ( 'rtm_rad_inswref' )
9472!--           array of sw radiation falling to surface from reflections
9473              DO isurf = dirstart(ids), dirend(ids)
9474                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9475                      surfinswref_av(isurf) = surfinswref_av(isurf) + surfinsw(isurf) - &
9476                                          surfinswdir(isurf) - surfinswdif(isurf)
9477                  ENDIF
9478              ENDDO
9479
9480
9481          CASE ( 'rtm_rad_inlwdif' )
9482!--           array of sw radiation falling to surface after i-th reflection
9483              DO isurf = dirstart(ids), dirend(ids)
9484                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9485                      surfinlwdif_av(isurf) = surfinlwdif_av(isurf) + surfinlwdif(isurf)
9486                  ENDIF
9487              ENDDO
9488!
9489          CASE ( 'rtm_rad_inlwref' )
9490!--           array of lw radiation falling to surface from reflections
9491              DO isurf = dirstart(ids), dirend(ids)
9492                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9493                      surfinlwref_av(isurf) = surfinlwref_av(isurf) + &
9494                                          surfinlw(isurf) - surfinlwdif(isurf)
9495                  ENDIF
9496              ENDDO
9497
9498          CASE ( 'rtm_rad_outsw' )
9499!--           array of sw radiation emitted from surface after i-th reflection
9500              DO isurf = dirstart(ids), dirend(ids)
9501                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9502                      surfoutsw_av(isurf) = surfoutsw_av(isurf) + surfoutsw(isurf)
9503                  ENDIF
9504              ENDDO
9505
9506          CASE ( 'rtm_rad_outlw' )
9507!--           array of lw radiation emitted from surface after i-th reflection
9508              DO isurf = dirstart(ids), dirend(ids)
9509                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9510                      surfoutlw_av(isurf) = surfoutlw_av(isurf) + surfoutlw(isurf)
9511                  ENDIF
9512              ENDDO
9513
9514          CASE ( 'rtm_rad_ressw' )
9515!--           array of residua of sw radiation absorbed in surface after last reflection
9516              DO isurf = dirstart(ids), dirend(ids)
9517                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9518                      surfins_av(isurf) = surfins_av(isurf) + surfins(isurf)
9519                  ENDIF
9520              ENDDO
9521
9522          CASE ( 'rtm_rad_reslw' )
9523!--           array of residua of lw radiation absorbed in surface after last reflection
9524              DO isurf = dirstart(ids), dirend(ids)
9525                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9526                      surfinl_av(isurf) = surfinl_av(isurf) + surfinl(isurf)
9527                  ENDIF
9528              ENDDO
9529
9530          CASE ( 'rtm_rad_pc_inlw' )
9531              DO l = 1, npcbl
9532                 pcbinlw_av(l) = pcbinlw_av(l) + pcbinlw(l)
9533              ENDDO
9534
9535          CASE ( 'rtm_rad_pc_insw' )
9536              DO l = 1, npcbl
9537                 pcbinsw_av(l) = pcbinsw_av(l) + pcbinsw(l)
9538              ENDDO
9539
9540          CASE ( 'rtm_rad_pc_inswdir' )
9541              DO l = 1, npcbl
9542                 pcbinswdir_av(l) = pcbinswdir_av(l) + pcbinswdir(l)
9543              ENDDO
9544
9545          CASE ( 'rtm_rad_pc_inswdif' )
9546              DO l = 1, npcbl
9547                 pcbinswdif_av(l) = pcbinswdif_av(l) + pcbinswdif(l)
9548              ENDDO
9549
9550          CASE ( 'rtm_rad_pc_inswref' )
9551              DO l = 1, npcbl
9552                 pcbinswref_av(l) = pcbinswref_av(l) + pcbinsw(l) - pcbinswdir(l) - pcbinswdif(l)
9553              ENDDO
9554
9555          CASE ( 'rad_mrt_sw' )
9556             IF ( ALLOCATED( mrtinsw_av ) )  THEN
9557                mrtinsw_av(:) = mrtinsw_av(:) + mrtinsw(:)
9558             ENDIF
9559
9560          CASE ( 'rad_mrt_lw' )
9561             IF ( ALLOCATED( mrtinlw_av ) )  THEN
9562                mrtinlw_av(:) = mrtinlw_av(:) + mrtinlw(:)
9563             ENDIF
9564
9565          CASE ( 'rad_mrt' )
9566             IF ( ALLOCATED( mrt_av ) )  THEN
9567                mrt_av(:) = mrt_av(:) + mrt(:)
9568             ENDIF
9569
9570          CASE DEFAULT
9571             CONTINUE
9572
9573       END SELECT
9574
9575    ELSEIF ( mode == 'average' )  THEN
9576
9577       SELECT CASE ( TRIM( var ) )
9578!--       block of large scale (e.g. RRTMG) radiation output variables
9579          CASE ( 'rad_net*' )
9580             IF ( ALLOCATED( rad_net_av ) ) THEN
9581                DO  i = nxlg, nxrg
9582                   DO  j = nysg, nyng
9583                      rad_net_av(j,i) = rad_net_av(j,i)                        &
9584                                        / REAL( average_count_3d, KIND=wp )
9585                   ENDDO
9586                ENDDO
9587             ENDIF
9588             
9589          CASE ( 'rad_lw_in*' )
9590             IF ( ALLOCATED( rad_lw_in_xy_av ) ) THEN
9591                DO  i = nxlg, nxrg
9592                   DO  j = nysg, nyng
9593                      rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i)              &
9594                                        / REAL( average_count_3d, KIND=wp )
9595                   ENDDO
9596                ENDDO
9597             ENDIF
9598             
9599          CASE ( 'rad_lw_out*' )
9600             IF ( ALLOCATED( rad_lw_out_xy_av ) ) THEN
9601                DO  i = nxlg, nxrg
9602                   DO  j = nysg, nyng
9603                      rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i)            &
9604                                        / REAL( average_count_3d, KIND=wp )
9605                   ENDDO
9606                ENDDO
9607             ENDIF
9608             
9609          CASE ( 'rad_sw_in*' )
9610             IF ( ALLOCATED( rad_sw_in_xy_av ) ) THEN
9611                DO  i = nxlg, nxrg
9612                   DO  j = nysg, nyng
9613                      rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i)              &
9614                                        / REAL( average_count_3d, KIND=wp )
9615                   ENDDO
9616                ENDDO
9617             ENDIF
9618             
9619          CASE ( 'rad_sw_out*' )
9620             IF ( ALLOCATED( rad_sw_out_xy_av ) ) THEN
9621                DO  i = nxlg, nxrg
9622                   DO  j = nysg, nyng
9623                      rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i)             &
9624                                        / REAL( average_count_3d, KIND=wp )
9625                   ENDDO
9626                ENDDO
9627             ENDIF
9628
9629          CASE ( 'rad_lw_in' )
9630             IF ( ALLOCATED( rad_lw_in_av ) ) THEN
9631                DO  i = nxlg, nxrg
9632                   DO  j = nysg, nyng
9633                      DO  k = nzb, nzt+1
9634                         rad_lw_in_av(k,j,i) = rad_lw_in_av(k,j,i)             &
9635                                               / REAL( average_count_3d, KIND=wp )
9636                      ENDDO
9637                   ENDDO
9638                ENDDO
9639             ENDIF
9640
9641          CASE ( 'rad_lw_out' )
9642             IF ( ALLOCATED( rad_lw_out_av ) ) THEN
9643                DO  i = nxlg, nxrg
9644                   DO  j = nysg, nyng
9645                      DO  k = nzb, nzt+1
9646                         rad_lw_out_av(k,j,i) = rad_lw_out_av(k,j,i)           &
9647                                                / REAL( average_count_3d, KIND=wp )
9648                      ENDDO
9649                   ENDDO
9650                ENDDO
9651             ENDIF
9652
9653          CASE ( 'rad_lw_cs_hr' )
9654             IF ( ALLOCATED( rad_lw_cs_hr_av ) ) THEN
9655                DO  i = nxlg, nxrg
9656                   DO  j = nysg, nyng
9657                      DO  k = nzb, nzt+1
9658                         rad_lw_cs_hr_av(k,j,i) = rad_lw_cs_hr_av(k,j,i)       &
9659                                                / REAL( average_count_3d, KIND=wp )
9660                      ENDDO
9661                   ENDDO
9662                ENDDO
9663             ENDIF
9664
9665          CASE ( 'rad_lw_hr' )
9666             IF ( ALLOCATED( rad_lw_hr_av ) ) THEN
9667                DO  i = nxlg, nxrg
9668                   DO  j = nysg, nyng
9669                      DO  k = nzb, nzt+1
9670                         rad_lw_hr_av(k,j,i) = rad_lw_hr_av(k,j,i)             &
9671                                               / REAL( average_count_3d, KIND=wp )
9672                      ENDDO
9673                   ENDDO
9674                ENDDO
9675             ENDIF
9676
9677          CASE ( 'rad_sw_in' )
9678             IF ( ALLOCATED( rad_sw_in_av ) ) THEN
9679                DO  i = nxlg, nxrg
9680                   DO  j = nysg, nyng
9681                      DO  k = nzb, nzt+1
9682                         rad_sw_in_av(k,j,i) = rad_sw_in_av(k,j,i)             &
9683                                               / REAL( average_count_3d, KIND=wp )
9684                      ENDDO
9685                   ENDDO
9686                ENDDO
9687             ENDIF
9688
9689          CASE ( 'rad_sw_out' )
9690             IF ( ALLOCATED( rad_sw_out_av ) ) THEN
9691                DO  i = nxlg, nxrg
9692                   DO  j = nysg, nyng
9693                      DO  k = nzb, nzt+1
9694                         rad_sw_out_av(k,j,i) = rad_sw_out_av(k,j,i)           &
9695                                                / REAL( average_count_3d, KIND=wp )
9696                      ENDDO
9697                   ENDDO
9698                ENDDO
9699             ENDIF
9700
9701          CASE ( 'rad_sw_cs_hr' )
9702             IF ( ALLOCATED( rad_sw_cs_hr_av ) ) THEN
9703                DO  i = nxlg, nxrg
9704                   DO  j = nysg, nyng
9705                      DO  k = nzb, nzt+1
9706                         rad_sw_cs_hr_av(k,j,i) = rad_sw_cs_hr_av(k,j,i)       &
9707                                                / REAL( average_count_3d, KIND=wp )
9708                      ENDDO
9709                   ENDDO
9710                ENDDO
9711             ENDIF
9712
9713          CASE ( 'rad_sw_hr' )
9714             IF ( ALLOCATED( rad_sw_hr_av ) ) THEN
9715                DO  i = nxlg, nxrg
9716                   DO  j = nysg, nyng
9717                      DO  k = nzb, nzt+1
9718                         rad_sw_hr_av(k,j,i) = rad_sw_hr_av(k,j,i)             &
9719                                               / REAL( average_count_3d, KIND=wp )
9720                      ENDDO
9721                   ENDDO
9722                ENDDO
9723             ENDIF
9724
9725!--       block of RTM output variables
9726          CASE ( 'rtm_rad_net' )
9727!--           array of complete radiation balance
9728              DO isurf = dirstart(ids), dirend(ids)
9729                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9730                      surfradnet_av(isurf) = surfinsw_av(isurf) / REAL( average_count_3d, kind=wp )
9731                  ENDIF
9732              ENDDO
9733
9734          CASE ( 'rtm_rad_insw' )
9735!--           array of sw radiation falling to surface after i-th reflection
9736              DO isurf = dirstart(ids), dirend(ids)
9737                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9738                      surfinsw_av(isurf) = surfinsw_av(isurf) / REAL( average_count_3d, kind=wp )
9739                  ENDIF
9740              ENDDO
9741
9742          CASE ( 'rtm_rad_inlw' )
9743!--           array of lw radiation falling to surface after i-th reflection
9744              DO isurf = dirstart(ids), dirend(ids)
9745                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9746                      surfinlw_av(isurf) = surfinlw_av(isurf) / REAL( average_count_3d, kind=wp )
9747                  ENDIF
9748              ENDDO
9749
9750          CASE ( 'rtm_rad_inswdir' )
9751!--           array of direct sw radiation falling to surface from sun
9752              DO isurf = dirstart(ids), dirend(ids)
9753                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9754                      surfinswdir_av(isurf) = surfinswdir_av(isurf) / REAL( average_count_3d, kind=wp )
9755                  ENDIF
9756              ENDDO
9757
9758          CASE ( 'rtm_rad_inswdif' )
9759!--           array of difusion sw radiation falling to surface from sky and borders of the domain
9760              DO isurf = dirstart(ids), dirend(ids)
9761                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9762                      surfinswdif_av(isurf) = surfinswdif_av(isurf) / REAL( average_count_3d, kind=wp )
9763                  ENDIF
9764              ENDDO
9765
9766          CASE ( 'rtm_rad_inswref' )
9767!--           array of sw radiation falling to surface from reflections
9768              DO isurf = dirstart(ids), dirend(ids)
9769                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9770                      surfinswref_av(isurf) = surfinswref_av(isurf) / REAL( average_count_3d, kind=wp )
9771                  ENDIF
9772              ENDDO
9773
9774          CASE ( 'rtm_rad_inlwdif' )
9775!--           array of sw radiation falling to surface after i-th reflection
9776              DO isurf = dirstart(ids), dirend(ids)
9777                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9778                      surfinlwdif_av(isurf) = surfinlwdif_av(isurf) / REAL( average_count_3d, kind=wp )
9779                  ENDIF
9780              ENDDO
9781
9782          CASE ( 'rtm_rad_inlwref' )
9783!--           array of lw radiation falling to surface from reflections
9784              DO isurf = dirstart(ids), dirend(ids)
9785                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9786                      surfinlwref_av(isurf) = surfinlwref_av(isurf) / REAL( average_count_3d, kind=wp )
9787                  ENDIF
9788              ENDDO
9789
9790          CASE ( 'rtm_rad_outsw' )
9791!--           array of sw radiation emitted from surface after i-th reflection
9792              DO isurf = dirstart(ids), dirend(ids)
9793                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9794                      surfoutsw_av(isurf) = surfoutsw_av(isurf) / REAL( average_count_3d, kind=wp )
9795                  ENDIF
9796              ENDDO
9797
9798          CASE ( 'rtm_rad_outlw' )
9799!--           array of lw radiation emitted from surface after i-th reflection
9800              DO isurf = dirstart(ids), dirend(ids)
9801                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9802                      surfoutlw_av(isurf) = surfoutlw_av(isurf) / REAL( average_count_3d, kind=wp )
9803                  ENDIF
9804              ENDDO
9805
9806          CASE ( 'rtm_rad_ressw' )
9807!--           array of residua of sw radiation absorbed in surface after last reflection
9808              DO isurf = dirstart(ids), dirend(ids)
9809                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9810                      surfins_av(isurf) = surfins_av(isurf) / REAL( average_count_3d, kind=wp )
9811                  ENDIF
9812              ENDDO
9813
9814          CASE ( 'rtm_rad_reslw' )
9815!--           array of residua of lw radiation absorbed in surface after last reflection
9816              DO isurf = dirstart(ids), dirend(ids)
9817                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9818                      surfinl_av(isurf) = surfinl_av(isurf) / REAL( average_count_3d, kind=wp )
9819                  ENDIF
9820              ENDDO
9821
9822          CASE ( 'rtm_rad_pc_inlw' )
9823              DO l = 1, npcbl
9824                 pcbinlw_av(:) = pcbinlw_av(:) / REAL( average_count_3d, kind=wp )
9825              ENDDO
9826
9827          CASE ( 'rtm_rad_pc_insw' )
9828              DO l = 1, npcbl
9829                 pcbinsw_av(:) = pcbinsw_av(:) / REAL( average_count_3d, kind=wp )
9830              ENDDO
9831
9832          CASE ( 'rtm_rad_pc_inswdir' )
9833              DO l = 1, npcbl
9834                 pcbinswdir_av(:) = pcbinswdir_av(:) / REAL( average_count_3d, kind=wp )
9835              ENDDO
9836
9837          CASE ( 'rtm_rad_pc_inswdif' )
9838              DO l = 1, npcbl
9839                 pcbinswdif_av(:) = pcbinswdif_av(:) / REAL( average_count_3d, kind=wp )
9840              ENDDO
9841
9842          CASE ( 'rtm_rad_pc_inswref' )
9843              DO l = 1, npcbl
9844                 pcbinswref_av(:) = pcbinswref_av(:) / REAL( average_count_3d, kind=wp )
9845              ENDDO
9846
9847          CASE ( 'rad_mrt_lw' )
9848             IF ( ALLOCATED( mrtinlw_av ) )  THEN
9849                mrtinlw_av(:) = mrtinlw_av(:) / REAL( average_count_3d, KIND=wp )
9850             ENDIF
9851
9852          CASE ( 'rad_mrt' )
9853             IF ( ALLOCATED( mrt_av ) )  THEN
9854                mrt_av(:) = mrt_av(:) / REAL( average_count_3d, KIND=wp )
9855             ENDIF
9856
9857       END SELECT
9858
9859    ENDIF
9860
9861END SUBROUTINE radiation_3d_data_averaging
9862
9863
9864!------------------------------------------------------------------------------!
9865!
9866! Description:
9867! ------------
9868!> Subroutine defining appropriate grid for netcdf variables.
9869!> It is called out from subroutine netcdf.
9870!------------------------------------------------------------------------------!
9871SUBROUTINE radiation_define_netcdf_grid( variable, found, grid_x, grid_y, grid_z )
9872   
9873    IMPLICIT NONE
9874
9875    CHARACTER (LEN=*), INTENT(IN)  ::  variable    !<
9876    LOGICAL, INTENT(OUT)           ::  found       !<
9877    CHARACTER (LEN=*), INTENT(OUT) ::  grid_x      !<
9878    CHARACTER (LEN=*), INTENT(OUT) ::  grid_y      !<
9879    CHARACTER (LEN=*), INTENT(OUT) ::  grid_z      !<
9880
9881    CHARACTER (len=varnamelength)  :: var
9882
9883    found  = .TRUE.
9884
9885!
9886!-- Check for the grid
9887    var = TRIM(variable)
9888!-- RTM directional variables
9889    IF ( var(1:12) == 'rtm_rad_net_'  .OR.  var(1:13) == 'rtm_rad_insw_'  .OR.          &
9890         var(1:13) == 'rtm_rad_inlw_'  .OR.  var(1:16) == 'rtm_rad_inswdir_'  .OR.      &
9891         var(1:16) == 'rtm_rad_inswdif_'  .OR.  var(1:16) == 'rtm_rad_inswref_'  .OR.   &
9892         var(1:16) == 'rtm_rad_inlwdif_'  .OR.  var(1:16) == 'rtm_rad_inlwref_'  .OR.   &
9893         var(1:14) == 'rtm_rad_outsw_'  .OR.  var(1:14) == 'rtm_rad_outlw_'  .OR.       &
9894         var(1:14) == 'rtm_rad_ressw_'  .OR.  var(1:14) == 'rtm_rad_reslw_'  .OR.       &
9895         var == 'rtm_rad_pc_inlw'  .OR.                                                 &
9896         var == 'rtm_rad_pc_insw'  .OR.  var == 'rtm_rad_pc_inswdir'  .OR.              &
9897         var == 'rtm_rad_pc_inswdif'  .OR.  var == 'rtm_rad_pc_inswref'  .OR.           &
9898         var(1:7) == 'rtm_svf'  .OR.  var(1:7) == 'rtm_dif'  .OR.                       &
9899         var(1:9) == 'rtm_skyvf' .OR. var(1:10) == 'rtm_skyvft'  .OR.                   &
9900         var(1:12) == 'rtm_surfalb_'  .OR.  var(1:13) == 'rtm_surfemis_'  .OR.          &
9901         var == 'rtm_mrt'  .OR.  var ==  'rtm_mrt_sw'  .OR.  var == 'rtm_mrt_lw' )  THEN
9902
9903         found = .TRUE.
9904         grid_x = 'x'
9905         grid_y = 'y'
9906         grid_z = 'zu'
9907    ELSE
9908
9909       SELECT CASE ( TRIM( var ) )
9910
9911          CASE ( 'rad_lw_cs_hr', 'rad_lw_hr', 'rad_sw_cs_hr', 'rad_sw_hr',        &
9912                 'rad_lw_cs_hr_xy', 'rad_lw_hr_xy', 'rad_sw_cs_hr_xy',            &
9913                 'rad_sw_hr_xy', 'rad_lw_cs_hr_xz', 'rad_lw_hr_xz',               &
9914                 'rad_sw_cs_hr_xz', 'rad_sw_hr_xz', 'rad_lw_cs_hr_yz',            &
9915                 'rad_lw_hr_yz', 'rad_sw_cs_hr_yz', 'rad_sw_hr_yz',               &
9916                 'rad_mrt', 'rad_mrt_sw', 'rad_mrt_lw' )
9917             grid_x = 'x'
9918             grid_y = 'y'
9919             grid_z = 'zu'
9920
9921          CASE ( 'rad_lw_in', 'rad_lw_out', 'rad_sw_in', 'rad_sw_out',            &
9922                 'rad_lw_in_xy', 'rad_lw_out_xy', 'rad_sw_in_xy','rad_sw_out_xy', &
9923                 'rad_lw_in_xz', 'rad_lw_out_xz', 'rad_sw_in_xz','rad_sw_out_xz', &
9924                 'rad_lw_in_yz', 'rad_lw_out_yz', 'rad_sw_in_yz','rad_sw_out_yz' )
9925             grid_x = 'x'
9926             grid_y = 'y'
9927             grid_z = 'zw'
9928
9929
9930          CASE DEFAULT
9931             found  = .FALSE.
9932             grid_x = 'none'
9933             grid_y = 'none'
9934             grid_z = 'none'
9935
9936           END SELECT
9937       ENDIF
9938
9939    END SUBROUTINE radiation_define_netcdf_grid
9940
9941!------------------------------------------------------------------------------!
9942!
9943! Description:
9944! ------------
9945!> Subroutine defining 2D output variables
9946!------------------------------------------------------------------------------!
9947 SUBROUTINE radiation_data_output_2d( av, variable, found, grid, mode,         &
9948                                      local_pf, two_d, nzb_do, nzt_do )
9949 
9950    USE indices
9951
9952    USE kinds
9953
9954
9955    IMPLICIT NONE
9956
9957    CHARACTER (LEN=*) ::  grid     !<
9958    CHARACTER (LEN=*) ::  mode     !<
9959    CHARACTER (LEN=*) ::  variable !<
9960
9961    INTEGER(iwp) ::  av !<
9962    INTEGER(iwp) ::  i  !<
9963    INTEGER(iwp) ::  j  !<
9964    INTEGER(iwp) ::  k  !<
9965    INTEGER(iwp) ::  m  !< index of surface element at grid point (j,i)
9966    INTEGER(iwp) ::  nzb_do   !<
9967    INTEGER(iwp) ::  nzt_do   !<
9968
9969    LOGICAL      ::  found !<
9970    LOGICAL      ::  two_d !< flag parameter that indicates 2D variables (horizontal cross sections)
9971
9972    REAL(wp) ::  fill_value = -999.0_wp    !< value for the _FillValue attribute
9973
9974    REAL(wp), DIMENSION(nxl:nxr,nys:nyn,nzb_do:nzt_do) ::  local_pf !<
9975
9976    found = .TRUE.
9977
9978    SELECT CASE ( TRIM( variable ) )
9979
9980       CASE ( 'rad_net*_xy' )        ! 2d-array
9981          IF ( av == 0 ) THEN
9982             DO  i = nxl, nxr
9983                DO  j = nys, nyn
9984!
9985!--                Obtain rad_net from its respective surface type
9986!--                Natural-type surfaces
9987                   DO  m = surf_lsm_h%start_index(j,i),                        &
9988                           surf_lsm_h%end_index(j,i) 
9989                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_net(m)
9990                   ENDDO
9991!
9992!--                Urban-type surfaces
9993                   DO  m = surf_usm_h%start_index(j,i),                        &
9994                           surf_usm_h%end_index(j,i) 
9995                      local_pf(i,j,nzb+1) = surf_usm_h%rad_net(m)
9996                   ENDDO
9997                ENDDO
9998             ENDDO
9999          ELSE
10000             IF ( .NOT. ALLOCATED( rad_net_av ) ) THEN
10001                ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
10002                rad_net_av = REAL( fill_value, KIND = wp )
10003             ENDIF
10004             DO  i = nxl, nxr
10005                DO  j = nys, nyn 
10006                   local_pf(i,j,nzb+1) = rad_net_av(j,i)
10007                ENDDO
10008             ENDDO
10009          ENDIF
10010          two_d = .TRUE.
10011          grid = 'zu1'
10012         
10013       CASE ( 'rad_lw_in*_xy' )        ! 2d-array
10014          IF ( av == 0 ) THEN
10015             DO  i = nxl, nxr
10016                DO  j = nys, nyn
10017!
10018!--                Obtain rad_net from its respective surface type
10019!--                Natural-type surfaces
10020                   DO  m = surf_lsm_h%start_index(j,i),                        &
10021                           surf_lsm_h%end_index(j,i) 
10022                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_lw_in(m)
10023                   ENDDO
10024!
10025!--                Urban-type surfaces
10026                   DO  m = surf_usm_h%start_index(j,i),                        &
10027                           surf_usm_h%end_index(j,i) 
10028                      local_pf(i,j,nzb+1) = surf_usm_h%rad_lw_in(m)
10029                   ENDDO
10030                ENDDO
10031             ENDDO
10032          ELSE
10033             IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) ) THEN
10034                ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
10035                rad_lw_in_xy_av = REAL( fill_value, KIND = wp )
10036             ENDIF
10037             DO  i = nxl, nxr
10038                DO  j = nys, nyn 
10039                   local_pf(i,j,nzb+1) = rad_lw_in_xy_av(j,i)
10040                ENDDO
10041             ENDDO
10042          ENDIF
10043          two_d = .TRUE.
10044          grid = 'zu1'
10045         
10046       CASE ( 'rad_lw_out*_xy' )        ! 2d-array
10047          IF ( av == 0 ) THEN
10048             DO  i = nxl, nxr
10049                DO  j = nys, nyn
10050!
10051!--                Obtain rad_net from its respective surface type
10052!--                Natural-type surfaces
10053                   DO  m = surf_lsm_h%start_index(j,i),                        &
10054                           surf_lsm_h%end_index(j,i) 
10055                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_lw_out(m)
10056                   ENDDO
10057!
10058!--                Urban-type surfaces
10059                   DO  m = surf_usm_h%start_index(j,i),                        &
10060                           surf_usm_h%end_index(j,i) 
10061                      local_pf(i,j,nzb+1) = surf_usm_h%rad_lw_out(m)
10062                   ENDDO
10063                ENDDO
10064             ENDDO
10065          ELSE
10066             IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) ) THEN
10067                ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
10068                rad_lw_out_xy_av = REAL( fill_value, KIND = wp )
10069             ENDIF
10070             DO  i = nxl, nxr
10071                DO  j = nys, nyn 
10072                   local_pf(i,j,nzb+1) = rad_lw_out_xy_av(j,i)
10073                ENDDO
10074             ENDDO
10075          ENDIF
10076          two_d = .TRUE.
10077          grid = 'zu1'
10078         
10079       CASE ( 'rad_sw_in*_xy' )        ! 2d-array
10080          IF ( av == 0 ) THEN
10081             DO  i = nxl, nxr
10082                DO  j = nys, nyn
10083!
10084!--                Obtain rad_net from its respective surface type
10085!--                Natural-type surfaces
10086                   DO  m = surf_lsm_h%start_index(j,i),                        &
10087                           surf_lsm_h%end_index(j,i) 
10088                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_sw_in(m)
10089                   ENDDO
10090!
10091!--                Urban-type surfaces
10092                   DO  m = surf_usm_h%start_index(j,i),                        &
10093                           surf_usm_h%end_index(j,i) 
10094                      local_pf(i,j,nzb+1) = surf_usm_h%rad_sw_in(m)
10095                   ENDDO
10096                ENDDO
10097             ENDDO
10098          ELSE
10099             IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) ) THEN
10100                ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
10101                rad_sw_in_xy_av = REAL( fill_value, KIND = wp )
10102             ENDIF
10103             DO  i = nxl, nxr
10104                DO  j = nys, nyn 
10105                   local_pf(i,j,nzb+1) = rad_sw_in_xy_av(j,i)
10106                ENDDO
10107             ENDDO
10108          ENDIF
10109          two_d = .TRUE.
10110          grid = 'zu1'
10111         
10112       CASE ( 'rad_sw_out*_xy' )        ! 2d-array
10113          IF ( av == 0 ) THEN
10114             DO  i = nxl, nxr
10115                DO  j = nys, nyn
10116!
10117!--                Obtain rad_net from its respective surface type
10118!--                Natural-type surfaces
10119                   DO  m = surf_lsm_h%start_index(j,i),                        &
10120                           surf_lsm_h%end_index(j,i) 
10121                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_sw_out(m)
10122                   ENDDO
10123!
10124!--                Urban-type surfaces
10125                   DO  m = surf_usm_h%start_index(j,i),                        &
10126                           surf_usm_h%end_index(j,i) 
10127                      local_pf(i,j,nzb+1) = surf_usm_h%rad_sw_out(m)
10128                   ENDDO
10129                ENDDO
10130             ENDDO
10131          ELSE
10132             IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) ) THEN
10133                ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
10134                rad_sw_out_xy_av = REAL( fill_value, KIND = wp )
10135             ENDIF
10136             DO  i = nxl, nxr
10137                DO  j = nys, nyn 
10138                   local_pf(i,j,nzb+1) = rad_sw_out_xy_av(j,i)
10139                ENDDO
10140             ENDDO
10141          ENDIF
10142          two_d = .TRUE.
10143          grid = 'zu1'         
10144         
10145       CASE ( 'rad_lw_in_xy', 'rad_lw_in_xz', 'rad_lw_in_yz' )
10146          IF ( av == 0 ) THEN
10147             DO  i = nxl, nxr
10148                DO  j = nys, nyn
10149                   DO  k = nzb_do, nzt_do
10150                      local_pf(i,j,k) = rad_lw_in(k,j,i)
10151                   ENDDO
10152                ENDDO
10153             ENDDO
10154          ELSE
10155            IF ( .NOT. ALLOCATED( rad_lw_in_av ) ) THEN
10156               ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10157               rad_lw_in_av = REAL( fill_value, KIND = wp )
10158            ENDIF
10159             DO  i = nxl, nxr
10160                DO  j = nys, nyn 
10161                   DO  k = nzb_do, nzt_do
10162                      local_pf(i,j,k) = rad_lw_in_av(k,j,i)
10163                   ENDDO
10164                ENDDO
10165             ENDDO
10166          ENDIF
10167          IF ( mode == 'xy' )  grid = 'zu'
10168
10169       CASE ( 'rad_lw_out_xy', 'rad_lw_out_xz', 'rad_lw_out_yz' )
10170          IF ( av == 0 ) THEN
10171             DO  i = nxl, nxr
10172                DO  j = nys, nyn
10173                   DO  k = nzb_do, nzt_do
10174                      local_pf(i,j,k) = rad_lw_out(k,j,i)
10175                   ENDDO
10176                ENDDO
10177             ENDDO
10178          ELSE
10179            IF ( .NOT. ALLOCATED( rad_lw_out_av ) ) THEN
10180               ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10181               rad_lw_out_av = REAL( fill_value, KIND = wp )
10182            ENDIF
10183             DO  i = nxl, nxr
10184                DO  j = nys, nyn 
10185                   DO  k = nzb_do, nzt_do
10186                      local_pf(i,j,k) = rad_lw_out_av(k,j,i)
10187                   ENDDO
10188                ENDDO
10189             ENDDO
10190          ENDIF   
10191          IF ( mode == 'xy' )  grid = 'zu'
10192
10193       CASE ( 'rad_lw_cs_hr_xy', 'rad_lw_cs_hr_xz', 'rad_lw_cs_hr_yz' )
10194          IF ( av == 0 ) THEN
10195             DO  i = nxl, nxr
10196                DO  j = nys, nyn
10197                   DO  k = nzb_do, nzt_do
10198                      local_pf(i,j,k) = rad_lw_cs_hr(k,j,i)
10199                   ENDDO
10200                ENDDO
10201             ENDDO
10202          ELSE
10203            IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) ) THEN
10204               ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10205               rad_lw_cs_hr_av = REAL( fill_value, KIND = wp )
10206            ENDIF
10207             DO  i = nxl, nxr
10208                DO  j = nys, nyn 
10209                   DO  k = nzb_do, nzt_do
10210                      local_pf(i,j,k) = rad_lw_cs_hr_av(k,j,i)
10211                   ENDDO
10212                ENDDO
10213             ENDDO
10214          ENDIF
10215          IF ( mode == 'xy' )  grid = 'zw'
10216
10217       CASE ( 'rad_lw_hr_xy', 'rad_lw_hr_xz', 'rad_lw_hr_yz' )
10218          IF ( av == 0 ) THEN
10219             DO  i = nxl, nxr
10220                DO  j = nys, nyn
10221                   DO  k = nzb_do, nzt_do
10222                      local_pf(i,j,k) = rad_lw_hr(k,j,i)
10223                   ENDDO
10224                ENDDO
10225             ENDDO
10226          ELSE
10227            IF ( .NOT. ALLOCATED( rad_lw_hr_av ) ) THEN
10228               ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10229               rad_lw_hr_av= REAL( fill_value, KIND = wp )
10230            ENDIF
10231             DO  i = nxl, nxr
10232                DO  j = nys, nyn 
10233                   DO  k = nzb_do, nzt_do
10234                      local_pf(i,j,k) = rad_lw_hr_av(k,j,i)
10235                   ENDDO
10236                ENDDO
10237             ENDDO
10238          ENDIF
10239          IF ( mode == 'xy' )  grid = 'zw'
10240
10241       CASE ( 'rad_sw_in_xy', 'rad_sw_in_xz', 'rad_sw_in_yz' )
10242          IF ( av == 0 ) THEN
10243             DO  i = nxl, nxr
10244                DO  j = nys, nyn
10245                   DO  k = nzb_do, nzt_do
10246                      local_pf(i,j,k) = rad_sw_in(k,j,i)
10247                   ENDDO
10248                ENDDO
10249             ENDDO
10250          ELSE
10251            IF ( .NOT. ALLOCATED( rad_sw_in_av ) ) THEN
10252               ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10253               rad_sw_in_av = REAL( fill_value, KIND = wp )
10254            ENDIF
10255             DO  i = nxl, nxr
10256                DO  j = nys, nyn 
10257                   DO  k = nzb_do, nzt_do
10258                      local_pf(i,j,k) = rad_sw_in_av(k,j,i)
10259                   ENDDO
10260                ENDDO
10261             ENDDO
10262          ENDIF
10263          IF ( mode == 'xy' )  grid = 'zu'
10264
10265       CASE ( 'rad_sw_out_xy', 'rad_sw_out_xz', 'rad_sw_out_yz' )
10266          IF ( av == 0 ) THEN
10267             DO  i = nxl, nxr
10268                DO  j = nys, nyn
10269                   DO  k = nzb_do, nzt_do
10270                      local_pf(i,j,k) = rad_sw_out(k,j,i)
10271                   ENDDO
10272                ENDDO
10273             ENDDO
10274          ELSE
10275            IF ( .NOT. ALLOCATED( rad_sw_out_av ) ) THEN
10276               ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10277               rad_sw_out_av = REAL( fill_value, KIND = wp )
10278            ENDIF
10279             DO  i = nxl, nxr
10280                DO  j = nys, nyn 
10281                   DO  k = nzb, nzt+1
10282                      local_pf(i,j,k) = rad_sw_out_av(k,j,i)
10283                   ENDDO
10284                ENDDO
10285             ENDDO
10286          ENDIF
10287          IF ( mode == 'xy' )  grid = 'zu'
10288
10289       CASE ( 'rad_sw_cs_hr_xy', 'rad_sw_cs_hr_xz', 'rad_sw_cs_hr_yz' )
10290          IF ( av == 0 ) THEN
10291             DO  i = nxl, nxr
10292                DO  j = nys, nyn
10293                   DO  k = nzb_do, nzt_do
10294                      local_pf(i,j,k) = rad_sw_cs_hr(k,j,i)
10295                   ENDDO
10296                ENDDO
10297             ENDDO
10298          ELSE
10299            IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) ) THEN
10300               ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10301               rad_sw_cs_hr_av = REAL( fill_value, KIND = wp )
10302            ENDIF
10303             DO  i = nxl, nxr
10304                DO  j = nys, nyn 
10305                   DO  k = nzb_do, nzt_do
10306                      local_pf(i,j,k) = rad_sw_cs_hr_av(k,j,i)
10307                   ENDDO
10308                ENDDO
10309             ENDDO
10310          ENDIF
10311          IF ( mode == 'xy' )  grid = 'zw'
10312
10313       CASE ( 'rad_sw_hr_xy', 'rad_sw_hr_xz', 'rad_sw_hr_yz' )
10314          IF ( av == 0 ) THEN
10315             DO  i = nxl, nxr
10316                DO  j = nys, nyn
10317                   DO  k = nzb_do, nzt_do
10318                      local_pf(i,j,k) = rad_sw_hr(k,j,i)
10319                   ENDDO
10320                ENDDO
10321             ENDDO
10322          ELSE
10323            IF ( .NOT. ALLOCATED( rad_sw_hr_av ) ) THEN
10324               ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10325               rad_sw_hr_av = REAL( fill_value, KIND = wp )
10326            ENDIF
10327             DO  i = nxl, nxr
10328                DO  j = nys, nyn 
10329                   DO  k = nzb_do, nzt_do
10330                      local_pf(i,j,k) = rad_sw_hr_av(k,j,i)
10331                   ENDDO
10332                ENDDO
10333             ENDDO
10334          ENDIF
10335          IF ( mode == 'xy' )  grid = 'zw'
10336
10337       CASE DEFAULT
10338          found = .FALSE.
10339          grid  = 'none'
10340
10341    END SELECT
10342 
10343 END SUBROUTINE radiation_data_output_2d
10344
10345
10346!------------------------------------------------------------------------------!
10347!
10348! Description:
10349! ------------
10350!> Subroutine defining 3D output variables
10351!------------------------------------------------------------------------------!
10352 SUBROUTINE radiation_data_output_3d( av, variable, found, local_pf, nzb_do, nzt_do )
10353 
10354
10355    USE indices
10356
10357    USE kinds
10358
10359
10360    IMPLICIT NONE
10361
10362    CHARACTER (LEN=*) ::  variable !<
10363
10364    INTEGER(iwp) ::  av          !<
10365    INTEGER(iwp) ::  i, j, k, l  !<
10366    INTEGER(iwp) ::  nzb_do      !<
10367    INTEGER(iwp) ::  nzt_do      !<
10368
10369    LOGICAL      ::  found       !<
10370
10371    REAL(wp)     ::  fill_value = -999.0_wp    !< value for the _FillValue attribute
10372
10373    REAL(sp), DIMENSION(nxl:nxr,nys:nyn,nzb_do:nzt_do) ::  local_pf !<
10374
10375    CHARACTER (len=varnamelength)                   :: var, surfid
10376    INTEGER(iwp)                                    :: ids,idsint_u,idsint_l,isurf,isvf,isurfs,isurflt,ipcgb
10377    INTEGER(iwp)                                    :: is, js, ks, istat
10378
10379    found = .TRUE.
10380
10381    ids = -1
10382    var = TRIM(variable)
10383    DO i = 0, nd-1
10384        k = len(TRIM(var))
10385        j = len(TRIM(dirname(i)))
10386        IF ( TRIM(var(k-j+1:k)) == TRIM(dirname(i)) )  THEN
10387            ids = i
10388            idsint_u = dirint_u(ids)
10389            idsint_l = dirint_l(ids)
10390            var = var(:k-j)
10391            EXIT
10392        ENDIF
10393    ENDDO
10394    IF ( ids == -1 )  THEN
10395        var = TRIM(variable)
10396    ENDIF
10397
10398    IF ( (var(1:8) == 'rtm_svf_'  .OR.  var(1:8) == 'rtm_dif_')  .AND.  len(TRIM(var)) >= 13 )  THEN
10399!--     svf values to particular surface
10400        surfid = var(9:)
10401        i = index(surfid,'_')
10402        j = index(surfid(i+1:),'_')
10403        READ(surfid(1:i-1),*, iostat=istat ) is
10404        IF ( istat == 0 )  THEN
10405            READ(surfid(i+1:i+j-1),*, iostat=istat ) js
10406        ENDIF
10407        IF ( istat == 0 )  THEN
10408            READ(surfid(i+j+1:),*, iostat=istat ) ks
10409        ENDIF
10410        IF ( istat == 0 )  THEN
10411            var = var(1:7)
10412        ENDIF
10413    ENDIF
10414
10415    local_pf = fill_value
10416
10417    SELECT CASE ( TRIM( var ) )
10418!--   block of large scale radiation model (e.g. RRTMG) output variables
10419      CASE ( 'rad_sw_in' )
10420         IF ( av == 0 )  THEN
10421            DO  i = nxl, nxr
10422               DO  j = nys, nyn
10423                  DO  k = nzb_do, nzt_do
10424                     local_pf(i,j,k) = rad_sw_in(k,j,i)
10425                  ENDDO
10426               ENDDO
10427            ENDDO
10428         ELSE
10429            IF ( .NOT. ALLOCATED( rad_sw_in_av ) ) THEN
10430               ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10431               rad_sw_in_av = REAL( fill_value, KIND = wp )
10432            ENDIF
10433            DO  i = nxl, nxr
10434               DO  j = nys, nyn
10435                  DO  k = nzb_do, nzt_do
10436                     local_pf(i,j,k) = rad_sw_in_av(k,j,i)
10437                  ENDDO
10438               ENDDO
10439            ENDDO
10440         ENDIF
10441
10442      CASE ( 'rad_sw_out' )
10443         IF ( av == 0 )  THEN
10444            DO  i = nxl, nxr
10445               DO  j = nys, nyn
10446                  DO  k = nzb_do, nzt_do
10447                     local_pf(i,j,k) = rad_sw_out(k,j,i)
10448                  ENDDO
10449               ENDDO
10450            ENDDO
10451         ELSE
10452            IF ( .NOT. ALLOCATED( rad_sw_out_av ) ) THEN
10453               ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10454               rad_sw_out_av = REAL( fill_value, KIND = wp )
10455            ENDIF
10456            DO  i = nxl, nxr
10457               DO  j = nys, nyn
10458                  DO  k = nzb_do, nzt_do
10459                     local_pf(i,j,k) = rad_sw_out_av(k,j,i)
10460                  ENDDO
10461               ENDDO
10462            ENDDO
10463         ENDIF
10464
10465      CASE ( 'rad_sw_cs_hr' )
10466         IF ( av == 0 )  THEN
10467            DO  i = nxl, nxr
10468               DO  j = nys, nyn
10469                  DO  k = nzb_do, nzt_do
10470                     local_pf(i,j,k) = rad_sw_cs_hr(k,j,i)
10471                  ENDDO
10472               ENDDO
10473            ENDDO
10474         ELSE
10475            IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) ) THEN
10476               ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10477               rad_sw_cs_hr_av = REAL( fill_value, KIND = wp )
10478            ENDIF
10479            DO  i = nxl, nxr
10480               DO  j = nys, nyn
10481                  DO  k = nzb_do, nzt_do
10482                     local_pf(i,j,k) = rad_sw_cs_hr_av(k,j,i)
10483                  ENDDO
10484               ENDDO
10485            ENDDO
10486         ENDIF
10487
10488      CASE ( 'rad_sw_hr' )
10489         IF ( av == 0 )  THEN
10490            DO  i = nxl, nxr
10491               DO  j = nys, nyn
10492                  DO  k = nzb_do, nzt_do
10493                     local_pf(i,j,k) = rad_sw_hr(k,j,i)
10494                  ENDDO
10495               ENDDO
10496            ENDDO
10497         ELSE
10498            IF ( .NOT. ALLOCATED( rad_sw_hr_av ) ) THEN
10499               ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10500               rad_sw_hr_av = REAL( fill_value, KIND = wp )
10501            ENDIF
10502            DO  i = nxl, nxr
10503               DO  j = nys, nyn
10504                  DO  k = nzb_do, nzt_do
10505                     local_pf(i,j,k) = rad_sw_hr_av(k,j,i)
10506                  ENDDO
10507               ENDDO
10508            ENDDO
10509         ENDIF
10510
10511      CASE ( 'rad_lw_in' )
10512         IF ( av == 0 )  THEN
10513            DO  i = nxl, nxr
10514               DO  j = nys, nyn
10515                  DO  k = nzb_do, nzt_do
10516                     local_pf(i,j,k) = rad_lw_in(k,j,i)
10517                  ENDDO
10518               ENDDO
10519            ENDDO
10520         ELSE
10521            IF ( .NOT. ALLOCATED( rad_lw_in_av ) ) THEN
10522               ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10523               rad_lw_in_av = REAL( fill_value, KIND = wp )
10524            ENDIF
10525            DO  i = nxl, nxr
10526               DO  j = nys, nyn
10527                  DO  k = nzb_do, nzt_do
10528                     local_pf(i,j,k) = rad_lw_in_av(k,j,i)
10529                  ENDDO
10530               ENDDO
10531            ENDDO
10532         ENDIF
10533
10534      CASE ( 'rad_lw_out' )
10535         IF ( av == 0 )  THEN
10536            DO  i = nxl, nxr
10537               DO  j = nys, nyn
10538                  DO  k = nzb_do, nzt_do
10539                     local_pf(i,j,k) = rad_lw_out(k,j,i)
10540                  ENDDO
10541               ENDDO
10542            ENDDO
10543         ELSE
10544            IF ( .NOT. ALLOCATED( rad_lw_out_av ) ) THEN
10545               ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10546               rad_lw_out_av = REAL( fill_value, KIND = wp )
10547            ENDIF
10548            DO  i = nxl, nxr
10549               DO  j = nys, nyn
10550                  DO  k = nzb_do, nzt_do
10551                     local_pf(i,j,k) = rad_lw_out_av(k,j,i)
10552                  ENDDO
10553               ENDDO
10554            ENDDO
10555         ENDIF
10556
10557      CASE ( 'rad_lw_cs_hr' )
10558         IF ( av == 0 )  THEN
10559            DO  i = nxl, nxr
10560               DO  j = nys, nyn
10561                  DO  k = nzb_do, nzt_do
10562                     local_pf(i,j,k) = rad_lw_cs_hr(k,j,i)
10563                  ENDDO
10564               ENDDO
10565            ENDDO
10566         ELSE
10567            IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) ) THEN
10568               ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10569               rad_lw_cs_hr_av = REAL( fill_value, KIND = wp )
10570            ENDIF
10571            DO  i = nxl, nxr
10572               DO  j = nys, nyn
10573                  DO  k = nzb_do, nzt_do
10574                     local_pf(i,j,k) = rad_lw_cs_hr_av(k,j,i)
10575                  ENDDO
10576               ENDDO
10577            ENDDO
10578         ENDIF
10579
10580      CASE ( 'rad_lw_hr' )
10581         IF ( av == 0 )  THEN
10582            DO  i = nxl, nxr
10583               DO  j = nys, nyn
10584                  DO  k = nzb_do, nzt_do
10585                     local_pf(i,j,k) = rad_lw_hr(k,j,i)
10586                  ENDDO
10587               ENDDO
10588            ENDDO
10589         ELSE
10590            IF ( .NOT. ALLOCATED( rad_lw_hr_av ) ) THEN
10591               ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10592              rad_lw_hr_av = REAL( fill_value, KIND = wp )
10593            ENDIF
10594            DO  i = nxl, nxr
10595               DO  j = nys, nyn
10596                  DO  k = nzb_do, nzt_do
10597                     local_pf(i,j,k) = rad_lw_hr_av(k,j,i)
10598                  ENDDO
10599               ENDDO
10600            ENDDO
10601         ENDIF
10602
10603      CASE ( 'rtm_rad_net' )
10604!--     array of complete radiation balance
10605         DO isurf = dirstart(ids), dirend(ids)
10606            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10607               IF ( av == 0 )  THEN
10608                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = &
10609                         surfinsw(isurf) - surfoutsw(isurf) +  surfinlw(isurf) - surfoutlw(isurf)
10610               ELSE
10611                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfradnet_av(isurf)
10612               ENDIF
10613            ENDIF
10614         ENDDO
10615
10616      CASE ( 'rtm_rad_insw' )
10617!--      array of sw radiation falling to surface after i-th reflection
10618         DO isurf = dirstart(ids), dirend(ids)
10619            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10620               IF ( av == 0 )  THEN
10621                 local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinsw(isurf)
10622               ELSE
10623                 local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinsw_av(isurf)
10624               ENDIF
10625            ENDIF
10626         ENDDO
10627
10628      CASE ( 'rtm_rad_inlw' )
10629!--      array of lw radiation falling to surface after i-th reflection
10630         DO isurf = dirstart(ids), dirend(ids)
10631            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10632               IF ( av == 0 )  THEN
10633                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlw(isurf)
10634               ELSE
10635                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlw_av(isurf)
10636               ENDIF
10637             ENDIF
10638         ENDDO
10639
10640      CASE ( 'rtm_rad_inswdir' )
10641!--      array of direct sw radiation falling to surface from sun
10642         DO isurf = dirstart(ids), dirend(ids)
10643            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10644               IF ( av == 0 )  THEN
10645                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdir(isurf)
10646               ELSE
10647                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdir_av(isurf)
10648               ENDIF
10649            ENDIF
10650         ENDDO
10651
10652      CASE ( 'rtm_rad_inswdif' )
10653!--      array of difusion sw radiation falling to surface from sky and borders of the domain
10654         DO isurf = dirstart(ids), dirend(ids)
10655            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10656               IF ( av == 0 )  THEN
10657                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdif(isurf)
10658               ELSE
10659                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdif_av(isurf)
10660               ENDIF
10661            ENDIF
10662         ENDDO
10663
10664      CASE ( 'rtm_rad_inswref' )
10665!--      array of sw radiation falling to surface from reflections
10666         DO isurf = dirstart(ids), dirend(ids)
10667            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10668               IF ( av == 0 )  THEN
10669                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = &
10670                    surfinsw(isurf) - surfinswdir(isurf) - surfinswdif(isurf)
10671               ELSE
10672                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswref_av(isurf)
10673               ENDIF
10674            ENDIF
10675         ENDDO
10676
10677      CASE ( 'rtm_rad_inlwdif' )
10678!--      array of difusion lw radiation falling to surface from sky and borders of the domain
10679         DO isurf = dirstart(ids), dirend(ids)
10680            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10681               IF ( av == 0 )  THEN
10682                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlwdif(isurf)
10683               ELSE
10684                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlwdif_av(isurf)
10685               ENDIF
10686            ENDIF
10687         ENDDO
10688
10689      CASE ( 'rtm_rad_inlwref' )
10690!--      array of lw radiation falling to surface from reflections
10691         DO isurf = dirstart(ids), dirend(ids)
10692            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10693               IF ( av == 0 )  THEN
10694                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlw(isurf) - surfinlwdif(isurf)
10695               ELSE
10696                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlwref_av(isurf)
10697               ENDIF
10698            ENDIF
10699         ENDDO
10700
10701      CASE ( 'rtm_rad_outsw' )
10702!--      array of sw radiation emitted from surface after i-th reflection
10703         DO isurf = dirstart(ids), dirend(ids)
10704            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10705               IF ( av == 0 )  THEN
10706                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutsw(isurf)
10707               ELSE
10708                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutsw_av(isurf)
10709               ENDIF
10710            ENDIF
10711         ENDDO
10712
10713      CASE ( 'rtm_rad_outlw' )
10714!--      array of lw radiation emitted from surface after i-th reflection
10715         DO isurf = dirstart(ids), dirend(ids)
10716            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10717               IF ( av == 0 )  THEN
10718                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutlw(isurf)
10719               ELSE
10720                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutlw_av(isurf)
10721               ENDIF
10722            ENDIF
10723         ENDDO
10724
10725      CASE ( 'rtm_rad_ressw' )
10726!--      average of array of residua of sw radiation absorbed in surface after last reflection
10727         DO isurf = dirstart(ids), dirend(ids)
10728            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10729               IF ( av == 0 )  THEN
10730                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfins(isurf)
10731               ELSE
10732                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfins_av(isurf)
10733               ENDIF
10734            ENDIF
10735         ENDDO
10736
10737      CASE ( 'rtm_rad_reslw' )
10738!--      average of array of residua of lw radiation absorbed in surface after last reflection
10739         DO isurf = dirstart(ids), dirend(ids)
10740            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10741               IF ( av == 0 )  THEN
10742                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinl(isurf)
10743               ELSE
10744                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinl_av(isurf)
10745               ENDIF
10746            ENDIF
10747         ENDDO
10748
10749      CASE ( 'rtm_rad_pc_inlw' )
10750!--      array of lw radiation absorbed by plant canopy
10751         DO ipcgb = 1, npcbl
10752            IF ( av == 0 )  THEN
10753               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinlw(ipcgb)
10754            ELSE
10755               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinlw_av(ipcgb)
10756            ENDIF
10757         ENDDO
10758
10759      CASE ( 'rtm_rad_pc_insw' )
10760!--      array of sw radiation absorbed by plant canopy
10761         DO ipcgb = 1, npcbl
10762            IF ( av == 0 )  THEN
10763              local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinsw(ipcgb)
10764            ELSE
10765              local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinsw_av(ipcgb)
10766            ENDIF
10767         ENDDO
10768
10769      CASE ( 'rtm_rad_pc_inswdir' )
10770!--      array of direct sw radiation absorbed by plant canopy
10771         DO ipcgb = 1, npcbl
10772            IF ( av == 0 )  THEN
10773               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdir(ipcgb)
10774            ELSE
10775               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdir_av(ipcgb)
10776            ENDIF
10777         ENDDO
10778
10779      CASE ( 'rtm_rad_pc_inswdif' )
10780!--      array of diffuse sw radiation absorbed by plant canopy
10781         DO ipcgb = 1, npcbl
10782            IF ( av == 0 )  THEN
10783               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdif(ipcgb)
10784            ELSE
10785               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdif_av(ipcgb)
10786            ENDIF
10787         ENDDO
10788
10789      CASE ( 'rtm_rad_pc_inswref' )
10790!--      array of reflected sw radiation absorbed by plant canopy
10791         DO ipcgb = 1, npcbl
10792            IF ( av == 0 )  THEN
10793               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = &
10794                                    pcbinsw(ipcgb) - pcbinswdir(ipcgb) - pcbinswdif(ipcgb)
10795            ELSE
10796               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswref_av(ipcgb)
10797            ENDIF
10798         ENDDO
10799
10800      CASE ( 'rtm_mrt_sw' )
10801         local_pf = REAL( fill_value, KIND = wp )
10802         IF ( av == 0 )  THEN
10803            DO  l = 1, nmrtbl
10804               local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinsw(l)
10805            ENDDO
10806         ELSE
10807            IF ( ALLOCATED( mrtinsw_av ) ) THEN
10808               DO  l = 1, nmrtbl
10809                  local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinsw_av(l)
10810               ENDDO
10811            ENDIF
10812         ENDIF
10813
10814      CASE ( 'rtm_mrt_lw' )
10815         local_pf = REAL( fill_value, KIND = wp )
10816         IF ( av == 0 )  THEN
10817            DO  l = 1, nmrtbl
10818               local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinlw(l)
10819            ENDDO
10820         ELSE
10821            IF ( ALLOCATED( mrtinlw_av ) ) THEN
10822               DO  l = 1, nmrtbl
10823                  local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinlw_av(l)
10824               ENDDO
10825            ENDIF
10826         ENDIF
10827
10828      CASE ( 'rtm_mrt' )
10829         local_pf = REAL( fill_value, KIND = wp )
10830         IF ( av == 0 )  THEN
10831            DO  l = 1, nmrtbl
10832               local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrt(l)
10833            ENDDO
10834         ELSE
10835            IF ( ALLOCATED( mrt_av ) ) THEN
10836               DO  l = 1, nmrtbl
10837                  local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrt_av(l)
10838               ENDDO
10839            ENDIF
10840         ENDIF
10841!         
10842!--   block of RTM output variables
10843!--   variables are intended mainly for debugging and detailed analyse purposes
10844      CASE ( 'rtm_skyvf' )
10845!     
10846!--      sky view factor
10847         DO isurf = dirstart(ids), dirend(ids)
10848            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10849               local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = skyvf(isurf)
10850            ENDIF
10851         ENDDO
10852
10853      CASE ( 'rtm_skyvft' )
10854!
10855!--      sky view factor
10856         DO isurf = dirstart(ids), dirend(ids)
10857            IF ( surfl(id,isurf) == ids )  THEN
10858               local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = skyvft(isurf)
10859            ENDIF
10860         ENDDO
10861
10862      CASE ( 'rtm_svf', 'rtm_dif' )
10863!
10864!--      shape view factors or iradiance factors to selected surface
10865         IF ( TRIM(var)=='rtm_svf' )  THEN
10866             k = 1
10867         ELSE
10868             k = 2
10869         ENDIF
10870         DO isvf = 1, nsvfl
10871            isurflt = svfsurf(1, isvf)
10872            isurfs = svfsurf(2, isvf)
10873
10874            IF ( surf(ix,isurfs) == is  .AND.  surf(iy,isurfs) == js  .AND. surf(iz,isurfs) == ks  .AND. &
10875                 (surf(id,isurfs) == idsint_u .OR. surfl(id,isurfs) == idsint_l ) ) THEN
10876!
10877!--            correct source surface
10878               local_pf(surfl(ix,isurflt),surfl(iy,isurflt),surfl(iz,isurflt)) = svf(k,isvf)
10879            ENDIF
10880         ENDDO
10881
10882      CASE ( 'rtm_surfalb' )
10883!
10884!--      surface albedo
10885         DO isurf = dirstart(ids), dirend(ids)
10886            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10887               local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = albedo_surf(isurf)
10888            ENDIF
10889         ENDDO
10890
10891      CASE ( 'rtm_surfemis' )
10892!
10893!--      surface emissivity, weighted average
10894         DO isurf = dirstart(ids), dirend(ids)
10895            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10896               local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = emiss_surf(isurf)
10897            ENDIF
10898         ENDDO
10899
10900      CASE DEFAULT
10901         found = .FALSE.
10902
10903    END SELECT
10904
10905
10906 END SUBROUTINE radiation_data_output_3d
10907
10908!------------------------------------------------------------------------------!
10909!
10910! Description:
10911! ------------
10912!> Subroutine defining masked data output
10913!------------------------------------------------------------------------------!
10914 SUBROUTINE radiation_data_output_mask( av, variable, found, local_pf )
10915 
10916    USE control_parameters
10917       
10918    USE indices
10919   
10920    USE kinds
10921   
10922
10923    IMPLICIT NONE
10924
10925    CHARACTER (LEN=*) ::  variable   !<
10926
10927    CHARACTER(LEN=5) ::  grid        !< flag to distinquish between staggered grids
10928
10929    INTEGER(iwp) ::  av              !<
10930    INTEGER(iwp) ::  i               !<
10931    INTEGER(iwp) ::  j               !<
10932    INTEGER(iwp) ::  k               !<
10933    INTEGER(iwp) ::  topo_top_ind    !< k index of highest horizontal surface
10934
10935    LOGICAL ::  found                !< true if output array was found
10936    LOGICAL ::  resorted             !< true if array is resorted
10937
10938
10939    REAL(wp),                                                                  &
10940       DIMENSION(mask_size_l(mid,1),mask_size_l(mid,2),mask_size_l(mid,3)) ::  &
10941          local_pf   !<
10942
10943    REAL(wp), DIMENSION(:,:,:), POINTER ::  to_be_resorted  !< points to array which needs to be resorted for output
10944
10945
10946    found    = .TRUE.
10947    grid     = 's'
10948    resorted = .FALSE.
10949
10950    SELECT CASE ( TRIM( variable ) )
10951
10952
10953       CASE ( 'rad_lw_in' )
10954          IF ( av == 0 )  THEN
10955             to_be_resorted => rad_lw_in
10956          ELSE
10957             to_be_resorted => rad_lw_in_av
10958          ENDIF
10959
10960       CASE ( 'rad_lw_out' )
10961          IF ( av == 0 )  THEN
10962             to_be_resorted => rad_lw_out
10963          ELSE
10964             to_be_resorted => rad_lw_out_av
10965          ENDIF
10966
10967       CASE ( 'rad_lw_cs_hr' )
10968          IF ( av == 0 )  THEN
10969             to_be_resorted => rad_lw_cs_hr
10970          ELSE
10971             to_be_resorted => rad_lw_cs_hr_av
10972          ENDIF
10973
10974       CASE ( 'rad_lw_hr' )
10975          IF ( av == 0 )  THEN
10976             to_be_resorted => rad_lw_hr
10977          ELSE
10978             to_be_resorted => rad_lw_hr_av
10979          ENDIF
10980
10981       CASE ( 'rad_sw_in' )
10982          IF ( av == 0 )  THEN
10983             to_be_resorted => rad_sw_in
10984          ELSE
10985             to_be_resorted => rad_sw_in_av
10986          ENDIF
10987
10988       CASE ( 'rad_sw_out' )
10989          IF ( av == 0 )  THEN
10990             to_be_resorted => rad_sw_out
10991          ELSE
10992             to_be_resorted => rad_sw_out_av
10993          ENDIF
10994
10995       CASE ( 'rad_sw_cs_hr' )
10996          IF ( av == 0 )  THEN
10997             to_be_resorted => rad_sw_cs_hr
10998          ELSE
10999             to_be_resorted => rad_sw_cs_hr_av
11000          ENDIF
11001
11002       CASE ( 'rad_sw_hr' )
11003          IF ( av == 0 )  THEN
11004             to_be_resorted => rad_sw_hr
11005          ELSE
11006             to_be_resorted => rad_sw_hr_av
11007          ENDIF
11008
11009       CASE DEFAULT
11010          found = .FALSE.
11011
11012    END SELECT
11013
11014!
11015!-- Resort the array to be output, if not done above
11016    IF ( .NOT. resorted )  THEN
11017       IF ( .NOT. mask_surface(mid) )  THEN
11018!
11019!--       Default masked output
11020          DO  i = 1, mask_size_l(mid,1)
11021             DO  j = 1, mask_size_l(mid,2)
11022                DO  k = 1, mask_size_l(mid,3)
11023                   local_pf(i,j,k) =  to_be_resorted(mask_k(mid,k), &
11024                                      mask_j(mid,j),mask_i(mid,i))
11025                ENDDO
11026             ENDDO
11027          ENDDO
11028
11029       ELSE
11030!
11031!--       Terrain-following masked output
11032          DO  i = 1, mask_size_l(mid,1)
11033             DO  j = 1, mask_size_l(mid,2)
11034!
11035!--             Get k index of highest horizontal surface
11036                topo_top_ind = get_topography_top_index_ji( mask_j(mid,j), &
11037                                                            mask_i(mid,i), &
11038                                                            grid )
11039!
11040!--             Save output array
11041                DO  k = 1, mask_size_l(mid,3)
11042                   local_pf(i,j,k) = to_be_resorted(                       &
11043                                          MIN( topo_top_ind+mask_k(mid,k), &
11044                                               nzt+1 ),                    &
11045                                          mask_j(mid,j),                   &
11046                                          mask_i(mid,i)                     )
11047                ENDDO
11048             ENDDO
11049          ENDDO
11050
11051       ENDIF
11052    ENDIF
11053
11054
11055
11056 END SUBROUTINE radiation_data_output_mask
11057
11058
11059!------------------------------------------------------------------------------!
11060! Description:
11061! ------------
11062!> Subroutine writes local (subdomain) restart data
11063!------------------------------------------------------------------------------!
11064 SUBROUTINE radiation_wrd_local
11065
11066
11067    IMPLICIT NONE
11068
11069
11070    IF ( ALLOCATED( rad_net_av ) )  THEN
11071       CALL wrd_write_string( 'rad_net_av' )
11072       WRITE ( 14 )  rad_net_av
11073    ENDIF
11074   
11075    IF ( ALLOCATED( rad_lw_in_xy_av ) )  THEN
11076       CALL wrd_write_string( 'rad_lw_in_xy_av' )
11077       WRITE ( 14 )  rad_lw_in_xy_av
11078    ENDIF
11079   
11080    IF ( ALLOCATED( rad_lw_out_xy_av ) )  THEN
11081       CALL wrd_write_string( 'rad_lw_out_xy_av' )
11082       WRITE ( 14 )  rad_lw_out_xy_av
11083    ENDIF
11084   
11085    IF ( ALLOCATED( rad_sw_in_xy_av ) )  THEN
11086       CALL wrd_write_string( 'rad_sw_in_xy_av' )
11087       WRITE ( 14 )  rad_sw_in_xy_av
11088    ENDIF
11089   
11090    IF ( ALLOCATED( rad_sw_out_xy_av ) )  THEN
11091       CALL wrd_write_string( 'rad_sw_out_xy_av' )
11092       WRITE ( 14 )  rad_sw_out_xy_av
11093    ENDIF
11094
11095    IF ( ALLOCATED( rad_lw_in ) )  THEN
11096       CALL wrd_write_string( 'rad_lw_in' )
11097       WRITE ( 14 )  rad_lw_in
11098    ENDIF
11099
11100    IF ( ALLOCATED( rad_lw_in_av ) )  THEN
11101       CALL wrd_write_string( 'rad_lw_in_av' )
11102       WRITE ( 14 )  rad_lw_in_av
11103    ENDIF
11104
11105    IF ( ALLOCATED( rad_lw_out ) )  THEN
11106       CALL wrd_write_string( 'rad_lw_out' )
11107       WRITE ( 14 )  rad_lw_out
11108    ENDIF
11109
11110    IF ( ALLOCATED( rad_lw_out_av) )  THEN
11111       CALL wrd_write_string( 'rad_lw_out_av' )
11112       WRITE ( 14 )  rad_lw_out_av
11113    ENDIF
11114
11115    IF ( ALLOCATED( rad_lw_cs_hr) )  THEN
11116       CALL wrd_write_string( 'rad_lw_cs_hr' )
11117       WRITE ( 14 )  rad_lw_cs_hr
11118    ENDIF
11119
11120    IF ( ALLOCATED( rad_lw_cs_hr_av) )  THEN
11121       CALL wrd_write_string( 'rad_lw_cs_hr_av' )
11122       WRITE ( 14 )  rad_lw_cs_hr_av
11123    ENDIF
11124
11125    IF ( ALLOCATED( rad_lw_hr) )  THEN
11126       CALL wrd_write_string( 'rad_lw_hr' )
11127       WRITE ( 14 )  rad_lw_hr
11128    ENDIF
11129
11130    IF ( ALLOCATED( rad_lw_hr_av) )  THEN
11131       CALL wrd_write_string( 'rad_lw_hr_av' )
11132       WRITE ( 14 )  rad_lw_hr_av
11133    ENDIF
11134
11135    IF ( ALLOCATED( rad_sw_in) )  THEN
11136       CALL wrd_write_string( 'rad_sw_in' )
11137       WRITE ( 14 )  rad_sw_in
11138    ENDIF
11139
11140    IF ( ALLOCATED( rad_sw_in_av) )  THEN
11141       CALL wrd_write_string( 'rad_sw_in_av' )
11142       WRITE ( 14 )  rad_sw_in_av
11143    ENDIF
11144
11145    IF ( ALLOCATED( rad_sw_out) )  THEN
11146       CALL wrd_write_string( 'rad_sw_out' )
11147       WRITE ( 14 )  rad_sw_out
11148    ENDIF
11149
11150    IF ( ALLOCATED( rad_sw_out_av) )  THEN
11151       CALL wrd_write_string( 'rad_sw_out_av' )
11152       WRITE ( 14 )  rad_sw_out_av
11153    ENDIF
11154
11155    IF ( ALLOCATED( rad_sw_cs_hr) )  THEN
11156       CALL wrd_write_string( 'rad_sw_cs_hr' )
11157       WRITE ( 14 )  rad_sw_cs_hr
11158    ENDIF
11159
11160    IF ( ALLOCATED( rad_sw_cs_hr_av) )  THEN
11161       CALL wrd_write_string( 'rad_sw_cs_hr_av' )
11162       WRITE ( 14 )  rad_sw_cs_hr_av
11163    ENDIF
11164
11165    IF ( ALLOCATED( rad_sw_hr) )  THEN
11166       CALL wrd_write_string( 'rad_sw_hr' )
11167       WRITE ( 14 )  rad_sw_hr
11168    ENDIF
11169
11170    IF ( ALLOCATED( rad_sw_hr_av) )  THEN
11171       CALL wrd_write_string( 'rad_sw_hr_av' )
11172       WRITE ( 14 )  rad_sw_hr_av
11173    ENDIF
11174
11175
11176 END SUBROUTINE radiation_wrd_local
11177
11178!------------------------------------------------------------------------------!
11179! Description:
11180! ------------
11181!> Subroutine reads local (subdomain) restart data
11182!------------------------------------------------------------------------------!
11183 SUBROUTINE radiation_rrd_local( k, nxlf, nxlc, nxl_on_file, nxrf, nxrc,       &
11184                                nxr_on_file, nynf, nync, nyn_on_file, nysf,    &
11185                                nysc, nys_on_file, tmp_2d, tmp_3d, found )
11186 
11187
11188    USE control_parameters
11189       
11190    USE indices
11191   
11192    USE kinds
11193   
11194    USE pegrid
11195
11196
11197    IMPLICIT NONE
11198
11199    INTEGER(iwp) ::  k               !<
11200    INTEGER(iwp) ::  nxlc            !<
11201    INTEGER(iwp) ::  nxlf            !<
11202    INTEGER(iwp) ::  nxl_on_file     !<
11203    INTEGER(iwp) ::  nxrc            !<
11204    INTEGER(iwp) ::  nxrf            !<
11205    INTEGER(iwp) ::  nxr_on_file     !<
11206    INTEGER(iwp) ::  nync            !<
11207    INTEGER(iwp) ::  nynf            !<
11208    INTEGER(iwp) ::  nyn_on_file     !<
11209    INTEGER(iwp) ::  nysc            !<
11210    INTEGER(iwp) ::  nysf            !<
11211    INTEGER(iwp) ::  nys_on_file     !<
11212
11213    LOGICAL, INTENT(OUT)  :: found
11214
11215    REAL(wp), DIMENSION(nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_2d   !<
11216
11217    REAL(wp), DIMENSION(nzb:nzt+1,nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_3d   !<
11218
11219    REAL(wp), DIMENSION(0:0,nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_3d2   !<
11220
11221
11222    found = .TRUE.
11223
11224
11225    SELECT CASE ( restart_string(1:length) )
11226
11227       CASE ( 'rad_net_av' )
11228          IF ( .NOT. ALLOCATED( rad_net_av ) )  THEN
11229             ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
11230          ENDIF 
11231          IF ( k == 1 )  READ ( 13 )  tmp_2d
11232          rad_net_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =           &
11233                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11234                       
11235       CASE ( 'rad_lw_in_xy_av' )
11236          IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) )  THEN
11237             ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
11238          ENDIF 
11239          IF ( k == 1 )  READ ( 13 )  tmp_2d
11240          rad_lw_in_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =      &
11241                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11242                       
11243       CASE ( 'rad_lw_out_xy_av' )
11244          IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) )  THEN
11245             ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
11246          ENDIF 
11247          IF ( k == 1 )  READ ( 13 )  tmp_2d
11248          rad_lw_out_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =     &
11249                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11250                       
11251       CASE ( 'rad_sw_in_xy_av' )
11252          IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) )  THEN
11253             ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
11254          ENDIF 
11255          IF ( k == 1 )  READ ( 13 )  tmp_2d
11256          rad_sw_in_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =      &
11257                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11258                       
11259       CASE ( 'rad_sw_out_xy_av' )
11260          IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) )  THEN
11261             ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
11262          ENDIF 
11263          IF ( k == 1 )  READ ( 13 )  tmp_2d
11264          rad_sw_out_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =     &
11265                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11266                       
11267       CASE ( 'rad_lw_in' )
11268          IF ( .NOT. ALLOCATED( rad_lw_in ) )  THEN
11269             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11270                  radiation_scheme == 'constant')  THEN
11271                ALLOCATE( rad_lw_in(0:0,nysg:nyng,nxlg:nxrg) )
11272             ELSE
11273                ALLOCATE( rad_lw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11274             ENDIF
11275          ENDIF 
11276          IF ( k == 1 )  THEN
11277             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11278                  radiation_scheme == 'constant')  THEN
11279                READ ( 13 )  tmp_3d2
11280                rad_lw_in(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =   &
11281                   tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11282             ELSE
11283                READ ( 13 )  tmp_3d
11284                rad_lw_in(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11285                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11286             ENDIF
11287          ENDIF
11288
11289       CASE ( 'rad_lw_in_av' )
11290          IF ( .NOT. ALLOCATED( rad_lw_in_av ) )  THEN
11291             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11292                  radiation_scheme == 'constant')  THEN
11293                ALLOCATE( rad_lw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
11294             ELSE
11295                ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11296             ENDIF
11297          ENDIF 
11298          IF ( k == 1 )  THEN
11299             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11300                  radiation_scheme == 'constant')  THEN
11301                READ ( 13 )  tmp_3d2
11302                rad_lw_in_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =&
11303                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11304             ELSE
11305                READ ( 13 )  tmp_3d
11306                rad_lw_in_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11307                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11308             ENDIF
11309          ENDIF
11310
11311       CASE ( 'rad_lw_out' )
11312          IF ( .NOT. ALLOCATED( rad_lw_out ) )  THEN
11313             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11314                  radiation_scheme == 'constant')  THEN
11315                ALLOCATE( rad_lw_out(0:0,nysg:nyng,nxlg:nxrg) )
11316             ELSE
11317                ALLOCATE( rad_lw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11318             ENDIF
11319          ENDIF 
11320          IF ( k == 1 )  THEN
11321             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11322                  radiation_scheme == 'constant')  THEN
11323                READ ( 13 )  tmp_3d2
11324                rad_lw_out(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11325                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11326             ELSE
11327                READ ( 13 )  tmp_3d
11328                rad_lw_out(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =    &
11329                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11330             ENDIF
11331          ENDIF
11332
11333       CASE ( 'rad_lw_out_av' )
11334          IF ( .NOT. ALLOCATED( rad_lw_out_av ) )  THEN
11335             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11336                  radiation_scheme == 'constant')  THEN
11337                ALLOCATE( rad_lw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
11338             ELSE
11339                ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11340             ENDIF
11341          ENDIF 
11342          IF ( k == 1 )  THEN
11343             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11344                  radiation_scheme == 'constant')  THEN
11345                READ ( 13 )  tmp_3d2
11346                rad_lw_out_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) &
11347                   = tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11348             ELSE
11349                READ ( 13 )  tmp_3d
11350                rad_lw_out_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &
11351                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11352             ENDIF
11353          ENDIF
11354
11355       CASE ( 'rad_lw_cs_hr' )
11356          IF ( .NOT. ALLOCATED( rad_lw_cs_hr ) )  THEN
11357             ALLOCATE( rad_lw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11358          ENDIF
11359          IF ( k == 1 )  READ ( 13 )  tmp_3d
11360          rad_lw_cs_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11361                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11362
11363       CASE ( 'rad_lw_cs_hr_av' )
11364          IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) )  THEN
11365             ALLOCATE( rad_lw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11366          ENDIF
11367          IF ( k == 1 )  READ ( 13 )  tmp_3d
11368          rad_lw_cs_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11369                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11370
11371       CASE ( 'rad_lw_hr' )
11372          IF ( .NOT. ALLOCATED( rad_lw_hr ) )  THEN
11373             ALLOCATE( rad_lw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11374          ENDIF
11375          IF ( k == 1 )  READ ( 13 )  tmp_3d
11376          rad_lw_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =           &
11377                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11378
11379       CASE ( 'rad_lw_hr_av' )
11380          IF ( .NOT. ALLOCATED( rad_lw_hr_av ) )  THEN
11381             ALLOCATE( rad_lw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11382          ENDIF
11383          IF ( k == 1 )  READ ( 13 )  tmp_3d
11384          rad_lw_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11385                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11386
11387       CASE ( 'rad_sw_in' )
11388          IF ( .NOT. ALLOCATED( rad_sw_in ) )  THEN
11389             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11390                  radiation_scheme == 'constant')  THEN
11391                ALLOCATE( rad_sw_in(0:0,nysg:nyng,nxlg:nxrg) )
11392             ELSE
11393                ALLOCATE( rad_sw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11394             ENDIF
11395          ENDIF 
11396          IF ( k == 1 )  THEN
11397             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11398                  radiation_scheme == 'constant')  THEN
11399                READ ( 13 )  tmp_3d2
11400                rad_sw_in(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =   &
11401                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11402             ELSE
11403                READ ( 13 )  tmp_3d
11404                rad_sw_in(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11405                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11406             ENDIF
11407          ENDIF
11408
11409       CASE ( 'rad_sw_in_av' )
11410          IF ( .NOT. ALLOCATED( rad_sw_in_av ) )  THEN
11411             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11412                  radiation_scheme == 'constant')  THEN
11413                ALLOCATE( rad_sw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
11414             ELSE
11415                ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11416             ENDIF
11417          ENDIF 
11418          IF ( k == 1 )  THEN
11419             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11420                  radiation_scheme == 'constant')  THEN
11421                READ ( 13 )  tmp_3d2
11422                rad_sw_in_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =&
11423                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11424             ELSE
11425                READ ( 13 )  tmp_3d
11426                rad_sw_in_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11427                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11428             ENDIF
11429          ENDIF
11430
11431       CASE ( 'rad_sw_out' )
11432          IF ( .NOT. ALLOCATED( rad_sw_out ) )  THEN
11433             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11434                  radiation_scheme == 'constant')  THEN
11435                ALLOCATE( rad_sw_out(0:0,nysg:nyng,nxlg:nxrg) )
11436             ELSE
11437                ALLOCATE( rad_sw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11438             ENDIF
11439          ENDIF 
11440          IF ( k == 1 )  THEN
11441             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11442                  radiation_scheme == 'constant')  THEN
11443                READ ( 13 )  tmp_3d2
11444                rad_sw_out(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11445                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11446             ELSE
11447                READ ( 13 )  tmp_3d
11448                rad_sw_out(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =    &
11449                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11450             ENDIF
11451          ENDIF
11452
11453       CASE ( 'rad_sw_out_av' )
11454          IF ( .NOT. ALLOCATED( rad_sw_out_av ) )  THEN
11455             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11456                  radiation_scheme == 'constant')  THEN
11457                ALLOCATE( rad_sw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
11458             ELSE
11459                ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11460             ENDIF
11461          ENDIF 
11462          IF ( k == 1 )  THEN
11463             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11464                  radiation_scheme == 'constant')  THEN
11465                READ ( 13 )  tmp_3d2
11466                rad_sw_out_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) &
11467                   = tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11468             ELSE
11469                READ ( 13 )  tmp_3d
11470                rad_sw_out_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &
11471                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11472             ENDIF
11473          ENDIF
11474
11475       CASE ( 'rad_sw_cs_hr' )
11476          IF ( .NOT. ALLOCATED( rad_sw_cs_hr ) )  THEN
11477             ALLOCATE( rad_sw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11478          ENDIF
11479          IF ( k == 1 )  READ ( 13 )  tmp_3d
11480          rad_sw_cs_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11481                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11482
11483       CASE ( 'rad_sw_cs_hr_av' )
11484          IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) )  THEN
11485             ALLOCATE( rad_sw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11486          ENDIF
11487          IF ( k == 1 )  READ ( 13 )  tmp_3d
11488          rad_sw_cs_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11489                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11490
11491       CASE ( 'rad_sw_hr' )
11492          IF ( .NOT. ALLOCATED( rad_sw_hr ) )  THEN
11493             ALLOCATE( rad_sw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11494          ENDIF
11495          IF ( k == 1 )  READ ( 13 )  tmp_3d
11496          rad_sw_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =           &
11497                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11498
11499       CASE ( 'rad_sw_hr_av' )
11500          IF ( .NOT. ALLOCATED( rad_sw_hr_av ) )  THEN
11501             ALLOCATE( rad_sw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11502          ENDIF
11503          IF ( k == 1 )  READ ( 13 )  tmp_3d
11504          rad_lw_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11505                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11506
11507       CASE DEFAULT
11508
11509          found = .FALSE.
11510
11511    END SELECT
11512
11513 END SUBROUTINE radiation_rrd_local
11514
11515
11516 END MODULE radiation_model_mod
Note: See TracBrowser for help on using the repository browser.