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

Last change on this file since 3859 was 3859, checked in by maronga, 6 years ago

comments in radiation model updated, minor bugfix in palm_csd

  • 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: 499.2 KB
Line 
1!> @file radiation_model_mod.f90
2!------------------------------------------------------------------------------!
3! This file is part of the PALM model system.
4!
5! PALM is free software: you can redistribute it and/or modify it under the
6! terms of the GNU General Public License as published by the Free Software
7! Foundation, either version 3 of the License, or (at your option) any later
8! version.
9!
10! PALM is distributed in the hope that it will be useful, but WITHOUT ANY
11! WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12! A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
13!
14! You should have received a copy of the GNU General Public License along with
15! PALM. If not, see <http://www.gnu.org/licenses/>.
16!
17! Copyright 2015-2018 Institute of Computer Science of the
18!                     Czech Academy of Sciences, Prague
19! Copyright 2015-2018 Czech Technical University in Prague
20! Copyright 1997-2019 Leibniz Universitaet Hannover
21!------------------------------------------------------------------------------!
22!
23! Current revisions:
24! ------------------
25!
26!
27! Former revisions:
28! -----------------
29! $Id: radiation_model_mod.f90 3859 2019-04-03 20:30:31Z maronga $
30! Added some descriptions
31!
32! 3847 2019-04-01 14:51:44Z suehring
33! Implement check for dt_radiation (must be > 0)
34!
35! 3846 2019-04-01 13:55:30Z suehring
36! unused variable removed
37!
38! 3814 2019-03-26 08:40:31Z pavelkrc
39! Change zenith(0:0) and others to scalar.
40! Code review.
41! Rename exported nzu, nzp and related variables due to name conflict
42!
43! 3771 2019-02-28 12:19:33Z raasch
44! rrtmg preprocessor for directives moved/added, save attribute added to temporary
45! pointers to avoid compiler warnings about outlived pointer targets,
46! statement added to avoid compiler warning about unused variable
47!
48! 3769 2019-02-28 10:16:49Z moh.hefny
49! removed unused variables and subroutine radiation_radflux_gridbox
50!
51! 3767 2019-02-27 08:18:02Z raasch
52! unused variable for file index removed from rrd-subroutines parameter list
53!
54! 3760 2019-02-21 18:47:35Z moh.hefny
55! Bugfix: initialized simulated_time before calculating solar position
56! to enable restart option with reading in SVF from file(s).
57!
58! 3754 2019-02-19 17:02:26Z kanani
59! (resler, pavelkrc)
60! Bugfixes: add further required MRT factors to read/write_svf,
61! fix for aggregating view factors to eliminate local noise in reflected
62! irradiance at mutually close surfaces (corners, presence of trees) in the
63! angular discretization scheme.
64!
65! 3752 2019-02-19 09:37:22Z resler
66! added read/write number of MRT factors to the respective routines
67!
68! 3705 2019-01-29 19:56:39Z suehring
69! Make variables that are sampled in virtual measurement module public
70!
71! 3704 2019-01-29 19:51:41Z suehring
72! Some interface calls moved to module_interface + cleanup
73!
74! 3667 2019-01-10 14:26:24Z schwenkel
75! Modified check for rrtmg input files
76!
77! 3655 2019-01-07 16:51:22Z knoop
78! nopointer option removed
79!
80! 3633 2018-12-17 16:17:57Z schwenkel
81! Include check for rrtmg files
82!
83! 3630 2018-12-17 11:04:17Z knoop
84! - fix initialization of date and time after calling zenith
85! - fix a bug in radiation_solar_pos
86!
87! 3616 2018-12-10 09:44:36Z Salim
88! fix manipulation of time variables in radiation_presimulate_solar_pos
89!
90! 3608 2018-12-07 12:59:57Z suehring $
91! Bugfix radiation output
92!
93! 3607 2018-12-07 11:56:58Z suehring
94! Output of radiation-related quantities migrated to radiation_model_mod.
95!
96! 3589 2018-11-30 15:09:51Z suehring
97! Remove erroneous UTF encoding
98!
99! 3572 2018-11-28 11:40:28Z suehring
100! Add filling the short- and longwave radiation flux arrays (e.g. diffuse,
101! direct, reflected, resedual) for all surfaces. This is required to surface
102! outputs in suface_output_mod. (M. Salim)
103!
104! 3571 2018-11-28 09:24:03Z moh.hefny
105! Add an epsilon value to compare values in if statement to fix possible
106! precsion related errors in raytrace routines.
107!
108! 3524 2018-11-14 13:36:44Z raasch
109! missing cpp-directives added
110!
111! 3495 2018-11-06 15:22:17Z kanani
112! Resort control_parameters ONLY list,
113! From branch radiation@3491 moh.hefny:
114! bugfix in calculating the apparent solar positions by updating
115! the simulated time so that the actual time is correct.
116!
117! 3464 2018-10-30 18:08:55Z kanani
118! From branch resler@3462, pavelkrc:
119! add MRT shaping function for human
120!
121! 3449 2018-10-29 19:36:56Z suehring
122! New RTM version 3.0: (Pavel Krc, Jaroslav Resler, ICS, Prague)
123!   - Interaction of plant canopy with LW radiation
124!   - Transpiration from resolved plant canopy dependent on radiation
125!     called from RTM
126!
127!
128! 3435 2018-10-26 18:25:44Z gronemeier
129! - workaround: return unit=illegal in check_data_output for certain variables
130!   when check called from init_masks
131! - Use pointer in masked output to reduce code redundancies
132! - Add terrain-following masked output
133!
134! 3424 2018-10-25 07:29:10Z gronemeier
135! bugfix: add rad_lw_in, rad_lw_out, rad_sw_out to radiation_check_data_output
136!
137! 3378 2018-10-19 12:34:59Z kanani
138! merge from radiation branch (r3362) into trunk
139! (moh.hefny):
140! - removed read/write_svf_on_init and read_dist_max_svf (not used anymore)
141! - bugfix nzut > nzpt in calculating maxboxes
142!
143! 3372 2018-10-18 14:03:19Z raasch
144! bugfix: kind type of 2nd argument of mpi_win_allocate changed, misplaced
145!         __parallel directive
146!
147! 3351 2018-10-15 18:40:42Z suehring
148! Do not overwrite values of spectral and broadband albedo during initialization
149! if they are already initialized in the urban-surface model via ASCII input.
150!
151! 3337 2018-10-12 15:17:09Z kanani
152! - New RTM version 2.9: (Pavel Krc, Jaroslav Resler, ICS, Prague)
153!   added calculation of the MRT inside the RTM module
154!   MRT fluxes are consequently used in the new biometeorology module
155!   for calculation of biological indices (MRT, PET)
156!   Fixes of v. 2.5 and SVN trunk:
157!    - proper initialization of rad_net_l
158!    - make arrays nsurfs and surfstart TARGET to prevent some MPI problems
159!    - initialization of arrays used in MPI one-sided operation as 1-D arrays
160!      to prevent problems with some MPI/compiler combinations
161!    - fix indexing of target displacement in subroutine request_itarget to
162!      consider nzub
163!    - fix LAD dimmension range in PCB calculation
164!    - check ierr in all MPI calls
165!    - use proper per-gridbox sky and diffuse irradiance
166!    - fix shading for reflected irradiance
167!    - clear away the residuals of "atmospheric surfaces" implementation
168!    - fix rounding bug in raytrace_2d introduced in SVN trunk
169! - New RTM version 2.5: (Pavel Krc, Jaroslav Resler, ICS, Prague)
170!   can use angular discretization for all SVF
171!   (i.e. reflected and emitted radiation in addition to direct and diffuse),
172!   allowing for much better scaling wih high resoltion and/or complex terrain
173! - Unite array grow factors
174! - Fix slightly shifted terrain height in raytrace_2d
175! - Use more efficient MPI_Win_allocate for reverse gridsurf index
176! - Fix random MPI RMA bugs on Intel compilers
177! - Fix approx. double plant canopy sink values for reflected radiation
178! - Fix mostly missing plant canopy sinks for direct radiation
179! - Fix discretization errors for plant canopy sink in diffuse radiation
180! - Fix rounding errors in raytrace_2d
181!
182! 3274 2018-09-24 15:42:55Z knoop
183! Modularization of all bulk cloud physics code components
184!
185! 3272 2018-09-24 10:16:32Z suehring
186! - split direct and diffusion shortwave radiation using RRTMG rather than using
187!   calc_diffusion_radiation, in case of RRTMG
188! - removed the namelist variable split_diffusion_radiation. Now splitting depends
189!   on the choise of radiation radiation scheme
190! - removed calculating the rdiation flux for surfaces at the radiation scheme
191!   in case of using RTM since it will be calculated anyway in the radiation
192!   interaction routine.
193! - set SW radiation flux for surfaces to zero at night in case of no RTM is used
194! - precalculate the unit vector yxdir of ray direction to avoid the temporarly
195!   array allocation during the subroutine call
196! - fixed a bug in calculating the max number of boxes ray can cross in the domain
197!
198! 3264 2018-09-20 13:54:11Z moh.hefny
199! Bugfix in raytrace_2d calls
200!
201! 3248 2018-09-14 09:42:06Z sward
202! Minor formating changes
203!
204! 3246 2018-09-13 15:14:50Z sward
205! Added error handling for input namelist via parin_fail_message
206!
207! 3241 2018-09-12 15:02:00Z raasch
208! unused variables removed or commented
209!
210! 3233 2018-09-07 13:21:24Z schwenkel
211! Adapted for the use of cloud_droplets
212!
213! 3230 2018-09-05 09:29:05Z schwenkel
214! Bugfix in radiation_constant_surf: changed (10.0 - emissivity_urb) to
215! (1.0 - emissivity_urb)
216!
217! 3226 2018-08-31 12:27:09Z suehring
218! Bugfixes in calculation of sky-view factors and canopy-sink factors.
219!
220! 3186 2018-07-30 17:07:14Z suehring
221! Remove print statement
222!
223! 3180 2018-07-27 11:00:56Z suehring
224! Revise concept for calculation of effective radiative temperature and mapping
225! of radiative heating
226!
227! 3175 2018-07-26 14:07:38Z suehring
228! Bugfix for commit 3172
229!
230! 3173 2018-07-26 12:55:23Z suehring
231! Revise output of surface radiation quantities in case of overhanging
232! structures
233!
234! 3172 2018-07-26 12:06:06Z suehring
235! Bugfixes:
236!  - temporal work-around for calculation of effective radiative surface
237!    temperature
238!  - prevent positive solar radiation during nighttime
239!
240! 3170 2018-07-25 15:19:37Z suehring
241! Bugfix, map signle-column radiation forcing profiles on top of any topography
242!
243! 3156 2018-07-19 16:30:54Z knoop
244! Bugfix: replaced usage of the pt array with the surf%pt_surface array
245!
246! 3137 2018-07-17 06:44:21Z maronga
247! String length for trace_names fixed
248!
249! 3127 2018-07-15 08:01:25Z maronga
250! A few pavement parameters updated.
251!
252! 3123 2018-07-12 16:21:53Z suehring
253! Correct working precision for INTEGER number
254!
255! 3122 2018-07-11 21:46:41Z maronga
256! Bugfix: maximum distance for raytracing was set to  -999 m by default,
257! effectively switching off all surface reflections when max_raytracing_dist
258! was not explicitly set in namelist
259!
260! 3117 2018-07-11 09:59:11Z maronga
261! Bugfix: water vapor was not transfered to RRTMG when bulk_cloud_model = .F.
262! Bugfix: changed the calculation of RRTMG boundary conditions (Mohamed Salim)
263! Bugfix: dry residual atmosphere is replaced by standard RRTMG atmosphere
264!
265! 3116 2018-07-10 14:31:58Z suehring
266! Output of long/shortwave radiation at surface
267!
268! 3107 2018-07-06 15:55:51Z suehring
269! Bugfix, missing index for dz
270!
271! 3066 2018-06-12 08:55:55Z Giersch
272! Error message revised
273!
274! 3065 2018-06-12 07:03:02Z Giersch
275! dz was replaced by dz(1), error message concerning vertical stretching was
276! added 
277!
278! 3049 2018-05-29 13:52:36Z Giersch
279! Error messages revised
280!
281! 3045 2018-05-28 07:55:41Z Giersch
282! Error message revised
283!
284! 3026 2018-05-22 10:30:53Z schwenkel
285! Changed the name specific humidity to mixing ratio, since we are computing
286! mixing ratios.
287!
288! 3016 2018-05-09 10:53:37Z Giersch
289! Revised structure of reading svf data according to PALM coding standard:
290! svf_code_field/len and fsvf removed, error messages PA0493 and PA0494 added,
291! allocation status of output arrays checked.
292!
293! 3014 2018-05-09 08:42:38Z maronga
294! Introduced plant canopy height similar to urban canopy height to limit
295! the memory requirement to allocate lad.
296! Deactivated automatic setting of minimum raytracing distance.
297!
298! 3004 2018-04-27 12:33:25Z Giersch
299! Further allocation checks implemented (averaged data will be assigned to fill
300! values if no allocation happened so far)
301!
302! 2995 2018-04-19 12:13:16Z Giersch
303! IF-statement in radiation_init removed so that the calculation of radiative
304! fluxes at model start is done in any case, bugfix in
305! radiation_presimulate_solar_pos (end_time is the sum of end_time and the
306! spinup_time specified in the p3d_file ), list of variables/fields that have
307! to be written out or read in case of restarts has been extended
308!
309! 2977 2018-04-17 10:27:57Z kanani
310! Implement changes from branch radiation (r2948-2971) with minor modifications,
311! plus some formatting.
312! (moh.hefny):
313! - replaced plant_canopy by npcbl to check tree existence to avoid weird
314!   allocation of related arrays (after domain decomposition some domains
315!   contains no trees although plant_canopy (global parameter) is still TRUE).
316! - added a namelist parameter to force RTM settings
317! - enabled the option to switch radiation reflections off
318! - renamed surf_reflections to surface_reflections
319! - removed average_radiation flag from the namelist (now it is implicitly set
320!   in init_3d_model according to RTM)
321! - edited read and write sky view factors and CSF routines to account for
322!   the sub-domains which may not contain any of them
323!
324! 2967 2018-04-13 11:22:08Z raasch
325! bugfix: missing parallel cpp-directives added
326!
327! 2964 2018-04-12 16:04:03Z Giersch
328! Error message PA0491 has been introduced which could be previously found in
329! check_open. The variable numprocs_previous_run is only known in case of
330! initializing_actions == read_restart_data
331!
332! 2963 2018-04-12 14:47:44Z suehring
333! - Introduce index for vegetation/wall, pavement/green-wall and water/window
334!   surfaces, for clearer access of surface fraction, albedo, emissivity, etc. .
335! - Minor bugfix in initialization of albedo for window surfaces
336!
337! 2944 2018-04-03 16:20:18Z suehring
338! Fixed bad commit
339!
340! 2943 2018-04-03 16:17:10Z suehring
341! No read of nsurfl from SVF file since it is calculated in
342! radiation_interaction_init,
343! allocation of arrays in radiation_read_svf only if not yet allocated,
344! update of 2920 revision comment.
345!
346! 2932 2018-03-26 09:39:22Z maronga
347! renamed radiation_par to radiation_parameters
348!
349! 2930 2018-03-23 16:30:46Z suehring
350! Remove default surfaces from radiation model, does not make much sense to
351! apply radiation model without energy-balance solvers; Further, add check for
352! this.
353!
354! 2920 2018-03-22 11:22:01Z kanani
355! - Bugfix: Initialize pcbl array (=-1)
356! RTM version 2.0 (Jaroslav Resler, Pavel Krc, Mohamed Salim):
357! - new major version of radiation interactions
358! - substantially enhanced performance and scalability
359! - processing of direct and diffuse solar radiation separated from reflected
360!   radiation, removed virtual surfaces
361! - new type of sky discretization by azimuth and elevation angles
362! - diffuse radiation processed cumulatively using sky view factor
363! - used precalculated apparent solar positions for direct irradiance
364! - added new 2D raytracing process for processing whole vertical column at once
365!   to increase memory efficiency and decrease number of MPI RMA operations
366! - enabled limiting the number of view factors between surfaces by the distance
367!   and value
368! - fixing issues induced by transferring radiation interactions from
369!   urban_surface_mod to radiation_mod
370! - bugfixes and other minor enhancements
371!
372! 2906 2018-03-19 08:56:40Z Giersch
373! NAMELIST paramter read/write_svf_on_init have been removed, functions
374! check_open and close_file are used now for opening/closing files related to
375! svf data, adjusted unit number and error numbers
376!
377! 2894 2018-03-15 09:17:58Z Giersch
378! Calculations of the index range of the subdomain on file which overlaps with
379! the current subdomain are already done in read_restart_data_mod
380! radiation_read_restart_data was renamed to radiation_rrd_local and
381! radiation_last_actions was renamed to radiation_wrd_local, variable named
382! found has been introduced for checking if restart data was found, reading
383! of restart strings has been moved completely to read_restart_data_mod,
384! radiation_rrd_local is already inside the overlap loop programmed in
385! read_restart_data_mod, the marker *** end rad *** is not necessary anymore,
386! strings and their respective lengths are written out and read now in case of
387! restart runs to get rid of prescribed character lengths (Giersch)
388!
389! 2809 2018-02-15 09:55:58Z suehring
390! Bugfix for gfortran: Replace the function C_SIZEOF with STORAGE_SIZE
391!
392! 2753 2018-01-16 14:16:49Z suehring
393! Tile approach for spectral albedo implemented.
394!
395! 2746 2018-01-15 12:06:04Z suehring
396! Move flag plant canopy to modules
397!
398! 2724 2018-01-05 12:12:38Z maronga
399! Set default of average_radiation to .FALSE.
400!
401! 2723 2018-01-05 09:27:03Z maronga
402! Bugfix in calculation of rad_lw_out (clear-sky). First grid level was used
403! instead of the surface value
404!
405! 2718 2018-01-02 08:49:38Z maronga
406! Corrected "Former revisions" section
407!
408! 2707 2017-12-18 18:34:46Z suehring
409! Changes from last commit documented
410!
411! 2706 2017-12-18 18:33:49Z suehring
412! Bugfix, in average radiation case calculate exner function before using it.
413!
414! 2701 2017-12-15 15:40:50Z suehring
415! Changes from last commit documented
416!
417! 2698 2017-12-14 18:46:24Z suehring
418! Bugfix in get_topography_top_index
419!
420! 2696 2017-12-14 17:12:51Z kanani
421! - Change in file header (GPL part)
422! - Improved reading/writing of SVF from/to file (BM)
423! - Bugfixes concerning RRTMG as well as average_radiation options (M. Salim)
424! - Revised initialization of surface albedo and some minor bugfixes (MS)
425! - Update net radiation after running radiation interaction routine (MS)
426! - Revisions from M Salim included
427! - Adjustment to topography and surface structure (MS)
428! - Initialization of albedo and surface emissivity via input file (MS)
429! - albedo_pars extended (MS)
430!
431! 2604 2017-11-06 13:29:00Z schwenkel
432! bugfix for calculation of effective radius using morrison microphysics
433!
434! 2601 2017-11-02 16:22:46Z scharf
435! added emissivity to namelist
436!
437! 2575 2017-10-24 09:57:58Z maronga
438! Bugfix: calculation of shortwave and longwave albedos for RRTMG swapped
439!
440! 2547 2017-10-16 12:41:56Z schwenkel
441! extended by cloud_droplets option, minor bugfix and correct calculation of
442! cloud droplet number concentration
443!
444! 2544 2017-10-13 18:09:32Z maronga
445! Moved date and time quantitis to separate module date_and_time_mod
446!
447! 2512 2017-10-04 08:26:59Z raasch
448! upper bounds of cross section and 3d output changed from nx+1,ny+1 to nx,ny
449! no output of ghost layer data
450!
451! 2504 2017-09-27 10:36:13Z maronga
452! Updates pavement types and albedo parameters
453!
454! 2328 2017-08-03 12:34:22Z maronga
455! Emissivity can now be set individually for each pixel.
456! Albedo type can be inferred from land surface model.
457! Added default albedo type for bare soil
458!
459! 2318 2017-07-20 17:27:44Z suehring
460! Get topography top index via Function call
461!
462! 2317 2017-07-20 17:27:19Z suehring
463! Improved syntax layout
464!
465! 2298 2017-06-29 09:28:18Z raasch
466! type of write_binary changed from CHARACTER to LOGICAL
467!
468! 2296 2017-06-28 07:53:56Z maronga
469! Added output of rad_sw_out for radiation_scheme = 'constant'
470!
471! 2270 2017-06-09 12:18:47Z maronga
472! Numbering changed (2 timeseries removed)
473!
474! 2249 2017-06-06 13:58:01Z sward
475! Allow for RRTMG runs without humidity/cloud physics
476!
477! 2248 2017-06-06 13:52:54Z sward
478! Error no changed
479!
480! 2233 2017-05-30 18:08:54Z suehring
481!
482! 2232 2017-05-30 17:47:52Z suehring
483! Adjustments to new topography concept
484! Bugfix in read restart
485!
486! 2200 2017-04-11 11:37:51Z suehring
487! Bugfix in call of exchange_horiz_2d and read restart data
488!
489! 2163 2017-03-01 13:23:15Z schwenkel
490! Bugfix in radiation_check_data_output
491!
492! 2157 2017-02-22 15:10:35Z suehring
493! Bugfix in read_restart data
494!
495! 2011 2016-09-19 17:29:57Z kanani
496! Removed CALL of auxiliary SUBROUTINE get_usm_info,
497! flag urban_surface is now defined in module control_parameters.
498!
499! 2007 2016-08-24 15:47:17Z kanani
500! Added calculation of solar directional vector for new urban surface
501! model,
502! accounted for urban_surface model in radiation_check_parameters,
503! correction of comments for zenith angle.
504!
505! 2000 2016-08-20 18:09:15Z knoop
506! Forced header and separation lines into 80 columns
507!
508! 1976 2016-07-27 13:28:04Z maronga
509! Output of 2D/3D/masked data is now directly done within this module. The
510! radiation schemes have been simplified for better usability so that
511! rad_lw_in, rad_lw_out, rad_sw_in, and rad_sw_out are available independent of
512! the radiation code used.
513!
514! 1856 2016-04-13 12:56:17Z maronga
515! Bugfix: allocation of rad_lw_out for radiation_scheme = 'clear-sky'
516!
517! 1853 2016-04-11 09:00:35Z maronga
518! Added routine for radiation_scheme = constant.
519
520! 1849 2016-04-08 11:33:18Z hoffmann
521! Adapted for modularization of microphysics
522!
523! 1826 2016-04-07 12:01:39Z maronga
524! Further modularization.
525!
526! 1788 2016-03-10 11:01:04Z maronga
527! Added new albedo class for pavements / roads.
528!
529! 1783 2016-03-06 18:36:17Z raasch
530! palm-netcdf-module removed in order to avoid a circular module dependency,
531! netcdf-variables moved to netcdf-module, new routine netcdf_handle_error_rad
532! added
533!
534! 1757 2016-02-22 15:49:32Z maronga
535! Added parameter unscheduled_radiation_calls. Bugfix: interpolation of sounding
536! profiles for pressure and temperature above the LES domain.
537!
538! 1709 2015-11-04 14:47:01Z maronga
539! Bugfix: set initial value for rrtm_lwuflx_dt to zero, small formatting
540! corrections
541!
542! 1701 2015-11-02 07:43:04Z maronga
543! Bugfixes: wrong index for output of timeseries, setting of nz_snd_end
544!
545! 1691 2015-10-26 16:17:44Z maronga
546! Added option for spin-up runs without radiation (skip_time_do_radiation). Bugfix
547! in calculation of pressure profiles. Bugfix in calculation of trace gas profiles.
548! Added output of radiative heating rates.
549!
550! 1682 2015-10-07 23:56:08Z knoop
551! Code annotations made doxygen readable
552!
553! 1606 2015-06-29 10:43:37Z maronga
554! Added preprocessor directive __netcdf to allow for compiling without netCDF.
555! Note, however, that RRTMG cannot be used without netCDF.
556!
557! 1590 2015-05-08 13:56:27Z maronga
558! Bugfix: definition of character strings requires same length for all elements
559!
560! 1587 2015-05-04 14:19:01Z maronga
561! Added albedo class for snow
562!
563! 1585 2015-04-30 07:05:52Z maronga
564! Added support for RRTMG
565!
566! 1571 2015-03-12 16:12:49Z maronga
567! Added missing KIND attribute. Removed upper-case variable names
568!
569! 1551 2015-03-03 14:18:16Z maronga
570! Added support for data output. Various variables have been renamed. Added
571! interface for different radiation schemes (currently: clear-sky, constant, and
572! RRTM (not yet implemented).
573!
574! 1496 2014-12-02 17:25:50Z maronga
575! Initial revision
576!
577!
578! Description:
579! ------------
580!> Radiation models and interfaces
581!> @todo Replace dz(1) appropriatly to account for grid stretching
582!> @todo move variable definitions used in radiation_init only to the subroutine
583!>       as they are no longer required after initialization.
584!> @todo Output of full column vertical profiles used in RRTMG
585!> @todo Output of other rrtm arrays (such as volume mixing ratios)
586!> @todo Check for mis-used NINT() calls in raytrace_2d
587!>       RESULT: Original was correct (carefully verified formula), the change
588!>               to INT broke raytracing      -- P. Krc
589!> @todo Optimize radiation_tendency routines
590!>
591!> @note Many variables have a leading dummy dimension (0:0) in order to
592!>       match the assume-size shape expected by the RRTMG model.
593!------------------------------------------------------------------------------!
594 MODULE radiation_model_mod
595 
596    USE arrays_3d,                                                             &
597        ONLY:  dzw, hyp, nc, pt, p, q, ql, u, v, w, zu, zw, exner, d_exner
598
599    USE basic_constants_and_equations_mod,                                     &
600        ONLY:  c_p, g, lv_d_cp, l_v, pi, r_d, rho_l, solar_constant, sigma_sb, &
601               barometric_formula
602
603    USE calc_mean_profile_mod,                                                 &
604        ONLY:  calc_mean_profile
605
606    USE control_parameters,                                                    &
607        ONLY:  cloud_droplets, coupling_char, dz, dt_spinup, end_time,         &
608               humidity,                                                       &
609               initializing_actions, io_blocks, io_group,                      &
610               land_surface, large_scale_forcing,                              &
611               latitude, longitude, lsf_surf,                                  &
612               message_string, plant_canopy, pt_surface,                       &
613               rho_surface, simulated_time, spinup_time, surface_pressure,     &
614               read_svf, write_svf,                                            &
615               time_since_reference_point, urban_surface, varnamelength
616
617    USE cpulog,                                                                &
618        ONLY:  cpu_log, log_point, log_point_s
619
620    USE grid_variables,                                                        &
621         ONLY:  ddx, ddy, dx, dy 
622
623    USE date_and_time_mod,                                                     &
624        ONLY:  calc_date_and_time, d_hours_day, d_seconds_hour, d_seconds_year,&
625               day_of_year, d_seconds_year, day_of_month, day_of_year_init,    &
626               init_date_and_time, month_of_year, time_utc_init, time_utc
627
628    USE indices,                                                               &
629        ONLY:  nnx, nny, nx, nxl, nxlg, nxr, nxrg, ny, nyn, nyng, nys, nysg,   &
630               nzb, nzt
631
632    USE, INTRINSIC :: iso_c_binding
633
634    USE kinds
635
636    USE bulk_cloud_model_mod,                                                  &
637        ONLY:  bulk_cloud_model, microphysics_morrison, na_init, nc_const, sigma_gc
638
639#if defined ( __netcdf )
640    USE NETCDF
641#endif
642
643    USE netcdf_data_input_mod,                                                 &
644        ONLY:  albedo_type_f, albedo_pars_f, building_type_f, pavement_type_f, &
645               vegetation_type_f, water_type_f
646
647    USE plant_canopy_model_mod,                                                &
648        ONLY:  lad_s, pc_heating_rate, pc_transpiration_rate, pc_latent_rate,  &
649               plant_canopy_transpiration, pcm_calc_transpiration_rate
650
651    USE pegrid
652
653#if defined ( __rrtmg )
654    USE parrrsw,                                                               &
655        ONLY:  naerec, nbndsw
656
657    USE parrrtm,                                                               &
658        ONLY:  nbndlw
659
660    USE rrtmg_lw_init,                                                         &
661        ONLY:  rrtmg_lw_ini
662
663    USE rrtmg_sw_init,                                                         &
664        ONLY:  rrtmg_sw_ini
665
666    USE rrtmg_lw_rad,                                                          &
667        ONLY:  rrtmg_lw
668
669    USE rrtmg_sw_rad,                                                          &
670        ONLY:  rrtmg_sw
671#endif
672    USE statistics,                                                            &
673        ONLY:  hom
674
675    USE surface_mod,                                                           &
676        ONLY:  get_topography_top_index, get_topography_top_index_ji,          &
677               ind_pav_green, ind_veg_wall, ind_wat_win,                       &
678               surf_lsm_h, surf_lsm_v, surf_type, surf_usm_h, surf_usm_v,      &
679               vertical_surfaces_exist
680
681    IMPLICIT NONE
682
683    CHARACTER(10) :: radiation_scheme = 'clear-sky' ! 'constant', 'clear-sky', or 'rrtmg'
684
685!
686!-- Predefined Land surface classes (albedo_type) after Briegleb (1992)
687    CHARACTER(37), DIMENSION(0:33), PARAMETER :: albedo_type_name = (/      &
688                                   'user defined                         ', & !  0
689                                   'ocean                                ', & !  1
690                                   'mixed farming, tall grassland        ', & !  2
691                                   'tall/medium grassland                ', & !  3
692                                   'evergreen shrubland                  ', & !  4
693                                   'short grassland/meadow/shrubland     ', & !  5
694                                   'evergreen needleleaf forest          ', & !  6
695                                   'mixed deciduous evergreen forest     ', & !  7
696                                   'deciduous forest                     ', & !  8
697                                   'tropical evergreen broadleaved forest', & !  9
698                                   'medium/tall grassland/woodland       ', & ! 10
699                                   'desert, sandy                        ', & ! 11
700                                   'desert, rocky                        ', & ! 12
701                                   'tundra                               ', & ! 13
702                                   'land ice                             ', & ! 14
703                                   'sea ice                              ', & ! 15
704                                   'snow                                 ', & ! 16
705                                   'bare soil                            ', & ! 17
706                                   'asphalt/concrete mix                 ', & ! 18
707                                   'asphalt (asphalt concrete)           ', & ! 19
708                                   'concrete (Portland concrete)         ', & ! 20
709                                   'sett                                 ', & ! 21
710                                   'paving stones                        ', & ! 22
711                                   'cobblestone                          ', & ! 23
712                                   'metal                                ', & ! 24
713                                   'wood                                 ', & ! 25
714                                   'gravel                               ', & ! 26
715                                   'fine gravel                          ', & ! 27
716                                   'pebblestone                          ', & ! 28
717                                   'woodchips                            ', & ! 29
718                                   'tartan (sports)                      ', & ! 30
719                                   'artifical turf (sports)              ', & ! 31
720                                   'clay (sports)                        ', & ! 32
721                                   'building (dummy)                     '  & ! 33
722                                                         /)
723
724    INTEGER(iwp) :: albedo_type  = 9999999_iwp, &     !< Albedo surface type
725                    dots_rad     = 0_iwp              !< starting index for timeseries output
726
727    LOGICAL ::  unscheduled_radiation_calls = .TRUE., & !< flag parameter indicating whether additional calls of the radiation code are allowed
728                constant_albedo = .FALSE.,            & !< flag parameter indicating whether the albedo may change depending on zenith
729                force_radiation_call = .FALSE.,       & !< flag parameter for unscheduled radiation calls
730                lw_radiation = .TRUE.,                & !< flag parameter indicating whether longwave radiation shall be calculated
731                radiation = .FALSE.,                  & !< flag parameter indicating whether the radiation model is used
732                sun_up    = .TRUE.,                   & !< flag parameter indicating whether the sun is up or down
733                sw_radiation = .TRUE.,                & !< flag parameter indicating whether shortwave radiation shall be calculated
734                sun_direction = .FALSE.,              & !< flag parameter indicating whether solar direction shall be calculated
735                average_radiation = .FALSE.,          & !< flag to set the calculation of radiation averaging for the domain
736                radiation_interactions = .FALSE.,     & !< flag to activiate RTM (TRUE only if vertical urban/land surface and trees exist)
737                surface_reflections = .TRUE.,         & !< flag to switch the calculation of radiation interaction between surfaces.
738                                                        !< When it switched off, only the effect of buildings and trees shadow
739                                                        !< will be considered. However fewer SVFs are expected.
740                radiation_interactions_on = .TRUE.      !< namelist flag to force RTM activiation regardless to vertical urban/land surface and trees
741
742    REAL(wp) :: albedo = 9999999.9_wp,           & !< NAMELIST alpha
743                albedo_lw_dif = 9999999.9_wp,    & !< NAMELIST aldif
744                albedo_lw_dir = 9999999.9_wp,    & !< NAMELIST aldir
745                albedo_sw_dif = 9999999.9_wp,    & !< NAMELIST asdif
746                albedo_sw_dir = 9999999.9_wp,    & !< NAMELIST asdir
747                decl_1,                          & !< declination coef. 1
748                decl_2,                          & !< declination coef. 2
749                decl_3,                          & !< declination coef. 3
750                dt_radiation = 0.0_wp,           & !< radiation model timestep
751                emissivity = 9999999.9_wp,       & !< NAMELIST surface emissivity
752                lon = 0.0_wp,                    & !< longitude in radians
753                lat = 0.0_wp,                    & !< latitude in radians
754                net_radiation = 0.0_wp,          & !< net radiation at surface
755                skip_time_do_radiation = 0.0_wp, & !< Radiation model is not called before this time
756                sky_trans,                       & !< sky transmissivity
757                time_radiation = 0.0_wp            !< time since last call of radiation code
758
759
760    REAL(wp) ::  cos_zenith        !< cosine of solar zenith angle, also z-coordinate of solar unit vector
761    REAL(wp) ::  sun_dir_lat       !< y-coordinate of solar unit vector
762    REAL(wp) ::  sun_dir_lon       !< x-coordinate of solar unit vector
763
764    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_net_av       !< average of net radiation (rad_net) at surface
765    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_lw_in_xy_av  !< average of incoming longwave radiation at surface
766    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_lw_out_xy_av !< average of outgoing longwave radiation at surface
767    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_sw_in_xy_av  !< average of incoming shortwave radiation at surface
768    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_sw_out_xy_av !< average of outgoing shortwave radiation at surface
769
770    REAL(wp), PARAMETER :: emissivity_atm_clsky = 0.8_wp       !< emissivity of the clear-sky atmosphere
771!
772!-- Land surface albedos for solar zenith angle of 60degree after Briegleb (1992)     
773!-- (shortwave, longwave, broadband):   sw,      lw,      bb,
774    REAL(wp), DIMENSION(0:2,1:33), PARAMETER :: albedo_pars = RESHAPE( (/& 
775                                   0.06_wp, 0.06_wp, 0.06_wp,            & !  1
776                                   0.09_wp, 0.28_wp, 0.19_wp,            & !  2
777                                   0.11_wp, 0.33_wp, 0.23_wp,            & !  3
778                                   0.11_wp, 0.33_wp, 0.23_wp,            & !  4
779                                   0.14_wp, 0.34_wp, 0.25_wp,            & !  5
780                                   0.06_wp, 0.22_wp, 0.14_wp,            & !  6
781                                   0.06_wp, 0.27_wp, 0.17_wp,            & !  7
782                                   0.06_wp, 0.31_wp, 0.19_wp,            & !  8
783                                   0.06_wp, 0.22_wp, 0.14_wp,            & !  9
784                                   0.06_wp, 0.28_wp, 0.18_wp,            & ! 10
785                                   0.35_wp, 0.51_wp, 0.43_wp,            & ! 11
786                                   0.24_wp, 0.40_wp, 0.32_wp,            & ! 12
787                                   0.10_wp, 0.27_wp, 0.19_wp,            & ! 13
788                                   0.90_wp, 0.65_wp, 0.77_wp,            & ! 14
789                                   0.90_wp, 0.65_wp, 0.77_wp,            & ! 15
790                                   0.95_wp, 0.70_wp, 0.82_wp,            & ! 16
791                                   0.08_wp, 0.08_wp, 0.08_wp,            & ! 17
792                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 18
793                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 19
794                                   0.30_wp, 0.30_wp, 0.30_wp,            & ! 20
795                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 21
796                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 22
797                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 23
798                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 24
799                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 25
800                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 26
801                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 27
802                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 28
803                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 29
804                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 30
805                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 31
806                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 32
807                                   0.17_wp, 0.17_wp, 0.17_wp             & ! 33
808                                 /), (/ 3, 33 /) )
809
810    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE, TARGET :: &
811                        rad_lw_cs_hr,                  & !< longwave clear sky radiation heating rate (K/s)
812                        rad_lw_cs_hr_av,               & !< average of rad_lw_cs_hr
813                        rad_lw_hr,                     & !< longwave radiation heating rate (K/s)
814                        rad_lw_hr_av,                  & !< average of rad_sw_hr
815                        rad_lw_in,                     & !< incoming longwave radiation (W/m2)
816                        rad_lw_in_av,                  & !< average of rad_lw_in
817                        rad_lw_out,                    & !< outgoing longwave radiation (W/m2)
818                        rad_lw_out_av,                 & !< average of rad_lw_out
819                        rad_sw_cs_hr,                  & !< shortwave clear sky radiation heating rate (K/s)
820                        rad_sw_cs_hr_av,               & !< average of rad_sw_cs_hr
821                        rad_sw_hr,                     & !< shortwave radiation heating rate (K/s)
822                        rad_sw_hr_av,                  & !< average of rad_sw_hr
823                        rad_sw_in,                     & !< incoming shortwave radiation (W/m2)
824                        rad_sw_in_av,                  & !< average of rad_sw_in
825                        rad_sw_out,                    & !< outgoing shortwave radiation (W/m2)
826                        rad_sw_out_av                    !< average of rad_sw_out
827
828
829!
830!-- Variables and parameters used in RRTMG only
831#if defined ( __rrtmg )
832    CHARACTER(LEN=12) :: rrtm_input_file = "RAD_SND_DATA" !< name of the NetCDF input file (sounding data)
833
834
835!
836!-- Flag parameters to be passed to RRTMG (should not be changed until ice phase in clouds is allowed)
837    INTEGER(iwp), PARAMETER :: rrtm_idrv     = 1, & !< flag for longwave upward flux calculation option (0,1)
838                               rrtm_inflglw  = 2, & !< flag for lw cloud optical properties (0,1,2)
839                               rrtm_iceflglw = 0, & !< flag for lw ice particle specifications (0,1,2,3)
840                               rrtm_liqflglw = 1, & !< flag for lw liquid droplet specifications
841                               rrtm_inflgsw  = 2, & !< flag for sw cloud optical properties (0,1,2)
842                               rrtm_iceflgsw = 0, & !< flag for sw ice particle specifications (0,1,2,3)
843                               rrtm_liqflgsw = 1    !< flag for sw liquid droplet specifications
844
845!
846!-- The following variables should be only changed with care, as this will
847!-- require further setting of some variables, which is currently not
848!-- implemented (aerosols, ice phase).
849    INTEGER(iwp) :: nzt_rad,           & !< upper vertical limit for radiation calculations
850                    rrtm_icld = 0,     & !< cloud flag (0: clear sky column, 1: cloudy column)
851                    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)
852
853    INTEGER(iwp) :: nc_stat !< local variable for storin the result of netCDF calls for error message handling
854
855    LOGICAL :: snd_exists = .FALSE.      !< flag parameter to check whether a user-defined input files exists
856    LOGICAL :: sw_exists = .FALSE.       !< flag parameter to check whether that required rrtmg sw file exists
857    LOGICAL :: lw_exists = .FALSE.       !< flag parameter to check whether that required rrtmg lw file exists
858
859
860    REAL(wp), PARAMETER :: mol_mass_air_d_wv = 1.607793_wp !< molecular weight dry air / water vapor
861
862    REAL(wp), DIMENSION(:), ALLOCATABLE :: hyp_snd,     & !< hypostatic pressure from sounding data (hPa)
863                                           rrtm_tsfc,   & !< dummy array for storing surface temperature
864                                           t_snd          !< actual temperature from sounding data (hPa)
865
866    REAL(wp), DIMENSION(:,:), ALLOCATABLE :: rrtm_ccl4vmr,   & !< CCL4 volume mixing ratio (g/mol)
867                                             rrtm_cfc11vmr,  & !< CFC11 volume mixing ratio (g/mol)
868                                             rrtm_cfc12vmr,  & !< CFC12 volume mixing ratio (g/mol)
869                                             rrtm_cfc22vmr,  & !< CFC22 volume mixing ratio (g/mol)
870                                             rrtm_ch4vmr,    & !< CH4 volume mixing ratio
871                                             rrtm_cicewp,    & !< in-cloud ice water path (g/m2)
872                                             rrtm_cldfr,     & !< cloud fraction (0,1)
873                                             rrtm_cliqwp,    & !< in-cloud liquid water path (g/m2)
874                                             rrtm_co2vmr,    & !< CO2 volume mixing ratio (g/mol)
875                                             rrtm_emis,      & !< surface emissivity (0-1) 
876                                             rrtm_h2ovmr,    & !< H2O volume mixing ratio
877                                             rrtm_n2ovmr,    & !< N2O volume mixing ratio
878                                             rrtm_o2vmr,     & !< O2 volume mixing ratio
879                                             rrtm_o3vmr,     & !< O3 volume mixing ratio
880                                             rrtm_play,      & !< pressure layers (hPa, zu-grid)
881                                             rrtm_plev,      & !< pressure layers (hPa, zw-grid)
882                                             rrtm_reice,     & !< cloud ice effective radius (microns)
883                                             rrtm_reliq,     & !< cloud water drop effective radius (microns)
884                                             rrtm_tlay,      & !< actual temperature (K, zu-grid)
885                                             rrtm_tlev,      & !< actual temperature (K, zw-grid)
886                                             rrtm_lwdflx,    & !< RRTM output of incoming longwave radiation flux (W/m2)
887                                             rrtm_lwdflxc,   & !< RRTM output of outgoing clear sky longwave radiation flux (W/m2)
888                                             rrtm_lwuflx,    & !< RRTM output of outgoing longwave radiation flux (W/m2)
889                                             rrtm_lwuflxc,   & !< RRTM output of incoming clear sky longwave radiation flux (W/m2)
890                                             rrtm_lwuflx_dt, & !< RRTM output of incoming clear sky longwave radiation flux (W/m2)
891                                             rrtm_lwuflxc_dt,& !< RRTM output of outgoing clear sky longwave radiation flux (W/m2)
892                                             rrtm_lwhr,      & !< RRTM output of longwave radiation heating rate (K/d)
893                                             rrtm_lwhrc,     & !< RRTM output of incoming longwave clear sky radiation heating rate (K/d)
894                                             rrtm_swdflx,    & !< RRTM output of incoming shortwave radiation flux (W/m2)
895                                             rrtm_swdflxc,   & !< RRTM output of outgoing clear sky shortwave radiation flux (W/m2)
896                                             rrtm_swuflx,    & !< RRTM output of outgoing shortwave radiation flux (W/m2)
897                                             rrtm_swuflxc,   & !< RRTM output of incoming clear sky shortwave radiation flux (W/m2)
898                                             rrtm_swhr,      & !< RRTM output of shortwave radiation heating rate (K/d)
899                                             rrtm_swhrc,     & !< RRTM output of incoming shortwave clear sky radiation heating rate (K/d)
900                                             rrtm_dirdflux,  & !< RRTM output of incoming direct shortwave (W/m2)
901                                             rrtm_difdflux     !< RRTM output of incoming diffuse shortwave (W/m2)
902
903    REAL(wp), DIMENSION(1) ::                rrtm_aldif,     & !< surface albedo for longwave diffuse radiation
904                                             rrtm_aldir,     & !< surface albedo for longwave direct radiation
905                                             rrtm_asdif,     & !< surface albedo for shortwave diffuse radiation
906                                             rrtm_asdir        !< surface albedo for shortwave direct radiation
907
908!
909!-- Definition of arrays that are currently not used for calling RRTMG (due to setting of flag parameters)
910    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::  rad_lw_cs_in,   & !< incoming clear sky longwave radiation (W/m2) (not used)
911                                                rad_lw_cs_out,  & !< outgoing clear sky longwave radiation (W/m2) (not used)
912                                                rad_sw_cs_in,   & !< incoming clear sky shortwave radiation (W/m2) (not used)
913                                                rad_sw_cs_out,  & !< outgoing clear sky shortwave radiation (W/m2) (not used)
914                                                rrtm_lw_tauaer, & !< lw aerosol optical depth
915                                                rrtm_lw_taucld, & !< lw in-cloud optical depth
916                                                rrtm_sw_taucld, & !< sw in-cloud optical depth
917                                                rrtm_sw_ssacld, & !< sw in-cloud single scattering albedo
918                                                rrtm_sw_asmcld, & !< sw in-cloud asymmetry parameter
919                                                rrtm_sw_fsfcld, & !< sw in-cloud forward scattering fraction
920                                                rrtm_sw_tauaer, & !< sw aerosol optical depth
921                                                rrtm_sw_ssaaer, & !< sw aerosol single scattering albedo
922                                                rrtm_sw_asmaer, & !< sw aerosol asymmetry parameter
923                                                rrtm_sw_ecaer     !< sw aerosol optical detph at 0.55 microns (rrtm_iaer = 6 only)
924
925#endif
926!
927!-- Parameters of urban and land surface models
928    INTEGER(iwp)                                   ::  nz_urban                           !< number of layers of urban surface (will be calculated)
929    INTEGER(iwp)                                   ::  nz_plant                           !< number of layers of plant canopy (will be calculated)
930    INTEGER(iwp)                                   ::  nz_urban_b                         !< bottom layer of urban surface (will be calculated)
931    INTEGER(iwp)                                   ::  nz_urban_t                         !< top layer of urban surface (will be calculated)
932    INTEGER(iwp)                                   ::  nz_plant_t                         !< top layer of plant canopy (will be calculated)
933!-- parameters of urban and land surface models
934    INTEGER(iwp), PARAMETER                        ::  nzut_free = 3                      !< number of free layers above top of of topography
935    INTEGER(iwp), PARAMETER                        ::  ndsvf = 2                          !< number of dimensions of real values in SVF
936    INTEGER(iwp), PARAMETER                        ::  idsvf = 2                          !< number of dimensions of integer values in SVF
937    INTEGER(iwp), PARAMETER                        ::  ndcsf = 1                          !< number of dimensions of real values in CSF
938    INTEGER(iwp), PARAMETER                        ::  idcsf = 2                          !< number of dimensions of integer values in CSF
939    INTEGER(iwp), PARAMETER                        ::  kdcsf = 4                          !< number of dimensions of integer values in CSF calculation array
940    INTEGER(iwp), PARAMETER                        ::  id = 1                             !< position of d-index in surfl and surf
941    INTEGER(iwp), PARAMETER                        ::  iz = 2                             !< position of k-index in surfl and surf
942    INTEGER(iwp), PARAMETER                        ::  iy = 3                             !< position of j-index in surfl and surf
943    INTEGER(iwp), PARAMETER                        ::  ix = 4                             !< position of i-index in surfl and surf
944    INTEGER(iwp), PARAMETER                        ::  im = 5                             !< position of surface m-index in surfl and surf
945    INTEGER(iwp), PARAMETER                        ::  nidx_surf = 5                      !< number of indices in surfl and surf
946
947    INTEGER(iwp), PARAMETER                        ::  nsurf_type = 10                    !< number of surf types incl. phys.(land+urban) & (atm.,sky,boundary) surfaces - 1
948
949    INTEGER(iwp), PARAMETER                        ::  iup_u    = 0                       !< 0 - index of urban upward surface (ground or roof)
950    INTEGER(iwp), PARAMETER                        ::  idown_u  = 1                       !< 1 - index of urban downward surface (overhanging)
951    INTEGER(iwp), PARAMETER                        ::  inorth_u = 2                       !< 2 - index of urban northward facing wall
952    INTEGER(iwp), PARAMETER                        ::  isouth_u = 3                       !< 3 - index of urban southward facing wall
953    INTEGER(iwp), PARAMETER                        ::  ieast_u  = 4                       !< 4 - index of urban eastward facing wall
954    INTEGER(iwp), PARAMETER                        ::  iwest_u  = 5                       !< 5 - index of urban westward facing wall
955
956    INTEGER(iwp), PARAMETER                        ::  iup_l    = 6                       !< 6 - index of land upward surface (ground or roof)
957    INTEGER(iwp), PARAMETER                        ::  inorth_l = 7                       !< 7 - index of land northward facing wall
958    INTEGER(iwp), PARAMETER                        ::  isouth_l = 8                       !< 8 - index of land southward facing wall
959    INTEGER(iwp), PARAMETER                        ::  ieast_l  = 9                       !< 9 - index of land eastward facing wall
960    INTEGER(iwp), PARAMETER                        ::  iwest_l  = 10                      !< 10- index of land westward facing wall
961
962    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  idir = (/0, 0,0, 0,1,-1,0,0, 0,1,-1/)   !< surface normal direction x indices
963    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  jdir = (/0, 0,1,-1,0, 0,0,1,-1,0, 0/)   !< surface normal direction y indices
964    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  kdir = (/1,-1,0, 0,0, 0,1,0, 0,0, 0/)   !< surface normal direction z indices
965    REAL(wp),     DIMENSION(0:nsurf_type)          :: facearea                            !< area of single face in respective
966                                                                                          !< direction (will be calc'd)
967
968
969!-- indices and sizes of urban and land surface models
970    INTEGER(iwp)                                   ::  startland        !< start index of block of land and roof surfaces
971    INTEGER(iwp)                                   ::  endland          !< end index of block of land and roof surfaces
972    INTEGER(iwp)                                   ::  nlands           !< number of land and roof surfaces in local processor
973    INTEGER(iwp)                                   ::  startwall        !< start index of block of wall surfaces
974    INTEGER(iwp)                                   ::  endwall          !< end index of block of wall surfaces
975    INTEGER(iwp)                                   ::  nwalls           !< number of wall surfaces in local processor
976
977!-- indices needed for RTM netcdf output subroutines
978    INTEGER(iwp), PARAMETER                        :: nd = 5
979    CHARACTER(LEN=6), DIMENSION(0:nd-1), PARAMETER :: dirname = (/ '_roof ', '_south', '_north', '_west ', '_east ' /)
980    INTEGER(iwp), DIMENSION(0:nd-1), PARAMETER     :: dirint_u = (/ iup_u, isouth_u, inorth_u, iwest_u, ieast_u /)
981    INTEGER(iwp), DIMENSION(0:nd-1), PARAMETER     :: dirint_l = (/ iup_l, isouth_l, inorth_l, iwest_l, ieast_l /)
982    INTEGER(iwp), DIMENSION(0:nd-1)                :: dirstart
983    INTEGER(iwp), DIMENSION(0:nd-1)                :: dirend
984
985!-- indices and sizes of urban and land surface models
986    INTEGER(iwp), DIMENSION(:,:), POINTER          ::  surfl            !< coordinates of i-th local surface in local grid - surfl[:,k] = [d, z, y, x, m]
987    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surfl_linear     !< dtto (linearly allocated array)
988    INTEGER(iwp), DIMENSION(:,:), POINTER          ::  surf             !< coordinates of i-th surface in grid - surf[:,k] = [d, z, y, x, m]
989    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surf_linear      !< dtto (linearly allocated array)
990    INTEGER(iwp)                                   ::  nsurfl           !< number of all surfaces in local processor
991    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  nsurfs           !< array of number of all surfaces in individual processors
992    INTEGER(iwp)                                   ::  nsurf            !< global number of surfaces in index array of surfaces (nsurf = proc nsurfs)
993    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surfstart        !< starts of blocks of surfaces for individual processors in array surf (indexed from 1)
994                                                                        !< respective block for particular processor is surfstart[iproc+1]+1 : surfstart[iproc+1]+nsurfs[iproc+1]
995
996!-- block variables needed for calculation of the plant canopy model inside the urban surface model
997    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pct              !< top layer of the plant canopy
998    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pch              !< heights of the plant canopy
999    INTEGER(iwp)                                   ::  npcbl = 0        !< number of the plant canopy gridboxes in local processor
1000    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pcbl             !< k,j,i coordinates of l-th local plant canopy box pcbl[:,l] = [k, j, i]
1001    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinsw          !< array of absorbed sw radiation for local plant canopy box
1002    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdir       !< array of absorbed direct sw radiation for local plant canopy box
1003    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdif       !< array of absorbed diffusion sw radiation for local plant canopy box
1004    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinlw          !< array of absorbed lw radiation for local plant canopy box
1005
1006!-- configuration parameters (they can be setup in PALM config)
1007    LOGICAL                                        ::  raytrace_mpi_rma = .TRUE.          !< use MPI RMA to access LAD and gridsurf from remote processes during raytracing
1008    LOGICAL                                        ::  rad_angular_discretization = .TRUE.!< whether to use fixed resolution discretization of view factors for
1009                                                                                          !< reflected radiation (as opposed to all mutually visible pairs)
1010    LOGICAL                                        ::  plant_lw_interact = .TRUE.         !< whether plant canopy interacts with LW radiation (in addition to SW)
1011    INTEGER(iwp)                                   ::  mrt_nlevels = 0                    !< number of vertical boxes above surface for which to calculate MRT
1012    LOGICAL                                        ::  mrt_skip_roof = .TRUE.             !< do not calculate MRT above roof surfaces
1013    LOGICAL                                        ::  mrt_include_sw = .TRUE.            !< should MRT calculation include SW radiation as well?
1014    LOGICAL                                        ::  mrt_geom_human = .TRUE.            !< MRT direction weights simulate human body instead of a sphere
1015    INTEGER(iwp)                                   ::  nrefsteps = 3                      !< number of reflection steps to perform
1016    REAL(wp), PARAMETER                            ::  ext_coef = 0.6_wp                  !< extinction coefficient (a.k.a. alpha)
1017    INTEGER(iwp), PARAMETER                        ::  rad_version_len = 10               !< length of identification string of rad version
1018    CHARACTER(rad_version_len), PARAMETER          ::  rad_version = 'RAD v. 3.0'         !< identification of version of binary svf and restart files
1019    INTEGER(iwp)                                   ::  raytrace_discrete_elevs = 40       !< number of discretization steps for elevation (nadir to zenith)
1020    INTEGER(iwp)                                   ::  raytrace_discrete_azims = 80       !< number of discretization steps for azimuth (out of 360 degrees)
1021    REAL(wp)                                       ::  max_raytracing_dist = -999.0_wp    !< maximum distance for raytracing (in metres)
1022    REAL(wp)                                       ::  min_irrf_value = 1e-6_wp           !< minimum potential irradiance factor value for raytracing
1023    REAL(wp), DIMENSION(1:30)                      ::  svfnorm_report_thresh = 1e21_wp    !< thresholds of SVF normalization values to report
1024    INTEGER(iwp)                                   ::  svfnorm_report_num                 !< number of SVF normalization thresholds to report
1025
1026!-- radiation related arrays to be used in radiation_interaction routine
1027    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_sw_in_dir    !< direct sw radiation
1028    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_sw_in_diff   !< diffusion sw radiation
1029    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_lw_in_diff   !< diffusion lw radiation
1030
1031!-- parameters required for RRTMG lower boundary condition
1032    REAL(wp)                   :: albedo_urb      !< albedo value retuned to RRTMG boundary cond.
1033    REAL(wp)                   :: emissivity_urb  !< emissivity value retuned to RRTMG boundary cond.
1034    REAL(wp)                   :: t_rad_urb       !< temperature value retuned to RRTMG boundary cond.
1035
1036!-- type for calculation of svf
1037    TYPE t_svf
1038        INTEGER(iwp)                               :: isurflt           !<
1039        INTEGER(iwp)                               :: isurfs            !<
1040        REAL(wp)                                   :: rsvf              !<
1041        REAL(wp)                                   :: rtransp           !<
1042    END TYPE
1043
1044!-- type for calculation of csf
1045    TYPE t_csf
1046        INTEGER(iwp)                               :: ip                !<
1047        INTEGER(iwp)                               :: itx               !<
1048        INTEGER(iwp)                               :: ity               !<
1049        INTEGER(iwp)                               :: itz               !<
1050        INTEGER(iwp)                               :: isurfs            !< Idx of source face / -1 for sky
1051        REAL(wp)                                   :: rcvf              !< Canopy view factor for faces /
1052                                                                        !< canopy sink factor for sky (-1)
1053    END TYPE
1054
1055!-- arrays storing the values of USM
1056    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  svfsurf          !< svfsurf[:,isvf] = index of target and source surface for svf[isvf]
1057    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  svf              !< array of shape view factors+direct irradiation factors for local surfaces
1058    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfins          !< array of sw radiation falling to local surface after i-th reflection
1059    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinl          !< array of lw radiation for local surface after i-th reflection
1060
1061    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  skyvf            !< array of sky view factor for each local surface
1062    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  skyvft           !< array of sky view factor including transparency for each local surface
1063    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsitrans         !< dsidir[isvfl,i] = path transmittance of i-th
1064                                                                        !< direction of direct solar irradiance per target surface
1065    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsitransc        !< dtto per plant canopy box
1066    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsidir           !< dsidir[:,i] = unit vector of i-th
1067                                                                        !< direction of direct solar irradiance
1068    INTEGER(iwp)                                   ::  ndsidir          !< number of apparent solar directions used
1069    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  dsidir_rev       !< dsidir_rev[ielev,iazim] = i for dsidir or -1 if not present
1070
1071    INTEGER(iwp)                                   ::  nmrtbl           !< No. of local grid boxes for which MRT is calculated
1072    INTEGER(iwp)                                   ::  nmrtf            !< number of MRT factors for local processor
1073    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  mrtbl            !< coordinates of i-th local MRT box - surfl[:,i] = [z, y, x]
1074    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  mrtfsurf         !< mrtfsurf[:,imrtf] = index of target MRT box and source surface for mrtf[imrtf]
1075    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtf             !< array of MRT factors for each local MRT box
1076    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtft            !< array of MRT factors including transparency for each local MRT box
1077    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtsky           !< array of sky view factor for each local MRT box
1078    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtskyt          !< array of sky view factor including transparency for each local MRT box
1079    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  mrtdsit          !< array of direct solar transparencies for each local MRT box
1080    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinsw          !< mean SW radiant flux for each MRT box
1081    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinlw          !< mean LW radiant flux for each MRT box
1082    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrt              !< mean radiant temperature for each MRT box
1083    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinsw_av       !< time average mean SW radiant flux for each MRT box
1084    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinlw_av       !< time average mean LW radiant flux for each MRT box
1085    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrt_av           !< time average mean radiant temperature for each MRT box
1086
1087    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinsw         !< array of sw radiation falling to local surface including radiation from reflections
1088    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlw         !< array of lw radiation falling to local surface including radiation from reflections
1089    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdir      !< array of direct sw radiation falling to local surface
1090    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdif      !< array of diffuse sw radiation from sky and model boundary falling to local surface
1091    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwdif      !< array of diffuse lw radiation from sky and model boundary falling to local surface
1092   
1093                                                                        !< Outward radiation is only valid for nonvirtual surfaces
1094    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsl        !< array of reflected sw radiation for local surface in i-th reflection
1095    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutll        !< array of reflected + emitted lw radiation for local surface in i-th reflection
1096    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfouts         !< array of reflected sw radiation for all surfaces in i-th reflection
1097    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutl         !< array of reflected + emitted lw radiation for all surfaces in i-th reflection
1098    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlg         !< global array of incoming lw radiation from plant canopy
1099    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsw        !< array of total sw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1100    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutlw        !< array of total lw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1101    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfemitlwl      !< array of emitted lw radiation for local surface used to calculate effective surface temperature for radiation model
1102
1103!-- block variables needed for calculation of the plant canopy model inside the urban surface model
1104    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  csfsurf          !< csfsurf[:,icsf] = index of target surface and csf grid index for csf[icsf]
1105    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  csf              !< array of plant canopy sink fators + direct irradiation factors (transparency)
1106    REAL(wp), DIMENSION(:,:,:), POINTER            ::  sub_lad          !< subset of lad_s within urban surface, transformed to plain Z coordinate
1107    REAL(wp), DIMENSION(:), POINTER                ::  sub_lad_g        !< sub_lad globalized (used to avoid MPI RMA calls in raytracing)
1108    REAL(wp)                                       ::  prototype_lad    !< prototype leaf area density for computing effective optical depth
1109    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  nzterr, plantt   !< temporary global arrays for raytracing
1110    INTEGER(iwp)                                   ::  plantt_max
1111
1112!-- arrays and variables for calculation of svf and csf
1113    TYPE(t_svf), DIMENSION(:), POINTER             ::  asvf             !< pointer to growing svc array
1114    TYPE(t_csf), DIMENSION(:), POINTER             ::  acsf             !< pointer to growing csf array
1115    TYPE(t_svf), DIMENSION(:), POINTER             ::  amrtf            !< pointer to growing mrtf array
1116    TYPE(t_svf), DIMENSION(:), ALLOCATABLE, TARGET ::  asvf1, asvf2     !< realizations of svf array
1117    TYPE(t_csf), DIMENSION(:), ALLOCATABLE, TARGET ::  acsf1, acsf2     !< realizations of csf array
1118    TYPE(t_svf), DIMENSION(:), ALLOCATABLE, TARGET ::  amrtf1, amrtf2   !< realizations of mftf array
1119    INTEGER(iwp)                                   ::  nsvfla           !< dimmension of array allocated for storage of svf in local processor
1120    INTEGER(iwp)                                   ::  ncsfla           !< dimmension of array allocated for storage of csf in local processor
1121    INTEGER(iwp)                                   ::  nmrtfa           !< dimmension of array allocated for storage of mrt
1122    INTEGER(iwp)                                   ::  msvf, mcsf, mmrtf!< mod for swapping the growing array
1123    INTEGER(iwp), PARAMETER                        ::  gasize = 100000_iwp  !< initial size of growing arrays
1124    REAL(wp), PARAMETER                            ::  grow_factor = 1.4_wp !< growth factor of growing arrays
1125    INTEGER(iwp)                                   ::  nsvfl            !< number of svf for local processor
1126    INTEGER(iwp)                                   ::  ncsfl            !< no. of csf in local processor
1127                                                                        !< needed only during calc_svf but must be here because it is
1128                                                                        !< shared between subroutines calc_svf and raytrace
1129    INTEGER(iwp), DIMENSION(:,:,:,:), POINTER      ::  gridsurf         !< reverse index of local surfl[d,k,j,i] (for case rad_angular_discretization)
1130    INTEGER(iwp), DIMENSION(:,:,:), ALLOCATABLE    ::  gridpcbl         !< reverse index of local pcbl[k,j,i]
1131    INTEGER(iwp), PARAMETER                        ::  nsurf_type_u = 6 !< number of urban surf types (used in gridsurf)
1132
1133!-- temporary arrays for calculation of csf in raytracing
1134    INTEGER(iwp)                                   ::  maxboxesg        !< max number of boxes ray can cross in the domain
1135    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  boxes            !< coordinates of gridboxes being crossed by ray
1136    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  crlens           !< array of crossing lengths of ray for particular grid boxes
1137    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  lad_ip           !< array of numbers of process where lad is stored
1138#if defined( __parallel )
1139    INTEGER(kind=MPI_ADDRESS_KIND), &
1140                  DIMENSION(:), ALLOCATABLE        ::  lad_disp         !< array of displaycements of lad in local array of proc lad_ip
1141    INTEGER(iwp)                                   ::  win_lad          !< MPI RMA window for leaf area density
1142    INTEGER(iwp)                                   ::  win_gridsurf     !< MPI RMA window for reverse grid surface index
1143#endif
1144    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  lad_s_ray        !< array of received lad_s for appropriate gridboxes crossed by ray
1145    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  target_surfl
1146    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  rt2_track
1147    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rt2_track_lad
1148    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  rt2_track_dist
1149    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  rt2_dist
1150
1151!-- arrays for time averages
1152    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfradnet_av    !< average of net radiation to local surface including radiation from reflections
1153    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinsw_av      !< average of sw radiation falling to local surface including radiation from reflections
1154    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlw_av      !< average of lw radiation falling to local surface including radiation from reflections
1155    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdir_av   !< average of direct sw radiation falling to local surface
1156    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdif_av   !< average of diffuse sw radiation from sky and model boundary falling to local surface
1157    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwdif_av   !< average of diffuse lw radiation from sky and model boundary falling to local surface
1158    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswref_av   !< average of sw radiation falling to surface from reflections
1159    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwref_av   !< average of lw radiation falling to surface from reflections
1160    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsw_av     !< average of total sw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1161    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutlw_av     !< average of total lw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1162    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfins_av       !< average of array of residua of sw radiation absorbed in surface after last reflection
1163    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinl_av       !< average of array of residua of lw radiation absorbed in surface after last reflection
1164    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinlw_av       !< Average of pcbinlw
1165    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinsw_av       !< Average of pcbinsw
1166    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdir_av    !< Average of pcbinswdir
1167    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdif_av    !< Average of pcbinswdif
1168    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswref_av    !< Average of pcbinswref
1169
1170
1171!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1172!-- Energy balance variables
1173!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1174!-- parameters of the land, roof and wall surfaces
1175    REAL(wp), DIMENSION(:), ALLOCATABLE            :: albedo_surf        !< albedo of the surface
1176    REAL(wp), DIMENSION(:), ALLOCATABLE            :: emiss_surf         !< emissivity of the wall surface
1177
1178
1179    INTERFACE radiation_check_data_output
1180       MODULE PROCEDURE radiation_check_data_output
1181    END INTERFACE radiation_check_data_output
1182
1183    INTERFACE radiation_check_data_output_ts
1184       MODULE PROCEDURE radiation_check_data_output_ts
1185    END INTERFACE radiation_check_data_output_ts
1186
1187    INTERFACE radiation_check_data_output_pr
1188       MODULE PROCEDURE radiation_check_data_output_pr
1189    END INTERFACE radiation_check_data_output_pr
1190 
1191    INTERFACE radiation_check_parameters
1192       MODULE PROCEDURE radiation_check_parameters
1193    END INTERFACE radiation_check_parameters
1194 
1195    INTERFACE radiation_clearsky
1196       MODULE PROCEDURE radiation_clearsky
1197    END INTERFACE radiation_clearsky
1198 
1199    INTERFACE radiation_constant
1200       MODULE PROCEDURE radiation_constant
1201    END INTERFACE radiation_constant
1202 
1203    INTERFACE radiation_control
1204       MODULE PROCEDURE radiation_control
1205    END INTERFACE radiation_control
1206
1207    INTERFACE radiation_3d_data_averaging
1208       MODULE PROCEDURE radiation_3d_data_averaging
1209    END INTERFACE radiation_3d_data_averaging
1210
1211    INTERFACE radiation_data_output_2d
1212       MODULE PROCEDURE radiation_data_output_2d
1213    END INTERFACE radiation_data_output_2d
1214
1215    INTERFACE radiation_data_output_3d
1216       MODULE PROCEDURE radiation_data_output_3d
1217    END INTERFACE radiation_data_output_3d
1218
1219    INTERFACE radiation_data_output_mask
1220       MODULE PROCEDURE radiation_data_output_mask
1221    END INTERFACE radiation_data_output_mask
1222
1223    INTERFACE radiation_define_netcdf_grid
1224       MODULE PROCEDURE radiation_define_netcdf_grid
1225    END INTERFACE radiation_define_netcdf_grid
1226
1227    INTERFACE radiation_header
1228       MODULE PROCEDURE radiation_header
1229    END INTERFACE radiation_header 
1230 
1231    INTERFACE radiation_init
1232       MODULE PROCEDURE radiation_init
1233    END INTERFACE radiation_init
1234
1235    INTERFACE radiation_parin
1236       MODULE PROCEDURE radiation_parin
1237    END INTERFACE radiation_parin
1238   
1239    INTERFACE radiation_rrtmg
1240       MODULE PROCEDURE radiation_rrtmg
1241    END INTERFACE radiation_rrtmg
1242
1243#if defined( __rrtmg )
1244    INTERFACE radiation_tendency
1245       MODULE PROCEDURE radiation_tendency
1246       MODULE PROCEDURE radiation_tendency_ij
1247    END INTERFACE radiation_tendency
1248#endif
1249
1250    INTERFACE radiation_rrd_local
1251       MODULE PROCEDURE radiation_rrd_local
1252    END INTERFACE radiation_rrd_local
1253
1254    INTERFACE radiation_wrd_local
1255       MODULE PROCEDURE radiation_wrd_local
1256    END INTERFACE radiation_wrd_local
1257
1258    INTERFACE radiation_interaction
1259       MODULE PROCEDURE radiation_interaction
1260    END INTERFACE radiation_interaction
1261
1262    INTERFACE radiation_interaction_init
1263       MODULE PROCEDURE radiation_interaction_init
1264    END INTERFACE radiation_interaction_init
1265 
1266    INTERFACE radiation_presimulate_solar_pos
1267       MODULE PROCEDURE radiation_presimulate_solar_pos
1268    END INTERFACE radiation_presimulate_solar_pos
1269
1270    INTERFACE radiation_calc_svf
1271       MODULE PROCEDURE radiation_calc_svf
1272    END INTERFACE radiation_calc_svf
1273
1274    INTERFACE radiation_write_svf
1275       MODULE PROCEDURE radiation_write_svf
1276    END INTERFACE radiation_write_svf
1277
1278    INTERFACE radiation_read_svf
1279       MODULE PROCEDURE radiation_read_svf
1280    END INTERFACE radiation_read_svf
1281
1282
1283    SAVE
1284
1285    PRIVATE
1286
1287!
1288!-- Public functions / NEEDS SORTING
1289    PUBLIC radiation_check_data_output, radiation_check_data_output_pr,        &
1290           radiation_check_data_output_ts,                                     &
1291           radiation_check_parameters, radiation_control,                      &
1292           radiation_header, radiation_init, radiation_parin,                  &
1293           radiation_3d_data_averaging,                                        &
1294           radiation_data_output_2d, radiation_data_output_3d,                 &
1295           radiation_define_netcdf_grid, radiation_wrd_local,                  &
1296           radiation_rrd_local, radiation_data_output_mask,                    &
1297           radiation_calc_svf, radiation_write_svf,                            &
1298           radiation_interaction, radiation_interaction_init,                  &
1299           radiation_read_svf, radiation_presimulate_solar_pos
1300
1301   
1302!
1303!-- Public variables and constants / NEEDS SORTING
1304    PUBLIC albedo, albedo_type, decl_1, decl_2, decl_3, dots_rad, dt_radiation,&
1305           emissivity, force_radiation_call, lat, lon, mrt_geom_human,         &
1306           mrt_include_sw, mrt_nlevels, mrtbl, mrtinsw, mrtinlw, nmrtbl,       &
1307           rad_net_av, radiation, radiation_scheme, rad_lw_in,                 &
1308           rad_lw_in_av, rad_lw_out, rad_lw_out_av,                            &
1309           rad_lw_cs_hr, rad_lw_cs_hr_av, rad_lw_hr, rad_lw_hr_av, rad_sw_in,  &
1310           rad_sw_in_av, rad_sw_out, rad_sw_out_av, rad_sw_cs_hr,              &
1311           rad_sw_cs_hr_av, rad_sw_hr, rad_sw_hr_av, solar_constant,           &
1312           skip_time_do_radiation, time_radiation, unscheduled_radiation_calls,&
1313           cos_zenith, calc_zenith, sun_direction, sun_dir_lat, sun_dir_lon,   &
1314           idir, jdir, kdir, id, iz, iy, ix,                                   &
1315           iup_u, inorth_u, isouth_u, ieast_u, iwest_u,                        &
1316           iup_l, inorth_l, isouth_l, ieast_l, iwest_l,                        &
1317           nsurf_type, nz_urban_b, nz_urban_t, nz_urban, pch, nsurf,                 &
1318           idsvf, ndsvf, idcsf, ndcsf, kdcsf, pct,                             &
1319           radiation_interactions, startwall, startland, endland, endwall,     &
1320           skyvf, skyvft, radiation_interactions_on, average_radiation,        &
1321           rad_sw_in_diff, rad_sw_in_dir
1322
1323
1324#if defined ( __rrtmg )
1325    PUBLIC radiation_tendency, rrtm_aldif, rrtm_aldir, rrtm_asdif, rrtm_asdir
1326#endif
1327
1328 CONTAINS
1329
1330
1331!------------------------------------------------------------------------------!
1332! Description:
1333! ------------
1334!> This subroutine controls the calls of the radiation schemes
1335!------------------------------------------------------------------------------!
1336    SUBROUTINE radiation_control
1337 
1338 
1339       IMPLICIT NONE
1340
1341
1342       SELECT CASE ( TRIM( radiation_scheme ) )
1343
1344          CASE ( 'constant' )
1345             CALL radiation_constant
1346         
1347          CASE ( 'clear-sky' ) 
1348             CALL radiation_clearsky
1349       
1350          CASE ( 'rrtmg' )
1351             CALL radiation_rrtmg
1352
1353          CASE DEFAULT
1354
1355       END SELECT
1356
1357
1358    END SUBROUTINE radiation_control
1359
1360!------------------------------------------------------------------------------!
1361! Description:
1362! ------------
1363!> Check data output for radiation model
1364!------------------------------------------------------------------------------!
1365    SUBROUTINE radiation_check_data_output( variable, unit, i, ilen, k )
1366 
1367 
1368       USE control_parameters,                                                 &
1369           ONLY: data_output, message_string
1370
1371       IMPLICIT NONE
1372
1373       CHARACTER (LEN=*) ::  unit          !<
1374       CHARACTER (LEN=*) ::  variable      !<
1375
1376       INTEGER(iwp) :: i, k
1377       INTEGER(iwp) :: ilen
1378       CHARACTER(LEN=varnamelength) :: var          !< TRIM(variable)
1379
1380       var = TRIM(variable)
1381
1382!--    first process diractional variables
1383       IF ( var(1:12) == 'rtm_rad_net_'  .OR.  var(1:13) == 'rtm_rad_insw_'  .OR.        &
1384            var(1:13) == 'rtm_rad_inlw_'  .OR.  var(1:16) == 'rtm_rad_inswdir_'  .OR.    &
1385            var(1:16) == 'rtm_rad_inswdif_'  .OR.  var(1:16) == 'rtm_rad_inswref_'  .OR. &
1386            var(1:16) == 'rtm_rad_inlwdif_'  .OR.  var(1:16) == 'rtm_rad_inlwref_'  .OR. &
1387            var(1:14) == 'rtm_rad_outsw_'  .OR.  var(1:14) == 'rtm_rad_outlw_'  .OR.     &
1388            var(1:14) == 'rtm_rad_ressw_'  .OR.  var(1:14) == 'rtm_rad_reslw_'  ) THEN
1389          IF ( .NOT.  radiation ) THEN
1390                message_string = 'output of "' // TRIM( var ) // '" require'&
1391                                 // 's radiation = .TRUE.'
1392                CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1393          ENDIF
1394          unit = 'W/m2'
1395       ELSE IF ( var(1:7) == 'rtm_svf'  .OR.  var(1:7) == 'rtm_dif'  .OR.                &
1396                 var(1:9) == 'rtm_skyvf' .OR. var(1:9) == 'rtm_skyvft' )  THEN
1397          IF ( .NOT.  radiation ) THEN
1398                message_string = 'output of "' // TRIM( var ) // '" require'&
1399                                 // 's radiation = .TRUE.'
1400                CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1401          ENDIF
1402          unit = '1'
1403       ELSE
1404!--       non-directional variables
1405          SELECT CASE ( TRIM( var ) )
1406             CASE ( 'rad_lw_cs_hr', 'rad_lw_hr', 'rad_lw_in', 'rad_lw_out', &
1407                    'rad_sw_cs_hr', 'rad_sw_hr', 'rad_sw_in', 'rad_sw_out'  )
1408                IF (  .NOT.  radiation  .OR.  radiation_scheme /= 'rrtmg' )  THEN
1409                   message_string = '"output of "' // TRIM( var ) // '" requi' // &
1410                                    'res radiation = .TRUE. and ' //              &
1411                                    'radiation_scheme = "rrtmg"'
1412                   CALL message( 'check_parameters', 'PA0406', 1, 2, 0, 6, 0 )
1413                ENDIF
1414                unit = 'K/h'
1415
1416             CASE ( 'rad_net*', 'rrtm_aldif*', 'rrtm_aldir*', 'rrtm_asdif*',      &
1417                    'rrtm_asdir*', 'rad_lw_in*', 'rad_lw_out*', 'rad_sw_in*',     &
1418                    'rad_sw_out*')
1419                IF ( i == 0 .AND. ilen == 0 .AND. k == 0)  THEN
1420                   ! Workaround for masked output (calls with i=ilen=k=0)
1421                   unit = 'illegal'
1422                   RETURN
1423                ENDIF
1424                IF ( k == 0  .OR.  data_output(i)(ilen-2:ilen) /= '_xy' )  THEN
1425                   message_string = 'illegal value for data_output: "' //         &
1426                                    TRIM( var ) // '" & only 2d-horizontal ' //   &
1427                                    'cross sections are allowed for this value'
1428                   CALL message( 'check_parameters', 'PA0111', 1, 2, 0, 6, 0 )
1429                ENDIF
1430                IF (  .NOT.  radiation  .OR.  radiation_scheme /= "rrtmg" )  THEN
1431                   IF ( TRIM( var ) == 'rrtm_aldif*'  .OR.                        &
1432                        TRIM( var ) == 'rrtm_aldir*'  .OR.                        &
1433                        TRIM( var ) == 'rrtm_asdif*'  .OR.                        &
1434                        TRIM( var ) == 'rrtm_asdir*'      )                       &
1435                   THEN
1436                      message_string = 'output of "' // TRIM( var ) // '" require'&
1437                                       // 's radiation = .TRUE. and radiation_sch'&
1438                                       // 'eme = "rrtmg"'
1439                      CALL message( 'check_parameters', 'PA0409', 1, 2, 0, 6, 0 )
1440                   ENDIF
1441                ENDIF
1442
1443                IF ( TRIM( var ) == 'rad_net*'      ) unit = 'W/m2'
1444                IF ( TRIM( var ) == 'rad_lw_in*'    ) unit = 'W/m2'
1445                IF ( TRIM( var ) == 'rad_lw_out*'   ) unit = 'W/m2'
1446                IF ( TRIM( var ) == 'rad_sw_in*'    ) unit = 'W/m2'
1447                IF ( TRIM( var ) == 'rad_sw_out*'   ) unit = 'W/m2'
1448                IF ( TRIM( var ) == 'rad_sw_in'     ) unit = 'W/m2'
1449                IF ( TRIM( var ) == 'rrtm_aldif*'   ) unit = ''
1450                IF ( TRIM( var ) == 'rrtm_aldir*'   ) unit = ''
1451                IF ( TRIM( var ) == 'rrtm_asdif*'   ) unit = ''
1452                IF ( TRIM( var ) == 'rrtm_asdir*'   ) unit = ''
1453
1454             CASE ( 'rtm_rad_pc_inlw', 'rtm_rad_pc_insw', 'rtm_rad_pc_inswdir', &
1455                    'rtm_rad_pc_inswdif', 'rtm_rad_pc_inswref')
1456                IF ( .NOT.  radiation ) THEN
1457                   message_string = 'output of "' // TRIM( var ) // '" require'&
1458                                    // 's radiation = .TRUE.'
1459                   CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1460                ENDIF
1461                unit = 'W'
1462
1463             CASE ( 'rtm_mrt', 'rtm_mrt_sw', 'rtm_mrt_lw'  )
1464                IF ( i == 0 .AND. ilen == 0 .AND. k == 0)  THEN
1465                   ! Workaround for masked output (calls with i=ilen=k=0)
1466                   unit = 'illegal'
1467                   RETURN
1468                ENDIF
1469
1470                IF ( .NOT.  radiation ) THEN
1471                   message_string = 'output of "' // TRIM( var ) // '" require'&
1472                                    // 's radiation = .TRUE.'
1473                   CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1474                ENDIF
1475                IF ( mrt_nlevels == 0 ) THEN
1476                   message_string = 'output of "' // TRIM( var ) // '" require'&
1477                                    // 's mrt_nlevels > 0'
1478                   CALL message( 'check_parameters', 'PA0510', 1, 2, 0, 6, 0 )
1479                ENDIF
1480                IF ( TRIM( var ) == 'rtm_mrt_sw'  .AND.  .NOT. mrt_include_sw ) THEN
1481                   message_string = 'output of "' // TRIM( var ) // '" require'&
1482                                    // 's rtm_mrt_sw = .TRUE.'
1483                   CALL message( 'check_parameters', 'PA0511', 1, 2, 0, 6, 0 )
1484                ENDIF
1485                IF ( TRIM( var ) == 'rtm_mrt' ) THEN
1486                   unit = 'K'
1487                ELSE
1488                   unit = 'W m-2'
1489                ENDIF
1490
1491             CASE DEFAULT
1492                unit = 'illegal'
1493
1494          END SELECT
1495       ENDIF
1496
1497    END SUBROUTINE radiation_check_data_output
1498
1499
1500!------------------------------------------------------------------------------!
1501! Description:
1502! ------------
1503!> Set module-specific timeseries units and labels
1504!------------------------------------------------------------------------------!
1505 SUBROUTINE radiation_check_data_output_ts( dots_max, dots_num )
1506
1507
1508    INTEGER(iwp),      INTENT(IN)     ::  dots_max
1509    INTEGER(iwp),      INTENT(INOUT)  ::  dots_num
1510
1511!
1512!-- Next line is just to avoid compiler warning about unused variable.
1513    IF ( dots_max == 0 )  CONTINUE
1514
1515!
1516!-- Temporary solution to add LSM and radiation time series to the default
1517!-- output
1518    IF ( land_surface  .OR.  radiation )  THEN
1519       IF ( TRIM( radiation_scheme ) == 'rrtmg' )  THEN
1520          dots_num = dots_num + 15
1521       ELSE
1522          dots_num = dots_num + 11
1523       ENDIF
1524    ENDIF
1525
1526
1527 END SUBROUTINE radiation_check_data_output_ts
1528
1529!------------------------------------------------------------------------------!
1530! Description:
1531! ------------
1532!> Check data output of profiles for radiation model
1533!------------------------------------------------------------------------------! 
1534    SUBROUTINE radiation_check_data_output_pr( variable, var_count, unit,      &
1535               dopr_unit )
1536 
1537       USE arrays_3d,                                                          &
1538           ONLY: zu
1539
1540       USE control_parameters,                                                 &
1541           ONLY: data_output_pr, message_string
1542
1543       USE indices
1544
1545       USE profil_parameter
1546
1547       USE statistics
1548
1549       IMPLICIT NONE
1550   
1551       CHARACTER (LEN=*) ::  unit      !<
1552       CHARACTER (LEN=*) ::  variable  !<
1553       CHARACTER (LEN=*) ::  dopr_unit !< local value of dopr_unit
1554 
1555       INTEGER(iwp) ::  var_count     !<
1556
1557       SELECT CASE ( TRIM( variable ) )
1558       
1559         CASE ( 'rad_net' )
1560             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme == 'constant' )&
1561             THEN
1562                message_string = 'data_output_pr = ' //                        &
1563                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1564                                 'not available for radiation = .FALSE. or ' //&
1565                                 'radiation_scheme = "constant"'
1566                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1567             ELSE
1568                dopr_index(var_count) = 99
1569                dopr_unit  = 'W/m2'
1570                hom(:,2,99,:)  = SPREAD( zw, 2, statistic_regions+1 )
1571                unit = dopr_unit
1572             ENDIF
1573
1574          CASE ( 'rad_lw_in' )
1575             IF ( (  .NOT.  radiation)  .OR.  radiation_scheme == 'constant' ) &
1576             THEN
1577                message_string = 'data_output_pr = ' //                        &
1578                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1579                                 'not available for radiation = .FALSE. or ' //&
1580                                 'radiation_scheme = "constant"'
1581                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1582             ELSE
1583                dopr_index(var_count) = 100
1584                dopr_unit  = 'W/m2'
1585                hom(:,2,100,:)  = SPREAD( zw, 2, statistic_regions+1 )
1586                unit = dopr_unit 
1587             ENDIF
1588
1589          CASE ( 'rad_lw_out' )
1590             IF ( (  .NOT. radiation )  .OR.  radiation_scheme == 'constant' ) &
1591             THEN
1592                message_string = 'data_output_pr = ' //                        &
1593                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1594                                 'not available for radiation = .FALSE. or ' //&
1595                                 'radiation_scheme = "constant"'
1596                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1597             ELSE
1598                dopr_index(var_count) = 101
1599                dopr_unit  = 'W/m2'
1600                hom(:,2,101,:)  = SPREAD( zw, 2, statistic_regions+1 )
1601                unit = dopr_unit   
1602             ENDIF
1603
1604          CASE ( 'rad_sw_in' )
1605             IF ( (  .NOT. radiation )  .OR.  radiation_scheme == 'constant' ) &
1606             THEN
1607                message_string = 'data_output_pr = ' //                        &
1608                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1609                                 'not available for radiation = .FALSE. or ' //&
1610                                 'radiation_scheme = "constant"'
1611                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1612             ELSE
1613                dopr_index(var_count) = 102
1614                dopr_unit  = 'W/m2'
1615                hom(:,2,102,:)  = SPREAD( zw, 2, statistic_regions+1 )
1616                unit = dopr_unit
1617             ENDIF
1618
1619          CASE ( 'rad_sw_out')
1620             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme == 'constant' )&
1621             THEN
1622                message_string = 'data_output_pr = ' //                        &
1623                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1624                                 'not available for radiation = .FALSE. or ' //&
1625                                 'radiation_scheme = "constant"'
1626                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1627             ELSE
1628                dopr_index(var_count) = 103
1629                dopr_unit  = 'W/m2'
1630                hom(:,2,103,:)  = SPREAD( zw, 2, statistic_regions+1 )
1631                unit = dopr_unit
1632             ENDIF
1633
1634          CASE ( 'rad_lw_cs_hr' )
1635             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1636             THEN
1637                message_string = 'data_output_pr = ' //                        &
1638                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1639                                 'not available for radiation = .FALSE. or ' //&
1640                                 'radiation_scheme /= "rrtmg"'
1641                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1642             ELSE
1643                dopr_index(var_count) = 104
1644                dopr_unit  = 'K/h'
1645                hom(:,2,104,:)  = SPREAD( zu, 2, statistic_regions+1 )
1646                unit = dopr_unit
1647             ENDIF
1648
1649          CASE ( 'rad_lw_hr' )
1650             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1651             THEN
1652                message_string = 'data_output_pr = ' //                        &
1653                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1654                                 'not available for radiation = .FALSE. or ' //&
1655                                 'radiation_scheme /= "rrtmg"'
1656                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1657             ELSE
1658                dopr_index(var_count) = 105
1659                dopr_unit  = 'K/h'
1660                hom(:,2,105,:)  = SPREAD( zu, 2, statistic_regions+1 )
1661                unit = dopr_unit
1662             ENDIF
1663
1664          CASE ( 'rad_sw_cs_hr' )
1665             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1666             THEN
1667                message_string = 'data_output_pr = ' //                        &
1668                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1669                                 'not available for radiation = .FALSE. or ' //&
1670                                 'radiation_scheme /= "rrtmg"'
1671                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1672             ELSE
1673                dopr_index(var_count) = 106
1674                dopr_unit  = 'K/h'
1675                hom(:,2,106,:)  = SPREAD( zu, 2, statistic_regions+1 )
1676                unit = dopr_unit
1677             ENDIF
1678
1679          CASE ( 'rad_sw_hr' )
1680             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1681             THEN
1682                message_string = 'data_output_pr = ' //                        &
1683                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1684                                 'not available for radiation = .FALSE. or ' //&
1685                                 'radiation_scheme /= "rrtmg"'
1686                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1687             ELSE
1688                dopr_index(var_count) = 107
1689                dopr_unit  = 'K/h'
1690                hom(:,2,107,:)  = SPREAD( zu, 2, statistic_regions+1 )
1691                unit = dopr_unit
1692             ENDIF
1693
1694
1695          CASE DEFAULT
1696             unit = 'illegal'
1697
1698       END SELECT
1699
1700
1701    END SUBROUTINE radiation_check_data_output_pr
1702 
1703 
1704!------------------------------------------------------------------------------!
1705! Description:
1706! ------------
1707!> Check parameters routine for radiation model
1708!------------------------------------------------------------------------------!
1709    SUBROUTINE radiation_check_parameters
1710
1711       USE control_parameters,                                                 &
1712           ONLY: land_surface, message_string, urban_surface
1713
1714       USE netcdf_data_input_mod,                                              &
1715           ONLY:  input_pids_static                 
1716   
1717       IMPLICIT NONE
1718       
1719!
1720!--    In case no urban-surface or land-surface model is applied, usage of
1721!--    a radiation model make no sense.         
1722       IF ( .NOT. land_surface  .AND.  .NOT. urban_surface )  THEN
1723          message_string = 'Usage of radiation module is only allowed if ' //  &
1724                           'land-surface and/or urban-surface model is applied.'
1725          CALL message( 'check_parameters', 'PA0486', 1, 2, 0, 6, 0 )
1726       ENDIF
1727
1728       IF ( radiation_scheme /= 'constant'   .AND.                             &
1729            radiation_scheme /= 'clear-sky'  .AND.                             &
1730            radiation_scheme /= 'rrtmg' )  THEN
1731          message_string = 'unknown radiation_scheme = '//                     &
1732                           TRIM( radiation_scheme )
1733          CALL message( 'check_parameters', 'PA0405', 1, 2, 0, 6, 0 )
1734       ELSEIF ( radiation_scheme == 'rrtmg' )  THEN
1735#if ! defined ( __rrtmg )
1736          message_string = 'radiation_scheme = "rrtmg" requires ' //           & 
1737                           'compilation of PALM with pre-processor ' //        &
1738                           'directive -D__rrtmg'
1739          CALL message( 'check_parameters', 'PA0407', 1, 2, 0, 6, 0 )
1740#endif
1741#if defined ( __rrtmg ) && ! defined( __netcdf )
1742          message_string = 'radiation_scheme = "rrtmg" requires ' //           & 
1743                           'the use of NetCDF (preprocessor directive ' //     &
1744                           '-D__netcdf'
1745          CALL message( 'check_parameters', 'PA0412', 1, 2, 0, 6, 0 )
1746#endif
1747
1748       ENDIF
1749!
1750!--    Checks performed only if data is given via namelist only.
1751       IF ( .NOT. input_pids_static )  THEN
1752          IF ( albedo_type == 0  .AND.  albedo == 9999999.9_wp  .AND.          &
1753               radiation_scheme == 'clear-sky')  THEN
1754             message_string = 'radiation_scheme = "clear-sky" in combination'//& 
1755                              'with albedo_type = 0 requires setting of'//     &
1756                              'albedo /= 9999999.9'
1757             CALL message( 'check_parameters', 'PA0410', 1, 2, 0, 6, 0 )
1758          ENDIF
1759
1760          IF ( albedo_type == 0  .AND.  radiation_scheme == 'rrtmg'  .AND.     &
1761             ( albedo_lw_dif == 9999999.9_wp .OR. albedo_lw_dir == 9999999.9_wp&
1762          .OR. albedo_sw_dif == 9999999.9_wp .OR. albedo_sw_dir == 9999999.9_wp& 
1763             ) ) THEN
1764             message_string = 'radiation_scheme = "rrtmg" in combination' //   & 
1765                              'with albedo_type = 0 requires setting of ' //   &
1766                              'albedo_lw_dif /= 9999999.9' //                  &
1767                              'albedo_lw_dir /= 9999999.9' //                  &
1768                              'albedo_sw_dif /= 9999999.9 and' //              &
1769                              'albedo_sw_dir /= 9999999.9'
1770             CALL message( 'check_parameters', 'PA0411', 1, 2, 0, 6, 0 )
1771          ENDIF
1772       ENDIF
1773!
1774!--    Parallel rad_angular_discretization without raytrace_mpi_rma is not implemented
1775#if defined( __parallel )     
1776       IF ( rad_angular_discretization  .AND.  .NOT. raytrace_mpi_rma )  THEN
1777          message_string = 'rad_angular_discretization can only be used ' //  &
1778                           'together with raytrace_mpi_rma or when ' //  &
1779                           'no parallelization is applied.'
1780          CALL message( 'check_parameters', 'PA0486', 1, 2, 0, 6, 0 )
1781       ENDIF
1782#endif
1783
1784       IF ( cloud_droplets  .AND.   radiation_scheme == 'rrtmg'  .AND.         &
1785            average_radiation ) THEN
1786          message_string = 'average_radiation = .T. with radiation_scheme'//   & 
1787                           '= "rrtmg" in combination cloud_droplets = .T.'//   &
1788                           'is not implementd'
1789          CALL message( 'check_parameters', 'PA0560', 1, 2, 0, 6, 0 )
1790       ENDIF
1791
1792!
1793!--    Incialize svf normalization reporting histogram
1794       svfnorm_report_num = 1
1795       DO WHILE ( svfnorm_report_thresh(svfnorm_report_num) < 1e20_wp          &
1796                   .AND. svfnorm_report_num <= 30 )
1797          svfnorm_report_num = svfnorm_report_num + 1
1798       ENDDO
1799       svfnorm_report_num = svfnorm_report_num - 1
1800!
1801!--    Check for dt_radiation
1802       IF ( dt_radiation <= 0.0 )  THEN
1803          message_string = 'dt_radiation must be > 0.0' 
1804          CALL message( 'check_parameters', 'PA0591', 1, 2, 0, 6, 0 ) 
1805       ENDIF
1806 
1807    END SUBROUTINE radiation_check_parameters 
1808 
1809 
1810!------------------------------------------------------------------------------!
1811! Description:
1812! ------------
1813!> Initialization of the radiation model
1814!------------------------------------------------------------------------------!
1815    SUBROUTINE radiation_init
1816   
1817       IMPLICIT NONE
1818
1819       INTEGER(iwp) ::  i         !< running index x-direction
1820       INTEGER(iwp) ::  ioff      !< offset in x between surface element reference grid point in atmosphere and actual surface
1821       INTEGER(iwp) ::  j         !< running index y-direction
1822       INTEGER(iwp) ::  joff      !< offset in y between surface element reference grid point in atmosphere and actual surface
1823       INTEGER(iwp) ::  l         !< running index for orientation of vertical surfaces
1824       INTEGER(iwp) ::  m         !< running index for surface elements
1825#if defined( __rrtmg )
1826       INTEGER(iwp) ::  ind_type  !< running index for subgrid-surface tiles
1827#endif
1828
1829!
1830!--    Activate radiation_interactions according to the existence of vertical surfaces and/or trees.
1831!--    The namelist parameter radiation_interactions_on can override this behavior.
1832!--    (This check cannot be performed in check_parameters, because vertical_surfaces_exist is first set in
1833!--    init_surface_arrays.)
1834       IF ( radiation_interactions_on )  THEN
1835          IF ( vertical_surfaces_exist  .OR.  plant_canopy )  THEN
1836             radiation_interactions    = .TRUE.
1837             average_radiation         = .TRUE.
1838          ELSE
1839             radiation_interactions_on = .FALSE.   !< reset namelist parameter: no interactions
1840                                                   !< calculations necessary in case of flat surface
1841          ENDIF
1842       ELSEIF ( vertical_surfaces_exist  .OR.  plant_canopy )  THEN
1843          message_string = 'radiation_interactions_on is set to .FALSE. although '     // &
1844                           'vertical surfaces and/or trees exist. The model will run ' // &
1845                           'without RTM (no shadows, no radiation reflections)'
1846          CALL message( 'init_3d_model', 'PA0348', 0, 1, 0, 6, 0 )
1847       ENDIF
1848!
1849!--    If required, initialize radiation interactions between surfaces
1850!--    via sky-view factors. This must be done before radiation is initialized.
1851       IF ( radiation_interactions )  CALL radiation_interaction_init
1852
1853!
1854!--    Initialize radiation model
1855       CALL location_message( 'initializing radiation model', .FALSE. )
1856
1857!
1858!--    Allocate array for storing the surface net radiation
1859       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_net )  .AND.                      &
1860                  surf_lsm_h%ns > 0  )   THEN
1861          ALLOCATE( surf_lsm_h%rad_net(1:surf_lsm_h%ns) )
1862          surf_lsm_h%rad_net = 0.0_wp 
1863       ENDIF
1864       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_net )  .AND.                      &
1865                  surf_usm_h%ns > 0  )  THEN
1866          ALLOCATE( surf_usm_h%rad_net(1:surf_usm_h%ns) )
1867          surf_usm_h%rad_net = 0.0_wp 
1868       ENDIF
1869       DO  l = 0, 3
1870          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_net )  .AND.                &
1871                     surf_lsm_v(l)%ns > 0  )  THEN
1872             ALLOCATE( surf_lsm_v(l)%rad_net(1:surf_lsm_v(l)%ns) )
1873             surf_lsm_v(l)%rad_net = 0.0_wp 
1874          ENDIF
1875          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_net )  .AND.                &
1876                     surf_usm_v(l)%ns > 0  )  THEN
1877             ALLOCATE( surf_usm_v(l)%rad_net(1:surf_usm_v(l)%ns) )
1878             surf_usm_v(l)%rad_net = 0.0_wp 
1879          ENDIF
1880       ENDDO
1881
1882
1883!
1884!--    Allocate array for storing the surface longwave (out) radiation change
1885       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_lw_out_change_0 )  .AND.          &
1886                  surf_lsm_h%ns > 0  )   THEN
1887          ALLOCATE( surf_lsm_h%rad_lw_out_change_0(1:surf_lsm_h%ns) )
1888          surf_lsm_h%rad_lw_out_change_0 = 0.0_wp 
1889       ENDIF
1890       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_lw_out_change_0 )  .AND.          &
1891                  surf_usm_h%ns > 0  )  THEN
1892          ALLOCATE( surf_usm_h%rad_lw_out_change_0(1:surf_usm_h%ns) )
1893          surf_usm_h%rad_lw_out_change_0 = 0.0_wp 
1894       ENDIF
1895       DO  l = 0, 3
1896          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_lw_out_change_0 )  .AND.    &
1897                     surf_lsm_v(l)%ns > 0  )  THEN
1898             ALLOCATE( surf_lsm_v(l)%rad_lw_out_change_0(1:surf_lsm_v(l)%ns) )
1899             surf_lsm_v(l)%rad_lw_out_change_0 = 0.0_wp 
1900          ENDIF
1901          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_lw_out_change_0 )  .AND.    &
1902                     surf_usm_v(l)%ns > 0  )  THEN
1903             ALLOCATE( surf_usm_v(l)%rad_lw_out_change_0(1:surf_usm_v(l)%ns) )
1904             surf_usm_v(l)%rad_lw_out_change_0 = 0.0_wp 
1905          ENDIF
1906       ENDDO
1907
1908!
1909!--    Allocate surface arrays for incoming/outgoing short/longwave radiation
1910       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_sw_in )  .AND.                    &
1911                  surf_lsm_h%ns > 0  )   THEN
1912          ALLOCATE( surf_lsm_h%rad_sw_in(1:surf_lsm_h%ns)  )
1913          ALLOCATE( surf_lsm_h%rad_sw_out(1:surf_lsm_h%ns) )
1914          ALLOCATE( surf_lsm_h%rad_sw_dir(1:surf_lsm_h%ns) )
1915          ALLOCATE( surf_lsm_h%rad_sw_dif(1:surf_lsm_h%ns) )
1916          ALLOCATE( surf_lsm_h%rad_sw_ref(1:surf_lsm_h%ns) )
1917          ALLOCATE( surf_lsm_h%rad_sw_res(1:surf_lsm_h%ns) )
1918          ALLOCATE( surf_lsm_h%rad_lw_in(1:surf_lsm_h%ns)  )
1919          ALLOCATE( surf_lsm_h%rad_lw_out(1:surf_lsm_h%ns) )
1920          ALLOCATE( surf_lsm_h%rad_lw_dif(1:surf_lsm_h%ns) )
1921          ALLOCATE( surf_lsm_h%rad_lw_ref(1:surf_lsm_h%ns) )
1922          ALLOCATE( surf_lsm_h%rad_lw_res(1:surf_lsm_h%ns) )
1923          surf_lsm_h%rad_sw_in  = 0.0_wp 
1924          surf_lsm_h%rad_sw_out = 0.0_wp 
1925          surf_lsm_h%rad_sw_dir = 0.0_wp 
1926          surf_lsm_h%rad_sw_dif = 0.0_wp 
1927          surf_lsm_h%rad_sw_ref = 0.0_wp 
1928          surf_lsm_h%rad_sw_res = 0.0_wp 
1929          surf_lsm_h%rad_lw_in  = 0.0_wp 
1930          surf_lsm_h%rad_lw_out = 0.0_wp 
1931          surf_lsm_h%rad_lw_dif = 0.0_wp 
1932          surf_lsm_h%rad_lw_ref = 0.0_wp 
1933          surf_lsm_h%rad_lw_res = 0.0_wp 
1934       ENDIF
1935       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_sw_in )  .AND.                    &
1936                  surf_usm_h%ns > 0  )  THEN
1937          ALLOCATE( surf_usm_h%rad_sw_in(1:surf_usm_h%ns)  )
1938          ALLOCATE( surf_usm_h%rad_sw_out(1:surf_usm_h%ns) )
1939          ALLOCATE( surf_usm_h%rad_sw_dir(1:surf_usm_h%ns) )
1940          ALLOCATE( surf_usm_h%rad_sw_dif(1:surf_usm_h%ns) )
1941          ALLOCATE( surf_usm_h%rad_sw_ref(1:surf_usm_h%ns) )
1942          ALLOCATE( surf_usm_h%rad_sw_res(1:surf_usm_h%ns) )
1943          ALLOCATE( surf_usm_h%rad_lw_in(1:surf_usm_h%ns)  )
1944          ALLOCATE( surf_usm_h%rad_lw_out(1:surf_usm_h%ns) )
1945          ALLOCATE( surf_usm_h%rad_lw_dif(1:surf_usm_h%ns) )
1946          ALLOCATE( surf_usm_h%rad_lw_ref(1:surf_usm_h%ns) )
1947          ALLOCATE( surf_usm_h%rad_lw_res(1:surf_usm_h%ns) )
1948          surf_usm_h%rad_sw_in  = 0.0_wp 
1949          surf_usm_h%rad_sw_out = 0.0_wp 
1950          surf_usm_h%rad_sw_dir = 0.0_wp 
1951          surf_usm_h%rad_sw_dif = 0.0_wp 
1952          surf_usm_h%rad_sw_ref = 0.0_wp 
1953          surf_usm_h%rad_sw_res = 0.0_wp 
1954          surf_usm_h%rad_lw_in  = 0.0_wp 
1955          surf_usm_h%rad_lw_out = 0.0_wp 
1956          surf_usm_h%rad_lw_dif = 0.0_wp 
1957          surf_usm_h%rad_lw_ref = 0.0_wp 
1958          surf_usm_h%rad_lw_res = 0.0_wp 
1959       ENDIF
1960       DO  l = 0, 3
1961          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_sw_in )  .AND.              &
1962                     surf_lsm_v(l)%ns > 0  )  THEN
1963             ALLOCATE( surf_lsm_v(l)%rad_sw_in(1:surf_lsm_v(l)%ns)  )
1964             ALLOCATE( surf_lsm_v(l)%rad_sw_out(1:surf_lsm_v(l)%ns) )
1965             ALLOCATE( surf_lsm_v(l)%rad_sw_dir(1:surf_lsm_v(l)%ns) )
1966             ALLOCATE( surf_lsm_v(l)%rad_sw_dif(1:surf_lsm_v(l)%ns) )
1967             ALLOCATE( surf_lsm_v(l)%rad_sw_ref(1:surf_lsm_v(l)%ns) )
1968             ALLOCATE( surf_lsm_v(l)%rad_sw_res(1:surf_lsm_v(l)%ns) )
1969
1970             ALLOCATE( surf_lsm_v(l)%rad_lw_in(1:surf_lsm_v(l)%ns)  )
1971             ALLOCATE( surf_lsm_v(l)%rad_lw_out(1:surf_lsm_v(l)%ns) )
1972             ALLOCATE( surf_lsm_v(l)%rad_lw_dif(1:surf_lsm_v(l)%ns) )
1973             ALLOCATE( surf_lsm_v(l)%rad_lw_ref(1:surf_lsm_v(l)%ns) )
1974             ALLOCATE( surf_lsm_v(l)%rad_lw_res(1:surf_lsm_v(l)%ns) )
1975
1976             surf_lsm_v(l)%rad_sw_in  = 0.0_wp 
1977             surf_lsm_v(l)%rad_sw_out = 0.0_wp
1978             surf_lsm_v(l)%rad_sw_dir = 0.0_wp
1979             surf_lsm_v(l)%rad_sw_dif = 0.0_wp
1980             surf_lsm_v(l)%rad_sw_ref = 0.0_wp
1981             surf_lsm_v(l)%rad_sw_res = 0.0_wp
1982
1983             surf_lsm_v(l)%rad_lw_in  = 0.0_wp 
1984             surf_lsm_v(l)%rad_lw_out = 0.0_wp 
1985             surf_lsm_v(l)%rad_lw_dif = 0.0_wp 
1986             surf_lsm_v(l)%rad_lw_ref = 0.0_wp 
1987             surf_lsm_v(l)%rad_lw_res = 0.0_wp 
1988          ENDIF
1989          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_sw_in )  .AND.              &
1990                     surf_usm_v(l)%ns > 0  )  THEN
1991             ALLOCATE( surf_usm_v(l)%rad_sw_in(1:surf_usm_v(l)%ns)  )
1992             ALLOCATE( surf_usm_v(l)%rad_sw_out(1:surf_usm_v(l)%ns) )
1993             ALLOCATE( surf_usm_v(l)%rad_sw_dir(1:surf_usm_v(l)%ns) )
1994             ALLOCATE( surf_usm_v(l)%rad_sw_dif(1:surf_usm_v(l)%ns) )
1995             ALLOCATE( surf_usm_v(l)%rad_sw_ref(1:surf_usm_v(l)%ns) )
1996             ALLOCATE( surf_usm_v(l)%rad_sw_res(1:surf_usm_v(l)%ns) )
1997             ALLOCATE( surf_usm_v(l)%rad_lw_in(1:surf_usm_v(l)%ns)  )
1998             ALLOCATE( surf_usm_v(l)%rad_lw_out(1:surf_usm_v(l)%ns) )
1999             ALLOCATE( surf_usm_v(l)%rad_lw_dif(1:surf_usm_v(l)%ns) )
2000             ALLOCATE( surf_usm_v(l)%rad_lw_ref(1:surf_usm_v(l)%ns) )
2001             ALLOCATE( surf_usm_v(l)%rad_lw_res(1:surf_usm_v(l)%ns) )
2002             surf_usm_v(l)%rad_sw_in  = 0.0_wp 
2003             surf_usm_v(l)%rad_sw_out = 0.0_wp
2004             surf_usm_v(l)%rad_sw_dir = 0.0_wp
2005             surf_usm_v(l)%rad_sw_dif = 0.0_wp
2006             surf_usm_v(l)%rad_sw_ref = 0.0_wp
2007             surf_usm_v(l)%rad_sw_res = 0.0_wp
2008             surf_usm_v(l)%rad_lw_in  = 0.0_wp 
2009             surf_usm_v(l)%rad_lw_out = 0.0_wp 
2010             surf_usm_v(l)%rad_lw_dif = 0.0_wp 
2011             surf_usm_v(l)%rad_lw_ref = 0.0_wp 
2012             surf_usm_v(l)%rad_lw_res = 0.0_wp 
2013          ENDIF
2014       ENDDO
2015!
2016!--    Fix net radiation in case of radiation_scheme = 'constant'
2017       IF ( radiation_scheme == 'constant' )  THEN
2018          IF ( ALLOCATED( surf_lsm_h%rad_net ) )                               &
2019             surf_lsm_h%rad_net    = net_radiation
2020          IF ( ALLOCATED( surf_usm_h%rad_net ) )                               &
2021             surf_usm_h%rad_net    = net_radiation
2022!
2023!--       Todo: weight with inclination angle
2024          DO  l = 0, 3
2025             IF ( ALLOCATED( surf_lsm_v(l)%rad_net ) )                         &
2026                surf_lsm_v(l)%rad_net = net_radiation
2027             IF ( ALLOCATED( surf_usm_v(l)%rad_net ) )                         &
2028                surf_usm_v(l)%rad_net = net_radiation
2029          ENDDO
2030!          radiation = .FALSE.
2031!
2032!--    Calculate orbital constants
2033       ELSE
2034          decl_1 = SIN(23.45_wp * pi / 180.0_wp)
2035          decl_2 = 2.0_wp * pi / 365.0_wp
2036          decl_3 = decl_2 * 81.0_wp
2037          lat    = latitude * pi / 180.0_wp
2038          lon    = longitude * pi / 180.0_wp
2039       ENDIF
2040
2041       IF ( radiation_scheme == 'clear-sky'  .OR.                              &
2042            radiation_scheme == 'constant')  THEN
2043
2044
2045!
2046!--       Allocate arrays for incoming/outgoing short/longwave radiation
2047          IF ( .NOT. ALLOCATED ( rad_sw_in ) )  THEN
2048             ALLOCATE ( rad_sw_in(0:0,nysg:nyng,nxlg:nxrg) )
2049          ENDIF
2050          IF ( .NOT. ALLOCATED ( rad_sw_out ) )  THEN
2051             ALLOCATE ( rad_sw_out(0:0,nysg:nyng,nxlg:nxrg) )
2052          ENDIF
2053
2054          IF ( .NOT. ALLOCATED ( rad_lw_in ) )  THEN
2055             ALLOCATE ( rad_lw_in(0:0,nysg:nyng,nxlg:nxrg) )
2056          ENDIF
2057          IF ( .NOT. ALLOCATED ( rad_lw_out ) )  THEN
2058             ALLOCATE ( rad_lw_out(0:0,nysg:nyng,nxlg:nxrg) )
2059          ENDIF
2060
2061!
2062!--       Allocate average arrays for incoming/outgoing short/longwave radiation
2063          IF ( .NOT. ALLOCATED ( rad_sw_in_av ) )  THEN
2064             ALLOCATE ( rad_sw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
2065          ENDIF
2066          IF ( .NOT. ALLOCATED ( rad_sw_out_av ) )  THEN
2067             ALLOCATE ( rad_sw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
2068          ENDIF
2069
2070          IF ( .NOT. ALLOCATED ( rad_lw_in_av ) )  THEN
2071             ALLOCATE ( rad_lw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
2072          ENDIF
2073          IF ( .NOT. ALLOCATED ( rad_lw_out_av ) )  THEN
2074             ALLOCATE ( rad_lw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
2075          ENDIF
2076!
2077!--       Allocate arrays for broadband albedo, and level 1 initialization
2078!--       via namelist paramter, unless not already allocated.
2079          IF ( .NOT. ALLOCATED(surf_lsm_h%albedo) )  THEN
2080             ALLOCATE( surf_lsm_h%albedo(0:2,1:surf_lsm_h%ns)     )
2081             surf_lsm_h%albedo    = albedo
2082          ENDIF
2083          IF ( .NOT. ALLOCATED(surf_usm_h%albedo) )  THEN
2084             ALLOCATE( surf_usm_h%albedo(0:2,1:surf_usm_h%ns)     )
2085             surf_usm_h%albedo    = albedo
2086          ENDIF
2087
2088          DO  l = 0, 3
2089             IF ( .NOT. ALLOCATED( surf_lsm_v(l)%albedo ) )  THEN
2090                ALLOCATE( surf_lsm_v(l)%albedo(0:2,1:surf_lsm_v(l)%ns) )
2091                surf_lsm_v(l)%albedo = albedo
2092             ENDIF
2093             IF ( .NOT. ALLOCATED( surf_usm_v(l)%albedo ) )  THEN
2094                ALLOCATE( surf_usm_v(l)%albedo(0:2,1:surf_usm_v(l)%ns) )
2095                surf_usm_v(l)%albedo = albedo
2096             ENDIF
2097          ENDDO
2098!
2099!--       Level 2 initialization of broadband albedo via given albedo_type.
2100!--       Only if albedo_type is non-zero. In case of urban surface and
2101!--       input data is read from ASCII file, albedo_type will be zero, so that
2102!--       albedo won't be overwritten.
2103          DO  m = 1, surf_lsm_h%ns
2104             IF ( surf_lsm_h%albedo_type(ind_veg_wall,m) /= 0 )                &
2105                surf_lsm_h%albedo(ind_veg_wall,m) =                            &
2106                           albedo_pars(2,surf_lsm_h%albedo_type(ind_veg_wall,m))
2107             IF ( surf_lsm_h%albedo_type(ind_pav_green,m) /= 0 )               &
2108                surf_lsm_h%albedo(ind_pav_green,m) =                           &
2109                           albedo_pars(2,surf_lsm_h%albedo_type(ind_pav_green,m))
2110             IF ( surf_lsm_h%albedo_type(ind_wat_win,m) /= 0 )                 &
2111                surf_lsm_h%albedo(ind_wat_win,m) =                             &
2112                           albedo_pars(2,surf_lsm_h%albedo_type(ind_wat_win,m))
2113          ENDDO
2114          DO  m = 1, surf_usm_h%ns
2115             IF ( surf_usm_h%albedo_type(ind_veg_wall,m) /= 0 )                &
2116                surf_usm_h%albedo(ind_veg_wall,m) =                            &
2117                           albedo_pars(2,surf_usm_h%albedo_type(ind_veg_wall,m))
2118             IF ( surf_usm_h%albedo_type(ind_pav_green,m) /= 0 )               &
2119                surf_usm_h%albedo(ind_pav_green,m) =                           &
2120                           albedo_pars(2,surf_usm_h%albedo_type(ind_pav_green,m))
2121             IF ( surf_usm_h%albedo_type(ind_wat_win,m) /= 0 )                 &
2122                surf_usm_h%albedo(ind_wat_win,m) =                             &
2123                           albedo_pars(2,surf_usm_h%albedo_type(ind_wat_win,m))
2124          ENDDO
2125
2126          DO  l = 0, 3
2127             DO  m = 1, surf_lsm_v(l)%ns
2128                IF ( surf_lsm_v(l)%albedo_type(ind_veg_wall,m) /= 0 )          &
2129                   surf_lsm_v(l)%albedo(ind_veg_wall,m) =                      &
2130                        albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_veg_wall,m))
2131                IF ( surf_lsm_v(l)%albedo_type(ind_pav_green,m) /= 0 )         &
2132                   surf_lsm_v(l)%albedo(ind_pav_green,m) =                     &
2133                        albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_pav_green,m))
2134                IF ( surf_lsm_v(l)%albedo_type(ind_wat_win,m) /= 0 )           &
2135                   surf_lsm_v(l)%albedo(ind_wat_win,m) =                       &
2136                        albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_wat_win,m))
2137             ENDDO
2138             DO  m = 1, surf_usm_v(l)%ns
2139                IF ( surf_usm_v(l)%albedo_type(ind_veg_wall,m) /= 0 )          &
2140                   surf_usm_v(l)%albedo(ind_veg_wall,m) =                      &
2141                        albedo_pars(2,surf_usm_v(l)%albedo_type(ind_veg_wall,m))
2142                IF ( surf_usm_v(l)%albedo_type(ind_pav_green,m) /= 0 )         &
2143                   surf_usm_v(l)%albedo(ind_pav_green,m) =                     &
2144                        albedo_pars(2,surf_usm_v(l)%albedo_type(ind_pav_green,m))
2145                IF ( surf_usm_v(l)%albedo_type(ind_wat_win,m) /= 0 )           &
2146                   surf_usm_v(l)%albedo(ind_wat_win,m) =                       &
2147                        albedo_pars(2,surf_usm_v(l)%albedo_type(ind_wat_win,m))
2148             ENDDO
2149          ENDDO
2150
2151!
2152!--       Level 3 initialization at grid points where albedo type is zero.
2153!--       This case, albedo is taken from file. In case of constant radiation
2154!--       or clear sky, only broadband albedo is given.
2155          IF ( albedo_pars_f%from_file )  THEN
2156!
2157!--          Horizontal surfaces
2158             DO  m = 1, surf_lsm_h%ns
2159                i = surf_lsm_h%i(m)
2160                j = surf_lsm_h%j(m)
2161                IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2162                   IF ( surf_lsm_h%albedo_type(ind_veg_wall,m) == 0 )          &
2163                      surf_lsm_h%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2164                   IF ( surf_lsm_h%albedo_type(ind_pav_green,m) == 0 )         &
2165                      surf_lsm_h%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2166                   IF ( surf_lsm_h%albedo_type(ind_wat_win,m) == 0 )           &
2167                      surf_lsm_h%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2168                ENDIF
2169             ENDDO
2170             DO  m = 1, surf_usm_h%ns
2171                i = surf_usm_h%i(m)
2172                j = surf_usm_h%j(m)
2173                IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2174                   IF ( surf_usm_h%albedo_type(ind_veg_wall,m) == 0 )          &
2175                      surf_usm_h%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2176                   IF ( surf_usm_h%albedo_type(ind_pav_green,m) == 0 )         &
2177                      surf_usm_h%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2178                   IF ( surf_usm_h%albedo_type(ind_wat_win,m) == 0 )           &
2179                      surf_usm_h%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2180                ENDIF
2181             ENDDO 
2182!
2183!--          Vertical surfaces           
2184             DO  l = 0, 3
2185
2186                ioff = surf_lsm_v(l)%ioff
2187                joff = surf_lsm_v(l)%joff
2188                DO  m = 1, surf_lsm_v(l)%ns
2189                   i = surf_lsm_v(l)%i(m) + ioff
2190                   j = surf_lsm_v(l)%j(m) + joff
2191                   IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2192                      IF ( surf_lsm_v(l)%albedo_type(ind_veg_wall,m) == 0 )    &
2193                         surf_lsm_v(l)%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2194                      IF ( surf_lsm_v(l)%albedo_type(ind_pav_green,m) == 0 )   &
2195                         surf_lsm_v(l)%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2196                      IF ( surf_lsm_v(l)%albedo_type(ind_wat_win,m) == 0 )     &
2197                         surf_lsm_v(l)%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2198                   ENDIF
2199                ENDDO
2200
2201                ioff = surf_usm_v(l)%ioff
2202                joff = surf_usm_v(l)%joff
2203                DO  m = 1, surf_usm_h%ns
2204                   i = surf_usm_h%i(m) + joff
2205                   j = surf_usm_h%j(m) + joff
2206                   IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2207                      IF ( surf_usm_v(l)%albedo_type(ind_veg_wall,m) == 0 )    &
2208                         surf_usm_v(l)%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2209                      IF ( surf_usm_v(l)%albedo_type(ind_pav_green,m) == 0 )   &
2210                         surf_usm_v(l)%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2211                      IF ( surf_usm_v(l)%albedo_type(ind_wat_win,m) == 0 )     &
2212                         surf_lsm_v(l)%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2213                   ENDIF
2214                ENDDO
2215             ENDDO
2216
2217          ENDIF 
2218!
2219!--    Initialization actions for RRTMG
2220       ELSEIF ( radiation_scheme == 'rrtmg' )  THEN
2221#if defined ( __rrtmg )
2222!
2223!--       Allocate albedos for short/longwave radiation, horizontal surfaces
2224!--       for wall/green/window (USM) or vegetation/pavement/water surfaces
2225!--       (LSM).
2226          ALLOCATE ( surf_lsm_h%aldif(0:2,1:surf_lsm_h%ns)       )
2227          ALLOCATE ( surf_lsm_h%aldir(0:2,1:surf_lsm_h%ns)       )
2228          ALLOCATE ( surf_lsm_h%asdif(0:2,1:surf_lsm_h%ns)       )
2229          ALLOCATE ( surf_lsm_h%asdir(0:2,1:surf_lsm_h%ns)       )
2230          ALLOCATE ( surf_lsm_h%rrtm_aldif(0:2,1:surf_lsm_h%ns)  )
2231          ALLOCATE ( surf_lsm_h%rrtm_aldir(0:2,1:surf_lsm_h%ns)  )
2232          ALLOCATE ( surf_lsm_h%rrtm_asdif(0:2,1:surf_lsm_h%ns)  )
2233          ALLOCATE ( surf_lsm_h%rrtm_asdir(0:2,1:surf_lsm_h%ns)  )
2234
2235          ALLOCATE ( surf_usm_h%aldif(0:2,1:surf_usm_h%ns)       )
2236          ALLOCATE ( surf_usm_h%aldir(0:2,1:surf_usm_h%ns)       )
2237          ALLOCATE ( surf_usm_h%asdif(0:2,1:surf_usm_h%ns)       )
2238          ALLOCATE ( surf_usm_h%asdir(0:2,1:surf_usm_h%ns)       )
2239          ALLOCATE ( surf_usm_h%rrtm_aldif(0:2,1:surf_usm_h%ns)  )
2240          ALLOCATE ( surf_usm_h%rrtm_aldir(0:2,1:surf_usm_h%ns)  )
2241          ALLOCATE ( surf_usm_h%rrtm_asdif(0:2,1:surf_usm_h%ns)  )
2242          ALLOCATE ( surf_usm_h%rrtm_asdir(0:2,1:surf_usm_h%ns)  )
2243
2244!
2245!--       Allocate broadband albedo (temporary for the current radiation
2246!--       implementations)
2247          IF ( .NOT. ALLOCATED(surf_lsm_h%albedo) )                            &
2248             ALLOCATE( surf_lsm_h%albedo(0:2,1:surf_lsm_h%ns)     )
2249          IF ( .NOT. ALLOCATED(surf_usm_h%albedo) )                            &
2250             ALLOCATE( surf_usm_h%albedo(0:2,1:surf_usm_h%ns)     )
2251
2252!
2253!--       Allocate albedos for short/longwave radiation, vertical surfaces
2254          DO  l = 0, 3
2255
2256             ALLOCATE ( surf_lsm_v(l)%aldif(0:2,1:surf_lsm_v(l)%ns)      )
2257             ALLOCATE ( surf_lsm_v(l)%aldir(0:2,1:surf_lsm_v(l)%ns)      )
2258             ALLOCATE ( surf_lsm_v(l)%asdif(0:2,1:surf_lsm_v(l)%ns)      )
2259             ALLOCATE ( surf_lsm_v(l)%asdir(0:2,1:surf_lsm_v(l)%ns)      )
2260
2261             ALLOCATE ( surf_lsm_v(l)%rrtm_aldif(0:2,1:surf_lsm_v(l)%ns) )
2262             ALLOCATE ( surf_lsm_v(l)%rrtm_aldir(0:2,1:surf_lsm_v(l)%ns) )
2263             ALLOCATE ( surf_lsm_v(l)%rrtm_asdif(0:2,1:surf_lsm_v(l)%ns) )
2264             ALLOCATE ( surf_lsm_v(l)%rrtm_asdir(0:2,1:surf_lsm_v(l)%ns) )
2265
2266             ALLOCATE ( surf_usm_v(l)%aldif(0:2,1:surf_usm_v(l)%ns)      )
2267             ALLOCATE ( surf_usm_v(l)%aldir(0:2,1:surf_usm_v(l)%ns)      )
2268             ALLOCATE ( surf_usm_v(l)%asdif(0:2,1:surf_usm_v(l)%ns)      )
2269             ALLOCATE ( surf_usm_v(l)%asdir(0:2,1:surf_usm_v(l)%ns)      )
2270
2271             ALLOCATE ( surf_usm_v(l)%rrtm_aldif(0:2,1:surf_usm_v(l)%ns) )
2272             ALLOCATE ( surf_usm_v(l)%rrtm_aldir(0:2,1:surf_usm_v(l)%ns) )
2273             ALLOCATE ( surf_usm_v(l)%rrtm_asdif(0:2,1:surf_usm_v(l)%ns) )
2274             ALLOCATE ( surf_usm_v(l)%rrtm_asdir(0:2,1:surf_usm_v(l)%ns) )
2275!
2276!--          Allocate broadband albedo (temporary for the current radiation
2277!--          implementations)
2278             IF ( .NOT. ALLOCATED( surf_lsm_v(l)%albedo ) )                    &
2279                ALLOCATE( surf_lsm_v(l)%albedo(0:2,1:surf_lsm_v(l)%ns) )
2280             IF ( .NOT. ALLOCATED( surf_usm_v(l)%albedo ) )                    &
2281                ALLOCATE( surf_usm_v(l)%albedo(0:2,1:surf_usm_v(l)%ns) )
2282
2283          ENDDO
2284!
2285!--       Level 1 initialization of spectral albedos via namelist
2286!--       paramters. Please note, this case all surface tiles are initialized
2287!--       the same.
2288          IF ( surf_lsm_h%ns > 0 )  THEN
2289             surf_lsm_h%aldif  = albedo_lw_dif
2290             surf_lsm_h%aldir  = albedo_lw_dir
2291             surf_lsm_h%asdif  = albedo_sw_dif
2292             surf_lsm_h%asdir  = albedo_sw_dir
2293             surf_lsm_h%albedo = albedo_sw_dif
2294          ENDIF
2295          IF ( surf_usm_h%ns > 0 )  THEN
2296             IF ( surf_usm_h%albedo_from_ascii )  THEN
2297                surf_usm_h%aldif  = surf_usm_h%albedo
2298                surf_usm_h%aldir  = surf_usm_h%albedo
2299                surf_usm_h%asdif  = surf_usm_h%albedo
2300                surf_usm_h%asdir  = surf_usm_h%albedo
2301             ELSE
2302                surf_usm_h%aldif  = albedo_lw_dif
2303                surf_usm_h%aldir  = albedo_lw_dir
2304                surf_usm_h%asdif  = albedo_sw_dif
2305                surf_usm_h%asdir  = albedo_sw_dir
2306                surf_usm_h%albedo = albedo_sw_dif
2307             ENDIF
2308          ENDIF
2309
2310          DO  l = 0, 3
2311
2312             IF ( surf_lsm_v(l)%ns > 0 )  THEN
2313                surf_lsm_v(l)%aldif  = albedo_lw_dif
2314                surf_lsm_v(l)%aldir  = albedo_lw_dir
2315                surf_lsm_v(l)%asdif  = albedo_sw_dif
2316                surf_lsm_v(l)%asdir  = albedo_sw_dir
2317                surf_lsm_v(l)%albedo = albedo_sw_dif
2318             ENDIF
2319
2320             IF ( surf_usm_v(l)%ns > 0 )  THEN
2321                IF ( surf_usm_v(l)%albedo_from_ascii )  THEN
2322                   surf_usm_v(l)%aldif  = surf_usm_v(l)%albedo
2323                   surf_usm_v(l)%aldir  = surf_usm_v(l)%albedo
2324                   surf_usm_v(l)%asdif  = surf_usm_v(l)%albedo
2325                   surf_usm_v(l)%asdir  = surf_usm_v(l)%albedo
2326                ELSE
2327                   surf_usm_v(l)%aldif  = albedo_lw_dif
2328                   surf_usm_v(l)%aldir  = albedo_lw_dir
2329                   surf_usm_v(l)%asdif  = albedo_sw_dif
2330                   surf_usm_v(l)%asdir  = albedo_sw_dir
2331                ENDIF
2332             ENDIF
2333          ENDDO
2334
2335!
2336!--       Level 2 initialization of spectral albedos via albedo_type.
2337!--       Please note, for natural- and urban-type surfaces, a tile approach
2338!--       is applied so that the resulting albedo is calculated via the weighted
2339!--       average of respective surface fractions.
2340          DO  m = 1, surf_lsm_h%ns
2341!
2342!--          Spectral albedos for vegetation/pavement/water surfaces
2343             DO  ind_type = 0, 2
2344                IF ( surf_lsm_h%albedo_type(ind_type,m) /= 0 )  THEN
2345                   surf_lsm_h%aldif(ind_type,m) =                              &
2346                               albedo_pars(0,surf_lsm_h%albedo_type(ind_type,m))
2347                   surf_lsm_h%asdif(ind_type,m) =                              &
2348                               albedo_pars(1,surf_lsm_h%albedo_type(ind_type,m))
2349                   surf_lsm_h%aldir(ind_type,m) =                              &
2350                               albedo_pars(0,surf_lsm_h%albedo_type(ind_type,m))
2351                   surf_lsm_h%asdir(ind_type,m) =                              &
2352                               albedo_pars(1,surf_lsm_h%albedo_type(ind_type,m))
2353                   surf_lsm_h%albedo(ind_type,m) =                             &
2354                               albedo_pars(2,surf_lsm_h%albedo_type(ind_type,m))
2355                ENDIF
2356             ENDDO
2357
2358          ENDDO
2359!
2360!--       For urban surface only if albedo has not been already initialized
2361!--       in the urban-surface model via the ASCII file.
2362          IF ( .NOT. surf_usm_h%albedo_from_ascii )  THEN
2363             DO  m = 1, surf_usm_h%ns
2364!
2365!--             Spectral albedos for wall/green/window surfaces
2366                DO  ind_type = 0, 2
2367                   IF ( surf_usm_h%albedo_type(ind_type,m) /= 0 )  THEN
2368                      surf_usm_h%aldif(ind_type,m) =                           &
2369                               albedo_pars(0,surf_usm_h%albedo_type(ind_type,m))
2370                      surf_usm_h%asdif(ind_type,m) =                           &
2371                               albedo_pars(1,surf_usm_h%albedo_type(ind_type,m))
2372                      surf_usm_h%aldir(ind_type,m) =                           &
2373                               albedo_pars(0,surf_usm_h%albedo_type(ind_type,m))
2374                      surf_usm_h%asdir(ind_type,m) =                           &
2375                               albedo_pars(1,surf_usm_h%albedo_type(ind_type,m))
2376                      surf_usm_h%albedo(ind_type,m) =                          &
2377                               albedo_pars(2,surf_usm_h%albedo_type(ind_type,m))
2378                   ENDIF
2379                ENDDO
2380
2381             ENDDO
2382          ENDIF
2383
2384          DO l = 0, 3
2385
2386             DO  m = 1, surf_lsm_v(l)%ns
2387!
2388!--             Spectral albedos for vegetation/pavement/water surfaces
2389                DO  ind_type = 0, 2
2390                   IF ( surf_lsm_v(l)%albedo_type(ind_type,m) /= 0 )  THEN
2391                      surf_lsm_v(l)%aldif(ind_type,m) =                        &
2392                            albedo_pars(0,surf_lsm_v(l)%albedo_type(ind_type,m))
2393                      surf_lsm_v(l)%asdif(ind_type,m) =                        &
2394                            albedo_pars(1,surf_lsm_v(l)%albedo_type(ind_type,m))
2395                      surf_lsm_v(l)%aldir(ind_type,m) =                        &
2396                            albedo_pars(0,surf_lsm_v(l)%albedo_type(ind_type,m))
2397                      surf_lsm_v(l)%asdir(ind_type,m) =                        &
2398                            albedo_pars(1,surf_lsm_v(l)%albedo_type(ind_type,m))
2399                      surf_lsm_v(l)%albedo(ind_type,m) =                       &
2400                            albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_type,m))
2401                   ENDIF
2402                ENDDO
2403             ENDDO
2404!
2405!--          For urban surface only if albedo has not been already initialized
2406!--          in the urban-surface model via the ASCII file.
2407             IF ( .NOT. surf_usm_v(l)%albedo_from_ascii )  THEN
2408                DO  m = 1, surf_usm_v(l)%ns
2409!
2410!--                Spectral albedos for wall/green/window surfaces
2411                   DO  ind_type = 0, 2
2412                      IF ( surf_usm_v(l)%albedo_type(ind_type,m) /= 0 )  THEN
2413                         surf_usm_v(l)%aldif(ind_type,m) =                     &
2414                            albedo_pars(0,surf_usm_v(l)%albedo_type(ind_type,m))
2415                         surf_usm_v(l)%asdif(ind_type,m) =                     &
2416                            albedo_pars(1,surf_usm_v(l)%albedo_type(ind_type,m))
2417                         surf_usm_v(l)%aldir(ind_type,m) =                     &
2418                            albedo_pars(0,surf_usm_v(l)%albedo_type(ind_type,m))
2419                         surf_usm_v(l)%asdir(ind_type,m) =                     &
2420                            albedo_pars(1,surf_usm_v(l)%albedo_type(ind_type,m))
2421                         surf_usm_v(l)%albedo(ind_type,m) =                    &
2422                            albedo_pars(2,surf_usm_v(l)%albedo_type(ind_type,m))
2423                      ENDIF
2424                   ENDDO
2425
2426                ENDDO
2427             ENDIF
2428          ENDDO
2429!
2430!--       Level 3 initialization at grid points where albedo type is zero.
2431!--       This case, spectral albedos are taken from file if available
2432          IF ( albedo_pars_f%from_file )  THEN
2433!
2434!--          Horizontal
2435             DO  m = 1, surf_lsm_h%ns
2436                i = surf_lsm_h%i(m)
2437                j = surf_lsm_h%j(m)
2438!
2439!--             Spectral albedos for vegetation/pavement/water surfaces
2440                DO  ind_type = 0, 2
2441                   IF ( surf_lsm_h%albedo_type(ind_type,m) == 0 )  THEN
2442                      IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2443                         surf_lsm_h%albedo(ind_type,m) =                       &
2444                                                albedo_pars_f%pars_xy(1,j,i)
2445                      IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2446                         surf_lsm_h%aldir(ind_type,m) =                        &
2447                                                albedo_pars_f%pars_xy(1,j,i)
2448                      IF ( albedo_pars_f%pars_xy(2,j,i) /= albedo_pars_f%fill )&
2449                         surf_lsm_h%aldif(ind_type,m) =                        &
2450                                                albedo_pars_f%pars_xy(2,j,i)
2451                      IF ( albedo_pars_f%pars_xy(3,j,i) /= albedo_pars_f%fill )&
2452                         surf_lsm_h%asdir(ind_type,m) =                        &
2453                                                albedo_pars_f%pars_xy(3,j,i)
2454                      IF ( albedo_pars_f%pars_xy(4,j,i) /= albedo_pars_f%fill )&
2455                         surf_lsm_h%asdif(ind_type,m) =                        &
2456                                                albedo_pars_f%pars_xy(4,j,i)
2457                   ENDIF
2458                ENDDO
2459             ENDDO
2460!
2461!--          For urban surface only if albedo has not been already initialized
2462!--          in the urban-surface model via the ASCII file.
2463             IF ( .NOT. surf_usm_h%albedo_from_ascii )  THEN
2464                DO  m = 1, surf_usm_h%ns
2465                   i = surf_usm_h%i(m)
2466                   j = surf_usm_h%j(m)
2467!
2468!--                Spectral albedos for wall/green/window surfaces
2469                   DO  ind_type = 0, 2
2470                      IF ( surf_usm_h%albedo_type(ind_type,m) == 0 )  THEN
2471                         IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2472                            surf_usm_h%albedo(ind_type,m) =                       &
2473                                                albedo_pars_f%pars_xy(1,j,i)
2474                         IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2475                            surf_usm_h%aldir(ind_type,m) =                        &
2476                                                albedo_pars_f%pars_xy(1,j,i)
2477                         IF ( albedo_pars_f%pars_xy(2,j,i) /= albedo_pars_f%fill )&
2478                            surf_usm_h%aldif(ind_type,m) =                        &
2479                                                albedo_pars_f%pars_xy(2,j,i)
2480                         IF ( albedo_pars_f%pars_xy(3,j,i) /= albedo_pars_f%fill )&
2481                            surf_usm_h%asdir(ind_type,m) =                        &
2482                                                albedo_pars_f%pars_xy(3,j,i)
2483                         IF ( albedo_pars_f%pars_xy(4,j,i) /= albedo_pars_f%fill )&
2484                            surf_usm_h%asdif(ind_type,m) =                        &
2485                                                albedo_pars_f%pars_xy(4,j,i)
2486                      ENDIF
2487                   ENDDO
2488
2489                ENDDO
2490             ENDIF
2491!
2492!--          Vertical
2493             DO  l = 0, 3
2494                ioff = surf_lsm_v(l)%ioff
2495                joff = surf_lsm_v(l)%joff
2496
2497                DO  m = 1, surf_lsm_v(l)%ns
2498                   i = surf_lsm_v(l)%i(m)
2499                   j = surf_lsm_v(l)%j(m)
2500!
2501!--                Spectral albedos for vegetation/pavement/water surfaces
2502                   DO  ind_type = 0, 2
2503                      IF ( surf_lsm_v(l)%albedo_type(ind_type,m) == 0 )  THEN
2504                         IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2505                              albedo_pars_f%fill )                             &
2506                            surf_lsm_v(l)%albedo(ind_type,m) =                 &
2507                                          albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2508                         IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2509                              albedo_pars_f%fill )                             &
2510                            surf_lsm_v(l)%aldir(ind_type,m) =                  &
2511                                          albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2512                         IF ( albedo_pars_f%pars_xy(2,j+joff,i+ioff) /=        &
2513                              albedo_pars_f%fill )                             &
2514                            surf_lsm_v(l)%aldif(ind_type,m) =                  &
2515                                          albedo_pars_f%pars_xy(2,j+joff,i+ioff)
2516                         IF ( albedo_pars_f%pars_xy(3,j+joff,i+ioff) /=        &
2517                              albedo_pars_f%fill )                             &
2518                            surf_lsm_v(l)%asdir(ind_type,m) =                  &
2519                                          albedo_pars_f%pars_xy(3,j+joff,i+ioff)
2520                         IF ( albedo_pars_f%pars_xy(4,j+joff,i+ioff) /=        &
2521                              albedo_pars_f%fill )                             &
2522                            surf_lsm_v(l)%asdif(ind_type,m) =                  &
2523                                          albedo_pars_f%pars_xy(4,j+joff,i+ioff)
2524                      ENDIF
2525                   ENDDO
2526                ENDDO
2527!
2528!--             For urban surface only if albedo has not been already initialized
2529!--             in the urban-surface model via the ASCII file.
2530                IF ( .NOT. surf_usm_v(l)%albedo_from_ascii )  THEN
2531                   ioff = surf_usm_v(l)%ioff
2532                   joff = surf_usm_v(l)%joff
2533
2534                   DO  m = 1, surf_usm_v(l)%ns
2535                      i = surf_usm_v(l)%i(m)
2536                      j = surf_usm_v(l)%j(m)
2537!
2538!--                   Spectral albedos for wall/green/window surfaces
2539                      DO  ind_type = 0, 2
2540                         IF ( surf_usm_v(l)%albedo_type(ind_type,m) == 0 )  THEN
2541                            IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2542                                 albedo_pars_f%fill )                             &
2543                               surf_usm_v(l)%albedo(ind_type,m) =                 &
2544                                             albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2545                            IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2546                                 albedo_pars_f%fill )                             &
2547                               surf_usm_v(l)%aldir(ind_type,m) =                  &
2548                                             albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2549                            IF ( albedo_pars_f%pars_xy(2,j+joff,i+ioff) /=        &
2550                                 albedo_pars_f%fill )                             &
2551                               surf_usm_v(l)%aldif(ind_type,m) =                  &
2552                                             albedo_pars_f%pars_xy(2,j+joff,i+ioff)
2553                            IF ( albedo_pars_f%pars_xy(3,j+joff,i+ioff) /=        &
2554                                 albedo_pars_f%fill )                             &
2555                               surf_usm_v(l)%asdir(ind_type,m) =                  &
2556                                             albedo_pars_f%pars_xy(3,j+joff,i+ioff)
2557                            IF ( albedo_pars_f%pars_xy(4,j+joff,i+ioff) /=        &
2558                                 albedo_pars_f%fill )                             &
2559                               surf_usm_v(l)%asdif(ind_type,m) =                  &
2560                                             albedo_pars_f%pars_xy(4,j+joff,i+ioff)
2561                         ENDIF
2562                      ENDDO
2563
2564                   ENDDO
2565                ENDIF
2566             ENDDO
2567
2568          ENDIF
2569
2570!
2571!--       Calculate initial values of current (cosine of) the zenith angle and
2572!--       whether the sun is up
2573          CALL calc_zenith
2574!
2575!--       readjust date and time to its initial value
2576          CALL init_date_and_time
2577!
2578!--       Calculate initial surface albedo for different surfaces
2579          IF ( .NOT. constant_albedo )  THEN
2580#if defined( __netcdf )
2581!
2582!--          Horizontally aligned natural and urban surfaces
2583             CALL calc_albedo( surf_lsm_h )
2584             CALL calc_albedo( surf_usm_h )
2585!
2586!--          Vertically aligned natural and urban surfaces
2587             DO  l = 0, 3
2588                CALL calc_albedo( surf_lsm_v(l) )
2589                CALL calc_albedo( surf_usm_v(l) )
2590             ENDDO
2591#endif
2592          ELSE
2593!
2594!--          Initialize sun-inclination independent spectral albedos
2595!--          Horizontal surfaces
2596             IF ( surf_lsm_h%ns > 0 )  THEN
2597                surf_lsm_h%rrtm_aldir = surf_lsm_h%aldir
2598                surf_lsm_h%rrtm_asdir = surf_lsm_h%asdir
2599                surf_lsm_h%rrtm_aldif = surf_lsm_h%aldif
2600                surf_lsm_h%rrtm_asdif = surf_lsm_h%asdif
2601             ENDIF
2602             IF ( surf_usm_h%ns > 0 )  THEN
2603                surf_usm_h%rrtm_aldir = surf_usm_h%aldir
2604                surf_usm_h%rrtm_asdir = surf_usm_h%asdir
2605                surf_usm_h%rrtm_aldif = surf_usm_h%aldif
2606                surf_usm_h%rrtm_asdif = surf_usm_h%asdif
2607             ENDIF
2608!
2609!--          Vertical surfaces
2610             DO  l = 0, 3
2611                IF ( surf_lsm_v(l)%ns > 0 )  THEN
2612                   surf_lsm_v(l)%rrtm_aldir = surf_lsm_v(l)%aldir
2613                   surf_lsm_v(l)%rrtm_asdir = surf_lsm_v(l)%asdir
2614                   surf_lsm_v(l)%rrtm_aldif = surf_lsm_v(l)%aldif
2615                   surf_lsm_v(l)%rrtm_asdif = surf_lsm_v(l)%asdif
2616                ENDIF
2617                IF ( surf_usm_v(l)%ns > 0 )  THEN
2618                   surf_usm_v(l)%rrtm_aldir = surf_usm_v(l)%aldir
2619                   surf_usm_v(l)%rrtm_asdir = surf_usm_v(l)%asdir
2620                   surf_usm_v(l)%rrtm_aldif = surf_usm_v(l)%aldif
2621                   surf_usm_v(l)%rrtm_asdif = surf_usm_v(l)%asdif
2622                ENDIF
2623             ENDDO
2624
2625          ENDIF
2626
2627!
2628!--       Allocate 3d arrays of radiative fluxes and heating rates
2629          IF ( .NOT. ALLOCATED ( rad_sw_in ) )  THEN
2630             ALLOCATE ( rad_sw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2631             rad_sw_in = 0.0_wp
2632          ENDIF
2633
2634          IF ( .NOT. ALLOCATED ( rad_sw_in_av ) )  THEN
2635             ALLOCATE ( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2636          ENDIF
2637
2638          IF ( .NOT. ALLOCATED ( rad_sw_out ) )  THEN
2639             ALLOCATE ( rad_sw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2640             rad_sw_out = 0.0_wp
2641          ENDIF
2642
2643          IF ( .NOT. ALLOCATED ( rad_sw_out_av ) )  THEN
2644             ALLOCATE ( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2645          ENDIF
2646
2647          IF ( .NOT. ALLOCATED ( rad_sw_hr ) )  THEN
2648             ALLOCATE ( rad_sw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2649             rad_sw_hr = 0.0_wp
2650          ENDIF
2651
2652          IF ( .NOT. ALLOCATED ( rad_sw_hr_av ) )  THEN
2653             ALLOCATE ( rad_sw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2654             rad_sw_hr_av = 0.0_wp
2655          ENDIF
2656
2657          IF ( .NOT. ALLOCATED ( rad_sw_cs_hr ) )  THEN
2658             ALLOCATE ( rad_sw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2659             rad_sw_cs_hr = 0.0_wp
2660          ENDIF
2661
2662          IF ( .NOT. ALLOCATED ( rad_sw_cs_hr_av ) )  THEN
2663             ALLOCATE ( rad_sw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2664             rad_sw_cs_hr_av = 0.0_wp
2665          ENDIF
2666
2667          IF ( .NOT. ALLOCATED ( rad_lw_in ) )  THEN
2668             ALLOCATE ( rad_lw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2669             rad_lw_in = 0.0_wp
2670          ENDIF
2671
2672          IF ( .NOT. ALLOCATED ( rad_lw_in_av ) )  THEN
2673             ALLOCATE ( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2674          ENDIF
2675
2676          IF ( .NOT. ALLOCATED ( rad_lw_out ) )  THEN
2677             ALLOCATE ( rad_lw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2678            rad_lw_out = 0.0_wp
2679          ENDIF
2680
2681          IF ( .NOT. ALLOCATED ( rad_lw_out_av ) )  THEN
2682             ALLOCATE ( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2683          ENDIF
2684
2685          IF ( .NOT. ALLOCATED ( rad_lw_hr ) )  THEN
2686             ALLOCATE ( rad_lw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2687             rad_lw_hr = 0.0_wp
2688          ENDIF
2689
2690          IF ( .NOT. ALLOCATED ( rad_lw_hr_av ) )  THEN
2691             ALLOCATE ( rad_lw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2692             rad_lw_hr_av = 0.0_wp
2693          ENDIF
2694
2695          IF ( .NOT. ALLOCATED ( rad_lw_cs_hr ) )  THEN
2696             ALLOCATE ( rad_lw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2697             rad_lw_cs_hr = 0.0_wp
2698          ENDIF
2699
2700          IF ( .NOT. ALLOCATED ( rad_lw_cs_hr_av ) )  THEN
2701             ALLOCATE ( rad_lw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2702             rad_lw_cs_hr_av = 0.0_wp
2703          ENDIF
2704
2705          ALLOCATE ( rad_sw_cs_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2706          ALLOCATE ( rad_sw_cs_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2707          rad_sw_cs_in  = 0.0_wp
2708          rad_sw_cs_out = 0.0_wp
2709
2710          ALLOCATE ( rad_lw_cs_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2711          ALLOCATE ( rad_lw_cs_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2712          rad_lw_cs_in  = 0.0_wp
2713          rad_lw_cs_out = 0.0_wp
2714
2715!
2716!--       Allocate 1-element array for surface temperature
2717!--       (RRTMG anticipates an array as passed argument).
2718          ALLOCATE ( rrtm_tsfc(1) )
2719!
2720!--       Allocate surface emissivity.
2721!--       Values will be given directly before calling rrtm_lw.
2722          ALLOCATE ( rrtm_emis(0:0,1:nbndlw+1) )
2723
2724!
2725!--       Initialize RRTMG, before check if files are existent
2726          INQUIRE( FILE='rrtmg_lw.nc', EXIST=lw_exists )
2727          IF ( .NOT. lw_exists )  THEN
2728             message_string = 'Input file rrtmg_lw.nc' //                &
2729                            '&for rrtmg missing. ' // &
2730                            '&Please provide <jobname>_lsw file in the INPUT directory.'
2731             CALL message( 'radiation_init', 'PA0583', 1, 2, 0, 6, 0 )
2732          ENDIF         
2733          INQUIRE( FILE='rrtmg_sw.nc', EXIST=sw_exists )
2734          IF ( .NOT. sw_exists )  THEN
2735             message_string = 'Input file rrtmg_sw.nc' //                &
2736                            '&for rrtmg missing. ' // &
2737                            '&Please provide <jobname>_rsw file in the INPUT directory.'
2738             CALL message( 'radiation_init', 'PA0584', 1, 2, 0, 6, 0 )
2739          ENDIF         
2740         
2741          IF ( lw_radiation )  CALL rrtmg_lw_ini ( c_p )
2742          IF ( sw_radiation )  CALL rrtmg_sw_ini ( c_p )
2743         
2744!
2745!--       Set input files for RRTMG
2746          INQUIRE(FILE="RAD_SND_DATA", EXIST=snd_exists) 
2747          IF ( .NOT. snd_exists )  THEN
2748             rrtm_input_file = "rrtmg_lw.nc"
2749          ENDIF
2750
2751!
2752!--       Read vertical layers for RRTMG from sounding data
2753!--       The routine provides nzt_rad, hyp_snd(1:nzt_rad),
2754!--       t_snd(nzt+2:nzt_rad), rrtm_play(1:nzt_rad), rrtm_plev(1_nzt_rad+1),
2755!--       rrtm_tlay(nzt+2:nzt_rad), rrtm_tlev(nzt+2:nzt_rad+1)
2756          CALL read_sounding_data
2757
2758!
2759!--       Read trace gas profiles from file. This routine provides
2760!--       the rrtm_ arrays (1:nzt_rad+1)
2761          CALL read_trace_gas_data
2762#endif
2763       ENDIF
2764
2765!
2766!--    Perform user actions if required
2767       CALL user_init_radiation
2768
2769!
2770!--    Calculate radiative fluxes at model start
2771       SELECT CASE ( TRIM( radiation_scheme ) )
2772
2773          CASE ( 'rrtmg' )
2774             CALL radiation_rrtmg
2775
2776          CASE ( 'clear-sky' )
2777             CALL radiation_clearsky
2778
2779          CASE ( 'constant' )
2780             CALL radiation_constant
2781
2782          CASE DEFAULT
2783
2784       END SELECT
2785
2786! readjust date and time to its initial value
2787       CALL init_date_and_time
2788
2789       CALL location_message( 'finished', .TRUE. )
2790
2791!
2792!--    Find all discretized apparent solar positions for radiation interaction.
2793       IF ( radiation_interactions )  CALL radiation_presimulate_solar_pos
2794
2795!
2796!--    If required, read or calculate and write out the SVF
2797       IF ( radiation_interactions .AND. read_svf)  THEN
2798!
2799!--       Read sky-view factors and further required data from file
2800          CALL location_message( '    Start reading SVF from file', .FALSE. )
2801          CALL radiation_read_svf()
2802          CALL location_message( '    Reading SVF from file has finished', .TRUE. )
2803
2804       ELSEIF ( radiation_interactions .AND. .NOT. read_svf)  THEN
2805!
2806!--       calculate SFV and CSF
2807          CALL location_message( '    Start calculation of SVF', .FALSE. )
2808          CALL radiation_calc_svf()
2809          CALL location_message( '    Calculation of SVF has finished', .TRUE. )
2810       ENDIF
2811
2812       IF ( radiation_interactions .AND. write_svf)  THEN
2813!
2814!--       Write svf, csf svfsurf and csfsurf data to file
2815          CALL location_message( '    Start writing SVF in file', .FALSE. )
2816          CALL radiation_write_svf()
2817          CALL location_message( '    Writing SVF in file has finished', .TRUE. )
2818       ENDIF
2819
2820!
2821!--    Adjust radiative fluxes. In case of urban and land surfaces, also
2822!--    call an initial interaction.
2823       IF ( radiation_interactions )  THEN
2824          CALL radiation_interaction
2825       ENDIF
2826
2827       RETURN
2828
2829    END SUBROUTINE radiation_init
2830
2831
2832!------------------------------------------------------------------------------!
2833! Description:
2834! ------------
2835!> A simple clear sky radiation model
2836!------------------------------------------------------------------------------!
2837    SUBROUTINE radiation_clearsky
2838
2839
2840       IMPLICIT NONE
2841
2842       INTEGER(iwp) ::  l         !< running index for surface orientation
2843       REAL(wp)     ::  pt1       !< potential temperature at first grid level or mean value at urban layer top
2844       REAL(wp)     ::  pt1_l     !< potential temperature at first grid level or mean value at urban layer top at local subdomain
2845       REAL(wp)     ::  ql1       !< liquid water mixing ratio at first grid level or mean value at urban layer top
2846       REAL(wp)     ::  ql1_l     !< liquid water mixing ratio at first grid level or mean value at urban layer top at local subdomain
2847
2848       TYPE(surf_type), POINTER ::  surf !< pointer on respective surface type, used to generalize routine   
2849
2850!
2851!--    Calculate current zenith angle
2852       CALL calc_zenith
2853
2854!
2855!--    Calculate sky transmissivity
2856       sky_trans = 0.6_wp + 0.2_wp * cos_zenith
2857
2858!
2859!--    Calculate value of the Exner function at model surface
2860!
2861!--    In case averaged radiation is used, calculate mean temperature and
2862!--    liquid water mixing ratio at the urban-layer top.
2863       IF ( average_radiation ) THEN
2864          pt1   = 0.0_wp
2865          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1   = 0.0_wp
2866
2867          pt1_l = SUM( pt(nz_urban_t,nys:nyn,nxl:nxr) )
2868          IF ( bulk_cloud_model  .OR.  cloud_droplets  )  ql1_l = SUM( ql(nz_urban_t,nys:nyn,nxl:nxr) )
2869
2870#if defined( __parallel )     
2871          IF ( collective_wait )  CALL MPI_BARRIER( comm2d, ierr )
2872          CALL MPI_ALLREDUCE( pt1_l, pt1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
2873          IF ( ierr /= 0 ) THEN
2874              WRITE(9,*) 'Error MPI_AllReduce1:', ierr, pt1_l, pt1
2875              FLUSH(9)
2876          ENDIF
2877
2878          IF ( bulk_cloud_model  .OR.  cloud_droplets ) THEN
2879              CALL MPI_ALLREDUCE( ql1_l, ql1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
2880              IF ( ierr /= 0 ) THEN
2881                  WRITE(9,*) 'Error MPI_AllReduce2:', ierr, ql1_l, ql1
2882                  FLUSH(9)
2883              ENDIF
2884          ENDIF
2885#else
2886          pt1 = pt1_l 
2887          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1 = ql1_l
2888#endif
2889
2890          IF ( bulk_cloud_model  .OR.  cloud_droplets  )  pt1 = pt1 + lv_d_cp / exner(nz_urban_t) * ql1
2891!
2892!--       Finally, divide by number of grid points
2893          pt1 = pt1 / REAL( ( nx + 1 ) * ( ny + 1 ), KIND=wp )
2894       ENDIF
2895!
2896!--    Call clear-sky calculation for each surface orientation.
2897!--    First, horizontal surfaces
2898       surf => surf_lsm_h
2899       CALL radiation_clearsky_surf
2900       surf => surf_usm_h
2901       CALL radiation_clearsky_surf
2902!
2903!--    Vertical surfaces
2904       DO  l = 0, 3
2905          surf => surf_lsm_v(l)
2906          CALL radiation_clearsky_surf
2907          surf => surf_usm_v(l)
2908          CALL radiation_clearsky_surf
2909       ENDDO
2910
2911       CONTAINS
2912
2913          SUBROUTINE radiation_clearsky_surf
2914
2915             IMPLICIT NONE
2916
2917             INTEGER(iwp) ::  i         !< index x-direction
2918             INTEGER(iwp) ::  j         !< index y-direction
2919             INTEGER(iwp) ::  k         !< index z-direction
2920             INTEGER(iwp) ::  m         !< running index for surface elements
2921
2922             IF ( surf%ns < 1 )  RETURN
2923
2924!
2925!--          Calculate radiation fluxes and net radiation (rad_net) assuming
2926!--          homogeneous urban radiation conditions.
2927             IF ( average_radiation ) THEN       
2928
2929                k = nz_urban_t
2930
2931                surf%rad_sw_in  = solar_constant * sky_trans * cos_zenith
2932                surf%rad_sw_out = albedo_urb * surf%rad_sw_in
2933               
2934                surf%rad_lw_in  = emissivity_atm_clsky * sigma_sb * (pt1 * exner(k+1))**4
2935
2936                surf%rad_lw_out = emissivity_urb * sigma_sb * (t_rad_urb)**4   &
2937                                    + (1.0_wp - emissivity_urb) * surf%rad_lw_in
2938
2939                surf%rad_net = surf%rad_sw_in - surf%rad_sw_out                &
2940                             + surf%rad_lw_in - surf%rad_lw_out
2941
2942                surf%rad_lw_out_change_0 = 3.0_wp * emissivity_urb * sigma_sb  &
2943                                           * (t_rad_urb)**3
2944
2945!
2946!--          Calculate radiation fluxes and net radiation (rad_net) for each surface
2947!--          element.
2948             ELSE
2949
2950                DO  m = 1, surf%ns
2951                   i = surf%i(m)
2952                   j = surf%j(m)
2953                   k = surf%k(m)
2954
2955                   surf%rad_sw_in(m) = solar_constant * sky_trans * cos_zenith
2956
2957!
2958!--                Weighted average according to surface fraction.
2959!--                ATTENTION: when radiation interactions are switched on the
2960!--                calculated fluxes below are not actually used as they are
2961!--                overwritten in radiation_interaction.
2962                   surf%rad_sw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
2963                                          surf%albedo(ind_veg_wall,m)          &
2964                                        + surf%frac(ind_pav_green,m) *         &
2965                                          surf%albedo(ind_pav_green,m)         &
2966                                        + surf%frac(ind_wat_win,m)   *         &
2967                                          surf%albedo(ind_wat_win,m) )         &
2968                                        * surf%rad_sw_in(m)
2969
2970                   surf%rad_lw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
2971                                          surf%emissivity(ind_veg_wall,m)      &
2972                                        + surf%frac(ind_pav_green,m) *         &
2973                                          surf%emissivity(ind_pav_green,m)     &
2974                                        + surf%frac(ind_wat_win,m)   *         &
2975                                          surf%emissivity(ind_wat_win,m)       &
2976                                        )                                      &
2977                                        * sigma_sb                             &
2978                                        * ( surf%pt_surface(m) * exner(nzb) )**4
2979
2980                   surf%rad_lw_out_change_0(m) =                               &
2981                                      ( surf%frac(ind_veg_wall,m)  *           &
2982                                        surf%emissivity(ind_veg_wall,m)        &
2983                                      + surf%frac(ind_pav_green,m) *           &
2984                                        surf%emissivity(ind_pav_green,m)       &
2985                                      + surf%frac(ind_wat_win,m)   *           &
2986                                        surf%emissivity(ind_wat_win,m)         &
2987                                      ) * 3.0_wp * sigma_sb                    &
2988                                      * ( surf%pt_surface(m) * exner(nzb) )** 3
2989
2990
2991                   IF ( bulk_cloud_model  .OR.  cloud_droplets  )  THEN
2992                      pt1 = pt(k,j,i) + lv_d_cp / exner(k) * ql(k,j,i)
2993                      surf%rad_lw_in(m)  = emissivity_atm_clsky * sigma_sb * (pt1 * exner(k))**4
2994                   ELSE
2995                      surf%rad_lw_in(m)  = emissivity_atm_clsky * sigma_sb * (pt(k,j,i) * exner(k))**4
2996                   ENDIF
2997
2998                   surf%rad_net(m) = surf%rad_sw_in(m) - surf%rad_sw_out(m)    &
2999                                   + surf%rad_lw_in(m) - surf%rad_lw_out(m)
3000
3001                ENDDO
3002
3003             ENDIF
3004
3005!
3006!--          Fill out values in radiation arrays
3007             DO  m = 1, surf%ns
3008                i = surf%i(m)
3009                j = surf%j(m)
3010                rad_sw_in(0,j,i) = surf%rad_sw_in(m)
3011                rad_sw_out(0,j,i) = surf%rad_sw_out(m)
3012                rad_lw_in(0,j,i) = surf%rad_lw_in(m)
3013                rad_lw_out(0,j,i) = surf%rad_lw_out(m)
3014             ENDDO
3015 
3016          END SUBROUTINE radiation_clearsky_surf
3017
3018    END SUBROUTINE radiation_clearsky
3019
3020
3021!------------------------------------------------------------------------------!
3022! Description:
3023! ------------
3024!> This scheme keeps the prescribed net radiation constant during the run
3025!------------------------------------------------------------------------------!
3026    SUBROUTINE radiation_constant
3027
3028
3029       IMPLICIT NONE
3030
3031       INTEGER(iwp) ::  l         !< running index for surface orientation
3032
3033       REAL(wp)     ::  pt1       !< potential temperature at first grid level or mean value at urban layer top
3034       REAL(wp)     ::  pt1_l     !< potential temperature at first grid level or mean value at urban layer top at local subdomain
3035       REAL(wp)     ::  ql1       !< liquid water mixing ratio at first grid level or mean value at urban layer top
3036       REAL(wp)     ::  ql1_l     !< liquid water mixing ratio at first grid level or mean value at urban layer top at local subdomain
3037
3038       TYPE(surf_type), POINTER ::  surf !< pointer on respective surface type, used to generalize routine
3039
3040!
3041!--    In case averaged radiation is used, calculate mean temperature and
3042!--    liquid water mixing ratio at the urban-layer top.
3043       IF ( average_radiation ) THEN   
3044          pt1   = 0.0_wp
3045          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1   = 0.0_wp
3046
3047          pt1_l = SUM( pt(nz_urban_t,nys:nyn,nxl:nxr) )
3048          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1_l = SUM( ql(nz_urban_t,nys:nyn,nxl:nxr) )
3049
3050#if defined( __parallel )     
3051          IF ( collective_wait )  CALL MPI_BARRIER( comm2d, ierr )
3052          CALL MPI_ALLREDUCE( pt1_l, pt1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
3053          IF ( ierr /= 0 ) THEN
3054              WRITE(9,*) 'Error MPI_AllReduce3:', ierr, pt1_l, pt1
3055              FLUSH(9)
3056          ENDIF
3057          IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
3058             CALL MPI_ALLREDUCE( ql1_l, ql1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
3059             IF ( ierr /= 0 ) THEN
3060                 WRITE(9,*) 'Error MPI_AllReduce4:', ierr, ql1_l, ql1
3061                 FLUSH(9)
3062             ENDIF
3063          ENDIF
3064#else
3065          pt1 = pt1_l
3066          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1 = ql1_l
3067#endif
3068          IF ( bulk_cloud_model  .OR.  cloud_droplets )  pt1 = pt1 + lv_d_cp / exner(nz_urban_t+1) * ql1
3069!
3070!--       Finally, divide by number of grid points
3071          pt1 = pt1 / REAL( ( nx + 1 ) * ( ny + 1 ), KIND=wp )
3072       ENDIF
3073
3074!
3075!--    First, horizontal surfaces
3076       surf => surf_lsm_h
3077       CALL radiation_constant_surf
3078       surf => surf_usm_h
3079       CALL radiation_constant_surf
3080!
3081!--    Vertical surfaces
3082       DO  l = 0, 3
3083          surf => surf_lsm_v(l)
3084          CALL radiation_constant_surf
3085          surf => surf_usm_v(l)
3086          CALL radiation_constant_surf
3087       ENDDO
3088
3089       CONTAINS
3090
3091          SUBROUTINE radiation_constant_surf
3092
3093             IMPLICIT NONE
3094
3095             INTEGER(iwp) ::  i         !< index x-direction
3096             INTEGER(iwp) ::  ioff      !< offset between surface element and adjacent grid point along x
3097             INTEGER(iwp) ::  j         !< index y-direction
3098             INTEGER(iwp) ::  joff      !< offset between surface element and adjacent grid point along y
3099             INTEGER(iwp) ::  k         !< index z-direction
3100             INTEGER(iwp) ::  koff      !< offset between surface element and adjacent grid point along z
3101             INTEGER(iwp) ::  m         !< running index for surface elements
3102
3103             IF ( surf%ns < 1 )  RETURN
3104
3105!--          Calculate homogenoeus urban radiation fluxes
3106             IF ( average_radiation ) THEN
3107
3108                surf%rad_net = net_radiation
3109
3110                surf%rad_lw_in  = emissivity_atm_clsky * sigma_sb * (pt1 * exner(nz_urban_t+1))**4
3111
3112                surf%rad_lw_out = emissivity_urb * sigma_sb * (t_rad_urb)**4   &
3113                                    + ( 1.0_wp - emissivity_urb )             & ! shouldn't be this a bulk value -- emissivity_urb?
3114                                    * surf%rad_lw_in
3115
3116                surf%rad_lw_out_change_0 = 3.0_wp * emissivity_urb * sigma_sb  &
3117                                           * t_rad_urb**3
3118
3119                surf%rad_sw_in = ( surf%rad_net - surf%rad_lw_in               &
3120                                     + surf%rad_lw_out )                       &
3121                                     / ( 1.0_wp - albedo_urb )
3122
3123                surf%rad_sw_out =  albedo_urb * surf%rad_sw_in
3124
3125!
3126!--          Calculate radiation fluxes for each surface element
3127             ELSE
3128!
3129!--             Determine index offset between surface element and adjacent
3130!--             atmospheric grid point
3131                ioff = surf%ioff
3132                joff = surf%joff
3133                koff = surf%koff
3134
3135!
3136!--             Prescribe net radiation and estimate the remaining radiative fluxes
3137                DO  m = 1, surf%ns
3138                   i = surf%i(m)
3139                   j = surf%j(m)
3140                   k = surf%k(m)
3141
3142                   surf%rad_net(m) = net_radiation
3143
3144                   IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
3145                      pt1 = pt(k,j,i) + lv_d_cp / exner(k) * ql(k,j,i)
3146                      surf%rad_lw_in(m)  = emissivity_atm_clsky * sigma_sb * (pt1 * exner(k))**4
3147                   ELSE
3148                      surf%rad_lw_in(m)  = emissivity_atm_clsky * sigma_sb *                 &
3149                                             ( pt(k,j,i) * exner(k) )**4
3150                   ENDIF
3151
3152!
3153!--                Weighted average according to surface fraction.
3154                   surf%rad_lw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
3155                                          surf%emissivity(ind_veg_wall,m)      &
3156                                        + surf%frac(ind_pav_green,m) *         &
3157                                          surf%emissivity(ind_pav_green,m)     &
3158                                        + surf%frac(ind_wat_win,m)   *         &
3159                                          surf%emissivity(ind_wat_win,m)       &
3160                                        )                                      &
3161                                      * sigma_sb                               &
3162                                      * ( surf%pt_surface(m) * exner(nzb) )**4
3163
3164                   surf%rad_sw_in(m) = ( surf%rad_net(m) - surf%rad_lw_in(m)   &
3165                                       + surf%rad_lw_out(m) )                  &
3166                                       / ( 1.0_wp -                            &
3167                                          ( surf%frac(ind_veg_wall,m)  *       &
3168                                            surf%albedo(ind_veg_wall,m)        &
3169                                         +  surf%frac(ind_pav_green,m) *       &
3170                                            surf%albedo(ind_pav_green,m)       &
3171                                         +  surf%frac(ind_wat_win,m)   *       &
3172                                            surf%albedo(ind_wat_win,m) )       &
3173                                         )
3174
3175                   surf%rad_sw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
3176                                          surf%albedo(ind_veg_wall,m)          &
3177                                        + surf%frac(ind_pav_green,m) *         &
3178                                          surf%albedo(ind_pav_green,m)         &
3179                                        + surf%frac(ind_wat_win,m)   *         &
3180                                          surf%albedo(ind_wat_win,m) )         &
3181                                      * surf%rad_sw_in(m)
3182
3183                ENDDO
3184
3185             ENDIF
3186
3187!
3188!--          Fill out values in radiation arrays
3189             DO  m = 1, surf%ns
3190                i = surf%i(m)
3191                j = surf%j(m)
3192                rad_sw_in(0,j,i) = surf%rad_sw_in(m)
3193                rad_sw_out(0,j,i) = surf%rad_sw_out(m)
3194                rad_lw_in(0,j,i) = surf%rad_lw_in(m)
3195                rad_lw_out(0,j,i) = surf%rad_lw_out(m)
3196             ENDDO
3197
3198          END SUBROUTINE radiation_constant_surf
3199         
3200
3201    END SUBROUTINE radiation_constant
3202
3203!------------------------------------------------------------------------------!
3204! Description:
3205! ------------
3206!> Header output for radiation model
3207!------------------------------------------------------------------------------!
3208    SUBROUTINE radiation_header ( io )
3209
3210
3211       IMPLICIT NONE
3212 
3213       INTEGER(iwp), INTENT(IN) ::  io            !< Unit of the output file
3214   
3215
3216       
3217!
3218!--    Write radiation model header
3219       WRITE( io, 3 )
3220
3221       IF ( radiation_scheme == "constant" )  THEN
3222          WRITE( io, 4 ) net_radiation
3223       ELSEIF ( radiation_scheme == "clear-sky" )  THEN
3224          WRITE( io, 5 )
3225       ELSEIF ( radiation_scheme == "rrtmg" )  THEN
3226          WRITE( io, 6 )
3227          IF ( .NOT. lw_radiation )  WRITE( io, 10 )
3228          IF ( .NOT. sw_radiation )  WRITE( io, 11 )
3229       ENDIF
3230
3231       IF ( albedo_type_f%from_file  .OR.  vegetation_type_f%from_file  .OR.   &
3232            pavement_type_f%from_file  .OR.  water_type_f%from_file  .OR.      &
3233            building_type_f%from_file )  THEN
3234             WRITE( io, 13 )
3235       ELSE 
3236          IF ( albedo_type == 0 )  THEN
3237             WRITE( io, 7 ) albedo
3238          ELSE
3239             WRITE( io, 8 ) TRIM( albedo_type_name(albedo_type) )
3240          ENDIF
3241       ENDIF
3242       IF ( constant_albedo )  THEN
3243          WRITE( io, 9 )
3244       ENDIF
3245       
3246       WRITE( io, 12 ) dt_radiation
3247 
3248
3249 3 FORMAT (//' Radiation model information:'/                                  &
3250              ' ----------------------------'/)
3251 4 FORMAT ('    --> Using constant net radiation: net_radiation = ', F6.2,     &
3252           // 'W/m**2')
3253 5 FORMAT ('    --> Simple radiation scheme for clear sky is used (no clouds,',&
3254                   ' default)')
3255 6 FORMAT ('    --> RRTMG scheme is used')
3256 7 FORMAT (/'    User-specific surface albedo: albedo =', F6.3)
3257 8 FORMAT (/'    Albedo is set for land surface type: ', A)
3258 9 FORMAT (/'    --> Albedo is fixed during the run')
325910 FORMAT (/'    --> Longwave radiation is disabled')
326011 FORMAT (/'    --> Shortwave radiation is disabled.')
326112 FORMAT  ('    Timestep: dt_radiation = ', F6.2, '  s')
326213 FORMAT (/'    Albedo is set individually for each xy-location, according ', &
3263                 'to given surface type.')
3264
3265
3266    END SUBROUTINE radiation_header
3267   
3268
3269!------------------------------------------------------------------------------!
3270! Description:
3271! ------------
3272!> Parin for &radiation_parameters for radiation model
3273!------------------------------------------------------------------------------!
3274    SUBROUTINE radiation_parin
3275
3276
3277       IMPLICIT NONE
3278
3279       CHARACTER (LEN=80) ::  line  !< dummy string that contains the current line of the parameter file
3280       
3281       NAMELIST /radiation_par/   albedo, albedo_lw_dif, albedo_lw_dir,         &
3282                                  albedo_sw_dif, albedo_sw_dir, albedo_type,    &
3283                                  constant_albedo, dt_radiation, emissivity,    &
3284                                  lw_radiation, max_raytracing_dist,            &
3285                                  min_irrf_value, mrt_geom_human,               &
3286                                  mrt_include_sw, mrt_nlevels,                  &
3287                                  mrt_skip_roof, net_radiation, nrefsteps,      &
3288                                  plant_lw_interact, rad_angular_discretization,&
3289                                  radiation_interactions_on, radiation_scheme,  &
3290                                  raytrace_discrete_azims,                      &
3291                                  raytrace_discrete_elevs, raytrace_mpi_rma,    &
3292                                  skip_time_do_radiation, surface_reflections,  &
3293                                  svfnorm_report_thresh, sw_radiation,          &
3294                                  unscheduled_radiation_calls
3295
3296   
3297       NAMELIST /radiation_parameters/ albedo, albedo_lw_dif, albedo_lw_dir,    &
3298                                  albedo_sw_dif, albedo_sw_dir, albedo_type,    &
3299                                  constant_albedo, dt_radiation, emissivity,    &
3300                                  lw_radiation, max_raytracing_dist,            &
3301                                  min_irrf_value, mrt_geom_human,               &
3302                                  mrt_include_sw, mrt_nlevels,                  &
3303                                  mrt_skip_roof, net_radiation, nrefsteps,      &
3304                                  plant_lw_interact, rad_angular_discretization,&
3305                                  radiation_interactions_on, radiation_scheme,  &
3306                                  raytrace_discrete_azims,                      &
3307                                  raytrace_discrete_elevs, raytrace_mpi_rma,    &
3308                                  skip_time_do_radiation, surface_reflections,  &
3309                                  svfnorm_report_thresh, sw_radiation,          &
3310                                  unscheduled_radiation_calls
3311   
3312       line = ' '
3313       
3314!
3315!--    Try to find radiation model namelist
3316       REWIND ( 11 )
3317       line = ' '
3318       DO WHILE ( INDEX( line, '&radiation_parameters' ) == 0 )
3319          READ ( 11, '(A)', END=12 )  line
3320       ENDDO
3321       BACKSPACE ( 11 )
3322
3323!
3324!--    Read user-defined namelist
3325       READ ( 11, radiation_parameters, ERR = 10 )
3326
3327!
3328!--    Set flag that indicates that the radiation model is switched on
3329       radiation = .TRUE.
3330
3331       GOTO 14
3332
3333 10    BACKSPACE( 11 )
3334       READ( 11 , '(A)') line
3335       CALL parin_fail_message( 'radiation_parameters', line )
3336!
3337!--    Try to find old namelist
3338 12    REWIND ( 11 )
3339       line = ' '
3340       DO WHILE ( INDEX( line, '&radiation_par' ) == 0 )
3341          READ ( 11, '(A)', END=14 )  line
3342       ENDDO
3343       BACKSPACE ( 11 )
3344
3345!
3346!--    Read user-defined namelist
3347       READ ( 11, radiation_par, ERR = 13, END = 14 )
3348
3349       message_string = 'namelist radiation_par is deprecated and will be ' // &
3350                     'removed in near future. Please use namelist ' //         &
3351                     'radiation_parameters instead'
3352       CALL message( 'radiation_parin', 'PA0487', 0, 1, 0, 6, 0 )
3353
3354!
3355!--    Set flag that indicates that the radiation model is switched on
3356       radiation = .TRUE.
3357
3358       IF ( .NOT.  radiation_interactions_on  .AND.  surface_reflections )  THEN
3359          message_string = 'surface_reflections is allowed only when '      // &
3360               'radiation_interactions_on is set to TRUE'
3361          CALL message( 'radiation_parin', 'PA0293',1, 2, 0, 6, 0 )
3362       ENDIF
3363
3364       GOTO 14
3365
3366 13    BACKSPACE( 11 )
3367       READ( 11 , '(A)') line
3368       CALL parin_fail_message( 'radiation_par', line )
3369
3370 14    CONTINUE
3371       
3372    END SUBROUTINE radiation_parin
3373
3374
3375!------------------------------------------------------------------------------!
3376! Description:
3377! ------------
3378!> Implementation of the RRTMG radiation_scheme
3379!------------------------------------------------------------------------------!
3380    SUBROUTINE radiation_rrtmg
3381
3382#if defined ( __rrtmg )
3383       USE indices,                                                            &
3384           ONLY:  nbgp
3385
3386       USE particle_attributes,                                                &
3387           ONLY:  grid_particles, number_of_particles, particles, prt_count
3388
3389       IMPLICIT NONE
3390
3391
3392       INTEGER(iwp) ::  i, j, k, l, m, n !< loop indices
3393       INTEGER(iwp) ::  k_topo     !< topography top index
3394
3395       REAL(wp)     ::  nc_rad, &    !< number concentration of cloud droplets
3396                        s_r2,   &    !< weighted sum over all droplets with r^2
3397                        s_r3         !< weighted sum over all droplets with r^3
3398
3399       REAL(wp), DIMENSION(0:nzt+1) :: pt_av, q_av, ql_av
3400       REAL(wp), DIMENSION(0:0)     :: zenith   !< to provide indexed array
3401!
3402!--    Just dummy arguments
3403       REAL(wp), DIMENSION(:,:,:), ALLOCATABLE :: rrtm_lw_taucld_dum,          &
3404                                                  rrtm_lw_tauaer_dum,          &
3405                                                  rrtm_sw_taucld_dum,          &
3406                                                  rrtm_sw_ssacld_dum,          &
3407                                                  rrtm_sw_asmcld_dum,          &
3408                                                  rrtm_sw_fsfcld_dum,          &
3409                                                  rrtm_sw_tauaer_dum,          &
3410                                                  rrtm_sw_ssaaer_dum,          &
3411                                                  rrtm_sw_asmaer_dum,          &
3412                                                  rrtm_sw_ecaer_dum
3413
3414!
3415!--    Calculate current (cosine of) zenith angle and whether the sun is up
3416       CALL calc_zenith     
3417       zenith(0) = cos_zenith
3418!
3419!--    Calculate surface albedo. In case average radiation is applied,
3420!--    this is not required.
3421#if defined( __netcdf )
3422       IF ( .NOT. constant_albedo )  THEN
3423!
3424!--       Horizontally aligned default, natural and urban surfaces
3425          CALL calc_albedo( surf_lsm_h    )
3426          CALL calc_albedo( surf_usm_h    )
3427!
3428!--       Vertically aligned default, natural and urban surfaces
3429          DO  l = 0, 3
3430             CALL calc_albedo( surf_lsm_v(l) )
3431             CALL calc_albedo( surf_usm_v(l) )
3432          ENDDO
3433       ENDIF
3434#endif
3435
3436!
3437!--    Prepare input data for RRTMG
3438
3439!
3440!--    In case of large scale forcing with surface data, calculate new pressure
3441!--    profile. nzt_rad might be modified by these calls and all required arrays
3442!--    will then be re-allocated
3443       IF ( large_scale_forcing  .AND.  lsf_surf )  THEN
3444          CALL read_sounding_data
3445          CALL read_trace_gas_data
3446       ENDIF
3447
3448
3449       IF ( average_radiation ) THEN
3450
3451          rrtm_asdir(1)  = albedo_urb
3452          rrtm_asdif(1)  = albedo_urb
3453          rrtm_aldir(1)  = albedo_urb
3454          rrtm_aldif(1)  = albedo_urb
3455
3456          rrtm_emis = emissivity_urb
3457!
3458!--       Calculate mean pt profile. Actually, only one height level is required.
3459          CALL calc_mean_profile( pt, 4 )
3460          pt_av = hom(:, 1, 4, 0)
3461         
3462          IF ( humidity )  THEN
3463             CALL calc_mean_profile( q, 41 )
3464             q_av  = hom(:, 1, 41, 0)
3465          ENDIF
3466!
3467!--       Prepare profiles of temperature and H2O volume mixing ratio
3468          rrtm_tlev(0,nzb+1) = t_rad_urb
3469
3470          IF ( bulk_cloud_model )  THEN
3471
3472             CALL calc_mean_profile( ql, 54 )
3473             ! average ql is now in hom(:, 1, 54, 0)
3474             ql_av = hom(:, 1, 54, 0)
3475             
3476             DO k = nzb+1, nzt+1
3477                rrtm_tlay(0,k) = pt_av(k) * ( (hyp(k) ) / 100000._wp       &
3478                                 )**.286_wp + lv_d_cp * ql_av(k)
3479                rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * (q_av(k) - ql_av(k))
3480             ENDDO
3481          ELSE
3482             DO k = nzb+1, nzt+1
3483                rrtm_tlay(0,k) = pt_av(k) * ( (hyp(k) ) / 100000._wp       &
3484                                 )**.286_wp
3485             ENDDO
3486
3487             IF ( humidity )  THEN
3488                DO k = nzb+1, nzt+1
3489                   rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * q_av(k)
3490                ENDDO
3491             ELSE
3492                rrtm_h2ovmr(0,nzb+1:nzt+1) = 0.0_wp
3493             ENDIF
3494          ENDIF
3495
3496!
3497!--       Avoid temperature/humidity jumps at the top of the PALM domain by
3498!--       linear interpolation from nzt+2 to nzt+7. Jumps are induced by
3499!--       discrepancies between the values in the  domain and those above that
3500!--       are prescribed in RRTMG
3501          DO k = nzt+2, nzt+7
3502             rrtm_tlay(0,k) = rrtm_tlay(0,nzt+1)                            &
3503                           + ( rrtm_tlay(0,nzt+8) - rrtm_tlay(0,nzt+1) )    &
3504                           / ( rrtm_play(0,nzt+8) - rrtm_play(0,nzt+1) )    &
3505                           * ( rrtm_play(0,k) - rrtm_play(0,nzt+1) )
3506
3507             rrtm_h2ovmr(0,k) = rrtm_h2ovmr(0,nzt+1)                        &
3508                           + ( rrtm_h2ovmr(0,nzt+8) - rrtm_h2ovmr(0,nzt+1) )&
3509                           / ( rrtm_play(0,nzt+8)   - rrtm_play(0,nzt+1)   )&
3510                           * ( rrtm_play(0,k) - rrtm_play(0,nzt+1) )
3511
3512          ENDDO
3513
3514!--       Linear interpolate to zw grid. Loop reaches one level further up
3515!--       due to the staggered grid in RRTMG
3516          DO k = nzb+2, nzt+8
3517             rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k) -        &
3518                                rrtm_tlay(0,k-1))                           &
3519                                / ( rrtm_play(0,k) - rrtm_play(0,k-1) )     &
3520                                * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
3521          ENDDO
3522
3523
3524!
3525!--       Calculate liquid water path and cloud fraction for each column.
3526!--       Note that LWP is required in g/m2 instead of kg/kg m.
3527          rrtm_cldfr  = 0.0_wp
3528          rrtm_reliq  = 0.0_wp
3529          rrtm_cliqwp = 0.0_wp
3530          rrtm_icld   = 0
3531
3532          IF ( bulk_cloud_model )  THEN
3533             DO k = nzb+1, nzt+1
3534                rrtm_cliqwp(0,k) =  ql_av(k) * 1000._wp *                   &
3535                                    (rrtm_plev(0,k) - rrtm_plev(0,k+1))     &
3536                                    * 100._wp / g 
3537
3538                IF ( rrtm_cliqwp(0,k) > 0._wp )  THEN
3539                   rrtm_cldfr(0,k) = 1._wp
3540                   IF ( rrtm_icld == 0 )  rrtm_icld = 1
3541
3542!
3543!--                Calculate cloud droplet effective radius
3544                   rrtm_reliq(0,k) = 1.0E6_wp * ( 3.0_wp * ql_av(k)         &
3545                                     * rho_surface                          &
3546                                     / ( 4.0_wp * pi * nc_const * rho_l )   &
3547                                     )**0.33333333333333_wp                 &
3548                                     * EXP( LOG( sigma_gc )**2 )
3549!
3550!--                Limit effective radius
3551                   IF ( rrtm_reliq(0,k) > 0.0_wp )  THEN
3552                      rrtm_reliq(0,k) = MAX(rrtm_reliq(0,k),2.5_wp)
3553                      rrtm_reliq(0,k) = MIN(rrtm_reliq(0,k),60.0_wp)
3554                   ENDIF
3555                ENDIF
3556             ENDDO
3557          ENDIF
3558
3559!
3560!--       Set surface temperature
3561          rrtm_tsfc = t_rad_urb
3562         
3563          IF ( lw_radiation )  THEN       
3564         
3565             CALL rrtmg_lw( 1, nzt_rad      , rrtm_icld    , rrtm_idrv      ,&
3566             rrtm_play       , rrtm_plev    , rrtm_tlay    , rrtm_tlev      ,&
3567             rrtm_tsfc       , rrtm_h2ovmr  , rrtm_o3vmr   , rrtm_co2vmr    ,&
3568             rrtm_ch4vmr     , rrtm_n2ovmr  , rrtm_o2vmr   , rrtm_cfc11vmr  ,&
3569             rrtm_cfc12vmr   , rrtm_cfc22vmr, rrtm_ccl4vmr , rrtm_emis      ,&
3570             rrtm_inflglw    , rrtm_iceflglw, rrtm_liqflglw, rrtm_cldfr     ,&
3571             rrtm_lw_taucld  , rrtm_cicewp  , rrtm_cliqwp  , rrtm_reice     ,& 
3572             rrtm_reliq      , rrtm_lw_tauaer,                               &
3573             rrtm_lwuflx     , rrtm_lwdflx  , rrtm_lwhr  ,                   &
3574             rrtm_lwuflxc    , rrtm_lwdflxc , rrtm_lwhrc ,                   &
3575             rrtm_lwuflx_dt  ,  rrtm_lwuflxc_dt )
3576
3577!
3578!--          Save fluxes
3579             DO k = nzb, nzt+1
3580                rad_lw_in(k,:,:)  = rrtm_lwdflx(0,k)
3581                rad_lw_out(k,:,:) = rrtm_lwuflx(0,k)
3582             ENDDO
3583             rad_lw_in_diff(:,:) = rad_lw_in(0,:,:)
3584!
3585!--          Save heating rates (convert from K/d to K/h).
3586!--          Further, even though an aggregated radiation is computed, map
3587!--          signle-column profiles on top of any topography, in order to
3588!--          obtain correct near surface radiation heating/cooling rates.
3589             DO  i = nxl, nxr
3590                DO  j = nys, nyn
3591                   k_topo = get_topography_top_index_ji( j, i, 's' )
3592                   DO k = k_topo+1, nzt+1
3593                      rad_lw_hr(k,j,i)     = rrtm_lwhr(0,k-k_topo)  * d_hours_day
3594                      rad_lw_cs_hr(k,j,i)  = rrtm_lwhrc(0,k-k_topo) * d_hours_day
3595                   ENDDO
3596                ENDDO
3597             ENDDO
3598
3599          ENDIF
3600
3601          IF ( sw_radiation .AND. sun_up )  THEN
3602             CALL rrtmg_sw( 1, nzt_rad      , rrtm_icld     , rrtm_iaer      ,&
3603             rrtm_play      , rrtm_plev     , rrtm_tlay     , rrtm_tlev      ,&
3604             rrtm_tsfc      , rrtm_h2ovmr   , rrtm_o3vmr    , rrtm_co2vmr    ,&
3605             rrtm_ch4vmr    , rrtm_n2ovmr   , rrtm_o2vmr    , rrtm_asdir     ,&
3606             rrtm_asdif     , rrtm_aldir    , rrtm_aldif    , zenith         ,&
3607             0.0_wp         , day_of_year   , solar_constant, rrtm_inflgsw   ,&
3608             rrtm_iceflgsw  , rrtm_liqflgsw , rrtm_cldfr    , rrtm_sw_taucld ,&
3609             rrtm_sw_ssacld , rrtm_sw_asmcld, rrtm_sw_fsfcld, rrtm_cicewp    ,&
3610             rrtm_cliqwp    , rrtm_reice    , rrtm_reliq    , rrtm_sw_tauaer ,&
3611             rrtm_sw_ssaaer , rrtm_sw_asmaer, rrtm_sw_ecaer , rrtm_swuflx    ,&
3612             rrtm_swdflx    , rrtm_swhr     , rrtm_swuflxc  , rrtm_swdflxc   ,&
3613             rrtm_swhrc     , rrtm_dirdflux , rrtm_difdflux )
3614 
3615!
3616!--          Save fluxes:
3617!--          - whole domain
3618             DO k = nzb, nzt+1
3619                rad_sw_in(k,:,:)  = rrtm_swdflx(0,k)
3620                rad_sw_out(k,:,:) = rrtm_swuflx(0,k)
3621             ENDDO
3622!--          - direct and diffuse SW at urban-surface-layer (required by RTM)
3623             rad_sw_in_dir(:,:) = rrtm_dirdflux(0,nzb)
3624             rad_sw_in_diff(:,:) = rrtm_difdflux(0,nzb)
3625
3626!
3627!--          Save heating rates (convert from K/d to K/s)
3628             DO k = nzb+1, nzt+1
3629                rad_sw_hr(k,:,:)     = rrtm_swhr(0,k)  * d_hours_day
3630                rad_sw_cs_hr(k,:,:)  = rrtm_swhrc(0,k) * d_hours_day
3631             ENDDO
3632!
3633!--       Solar radiation is zero during night
3634          ELSE
3635             rad_sw_in  = 0.0_wp
3636             rad_sw_out = 0.0_wp
3637             rad_sw_in_dir(:,:) = 0.0_wp
3638             rad_sw_in_diff(:,:) = 0.0_wp
3639          ENDIF
3640!
3641!--    RRTMG is called for each (j,i) grid point separately, starting at the
3642!--    highest topography level. Here no RTM is used since average_radiation is false
3643       ELSE
3644!
3645!--       Loop over all grid points
3646          DO i = nxl, nxr
3647             DO j = nys, nyn
3648
3649!
3650!--             Prepare profiles of temperature and H2O volume mixing ratio
3651                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
3652                   rrtm_tlev(0,nzb+1) = surf_lsm_h%pt_surface(m) * exner(nzb)
3653                ENDDO
3654                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
3655                   rrtm_tlev(0,nzb+1) = surf_usm_h%pt_surface(m) * exner(nzb)
3656                ENDDO
3657
3658
3659                IF ( bulk_cloud_model )  THEN
3660                   DO k = nzb+1, nzt+1
3661                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)                    &
3662                                        + lv_d_cp * ql(k,j,i)
3663                      rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * (q(k,j,i) - ql(k,j,i))
3664                   ENDDO
3665                ELSEIF ( cloud_droplets )  THEN
3666                   DO k = nzb+1, nzt+1
3667                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)                     &
3668                                        + lv_d_cp * ql(k,j,i)
3669                      rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * q(k,j,i) 
3670                   ENDDO
3671                ELSE
3672                   DO k = nzb+1, nzt+1
3673                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)
3674                   ENDDO
3675
3676                   IF ( humidity )  THEN
3677                      DO k = nzb+1, nzt+1
3678                         rrtm_h2ovmr(0,k) =  mol_mass_air_d_wv * q(k,j,i)
3679                      ENDDO   
3680                   ELSE
3681                      rrtm_h2ovmr(0,nzb+1:nzt+1) = 0.0_wp
3682                   ENDIF
3683                ENDIF
3684
3685!
3686!--             Avoid temperature/humidity jumps at the top of the LES domain by
3687!--             linear interpolation from nzt+2 to nzt+7
3688                DO k = nzt+2, nzt+7
3689                   rrtm_tlay(0,k) = rrtm_tlay(0,nzt+1)                         &
3690                                 + ( rrtm_tlay(0,nzt+8) - rrtm_tlay(0,nzt+1) ) &
3691                                 / ( rrtm_play(0,nzt+8) - rrtm_play(0,nzt+1) ) &
3692                                 * ( rrtm_play(0,k)     - rrtm_play(0,nzt+1) )
3693
3694                   rrtm_h2ovmr(0,k) = rrtm_h2ovmr(0,nzt+1)                     &
3695                              + ( rrtm_h2ovmr(0,nzt+8) - rrtm_h2ovmr(0,nzt+1) )&
3696                              / ( rrtm_play(0,nzt+8)   - rrtm_play(0,nzt+1)   )&
3697                              * ( rrtm_play(0,k)       - rrtm_play(0,nzt+1) )
3698
3699                ENDDO
3700
3701!--             Linear interpolate to zw grid
3702                DO k = nzb+2, nzt+8
3703                   rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k) -     &
3704                                      rrtm_tlay(0,k-1))                        &
3705                                      / ( rrtm_play(0,k) - rrtm_play(0,k-1) )  &
3706                                      * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
3707                ENDDO
3708
3709
3710!
3711!--             Calculate liquid water path and cloud fraction for each column.
3712!--             Note that LWP is required in g/m2 instead of kg/kg m.
3713                rrtm_cldfr  = 0.0_wp
3714                rrtm_reliq  = 0.0_wp
3715                rrtm_cliqwp = 0.0_wp
3716                rrtm_icld   = 0
3717
3718                IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
3719                   DO k = nzb+1, nzt+1
3720                      rrtm_cliqwp(0,k) =  ql(k,j,i) * 1000.0_wp *              &
3721                                          (rrtm_plev(0,k) - rrtm_plev(0,k+1))  &
3722                                          * 100.0_wp / g 
3723
3724                      IF ( rrtm_cliqwp(0,k) > 0.0_wp )  THEN
3725                         rrtm_cldfr(0,k) = 1.0_wp
3726                         IF ( rrtm_icld == 0 )  rrtm_icld = 1
3727
3728!
3729!--                      Calculate cloud droplet effective radius
3730                         IF ( bulk_cloud_model )  THEN
3731!
3732!--                         Calculete effective droplet radius. In case of using
3733!--                         cloud_scheme = 'morrison' and a non reasonable number
3734!--                         of cloud droplets the inital aerosol number 
3735!--                         concentration is considered.
3736                            IF ( microphysics_morrison )  THEN
3737                               IF ( nc(k,j,i) > 1.0E-20_wp )  THEN
3738                                  nc_rad = nc(k,j,i)
3739                               ELSE
3740                                  nc_rad = na_init
3741                               ENDIF
3742                            ELSE
3743                               nc_rad = nc_const
3744                            ENDIF 
3745
3746                            rrtm_reliq(0,k) = 1.0E6_wp * ( 3.0_wp * ql(k,j,i)     &
3747                                              * rho_surface                       &
3748                                              / ( 4.0_wp * pi * nc_rad * rho_l )  &
3749                                              )**0.33333333333333_wp              &
3750                                              * EXP( LOG( sigma_gc )**2 )
3751
3752                         ELSEIF ( cloud_droplets )  THEN
3753                            number_of_particles = prt_count(k,j,i)
3754
3755                            IF (number_of_particles <= 0)  CYCLE
3756                            particles => grid_particles(k,j,i)%particles(1:number_of_particles)
3757                            s_r2 = 0.0_wp
3758                            s_r3 = 0.0_wp
3759
3760                            DO  n = 1, number_of_particles
3761                               IF ( particles(n)%particle_mask )  THEN
3762                                  s_r2 = s_r2 + particles(n)%radius**2 *       &
3763                                         particles(n)%weight_factor
3764                                  s_r3 = s_r3 + particles(n)%radius**3 *       &
3765                                         particles(n)%weight_factor
3766                               ENDIF
3767                            ENDDO
3768
3769                            IF ( s_r2 > 0.0_wp )  rrtm_reliq(0,k) = s_r3 / s_r2
3770
3771                         ENDIF
3772
3773!
3774!--                      Limit effective radius
3775                         IF ( rrtm_reliq(0,k) > 0.0_wp )  THEN
3776                            rrtm_reliq(0,k) = MAX(rrtm_reliq(0,k),2.5_wp)
3777                            rrtm_reliq(0,k) = MIN(rrtm_reliq(0,k),60.0_wp)
3778                        ENDIF
3779                      ENDIF
3780                   ENDDO
3781                ENDIF
3782
3783!
3784!--             Write surface emissivity and surface temperature at current
3785!--             surface element on RRTMG-shaped array.
3786!--             Please note, as RRTMG is a single column model, surface attributes
3787!--             are only obtained from horizontally aligned surfaces (for
3788!--             simplicity). Taking surface attributes from horizontal and
3789!--             vertical walls would lead to multiple solutions. 
3790!--             Moreover, for natural- and urban-type surfaces, several surface
3791!--             classes can exist at a surface element next to each other.
3792!--             To obtain bulk parameters, apply a weighted average for these
3793!--             surfaces.
3794                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
3795                   rrtm_emis = surf_lsm_h%frac(ind_veg_wall,m)  *              &
3796                               surf_lsm_h%emissivity(ind_veg_wall,m)  +        &
3797                               surf_lsm_h%frac(ind_pav_green,m) *              &
3798                               surf_lsm_h%emissivity(ind_pav_green,m) +        & 
3799                               surf_lsm_h%frac(ind_wat_win,m)   *              &
3800                               surf_lsm_h%emissivity(ind_wat_win,m)
3801                   rrtm_tsfc = surf_lsm_h%pt_surface(m) * exner(nzb)
3802                ENDDO             
3803                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
3804                   rrtm_emis = surf_usm_h%frac(ind_veg_wall,m)  *              &
3805                               surf_usm_h%emissivity(ind_veg_wall,m)  +        &
3806                               surf_usm_h%frac(ind_pav_green,m) *              &
3807                               surf_usm_h%emissivity(ind_pav_green,m) +        & 
3808                               surf_usm_h%frac(ind_wat_win,m)   *              &
3809                               surf_usm_h%emissivity(ind_wat_win,m)
3810                   rrtm_tsfc = surf_usm_h%pt_surface(m) * exner(nzb)
3811                ENDDO
3812!
3813!--             Obtain topography top index (lower bound of RRTMG)
3814                k_topo = get_topography_top_index_ji( j, i, 's' )
3815
3816                IF ( lw_radiation )  THEN
3817!
3818!--                Due to technical reasons, copy optical depth to dummy arguments
3819!--                which are allocated on the exact size as the rrtmg_lw is called.
3820!--                As one dimesion is allocated with zero size, compiler complains
3821!--                that rank of the array does not match that of the
3822!--                assumed-shaped arguments in the RRTMG library. In order to
3823!--                avoid this, write to dummy arguments and give pass the entire
3824!--                dummy array. Seems to be the only existing work-around. 
3825                   ALLOCATE( rrtm_lw_taucld_dum(1:nbndlw+1,0:0,k_topo+1:nzt_rad+1) )
3826                   ALLOCATE( rrtm_lw_tauaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndlw+1) )
3827
3828                   rrtm_lw_taucld_dum =                                        &
3829                               rrtm_lw_taucld(1:nbndlw+1,0:0,k_topo+1:nzt_rad+1)
3830                   rrtm_lw_tauaer_dum =                                        &
3831                               rrtm_lw_tauaer(0:0,k_topo+1:nzt_rad+1,1:nbndlw+1)
3832
3833                   CALL rrtmg_lw( 1,                                           &                                       
3834                                  nzt_rad-k_topo,                              &
3835                                  rrtm_icld,                                   &
3836                                  rrtm_idrv,                                   &
3837                                  rrtm_play(:,k_topo+1:nzt_rad+1),             &
3838                                  rrtm_plev(:,k_topo+1:nzt_rad+2),             &
3839                                  rrtm_tlay(:,k_topo+1:nzt_rad+1),             &
3840                                  rrtm_tlev(:,k_topo+1:nzt_rad+2),             &
3841                                  rrtm_tsfc,                                   &
3842                                  rrtm_h2ovmr(:,k_topo+1:nzt_rad+1),           &
3843                                  rrtm_o3vmr(:,k_topo+1:nzt_rad+1),            &
3844                                  rrtm_co2vmr(:,k_topo+1:nzt_rad+1),           &
3845                                  rrtm_ch4vmr(:,k_topo+1:nzt_rad+1),           &
3846                                  rrtm_n2ovmr(:,k_topo+1:nzt_rad+1),           &
3847                                  rrtm_o2vmr(:,k_topo+1:nzt_rad+1),            &
3848                                  rrtm_cfc11vmr(:,k_topo+1:nzt_rad+1),         &
3849                                  rrtm_cfc12vmr(:,k_topo+1:nzt_rad+1),         &
3850                                  rrtm_cfc22vmr(:,k_topo+1:nzt_rad+1),         &
3851                                  rrtm_ccl4vmr(:,k_topo+1:nzt_rad+1),          &
3852                                  rrtm_emis,                                   &
3853                                  rrtm_inflglw,                                &
3854                                  rrtm_iceflglw,                               &
3855                                  rrtm_liqflglw,                               &
3856                                  rrtm_cldfr(:,k_topo+1:nzt_rad+1),            &
3857                                  rrtm_lw_taucld_dum,                          &
3858                                  rrtm_cicewp(:,k_topo+1:nzt_rad+1),           &
3859                                  rrtm_cliqwp(:,k_topo+1:nzt_rad+1),           &
3860                                  rrtm_reice(:,k_topo+1:nzt_rad+1),            & 
3861                                  rrtm_reliq(:,k_topo+1:nzt_rad+1),            &
3862                                  rrtm_lw_tauaer_dum,                          &
3863                                  rrtm_lwuflx(:,k_topo:nzt_rad+1),             &
3864                                  rrtm_lwdflx(:,k_topo:nzt_rad+1),             &
3865                                  rrtm_lwhr(:,k_topo+1:nzt_rad+1),             &
3866                                  rrtm_lwuflxc(:,k_topo:nzt_rad+1),            &
3867                                  rrtm_lwdflxc(:,k_topo:nzt_rad+1),            &
3868                                  rrtm_lwhrc(:,k_topo+1:nzt_rad+1),            &
3869                                  rrtm_lwuflx_dt(:,k_topo:nzt_rad+1),          &
3870                                  rrtm_lwuflxc_dt(:,k_topo:nzt_rad+1) )
3871
3872                   DEALLOCATE ( rrtm_lw_taucld_dum )
3873                   DEALLOCATE ( rrtm_lw_tauaer_dum )
3874!
3875!--                Save fluxes
3876                   DO k = k_topo, nzt+1
3877                      rad_lw_in(k,j,i)  = rrtm_lwdflx(0,k)
3878                      rad_lw_out(k,j,i) = rrtm_lwuflx(0,k)
3879                   ENDDO
3880
3881!
3882!--                Save heating rates (convert from K/d to K/h)
3883                   DO k = k_topo+1, nzt+1
3884                      rad_lw_hr(k,j,i)     = rrtm_lwhr(0,k-k_topo)  * d_hours_day
3885                      rad_lw_cs_hr(k,j,i)  = rrtm_lwhrc(0,k-k_topo) * d_hours_day
3886                   ENDDO
3887
3888!
3889!--                Save surface radiative fluxes and change in LW heating rate
3890!--                onto respective surface elements
3891!--                Horizontal surfaces
3892                   DO  m = surf_lsm_h%start_index(j,i),                        &
3893                           surf_lsm_h%end_index(j,i)
3894                      surf_lsm_h%rad_lw_in(m)           = rrtm_lwdflx(0,k_topo)
3895                      surf_lsm_h%rad_lw_out(m)          = rrtm_lwuflx(0,k_topo)
3896                      surf_lsm_h%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k_topo)
3897                   ENDDO             
3898                   DO  m = surf_usm_h%start_index(j,i),                        &
3899                           surf_usm_h%end_index(j,i)
3900                      surf_usm_h%rad_lw_in(m)           = rrtm_lwdflx(0,k_topo)
3901                      surf_usm_h%rad_lw_out(m)          = rrtm_lwuflx(0,k_topo)
3902                      surf_usm_h%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k_topo)
3903                   ENDDO 
3904!
3905!--                Vertical surfaces. Fluxes are obtain at vertical level of the
3906!--                respective surface element
3907                   DO  l = 0, 3
3908                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
3909                              surf_lsm_v(l)%end_index(j,i)
3910                         k                                    = surf_lsm_v(l)%k(m)
3911                         surf_lsm_v(l)%rad_lw_in(m)           = rrtm_lwdflx(0,k)
3912                         surf_lsm_v(l)%rad_lw_out(m)          = rrtm_lwuflx(0,k)
3913                         surf_lsm_v(l)%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k)
3914                      ENDDO             
3915                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
3916                              surf_usm_v(l)%end_index(j,i)
3917                         k                                    = surf_usm_v(l)%k(m)
3918                         surf_usm_v(l)%rad_lw_in(m)           = rrtm_lwdflx(0,k)
3919                         surf_usm_v(l)%rad_lw_out(m)          = rrtm_lwuflx(0,k)
3920                         surf_usm_v(l)%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k)
3921                      ENDDO 
3922                   ENDDO
3923
3924                ENDIF
3925
3926                IF ( sw_radiation .AND. sun_up )  THEN
3927!
3928!--                Get albedo for direct/diffusive long/shortwave radiation at
3929!--                current (y,x)-location from surface variables.
3930!--                Only obtain it from horizontal surfaces, as RRTMG is a single
3931!--                column model
3932!--                (Please note, only one loop will entered, controlled by
3933!--                start-end index.)
3934                   DO  m = surf_lsm_h%start_index(j,i),                        &
3935                           surf_lsm_h%end_index(j,i)
3936                      rrtm_asdir(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3937                                            surf_lsm_h%rrtm_asdir(:,m) )
3938                      rrtm_asdif(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3939                                            surf_lsm_h%rrtm_asdif(:,m) )
3940                      rrtm_aldir(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3941                                            surf_lsm_h%rrtm_aldir(:,m) )
3942                      rrtm_aldif(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3943                                            surf_lsm_h%rrtm_aldif(:,m) )
3944                   ENDDO             
3945                   DO  m = surf_usm_h%start_index(j,i),                        &
3946                           surf_usm_h%end_index(j,i)
3947                      rrtm_asdir(1)  = SUM( surf_usm_h%frac(:,m) *             &
3948                                            surf_usm_h%rrtm_asdir(:,m) )
3949                      rrtm_asdif(1)  = SUM( surf_usm_h%frac(:,m) *             &
3950                                            surf_usm_h%rrtm_asdif(:,m) )
3951                      rrtm_aldir(1)  = SUM( surf_usm_h%frac(:,m) *             &
3952                                            surf_usm_h%rrtm_aldir(:,m) )
3953                      rrtm_aldif(1)  = SUM( surf_usm_h%frac(:,m) *             &
3954                                            surf_usm_h%rrtm_aldif(:,m) )
3955                   ENDDO
3956!
3957!--                Due to technical reasons, copy optical depths and other
3958!--                to dummy arguments which are allocated on the exact size as the
3959!--                rrtmg_sw is called.
3960!--                As one dimesion is allocated with zero size, compiler complains
3961!--                that rank of the array does not match that of the
3962!--                assumed-shaped arguments in the RRTMG library. In order to
3963!--                avoid this, write to dummy arguments and give pass the entire
3964!--                dummy array. Seems to be the only existing work-around. 
3965                   ALLOCATE( rrtm_sw_taucld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3966                   ALLOCATE( rrtm_sw_ssacld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3967                   ALLOCATE( rrtm_sw_asmcld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3968                   ALLOCATE( rrtm_sw_fsfcld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3969                   ALLOCATE( rrtm_sw_tauaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3970                   ALLOCATE( rrtm_sw_ssaaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3971                   ALLOCATE( rrtm_sw_asmaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3972                   ALLOCATE( rrtm_sw_ecaer_dum(0:0,k_topo+1:nzt_rad+1,1:naerec+1)  )
3973     
3974                   rrtm_sw_taucld_dum = rrtm_sw_taucld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3975                   rrtm_sw_ssacld_dum = rrtm_sw_ssacld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3976                   rrtm_sw_asmcld_dum = rrtm_sw_asmcld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3977                   rrtm_sw_fsfcld_dum = rrtm_sw_fsfcld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3978                   rrtm_sw_tauaer_dum = rrtm_sw_tauaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3979                   rrtm_sw_ssaaer_dum = rrtm_sw_ssaaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3980                   rrtm_sw_asmaer_dum = rrtm_sw_asmaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3981                   rrtm_sw_ecaer_dum  = rrtm_sw_ecaer(0:0,k_topo+1:nzt_rad+1,1:naerec+1)
3982
3983                   CALL rrtmg_sw( 1,                                           &
3984                                  nzt_rad-k_topo,                              &
3985                                  rrtm_icld,                                   &
3986                                  rrtm_iaer,                                   &
3987                                  rrtm_play(:,k_topo+1:nzt_rad+1),             &
3988                                  rrtm_plev(:,k_topo+1:nzt_rad+2),             &
3989                                  rrtm_tlay(:,k_topo+1:nzt_rad+1),             &
3990                                  rrtm_tlev(:,k_topo+1:nzt_rad+2),             &
3991                                  rrtm_tsfc,                                   &
3992                                  rrtm_h2ovmr(:,k_topo+1:nzt_rad+1),           &                               
3993                                  rrtm_o3vmr(:,k_topo+1:nzt_rad+1),            &       
3994                                  rrtm_co2vmr(:,k_topo+1:nzt_rad+1),           &
3995                                  rrtm_ch4vmr(:,k_topo+1:nzt_rad+1),           &
3996                                  rrtm_n2ovmr(:,k_topo+1:nzt_rad+1),           &
3997                                  rrtm_o2vmr(:,k_topo+1:nzt_rad+1),            &
3998                                  rrtm_asdir,                                  & 
3999                                  rrtm_asdif,                                  &
4000                                  rrtm_aldir,                                  &
4001                                  rrtm_aldif,                                  &
4002                                  zenith,                                      &
4003                                  0.0_wp,                                      &
4004                                  day_of_year,                                 &
4005                                  solar_constant,                              &
4006                                  rrtm_inflgsw,                                &
4007                                  rrtm_iceflgsw,                               &
4008                                  rrtm_liqflgsw,                               &
4009                                  rrtm_cldfr(:,k_topo+1:nzt_rad+1),            &
4010                                  rrtm_sw_taucld_dum,                          &
4011                                  rrtm_sw_ssacld_dum,                          &
4012                                  rrtm_sw_asmcld_dum,                          &
4013                                  rrtm_sw_fsfcld_dum,                          &
4014                                  rrtm_cicewp(:,k_topo+1:nzt_rad+1),           &
4015                                  rrtm_cliqwp(:,k_topo+1:nzt_rad+1),           &
4016                                  rrtm_reice(:,k_topo+1:nzt_rad+1),            &
4017                                  rrtm_reliq(:,k_topo+1:nzt_rad+1),            &
4018                                  rrtm_sw_tauaer_dum,                          &
4019                                  rrtm_sw_ssaaer_dum,                          &
4020                                  rrtm_sw_asmaer_dum,                          &
4021                                  rrtm_sw_ecaer_dum,                           &
4022                                  rrtm_swuflx(:,k_topo:nzt_rad+1),             & 
4023                                  rrtm_swdflx(:,k_topo:nzt_rad+1),             & 
4024                                  rrtm_swhr(:,k_topo+1:nzt_rad+1),             & 
4025                                  rrtm_swuflxc(:,k_topo:nzt_rad+1),            & 
4026                                  rrtm_swdflxc(:,k_topo:nzt_rad+1),            &
4027                                  rrtm_swhrc(:,k_topo+1:nzt_rad+1),            &
4028                                  rrtm_dirdflux(:,k_topo:nzt_rad+1),           &
4029                                  rrtm_difdflux(:,k_topo:nzt_rad+1) )
4030
4031                   DEALLOCATE( rrtm_sw_taucld_dum )
4032                   DEALLOCATE( rrtm_sw_ssacld_dum )
4033                   DEALLOCATE( rrtm_sw_asmcld_dum )
4034                   DEALLOCATE( rrtm_sw_fsfcld_dum )
4035                   DEALLOCATE( rrtm_sw_tauaer_dum )
4036                   DEALLOCATE( rrtm_sw_ssaaer_dum )
4037                   DEALLOCATE( rrtm_sw_asmaer_dum )
4038                   DEALLOCATE( rrtm_sw_ecaer_dum )
4039!
4040!--                Save fluxes
4041                   DO k = nzb, nzt+1
4042                      rad_sw_in(k,j,i)  = rrtm_swdflx(0,k)
4043                      rad_sw_out(k,j,i) = rrtm_swuflx(0,k)
4044                   ENDDO
4045!
4046!--                Save heating rates (convert from K/d to K/s)
4047                   DO k = nzb+1, nzt+1
4048                      rad_sw_hr(k,j,i)     = rrtm_swhr(0,k)  * d_hours_day
4049                      rad_sw_cs_hr(k,j,i)  = rrtm_swhrc(0,k) * d_hours_day
4050                   ENDDO
4051
4052!
4053!--                Save surface radiative fluxes onto respective surface elements
4054!--                Horizontal surfaces
4055                   DO  m = surf_lsm_h%start_index(j,i),                        &
4056                           surf_lsm_h%end_index(j,i)
4057                      surf_lsm_h%rad_sw_in(m)     = rrtm_swdflx(0,k_topo)
4058                      surf_lsm_h%rad_sw_out(m)    = rrtm_swuflx(0,k_topo)
4059                   ENDDO             
4060                   DO  m = surf_usm_h%start_index(j,i),                        &
4061                           surf_usm_h%end_index(j,i)
4062                      surf_usm_h%rad_sw_in(m)     = rrtm_swdflx(0,k_topo)
4063                      surf_usm_h%rad_sw_out(m)    = rrtm_swuflx(0,k_topo)
4064                   ENDDO 
4065!
4066!--                Vertical surfaces. Fluxes are obtain at respective vertical
4067!--                level of the surface element
4068                   DO  l = 0, 3
4069                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
4070                              surf_lsm_v(l)%end_index(j,i)
4071                         k                           = surf_lsm_v(l)%k(m)
4072                         surf_lsm_v(l)%rad_sw_in(m)  = rrtm_swdflx(0,k)
4073                         surf_lsm_v(l)%rad_sw_out(m) = rrtm_swuflx(0,k)
4074                      ENDDO             
4075                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
4076                              surf_usm_v(l)%end_index(j,i)
4077                         k                           = surf_usm_v(l)%k(m)
4078                         surf_usm_v(l)%rad_sw_in(m)  = rrtm_swdflx(0,k)
4079                         surf_usm_v(l)%rad_sw_out(m) = rrtm_swuflx(0,k)
4080                      ENDDO 
4081                   ENDDO
4082!
4083!--             Solar radiation is zero during night
4084                ELSE
4085                   rad_sw_in  = 0.0_wp
4086                   rad_sw_out = 0.0_wp
4087!--             !!!!!!!! ATTENSION !!!!!!!!!!!!!!!
4088!--             Surface radiative fluxes should be also set to zero here                 
4089!--                Save surface radiative fluxes onto respective surface elements
4090!--                Horizontal surfaces
4091                   DO  m = surf_lsm_h%start_index(j,i),                        &
4092                           surf_lsm_h%end_index(j,i)
4093                      surf_lsm_h%rad_sw_in(m)     = 0.0_wp
4094                      surf_lsm_h%rad_sw_out(m)    = 0.0_wp
4095                   ENDDO             
4096                   DO  m = surf_usm_h%start_index(j,i),                        &
4097                           surf_usm_h%end_index(j,i)
4098                      surf_usm_h%rad_sw_in(m)     = 0.0_wp
4099                      surf_usm_h%rad_sw_out(m)    = 0.0_wp
4100                   ENDDO 
4101!
4102!--                Vertical surfaces. Fluxes are obtain at respective vertical
4103!--                level of the surface element
4104                   DO  l = 0, 3
4105                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
4106                              surf_lsm_v(l)%end_index(j,i)
4107                         k                           = surf_lsm_v(l)%k(m)
4108                         surf_lsm_v(l)%rad_sw_in(m)  = 0.0_wp
4109                         surf_lsm_v(l)%rad_sw_out(m) = 0.0_wp
4110                      ENDDO             
4111                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
4112                              surf_usm_v(l)%end_index(j,i)
4113                         k                           = surf_usm_v(l)%k(m)
4114                         surf_usm_v(l)%rad_sw_in(m)  = 0.0_wp
4115                         surf_usm_v(l)%rad_sw_out(m) = 0.0_wp
4116                      ENDDO 
4117                   ENDDO
4118                ENDIF
4119
4120             ENDDO
4121          ENDDO
4122
4123       ENDIF
4124!
4125!--    Finally, calculate surface net radiation for surface elements.
4126       IF (  .NOT.  radiation_interactions  ) THEN
4127!--       First, for horizontal surfaces   
4128          DO  m = 1, surf_lsm_h%ns
4129             surf_lsm_h%rad_net(m) = surf_lsm_h%rad_sw_in(m)                   &
4130                                   - surf_lsm_h%rad_sw_out(m)                  &
4131                                   + surf_lsm_h%rad_lw_in(m)                   &
4132                                   - surf_lsm_h%rad_lw_out(m)
4133          ENDDO
4134          DO  m = 1, surf_usm_h%ns
4135             surf_usm_h%rad_net(m) = surf_usm_h%rad_sw_in(m)                   &
4136                                   - surf_usm_h%rad_sw_out(m)                  &
4137                                   + surf_usm_h%rad_lw_in(m)                   &
4138                                   - surf_usm_h%rad_lw_out(m)
4139          ENDDO
4140!
4141!--       Vertical surfaces.
4142!--       Todo: weight with azimuth and zenith angle according to their orientation!
4143          DO  l = 0, 3     
4144             DO  m = 1, surf_lsm_v(l)%ns
4145                surf_lsm_v(l)%rad_net(m) = surf_lsm_v(l)%rad_sw_in(m)          &
4146                                         - surf_lsm_v(l)%rad_sw_out(m)         &
4147                                         + surf_lsm_v(l)%rad_lw_in(m)          &
4148                                         - surf_lsm_v(l)%rad_lw_out(m)
4149             ENDDO
4150             DO  m = 1, surf_usm_v(l)%ns
4151                surf_usm_v(l)%rad_net(m) = surf_usm_v(l)%rad_sw_in(m)          &
4152                                         - surf_usm_v(l)%rad_sw_out(m)         &
4153                                         + surf_usm_v(l)%rad_lw_in(m)          &
4154                                         - surf_usm_v(l)%rad_lw_out(m)
4155             ENDDO
4156          ENDDO
4157       ENDIF
4158
4159
4160       CALL exchange_horiz( rad_lw_in,  nbgp )
4161       CALL exchange_horiz( rad_lw_out, nbgp )
4162       CALL exchange_horiz( rad_lw_hr,    nbgp )
4163       CALL exchange_horiz( rad_lw_cs_hr, nbgp )
4164
4165       CALL exchange_horiz( rad_sw_in,  nbgp )
4166       CALL exchange_horiz( rad_sw_out, nbgp ) 
4167       CALL exchange_horiz( rad_sw_hr,    nbgp )
4168       CALL exchange_horiz( rad_sw_cs_hr, nbgp )
4169
4170#endif
4171
4172    END SUBROUTINE radiation_rrtmg
4173
4174
4175!------------------------------------------------------------------------------!
4176! Description:
4177! ------------
4178!> Calculate the cosine of the zenith angle (variable is called zenith)
4179!------------------------------------------------------------------------------!
4180    SUBROUTINE calc_zenith
4181
4182       IMPLICIT NONE
4183
4184       REAL(wp) ::  declination,  & !< solar declination angle
4185                    hour_angle      !< solar hour angle
4186!
4187!--    Calculate current day and time based on the initial values and simulation
4188!--    time
4189       CALL calc_date_and_time
4190
4191!
4192!--    Calculate solar declination and hour angle   
4193       declination = ASIN( decl_1 * SIN(decl_2 * REAL(day_of_year, KIND=wp) - decl_3) )
4194       hour_angle  = 2.0_wp * pi * (time_utc / 86400.0_wp) + lon - pi
4195
4196!
4197!--    Calculate cosine of solar zenith angle
4198       cos_zenith = SIN(lat) * SIN(declination) + COS(lat) * COS(declination)   &
4199                                            * COS(hour_angle)
4200       cos_zenith = MAX(0.0_wp,cos_zenith)
4201
4202!
4203!--    Calculate solar directional vector
4204       IF ( sun_direction )  THEN
4205
4206!
4207!--       Direction in longitudes equals to sin(solar_azimuth) * sin(zenith)
4208          sun_dir_lon = -SIN(hour_angle) * COS(declination)
4209
4210!
4211!--       Direction in latitues equals to cos(solar_azimuth) * sin(zenith)
4212          sun_dir_lat = SIN(declination) * COS(lat) - COS(hour_angle) &
4213                              * COS(declination) * SIN(lat)
4214       ENDIF
4215
4216!
4217!--    Check if the sun is up (otheriwse shortwave calculations can be skipped)
4218       IF ( cos_zenith > 0.0_wp )  THEN
4219          sun_up = .TRUE.
4220       ELSE
4221          sun_up = .FALSE.
4222       END IF
4223
4224    END SUBROUTINE calc_zenith
4225
4226#if defined ( __rrtmg ) && defined ( __netcdf )
4227!------------------------------------------------------------------------------!
4228! Description:
4229! ------------
4230!> Calculates surface albedo components based on Briegleb (1992) and
4231!> Briegleb et al. (1986)
4232!------------------------------------------------------------------------------!
4233    SUBROUTINE calc_albedo( surf )
4234
4235        IMPLICIT NONE
4236
4237        INTEGER(iwp)    ::  ind_type !< running index surface tiles
4238        INTEGER(iwp)    ::  m        !< running index surface elements
4239
4240        TYPE(surf_type) ::  surf !< treated surfaces
4241
4242        IF ( sun_up  .AND.  .NOT. average_radiation )  THEN
4243
4244           DO  m = 1, surf%ns
4245!
4246!--           Loop over surface elements
4247              DO  ind_type = 0, SIZE( surf%albedo_type, 1 ) - 1
4248           
4249!
4250!--              Ocean
4251                 IF ( surf%albedo_type(ind_type,m) == 1 )  THEN
4252                    surf%rrtm_aldir(ind_type,m) = 0.026_wp /                    &
4253                                                ( cos_zenith**1.7_wp + 0.065_wp )&
4254                                     + 0.15_wp * ( cos_zenith - 0.1_wp )         &
4255                                               * ( cos_zenith - 0.5_wp )         &
4256                                               * ( cos_zenith - 1.0_wp )
4257                    surf%rrtm_asdir(ind_type,m) = surf%rrtm_aldir(ind_type,m)
4258!
4259!--              Snow
4260                 ELSEIF ( surf%albedo_type(ind_type,m) == 16 )  THEN
4261                    IF ( cos_zenith < 0.5_wp )  THEN
4262                       surf%rrtm_aldir(ind_type,m) =                           &
4263                                 0.5_wp * ( 1.0_wp - surf%aldif(ind_type,m) )  &
4264                                        * ( 3.0_wp / ( 1.0_wp + 4.0_wp         &
4265                                        * cos_zenith ) ) - 1.0_wp
4266                       surf%rrtm_asdir(ind_type,m) =                           &
4267                                 0.5_wp * ( 1.0_wp - surf%asdif(ind_type,m) )  &
4268                                        * ( 3.0_wp / ( 1.0_wp + 4.0_wp         &
4269                                        * cos_zenith ) ) - 1.0_wp
4270
4271                       surf%rrtm_aldir(ind_type,m) =                           &
4272                                       MIN(0.98_wp, surf%rrtm_aldir(ind_type,m))
4273                       surf%rrtm_asdir(ind_type,m) =                           &
4274                                       MIN(0.98_wp, surf%rrtm_asdir(ind_type,m))
4275                    ELSE
4276                       surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4277                       surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4278                    ENDIF
4279!
4280!--              Sea ice
4281                 ELSEIF ( surf%albedo_type(ind_type,m) == 15 )  THEN
4282                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4283                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4284
4285!
4286!--              Asphalt
4287                 ELSEIF ( surf%albedo_type(ind_type,m) == 17 )  THEN
4288                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4289                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4290
4291
4292!
4293!--              Bare soil
4294                 ELSEIF ( surf%albedo_type(ind_type,m) == 18 )  THEN
4295                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4296                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4297
4298!
4299!--              Land surfaces
4300                 ELSE
4301                    SELECT CASE ( surf%albedo_type(ind_type,m) )
4302
4303!
4304!--                    Surface types with strong zenith dependence
4305                       CASE ( 1, 2, 3, 4, 11, 12, 13 )
4306                          surf%rrtm_aldir(ind_type,m) =                        &
4307                                surf%aldif(ind_type,m) * 1.4_wp /              &
4308                                           ( 1.0_wp + 0.8_wp * cos_zenith )
4309                          surf%rrtm_asdir(ind_type,m) =                        &
4310                                surf%asdif(ind_type,m) * 1.4_wp /              &
4311                                           ( 1.0_wp + 0.8_wp * cos_zenith )
4312!
4313!--                    Surface types with weak zenith dependence
4314                       CASE ( 5, 6, 7, 8, 9, 10, 14 )
4315                          surf%rrtm_aldir(ind_type,m) =                        &
4316                                surf%aldif(ind_type,m) * 1.1_wp /              &
4317                                           ( 1.0_wp + 0.2_wp * cos_zenith )
4318                          surf%rrtm_asdir(ind_type,m) =                        &
4319                                surf%asdif(ind_type,m) * 1.1_wp /              &
4320                                           ( 1.0_wp + 0.2_wp * cos_zenith )
4321
4322                       CASE DEFAULT
4323
4324                    END SELECT
4325                 ENDIF
4326!
4327!--              Diffusive albedo is taken from Table 2
4328                 surf%rrtm_aldif(ind_type,m) = surf%aldif(ind_type,m)
4329                 surf%rrtm_asdif(ind_type,m) = surf%asdif(ind_type,m)
4330              ENDDO
4331           ENDDO
4332!
4333!--     Set albedo in case of average radiation
4334        ELSEIF ( sun_up  .AND.  average_radiation )  THEN
4335           surf%rrtm_asdir = albedo_urb
4336           surf%rrtm_asdif = albedo_urb
4337           surf%rrtm_aldir = albedo_urb
4338           surf%rrtm_aldif = albedo_urb 
4339!
4340!--     Darkness
4341        ELSE
4342           surf%rrtm_aldir = 0.0_wp
4343           surf%rrtm_asdir = 0.0_wp
4344           surf%rrtm_aldif = 0.0_wp
4345           surf%rrtm_asdif = 0.0_wp
4346        ENDIF
4347
4348    END SUBROUTINE calc_albedo
4349
4350!------------------------------------------------------------------------------!
4351! Description:
4352! ------------
4353!> Read sounding data (pressure and temperature) from RADIATION_DATA.
4354!------------------------------------------------------------------------------!
4355    SUBROUTINE read_sounding_data
4356
4357       IMPLICIT NONE
4358
4359       INTEGER(iwp) :: id,           & !< NetCDF id of input file
4360                       id_dim_zrad,  & !< pressure level id in the NetCDF file
4361                       id_var,       & !< NetCDF variable id
4362                       k,            & !< loop index
4363                       nz_snd,       & !< number of vertical levels in the sounding data
4364                       nz_snd_start, & !< start vertical index for sounding data to be used
4365                       nz_snd_end      !< end vertical index for souding data to be used
4366
4367       REAL(wp) :: t_surface           !< actual surface temperature
4368
4369       REAL(wp), DIMENSION(:), ALLOCATABLE ::  hyp_snd_tmp, & !< temporary hydrostatic pressure profile (sounding)
4370                                               t_snd_tmp      !< temporary temperature profile (sounding)
4371
4372!
4373!--    In case of updates, deallocate arrays first (sufficient to check one
4374!--    array as the others are automatically allocated). This is required
4375!--    because nzt_rad might change during the update
4376       IF ( ALLOCATED ( hyp_snd ) )  THEN
4377          DEALLOCATE( hyp_snd )
4378          DEALLOCATE( t_snd )
4379          DEALLOCATE ( rrtm_play )
4380          DEALLOCATE ( rrtm_plev )
4381          DEALLOCATE ( rrtm_tlay )
4382          DEALLOCATE ( rrtm_tlev )
4383
4384          DEALLOCATE ( rrtm_cicewp )
4385          DEALLOCATE ( rrtm_cldfr )
4386          DEALLOCATE ( rrtm_cliqwp )
4387          DEALLOCATE ( rrtm_reice )
4388          DEALLOCATE ( rrtm_reliq )
4389          DEALLOCATE ( rrtm_lw_taucld )
4390          DEALLOCATE ( rrtm_lw_tauaer )
4391
4392          DEALLOCATE ( rrtm_lwdflx  )
4393          DEALLOCATE ( rrtm_lwdflxc )
4394          DEALLOCATE ( rrtm_lwuflx  )
4395          DEALLOCATE ( rrtm_lwuflxc )
4396          DEALLOCATE ( rrtm_lwuflx_dt )
4397          DEALLOCATE ( rrtm_lwuflxc_dt )
4398          DEALLOCATE ( rrtm_lwhr  )
4399          DEALLOCATE ( rrtm_lwhrc )
4400
4401          DEALLOCATE ( rrtm_sw_taucld )
4402          DEALLOCATE ( rrtm_sw_ssacld )
4403          DEALLOCATE ( rrtm_sw_asmcld )
4404          DEALLOCATE ( rrtm_sw_fsfcld )
4405          DEALLOCATE ( rrtm_sw_tauaer )
4406          DEALLOCATE ( rrtm_sw_ssaaer )
4407          DEALLOCATE ( rrtm_sw_asmaer ) 
4408          DEALLOCATE ( rrtm_sw_ecaer )   
4409 
4410          DEALLOCATE ( rrtm_swdflx  )
4411          DEALLOCATE ( rrtm_swdflxc )
4412          DEALLOCATE ( rrtm_swuflx  )
4413          DEALLOCATE ( rrtm_swuflxc )
4414          DEALLOCATE ( rrtm_swhr  )
4415          DEALLOCATE ( rrtm_swhrc )
4416          DEALLOCATE ( rrtm_dirdflux )
4417          DEALLOCATE ( rrtm_difdflux )
4418
4419       ENDIF
4420
4421!
4422!--    Open file for reading
4423       nc_stat = NF90_OPEN( rrtm_input_file, NF90_NOWRITE, id )
4424       CALL netcdf_handle_error_rad( 'read_sounding_data', 549 )
4425
4426!
4427!--    Inquire dimension of z axis and save in nz_snd
4428       nc_stat = NF90_INQ_DIMID( id, "Pressure", id_dim_zrad )
4429       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim_zrad, len = nz_snd )
4430       CALL netcdf_handle_error_rad( 'read_sounding_data', 551 )
4431
4432!
4433! !--    Allocate temporary array for storing pressure data
4434       ALLOCATE( hyp_snd_tmp(1:nz_snd) )
4435       hyp_snd_tmp = 0.0_wp
4436
4437
4438!--    Read pressure from file
4439       nc_stat = NF90_INQ_VARID( id, "Pressure", id_var )
4440       nc_stat = NF90_GET_VAR( id, id_var, hyp_snd_tmp(:), start = (/1/),      &
4441                               count = (/nz_snd/) )
4442       CALL netcdf_handle_error_rad( 'read_sounding_data', 552 )
4443
4444!
4445!--    Allocate temporary array for storing temperature data
4446       ALLOCATE( t_snd_tmp(1:nz_snd) )
4447       t_snd_tmp = 0.0_wp
4448
4449!
4450!--    Read temperature from file
4451       nc_stat = NF90_INQ_VARID( id, "ReferenceTemperature", id_var )
4452       nc_stat = NF90_GET_VAR( id, id_var, t_snd_tmp(:), start = (/1/),        &
4453                               count = (/nz_snd/) )
4454       CALL netcdf_handle_error_rad( 'read_sounding_data', 553 )
4455
4456!
4457!--    Calculate start of sounding data
4458       nz_snd_start = nz_snd + 1
4459       nz_snd_end   = nz_snd + 1
4460
4461!
4462!--    Start filling vertical dimension at 10hPa above the model domain (hyp is
4463!--    in Pa, hyp_snd in hPa).
4464       DO  k = 1, nz_snd
4465          IF ( hyp_snd_tmp(k) < ( hyp(nzt+1) - 1000.0_wp) * 0.01_wp )  THEN
4466             nz_snd_start = k
4467             EXIT
4468          END IF
4469       END DO
4470
4471       IF ( nz_snd_start <= nz_snd )  THEN
4472          nz_snd_end = nz_snd
4473       END IF
4474
4475
4476!
4477!--    Calculate of total grid points for RRTMG calculations
4478       nzt_rad = nzt + nz_snd_end - nz_snd_start + 1
4479
4480!
4481!--    Save data above LES domain in hyp_snd, t_snd
4482       ALLOCATE( hyp_snd(nzb+1:nzt_rad) )
4483       ALLOCATE( t_snd(nzb+1:nzt_rad)   )
4484       hyp_snd = 0.0_wp
4485       t_snd = 0.0_wp
4486
4487       hyp_snd(nzt+2:nzt_rad) = hyp_snd_tmp(nz_snd_start+1:nz_snd_end)
4488       t_snd(nzt+2:nzt_rad)   = t_snd_tmp(nz_snd_start+1:nz_snd_end)
4489
4490       nc_stat = NF90_CLOSE( id )
4491
4492!
4493!--    Calculate pressure levels on zu and zw grid. Sounding data is added at
4494!--    top of the LES domain. This routine does not consider horizontal or
4495!--    vertical variability of pressure and temperature
4496       ALLOCATE ( rrtm_play(0:0,nzb+1:nzt_rad+1)   )
4497       ALLOCATE ( rrtm_plev(0:0,nzb+1:nzt_rad+2)   )
4498
4499       t_surface = pt_surface * exner(nzb)
4500       DO k = nzb+1, nzt+1
4501          rrtm_play(0,k) = hyp(k) * 0.01_wp
4502          rrtm_plev(0,k) = barometric_formula(zw(k-1),                         &
4503                              pt_surface * exner(nzb), &
4504                              surface_pressure )
4505       ENDDO
4506
4507       DO k = nzt+2, nzt_rad
4508          rrtm_play(0,k) = hyp_snd(k)
4509          rrtm_plev(0,k) = 0.5_wp * ( rrtm_play(0,k) + rrtm_play(0,k-1) )
4510       ENDDO
4511       rrtm_plev(0,nzt_rad+1) = MAX( 0.5 * hyp_snd(nzt_rad),                   &
4512                                   1.5 * hyp_snd(nzt_rad)                      &
4513                                 - 0.5 * hyp_snd(nzt_rad-1) )
4514       rrtm_plev(0,nzt_rad+2)  = MIN( 1.0E-4_wp,                               &
4515                                      0.25_wp * rrtm_plev(0,nzt_rad+1) )
4516
4517       rrtm_play(0,nzt_rad+1) = 0.5 * rrtm_plev(0,nzt_rad+1)
4518
4519!
4520!--    Calculate temperature/humidity levels at top of the LES domain.
4521!--    Currently, the temperature is taken from sounding data (might lead to a
4522!--    temperature jump at interface. To do: Humidity is currently not
4523!--    calculated above the LES domain.
4524       ALLOCATE ( rrtm_tlay(0:0,nzb+1:nzt_rad+1)   )
4525       ALLOCATE ( rrtm_tlev(0:0,nzb+1:nzt_rad+2)   )
4526
4527       DO k = nzt+8, nzt_rad
4528          rrtm_tlay(0,k)   = t_snd(k)
4529       ENDDO
4530       rrtm_tlay(0,nzt_rad+1) = 2.0_wp * rrtm_tlay(0,nzt_rad)                  &
4531                                - rrtm_tlay(0,nzt_rad-1)
4532       DO k = nzt+9, nzt_rad+1
4533          rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k)                &
4534                             - rrtm_tlay(0,k-1))                               &
4535                             / ( rrtm_play(0,k) - rrtm_play(0,k-1) )           &
4536                             * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
4537       ENDDO
4538
4539       rrtm_tlev(0,nzt_rad+2)   = 2.0_wp * rrtm_tlay(0,nzt_rad+1)              &
4540                                  - rrtm_tlev(0,nzt_rad)
4541!
4542!--    Allocate remaining RRTMG arrays
4543       ALLOCATE ( rrtm_cicewp(0:0,nzb+1:nzt_rad+1) )
4544       ALLOCATE ( rrtm_cldfr(0:0,nzb+1:nzt_rad+1) )
4545       ALLOCATE ( rrtm_cliqwp(0:0,nzb+1:nzt_rad+1) )
4546       ALLOCATE ( rrtm_reice(0:0,nzb+1:nzt_rad+1) )
4547       ALLOCATE ( rrtm_reliq(0:0,nzb+1:nzt_rad+1) )
4548       ALLOCATE ( rrtm_lw_taucld(1:nbndlw+1,0:0,nzb+1:nzt_rad+1) )
4549       ALLOCATE ( rrtm_lw_tauaer(0:0,nzb+1:nzt_rad+1,1:nbndlw+1) )
4550       ALLOCATE ( rrtm_sw_taucld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4551       ALLOCATE ( rrtm_sw_ssacld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4552       ALLOCATE ( rrtm_sw_asmcld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4553       ALLOCATE ( rrtm_sw_fsfcld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4554       ALLOCATE ( rrtm_sw_tauaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) )
4555       ALLOCATE ( rrtm_sw_ssaaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) )
4556       ALLOCATE ( rrtm_sw_asmaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) ) 
4557       ALLOCATE ( rrtm_sw_ecaer(0:0,nzb+1:nzt_rad+1,1:naerec+1) )   
4558
4559!
4560!--    The ice phase is currently not considered in PALM
4561       rrtm_cicewp = 0.0_wp
4562       rrtm_reice  = 0.0_wp
4563
4564!
4565!--    Set other parameters (move to NAMELIST parameters in the future)
4566       rrtm_lw_tauaer = 0.0_wp
4567       rrtm_lw_taucld = 0.0_wp
4568       rrtm_sw_taucld = 0.0_wp
4569       rrtm_sw_ssacld = 0.0_wp
4570       rrtm_sw_asmcld = 0.0_wp
4571       rrtm_sw_fsfcld = 0.0_wp
4572       rrtm_sw_tauaer = 0.0_wp
4573       rrtm_sw_ssaaer = 0.0_wp
4574       rrtm_sw_asmaer = 0.0_wp
4575       rrtm_sw_ecaer  = 0.0_wp
4576
4577
4578       ALLOCATE ( rrtm_swdflx(0:0,nzb:nzt_rad+1)  )
4579       ALLOCATE ( rrtm_swuflx(0:0,nzb:nzt_rad+1)  )
4580       ALLOCATE ( rrtm_swhr(0:0,nzb+1:nzt_rad+1)  )
4581       ALLOCATE ( rrtm_swuflxc(0:0,nzb:nzt_rad+1) )
4582       ALLOCATE ( rrtm_swdflxc(0:0,nzb:nzt_rad+1) )
4583       ALLOCATE ( rrtm_swhrc(0:0,nzb+1:nzt_rad+1) )
4584       ALLOCATE ( rrtm_dirdflux(0:0,nzb:nzt_rad+1) )
4585       ALLOCATE ( rrtm_difdflux(0:0,nzb:nzt_rad+1) )
4586
4587       rrtm_swdflx  = 0.0_wp
4588       rrtm_swuflx  = 0.0_wp
4589       rrtm_swhr    = 0.0_wp 
4590       rrtm_swuflxc = 0.0_wp
4591       rrtm_swdflxc = 0.0_wp
4592       rrtm_swhrc   = 0.0_wp
4593       rrtm_dirdflux = 0.0_wp
4594       rrtm_difdflux = 0.0_wp
4595
4596       ALLOCATE ( rrtm_lwdflx(0:0,nzb:nzt_rad+1)  )
4597       ALLOCATE ( rrtm_lwuflx(0:0,nzb:nzt_rad+1)  )
4598       ALLOCATE ( rrtm_lwhr(0:0,nzb+1:nzt_rad+1)  )
4599       ALLOCATE ( rrtm_lwuflxc(0:0,nzb:nzt_rad+1) )
4600       ALLOCATE ( rrtm_lwdflxc(0:0,nzb:nzt_rad+1) )
4601       ALLOCATE ( rrtm_lwhrc(0:0,nzb+1:nzt_rad+1) )
4602
4603       rrtm_lwdflx  = 0.0_wp
4604       rrtm_lwuflx  = 0.0_wp
4605       rrtm_lwhr    = 0.0_wp 
4606       rrtm_lwuflxc = 0.0_wp
4607       rrtm_lwdflxc = 0.0_wp
4608       rrtm_lwhrc   = 0.0_wp
4609
4610       ALLOCATE ( rrtm_lwuflx_dt(0:0,nzb:nzt_rad+1) )
4611       ALLOCATE ( rrtm_lwuflxc_dt(0:0,nzb:nzt_rad+1) )
4612
4613       rrtm_lwuflx_dt = 0.0_wp
4614       rrtm_lwuflxc_dt = 0.0_wp
4615
4616    END SUBROUTINE read_sounding_data
4617
4618
4619!------------------------------------------------------------------------------!
4620! Description:
4621! ------------
4622!> Read trace gas data from file and convert into trace gas paths / volume
4623!> mixing ratios. If a user-defined input file is provided it needs to follow
4624!> the convections used in RRTMG (see respective netCDF files shipped with
4625!> RRTMG)
4626!------------------------------------------------------------------------------!
4627    SUBROUTINE read_trace_gas_data
4628
4629       USE rrsw_ncpar
4630
4631       IMPLICIT NONE
4632
4633       INTEGER(iwp), PARAMETER :: num_trace_gases = 10 !< number of trace gases (absorbers)
4634
4635       CHARACTER(LEN=5), DIMENSION(num_trace_gases), PARAMETER ::              & !< trace gas names
4636           trace_names = (/'O3   ', 'CO2  ', 'CH4  ', 'N2O  ', 'O2   ',        &
4637                           'CFC11', 'CFC12', 'CFC22', 'CCL4 ', 'H2O  '/)
4638
4639       INTEGER(iwp) :: id,     & !< NetCDF id
4640                       k,      & !< loop index
4641                       m,      & !< loop index
4642                       n,      & !< loop index
4643                       nabs,   & !< number of absorbers
4644                       np,     & !< number of pressure levels
4645                       id_abs, & !< NetCDF id of the respective absorber
4646                       id_dim, & !< NetCDF id of asborber's dimension
4647                       id_var    !< NetCDf id ot the absorber
4648
4649       REAL(wp) :: p_mls_l, &    !< pressure lower limit for interpolation
4650                   p_mls_u, &    !< pressure upper limit for interpolation
4651                   p_wgt_l, &    !< pressure weight lower limit for interpolation
4652                   p_wgt_u, &    !< pressure weight upper limit for interpolation
4653                   p_mls_m       !< mean pressure between upper and lower limits
4654
4655
4656       REAL(wp), DIMENSION(:), ALLOCATABLE   ::  p_mls,          & !< pressure levels for the absorbers
4657                                                 rrtm_play_tmp,  & !< temporary array for pressure zu-levels
4658                                                 rrtm_plev_tmp,  & !< temporary array for pressure zw-levels
4659                                                 trace_path_tmp    !< temporary array for storing trace gas path data
4660
4661       REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  trace_mls,      & !< array for storing the absorber amounts
4662                                                 trace_mls_path, & !< array for storing trace gas path data
4663                                                 trace_mls_tmp     !< temporary array for storing trace gas data
4664
4665
4666!
4667!--    In case of updates, deallocate arrays first (sufficient to check one
4668!--    array as the others are automatically allocated)
4669       IF ( ALLOCATED ( rrtm_o3vmr ) )  THEN
4670          DEALLOCATE ( rrtm_o3vmr  )
4671          DEALLOCATE ( rrtm_co2vmr )
4672          DEALLOCATE ( rrtm_ch4vmr )
4673          DEALLOCATE ( rrtm_n2ovmr )
4674          DEALLOCATE ( rrtm_o2vmr  )
4675          DEALLOCATE ( rrtm_cfc11vmr )
4676          DEALLOCATE ( rrtm_cfc12vmr )
4677          DEALLOCATE ( rrtm_cfc22vmr )
4678          DEALLOCATE ( rrtm_ccl4vmr  )
4679          DEALLOCATE ( rrtm_h2ovmr  )     
4680       ENDIF
4681
4682!
4683!--    Allocate trace gas profiles
4684       ALLOCATE ( rrtm_o3vmr(0:0,1:nzt_rad+1)  )
4685       ALLOCATE ( rrtm_co2vmr(0:0,1:nzt_rad+1) )
4686       ALLOCATE ( rrtm_ch4vmr(0:0,1:nzt_rad+1) )
4687       ALLOCATE ( rrtm_n2ovmr(0:0,1:nzt_rad+1) )
4688       ALLOCATE ( rrtm_o2vmr(0:0,1:nzt_rad+1)  )
4689       ALLOCATE ( rrtm_cfc11vmr(0:0,1:nzt_rad+1) )
4690       ALLOCATE ( rrtm_cfc12vmr(0:0,1:nzt_rad+1) )
4691       ALLOCATE ( rrtm_cfc22vmr(0:0,1:nzt_rad+1) )
4692       ALLOCATE ( rrtm_ccl4vmr(0:0,1:nzt_rad+1)  )
4693       ALLOCATE ( rrtm_h2ovmr(0:0,1:nzt_rad+1)  )
4694
4695!
4696!--    Open file for reading
4697       nc_stat = NF90_OPEN( rrtm_input_file, NF90_NOWRITE, id )
4698       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 549 )
4699!
4700!--    Inquire dimension ids and dimensions
4701       nc_stat = NF90_INQ_DIMID( id, "Pressure", id_dim )
4702       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4703       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim, len = np) 
4704       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4705
4706       nc_stat = NF90_INQ_DIMID( id, "Absorber", id_dim )
4707       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4708       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim, len = nabs ) 
4709       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4710   
4711
4712!
4713!--    Allocate pressure, and trace gas arrays     
4714       ALLOCATE( p_mls(1:np) )
4715       ALLOCATE( trace_mls(1:num_trace_gases,1:np) ) 
4716       ALLOCATE( trace_mls_tmp(1:nabs,1:np) ) 
4717
4718
4719       nc_stat = NF90_INQ_VARID( id, "Pressure", id_var )
4720       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4721       nc_stat = NF90_GET_VAR( id, id_var, p_mls )
4722       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4723
4724       nc_stat = NF90_INQ_VARID( id, "AbsorberAmountMLS", id_var )
4725       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4726       nc_stat = NF90_GET_VAR( id, id_var, trace_mls_tmp )
4727       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4728
4729
4730!
4731!--    Write absorber amounts (mls) to trace_mls
4732       DO n = 1, num_trace_gases
4733          CALL getAbsorberIndex( TRIM( trace_names(n) ), id_abs )
4734
4735          trace_mls(n,1:np) = trace_mls_tmp(id_abs,1:np)
4736
4737!
4738!--       Replace missing values by zero
4739          WHERE ( trace_mls(n,:) > 2.0_wp ) 
4740             trace_mls(n,:) = 0.0_wp
4741          END WHERE
4742       END DO
4743
4744       DEALLOCATE ( trace_mls_tmp )
4745
4746       nc_stat = NF90_CLOSE( id )
4747       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 551 )
4748
4749!
4750!--    Add extra pressure level for calculations of the trace gas paths
4751       ALLOCATE ( rrtm_play_tmp(1:nzt_rad+1) )
4752       ALLOCATE ( rrtm_plev_tmp(1:nzt_rad+2) )
4753
4754       rrtm_play_tmp(1:nzt_rad)   = rrtm_play(0,1:nzt_rad) 
4755       rrtm_plev_tmp(1:nzt_rad+1) = rrtm_plev(0,1:nzt_rad+1)
4756       rrtm_play_tmp(nzt_rad+1)   = rrtm_plev(0,nzt_rad+1) * 0.5_wp
4757       rrtm_plev_tmp(nzt_rad+2)   = MIN( 1.0E-4_wp, 0.25_wp                    &
4758                                         * rrtm_plev(0,nzt_rad+1) )
4759 
4760!
4761!--    Calculate trace gas path (zero at surface) with interpolation to the
4762!--    sounding levels
4763       ALLOCATE ( trace_mls_path(1:nzt_rad+2,1:num_trace_gases) )
4764
4765       trace_mls_path(nzb+1,:) = 0.0_wp
4766       
4767       DO k = nzb+2, nzt_rad+2
4768          DO m = 1, num_trace_gases
4769             trace_mls_path(k,m) = trace_mls_path(k-1,m)
4770
4771!
4772!--          When the pressure level is higher than the trace gas pressure
4773!--          level, assume that
4774             IF ( rrtm_plev_tmp(k-1) > p_mls(1) )  THEN             
4775               
4776                trace_mls_path(k,m) = trace_mls_path(k,m) + trace_mls(m,1)     &
4777                                      * ( rrtm_plev_tmp(k-1)                   &
4778                                          - MAX( p_mls(1), rrtm_plev_tmp(k) )  &
4779                                        ) / g
4780             ENDIF
4781
4782!
4783!--          Integrate for each sounding level from the contributing p_mls
4784!--          levels
4785             DO n = 2, np
4786!
4787!--             Limit p_mls so that it is within the model level
4788                p_mls_u = MIN( rrtm_plev_tmp(k-1),                             &
4789                          MAX( rrtm_plev_tmp(k), p_mls(n) ) )
4790                p_mls_l = MIN( rrtm_plev_tmp(k-1),                             &
4791                          MAX( rrtm_plev_tmp(k), p_mls(n-1) ) )
4792
4793                IF ( p_mls_l > p_mls_u )  THEN
4794
4795!
4796!--                Calculate weights for interpolation
4797                   p_mls_m = 0.5_wp * (p_mls_l + p_mls_u)
4798                   p_wgt_u = (p_mls(n-1) - p_mls_m) / (p_mls(n-1) - p_mls(n))
4799                   p_wgt_l = (p_mls_m - p_mls(n))   / (p_mls(n-1) - p_mls(n))
4800
4801!
4802!--                Add level to trace gas path
4803                   trace_mls_path(k,m) = trace_mls_path(k,m)                   &
4804                                         +  ( p_wgt_u * trace_mls(m,n)         &
4805                                            + p_wgt_l * trace_mls(m,n-1) )     &
4806                                         * (p_mls_l - p_mls_u) / g
4807                ENDIF
4808             ENDDO
4809
4810             IF ( rrtm_plev_tmp(k) < p_mls(np) )  THEN
4811                trace_mls_path(k,m) = trace_mls_path(k,m) + trace_mls(m,np)    &
4812                                      * ( MIN( rrtm_plev_tmp(k-1), p_mls(np) ) &
4813                                          - rrtm_plev_tmp(k)                   &
4814                                        ) / g 
4815             ENDIF 
4816          ENDDO
4817       ENDDO
4818
4819
4820!
4821!--    Prepare trace gas path profiles
4822       ALLOCATE ( trace_path_tmp(1:nzt_rad+1) )
4823
4824       DO m = 1, num_trace_gases
4825
4826          trace_path_tmp(1:nzt_rad+1) = ( trace_mls_path(2:nzt_rad+2,m)        &
4827                                       - trace_mls_path(1:nzt_rad+1,m) ) * g   &
4828                                       / ( rrtm_plev_tmp(1:nzt_rad+1)          &
4829                                       - rrtm_plev_tmp(2:nzt_rad+2) )
4830
4831!
4832!--       Save trace gas paths to the respective arrays
4833          SELECT CASE ( TRIM( trace_names(m) ) )
4834
4835             CASE ( 'O3' )
4836
4837                rrtm_o3vmr(0,:) = trace_path_tmp(:)
4838
4839             CASE ( 'CO2' )
4840
4841                rrtm_co2vmr(0,:) = trace_path_tmp(:)
4842
4843             CASE ( 'CH4' )
4844
4845                rrtm_ch4vmr(0,:) = trace_path_tmp(:)
4846
4847             CASE ( 'N2O' )
4848
4849                rrtm_n2ovmr(0,:) = trace_path_tmp(:)
4850
4851             CASE ( 'O2' )
4852
4853                rrtm_o2vmr(0,:) = trace_path_tmp(:)
4854
4855             CASE ( 'CFC11' )
4856
4857                rrtm_cfc11vmr(0,:) = trace_path_tmp(:)
4858
4859             CASE ( 'CFC12' )
4860
4861                rrtm_cfc12vmr(0,:) = trace_path_tmp(:)
4862
4863             CASE ( 'CFC22' )
4864
4865                rrtm_cfc22vmr(0,:) = trace_path_tmp(:)
4866
4867             CASE ( 'CCL4' )
4868
4869                rrtm_ccl4vmr(0,:) = trace_path_tmp(:)
4870
4871             CASE ( 'H2O' )
4872
4873                rrtm_h2ovmr(0,:) = trace_path_tmp(:)
4874               
4875             CASE DEFAULT
4876
4877          END SELECT
4878
4879       ENDDO
4880
4881       DEALLOCATE ( trace_path_tmp )
4882       DEALLOCATE ( trace_mls_path )
4883       DEALLOCATE ( rrtm_play_tmp )
4884       DEALLOCATE ( rrtm_plev_tmp )
4885       DEALLOCATE ( trace_mls )
4886       DEALLOCATE ( p_mls )
4887
4888    END SUBROUTINE read_trace_gas_data
4889
4890
4891    SUBROUTINE netcdf_handle_error_rad( routine_name, errno )
4892
4893       USE control_parameters,                                                 &
4894           ONLY:  message_string
4895
4896       USE NETCDF
4897
4898       USE pegrid
4899
4900       IMPLICIT NONE
4901
4902       CHARACTER(LEN=6) ::  message_identifier
4903       CHARACTER(LEN=*) ::  routine_name
4904
4905       INTEGER(iwp) ::  errno
4906
4907       IF ( nc_stat /= NF90_NOERR )  THEN
4908
4909          WRITE( message_identifier, '(''NC'',I4.4)' )  errno
4910          message_string = TRIM( NF90_STRERROR( nc_stat ) )
4911
4912          CALL message( routine_name, message_identifier, 2, 2, 0, 6, 1 )
4913
4914       ENDIF
4915
4916    END SUBROUTINE netcdf_handle_error_rad
4917#endif
4918
4919
4920!------------------------------------------------------------------------------!
4921! Description:
4922! ------------
4923!> Calculate temperature tendency due to radiative cooling/heating.
4924!> Cache-optimized version.
4925!------------------------------------------------------------------------------!
4926#if defined( __rrtmg )
4927 SUBROUTINE radiation_tendency_ij ( i, j, tend )
4928
4929    IMPLICIT NONE
4930
4931    INTEGER(iwp) :: i, j, k !< loop indices
4932
4933    REAL(wp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg) :: tend !< pt tendency term
4934
4935    IF ( radiation_scheme == 'rrtmg' )  THEN
4936!
4937!--    Calculate tendency based on heating rate
4938       DO k = nzb+1, nzt+1
4939          tend(k,j,i) = tend(k,j,i) + (rad_lw_hr(k,j,i) + rad_sw_hr(k,j,i))    &
4940                                         * d_exner(k) * d_seconds_hour
4941       ENDDO
4942
4943    ENDIF
4944
4945 END SUBROUTINE radiation_tendency_ij
4946#endif
4947
4948
4949!------------------------------------------------------------------------------!
4950! Description:
4951! ------------
4952!> Calculate temperature tendency due to radiative cooling/heating.
4953!> Vector-optimized version
4954!------------------------------------------------------------------------------!
4955#if defined( __rrtmg )
4956 SUBROUTINE radiation_tendency ( tend )
4957
4958    USE indices,                                                               &
4959        ONLY:  nxl, nxr, nyn, nys
4960
4961    IMPLICIT NONE
4962
4963    INTEGER(iwp) :: i, j, k !< loop indices
4964
4965    REAL(wp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg) :: tend !< pt tendency term
4966
4967    IF ( radiation_scheme == 'rrtmg' )  THEN
4968!
4969!--    Calculate tendency based on heating rate
4970       DO  i = nxl, nxr
4971          DO  j = nys, nyn
4972             DO k = nzb+1, nzt+1
4973                tend(k,j,i) = tend(k,j,i) + ( rad_lw_hr(k,j,i)                 &
4974                                          +  rad_sw_hr(k,j,i) ) * d_exner(k)   &
4975                                          * d_seconds_hour
4976             ENDDO
4977          ENDDO
4978       ENDDO
4979    ENDIF
4980
4981 END SUBROUTINE radiation_tendency
4982#endif
4983
4984!------------------------------------------------------------------------------!
4985! Description:
4986! ------------
4987!> This subroutine calculates interaction of the solar radiation
4988!> with urban and land surfaces and updates all surface heatfluxes.
4989!> It calculates also the required parameters for RRTMG lower BC.
4990!>
4991!> For more info. see Resler et al. 2017
4992!>
4993!> The new version 2.0 was radically rewriten, the discretization scheme
4994!> has been changed. This new version significantly improves effectivity
4995!> of the paralelization and the scalability of the model.
4996!------------------------------------------------------------------------------!
4997
4998 SUBROUTINE radiation_interaction
4999
5000     IMPLICIT NONE
5001
5002     INTEGER(iwp)                      :: i, j, k, kk, d, refstep, m, mm, l, ll
5003     INTEGER(iwp)                      :: isurf, isurfsrc, isvf, icsf, ipcgb
5004     INTEGER(iwp)                      :: imrt, imrtf
5005     INTEGER(iwp)                      :: isd                !< solar direction number
5006     INTEGER(iwp)                      :: pc_box_dimshift    !< transform for best accuracy
5007     INTEGER(iwp), DIMENSION(0:3)      :: reorder = (/ 1, 0, 3, 2 /)
5008     
5009     REAL(wp), DIMENSION(3,3)          :: mrot               !< grid rotation matrix (zyx)
5010     REAL(wp), DIMENSION(3,0:nsurf_type):: vnorm             !< face direction normal vectors (zyx)
5011     REAL(wp), DIMENSION(3)            :: sunorig            !< grid rotated solar direction unit vector (zyx)
5012     REAL(wp), DIMENSION(3)            :: sunorig_grid       !< grid squashed solar direction unit vector (zyx)
5013     REAL(wp), DIMENSION(0:nsurf_type) :: costheta           !< direct irradiance factor of solar angle
5014     REAL(wp), DIMENSION(nz_urban_b:nz_urban_t)    :: pchf_prep          !< precalculated factor for canopy temperature tendency
5015     REAL(wp), PARAMETER               :: alpha = 0._wp      !< grid rotation (TODO: synchronize with rotation_angle
5016                                                             !< from netcdf_data_input_mod)
5017     REAL(wp)                          :: pc_box_area, pc_abs_frac, pc_abs_eff
5018     REAL(wp)                          :: asrc               !< area of source face
5019     REAL(wp)                          :: pcrad              !< irradiance from plant canopy
5020     REAL(wp)                          :: pabsswl  = 0.0_wp  !< total absorbed SW radiation energy in local processor (W)
5021     REAL(wp)                          :: pabssw   = 0.0_wp  !< total absorbed SW radiation energy in all processors (W)
5022     REAL(wp)                          :: pabslwl  = 0.0_wp  !< total absorbed LW radiation energy in local processor (W)
5023     REAL(wp)                          :: pabslw   = 0.0_wp  !< total absorbed LW radiation energy in all processors (W)
5024     REAL(wp)                          :: pemitlwl = 0.0_wp  !< total emitted LW radiation energy in all processors (W)
5025     REAL(wp)                          :: pemitlw  = 0.0_wp  !< total emitted LW radiation energy in all processors (W)
5026     REAL(wp)                          :: pinswl   = 0.0_wp  !< total received SW radiation energy in local processor (W)
5027     REAL(wp)                          :: pinsw    = 0.0_wp  !< total received SW radiation energy in all processor (W)
5028     REAL(wp)                          :: pinlwl   = 0.0_wp  !< total received LW radiation energy in local processor (W)
5029     REAL(wp)                          :: pinlw    = 0.0_wp  !< total received LW radiation energy in all processor (W)
5030     REAL(wp)                          :: emiss_sum_surfl    !< sum of emissisivity of surfaces in local processor
5031     REAL(wp)                          :: emiss_sum_surf     !< sum of emissisivity of surfaces in all processor
5032     REAL(wp)                          :: area_surfl         !< total area of surfaces in local processor
5033     REAL(wp)                          :: area_surf          !< total area of surfaces in all processor
5034     REAL(wp)                          :: area_hor           !< total horizontal area of domain in all processor
5035
5036
5037     IF ( plant_canopy )  THEN
5038         pchf_prep(:) = r_d * exner(nz_urban_b:nz_urban_t)                                 &
5039                     / (c_p * hyp(nz_urban_b:nz_urban_t) * dx*dy*dz(1)) !< equals to 1 / (rho * c_p * Vbox * T)
5040     ENDIF
5041
5042     sun_direction = .TRUE.
5043     CALL calc_zenith  !< required also for diffusion radiation
5044
5045!--     prepare rotated normal vectors and irradiance factor
5046     vnorm(1,:) = kdir(:)
5047     vnorm(2,:) = jdir(:)
5048     vnorm(3,:) = idir(:)
5049     mrot(1, :) = (/ 1._wp,  0._wp,      0._wp      /)
5050     mrot(2, :) = (/ 0._wp,  COS(alpha), SIN(alpha) /)
5051     mrot(3, :) = (/ 0._wp, -SIN(alpha), COS(alpha) /)
5052     sunorig = (/ cos_zenith, sun_dir_lat, sun_dir_lon /)
5053     sunorig = MATMUL(mrot, sunorig)
5054     DO d = 0, nsurf_type
5055         costheta(d) = DOT_PRODUCT(sunorig, vnorm(:,d))
5056     ENDDO
5057
5058     IF ( cos_zenith > 0 )  THEN
5059!--      now we will "squash" the sunorig vector by grid box size in
5060!--      each dimension, so that this new direction vector will allow us
5061!--      to traverse the ray path within grid coordinates directly
5062         sunorig_grid = (/ sunorig(1)/dz(1), sunorig(2)/dy, sunorig(3)/dx /)
5063!--      sunorig_grid = sunorig_grid / norm2(sunorig_grid)
5064         sunorig_grid = sunorig_grid / SQRT(SUM(sunorig_grid**2))
5065
5066         IF ( npcbl > 0 )  THEN
5067!--         precompute effective box depth with prototype Leaf Area Density
5068            pc_box_dimshift = MAXLOC(ABS(sunorig), 1) - 1
5069            CALL box_absorb(CSHIFT((/dz(1),dy,dx/), pc_box_dimshift),       &
5070                                60, prototype_lad,                          &
5071                                CSHIFT(ABS(sunorig), pc_box_dimshift),      &
5072                                pc_box_area, pc_abs_frac)
5073            pc_box_area = pc_box_area * ABS(sunorig(pc_box_dimshift+1)      &
5074                          / sunorig(1))
5075            pc_abs_eff = LOG(1._wp - pc_abs_frac) / prototype_lad
5076         ENDIF
5077     ENDIF
5078
5079!--  if radiation scheme is not RRTMG, split diffusion and direct part of the solar downward radiation
5080!--  comming from radiation model and store it in 2D arrays
5081     IF (  radiation_scheme /= 'rrtmg'  )  CALL calc_diffusion_radiation
5082
5083!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5084!--     First pass: direct + diffuse irradiance + thermal
5085!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5086     surfinswdir   = 0._wp !nsurfl
5087     surfins       = 0._wp !nsurfl
5088     surfinl       = 0._wp !nsurfl
5089     surfoutsl(:)  = 0.0_wp !start-end
5090     surfoutll(:)  = 0.0_wp !start-end
5091     IF ( nmrtbl > 0 )  THEN
5092        mrtinsw(:) = 0._wp
5093        mrtinlw(:) = 0._wp
5094     ENDIF
5095     surfinlg(:)  = 0._wp !global
5096
5097
5098!--  Set up thermal radiation from surfaces
5099!--  emiss_surf is defined only for surfaces for which energy balance is calculated
5100!--  Workaround: reorder surface data type back on 1D array including all surfaces,
5101!--  which implies to reorder horizontal and vertical surfaces
5102!
5103!--  Horizontal walls
5104     mm = 1
5105     DO  i = nxl, nxr
5106        DO  j = nys, nyn
5107!--           urban
5108           DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
5109              surfoutll(mm) = SUM ( surf_usm_h%frac(:,m) *                  &
5110                                    surf_usm_h%emissivity(:,m) )            &
5111                                  * sigma_sb                                &
5112                                  * surf_usm_h%pt_surface(m)**4
5113              albedo_surf(mm) = SUM ( surf_usm_h%frac(:,m) *                &
5114                                      surf_usm_h%albedo(:,m) )
5115              emiss_surf(mm)  = SUM ( surf_usm_h%frac(:,m) *                &
5116                                      surf_usm_h%emissivity(:,m) )
5117              mm = mm + 1
5118           ENDDO
5119!--           land
5120           DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
5121              surfoutll(mm) = SUM ( surf_lsm_h%frac(:,m) *                  &
5122                                    surf_lsm_h%emissivity(:,m) )            &
5123                                  * sigma_sb                                &
5124                                  * surf_lsm_h%pt_surface(m)**4
5125              albedo_surf(mm) = SUM ( surf_lsm_h%frac(:,m) *                &
5126                                      surf_lsm_h%albedo(:,m) )
5127              emiss_surf(mm)  = SUM ( surf_lsm_h%frac(:,m) *                &
5128                                      surf_lsm_h%emissivity(:,m) )
5129              mm = mm + 1
5130           ENDDO
5131        ENDDO
5132     ENDDO
5133!
5134!--     Vertical walls
5135     DO  i = nxl, nxr
5136        DO  j = nys, nyn
5137           DO  ll = 0, 3
5138              l = reorder(ll)
5139!--              urban
5140              DO  m = surf_usm_v(l)%start_index(j,i),                       &
5141                      surf_usm_v(l)%end_index(j,i)
5142                 surfoutll(mm) = SUM ( surf_usm_v(l)%frac(:,m) *            &
5143                                       surf_usm_v(l)%emissivity(:,m) )      &
5144                                  * sigma_sb                                &
5145                                  * surf_usm_v(l)%pt_surface(m)**4
5146                 albedo_surf(mm) = SUM ( surf_usm_v(l)%frac(:,m) *          &
5147                                         surf_usm_v(l)%albedo(:,m) )
5148                 emiss_surf(mm)  = SUM ( surf_usm_v(l)%frac(:,m) *          &
5149                                         surf_usm_v(l)%emissivity(:,m) )
5150                 mm = mm + 1
5151              ENDDO
5152!--              land
5153              DO  m = surf_lsm_v(l)%start_index(j,i),                       &
5154                      surf_lsm_v(l)%end_index(j,i)
5155                 surfoutll(mm) = SUM ( surf_lsm_v(l)%frac(:,m) *            &
5156                                       surf_lsm_v(l)%emissivity(:,m) )      &
5157                                  * sigma_sb                                &
5158                                  * surf_lsm_v(l)%pt_surface(m)**4
5159                 albedo_surf(mm) = SUM ( surf_lsm_v(l)%frac(:,m) *          &
5160                                         surf_lsm_v(l)%albedo(:,m) )
5161                 emiss_surf(mm)  = SUM ( surf_lsm_v(l)%frac(:,m) *          &
5162                                         surf_lsm_v(l)%emissivity(:,m) )
5163                 mm = mm + 1
5164              ENDDO
5165           ENDDO
5166        ENDDO
5167     ENDDO
5168
5169#if defined( __parallel )
5170!--     might be optimized and gather only values relevant for current processor
5171     CALL MPI_AllGatherv(surfoutll, nsurfl, MPI_REAL, &
5172                         surfoutl, nsurfs, surfstart, MPI_REAL, comm2d, ierr) !nsurf global
5173     IF ( ierr /= 0 ) THEN
5174         WRITE(9,*) 'Error MPI_AllGatherv1:', ierr, SIZE(surfoutll), nsurfl, &
5175                     SIZE(surfoutl), nsurfs, surfstart
5176         FLUSH(9)
5177     ENDIF
5178#else
5179     surfoutl(:) = surfoutll(:) !nsurf global
5180#endif
5181
5182     IF ( surface_reflections)  THEN
5183        DO  isvf = 1, nsvfl
5184           isurf = svfsurf(1, isvf)
5185           k     = surfl(iz, isurf)
5186           j     = surfl(iy, isurf)
5187           i     = surfl(ix, isurf)
5188           isurfsrc = svfsurf(2, isvf)
5189!
5190!--        For surface-to-surface factors we calculate thermal radiation in 1st pass
5191           IF ( plant_lw_interact )  THEN
5192              surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * svf(2,isvf) * surfoutl(isurfsrc)
5193           ELSE
5194              surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * surfoutl(isurfsrc)
5195           ENDIF
5196        ENDDO
5197     ENDIF
5198!
5199!--  diffuse radiation using sky view factor
5200     DO isurf = 1, nsurfl
5201        j = surfl(iy, isurf)
5202        i = surfl(ix, isurf)
5203        surfinswdif(isurf) = rad_sw_in_diff(j,i) * skyvft(isurf)
5204        IF ( plant_lw_interact )  THEN
5205           surfinlwdif(isurf) = rad_lw_in_diff(j,i) * skyvft(isurf)
5206        ELSE
5207           surfinlwdif(isurf) = rad_lw_in_diff(j,i) * skyvf(isurf)
5208        ENDIF
5209     ENDDO
5210!
5211!--  MRT diffuse irradiance
5212     DO  imrt = 1, nmrtbl
5213        j = mrtbl(iy, imrt)
5214        i = mrtbl(ix, imrt)
5215        mrtinsw(imrt) = mrtskyt(imrt) * rad_sw_in_diff(j,i)
5216        mrtinlw(imrt) = mrtsky(imrt) * rad_lw_in_diff(j,i)
5217     ENDDO
5218
5219     !-- direct radiation
5220     IF ( cos_zenith > 0 )  THEN
5221        !--Identify solar direction vector (discretized number) 1)
5222        !--
5223        j = FLOOR(ACOS(cos_zenith) / pi * raytrace_discrete_elevs)
5224        i = MODULO(NINT(ATAN2(sun_dir_lon, sun_dir_lat)               &
5225                        / (2._wp*pi) * raytrace_discrete_azims-.5_wp, iwp), &
5226                   raytrace_discrete_azims)
5227        isd = dsidir_rev(j, i)
5228!-- TODO: check if isd = -1 to report that this solar position is not precalculated
5229        DO isurf = 1, nsurfl
5230           j = surfl(iy, isurf)
5231           i = surfl(ix, isurf)
5232           surfinswdir(isurf) = rad_sw_in_dir(j,i) *                        &
5233                costheta(surfl(id, isurf)) * dsitrans(isurf, isd) / cos_zenith
5234        ENDDO
5235!
5236!--     MRT direct irradiance
5237        DO  imrt = 1, nmrtbl
5238           j = mrtbl(iy, imrt)
5239           i = mrtbl(ix, imrt)
5240           mrtinsw(imrt) = mrtinsw(imrt) + mrtdsit(imrt, isd) * rad_sw_in_dir(j,i) &
5241                                     / cos_zenith / 4._wp ! normal to sphere
5242        ENDDO
5243     ENDIF
5244!
5245!--  MRT first pass thermal
5246     DO  imrtf = 1, nmrtf
5247        imrt = mrtfsurf(1, imrtf)
5248        isurfsrc = mrtfsurf(2, imrtf)
5249        mrtinlw(imrt) = mrtinlw(imrt) + mrtf(imrtf) * surfoutl(isurfsrc)
5250     ENDDO
5251!
5252!--  Absorption in each local plant canopy grid box from the first atmospheric
5253!--  pass of radiation
5254     IF ( npcbl > 0 )  THEN
5255
5256         pcbinswdir(:) = 0._wp
5257         pcbinswdif(:) = 0._wp
5258         pcbinlw(:) = 0._wp
5259
5260         DO icsf = 1, ncsfl
5261             ipcgb = csfsurf(1, icsf)
5262             i = pcbl(ix,ipcgb)
5263             j = pcbl(iy,ipcgb)
5264             k = pcbl(iz,ipcgb)
5265             isurfsrc = csfsurf(2, icsf)
5266
5267             IF ( isurfsrc == -1 )  THEN
5268!
5269!--             Diffuse radiation from sky
5270                pcbinswdif(ipcgb) = csf(1,icsf) * rad_sw_in_diff(j,i)
5271!
5272!--             Absorbed diffuse LW radiation from sky minus emitted to sky
5273                IF ( plant_lw_interact )  THEN
5274                   pcbinlw(ipcgb) = csf(1,icsf)                                  &
5275                                       * (rad_lw_in_diff(j, i)                   &
5276                                          - sigma_sb * (pt(k,j,i)*exner(k))**4)
5277                ENDIF
5278!
5279!--             Direct solar radiation
5280                IF ( cos_zenith > 0 )  THEN
5281!--                Estimate directed box absorption
5282                   pc_abs_frac = 1._wp - exp(pc_abs_eff * lad_s(k,j,i))
5283!
5284!--                isd has already been established, see 1)
5285                   pcbinswdir(ipcgb) = rad_sw_in_dir(j, i) * pc_box_area &
5286                                       * pc_abs_frac * dsitransc(ipcgb, isd)
5287                ENDIF
5288             ELSE
5289                IF ( plant_lw_interact )  THEN
5290!
5291!--                Thermal emission from plan canopy towards respective face
5292                   pcrad = sigma_sb * (pt(k,j,i) * exner(k))**4 * csf(1,icsf)
5293                   surfinlg(isurfsrc) = surfinlg(isurfsrc) + pcrad
5294!
5295!--                Remove the flux above + absorb LW from first pass from surfaces
5296                   asrc = facearea(surf(id, isurfsrc))
5297                   pcbinlw(ipcgb) = pcbinlw(ipcgb)                      &
5298                                    + (csf(1,icsf) * surfoutl(isurfsrc) & ! Absorb from first pass surf emit
5299                                       - pcrad)                         & ! Remove emitted heatflux
5300                                    * asrc
5301                ENDIF
5302             ENDIF
5303         ENDDO
5304
5305         pcbinsw(:) = pcbinswdir(:) + pcbinswdif(:)
5306     ENDIF
5307
5308     IF ( plant_lw_interact )  THEN
5309!
5310!--     Exchange incoming lw radiation from plant canopy
5311#if defined( __parallel )
5312        CALL MPI_Allreduce(MPI_IN_PLACE, surfinlg, nsurf, MPI_REAL, MPI_SUM, comm2d, ierr)
5313        IF ( ierr /= 0 )  THEN
5314           WRITE (9,*) 'Error MPI_Allreduce:', ierr
5315           FLUSH(9)
5316        ENDIF
5317        surfinl(:) = surfinl(:) + surfinlg(surfstart(myid)+1:surfstart(myid+1))
5318#else
5319        surfinl(:) = surfinl(:) + surfinlg(:)
5320#endif
5321     ENDIF
5322
5323     surfins = surfinswdir + surfinswdif
5324     surfinl = surfinl + surfinlwdif
5325     surfinsw = surfins
5326     surfinlw = surfinl
5327     surfoutsw = 0.0_wp
5328     surfoutlw = surfoutll
5329     surfemitlwl = surfoutll
5330
5331     IF ( .NOT.  surface_reflections )  THEN
5332!
5333!--     Set nrefsteps to 0 to disable reflections       
5334        nrefsteps = 0
5335        surfoutsl = albedo_surf * surfins
5336        surfoutll = (1._wp - emiss_surf) * surfinl
5337        surfoutsw = surfoutsw + surfoutsl
5338        surfoutlw = surfoutlw + surfoutll
5339     ENDIF
5340
5341!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5342!--     Next passes - reflections
5343!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5344     DO refstep = 1, nrefsteps
5345
5346         surfoutsl = albedo_surf * surfins
5347!
5348!--      for non-transparent surfaces, longwave albedo is 1 - emissivity
5349         surfoutll = (1._wp - emiss_surf) * surfinl
5350
5351#if defined( __parallel )
5352         CALL MPI_AllGatherv(surfoutsl, nsurfl, MPI_REAL, &
5353             surfouts, nsurfs, surfstart, MPI_REAL, comm2d, ierr)
5354         IF ( ierr /= 0 )  THEN
5355             WRITE(9,*) 'Error MPI_AllGatherv2:', ierr, SIZE(surfoutsl), nsurfl, &
5356                        SIZE(surfouts), nsurfs, surfstart
5357             FLUSH(9)
5358         ENDIF
5359
5360         CALL MPI_AllGatherv(surfoutll, nsurfl, MPI_REAL, &
5361             surfoutl, nsurfs, surfstart, MPI_REAL, comm2d, ierr)
5362         IF ( ierr /= 0 )  THEN
5363             WRITE(9,*) 'Error MPI_AllGatherv3:', ierr, SIZE(surfoutll), nsurfl, &
5364                        SIZE(surfoutl), nsurfs, surfstart
5365             FLUSH(9)
5366         ENDIF
5367
5368#else
5369         surfouts = surfoutsl
5370         surfoutl = surfoutll
5371#endif
5372!
5373!--      Reset for the input from next reflective pass
5374         surfins = 0._wp
5375         surfinl = 0._wp
5376!
5377!--      Reflected radiation
5378         DO isvf = 1, nsvfl
5379             isurf = svfsurf(1, isvf)
5380             isurfsrc = svfsurf(2, isvf)
5381             surfins(isurf) = surfins(isurf) + svf(1,isvf) * svf(2,isvf) * surfouts(isurfsrc)
5382             IF ( plant_lw_interact )  THEN
5383                surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * svf(2,isvf) * surfoutl(isurfsrc)
5384             ELSE
5385                surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * surfoutl(isurfsrc)
5386             ENDIF
5387         ENDDO
5388!
5389!--      NOTE: PC absorbtion and MRT from reflected can both be done at once
5390!--      after all reflections if we do one more MPI_ALLGATHERV on surfout.
5391!--      Advantage: less local computation. Disadvantage: one more collective
5392!--      MPI call.
5393!
5394!--      Radiation absorbed by plant canopy
5395         DO  icsf = 1, ncsfl
5396             ipcgb = csfsurf(1, icsf)
5397             isurfsrc = csfsurf(2, icsf)
5398             IF ( isurfsrc == -1 )  CYCLE ! sky->face only in 1st pass, not here
5399!
5400!--          Calculate source surface area. If the `surf' array is removed
5401!--          before timestepping starts (future version), then asrc must be
5402!--          stored within `csf'
5403             asrc = facearea(surf(id, isurfsrc))
5404             pcbinsw(ipcgb) = pcbinsw(ipcgb) + csf(1,icsf) * surfouts(isurfsrc) * asrc
5405             IF ( plant_lw_interact )  THEN
5406                pcbinlw(ipcgb) = pcbinlw(ipcgb) + csf(1,icsf) * surfoutl(isurfsrc) * asrc
5407             ENDIF
5408         ENDDO
5409!
5410!--      MRT reflected
5411         DO  imrtf = 1, nmrtf
5412            imrt = mrtfsurf(1, imrtf)
5413            isurfsrc = mrtfsurf(2, imrtf)
5414            mrtinsw(imrt) = mrtinsw(imrt) + mrtft(imrtf) * surfouts(isurfsrc)
5415            mrtinlw(imrt) = mrtinlw(imrt) + mrtf(imrtf) * surfoutl(isurfsrc)
5416         ENDDO
5417
5418         surfinsw = surfinsw  + surfins
5419         surfinlw = surfinlw  + surfinl
5420         surfoutsw = surfoutsw + surfoutsl
5421         surfoutlw = surfoutlw + surfoutll
5422
5423     ENDDO ! refstep
5424
5425!--  push heat flux absorbed by plant canopy to respective 3D arrays
5426     IF ( npcbl > 0 )  THEN
5427         pc_heating_rate(:,:,:) = 0.0_wp
5428         DO ipcgb = 1, npcbl
5429             j = pcbl(iy, ipcgb)
5430             i = pcbl(ix, ipcgb)
5431             k = pcbl(iz, ipcgb)
5432!
5433!--          Following expression equals former kk = k - nzb_s_inner(j,i)
5434             kk = k - get_topography_top_index_ji( j, i, 's' )  !- lad arrays are defined flat
5435             pc_heating_rate(kk, j, i) = (pcbinsw(ipcgb) + pcbinlw(ipcgb)) &
5436                 * pchf_prep(k) * pt(k, j, i) !-- = dT/dt
5437         ENDDO
5438
5439         IF ( humidity .AND. plant_canopy_transpiration ) THEN
5440!--          Calculation of plant canopy transpiration rate and correspondidng latent heat rate
5441             pc_transpiration_rate(:,:,:) = 0.0_wp
5442             pc_latent_rate(:,:,:) = 0.0_wp
5443             DO ipcgb = 1, npcbl
5444                 i = pcbl(ix, ipcgb)
5445                 j = pcbl(iy, ipcgb)
5446                 k = pcbl(iz, ipcgb)
5447                 kk = k - get_topography_top_index_ji( j, i, 's' )  !- lad arrays are defined flat
5448                 CALL pcm_calc_transpiration_rate( i, j, k, kk, pcbinsw(ipcgb), pcbinlw(ipcgb), &
5449                                                   pc_transpiration_rate(kk,j,i), pc_latent_rate(kk,j,i) )
5450              ENDDO
5451         ENDIF
5452     ENDIF
5453!
5454!--  Calculate black body MRT (after all reflections)
5455     IF ( nmrtbl > 0 )  THEN
5456        IF ( mrt_include_sw )  THEN
5457           mrt(:) = ((mrtinsw(:) + mrtinlw(:)) / sigma_sb) ** .25_wp
5458        ELSE
5459           mrt(:) = (mrtinlw(:) / sigma_sb) ** .25_wp
5460        ENDIF
5461     ENDIF
5462!
5463!--     Transfer radiation arrays required for energy balance to the respective data types
5464     DO  i = 1, nsurfl
5465        m  = surfl(im,i)
5466!
5467!--     (1) Urban surfaces
5468!--     upward-facing
5469        IF ( surfl(1,i) == iup_u )  THEN
5470           surf_usm_h%rad_sw_in(m)  = surfinsw(i)
5471           surf_usm_h%rad_sw_out(m) = surfoutsw(i)
5472           surf_usm_h%rad_sw_dir(m) = surfinswdir(i)
5473           surf_usm_h%rad_sw_dif(m) = surfinswdif(i)
5474           surf_usm_h%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -        &
5475                                      surfinswdif(i)
5476           surf_usm_h%rad_sw_res(m) = surfins(i)
5477           surf_usm_h%rad_lw_in(m)  = surfinlw(i)
5478           surf_usm_h%rad_lw_out(m) = surfoutlw(i)
5479           surf_usm_h%rad_net(m)    = surfinsw(i) - surfoutsw(i) +          &
5480                                      surfinlw(i) - surfoutlw(i)
5481           surf_usm_h%rad_net_l(m)  = surf_usm_h%rad_net(m)
5482           surf_usm_h%rad_lw_dif(m) = surfinlwdif(i)
5483           surf_usm_h%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5484           surf_usm_h%rad_lw_res(m) = surfinl(i)
5485!
5486!--     northward-facding
5487        ELSEIF ( surfl(1,i) == inorth_u )  THEN
5488           surf_usm_v(0)%rad_sw_in(m)  = surfinsw(i)
5489           surf_usm_v(0)%rad_sw_out(m) = surfoutsw(i)
5490           surf_usm_v(0)%rad_sw_dir(m) = surfinswdir(i)
5491           surf_usm_v(0)%rad_sw_dif(m) = surfinswdif(i)
5492           surf_usm_v(0)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5493                                         surfinswdif(i)
5494           surf_usm_v(0)%rad_sw_res(m) = surfins(i)
5495           surf_usm_v(0)%rad_lw_in(m)  = surfinlw(i)
5496           surf_usm_v(0)%rad_lw_out(m) = surfoutlw(i)
5497           surf_usm_v(0)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5498                                         surfinlw(i) - surfoutlw(i)
5499           surf_usm_v(0)%rad_net_l(m)  = surf_usm_v(0)%rad_net(m)
5500           surf_usm_v(0)%rad_lw_dif(m) = surfinlwdif(i)
5501           surf_usm_v(0)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5502           surf_usm_v(0)%rad_lw_res(m) = surfinl(i)
5503!
5504!--     southward-facding
5505        ELSEIF ( surfl(1,i) == isouth_u )  THEN
5506           surf_usm_v(1)%rad_sw_in(m)  = surfinsw(i)
5507           surf_usm_v(1)%rad_sw_out(m) = surfoutsw(i)
5508           surf_usm_v(1)%rad_sw_dir(m) = surfinswdir(i)
5509           surf_usm_v(1)%rad_sw_dif(m) = surfinswdif(i)
5510           surf_usm_v(1)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5511                                         surfinswdif(i)
5512           surf_usm_v(1)%rad_sw_res(m) = surfins(i)
5513           surf_usm_v(1)%rad_lw_in(m)  = surfinlw(i)
5514           surf_usm_v(1)%rad_lw_out(m) = surfoutlw(i)
5515           surf_usm_v(1)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5516                                         surfinlw(i) - surfoutlw(i)
5517           surf_usm_v(1)%rad_net_l(m)  = surf_usm_v(1)%rad_net(m)
5518           surf_usm_v(1)%rad_lw_dif(m) = surfinlwdif(i)
5519           surf_usm_v(1)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5520           surf_usm_v(1)%rad_lw_res(m) = surfinl(i)
5521!
5522!--     eastward-facing
5523        ELSEIF ( surfl(1,i) == ieast_u )  THEN
5524           surf_usm_v(2)%rad_sw_in(m)  = surfinsw(i)
5525           surf_usm_v(2)%rad_sw_out(m) = surfoutsw(i)
5526           surf_usm_v(2)%rad_sw_dir(m) = surfinswdir(i)
5527           surf_usm_v(2)%rad_sw_dif(m) = surfinswdif(i)
5528           surf_usm_v(2)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5529                                         surfinswdif(i)
5530           surf_usm_v(2)%rad_sw_res(m) = surfins(i)
5531           surf_usm_v(2)%rad_lw_in(m)  = surfinlw(i)
5532           surf_usm_v(2)%rad_lw_out(m) = surfoutlw(i)
5533           surf_usm_v(2)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5534                                         surfinlw(i) - surfoutlw(i)
5535           surf_usm_v(2)%rad_net_l(m)  = surf_usm_v(2)%rad_net(m)
5536           surf_usm_v(2)%rad_lw_dif(m) = surfinlwdif(i)
5537           surf_usm_v(2)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5538           surf_usm_v(2)%rad_lw_res(m) = surfinl(i)
5539!
5540!--     westward-facding
5541        ELSEIF ( surfl(1,i) == iwest_u )  THEN
5542           surf_usm_v(3)%rad_sw_in(m)  = surfinsw(i)
5543           surf_usm_v(3)%rad_sw_out(m) = surfoutsw(i)
5544           surf_usm_v(3)%rad_sw_dir(m) = surfinswdir(i)
5545           surf_usm_v(3)%rad_sw_dif(m) = surfinswdif(i)
5546           surf_usm_v(3)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5547                                         surfinswdif(i)
5548           surf_usm_v(3)%rad_sw_res(m) = surfins(i)
5549           surf_usm_v(3)%rad_lw_in(m)  = surfinlw(i)
5550           surf_usm_v(3)%rad_lw_out(m) = surfoutlw(i)
5551           surf_usm_v(3)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5552                                         surfinlw(i) - surfoutlw(i)
5553           surf_usm_v(3)%rad_net_l(m)  = surf_usm_v(3)%rad_net(m)
5554           surf_usm_v(3)%rad_lw_dif(m) = surfinlwdif(i)
5555           surf_usm_v(3)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5556           surf_usm_v(3)%rad_lw_res(m) = surfinl(i)
5557!
5558!--     (2) land surfaces
5559!--     upward-facing
5560        ELSEIF ( surfl(1,i) == iup_l )  THEN
5561           surf_lsm_h%rad_sw_in(m)  = surfinsw(i)
5562           surf_lsm_h%rad_sw_out(m) = surfoutsw(i)
5563           surf_lsm_h%rad_sw_dir(m) = surfinswdir(i)
5564           surf_lsm_h%rad_sw_dif(m) = surfinswdif(i)
5565           surf_lsm_h%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -        &
5566                                         surfinswdif(i)
5567           surf_lsm_h%rad_sw_res(m) = surfins(i)
5568           surf_lsm_h%rad_lw_in(m)  = surfinlw(i)
5569           surf_lsm_h%rad_lw_out(m) = surfoutlw(i)
5570           surf_lsm_h%rad_net(m)    = surfinsw(i) - surfoutsw(i) +          &
5571                                      surfinlw(i) - surfoutlw(i)
5572           surf_lsm_h%rad_lw_dif(m) = surfinlwdif(i)
5573           surf_lsm_h%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5574           surf_lsm_h%rad_lw_res(m) = surfinl(i)
5575!
5576!--     northward-facding
5577        ELSEIF ( surfl(1,i) == inorth_l )  THEN
5578           surf_lsm_v(0)%rad_sw_in(m)  = surfinsw(i)
5579           surf_lsm_v(0)%rad_sw_out(m) = surfoutsw(i)
5580           surf_lsm_v(0)%rad_sw_dir(m) = surfinswdir(i)
5581           surf_lsm_v(0)%rad_sw_dif(m) = surfinswdif(i)
5582           surf_lsm_v(0)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5583                                         surfinswdif(i)
5584           surf_lsm_v(0)%rad_sw_res(m) = surfins(i)
5585           surf_lsm_v(0)%rad_lw_in(m)  = surfinlw(i)
5586           surf_lsm_v(0)%rad_lw_out(m) = surfoutlw(i)
5587           surf_lsm_v(0)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5588                                         surfinlw(i) - surfoutlw(i)
5589           surf_lsm_v(0)%rad_lw_dif(m) = surfinlwdif(i)
5590           surf_lsm_v(0)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5591           surf_lsm_v(0)%rad_lw_res(m) = surfinl(i)
5592!
5593!--     southward-facding
5594        ELSEIF ( surfl(1,i) == isouth_l )  THEN
5595           surf_lsm_v(1)%rad_sw_in(m)  = surfinsw(i)
5596           surf_lsm_v(1)%rad_sw_out(m) = surfoutsw(i)
5597           surf_lsm_v(1)%rad_sw_dir(m) = surfinswdir(i)
5598           surf_lsm_v(1)%rad_sw_dif(m) = surfinswdif(i)
5599           surf_lsm_v(1)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5600                                         surfinswdif(i)
5601           surf_lsm_v(1)%rad_sw_res(m) = surfins(i)
5602           surf_lsm_v(1)%rad_lw_in(m)  = surfinlw(i)
5603           surf_lsm_v(1)%rad_lw_out(m) = surfoutlw(i)
5604           surf_lsm_v(1)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5605                                         surfinlw(i) - surfoutlw(i)
5606           surf_lsm_v(1)%rad_lw_dif(m) = surfinlwdif(i)
5607           surf_lsm_v(1)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5608           surf_lsm_v(1)%rad_lw_res(m) = surfinl(i)
5609!
5610!--     eastward-facing
5611        ELSEIF ( surfl(1,i) == ieast_l )  THEN
5612           surf_lsm_v(2)%rad_sw_in(m)  = surfinsw(i)
5613           surf_lsm_v(2)%rad_sw_out(m) = surfoutsw(i)
5614           surf_lsm_v(2)%rad_sw_dir(m) = surfinswdir(i)
5615           surf_lsm_v(2)%rad_sw_dif(m) = surfinswdif(i)
5616           surf_lsm_v(2)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5617                                         surfinswdif(i)
5618           surf_lsm_v(2)%rad_sw_res(m) = surfins(i)
5619           surf_lsm_v(2)%rad_lw_in(m)  = surfinlw(i)
5620           surf_lsm_v(2)%rad_lw_out(m) = surfoutlw(i)
5621           surf_lsm_v(2)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5622                                         surfinlw(i) - surfoutlw(i)
5623           surf_lsm_v(2)%rad_lw_dif(m) = surfinlwdif(i)
5624           surf_lsm_v(2)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5625           surf_lsm_v(2)%rad_lw_res(m) = surfinl(i)
5626!
5627!--     westward-facing
5628        ELSEIF ( surfl(1,i) == iwest_l )  THEN
5629           surf_lsm_v(3)%rad_sw_in(m)  = surfinsw(i)
5630           surf_lsm_v(3)%rad_sw_out(m) = surfoutsw(i)
5631           surf_lsm_v(3)%rad_sw_dir(m) = surfinswdir(i)
5632           surf_lsm_v(3)%rad_sw_dif(m) = surfinswdif(i)
5633           surf_lsm_v(3)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5634                                         surfinswdif(i)
5635           surf_lsm_v(3)%rad_sw_res(m) = surfins(i)
5636           surf_lsm_v(3)%rad_lw_in(m)  = surfinlw(i)
5637           surf_lsm_v(3)%rad_lw_out(m) = surfoutlw(i)
5638           surf_lsm_v(3)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5639                                         surfinlw(i) - surfoutlw(i)
5640           surf_lsm_v(3)%rad_lw_dif(m) = surfinlwdif(i)
5641           surf_lsm_v(3)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5642           surf_lsm_v(3)%rad_lw_res(m) = surfinl(i)
5643        ENDIF
5644
5645     ENDDO
5646
5647     DO  m = 1, surf_usm_h%ns
5648        surf_usm_h%surfhf(m) = surf_usm_h%rad_sw_in(m)  +                   &
5649                               surf_usm_h%rad_lw_in(m)  -                   &
5650                               surf_usm_h%rad_sw_out(m) -                   &
5651                               surf_usm_h%rad_lw_out(m)
5652     ENDDO
5653     DO  m = 1, surf_lsm_h%ns
5654        surf_lsm_h%surfhf(m) = surf_lsm_h%rad_sw_in(m)  +                   &
5655                               surf_lsm_h%rad_lw_in(m)  -                   &
5656                               surf_lsm_h%rad_sw_out(m) -                   &
5657                               surf_lsm_h%rad_lw_out(m)
5658     ENDDO
5659
5660     DO  l = 0, 3
5661!--     urban
5662        DO  m = 1, surf_usm_v(l)%ns
5663           surf_usm_v(l)%surfhf(m) = surf_usm_v(l)%rad_sw_in(m)  +          &
5664                                     surf_usm_v(l)%rad_lw_in(m)  -          &
5665                                     surf_usm_v(l)%rad_sw_out(m) -          &
5666                                     surf_usm_v(l)%rad_lw_out(m)
5667        ENDDO
5668!--     land
5669        DO  m = 1, surf_lsm_v(l)%ns
5670           surf_lsm_v(l)%surfhf(m) = surf_lsm_v(l)%rad_sw_in(m)  +          &
5671                                     surf_lsm_v(l)%rad_lw_in(m)  -          &
5672                                     surf_lsm_v(l)%rad_sw_out(m) -          &
5673                                     surf_lsm_v(l)%rad_lw_out(m)
5674
5675        ENDDO
5676     ENDDO
5677!
5678!--  Calculate the average temperature, albedo, and emissivity for urban/land
5679!--  domain when using average_radiation in the respective radiation model
5680
5681!--  calculate horizontal area
5682! !!! ATTENTION!!! uniform grid is assumed here
5683     area_hor = (nx+1) * (ny+1) * dx * dy
5684!
5685!--  absorbed/received SW & LW and emitted LW energy of all physical
5686!--  surfaces (land and urban) in local processor
5687     pinswl = 0._wp
5688     pinlwl = 0._wp
5689     pabsswl = 0._wp
5690     pabslwl = 0._wp
5691     pemitlwl = 0._wp
5692     emiss_sum_surfl = 0._wp
5693     area_surfl = 0._wp
5694     DO  i = 1, nsurfl
5695        d = surfl(id, i)
5696!--  received SW & LW
5697        pinswl = pinswl + (surfinswdir(i) + surfinswdif(i)) * facearea(d)
5698        pinlwl = pinlwl + surfinlwdif(i) * facearea(d)
5699!--   absorbed SW & LW
5700        pabsswl = pabsswl + (1._wp - albedo_surf(i)) *                   &
5701                                                surfinsw(i) * facearea(d)
5702        pabslwl = pabslwl + emiss_surf(i) * surfinlw(i) * facearea(d)
5703!--   emitted LW
5704        pemitlwl = pemitlwl + surfemitlwl(i) * facearea(d)
5705!--   emissivity and area sum
5706        emiss_sum_surfl = emiss_sum_surfl + emiss_surf(i) * facearea(d)
5707        area_surfl = area_surfl + facearea(d)
5708     END DO
5709!
5710!--  add the absorbed SW energy by plant canopy
5711     IF ( npcbl > 0 )  THEN
5712        pabsswl = pabsswl + SUM(pcbinsw)
5713        pabslwl = pabslwl + SUM(pcbinlw)
5714        pinswl = pinswl + SUM(pcbinswdir) + SUM(pcbinswdif)
5715     ENDIF
5716!
5717!--  gather all rad flux energy in all processors
5718#if defined( __parallel )
5719     CALL MPI_ALLREDUCE( pinswl, pinsw, 1, MPI_REAL, MPI_SUM, comm2d, ierr)
5720     IF ( ierr /= 0 ) THEN
5721         WRITE(9,*) 'Error MPI_AllReduce5:', ierr, pinswl, pinsw
5722         FLUSH(9)
5723     ENDIF
5724     CALL MPI_ALLREDUCE( pinlwl, pinlw, 1, MPI_REAL, MPI_SUM, comm2d, ierr)
5725     IF ( ierr /= 0 ) THEN
5726         WRITE(9,*) 'Error MPI_AllReduce6:', ierr, pinlwl, pinlw
5727         FLUSH(9)
5728     ENDIF
5729     CALL MPI_ALLREDUCE( pabsswl, pabssw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5730     IF ( ierr /= 0 ) THEN
5731         WRITE(9,*) 'Error MPI_AllReduce7:', ierr, pabsswl, pabssw
5732         FLUSH(9)
5733     ENDIF
5734     CALL MPI_ALLREDUCE( pabslwl, pabslw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5735     IF ( ierr /= 0 ) THEN
5736         WRITE(9,*) 'Error MPI_AllReduce8:', ierr, pabslwl, pabslw
5737         FLUSH(9)
5738     ENDIF
5739     CALL MPI_ALLREDUCE( pemitlwl, pemitlw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5740     IF ( ierr /= 0 ) THEN
5741         WRITE(9,*) 'Error MPI_AllReduce8:', ierr, pemitlwl, pemitlw
5742         FLUSH(9)
5743     ENDIF
5744     CALL MPI_ALLREDUCE( emiss_sum_surfl, emiss_sum_surf, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5745     IF ( ierr /= 0 ) THEN
5746         WRITE(9,*) 'Error MPI_AllReduce9:', ierr, emiss_sum_surfl, emiss_sum_surf
5747         FLUSH(9)
5748     ENDIF
5749     CALL MPI_ALLREDUCE( area_surfl, area_surf, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5750     IF ( ierr /= 0 ) THEN
5751         WRITE(9,*) 'Error MPI_AllReduce10:', ierr, area_surfl, area_surf
5752         FLUSH(9)
5753     ENDIF
5754#else
5755     pinsw = pinswl
5756     pinlw = pinlwl
5757     pabssw = pabsswl
5758     pabslw = pabslwl
5759     pemitlw = pemitlwl
5760     emiss_sum_surf = emiss_sum_surfl
5761     area_surf = area_surfl
5762#endif
5763
5764!--  (1) albedo
5765     IF ( pinsw /= 0.0_wp )  &
5766          albedo_urb = (pinsw - pabssw) / pinsw
5767!--  (2) average emmsivity
5768     IF ( area_surf /= 0.0_wp ) &
5769          emissivity_urb = emiss_sum_surf / area_surf
5770!
5771!--  Temporally comment out calculation of effective radiative temperature.
5772!--  See below for more explanation.
5773!--  (3) temperature
5774!--   first we calculate an effective horizontal area to account for
5775!--   the effect of vertical surfaces (which contributes to LW emission)
5776!--   We simply use the ratio of the total LW to the incoming LW flux
5777      area_hor = pinlw/rad_lw_in_diff(nyn,nxl)
5778      t_rad_urb = ( (pemitlw - pabslw + emissivity_urb*pinlw) / &
5779           (emissivity_urb*sigma_sb * area_hor) )**0.25_wp
5780
5781    CONTAINS
5782
5783!------------------------------------------------------------------------------!
5784!> Calculates radiation absorbed by box with given size and LAD.
5785!>
5786!> Simulates resol**2 rays (by equally spacing a bounding horizontal square
5787!> conatining all possible rays that would cross the box) and calculates
5788!> average transparency per ray. Returns fraction of absorbed radiation flux
5789!> and area for which this fraction is effective.
5790!------------------------------------------------------------------------------!
5791    PURE SUBROUTINE box_absorb(boxsize, resol, dens, uvec, area, absorb)
5792       IMPLICIT NONE
5793
5794       REAL(wp), DIMENSION(3), INTENT(in) :: &
5795            boxsize, &      !< z, y, x size of box in m
5796            uvec            !< z, y, x unit vector of incoming flux
5797       INTEGER(iwp), INTENT(in) :: &
5798            resol           !< No. of rays in x and y dimensions
5799       REAL(wp), INTENT(in) :: &
5800            dens            !< box density (e.g. Leaf Area Density)
5801       REAL(wp), INTENT(out) :: &
5802            area, &         !< horizontal area for flux absorbtion
5803            absorb          !< fraction of absorbed flux
5804       REAL(wp) :: &
5805            xshift, yshift, &
5806            xmin, xmax, ymin, ymax, &
5807            xorig, yorig, &
5808            dx1, dy1, dz1, dx2, dy2, dz2, &
5809            crdist, &
5810            transp
5811       INTEGER(iwp) :: &
5812            i, j
5813
5814       xshift = uvec(3) / uvec(1) * boxsize(1)
5815       xmin = min(0._wp, -xshift)
5816       xmax = boxsize(3) + max(0._wp, -xshift)
5817       yshift = uvec(2) / uvec(1) * boxsize(1)
5818       ymin = min(0._wp, -yshift)
5819       ymax = boxsize(2) + max(0._wp, -yshift)
5820
5821       transp = 0._wp
5822       DO i = 1, resol
5823          xorig = xmin + (xmax-xmin) * (i-.5_wp) / resol
5824          DO j = 1, resol
5825             yorig = ymin + (ymax-ymin) * (j-.5_wp) / resol
5826
5827             dz1 = 0._wp
5828             dz2 = boxsize(1)/uvec(1)
5829
5830             IF ( uvec(2) > 0._wp )  THEN
5831                dy1 = -yorig             / uvec(2) !< crossing with y=0
5832                dy2 = (boxsize(2)-yorig) / uvec(2) !< crossing with y=boxsize(2)
5833             ELSE !uvec(2)==0
5834                dy1 = -huge(1._wp)
5835                dy2 = huge(1._wp)
5836             ENDIF
5837
5838             IF ( uvec(3) > 0._wp )  THEN
5839                dx1 = -xorig             / uvec(3) !< crossing with x=0
5840                dx2 = (boxsize(3)-xorig) / uvec(3) !< crossing with x=boxsize(3)
5841             ELSE !uvec(3)==0
5842                dx1 = -huge(1._wp)
5843                dx2 = huge(1._wp)
5844             ENDIF
5845
5846             crdist = max(0._wp, (min(dz2, dy2, dx2) - max(dz1, dy1, dx1)))
5847             transp = transp + exp(-ext_coef * dens * crdist)
5848          ENDDO
5849       ENDDO
5850       transp = transp / resol**2
5851       area = (boxsize(3)+xshift)*(boxsize(2)+yshift)
5852       absorb = 1._wp - transp
5853
5854    END SUBROUTINE box_absorb
5855
5856!------------------------------------------------------------------------------!
5857! Description:
5858! ------------
5859!> This subroutine splits direct and diffusion dw radiation
5860!> It sould not be called in case the radiation model already does it
5861!> It follows Boland, Ridley & Brown (2008)
5862!------------------------------------------------------------------------------!
5863    SUBROUTINE calc_diffusion_radiation 
5864   
5865        REAL(wp), PARAMETER                          :: lowest_solarUp = 0.1_wp  !< limit the sun elevation to protect stability of the calculation
5866        INTEGER(iwp)                                 :: i, j
5867        REAL(wp)                                     ::  year_angle              !< angle
5868        REAL(wp)                                     ::  etr                     !< extraterestrial radiation
5869        REAL(wp)                                     ::  corrected_solarUp       !< corrected solar up radiation
5870        REAL(wp)                                     ::  horizontalETR           !< horizontal extraterestrial radiation
5871        REAL(wp)                                     ::  clearnessIndex          !< clearness index
5872        REAL(wp)                                     ::  diff_frac               !< diffusion fraction of the radiation
5873
5874       
5875!--     Calculate current day and time based on the initial values and simulation time
5876        year_angle = ( (day_of_year_init * 86400) + time_utc_init              &
5877                        + time_since_reference_point )  * d_seconds_year       &
5878                        * 2.0_wp * pi
5879       
5880        etr = solar_constant * (1.00011_wp +                                   &
5881                          0.034221_wp * cos(year_angle) +                      &
5882                          0.001280_wp * sin(year_angle) +                      &
5883                          0.000719_wp * cos(2.0_wp * year_angle) +             &
5884                          0.000077_wp * sin(2.0_wp * year_angle))
5885       
5886!--   
5887!--     Under a very low angle, we keep extraterestrial radiation at
5888!--     the last small value, therefore the clearness index will be pushed
5889!--     towards 0 while keeping full continuity.
5890!--   
5891        IF ( cos_zenith <= lowest_solarUp )  THEN
5892            corrected_solarUp = lowest_solarUp
5893        ELSE
5894            corrected_solarUp = cos_zenith
5895        ENDIF
5896       
5897        horizontalETR = etr * corrected_solarUp
5898       
5899        DO i = nxl, nxr
5900            DO j = nys, nyn
5901                clearnessIndex = rad_sw_in(0,j,i) / horizontalETR
5902                diff_frac = 1.0_wp / (1.0_wp + exp(-5.0033_wp + 8.6025_wp * clearnessIndex))
5903                rad_sw_in_diff(j,i) = rad_sw_in(0,j,i) * diff_frac
5904                rad_sw_in_dir(j,i)  = rad_sw_in(0,j,i) * (1.0_wp - diff_frac)
5905                rad_lw_in_diff(j,i) = rad_lw_in(0,j,i)
5906            ENDDO
5907        ENDDO
5908       
5909    END SUBROUTINE calc_diffusion_radiation
5910
5911
5912 END SUBROUTINE radiation_interaction
5913   
5914!------------------------------------------------------------------------------!
5915! Description:
5916! ------------
5917!> This subroutine initializes structures needed for radiative transfer
5918!> model. This model calculates transformation processes of the
5919!> radiation inside urban and land canopy layer. The module includes also
5920!> the interaction of the radiation with the resolved plant canopy.
5921!>
5922!> For more info. see Resler et al. 2017
5923!>
5924!> The new version 2.0 was radically rewriten, the discretization scheme
5925!> has been changed. This new version significantly improves effectivity
5926!> of the paralelization and the scalability of the model.
5927!>
5928!------------------------------------------------------------------------------!
5929    SUBROUTINE radiation_interaction_init
5930
5931       USE control_parameters,                                                 &
5932           ONLY:  dz_stretch_level_start
5933           
5934       USE netcdf_data_input_mod,                                              &
5935           ONLY:  leaf_area_density_f
5936
5937       USE plant_canopy_model_mod,                                             &
5938           ONLY:  pch_index, lad_s
5939
5940       IMPLICIT NONE
5941
5942       INTEGER(iwp) :: i, j, k, l, m, d
5943       INTEGER(iwp) :: k_topo     !< vertical index indicating topography top for given (j,i)
5944       INTEGER(iwp) :: nzptl, nzubl, nzutl, isurf, ipcgb, imrt
5945       REAL(wp)     :: mrl
5946#if defined( __parallel )
5947       INTEGER(iwp), DIMENSION(:), POINTER, SAVE ::  gridsurf_rma   !< fortran pointer, but lower bounds are 1
5948       TYPE(c_ptr)                               ::  gridsurf_rma_p !< allocated c pointer
5949       INTEGER(iwp)                              ::  minfo          !< MPI RMA window info handle
5950#endif
5951
5952!
5953!--     precalculate face areas for different face directions using normal vector
5954        DO d = 0, nsurf_type
5955            facearea(d) = 1._wp
5956            IF ( idir(d) == 0 ) facearea(d) = facearea(d) * dx
5957            IF ( jdir(d) == 0 ) facearea(d) = facearea(d) * dy
5958            IF ( kdir(d) == 0 ) facearea(d) = facearea(d) * dz(1)
5959        ENDDO
5960!
5961!--    Find nz_urban_b, nz_urban_t, nz_urban via wall_flag_0 array (nzb_s_inner will be
5962!--    removed later). The following contruct finds the lowest / largest index
5963!--    for any upward-facing wall (see bit 12).
5964       nzubl = MINVAL( get_topography_top_index( 's' ) )
5965       nzutl = MAXVAL( get_topography_top_index( 's' ) )
5966
5967       nzubl = MAX( nzubl, nzb )
5968
5969       IF ( plant_canopy )  THEN
5970!--        allocate needed arrays
5971           ALLOCATE( pct(nys:nyn,nxl:nxr) )
5972           ALLOCATE( pch(nys:nyn,nxl:nxr) )
5973
5974!--        calculate plant canopy height
5975           npcbl = 0
5976           pct   = 0
5977           pch   = 0
5978           DO i = nxl, nxr
5979               DO j = nys, nyn
5980!
5981!--                Find topography top index
5982                   k_topo = get_topography_top_index_ji( j, i, 's' )
5983
5984                   DO k = nzt+1, 0, -1
5985                       IF ( lad_s(k,j,i) /= 0.0_wp )  THEN
5986!--                        we are at the top of the pcs
5987                           pct(j,i) = k + k_topo
5988                           pch(j,i) = k
5989                           npcbl = npcbl + pch(j,i)
5990                           EXIT
5991                       ENDIF
5992                   ENDDO
5993               ENDDO
5994           ENDDO
5995
5996           nzutl = MAX( nzutl, MAXVAL( pct ) )
5997           nzptl = MAXVAL( pct )
5998!--        code of plant canopy model uses parameter pch_index
5999!--        we need to setup it here to right value
6000!--        (pch_index, lad_s and other arrays in PCM are defined flat)
6001           pch_index = MERGE( leaf_area_density_f%nz - 1, MAXVAL( pch ),       &
6002                              leaf_area_density_f%from_file )
6003
6004           prototype_lad = MAXVAL( lad_s ) * .9_wp  !< better be *1.0 if lad is either 0 or maxval(lad) everywhere
6005           IF ( prototype_lad <= 0._wp ) prototype_lad = .3_wp
6006           !WRITE(message_string, '(a,f6.3)') 'Precomputing effective box optical ' &
6007           !    // 'depth using prototype leaf area density = ', prototype_lad
6008           !CALL message('radiation_interaction_init', 'PA0520', 0, 0, -1, 6, 0)
6009       ENDIF
6010
6011       nzutl = MIN( nzutl + nzut_free, nzt )
6012
6013#if defined( __parallel )
6014       CALL MPI_AllReduce(nzubl, nz_urban_b, 1, MPI_INTEGER, MPI_MIN, comm2d, ierr )
6015       IF ( ierr /= 0 ) THEN
6016           WRITE(9,*) 'Error MPI_AllReduce11:', ierr, nzubl, nz_urban_b
6017           FLUSH(9)
6018       ENDIF
6019       CALL MPI_AllReduce(nzutl, nz_urban_t, 1, MPI_INTEGER, MPI_MAX, comm2d, ierr )
6020       IF ( ierr /= 0 ) THEN
6021           WRITE(9,*) 'Error MPI_AllReduce12:', ierr, nzutl, nz_urban_t
6022           FLUSH(9)
6023       ENDIF
6024       CALL MPI_AllReduce(nzptl, nz_plant_t, 1, MPI_INTEGER, MPI_MAX, comm2d, ierr )
6025       IF ( ierr /= 0 ) THEN
6026           WRITE(9,*) 'Error MPI_AllReduce13:', ierr, nzptl, nz_plant_t
6027           FLUSH(9)
6028       ENDIF
6029#else
6030       nz_urban_b = nzubl
6031       nz_urban_t = nzutl
6032       nz_plant_t = nzptl
6033#endif
6034!
6035!--    Stretching (non-uniform grid spacing) is not considered in the radiation
6036!--    model. Therefore, vertical stretching has to be applied above the area
6037!--    where the parts of the radiation model which assume constant grid spacing
6038!--    are active. ABS (...) is required because the default value of
6039!--    dz_stretch_level_start is -9999999.9_wp (negative).
6040       IF ( ABS( dz_stretch_level_start(1) ) <= zw(nz_urban_t) ) THEN
6041          WRITE( message_string, * ) 'The lowest level where vertical ',       &
6042                                     'stretching is applied have to be ',      &
6043                                     'greater than ', zw(nz_urban_t)
6044          CALL message( 'radiation_interaction_init', 'PA0496', 1, 2, 0, 6, 0 )
6045       ENDIF 
6046!
6047!--    global number of urban and plant layers
6048       nz_urban = nz_urban_t - nz_urban_b + 1
6049       nz_plant = nz_plant_t - nz_urban_b + 1
6050!
6051!--    check max_raytracing_dist relative to urban surface layer height
6052       mrl = 2.0_wp * nz_urban * dz(1)
6053!--    set max_raytracing_dist to double the urban surface layer height, if not set
6054       IF ( max_raytracing_dist == -999.0_wp ) THEN
6055          max_raytracing_dist = mrl
6056       ENDIF
6057!--    check if max_raytracing_dist set too low (here we only warn the user. Other
6058!      option is to correct the value again to double the urban surface layer height)
6059       IF ( max_raytracing_dist  <  mrl ) THEN
6060          WRITE(message_string, '(a,f6.1)') 'Max_raytracing_dist is set less than ', &
6061               'double the urban surface layer height, i.e. ', mrl
6062          CALL message('radiation_interaction_init', 'PA0521', 0, 0, -1, 6, 0)
6063       ENDIF
6064!        IF ( max_raytracing_dist <= mrl ) THEN
6065!           IF ( max_raytracing_dist /= -999.0_wp ) THEN
6066! !--          max_raytracing_dist too low
6067!              WRITE(message_string, '(a,f6.1)') 'Max_raytracing_dist too low, ' &
6068!                    // 'override to value ', mrl
6069!              CALL message('radiation_interaction_init', 'PA0521', 0, 0, -1, 6, 0)
6070!           ENDIF
6071!           max_raytracing_dist = mrl
6072!        ENDIF
6073!
6074!--    allocate urban surfaces grid
6075!--    calc number of surfaces in local proc
6076       CALL location_message( '    calculation of indices for surfaces', .TRUE. )
6077       nsurfl = 0
6078!
6079!--    Number of horizontal surfaces including land- and roof surfaces in both USM and LSM. Note that
6080!--    All horizontal surface elements are already counted in surface_mod.
6081       startland = 1
6082       nsurfl    = surf_usm_h%ns + surf_lsm_h%ns
6083       endland   = nsurfl
6084       nlands    = endland - startland + 1
6085
6086!
6087!--    Number of vertical surfaces in both USM and LSM. Note that all vertical surface elements are
6088!--    already counted in surface_mod.
6089       startwall = nsurfl+1
6090       DO  i = 0,3
6091          nsurfl = nsurfl + surf_usm_v(i)%ns + surf_lsm_v(i)%ns
6092       ENDDO
6093       endwall = nsurfl
6094       nwalls  = endwall - startwall + 1
6095       dirstart = (/ startland, startwall, startwall, startwall, startwall /)
6096       dirend = (/ endland, endwall, endwall, endwall, endwall /)
6097
6098!--    fill gridpcbl and pcbl
6099       IF ( npcbl > 0 )  THEN
6100           ALLOCATE( pcbl(iz:ix, 1:npcbl) )
6101           ALLOCATE( gridpcbl(nz_urban_b:nz_plant_t,nys:nyn,nxl:nxr) )
6102           pcbl = -1
6103           gridpcbl(:,:,:) = 0
6104           ipcgb = 0
6105           DO i = nxl, nxr
6106               DO j = nys, nyn
6107!
6108!--                Find topography top index
6109                   k_topo = get_topography_top_index_ji( j, i, 's' )
6110
6111                   DO k = k_topo + 1, pct(j,i)
6112                       ipcgb = ipcgb + 1
6113                       gridpcbl(k,j,i) = ipcgb
6114                       pcbl(:,ipcgb) = (/ k, j, i /)
6115                   ENDDO
6116               ENDDO
6117           ENDDO
6118           ALLOCATE( pcbinsw( 1:npcbl ) )
6119           ALLOCATE( pcbinswdir( 1:npcbl ) )
6120           ALLOCATE( pcbinswdif( 1:npcbl ) )
6121           ALLOCATE( pcbinlw( 1:npcbl ) )
6122       ENDIF
6123
6124!
6125!--    Fill surfl (the ordering of local surfaces given by the following
6126!--    cycles must not be altered, certain file input routines may depend
6127!--    on it).
6128!
6129!--    We allocate the array as linear and then use a two-dimensional pointer
6130!--    into it, because some MPI implementations crash with 2D-allocated arrays.
6131       ALLOCATE(surfl_linear(nidx_surf*nsurfl))
6132       surfl(1:nidx_surf,1:nsurfl) => surfl_linear(1:nidx_surf*nsurfl)
6133       isurf = 0
6134       IF ( rad_angular_discretization )  THEN
6135!
6136!--       Allocate and fill the reverse indexing array gridsurf
6137#if defined( __parallel )
6138!
6139!--       raytrace_mpi_rma is asserted
6140
6141          CALL MPI_Info_create(minfo, ierr)
6142          IF ( ierr /= 0 ) THEN
6143              WRITE(9,*) 'Error MPI_Info_create1:', ierr
6144              FLUSH(9)
6145          ENDIF
6146          CALL MPI_Info_set(minfo, 'accumulate_ordering', '', ierr)
6147          IF ( ierr /= 0 ) THEN
6148              WRITE(9,*) 'Error MPI_Info_set1:', ierr
6149              FLUSH(9)
6150          ENDIF
6151          CALL MPI_Info_set(minfo, 'accumulate_ops', 'same_op', ierr)
6152          IF ( ierr /= 0 ) THEN
6153              WRITE(9,*) 'Error MPI_Info_set2:', ierr
6154              FLUSH(9)
6155          ENDIF
6156          CALL MPI_Info_set(minfo, 'same_size', 'true', ierr)
6157          IF ( ierr /= 0 ) THEN
6158              WRITE(9,*) 'Error MPI_Info_set3:', ierr
6159              FLUSH(9)
6160          ENDIF
6161          CALL MPI_Info_set(minfo, 'same_disp_unit', 'true', ierr)
6162          IF ( ierr /= 0 ) THEN
6163              WRITE(9,*) 'Error MPI_Info_set4:', ierr
6164              FLUSH(9)
6165          ENDIF
6166
6167          CALL MPI_Win_allocate(INT(STORAGE_SIZE(1_iwp)/8*nsurf_type_u*nz_urban*nny*nnx, &
6168                                    kind=MPI_ADDRESS_KIND), STORAGE_SIZE(1_iwp)/8,  &
6169                                minfo, comm2d, gridsurf_rma_p, win_gridsurf, ierr)
6170          IF ( ierr /= 0 ) THEN
6171              WRITE(9,*) 'Error MPI_Win_allocate1:', ierr, &
6172                 INT(STORAGE_SIZE(1_iwp)/8*nsurf_type_u*nz_urban*nny*nnx,kind=MPI_ADDRESS_KIND), &
6173                 STORAGE_SIZE(1_iwp)/8, win_gridsurf
6174              FLUSH(9)
6175          ENDIF
6176
6177          CALL MPI_Info_free(minfo, ierr)
6178          IF ( ierr /= 0 ) THEN
6179              WRITE(9,*) 'Error MPI_Info_free1:', ierr
6180              FLUSH(9)
6181          ENDIF
6182
6183!
6184!--       On Intel compilers, calling c_f_pointer to transform a C pointer
6185!--       directly to a multi-dimensional Fotran pointer leads to strange
6186!--       errors on dimension boundaries. However, transforming to a 1D
6187!--       pointer and then redirecting a multidimensional pointer to it works
6188!--       fine.
6189          CALL c_f_pointer(gridsurf_rma_p, gridsurf_rma, (/ nsurf_type_u*nz_urban*nny*nnx /))
6190          gridsurf(0:nsurf_type_u-1, nz_urban_b:nz_urban_t, nys:nyn, nxl:nxr) =>                &
6191                     gridsurf_rma(1:nsurf_type_u*nz_urban*nny*nnx)
6192#else
6193          ALLOCATE(gridsurf(0:nsurf_type_u-1,nz_urban_b:nz_urban_t,nys:nyn,nxl:nxr) )
6194#endif
6195          gridsurf(:,:,:,:) = -999
6196       ENDIF
6197
6198!--    add horizontal surface elements (land and urban surfaces)
6199!--    TODO: add urban overhanging surfaces (idown_u)
6200       DO i = nxl, nxr
6201           DO j = nys, nyn
6202              DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
6203                 k = surf_usm_h%k(m)
6204                 isurf = isurf + 1
6205                 surfl(:,isurf) = (/iup_u,k,j,i,m/)
6206                 IF ( rad_angular_discretization ) THEN
6207                    gridsurf(iup_u,k,j,i) = isurf
6208                 ENDIF
6209              ENDDO
6210
6211              DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6212                 k = surf_lsm_h%k(m)
6213                 isurf = isurf + 1
6214                 surfl(:,isurf) = (/iup_l,k,j,i,m/)
6215                 IF ( rad_angular_discretization ) THEN
6216                    gridsurf(iup_u,k,j,i) = isurf
6217                 ENDIF
6218              ENDDO
6219
6220           ENDDO
6221       ENDDO
6222
6223!--    add vertical surface elements (land and urban surfaces)
6224!--    TODO: remove the hard coding of l = 0 to l = idirection
6225       DO i = nxl, nxr
6226           DO j = nys, nyn
6227              l = 0
6228              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6229                 k = surf_usm_v(l)%k(m)
6230                 isurf = isurf + 1
6231                 surfl(:,isurf) = (/inorth_u,k,j,i,m/)
6232                 IF ( rad_angular_discretization ) THEN
6233                    gridsurf(inorth_u,k,j,i) = isurf
6234                 ENDIF
6235              ENDDO
6236              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6237                 k = surf_lsm_v(l)%k(m)
6238                 isurf = isurf + 1
6239                 surfl(:,isurf) = (/inorth_l,k,j,i,m/)
6240                 IF ( rad_angular_discretization ) THEN
6241                    gridsurf(inorth_u,k,j,i) = isurf
6242                 ENDIF
6243              ENDDO
6244
6245              l = 1
6246              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6247                 k = surf_usm_v(l)%k(m)
6248                 isurf = isurf + 1
6249                 surfl(:,isurf) = (/isouth_u,k,j,i,m/)
6250                 IF ( rad_angular_discretization ) THEN
6251                    gridsurf(isouth_u,k,j,i) = isurf
6252                 ENDIF
6253              ENDDO
6254              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6255                 k = surf_lsm_v(l)%k(m)
6256                 isurf = isurf + 1
6257                 surfl(:,isurf) = (/isouth_l,k,j,i,m/)
6258                 IF ( rad_angular_discretization ) THEN
6259                    gridsurf(isouth_u,k,j,i) = isurf
6260                 ENDIF
6261              ENDDO
6262
6263              l = 2
6264              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6265                 k = surf_usm_v(l)%k(m)
6266                 isurf = isurf + 1
6267                 surfl(:,isurf) = (/ieast_u,k,j,i,m/)
6268                 IF ( rad_angular_discretization ) THEN
6269                    gridsurf(ieast_u,k,j,i) = isurf
6270                 ENDIF
6271              ENDDO
6272              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6273                 k = surf_lsm_v(l)%k(m)
6274                 isurf = isurf + 1
6275                 surfl(:,isurf) = (/ieast_l,k,j,i,m/)
6276                 IF ( rad_angular_discretization ) THEN
6277                    gridsurf(ieast_u,k,j,i) = isurf
6278                 ENDIF
6279              ENDDO
6280
6281              l = 3
6282              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6283                 k = surf_usm_v(l)%k(m)
6284                 isurf = isurf + 1
6285                 surfl(:,isurf) = (/iwest_u,k,j,i,m/)
6286                 IF ( rad_angular_discretization ) THEN
6287                    gridsurf(iwest_u,k,j,i) = isurf
6288                 ENDIF
6289              ENDDO
6290              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6291                 k = surf_lsm_v(l)%k(m)
6292                 isurf = isurf + 1
6293                 surfl(:,isurf) = (/iwest_l,k,j,i,m/)
6294                 IF ( rad_angular_discretization ) THEN
6295                    gridsurf(iwest_u,k,j,i) = isurf
6296                 ENDIF
6297              ENDDO
6298           ENDDO
6299       ENDDO
6300!
6301!--    Add local MRT boxes for specified number of levels
6302       nmrtbl = 0
6303       IF ( mrt_nlevels > 0 )  THEN
6304          DO  i = nxl, nxr
6305             DO  j = nys, nyn
6306                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
6307!
6308!--                Skip roof if requested
6309                   IF ( mrt_skip_roof  .AND.  surf_usm_h%isroof_surf(m) )  CYCLE
6310!
6311!--                Cycle over specified no of levels
6312                   nmrtbl = nmrtbl + mrt_nlevels
6313                ENDDO
6314!
6315!--             Dtto for LSM
6316                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6317                   nmrtbl = nmrtbl + mrt_nlevels
6318                ENDDO
6319             ENDDO
6320          ENDDO
6321
6322          ALLOCATE( mrtbl(iz:ix,nmrtbl), mrtsky(nmrtbl), mrtskyt(nmrtbl), &
6323                    mrtinsw(nmrtbl), mrtinlw(nmrtbl), mrt(nmrtbl) )
6324
6325          imrt = 0
6326          DO  i = nxl, nxr
6327             DO  j = nys, nyn
6328                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
6329!
6330!--                Skip roof if requested
6331                   IF ( mrt_skip_roof  .AND.  surf_usm_h%isroof_surf(m) )  CYCLE
6332!
6333!--                Cycle over specified no of levels
6334                   l = surf_usm_h%k(m)
6335                   DO  k = l, l + mrt_nlevels - 1
6336                      imrt = imrt + 1
6337                      mrtbl(:,imrt) = (/k,j,i/)
6338                   ENDDO
6339                ENDDO
6340!
6341!--             Dtto for LSM
6342                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6343                   l = surf_lsm_h%k(m)
6344                   DO  k = l, l + mrt_nlevels - 1
6345                      imrt = imrt + 1
6346                      mrtbl(:,imrt) = (/k,j,i/)
6347                   ENDDO
6348                ENDDO
6349             ENDDO
6350          ENDDO
6351       ENDIF
6352
6353!
6354!--    broadband albedo of the land, roof and wall surface
6355!--    for domain border and sky set artifically to 1.0
6356!--    what allows us to calculate heat flux leaving over
6357!--    side and top borders of the domain
6358       ALLOCATE ( albedo_surf(nsurfl) )
6359       albedo_surf = 1.0_wp
6360!
6361!--    Also allocate further array for emissivity with identical order of
6362!--    surface elements as radiation arrays.
6363       ALLOCATE ( emiss_surf(nsurfl)  )
6364
6365
6366!
6367!--    global array surf of indices of surfaces and displacement index array surfstart
6368       ALLOCATE(nsurfs(0:numprocs-1))
6369
6370#if defined( __parallel )
6371       CALL MPI_Allgather(nsurfl,1,MPI_INTEGER,nsurfs,1,MPI_INTEGER,comm2d,ierr)
6372       IF ( ierr /= 0 ) THEN
6373         WRITE(9,*) 'Error MPI_AllGather1:', ierr, nsurfl, nsurfs
6374         FLUSH(9)
6375     ENDIF
6376
6377#else
6378       nsurfs(0) = nsurfl
6379#endif
6380       ALLOCATE(surfstart(0:numprocs))
6381       k = 0
6382       DO i=0,numprocs-1
6383           surfstart(i) = k
6384           k = k+nsurfs(i)
6385       ENDDO
6386       surfstart(numprocs) = k
6387       nsurf = k
6388!
6389!--    We allocate the array as linear and then use a two-dimensional pointer
6390!--    into it, because some MPI implementations crash with 2D-allocated arrays.
6391       ALLOCATE(surf_linear(nidx_surf*nsurf))
6392       surf(1:nidx_surf,1:nsurf) => surf_linear(1:nidx_surf*nsurf)
6393
6394#if defined( __parallel )
6395       CALL MPI_AllGatherv(surfl_linear, nsurfl*nidx_surf, MPI_INTEGER,    &
6396                           surf_linear, nsurfs*nidx_surf,                  &
6397                           surfstart(0:numprocs-1)*nidx_surf, MPI_INTEGER, &
6398                           comm2d, ierr)
6399       IF ( ierr /= 0 ) THEN
6400           WRITE(9,*) 'Error MPI_AllGatherv4:', ierr, SIZE(surfl_linear),    &
6401                      nsurfl*nidx_surf, SIZE(surf_linear), nsurfs*nidx_surf, &
6402                      surfstart(0:numprocs-1)*nidx_surf
6403           FLUSH(9)
6404       ENDIF
6405#else
6406       surf = surfl
6407#endif
6408
6409!--
6410!--    allocation of the arrays for direct and diffusion radiation
6411       CALL location_message( '    allocation of radiation arrays', .TRUE. )
6412!--    rad_sw_in, rad_lw_in are computed in radiation model,
6413!--    splitting of direct and diffusion part is done
6414!--    in calc_diffusion_radiation for now
6415
6416       ALLOCATE( rad_sw_in_dir(nysg:nyng,nxlg:nxrg) )
6417       ALLOCATE( rad_sw_in_diff(nysg:nyng,nxlg:nxrg) )
6418       ALLOCATE( rad_lw_in_diff(nysg:nyng,nxlg:nxrg) )
6419       rad_sw_in_dir  = 0.0_wp
6420       rad_sw_in_diff = 0.0_wp
6421       rad_lw_in_diff = 0.0_wp
6422
6423!--    allocate radiation arrays
6424       ALLOCATE( surfins(nsurfl) )
6425       ALLOCATE( surfinl(nsurfl) )
6426       ALLOCATE( surfinsw(nsurfl) )
6427       ALLOCATE( surfinlw(nsurfl) )
6428       ALLOCATE( surfinswdir(nsurfl) )
6429       ALLOCATE( surfinswdif(nsurfl) )
6430       ALLOCATE( surfinlwdif(nsurfl) )
6431       ALLOCATE( surfoutsl(nsurfl) )
6432       ALLOCATE( surfoutll(nsurfl) )
6433       ALLOCATE( surfoutsw(nsurfl) )
6434       ALLOCATE( surfoutlw(nsurfl) )
6435       ALLOCATE( surfouts(nsurf) )
6436       ALLOCATE( surfoutl(nsurf) )
6437       ALLOCATE( surfinlg(nsurf) )
6438       ALLOCATE( skyvf(nsurfl) )
6439       ALLOCATE( skyvft(nsurfl) )
6440       ALLOCATE( surfemitlwl(nsurfl) )
6441
6442!
6443!--    In case of average_radiation, aggregated surface albedo and emissivity,
6444!--    also set initial value for t_rad_urb.
6445!--    For now set an arbitrary initial value.
6446       IF ( average_radiation )  THEN
6447          albedo_urb = 0.1_wp
6448          emissivity_urb = 0.9_wp
6449          t_rad_urb = pt_surface
6450       ENDIF
6451
6452    END SUBROUTINE radiation_interaction_init
6453
6454!------------------------------------------------------------------------------!
6455! Description:
6456! ------------
6457!> Calculates shape view factors (SVF), plant sink canopy factors (PCSF),
6458!> sky-view factors, discretized path for direct solar radiation, MRT factors
6459!> and other preprocessed data needed for radiation_interaction.
6460!------------------------------------------------------------------------------!
6461    SUBROUTINE radiation_calc_svf
6462   
6463        IMPLICIT NONE
6464       
6465        INTEGER(iwp)                                  :: i, j, k, d, ip, jp
6466        INTEGER(iwp)                                  :: isvf, ksvf, icsf, kcsf, npcsfl, isvf_surflt, imrt, imrtf, ipcgb
6467        INTEGER(iwp)                                  :: sd, td
6468        INTEGER(iwp)                                  :: iaz, izn      !< azimuth, zenith counters
6469        INTEGER(iwp)                                  :: naz, nzn      !< azimuth, zenith num of steps
6470        REAL(wp)                                      :: az0, zn0      !< starting azimuth/zenith
6471        REAL(wp)                                      :: azs, zns      !< azimuth/zenith cycle step
6472        REAL(wp)                                      :: az1, az2      !< relative azimuth of section borders
6473        REAL(wp)                                      :: azmid         !< ray (center) azimuth
6474        REAL(wp)                                      :: yxlen         !< |yxdir|
6475        REAL(wp), DIMENSION(2)                        :: yxdir         !< y,x *unit* vector of ray direction (in grid units)
6476        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zdirs         !< directions in z (tangent of elevation)
6477        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zcent         !< zenith angle centers
6478        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zbdry         !< zenith angle boundaries
6479        REAL(wp), DIMENSION(:), ALLOCATABLE           :: vffrac        !< view factor fractions for individual rays
6480        REAL(wp), DIMENSION(:), ALLOCATABLE           :: vffrac0       !< dtto (original values)
6481        REAL(wp), DIMENSION(:), ALLOCATABLE           :: ztransp       !< array of transparency in z steps
6482        INTEGER(iwp)                                  :: lowest_free_ray !< index into zdirs
6483        INTEGER(iwp), DIMENSION(:), ALLOCATABLE       :: itarget       !< face indices of detected obstacles
6484        INTEGER(iwp)                                  :: itarg0, itarg1
6485
6486        INTEGER(iwp)                                  :: udim
6487        INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET:: nzterrl_l
6488        INTEGER(iwp), DIMENSION(:,:), POINTER         :: nzterrl
6489        REAL(wp),     DIMENSION(:), ALLOCATABLE,TARGET:: csflt_l, pcsflt_l
6490        REAL(wp),     DIMENSION(:,:), POINTER         :: csflt, pcsflt
6491        INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET:: kcsflt_l,kpcsflt_l
6492        INTEGER(iwp), DIMENSION(:,:), POINTER         :: kcsflt,kpcsflt
6493        INTEGER(iwp), DIMENSION(:), ALLOCATABLE       :: icsflt,dcsflt,ipcsflt,dpcsflt
6494        REAL(wp), DIMENSION(3)                        :: uv
6495        LOGICAL                                       :: visible
6496        REAL(wp), DIMENSION(3)                        :: sa, ta          !< real coordinates z,y,x of source and target
6497        REAL(wp)                                      :: difvf           !< differential view factor
6498        REAL(wp)                                      :: transparency, rirrf, sqdist, svfsum
6499        INTEGER(iwp)                                  :: isurflt, isurfs, isurflt_prev
6500        INTEGER(idp)                                  :: ray_skip_maxdist, ray_skip_minval !< skipped raytracing counts
6501        INTEGER(iwp)                                  :: max_track_len !< maximum 2d track length
6502        INTEGER(iwp)                                  :: minfo
6503        REAL(wp), DIMENSION(:), POINTER, SAVE         :: lad_s_rma       !< fortran 1D pointer
6504        TYPE(c_ptr)                                   :: lad_s_rma_p     !< allocated c pointer
6505#if defined( __parallel )
6506        INTEGER(kind=MPI_ADDRESS_KIND)                :: size_lad_rma
6507#endif
6508!   
6509        INTEGER(iwp), DIMENSION(0:svfnorm_report_num) :: svfnorm_counts
6510        CHARACTER(200)                                :: msg
6511
6512!--     calculation of the SVF
6513        CALL location_message( '    calculation of SVF and CSF', .TRUE. )
6514        CALL radiation_write_debug_log('Start calculation of SVF and CSF')
6515
6516!--     initialize variables and temporary arrays for calculation of svf and csf
6517        nsvfl  = 0
6518        ncsfl  = 0
6519        nsvfla = gasize
6520        msvf   = 1
6521        ALLOCATE( asvf1(nsvfla) )
6522        asvf => asvf1
6523        IF ( plant_canopy )  THEN
6524            ncsfla = gasize
6525            mcsf   = 1
6526            ALLOCATE( acsf1(ncsfla) )
6527            acsf => acsf1
6528        ENDIF
6529        nmrtf = 0
6530        IF ( mrt_nlevels > 0 )  THEN
6531           nmrtfa = gasize
6532           mmrtf = 1
6533           ALLOCATE ( amrtf1(nmrtfa) )
6534           amrtf => amrtf1
6535        ENDIF
6536        ray_skip_maxdist = 0
6537        ray_skip_minval = 0
6538       
6539!--     initialize temporary terrain and plant canopy height arrays (global 2D array!)
6540        ALLOCATE( nzterr(0:(nx+1)*(ny+1)-1) )
6541#if defined( __parallel )
6542        !ALLOCATE( nzterrl(nys:nyn,nxl:nxr) )
6543        ALLOCATE( nzterrl_l((nyn-nys+1)*(nxr-nxl+1)) )
6544        nzterrl(nys:nyn,nxl:nxr) => nzterrl_l(1:(nyn-nys+1)*(nxr-nxl+1))
6545        nzterrl = get_topography_top_index( 's' )
6546        CALL MPI_AllGather( nzterrl_l, nnx*nny, MPI_INTEGER, &
6547                            nzterr, nnx*nny, MPI_INTEGER, comm2d, ierr )
6548        IF ( ierr /= 0 ) THEN
6549            WRITE(9,*) 'Error MPI_AllGather1:', ierr, SIZE(nzterrl_l), nnx*nny, &
6550                       SIZE(nzterr), nnx*nny
6551            FLUSH(9)
6552        ENDIF
6553        DEALLOCATE(nzterrl_l)
6554#else
6555        nzterr = RESHAPE( get_topography_top_index( 's' ), (/(nx+1)*(ny+1)/) )
6556#endif
6557        IF ( plant_canopy )  THEN
6558            ALLOCATE( plantt(0:(nx+1)*(ny+1)-1) )
6559            maxboxesg = nx + ny + nz_plant + 1
6560            max_track_len = nx + ny + 1
6561!--         temporary arrays storing values for csf calculation during raytracing
6562            ALLOCATE( boxes(3, maxboxesg) )
6563            ALLOCATE( crlens(maxboxesg) )
6564
6565#if defined( __parallel )
6566            CALL MPI_AllGather( pct, nnx*nny, MPI_INTEGER, &
6567                                plantt, nnx*nny, MPI_INTEGER, comm2d, ierr )
6568            IF ( ierr /= 0 ) THEN
6569                WRITE(9,*) 'Error MPI_AllGather2:', ierr, SIZE(pct), nnx*nny, &
6570                           SIZE(plantt), nnx*nny
6571                FLUSH(9)
6572            ENDIF
6573
6574!--         temporary arrays storing values for csf calculation during raytracing
6575            ALLOCATE( lad_ip(maxboxesg) )
6576            ALLOCATE( lad_disp(maxboxesg) )
6577
6578            IF ( raytrace_mpi_rma )  THEN
6579                ALLOCATE( lad_s_ray(maxboxesg) )
6580               
6581                ! set conditions for RMA communication
6582                CALL MPI_Info_create(minfo, ierr)
6583                IF ( ierr /= 0 ) THEN
6584                    WRITE(9,*) 'Error MPI_Info_create2:', ierr
6585                    FLUSH(9)
6586                ENDIF
6587                CALL MPI_Info_set(minfo, 'accumulate_ordering', '', ierr)
6588                IF ( ierr /= 0 ) THEN
6589                    WRITE(9,*) 'Error MPI_Info_set5:', ierr
6590                    FLUSH(9)
6591                ENDIF
6592                CALL MPI_Info_set(minfo, 'accumulate_ops', 'same_op', ierr)
6593                IF ( ierr /= 0 ) THEN
6594                    WRITE(9,*) 'Error MPI_Info_set6:', ierr
6595                    FLUSH(9)
6596                ENDIF
6597                CALL MPI_Info_set(minfo, 'same_size', 'true', ierr)
6598                IF ( ierr /= 0 ) THEN
6599                    WRITE(9,*) 'Error MPI_Info_set7:', ierr
6600                    FLUSH(9)
6601                ENDIF
6602                CALL MPI_Info_set(minfo, 'same_disp_unit', 'true', ierr)
6603                IF ( ierr /= 0 ) THEN
6604                    WRITE(9,*) 'Error MPI_Info_set8:', ierr
6605                    FLUSH(9)
6606                ENDIF
6607
6608!--             Allocate and initialize the MPI RMA window
6609!--             must be in accordance with allocation of lad_s in plant_canopy_model
6610!--             optimization of memory should be done
6611!--             Argument X of function STORAGE_SIZE(X) needs arbitrary REAL(wp) value, set to 1.0_wp for now
6612                size_lad_rma = STORAGE_SIZE(1.0_wp)/8*nnx*nny*nz_plant
6613                CALL MPI_Win_allocate(size_lad_rma, STORAGE_SIZE(1.0_wp)/8, minfo, comm2d, &
6614                                        lad_s_rma_p, win_lad, ierr)
6615                IF ( ierr /= 0 ) THEN
6616                    WRITE(9,*) 'Error MPI_Win_allocate2:', ierr, size_lad_rma, &
6617                                STORAGE_SIZE(1.0_wp)/8, win_lad
6618                    FLUSH(9)
6619                ENDIF
6620                CALL c_f_pointer(lad_s_rma_p, lad_s_rma, (/ nz_plant*nny*nnx /))
6621                sub_lad(nz_urban_b:nz_plant_t, nys:nyn, nxl:nxr) => lad_s_rma(1:nz_plant*nny*nnx)
6622            ELSE
6623                ALLOCATE(sub_lad(nz_urban_b:nz_plant_t, nys:nyn, nxl:nxr))
6624            ENDIF
6625#else
6626            plantt = RESHAPE( pct(nys:nyn,nxl:nxr), (/(nx+1)*(ny+1)/) )
6627            ALLOCATE(sub_lad(nz_urban_b:nz_plant_t, nys:nyn, nxl:nxr))
6628#endif
6629            plantt_max = MAXVAL(plantt)
6630            ALLOCATE( rt2_track(2, max_track_len), rt2_track_lad(nz_urban_b:plantt_max, max_track_len), &
6631                      rt2_track_dist(0:max_track_len), rt2_dist(plantt_max-nz_urban_b+2) )
6632
6633            sub_lad(:,:,:) = 0._wp
6634            DO i = nxl, nxr
6635                DO j = nys, nyn
6636                    k = get_topography_top_index_ji( j, i, 's' )
6637
6638                    sub_lad(k:nz_plant_t, j, i) = lad_s(0:nz_plant_t-k, j, i)
6639                ENDDO
6640            ENDDO
6641
6642#if defined( __parallel )
6643            IF ( raytrace_mpi_rma )  THEN
6644                CALL MPI_Info_free(minfo, ierr)
6645                IF ( ierr /= 0 ) THEN
6646                    WRITE(9,*) 'Error MPI_Info_free2:', ierr
6647                    FLUSH(9)
6648                ENDIF
6649                CALL MPI_Win_lock_all(0, win_lad, ierr)
6650                IF ( ierr /= 0 ) THEN
6651                    WRITE(9,*) 'Error MPI_Win_lock_all1:', ierr, win_lad
6652                    FLUSH(9)
6653                ENDIF
6654               
6655            ELSE
6656                ALLOCATE( sub_lad_g(0:(nx+1)*(ny+1)*nz_plant-1) )
6657                CALL MPI_AllGather( sub_lad, nnx*nny*nz_plant, MPI_REAL, &
6658                                    sub_lad_g, nnx*nny*nz_plant, MPI_REAL, comm2d, ierr )
6659                IF ( ierr /= 0 ) THEN
6660                    WRITE(9,*) 'Error MPI_AllGather3:', ierr, SIZE(sub_lad), &
6661                                nnx*nny*nz_plant, SIZE(sub_lad_g), nnx*nny*nz_plant
6662                    FLUSH(9)
6663                ENDIF
6664            ENDIF
6665#endif
6666        ENDIF
6667
6668!--     prepare the MPI_Win for collecting the surface indices
6669!--     from the reverse index arrays gridsurf from processors of target surfaces
6670#if defined( __parallel )
6671        IF ( rad_angular_discretization )  THEN
6672!
6673!--         raytrace_mpi_rma is asserted
6674            CALL MPI_Win_lock_all(0, win_gridsurf, ierr)
6675            IF ( ierr /= 0 ) THEN
6676                WRITE(9,*) 'Error MPI_Win_lock_all2:', ierr, win_gridsurf
6677                FLUSH(9)
6678            ENDIF
6679        ENDIF
6680#endif
6681
6682
6683        !--Directions opposite to face normals are not even calculated,
6684        !--they must be preset to 0
6685        !--
6686        dsitrans(:,:) = 0._wp
6687       
6688        DO isurflt = 1, nsurfl
6689!--         determine face centers
6690            td = surfl(id, isurflt)
6691            ta = (/ REAL(surfl(iz, isurflt), wp) - 0.5_wp * kdir(td),  &
6692                      REAL(surfl(iy, isurflt), wp) - 0.5_wp * jdir(td),  &
6693                      REAL(surfl(ix, isurflt), wp) - 0.5_wp * idir(td)  /)
6694
6695            !--Calculate sky view factor and raytrace DSI paths
6696            skyvf(isurflt) = 0._wp
6697            skyvft(isurflt) = 0._wp
6698
6699            !--Select a proper half-sphere for 2D raytracing
6700            SELECT CASE ( td )
6701               CASE ( iup_u, iup_l )
6702                  az0 = 0._wp
6703                  naz = raytrace_discrete_azims
6704                  azs = 2._wp * pi / REAL(naz, wp)
6705                  zn0 = 0._wp
6706                  nzn = raytrace_discrete_elevs / 2
6707                  zns = pi / 2._wp / REAL(nzn, wp)
6708               CASE ( isouth_u, isouth_l )
6709                  az0 = pi / 2._wp
6710                  naz = raytrace_discrete_azims / 2
6711                  azs = pi / REAL(naz, wp)
6712                  zn0 = 0._wp
6713                  nzn = raytrace_discrete_elevs
6714                  zns = pi / REAL(nzn, wp)
6715               CASE ( inorth_u, inorth_l )
6716                  az0 = - pi / 2._wp
6717                  naz = raytrace_discrete_azims / 2
6718                  azs = pi / REAL(naz, wp)
6719                  zn0 = 0._wp
6720                  nzn = raytrace_discrete_elevs
6721                  zns = pi / REAL(nzn, wp)
6722               CASE ( iwest_u, iwest_l )
6723                  az0 = pi
6724                  naz = raytrace_discrete_azims / 2
6725                  azs = pi / REAL(naz, wp)
6726                  zn0 = 0._wp
6727                  nzn = raytrace_discrete_elevs
6728                  zns = pi / REAL(nzn, wp)
6729               CASE ( ieast_u, ieast_l )
6730                  az0 = 0._wp
6731                  naz = raytrace_discrete_azims / 2
6732                  azs = pi / REAL(naz, wp)
6733                  zn0 = 0._wp
6734                  nzn = raytrace_discrete_elevs
6735                  zns = pi / REAL(nzn, wp)
6736               CASE DEFAULT
6737                  WRITE(message_string, *) 'ERROR: the surface type ', td,     &
6738                                           ' is not supported for calculating',&
6739                                           ' SVF'
6740                  CALL message( 'radiation_calc_svf', 'PA0488', 1, 2, 0, 6, 0 )
6741            END SELECT
6742
6743            ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), zbdry(0:nzn), vffrac(1:nzn*naz), &
6744                       ztransp(1:nzn*naz), itarget(1:nzn*naz) )   !FIXME allocate itarget only
6745                                                                  !in case of rad_angular_discretization
6746
6747            itarg0 = 1
6748            itarg1 = nzn
6749            zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
6750            zbdry(:) = (/( zn0+REAL(izn,wp)*zns, izn=0, nzn )/)
6751            IF ( td == iup_u  .OR.  td == iup_l )  THEN
6752               vffrac(1:nzn) = (COS(2 * zbdry(0:nzn-1)) - COS(2 * zbdry(1:nzn))) / 2._wp / REAL(naz, wp)
6753!
6754!--            For horizontal target, vf fractions are constant per azimuth
6755               DO iaz = 1, naz-1
6756                  vffrac(iaz*nzn+1:(iaz+1)*nzn) = vffrac(1:nzn)
6757               ENDDO
6758!--            sum of whole vffrac equals 1, verified
6759            ENDIF
6760!
6761!--         Calculate sky-view factor and direct solar visibility using 2D raytracing
6762            DO iaz = 1, naz
6763               azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
6764               IF ( td /= iup_u  .AND.  td /= iup_l )  THEN
6765                  az2 = REAL(iaz, wp) * azs - pi/2._wp
6766                  az1 = az2 - azs
6767                  !TODO precalculate after 1st line
6768                  vffrac(itarg0:itarg1) = (SIN(az2) - SIN(az1))               &
6769                              * (zbdry(1:nzn) - zbdry(0:nzn-1)                &
6770                                 + SIN(zbdry(0:nzn-1))*COS(zbdry(0:nzn-1))    &
6771                                 - SIN(zbdry(1:nzn))*COS(zbdry(1:nzn)))       &
6772                              / (2._wp * pi)
6773!--               sum of whole vffrac equals 1, verified
6774               ENDIF
6775               yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
6776               yxlen = SQRT(SUM(yxdir(:)**2))
6777               zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
6778               yxdir(:) = yxdir(:) / yxlen
6779
6780               CALL raytrace_2d(ta, yxdir, nzn, zdirs,                        &
6781                                    surfstart(myid) + isurflt, facearea(td),  &
6782                                    vffrac(itarg0:itarg1), .TRUE., .TRUE.,    &
6783                                    .FALSE., lowest_free_ray,                 &
6784                                    ztransp(itarg0:itarg1),                   &
6785                                    itarget(itarg0:itarg1))
6786
6787               skyvf(isurflt) = skyvf(isurflt) + &
6788                                SUM(vffrac(itarg0:itarg0+lowest_free_ray-1))
6789               skyvft(isurflt) = skyvft(isurflt) + &
6790                                 SUM(ztransp(itarg0:itarg0+lowest_free_ray-1) &
6791                                             * vffrac(itarg0:itarg0+lowest_free_ray-1))
6792 
6793!--            Save direct solar transparency
6794               j = MODULO(NINT(azmid/                                          &
6795                               (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
6796                          raytrace_discrete_azims)
6797
6798               DO k = 1, raytrace_discrete_elevs/2
6799                  i = dsidir_rev(k-1, j)
6800                  IF ( i /= -1  .AND.  k <= lowest_free_ray )  &
6801                     dsitrans(isurflt, i) = ztransp(itarg0+k-1)
6802               ENDDO
6803
6804!
6805!--            Advance itarget indices
6806               itarg0 = itarg1 + 1
6807               itarg1 = itarg1 + nzn
6808            ENDDO
6809
6810            IF ( rad_angular_discretization )  THEN
6811!--            sort itarget by face id
6812               CALL quicksort_itarget(itarget,vffrac,ztransp,1,nzn*naz)
6813!
6814!--            For aggregation, we need fractions multiplied by transmissivities
6815               ztransp(:) = vffrac(:) * ztransp(:)
6816!
6817!--            find the first valid position
6818               itarg0 = 1
6819               DO WHILE ( itarg0 <= nzn*naz )
6820                  IF ( itarget(itarg0) /= -1 )  EXIT
6821                  itarg0 = itarg0 + 1
6822               ENDDO
6823
6824               DO  i = itarg0, nzn*naz
6825!
6826!--               For duplicate values, only sum up vf fraction value
6827                  IF ( i < nzn*naz )  THEN
6828                     IF ( itarget(i+1) == itarget(i) )  THEN
6829                        vffrac(i+1) = vffrac(i+1) + vffrac(i)
6830                        ztransp(i+1) = ztransp(i+1) + ztransp(i)
6831                        CYCLE
6832                     ENDIF
6833                  ENDIF
6834!
6835!--               write to the svf array
6836                  nsvfl = nsvfl + 1
6837!--               check dimmension of asvf array and enlarge it if needed
6838                  IF ( nsvfla < nsvfl )  THEN
6839                     k = CEILING(REAL(nsvfla, kind=wp) * grow_factor)
6840                     IF ( msvf == 0 )  THEN
6841                        msvf = 1
6842                        ALLOCATE( asvf1(k) )
6843                        asvf => asvf1
6844                        asvf1(1:nsvfla) = asvf2
6845                        DEALLOCATE( asvf2 )
6846                     ELSE
6847                        msvf = 0
6848                        ALLOCATE( asvf2(k) )
6849                        asvf => asvf2
6850                        asvf2(1:nsvfla) = asvf1
6851                        DEALLOCATE( asvf1 )
6852                     ENDIF
6853
6854                     WRITE (msg,'(A,3I12)') 'Grow asvf:',nsvfl,nsvfla,k
6855                     CALL radiation_write_debug_log( msg )
6856                     
6857                     nsvfla = k
6858                  ENDIF
6859!--               write svf values into the array
6860                  asvf(nsvfl)%isurflt = isurflt
6861                  asvf(nsvfl)%isurfs = itarget(i)
6862                  asvf(nsvfl)%rsvf = vffrac(i)
6863                  asvf(nsvfl)%rtransp = ztransp(i) / vffrac(i)
6864               END DO
6865
6866            ENDIF ! rad_angular_discretization
6867
6868            DEALLOCATE ( zdirs, zcent, zbdry, vffrac, ztransp, itarget ) !FIXME itarget shall be allocated only
6869                                                                  !in case of rad_angular_discretization
6870!
6871!--         Following calculations only required for surface_reflections
6872            IF ( surface_reflections  .AND.  .NOT. rad_angular_discretization )  THEN
6873
6874               DO  isurfs = 1, nsurf
6875                  IF ( .NOT.  surface_facing(surfl(ix, isurflt), surfl(iy, isurflt), &
6876                     surfl(iz, isurflt), surfl(id, isurflt), &
6877                     surf(ix, isurfs), surf(iy, isurfs), &
6878                     surf(iz, isurfs), surf(id, isurfs)) )  THEN
6879                     CYCLE
6880                  ENDIF
6881                 
6882                  sd = surf(id, isurfs)
6883                  sa = (/ REAL(surf(iz, isurfs), wp) - 0.5_wp * kdir(sd),  &
6884                          REAL(surf(iy, isurfs), wp) - 0.5_wp * jdir(sd),  &
6885                          REAL(surf(ix, isurfs), wp) - 0.5_wp * idir(sd)  /)
6886
6887!--               unit vector source -> target
6888                  uv = (/ (ta(1)-sa(1))*dz(1), (ta(2)-sa(2))*dy, (ta(3)-sa(3))*dx /)
6889                  sqdist = SUM(uv(:)**2)
6890                  uv = uv / SQRT(sqdist)
6891
6892!--               reject raytracing above max distance
6893                  IF ( SQRT(sqdist) > max_raytracing_dist ) THEN
6894                     ray_skip_maxdist = ray_skip_maxdist + 1
6895                     CYCLE
6896                  ENDIF
6897                 
6898                  difvf = dot_product((/ kdir(sd), jdir(sd), idir(sd) /), uv) & ! cosine of source normal and direction
6899                      * dot_product((/ kdir(td), jdir(td), idir(td) /), -uv) &  ! cosine of target normal and reverse direction
6900                      / (pi * sqdist) ! square of distance between centers
6901!
6902!--               irradiance factor (our unshaded shape view factor) = view factor per differential target area * source area
6903                  rirrf = difvf * facearea(sd)
6904
6905!--               reject raytracing for potentially too small view factor values
6906                  IF ( rirrf < min_irrf_value ) THEN
6907                      ray_skip_minval = ray_skip_minval + 1
6908                      CYCLE
6909                  ENDIF
6910
6911!--               raytrace + process plant canopy sinks within
6912                  CALL raytrace(sa, ta, isurfs, difvf, facearea(td), .TRUE., &
6913                                visible, transparency)
6914
6915                  IF ( .NOT.  visible ) CYCLE
6916                 ! rsvf = rirrf * transparency
6917
6918!--               write to the svf array
6919                  nsvfl = nsvfl + 1
6920!--               check dimmension of asvf array and enlarge it if needed
6921                  IF ( nsvfla < nsvfl )  THEN
6922                     k = CEILING(REAL(nsvfla, kind=wp) * grow_factor)
6923                     IF ( msvf == 0 )  THEN
6924                        msvf = 1
6925                        ALLOCATE( asvf1(k) )
6926                        asvf => asvf1
6927                        asvf1(1:nsvfla) = asvf2
6928                        DEALLOCATE( asvf2 )
6929                     ELSE
6930                        msvf = 0
6931                        ALLOCATE( asvf2(k) )
6932                        asvf => asvf2
6933                        asvf2(1:nsvfla) = asvf1
6934                        DEALLOCATE( asvf1 )
6935                     ENDIF
6936
6937                     WRITE(msg,'(A,3I12)') 'Grow asvf:',nsvfl,nsvfla,k
6938                     CALL radiation_write_debug_log( msg )
6939                     
6940                     nsvfla = k
6941                  ENDIF
6942!--               write svf values into the array
6943                  asvf(nsvfl)%isurflt = isurflt
6944                  asvf(nsvfl)%isurfs = isurfs
6945                  asvf(nsvfl)%rsvf = rirrf !we postopne multiplication by transparency
6946                  asvf(nsvfl)%rtransp = transparency !a.k.a. Direct Irradiance Factor
6947               ENDDO
6948            ENDIF
6949        ENDDO
6950
6951!--
6952!--     Raytrace to canopy boxes to fill dsitransc TODO optimize
6953        dsitransc(:,:) = 0._wp
6954        az0 = 0._wp
6955        naz = raytrace_discrete_azims
6956        azs = 2._wp * pi / REAL(naz, wp)
6957        zn0 = 0._wp
6958        nzn = raytrace_discrete_elevs / 2
6959        zns = pi / 2._wp / REAL(nzn, wp)
6960        ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), vffrac(1:nzn), ztransp(1:nzn), &
6961               itarget(1:nzn) )
6962        zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
6963        vffrac(:) = 0._wp
6964
6965        DO  ipcgb = 1, npcbl
6966           ta = (/ REAL(pcbl(iz, ipcgb), wp),  &
6967                   REAL(pcbl(iy, ipcgb), wp),  &
6968                   REAL(pcbl(ix, ipcgb), wp) /)
6969!--        Calculate direct solar visibility using 2D raytracing
6970           DO  iaz = 1, naz
6971              azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
6972              yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
6973              yxlen = SQRT(SUM(yxdir(:)**2))
6974              zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
6975              yxdir(:) = yxdir(:) / yxlen
6976              CALL raytrace_2d(ta, yxdir, nzn, zdirs,                                &
6977                                   -999, -999._wp, vffrac, .FALSE., .FALSE., .TRUE., &
6978                                   lowest_free_ray, ztransp, itarget)
6979
6980!--           Save direct solar transparency
6981              j = MODULO(NINT(azmid/                                         &
6982                             (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
6983                         raytrace_discrete_azims)
6984              DO  k = 1, raytrace_discrete_elevs/2
6985                 i = dsidir_rev(k-1, j)
6986                 IF ( i /= -1  .AND.  k <= lowest_free_ray ) &
6987                    dsitransc(ipcgb, i) = ztransp(k)
6988              ENDDO
6989           ENDDO
6990        ENDDO
6991        DEALLOCATE ( zdirs, zcent, vffrac, ztransp, itarget )
6992!--
6993!--     Raytrace to MRT boxes
6994        IF ( nmrtbl > 0 )  THEN
6995           mrtdsit(:,:) = 0._wp
6996           mrtsky(:) = 0._wp
6997           mrtskyt(:) = 0._wp
6998           az0 = 0._wp
6999           naz = raytrace_discrete_azims
7000           azs = 2._wp * pi / REAL(naz, wp)
7001           zn0 = 0._wp
7002           nzn = raytrace_discrete_elevs
7003           zns = pi / REAL(nzn, wp)
7004           ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), zbdry(0:nzn), vffrac(1:nzn*naz), vffrac0(1:nzn), &
7005                      ztransp(1:nzn*naz), itarget(1:nzn*naz) )   !FIXME allocate itarget only
7006                                                                 !in case of rad_angular_discretization
7007
7008           zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
7009           zbdry(:) = (/( zn0+REAL(izn,wp)*zns, izn=0, nzn )/)
7010           vffrac0(:) = (COS(zbdry(0:nzn-1)) - COS(zbdry(1:nzn))) / 2._wp / REAL(naz, wp)
7011           !
7012           !--Modify direction weights to simulate human body (lower weight for top-down)
7013           IF ( mrt_geom_human )  THEN
7014              vffrac0(:) = vffrac0(:) * MAX(0._wp, SIN(zcent(:))*0.88_wp + COS(zcent(:))*0.12_wp)
7015              vffrac0(:) = vffrac0(:) / (SUM(vffrac0) * REAL(naz, wp))
7016           ENDIF
7017
7018           DO  imrt = 1, nmrtbl
7019              ta = (/ REAL(mrtbl(iz, imrt), wp),  &
7020                      REAL(mrtbl(iy, imrt), wp),  &
7021                      REAL(mrtbl(ix, imrt), wp) /)
7022!
7023!--           vf fractions are constant per azimuth
7024              DO iaz = 0, naz-1
7025                 vffrac(iaz*nzn+1:(iaz+1)*nzn) = vffrac0(:)
7026              ENDDO
7027!--           sum of whole vffrac equals 1, verified
7028              itarg0 = 1
7029              itarg1 = nzn
7030!
7031!--           Calculate sky-view factor and direct solar visibility using 2D raytracing
7032              DO  iaz = 1, naz
7033                 azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
7034                 yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
7035                 yxlen = SQRT(SUM(yxdir(:)**2))
7036                 zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
7037                 yxdir(:) = yxdir(:) / yxlen
7038
7039                 CALL raytrace_2d(ta, yxdir, nzn, zdirs,                         &
7040                                  -999, -999._wp, vffrac(itarg0:itarg1), .TRUE., &
7041                                  .FALSE., .TRUE., lowest_free_ray,              &
7042                                  ztransp(itarg0:itarg1),                        &
7043                                  itarget(itarg0:itarg1))
7044
7045!--              Sky view factors for MRT
7046                 mrtsky(imrt) = mrtsky(imrt) + &
7047                                  SUM(vffrac(itarg0:itarg0+lowest_free_ray-1))
7048                 mrtskyt(imrt) = mrtskyt(imrt) + &
7049                                   SUM(ztransp(itarg0:itarg0+lowest_free_ray-1) &
7050                                               * vffrac(itarg0:itarg0+lowest_free_ray-1))
7051!--              Direct solar transparency for MRT
7052                 j = MODULO(NINT(azmid/                                         &
7053                                (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
7054                            raytrace_discrete_azims)
7055                 DO  k = 1, raytrace_discrete_elevs/2
7056                    i = dsidir_rev(k-1, j)
7057                    IF ( i /= -1  .AND.  k <= lowest_free_ray ) &
7058                       mrtdsit(imrt, i) = ztransp(itarg0+k-1)
7059                 ENDDO
7060!
7061!--              Advance itarget indices
7062                 itarg0 = itarg1 + 1
7063                 itarg1 = itarg1 + nzn
7064              ENDDO
7065
7066!--           sort itarget by face id
7067              CALL quicksort_itarget(itarget,vffrac,ztransp,1,nzn*naz)
7068!
7069!--           find the first valid position
7070              itarg0 = 1
7071              DO WHILE ( itarg0 <= nzn*naz )
7072                 IF ( itarget(itarg0) /= -1 )  EXIT
7073                 itarg0 = itarg0 + 1
7074              ENDDO
7075
7076              DO  i = itarg0, nzn*naz
7077!
7078!--              For duplicate values, only sum up vf fraction value
7079                 IF ( i < nzn*naz )  THEN
7080                    IF ( itarget(i+1) == itarget(i) )  THEN
7081                       vffrac(i+1) = vffrac(i+1) + vffrac(i)
7082                       CYCLE
7083                    ENDIF
7084                 ENDIF
7085!
7086!--              write to the mrtf array
7087                 nmrtf = nmrtf + 1
7088!--              check dimmension of mrtf array and enlarge it if needed
7089                 IF ( nmrtfa < nmrtf )  THEN
7090                    k = CEILING(REAL(nmrtfa, kind=wp) * grow_factor)
7091                    IF ( mmrtf == 0 )  THEN
7092                       mmrtf = 1
7093                       ALLOCATE( amrtf1(k) )
7094                       amrtf => amrtf1
7095                       amrtf1(1:nmrtfa) = amrtf2
7096                       DEALLOCATE( amrtf2 )
7097                    ELSE
7098                       mmrtf = 0
7099                       ALLOCATE( amrtf2(k) )
7100                       amrtf => amrtf2
7101                       amrtf2(1:nmrtfa) = amrtf1
7102                       DEALLOCATE( amrtf1 )
7103                    ENDIF
7104
7105                    WRITE (msg,'(A,3I12)') 'Grow amrtf:', nmrtf, nmrtfa, k
7106                    CALL radiation_write_debug_log( msg )
7107
7108                    nmrtfa = k
7109                 ENDIF
7110!--              write mrtf values into the array
7111                 amrtf(nmrtf)%isurflt = imrt
7112                 amrtf(nmrtf)%isurfs = itarget(i)
7113                 amrtf(nmrtf)%rsvf = vffrac(i)
7114                 amrtf(nmrtf)%rtransp = ztransp(i)
7115              ENDDO ! itarg
7116
7117           ENDDO ! imrt
7118           DEALLOCATE ( zdirs, zcent, zbdry, vffrac, vffrac0, ztransp, itarget )
7119!
7120!--        Move MRT factors to final arrays
7121           ALLOCATE ( mrtf(nmrtf), mrtft(nmrtf), mrtfsurf(2,nmrtf) )
7122           DO  imrtf = 1, nmrtf
7123              mrtf(imrtf) = amrtf(imrtf)%rsvf
7124              mrtft(imrtf) = amrtf(imrtf)%rsvf * amrtf(imrtf)%rtransp
7125              mrtfsurf(:,imrtf) = (/amrtf(imrtf)%isurflt, amrtf(imrtf)%isurfs /)
7126           ENDDO
7127           IF ( ALLOCATED(amrtf1) )  DEALLOCATE( amrtf1 )
7128           IF ( ALLOCATED(amrtf2) )  DEALLOCATE( amrtf2 )
7129        ENDIF ! nmrtbl > 0
7130
7131        IF ( rad_angular_discretization )  THEN
7132#if defined( __parallel )
7133!--        finalize MPI_RMA communication established to get global index of the surface from grid indices
7134!--        flush all MPI window pending requests
7135           CALL MPI_Win_flush_all(win_gridsurf, ierr)
7136           IF ( ierr /= 0 ) THEN
7137               WRITE(9,*) 'Error MPI_Win_flush_all1:', ierr, win_gridsurf
7138               FLUSH(9)
7139           ENDIF
7140!--        unlock MPI window
7141           CALL MPI_Win_unlock_all(win_gridsurf, ierr)
7142           IF ( ierr /= 0 ) THEN
7143               WRITE(9,*) 'Error MPI_Win_unlock_all1:', ierr, win_gridsurf
7144               FLUSH(9)
7145           ENDIF
7146!--        free MPI window
7147           CALL MPI_Win_free(win_gridsurf, ierr)
7148           IF ( ierr /= 0 ) THEN
7149               WRITE(9,*) 'Error MPI_Win_free1:', ierr, win_gridsurf
7150               FLUSH(9)
7151           ENDIF
7152#else
7153           DEALLOCATE ( gridsurf )
7154#endif
7155        ENDIF
7156
7157        CALL radiation_write_debug_log( 'End of calculation SVF' )
7158        WRITE(msg, *) 'Raytracing skipped for maximum distance of ', &
7159           max_raytracing_dist, ' m on ', ray_skip_maxdist, ' pairs.'
7160        CALL radiation_write_debug_log( msg )
7161        WRITE(msg, *) 'Raytracing skipped for minimum potential value of ', &
7162           min_irrf_value , ' on ', ray_skip_minval, ' pairs.'
7163        CALL radiation_write_debug_log( msg )
7164
7165        CALL location_message( '    waiting for completion of SVF and CSF calculation in all processes', .TRUE. )
7166!--     deallocate temporary global arrays
7167        DEALLOCATE(nzterr)
7168       
7169        IF ( plant_canopy )  THEN
7170!--         finalize mpi_rma communication and deallocate temporary arrays
7171#if defined( __parallel )
7172            IF ( raytrace_mpi_rma )  THEN
7173                CALL MPI_Win_flush_all(win_lad, ierr)
7174                IF ( ierr /= 0 ) THEN
7175                    WRITE(9,*) 'Error MPI_Win_flush_all2:', ierr, win_lad
7176                    FLUSH(9)
7177                ENDIF
7178!--             unlock MPI window
7179                CALL MPI_Win_unlock_all(win_lad, ierr)
7180                IF ( ierr /= 0 ) THEN
7181                    WRITE(9,*) 'Error MPI_Win_unlock_all2:', ierr, win_lad
7182                    FLUSH(9)
7183                ENDIF
7184!--             free MPI window
7185                CALL MPI_Win_free(win_lad, ierr)
7186                IF ( ierr /= 0 ) THEN
7187                    WRITE(9,*) 'Error MPI_Win_free2:', ierr, win_lad
7188                    FLUSH(9)
7189                ENDIF
7190!--             deallocate temporary arrays storing values for csf calculation during raytracing
7191                DEALLOCATE( lad_s_ray )
7192!--             sub_lad is the pointer to lad_s_rma in case of raytrace_mpi_rma
7193!--             and must not be deallocated here
7194            ELSE
7195                DEALLOCATE(sub_lad)
7196                DEALLOCATE(sub_lad_g)
7197            ENDIF
7198#else
7199            DEALLOCATE(sub_lad)
7200#endif
7201            DEALLOCATE( boxes )
7202            DEALLOCATE( crlens )
7203            DEALLOCATE( plantt )
7204            DEALLOCATE( rt2_track, rt2_track_lad, rt2_track_dist, rt2_dist )
7205        ENDIF
7206
7207        CALL location_message( '    calculation of the complete SVF array', .TRUE. )
7208
7209        IF ( rad_angular_discretization )  THEN
7210           CALL radiation_write_debug_log( 'Load svf from the structure array to plain arrays' )
7211           ALLOCATE( svf(ndsvf,nsvfl) )
7212           ALLOCATE( svfsurf(idsvf,nsvfl) )
7213
7214           DO isvf = 1, nsvfl
7215               svf(:, isvf) = (/ asvf(isvf)%rsvf, asvf(isvf)%rtransp /)
7216               svfsurf(:, isvf) = (/ asvf(isvf)%isurflt, asvf(isvf)%isurfs /)
7217           ENDDO
7218        ELSE
7219           CALL radiation_write_debug_log( 'Start SVF sort' )
7220!--        sort svf ( a version of quicksort )
7221           CALL quicksort_svf(asvf,1,nsvfl)
7222
7223           !< load svf from the structure array to plain arrays
7224           CALL radiation_write_debug_log( 'Load svf from the structure array to plain arrays' )
7225           ALLOCATE( svf(ndsvf,nsvfl) )
7226           ALLOCATE( svfsurf(idsvf,nsvfl) )
7227           svfnorm_counts(:) = 0._wp
7228           isurflt_prev = -1
7229           ksvf = 1
7230           svfsum = 0._wp
7231           DO isvf = 1, nsvfl
7232!--            normalize svf per target face
7233               IF ( asvf(ksvf)%isurflt /= isurflt_prev )  THEN
7234                   IF ( isurflt_prev /= -1  .AND.  svfsum /= 0._wp )  THEN
7235                       !< update histogram of logged svf normalization values
7236                       i = searchsorted(svfnorm_report_thresh, svfsum / (1._wp-skyvf(isurflt_prev)))
7237                       svfnorm_counts(i) = svfnorm_counts(i) + 1
7238
7239                       svf(1, isvf_surflt:isvf-1) = svf(1, isvf_surflt:isvf-1) / svfsum * (1._wp-skyvf(isurflt_prev))
7240                   ENDIF
7241                   isurflt_prev = asvf(ksvf)%isurflt
7242                   isvf_surflt = isvf
7243                   svfsum = asvf(ksvf)%rsvf !?? / asvf(ksvf)%rtransp
7244               ELSE
7245                   svfsum = svfsum + asvf(ksvf)%rsvf !?? / asvf(ksvf)%rtransp
7246               ENDIF
7247
7248               svf(:, isvf) = (/ asvf(ksvf)%rsvf, asvf(ksvf)%rtransp /)
7249               svfsurf(:, isvf) = (/ asvf(ksvf)%isurflt, asvf(ksvf)%isurfs /)
7250
7251!--            next element
7252               ksvf = ksvf + 1
7253           ENDDO
7254
7255           IF ( isurflt_prev /= -1  .AND.  svfsum /= 0._wp )  THEN
7256               i = searchsorted(svfnorm_report_thresh, svfsum / (1._wp-skyvf(isurflt_prev)))
7257               svfnorm_counts(i) = svfnorm_counts(i) + 1
7258
7259               svf(1, isvf_surflt:nsvfl) = svf(1, isvf_surflt:nsvfl) / svfsum * (1._wp-skyvf(isurflt_prev))
7260           ENDIF
7261           WRITE(9, *) 'SVF normalization histogram:', svfnorm_counts,  &
7262                       'on thresholds:', svfnorm_report_thresh(1:svfnorm_report_num), '(val < thresh <= val)'
7263           !TODO we should be able to deallocate skyvf, from now on we only need skyvft
7264        ENDIF ! rad_angular_discretization
7265
7266!--     deallocate temporary asvf array
7267!--     DEALLOCATE(asvf) - ifort has a problem with deallocation of allocatable target
7268!--     via pointing pointer - we need to test original targets
7269        IF ( ALLOCATED(asvf1) )  THEN
7270            DEALLOCATE(asvf1)
7271        ENDIF
7272        IF ( ALLOCATED(asvf2) )  THEN
7273            DEALLOCATE(asvf2)
7274        ENDIF
7275
7276        npcsfl = 0
7277        IF ( plant_canopy )  THEN
7278
7279            CALL location_message( '    calculation of the complete CSF array', .TRUE. )
7280            CALL radiation_write_debug_log( 'Calculation of the complete CSF array' )
7281!--         sort and merge csf for the last time, keeping the array size to minimum
7282            CALL merge_and_grow_csf(-1)
7283           
7284!--         aggregate csb among processors
7285!--         allocate necessary arrays
7286            udim = max(ncsfl,1)
7287            ALLOCATE( csflt_l(ndcsf*udim) )
7288            csflt(1:ndcsf,1:udim) => csflt_l(1:ndcsf*udim)
7289            ALLOCATE( kcsflt_l(kdcsf*udim) )
7290            kcsflt(1:kdcsf,1:udim) => kcsflt_l(1:kdcsf*udim)
7291            ALLOCATE( icsflt(0:numprocs-1) )
7292            ALLOCATE( dcsflt(0:numprocs-1) )
7293            ALLOCATE( ipcsflt(0:numprocs-1) )
7294            ALLOCATE( dpcsflt(0:numprocs-1) )
7295           
7296!--         fill out arrays of csf values and
7297!--         arrays of number of elements and displacements
7298!--         for particular precessors
7299            icsflt = 0
7300            dcsflt = 0
7301            ip = -1
7302            j = -1
7303            d = 0
7304            DO kcsf = 1, ncsfl
7305                j = j+1
7306                IF ( acsf(kcsf)%ip /= ip )  THEN
7307!--                 new block of the processor
7308!--                 number of elements of previous block
7309                    IF ( ip>=0) icsflt(ip) = j
7310                    d = d+j
7311!--                 blank blocks
7312                    DO jp = ip+1, acsf(kcsf)%ip-1
7313!--                     number of elements is zero, displacement is equal to previous
7314                        icsflt(jp) = 0
7315                        dcsflt(jp) = d
7316                    ENDDO
7317!--                 the actual block
7318                    ip = acsf(kcsf)%ip
7319                    dcsflt(ip) = d
7320                    j = 0
7321                ENDIF
7322                csflt(1,kcsf) = acsf(kcsf)%rcvf
7323!--             fill out integer values of itz,ity,itx,isurfs
7324                kcsflt(1,kcsf) = acsf(kcsf)%itz
7325                kcsflt(2,kcsf) = acsf(kcsf)%ity
7326                kcsflt(3,kcsf) = acsf(kcsf)%itx
7327                kcsflt(4,kcsf) = acsf(kcsf)%isurfs
7328            ENDDO
7329!--         last blank blocks at the end of array
7330            j = j+1
7331            IF ( ip>=0 ) icsflt(ip) = j
7332            d = d+j
7333            DO jp = ip+1, numprocs-1
7334!--             number of elements is zero, displacement is equal to previous
7335                icsflt(jp) = 0
7336                dcsflt(jp) = d
7337            ENDDO
7338           
7339!--         deallocate temporary acsf array
7340!--         DEALLOCATE(acsf) - ifort has a problem with deallocation of allocatable target
7341!--         via pointing pointer - we need to test original targets
7342            IF ( ALLOCATED(acsf1) )  THEN
7343                DEALLOCATE(acsf1)
7344            ENDIF
7345            IF ( ALLOCATED(acsf2) )  THEN
7346                DEALLOCATE(acsf2)
7347            ENDIF
7348                   
7349#if defined( __parallel )
7350!--         scatter and gather the number of elements to and from all processor
7351!--         and calculate displacements
7352            CALL radiation_write_debug_log( 'Scatter and gather the number of elements to and from all processor' )
7353            CALL MPI_AlltoAll(icsflt,1,MPI_INTEGER,ipcsflt,1,MPI_INTEGER,comm2d, ierr)
7354            IF ( ierr /= 0 ) THEN
7355                WRITE(9,*) 'Error MPI_AlltoAll1:', ierr, SIZE(icsflt), SIZE(ipcsflt)
7356                FLUSH(9)
7357            ENDIF
7358
7359            npcsfl = SUM(ipcsflt)
7360            d = 0
7361            DO i = 0, numprocs-1
7362                dpcsflt(i) = d
7363                d = d + ipcsflt(i)
7364            ENDDO
7365
7366!--         exchange csf fields between processors
7367            CALL radiation_write_debug_log( 'Exchange csf fields between processors' )
7368            udim = max(npcsfl,1)
7369            ALLOCATE( pcsflt_l(ndcsf*udim) )
7370            pcsflt(1:ndcsf,1:udim) => pcsflt_l(1:ndcsf*udim)
7371            ALLOCATE( kpcsflt_l(kdcsf*udim) )
7372            kpcsflt(1:kdcsf,1:udim) => kpcsflt_l(1:kdcsf*udim)
7373            CALL MPI_AlltoAllv(csflt_l, ndcsf*icsflt, ndcsf*dcsflt, MPI_REAL, &
7374                pcsflt_l, ndcsf*ipcsflt, ndcsf*dpcsflt, MPI_REAL, comm2d, ierr)
7375            IF ( ierr /= 0 ) THEN
7376                WRITE(9,*) 'Error MPI_AlltoAllv1:', ierr, SIZE(ipcsflt), ndcsf*icsflt, &
7377                            ndcsf*dcsflt, SIZE(pcsflt_l),ndcsf*ipcsflt, ndcsf*dpcsflt
7378                FLUSH(9)
7379            ENDIF
7380
7381            CALL MPI_AlltoAllv(kcsflt_l, kdcsf*icsflt, kdcsf*dcsflt, MPI_INTEGER, &
7382                kpcsflt_l, kdcsf*ipcsflt, kdcsf*dpcsflt, MPI_INTEGER, comm2d, ierr)
7383            IF ( ierr /= 0 ) THEN
7384                WRITE(9,*) 'Error MPI_AlltoAllv2:', ierr, SIZE(kcsflt_l),kdcsf*icsflt, &
7385                           kdcsf*dcsflt, SIZE(kpcsflt_l), kdcsf*ipcsflt, kdcsf*dpcsflt
7386                FLUSH(9)
7387            ENDIF
7388           
7389#else
7390            npcsfl = ncsfl
7391            ALLOCATE( pcsflt(ndcsf,max(npcsfl,ndcsf)) )
7392            ALLOCATE( kpcsflt(kdcsf,max(npcsfl,kdcsf)) )
7393            pcsflt = csflt
7394            kpcsflt = kcsflt
7395#endif
7396
7397!--         deallocate temporary arrays
7398            DEALLOCATE( csflt_l )
7399            DEALLOCATE( kcsflt_l )
7400            DEALLOCATE( icsflt )
7401            DEALLOCATE( dcsflt )
7402            DEALLOCATE( ipcsflt )
7403            DEALLOCATE( dpcsflt )
7404
7405!--         sort csf ( a version of quicksort )
7406            CALL radiation_write_debug_log( 'Sort csf' )
7407            CALL quicksort_csf2(kpcsflt, pcsflt, 1, npcsfl)
7408
7409!--         aggregate canopy sink factor records with identical box & source
7410!--         againg across all values from all processors
7411            CALL radiation_write_debug_log( 'Aggregate canopy sink factor records with identical box' )
7412
7413            IF ( npcsfl > 0 )  THEN
7414                icsf = 1 !< reading index
7415                kcsf = 1 !< writing index
7416                DO WHILE (icsf < npcsfl)
7417!--                 here kpcsf(kcsf) already has values from kpcsf(icsf)
7418                    IF ( kpcsflt(3,icsf) == kpcsflt(3,icsf+1)  .AND.  &
7419                         kpcsflt(2,icsf) == kpcsflt(2,icsf+1)  .AND.  &
7420                         kpcsflt(1,icsf) == kpcsflt(1,icsf+1)  .AND.  &
7421                         kpcsflt(4,icsf) == kpcsflt(4,icsf+1) )  THEN
7422
7423                        pcsflt(1,kcsf) = pcsflt(1,kcsf) + pcsflt(1,icsf+1)
7424
7425!--                     advance reading index, keep writing index
7426                        icsf = icsf + 1
7427                    ELSE
7428!--                     not identical, just advance and copy
7429                        icsf = icsf + 1
7430                        kcsf = kcsf + 1
7431                        kpcsflt(:,kcsf) = kpcsflt(:,icsf)
7432                        pcsflt(:,kcsf) = pcsflt(:,icsf)
7433                    ENDIF
7434                ENDDO
7435!--             last written item is now also the last item in valid part of array
7436                npcsfl = kcsf
7437            ENDIF
7438
7439            ncsfl = npcsfl
7440            IF ( ncsfl > 0 )  THEN
7441                ALLOCATE( csf(ndcsf,ncsfl) )
7442                ALLOCATE( csfsurf(idcsf,ncsfl) )
7443                DO icsf = 1, ncsfl
7444                    csf(:,icsf) = pcsflt(:,icsf)
7445                    csfsurf(1,icsf) =  gridpcbl(kpcsflt(1,icsf),kpcsflt(2,icsf),kpcsflt(3,icsf))
7446                    csfsurf(2,icsf) =  kpcsflt(4,icsf)
7447                ENDDO
7448            ENDIF
7449           
7450!--         deallocation of temporary arrays
7451            IF ( npcbl > 0 )  DEALLOCATE( gridpcbl )
7452            DEALLOCATE( pcsflt_l )
7453            DEALLOCATE( kpcsflt_l )
7454            CALL radiation_write_debug_log( 'End of aggregate csf' )
7455           
7456        ENDIF
7457
7458#if defined( __parallel )
7459        CALL MPI_BARRIER( comm2d, ierr )
7460#endif
7461        CALL radiation_write_debug_log( 'End of radiation_calc_svf (after mpi_barrier)' )
7462
7463        RETURN
7464       
7465!        WRITE( message_string, * )  &
7466!            'I/O error when processing shape view factors / ',  &
7467!            'plant canopy sink factors / direct irradiance factors.'
7468!        CALL message( 'init_urban_surface', 'PA0502', 2, 2, 0, 6, 0 )
7469       
7470    END SUBROUTINE radiation_calc_svf
7471
7472   
7473!------------------------------------------------------------------------------!
7474! Description:
7475! ------------
7476!> Raytracing for detecting obstacles and calculating compound canopy sink
7477!> factors. (A simple obstacle detection would only need to process faces in
7478!> 3 dimensions without any ordering.)
7479!> Assumtions:
7480!> -----------
7481!> 1. The ray always originates from a face midpoint (only one coordinate equals
7482!>    *.5, i.e. wall) and doesn't travel parallel to the surface (that would mean
7483!>    shape factor=0). Therefore, the ray may never travel exactly along a face
7484!>    or an edge.
7485!> 2. From grid bottom to urban surface top the grid has to be *equidistant*
7486!>    within each of the dimensions, including vertical (but the resolution
7487!>    doesn't need to be the same in all three dimensions).
7488!------------------------------------------------------------------------------!
7489    SUBROUTINE raytrace(src, targ, isrc, difvf, atarg, create_csf, visible, transparency)
7490        IMPLICIT NONE
7491
7492        REAL(wp), DIMENSION(3), INTENT(in)     :: src, targ    !< real coordinates z,y,x
7493        INTEGER(iwp), INTENT(in)               :: isrc         !< index of source face for csf
7494        REAL(wp), INTENT(in)                   :: difvf        !< differential view factor for csf
7495        REAL(wp), INTENT(in)                   :: atarg        !< target surface area for csf
7496        LOGICAL, INTENT(in)                    :: create_csf   !< whether to generate new CSFs during raytracing
7497        LOGICAL, INTENT(out)                   :: visible
7498        REAL(wp), INTENT(out)                  :: transparency !< along whole path
7499        INTEGER(iwp)                           :: i, k, d
7500        INTEGER(iwp)                           :: seldim       !< dimension to be incremented
7501        INTEGER(iwp)                           :: ncsb         !< no of written plant canopy sinkboxes
7502        INTEGER(iwp)                           :: maxboxes     !< max no of gridboxes visited
7503        REAL(wp)                               :: distance     !< euclidean along path
7504        REAL(wp)                               :: crlen        !< length of gridbox crossing
7505        REAL(wp)                               :: lastdist     !< beginning of current crossing
7506        REAL(wp)                               :: nextdist     !< end of current crossing
7507        REAL(wp)                               :: realdist     !< distance in meters per unit distance
7508        REAL(wp)                               :: crmid        !< midpoint of crossing
7509        REAL(wp)                               :: cursink      !< sink factor for current canopy box
7510        REAL(wp), DIMENSION(3)                 :: delta        !< path vector
7511        REAL(wp), DIMENSION(3)                 :: uvect        !< unit vector
7512        REAL(wp), DIMENSION(3)                 :: dimnextdist  !< distance for each dimension increments
7513        INTEGER(iwp), DIMENSION(3)             :: box          !< gridbox being crossed
7514        INTEGER(iwp), DIMENSION(3)             :: dimnext      !< next dimension increments along path
7515        INTEGER(iwp), DIMENSION(3)             :: dimdelta     !< dimension direction = +- 1
7516        INTEGER(iwp)                           :: px, py       !< number of processors in x and y dir before
7517                                                               !< the processor in the question
7518        INTEGER(iwp)                           :: ip           !< number of processor where gridbox reside
7519        INTEGER(iwp)                           :: ig           !< 1D index of gridbox in global 2D array
7520       
7521        REAL(wp)                               :: eps = 1E-10_wp !< epsilon for value comparison
7522        REAL(wp)                               :: lad_s_target   !< recieved lad_s of particular grid box
7523
7524!
7525!--     Maximum number of gridboxes visited equals to maximum number of boundaries crossed in each dimension plus one. That's also
7526!--     the maximum number of plant canopy boxes written. We grow the acsf array accordingly using exponential factor.
7527        maxboxes = SUM(ABS(NINT(targ, iwp) - NINT(src, iwp))) + 1
7528        IF ( plant_canopy  .AND.  ncsfl + maxboxes > ncsfla )  THEN
7529!--         use this code for growing by fixed exponential increments (equivalent to case where ncsfl always increases by 1)
7530!--         k = CEILING(grow_factor ** real(CEILING(log(real(ncsfl + maxboxes, kind=wp)) &
7531!--                                                / log(grow_factor)), kind=wp))
7532!--         or use this code to simply always keep some extra space after growing
7533            k = CEILING(REAL(ncsfl + maxboxes, kind=wp) * grow_factor)
7534
7535            CALL merge_and_grow_csf(k)
7536        ENDIF
7537       
7538        transparency = 1._wp
7539        ncsb = 0
7540
7541        delta(:) = targ(:) - src(:)
7542        distance = SQRT(SUM(delta(:)**2))
7543        IF ( distance == 0._wp )  THEN
7544            visible = .TRUE.
7545            RETURN
7546        ENDIF
7547        uvect(:) = delta(:) / distance
7548        realdist = SQRT(SUM( (uvect(:)*(/dz(1),dy,dx/))**2 ))
7549
7550        lastdist = 0._wp
7551
7552!--     Since all face coordinates have values *.5 and we'd like to use
7553!--     integers, all these have .5 added
7554        DO d = 1, 3
7555            IF ( uvect(d) == 0._wp )  THEN
7556                dimnext(d) = 999999999
7557                dimdelta(d) = 999999999
7558                dimnextdist(d) = 1.0E20_wp
7559            ELSE IF ( uvect(d) > 0._wp )  THEN
7560                dimnext(d) = CEILING(src(d) + .5_wp)
7561                dimdelta(d) = 1
7562                dimnextdist(d) = (dimnext(d) - .5_wp - src(d)) / uvect(d)
7563            ELSE
7564                dimnext(d) = FLOOR(src(d) + .5_wp)
7565                dimdelta(d) = -1
7566                dimnextdist(d) = (dimnext(d) - .5_wp - src(d)) / uvect(d)
7567            ENDIF
7568        ENDDO
7569
7570        DO
7571!--         along what dimension will the next wall crossing be?
7572            seldim = minloc(dimnextdist, 1)
7573            nextdist = dimnextdist(seldim)
7574            IF ( nextdist > distance ) nextdist = distance
7575
7576            crlen = nextdist - lastdist
7577            IF ( crlen > .001_wp )  THEN
7578                crmid = (lastdist + nextdist) * .5_wp
7579                box = NINT(src(:) + uvect(:) * crmid, iwp)
7580
7581!--             calculate index of the grid with global indices (box(2),box(3))
7582!--             in the array nzterr and plantt and id of the coresponding processor
7583                px = box(3)/nnx
7584                py = box(2)/nny
7585                ip = px*pdims(2)+py
7586                ig = ip*nnx*nny + (box(3)-px*nnx)*nny + box(2)-py*nny
7587                IF ( box(1) <= nzterr(ig) )  THEN
7588                    visible = .FALSE.
7589                    RETURN
7590                ENDIF
7591
7592                IF ( plant_canopy )  THEN
7593                    IF ( box(1) <= plantt(ig) )  THEN
7594                        ncsb = ncsb + 1
7595                        boxes(:,ncsb) = box
7596                        crlens(ncsb) = crlen
7597#if defined( __parallel )
7598                        lad_ip(ncsb) = ip
7599                        lad_disp(ncsb) = (box(3)-px*nnx)*(nny*nz_plant) + (box(2)-py*nny)*nz_plant + box(1)-nz_urban_b
7600#endif
7601                    ENDIF
7602                ENDIF
7603            ENDIF
7604
7605            IF ( ABS(distance - nextdist) < eps )  EXIT
7606            lastdist = nextdist
7607            dimnext(seldim) = dimnext(seldim) + dimdelta(seldim)
7608            dimnextdist(seldim) = (dimnext(seldim) - .5_wp - src(seldim)) / uvect(seldim)
7609        ENDDO
7610       
7611        IF ( plant_canopy )  THEN
7612#if defined( __parallel )
7613            IF ( raytrace_mpi_rma )  THEN
7614!--             send requests for lad_s to appropriate processor
7615                CALL cpu_log( log_point_s(77), 'rad_rma_lad', 'start' )
7616                DO i = 1, ncsb
7617                    CALL MPI_Get(lad_s_ray(i), 1, MPI_REAL, lad_ip(i), lad_disp(i), &
7618                                 1, MPI_REAL, win_lad, ierr)
7619                    IF ( ierr /= 0 )  THEN
7620                        WRITE(9,*) 'Error MPI_Get1:', ierr, lad_s_ray(i), &
7621                                   lad_ip(i), lad_disp(i), win_lad
7622                        FLUSH(9)
7623                    ENDIF
7624                ENDDO
7625               
7626!--             wait for all pending local requests complete
7627                CALL MPI_Win_flush_local_all(win_lad, ierr)
7628                IF ( ierr /= 0 )  THEN
7629                    WRITE(9,*) 'Error MPI_Win_flush_local_all1:', ierr, win_lad
7630                    FLUSH(9)
7631                ENDIF
7632                CALL cpu_log( log_point_s(77), 'rad_rma_lad', 'stop' )
7633               
7634            ENDIF
7635#endif
7636
7637!--         calculate csf and transparency
7638            DO i = 1, ncsb
7639#if defined( __parallel )
7640                IF ( raytrace_mpi_rma )  THEN
7641                    lad_s_target = lad_s_ray(i)
7642                ELSE
7643                    lad_s_target = sub_lad_g(lad_ip(i)*nnx*nny*nz_plant + lad_disp(i))
7644                ENDIF
7645#else
7646                lad_s_target = sub_lad(boxes(1,i),boxes(2,i),boxes(3,i))
7647#endif
7648                cursink = 1._wp - exp(-ext_coef * lad_s_target * crlens(i)*realdist)
7649
7650                IF ( create_csf )  THEN
7651!--                 write svf values into the array
7652                    ncsfl = ncsfl + 1
7653                    acsf(ncsfl)%ip = lad_ip(i)
7654                    acsf(ncsfl)%itx = boxes(3,i)
7655                    acsf(ncsfl)%ity = boxes(2,i)
7656                    acsf(ncsfl)%itz = boxes(1,i)
7657                    acsf(ncsfl)%isurfs = isrc
7658                    acsf(ncsfl)%rcvf = cursink*transparency*difvf*atarg
7659                ENDIF  !< create_csf
7660
7661                transparency = transparency * (1._wp - cursink)
7662               
7663            ENDDO
7664        ENDIF
7665       
7666        visible = .TRUE.
7667
7668    END SUBROUTINE raytrace
7669   
7670 
7671!------------------------------------------------------------------------------!
7672! Description:
7673! ------------
7674!> A new, more efficient version of ray tracing algorithm that processes a whole
7675!> arc instead of a single ray.
7676!>
7677!> In all comments, horizon means tangent of horizon angle, i.e.
7678!> vertical_delta / horizontal_distance
7679!------------------------------------------------------------------------------!
7680   SUBROUTINE raytrace_2d(origin, yxdir, nrays, zdirs, iorig, aorig, vffrac,  &
7681                              calc_svf, create_csf, skip_1st_pcb,             &
7682                              lowest_free_ray, transparency, itarget)
7683      IMPLICIT NONE
7684
7685      REAL(wp), DIMENSION(3), INTENT(IN)     ::  origin        !< z,y,x coordinates of ray origin
7686      REAL(wp), DIMENSION(2), INTENT(IN)     ::  yxdir         !< y,x *unit* vector of ray direction (in grid units)
7687      INTEGER(iwp)                           ::  nrays         !< number of rays (z directions) to raytrace
7688      REAL(wp), DIMENSION(nrays), INTENT(IN) ::  zdirs         !< list of z directions to raytrace (z/hdist, grid, zenith->nadir)
7689      INTEGER(iwp), INTENT(in)               ::  iorig         !< index of origin face for csf
7690      REAL(wp), INTENT(in)                   ::  aorig         !< origin face area for csf
7691      REAL(wp), DIMENSION(nrays), INTENT(in) ::  vffrac        !< view factor fractions of each ray for csf
7692      LOGICAL, INTENT(in)                    ::  calc_svf      !< whether to calculate SFV (identify obstacle surfaces)
7693      LOGICAL, INTENT(in)                    ::  create_csf    !< whether to create canopy sink factors
7694      LOGICAL, INTENT(in)                    ::  skip_1st_pcb  !< whether to skip first plant canopy box during raytracing
7695      INTEGER(iwp), INTENT(out)              ::  lowest_free_ray !< index into zdirs
7696      REAL(wp), DIMENSION(nrays), INTENT(OUT) ::  transparency !< transparencies of zdirs paths
7697      INTEGER(iwp), DIMENSION(nrays), INTENT(OUT) ::  itarget  !< global indices of target faces for zdirs
7698
7699      INTEGER(iwp), DIMENSION(nrays)         ::  target_procs
7700      REAL(wp)                               ::  horizon       !< highest horizon found after raytracing (z/hdist)
7701      INTEGER(iwp)                           ::  i, k, l, d
7702      INTEGER(iwp)                           ::  seldim       !< dimension to be incremented
7703      REAL(wp), DIMENSION(2)                 ::  yxorigin     !< horizontal copy of origin (y,x)
7704      REAL(wp)                               ::  distance     !< euclidean along path
7705      REAL(wp)                               ::  lastdist     !< beginning of current crossing
7706      REAL(wp)                               ::  nextdist     !< end of current crossing
7707      REAL(wp)                               ::  crmid        !< midpoint of crossing
7708      REAL(wp)                               ::  horz_entry   !< horizon at entry to column
7709      REAL(wp)                               ::  horz_exit    !< horizon at exit from column
7710      REAL(wp)                               ::  bdydim       !< boundary for current dimension
7711      REAL(wp), DIMENSION(2)                 ::  crossdist    !< distances to boundary for dimensions
7712      REAL(wp), DIMENSION(2)                 ::  dimnextdist  !< distance for each dimension increments
7713      INTEGER(iwp), DIMENSION(2)             ::  column       !< grid column being crossed
7714      INTEGER(iwp), DIMENSION(2)             ::  dimnext      !< next dimension increments along path
7715      INTEGER(iwp), DIMENSION(2)             ::  dimdelta     !< dimension direction = +- 1
7716      INTEGER(iwp)                           ::  px, py       !< number of processors in x and y dir before
7717                                                              !< the processor in the question
7718      INTEGER(iwp)                           ::  ip           !< number of processor where gridbox reside
7719      INTEGER(iwp)                           ::  ig           !< 1D index of gridbox in global 2D array
7720      INTEGER(iwp)                           ::  wcount       !< RMA window item count
7721      INTEGER(iwp)                           ::  maxboxes     !< max no of CSF created
7722      INTEGER(iwp)                           ::  nly          !< maximum  plant canopy height
7723      INTEGER(iwp)                           ::  ntrack
7724     
7725      INTEGER(iwp)                           ::  zb0
7726      INTEGER(iwp)                           ::  zb1
7727      INTEGER(iwp)                           ::  nz
7728      INTEGER(iwp)                           ::  iz
7729      INTEGER(iwp)                           ::  zsgn
7730      INTEGER(iwp)                           ::  lowest_lad   !< lowest column cell for which we need LAD
7731      INTEGER(iwp)                           ::  lastdir      !< wall direction before hitting this column
7732      INTEGER(iwp), DIMENSION(2)             ::  lastcolumn
7733
7734#if defined( __parallel )
7735      INTEGER(MPI_ADDRESS_KIND)              ::  wdisp        !< RMA window displacement
7736#endif
7737     
7738      REAL(wp)                               ::  eps = 1E-10_wp !< epsilon for value comparison
7739      REAL(wp)                               ::  zbottom, ztop !< urban surface boundary in real numbers
7740      REAL(wp)                               ::  zorig         !< z coordinate of ray column entry
7741      REAL(wp)                               ::  zexit         !< z coordinate of ray column exit
7742      REAL(wp)                               ::  qdist         !< ratio of real distance to z coord difference
7743      REAL(wp)                               ::  dxxyy         !< square of real horizontal distance
7744      REAL(wp)                               ::  curtrans      !< transparency of current PC box crossing
7745     
7746
7747     
7748      yxorigin(:) = origin(2:3)
7749      transparency(:) = 1._wp !-- Pre-set the all rays to transparent before reducing
7750      horizon = -HUGE(1._wp)
7751      lowest_free_ray = nrays
7752      IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7753         ALLOCATE(target_surfl(nrays))
7754         target_surfl(:) = -1
7755         lastdir = -999
7756         lastcolumn(:) = -999
7757      ENDIF
7758
7759!--   Determine distance to boundary (in 2D xy)
7760      IF ( yxdir(1) > 0._wp )  THEN
7761         bdydim = ny + .5_wp !< north global boundary
7762         crossdist(1) = (bdydim - yxorigin(1)) / yxdir(1)
7763      ELSEIF ( yxdir(1) == 0._wp )  THEN
7764         crossdist(1) = HUGE(1._wp)
7765      ELSE
7766          bdydim = -.5_wp !< south global boundary
7767          crossdist(1) = (bdydim - yxorigin(1)) / yxdir(1)
7768      ENDIF
7769
7770      IF ( yxdir(2) > 0._wp )  THEN
7771          bdydim = nx + .5_wp !< east global boundary
7772          crossdist(2) = (bdydim - yxorigin(2)) / yxdir(2)
7773      ELSEIF ( yxdir(2) == 0._wp )  THEN
7774         crossdist(2) = HUGE(1._wp)
7775      ELSE
7776          bdydim = -.5_wp !< west global boundary
7777          crossdist(2) = (bdydim - yxorigin(2)) / yxdir(2)
7778      ENDIF
7779      distance = minval(crossdist, 1)
7780
7781      IF ( plant_canopy )  THEN
7782         rt2_track_dist(0) = 0._wp
7783         rt2_track_lad(:,:) = 0._wp
7784         nly = plantt_max - nz_urban_b + 1
7785      ENDIF
7786
7787      lastdist = 0._wp
7788
7789!--   Since all face coordinates have values *.5 and we'd like to use
7790!--   integers, all these have .5 added
7791      DO  d = 1, 2
7792          IF ( yxdir(d) == 0._wp )  THEN
7793              dimnext(d) = HUGE(1_iwp)
7794              dimdelta(d) = HUGE(1_iwp)
7795              dimnextdist(d) = HUGE(1._wp)
7796          ELSE IF ( yxdir(d) > 0._wp )  THEN
7797              dimnext(d) = FLOOR(yxorigin(d) + .5_wp) + 1
7798              dimdelta(d) = 1
7799              dimnextdist(d) = (dimnext(d) - .5_wp - yxorigin(d)) / yxdir(d)
7800          ELSE
7801              dimnext(d) = CEILING(yxorigin(d) + .5_wp) - 1
7802              dimdelta(d) = -1
7803              dimnextdist(d) = (dimnext(d) - .5_wp - yxorigin(d)) / yxdir(d)
7804          ENDIF
7805      ENDDO
7806
7807      ntrack = 0
7808      DO
7809!--      along what dimension will the next wall crossing be?
7810         seldim = minloc(dimnextdist, 1)
7811         nextdist = dimnextdist(seldim)
7812         IF ( nextdist > distance )  nextdist = distance
7813
7814         IF ( nextdist > lastdist )  THEN
7815            ntrack = ntrack + 1
7816            crmid = (lastdist + nextdist) * .5_wp
7817            column = NINT(yxorigin(:) + yxdir(:) * crmid, iwp)
7818
7819!--         calculate index of the grid with global indices (column(1),column(2))
7820!--         in the array nzterr and plantt and id of the coresponding processor
7821            px = column(2)/nnx
7822            py = column(1)/nny
7823            ip = px*pdims(2)+py
7824            ig = ip*nnx*nny + (column(2)-px*nnx)*nny + column(1)-py*nny
7825
7826            IF ( lastdist == 0._wp )  THEN
7827               horz_entry = -HUGE(1._wp)
7828            ELSE
7829               horz_entry = (REAL(nzterr(ig), wp) + .5_wp - origin(1)) / lastdist
7830            ENDIF
7831            horz_exit = (REAL(nzterr(ig), wp) + .5_wp - origin(1)) / nextdist
7832
7833            IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7834!
7835!--            Identify vertical obstacles hit by rays in current column
7836               DO WHILE ( lowest_free_ray > 0 )
7837                  IF ( zdirs(lowest_free_ray) > horz_entry )  EXIT
7838!
7839!--               This may only happen after 1st column, so lastdir and lastcolumn are valid
7840                  CALL request_itarget(lastdir,                                         &
7841                        CEILING(-0.5_wp + origin(1) + zdirs(lowest_free_ray)*lastdist), &
7842                        lastcolumn(1), lastcolumn(2),                                   &
7843                        target_surfl(lowest_free_ray), target_procs(lowest_free_ray))
7844                  lowest_free_ray = lowest_free_ray - 1
7845               ENDDO
7846!
7847!--            Identify horizontal obstacles hit by rays in current column
7848               DO WHILE ( lowest_free_ray > 0 )
7849                  IF ( zdirs(lowest_free_ray) > horz_exit )  EXIT
7850                  CALL request_itarget(iup_u, nzterr(ig)+1, column(1), column(2), &
7851                                       target_surfl(lowest_free_ray),           &
7852                                       target_procs(lowest_free_ray))
7853                  lowest_free_ray = lowest_free_ray - 1
7854               ENDDO
7855            ENDIF
7856
7857            horizon = MAX(horizon, horz_entry, horz_exit)
7858
7859            IF ( plant_canopy )  THEN
7860               rt2_track(:, ntrack) = column(:)
7861               rt2_track_dist(ntrack) = nextdist
7862            ENDIF
7863         ENDIF
7864
7865         IF ( nextdist + eps >= distance )  EXIT
7866
7867         IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7868!
7869!--         Save wall direction of coming building column (= this air column)
7870            IF ( seldim == 1 )  THEN
7871               IF ( dimdelta(seldim) == 1 )  THEN
7872                  lastdir = isouth_u
7873               ELSE
7874                  lastdir = inorth_u
7875               ENDIF
7876            ELSE
7877               IF ( dimdelta(seldim) == 1 )  THEN
7878                  lastdir = iwest_u
7879               ELSE
7880                  lastdir = ieast_u
7881               ENDIF
7882            ENDIF
7883            lastcolumn = column
7884         ENDIF
7885         lastdist = nextdist
7886         dimnext(seldim) = dimnext(seldim) + dimdelta(seldim)
7887         dimnextdist(seldim) = (dimnext(seldim) - .5_wp - yxorigin(seldim)) / yxdir(seldim)
7888      ENDDO
7889
7890      IF ( plant_canopy )  THEN
7891!--      Request LAD WHERE applicable
7892!--     
7893#if defined( __parallel )
7894         IF ( raytrace_mpi_rma )  THEN
7895!--         send requests for lad_s to appropriate processor
7896            !CALL cpu_log( log_point_s(77), 'usm_init_rma', 'start' )
7897            DO  i = 1, ntrack
7898               px = rt2_track(2,i)/nnx
7899               py = rt2_track(1,i)/nny
7900               ip = px*pdims(2)+py
7901               ig = ip*nnx*nny + (rt2_track(2,i)-px*nnx)*nny + rt2_track(1,i)-py*nny
7902
7903               IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7904!
7905!--               For fixed view resolution, we need plant canopy even for rays
7906!--               to opposing surfaces
7907                  lowest_lad = nzterr(ig) + 1
7908               ELSE
7909!
7910!--               We only need LAD for rays directed above horizon (to sky)
7911                  lowest_lad = CEILING( -0.5_wp + origin(1) +            &
7912                                    MIN( horizon * rt2_track_dist(i-1),  & ! entry
7913                                         horizon * rt2_track_dist(i)   ) ) ! exit
7914               ENDIF
7915!
7916!--            Skip asking for LAD where all plant canopy is under requested level
7917               IF ( plantt(ig) < lowest_lad )  CYCLE
7918
7919               wdisp = (rt2_track(2,i)-px*nnx)*(nny*nz_plant) + (rt2_track(1,i)-py*nny)*nz_plant + lowest_lad-nz_urban_b
7920               wcount = plantt(ig)-lowest_lad+1
7921               ! TODO send request ASAP - even during raytracing
7922               CALL MPI_Get(rt2_track_lad(lowest_lad:plantt(ig), i), wcount, MPI_REAL, ip,    &
7923                            wdisp, wcount, MPI_REAL, win_lad, ierr)
7924               IF ( ierr /= 0 )  THEN
7925                  WRITE(9,*) 'Error MPI_Get2:', ierr, rt2_track_lad(lowest_lad:plantt(ig), i), &
7926                             wcount, ip, wdisp, win_lad
7927                  FLUSH(9)
7928               ENDIF
7929            ENDDO
7930
7931!--         wait for all pending local requests complete
7932            ! TODO WAIT selectively for each column later when needed
7933            CALL MPI_Win_flush_local_all(win_lad, ierr)
7934            IF ( ierr /= 0 )  THEN
7935               WRITE(9,*) 'Error MPI_Win_flush_local_all2:', ierr, win_lad
7936               FLUSH(9)
7937            ENDIF
7938            !CALL cpu_log( log_point_s(77), 'usm_init_rma', 'stop' )
7939
7940         ELSE ! raytrace_mpi_rma = .F.
7941            DO  i = 1, ntrack
7942               px = rt2_track(2,i)/nnx
7943               py = rt2_track(1,i)/nny
7944               ip = px*pdims(2)+py
7945               ig = ip*nnx*nny*nz_plant + (rt2_track(2,i)-px*nnx)*(nny*nz_plant) + (rt2_track(1,i)-py*nny)*nz_plant
7946               rt2_track_lad(nz_urban_b:plantt_max, i) = sub_lad_g(ig:ig+nly-1)
7947            ENDDO
7948         ENDIF
7949#else
7950         DO  i = 1, ntrack
7951            rt2_track_lad(nz_urban_b:plantt_max, i) = sub_lad(rt2_track(1,i), rt2_track(2,i), nz_urban_b:plantt_max)
7952         ENDDO
7953#endif
7954      ENDIF ! plant_canopy
7955
7956      IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7957#if defined( __parallel )
7958!--      wait for all gridsurf requests to complete
7959         CALL MPI_Win_flush_local_all(win_gridsurf, ierr)
7960         IF ( ierr /= 0 )  THEN
7961            WRITE(9,*) 'Error MPI_Win_flush_local_all3:', ierr, win_gridsurf
7962            FLUSH(9)
7963         ENDIF
7964#endif
7965!
7966!--      recalculate local surf indices into global ones
7967         DO i = 1, nrays
7968            IF ( target_surfl(i) == -1 )  THEN
7969               itarget(i) = -1
7970            ELSE
7971               itarget(i) = target_surfl(i) + surfstart(target_procs(i))
7972            ENDIF
7973         ENDDO
7974         
7975         DEALLOCATE( target_surfl )
7976         
7977      ELSE
7978         itarget(:) = -1
7979      ENDIF ! rad_angular_discretization
7980
7981      IF ( plant_canopy )  THEN
7982!--      Skip the PCB around origin if requested (for MRT, the PCB might not be there)
7983!--     
7984         IF ( skip_1st_pcb  .AND.  NINT(origin(1)) <= plantt_max )  THEN
7985            rt2_track_lad(NINT(origin(1), iwp), 1) = 0._wp
7986         ENDIF
7987
7988!--      Assert that we have space allocated for CSFs
7989!--     
7990         maxboxes = (ntrack + MAX(CEILING(origin(1)-.5_wp) - nz_urban_b,          &
7991                                  nz_urban_t - CEILING(origin(1)-.5_wp))) * nrays
7992         IF ( ncsfl + maxboxes > ncsfla )  THEN
7993!--         use this code for growing by fixed exponential increments (equivalent to case where ncsfl always increases by 1)
7994!--         k = CEILING(grow_factor ** real(CEILING(log(real(ncsfl + maxboxes, kind=wp)) &
7995!--                                                / log(grow_factor)), kind=wp))
7996!--         or use this code to simply always keep some extra space after growing
7997            k = CEILING(REAL(ncsfl + maxboxes, kind=wp) * grow_factor)
7998            CALL merge_and_grow_csf(k)
7999         ENDIF
8000
8001!--      Calculate transparencies and store new CSFs
8002!--     
8003         zbottom = REAL(nz_urban_b, wp) - .5_wp
8004         ztop = REAL(plantt_max, wp) + .5_wp
8005
8006!--      Reverse direction of radiation (face->sky), only when calc_svf
8007!--     
8008         IF ( calc_svf )  THEN
8009            DO  i = 1, ntrack ! for each column
8010               dxxyy = ((dy*yxdir(1))**2 + (dx*yxdir(2))**2) * (rt2_track_dist(i)-rt2_track_dist(i-1))**2
8011               px = rt2_track(2,i)/nnx
8012               py = rt2_track(1,i)/nny
8013               ip = px*pdims(2)+py
8014
8015               DO  k = 1, nrays ! for each ray
8016!
8017!--               NOTE 6778:
8018!--               With traditional svf discretization, CSFs under the horizon
8019!--               (i.e. for surface to surface radiation)  are created in
8020!--               raytrace(). With rad_angular_discretization, we must create
8021!--               CSFs under horizon only for one direction, otherwise we would
8022!--               have duplicate amount of energy. Although we could choose
8023!--               either of the two directions (they differ only by
8024!--               discretization error with no bias), we choose the the backward
8025!--               direction, because it tends to cumulate high canopy sink
8026!--               factors closer to raytrace origin, i.e. it should potentially
8027!--               cause less moiree.
8028                  IF ( .NOT. rad_angular_discretization )  THEN
8029                     IF ( zdirs(k) <= horizon )  CYCLE
8030                  ENDIF
8031
8032                  zorig = origin(1) + zdirs(k) * rt2_track_dist(i-1)
8033                  IF ( zorig <= zbottom  .OR.  zorig >= ztop )  CYCLE
8034
8035                  zsgn = INT(SIGN(1._wp, zdirs(k)), iwp)
8036                  rt2_dist(1) = 0._wp
8037                  IF ( zdirs(k) == 0._wp )  THEN ! ray is exactly horizontal
8038                     nz = 2
8039                     rt2_dist(nz) = SQRT(dxxyy)
8040                     iz = CEILING(-.5_wp + zorig, iwp)
8041                  ELSE
8042                     zexit = MIN(MAX(origin(1) + zdirs(k) * rt2_track_dist(i), zbottom), ztop)
8043
8044                     zb0 = FLOOR(  zorig * zsgn - .5_wp) + 1  ! because it must be greater than orig
8045                     zb1 = CEILING(zexit * zsgn - .5_wp) - 1  ! because it must be smaller than exit
8046                     nz = MAX(zb1 - zb0 + 3, 2)
8047                     rt2_dist(nz) = SQRT(((zexit-zorig)*dz(1))**2 + dxxyy)
8048                     qdist = rt2_dist(nz) / (zexit-zorig)
8049                     rt2_dist(2:nz-1) = (/( ((REAL(l, wp) + .5_wp) * zsgn - zorig) * qdist , l = zb0, zb1 )/)
8050                     iz = zb0 * zsgn
8051                  ENDIF
8052
8053                  DO  l = 2, nz
8054                     IF ( rt2_track_lad(iz, i) > 0._wp )  THEN
8055                        curtrans = exp(-ext_coef * rt2_track_lad(iz, i) * (rt2_dist(l)-rt2_dist(l-1)))
8056
8057                        IF ( create_csf )  THEN
8058                           ncsfl = ncsfl + 1
8059                           acsf(ncsfl)%ip = ip
8060                           acsf(ncsfl)%itx = rt2_track(2,i)
8061                           acsf(ncsfl)%ity = rt2_track(1,i)
8062                           acsf(ncsfl)%itz = iz
8063                           acsf(ncsfl)%isurfs = iorig
8064                           acsf(ncsfl)%rcvf = (1._wp - curtrans)*transparency(k)*vffrac(k)
8065                        ENDIF
8066
8067                        transparency(k) = transparency(k) * curtrans
8068                     ENDIF
8069                     iz = iz + zsgn
8070                  ENDDO ! l = 1, nz - 1
8071               ENDDO ! k = 1, nrays
8072            ENDDO ! i = 1, ntrack
8073
8074            transparency(1:lowest_free_ray) = 1._wp !-- Reset rays above horizon to transparent (see NOTE 6778)
8075         ENDIF
8076
8077!--      Forward direction of radiation (sky->face), always
8078!--     
8079         DO  i = ntrack, 1, -1 ! for each column backwards
8080            dxxyy = ((dy*yxdir(1))**2 + (dx*yxdir(2))**2) * (rt2_track_dist(i)-rt2_track_dist(i-1))**2
8081            px = rt2_track(2,i)/nnx
8082            py = rt2_track(1,i)/nny
8083            ip = px*pdims(2)+py
8084
8085            DO  k = 1, nrays ! for each ray
8086!
8087!--            See NOTE 6778 above
8088               IF ( zdirs(k) <= horizon )  CYCLE
8089
8090               zexit = origin(1) + zdirs(k) * rt2_track_dist(i-1)
8091               IF ( zexit <= zbottom  .OR.  zexit >= ztop )  CYCLE
8092
8093               zsgn = -INT(SIGN(1._wp, zdirs(k)), iwp)
8094               rt2_dist(1) = 0._wp
8095               IF ( zdirs(k) == 0._wp )  THEN ! ray is exactly horizontal
8096                  nz = 2
8097                  rt2_dist(nz) = SQRT(dxxyy)
8098                  iz = NINT(zexit, iwp)
8099               ELSE
8100                  zorig = MIN(MAX(origin(1) + zdirs(k) * rt2_track_dist(i), zbottom), ztop)
8101
8102                  zb0 = FLOOR(  zorig * zsgn - .5_wp) + 1  ! because it must be greater than orig
8103                  zb1 = CEILING(zexit * zsgn - .5_wp) - 1  ! because it must be smaller than exit
8104                  nz = MAX(zb1 - zb0 + 3, 2)
8105                  rt2_dist(nz) = SQRT(((zexit-zorig)*dz(1))**2 + dxxyy)
8106                  qdist = rt2_dist(nz) / (zexit-zorig)
8107                  rt2_dist(2:nz-1) = (/( ((REAL(l, wp) + .5_wp) * zsgn - zorig) * qdist , l = zb0, zb1 )/)
8108                  iz = zb0 * zsgn
8109               ENDIF
8110
8111               DO  l = 2, nz
8112                  IF ( rt2_track_lad(iz, i) > 0._wp )  THEN
8113                     curtrans = exp(-ext_coef * rt2_track_lad(iz, i) * (rt2_dist(l)-rt2_dist(l-1)))
8114
8115                     IF ( create_csf )  THEN
8116                        ncsfl = ncsfl + 1
8117                        acsf(ncsfl)%ip = ip
8118                        acsf(ncsfl)%itx = rt2_track(2,i)
8119                        acsf(ncsfl)%ity = rt2_track(1,i)
8120                        acsf(ncsfl)%itz = iz
8121                        IF ( itarget(k) /= -1 ) STOP 1 !FIXME remove after test
8122                        acsf(ncsfl)%isurfs = -1
8123                        acsf(ncsfl)%rcvf = (1._wp - curtrans)*transparency(k)*aorig*vffrac(k)
8124                     ENDIF  ! create_csf
8125
8126                     transparency(k) = transparency(k) * curtrans
8127                  ENDIF
8128                  iz = iz + zsgn
8129               ENDDO ! l = 1, nz - 1
8130            ENDDO ! k = 1, nrays
8131         ENDDO ! i = 1, ntrack
8132      ENDIF ! plant_canopy
8133
8134      IF ( .NOT. (rad_angular_discretization  .AND.  calc_svf) )  THEN
8135!
8136!--      Just update lowest_free_ray according to horizon
8137         DO WHILE ( lowest_free_ray > 0 )
8138            IF ( zdirs(lowest_free_ray) > horizon )  EXIT
8139            lowest_free_ray = lowest_free_ray - 1
8140         ENDDO
8141      ENDIF
8142
8143   CONTAINS
8144
8145      SUBROUTINE request_itarget( d, z, y, x, isurfl, iproc )
8146
8147         INTEGER(iwp), INTENT(in)            ::  d, z, y, x
8148         INTEGER(iwp), TARGET, INTENT(out)   ::  isurfl
8149         INTEGER(iwp), INTENT(out)           ::  iproc
8150#if defined( __parallel )
8151#else
8152         INTEGER(iwp)                        ::  target_displ  !< index of the grid in the local gridsurf array
8153#endif
8154         INTEGER(iwp)                        ::  px, py        !< number of processors in x and y direction
8155                                                               !< before the processor in the question
8156#if defined( __parallel )
8157         INTEGER(KIND=MPI_ADDRESS_KIND)      ::  target_displ  !< index of the grid in the local gridsurf array
8158
8159!
8160!--      Calculate target processor and index in the remote local target gridsurf array
8161         px = x / nnx
8162         py = y / nny
8163         iproc = px * pdims(2) + py
8164         target_displ = ((x-px*nnx) * nny + y - py*nny ) * nz_urban * nsurf_type_u +&
8165                        ( z-nz_urban_b ) * nsurf_type_u + d
8166!
8167!--      Send MPI_Get request to obtain index target_surfl(i)
8168         CALL MPI_GET( isurfl, 1, MPI_INTEGER, iproc, target_displ,            &
8169                       1, MPI_INTEGER, win_gridsurf, ierr)
8170         IF ( ierr /= 0 )  THEN
8171            WRITE( 9,* ) 'Error MPI_Get3:', ierr, isurfl, iproc, target_displ, &
8172                         win_gridsurf
8173            FLUSH( 9 )
8174         ENDIF
8175#else
8176!--      set index target_surfl(i)
8177         isurfl = gridsurf(d,z,y,x)
8178#endif
8179
8180      END SUBROUTINE request_itarget
8181
8182   END SUBROUTINE raytrace_2d
8183 
8184
8185!------------------------------------------------------------------------------!
8186!
8187! Description:
8188! ------------
8189!> Calculates apparent solar positions for all timesteps and stores discretized
8190!> positions.
8191!------------------------------------------------------------------------------!
8192   SUBROUTINE radiation_presimulate_solar_pos
8193
8194      IMPLICIT NONE
8195
8196      INTEGER(iwp)                              ::  it, i, j
8197      INTEGER(iwp)                              ::  day_of_month_prev,month_of_year_prev
8198      REAL(wp)                                  ::  tsrp_prev
8199      REAL(wp)                                  ::  simulated_time_prev
8200      REAL(wp), DIMENSION(:,:), ALLOCATABLE     ::  dsidir_tmp       !< dsidir_tmp[:,i] = unit vector of i-th
8201                                                                     !< appreant solar direction
8202
8203      ALLOCATE ( dsidir_rev(0:raytrace_discrete_elevs/2-1,                 &
8204                            0:raytrace_discrete_azims-1) )
8205      dsidir_rev(:,:) = -1
8206      ALLOCATE ( dsidir_tmp(3,                                             &
8207                     raytrace_discrete_elevs/2*raytrace_discrete_azims) )
8208      ndsidir = 0
8209
8210!
8211!--   We will artificialy update time_since_reference_point and return to
8212!--   true value later
8213      tsrp_prev = time_since_reference_point
8214      simulated_time_prev = simulated_time
8215      day_of_month_prev = day_of_month
8216      month_of_year_prev = month_of_year
8217      sun_direction = .TRUE.
8218
8219!
8220!--   initialize the simulated_time
8221      simulated_time = 0._wp
8222!
8223!--   Process spinup time if configured
8224      IF ( spinup_time > 0._wp )  THEN
8225         DO  it = 0, CEILING(spinup_time / dt_spinup)
8226            time_since_reference_point = -spinup_time + REAL(it, wp) * dt_spinup
8227            simulated_time = simulated_time + dt_spinup
8228            CALL simulate_pos
8229         ENDDO
8230      ENDIF
8231!
8232!--   Process simulation time
8233      DO  it = 0, CEILING(( end_time - spinup_time ) / dt_radiation)
8234         time_since_reference_point = REAL(it, wp) * dt_radiation
8235         simulated_time = simulated_time + dt_radiation
8236         CALL simulate_pos
8237      ENDDO
8238!
8239!--   Return date and time to its original values
8240      time_since_reference_point = tsrp_prev
8241      simulated_time = simulated_time_prev
8242      day_of_month = day_of_month_prev
8243      month_of_year = month_of_year_prev
8244      CALL init_date_and_time
8245
8246!--   Allocate global vars which depend on ndsidir
8247      ALLOCATE ( dsidir ( 3, ndsidir ) )
8248      dsidir(:,:) = dsidir_tmp(:, 1:ndsidir)
8249      DEALLOCATE ( dsidir_tmp )
8250
8251      ALLOCATE ( dsitrans(nsurfl, ndsidir) )
8252      ALLOCATE ( dsitransc(npcbl, ndsidir) )
8253      IF ( nmrtbl > 0 )  ALLOCATE ( mrtdsit(nmrtbl, ndsidir) )
8254
8255      WRITE ( message_string, * ) 'Precalculated', ndsidir, ' solar positions', &
8256                                  'from', it, ' timesteps.'
8257      CALL message( 'radiation_presimulate_solar_pos', 'UI0013', 0, 0, 0, 6, 0 )
8258
8259      CONTAINS
8260
8261      !------------------------------------------------------------------------!
8262      ! Description:
8263      ! ------------
8264      !> Simuates a single position
8265      !------------------------------------------------------------------------!
8266      SUBROUTINE simulate_pos
8267         IMPLICIT NONE
8268!
8269!--      Update apparent solar position based on modified t_s_r_p
8270         CALL calc_zenith
8271         IF ( cos_zenith > 0 )  THEN
8272!--         
8273!--         Identify solar direction vector (discretized number) 1)
8274            i = MODULO(NINT(ATAN2(sun_dir_lon, sun_dir_lat)               &
8275                            / (2._wp*pi) * raytrace_discrete_azims-.5_wp, iwp), &
8276                       raytrace_discrete_azims)
8277            j = FLOOR(ACOS(cos_zenith) / pi * raytrace_discrete_elevs)
8278            IF ( dsidir_rev(j, i) == -1 )  THEN
8279               ndsidir = ndsidir + 1
8280               dsidir_tmp(:, ndsidir) =                                              &
8281                     (/ COS((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs), &
8282                        SIN((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs)  &
8283                      * COS((REAL(i,wp)+.5_wp) * 2_wp*pi / raytrace_discrete_azims), &
8284                        SIN((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs)  &
8285                      * SIN((REAL(i,wp)+.5_wp) * 2_wp*pi / raytrace_discrete_azims) /)
8286               dsidir_rev(j, i) = ndsidir
8287            ENDIF
8288         ENDIF
8289      END SUBROUTINE simulate_pos
8290
8291   END SUBROUTINE radiation_presimulate_solar_pos
8292
8293
8294
8295!------------------------------------------------------------------------------!
8296! Description:
8297! ------------
8298!> Determines whether two faces are oriented towards each other. Since the
8299!> surfaces follow the gird box surfaces, it checks first whether the two surfaces
8300!> are directed in the same direction, then it checks if the two surfaces are
8301!> located in confronted direction but facing away from each other, e.g. <--| |-->
8302!------------------------------------------------------------------------------!
8303    PURE LOGICAL FUNCTION surface_facing(x, y, z, d, x2, y2, z2, d2)
8304        IMPLICIT NONE
8305        INTEGER(iwp),   INTENT(in)  :: x, y, z, d, x2, y2, z2, d2
8306     
8307        surface_facing = .FALSE.
8308
8309!-- first check: are the two surfaces directed in the same direction
8310        IF ( (d==iup_u  .OR.  d==iup_l )                             &
8311             .AND. (d2==iup_u  .OR. d2==iup_l) ) RETURN
8312        IF ( (d==isouth_u  .OR.  d==isouth_l ) &
8313             .AND.  (d2==isouth_u  .OR.  d2==isouth_l) ) RETURN
8314        IF ( (d==inorth_u  .OR.  d==inorth_l ) &
8315             .AND.  (d2==inorth_u  .OR.  d2==inorth_l) ) RETURN
8316        IF ( (d==iwest_u  .OR.  d==iwest_l )     &
8317             .AND.  (d2==iwest_u  .OR.  d2==iwest_l ) ) RETURN
8318        IF ( (d==ieast_u  .OR.  d==ieast_l )     &
8319             .AND.  (d2==ieast_u  .OR.  d2==ieast_l ) ) RETURN
8320
8321!-- second check: are surfaces facing away from each other
8322        SELECT CASE (d)
8323            CASE (iup_u, iup_l)                     !< upward facing surfaces
8324                IF ( z2 < z ) RETURN
8325            CASE (isouth_u, isouth_l)               !< southward facing surfaces
8326                IF ( y2 > y ) RETURN
8327            CASE (inorth_u, inorth_l)               !< northward facing surfaces
8328                IF ( y2 < y ) RETURN
8329            CASE (iwest_u, iwest_l)                 !< westward facing surfaces
8330                IF ( x2 > x ) RETURN
8331            CASE (ieast_u, ieast_l)                 !< eastward facing surfaces
8332                IF ( x2 < x ) RETURN
8333        END SELECT
8334
8335        SELECT CASE (d2)
8336            CASE (iup_u)                            !< ground, roof
8337                IF ( z < z2 ) RETURN
8338            CASE (isouth_u, isouth_l)               !< south facing
8339                IF ( y > y2 ) RETURN
8340            CASE (inorth_u, inorth_l)               !< north facing
8341                IF ( y < y2 ) RETURN
8342            CASE (iwest_u, iwest_l)                 !< west facing
8343                IF ( x > x2 ) RETURN
8344            CASE (ieast_u, ieast_l)                 !< east facing
8345                IF ( x < x2 ) RETURN
8346            CASE (-1)
8347                CONTINUE
8348        END SELECT
8349
8350        surface_facing = .TRUE.
8351       
8352    END FUNCTION surface_facing
8353
8354
8355!------------------------------------------------------------------------------!
8356!
8357! Description:
8358! ------------
8359!> Reads svf, svfsurf, csf, csfsurf and mrt factors data from saved file
8360!> SVF means sky view factors and CSF means canopy sink factors
8361!------------------------------------------------------------------------------!
8362    SUBROUTINE radiation_read_svf
8363
8364       IMPLICIT NONE
8365       
8366       CHARACTER(rad_version_len)   :: rad_version_field
8367       
8368       INTEGER(iwp)                 :: i
8369       INTEGER(iwp)                 :: ndsidir_from_file = 0
8370       INTEGER(iwp)                 :: npcbl_from_file = 0
8371       INTEGER(iwp)                 :: nsurfl_from_file = 0
8372       INTEGER(iwp)                 :: nmrtbl_from_file = 0
8373       
8374       DO  i = 0, io_blocks-1
8375          IF ( i == io_group )  THEN
8376
8377!
8378!--          numprocs_previous_run is only known in case of reading restart
8379!--          data. If a new initial run which reads svf data is started the
8380!--          following query will be skipped
8381             IF ( initializing_actions == 'read_restart_data' ) THEN
8382
8383                IF ( numprocs_previous_run /= numprocs ) THEN
8384                   WRITE( message_string, * ) 'A different number of ',        &
8385                                              'processors between the run ',   &
8386                                              'that has written the svf data ',&
8387                                              'and the one that will read it ',&
8388                                              'is not allowed' 
8389                   CALL message( 'check_open', 'PA0491', 1, 2, 0, 6, 0 )
8390                ENDIF
8391
8392             ENDIF
8393             
8394!
8395!--          Open binary file
8396             CALL check_open( 88 )
8397
8398!
8399!--          read and check version
8400             READ ( 88 ) rad_version_field
8401             IF ( TRIM(rad_version_field) /= TRIM(rad_version) )  THEN
8402                 WRITE( message_string, * ) 'Version of binary SVF file "',    &
8403                             TRIM(rad_version_field), '" does not match ',     &
8404                             'the version of model "', TRIM(rad_version), '"'
8405                 CALL message( 'radiation_read_svf', 'PA0482', 1, 2, 0, 6, 0 )
8406             ENDIF
8407             
8408!
8409!--          read nsvfl, ncsfl, nsurfl, nmrtf
8410             READ ( 88 ) nsvfl, ncsfl, nsurfl_from_file, npcbl_from_file,      &
8411                         ndsidir_from_file, nmrtbl_from_file, nmrtf
8412             
8413             IF ( nsvfl < 0  .OR.  ncsfl < 0 )  THEN
8414                 WRITE( message_string, * ) 'Wrong number of SVF or CSF'
8415                 CALL message( 'radiation_read_svf', 'PA0483', 1, 2, 0, 6, 0 )
8416             ELSE
8417                 WRITE(message_string,*) '    Number of SVF, CSF, and nsurfl ',&
8418                                         'to read', nsvfl, ncsfl,              &
8419                                         nsurfl_from_file
8420                 CALL location_message( message_string, .TRUE. )
8421             ENDIF
8422             
8423             IF ( nsurfl_from_file /= nsurfl )  THEN
8424                 WRITE( message_string, * ) 'nsurfl from SVF file does not ',  &
8425                                            'match calculated nsurfl from ',   &
8426                                            'radiation_interaction_init'
8427                 CALL message( 'radiation_read_svf', 'PA0490', 1, 2, 0, 6, 0 )
8428             ENDIF
8429             
8430             IF ( npcbl_from_file /= npcbl )  THEN
8431                 WRITE( message_string, * ) 'npcbl from SVF file does not ',   &
8432                                            'match calculated npcbl from ',    &
8433                                            'radiation_interaction_init'
8434                 CALL message( 'radiation_read_svf', 'PA0493', 1, 2, 0, 6, 0 )
8435             ENDIF
8436             
8437             IF ( ndsidir_from_file /= ndsidir )  THEN
8438                 WRITE( message_string, * ) 'ndsidir from SVF file does not ', &
8439                                            'match calculated ndsidir from ',  &
8440                                            'radiation_presimulate_solar_pos'
8441                 CALL message( 'radiation_read_svf', 'PA0494', 1, 2, 0, 6, 0 )
8442             ENDIF
8443             IF ( nmrtbl_from_file /= nmrtbl )  THEN
8444                 WRITE( message_string, * ) 'nmrtbl from SVF file does not ',  &
8445                                            'match calculated nmrtbl from ',   &
8446                                            'radiation_interaction_init'
8447                 CALL message( 'radiation_read_svf', 'PA0494', 1, 2, 0, 6, 0 )
8448             ELSE
8449                 WRITE(message_string,*) '    Number of nmrtf to read ', nmrtf
8450                 CALL location_message( message_string, .TRUE. )
8451             ENDIF
8452             
8453!
8454!--          Arrays skyvf, skyvft, dsitrans and dsitransc are allready
8455!--          allocated in radiation_interaction_init and
8456!--          radiation_presimulate_solar_pos
8457             IF ( nsurfl > 0 )  THEN
8458                READ(88) skyvf
8459                READ(88) skyvft
8460                READ(88) dsitrans 
8461             ENDIF
8462             
8463             IF ( plant_canopy  .AND.  npcbl > 0 ) THEN
8464                READ ( 88 )  dsitransc
8465             ENDIF
8466             
8467!
8468!--          The allocation of svf, svfsurf, csf, csfsurf, mrtf, mrtft, and
8469!--          mrtfsurf happens in routine radiation_calc_svf which is not
8470!--          called if the program enters radiation_read_svf. Therefore
8471!--          these arrays has to allocate in the following
8472             IF ( nsvfl > 0 )  THEN
8473                ALLOCATE( svf(ndsvf,nsvfl) )
8474                ALLOCATE( svfsurf(idsvf,nsvfl) )
8475                READ(88) svf
8476                READ(88) svfsurf
8477             ENDIF
8478
8479             IF ( plant_canopy  .AND.  ncsfl > 0 )  THEN
8480                ALLOCATE( csf(ndcsf,ncsfl) )
8481                ALLOCATE( csfsurf(idcsf,ncsfl) )
8482                READ(88) csf
8483                READ(88) csfsurf
8484             ENDIF
8485
8486             IF ( nmrtbl > 0 )  THEN
8487                READ(88) mrtsky
8488                READ(88) mrtskyt
8489                READ(88) mrtdsit
8490             ENDIF
8491
8492             IF ( nmrtf > 0 )  THEN
8493                ALLOCATE ( mrtf(nmrtf) )
8494                ALLOCATE ( mrtft(nmrtf) )
8495                ALLOCATE ( mrtfsurf(2,nmrtf) )
8496                READ(88) mrtf
8497                READ(88) mrtft
8498                READ(88) mrtfsurf
8499             ENDIF
8500             
8501!
8502!--          Close binary file                 
8503             CALL close_file( 88 )
8504               
8505          ENDIF
8506#if defined( __parallel )
8507          CALL MPI_BARRIER( comm2d, ierr )
8508#endif
8509       ENDDO
8510
8511    END SUBROUTINE radiation_read_svf
8512
8513
8514!------------------------------------------------------------------------------!
8515!
8516! Description:
8517! ------------
8518!> Subroutine stores svf, svfsurf, csf, csfsurf and mrt data to a file.
8519!------------------------------------------------------------------------------!
8520    SUBROUTINE radiation_write_svf
8521
8522       IMPLICIT NONE
8523       
8524       INTEGER(iwp)        :: i
8525
8526       DO  i = 0, io_blocks-1
8527          IF ( i == io_group )  THEN
8528!
8529!--          Open binary file
8530             CALL check_open( 89 )
8531
8532             WRITE ( 89 )  rad_version
8533             WRITE ( 89 )  nsvfl, ncsfl, nsurfl, npcbl, ndsidir, nmrtbl, nmrtf
8534             IF ( nsurfl > 0 ) THEN
8535                WRITE ( 89 )  skyvf
8536                WRITE ( 89 )  skyvft
8537                WRITE ( 89 )  dsitrans
8538             ENDIF
8539             IF ( npcbl > 0 ) THEN
8540                WRITE ( 89 )  dsitransc
8541             ENDIF
8542             IF ( nsvfl > 0 ) THEN
8543                WRITE ( 89 )  svf
8544                WRITE ( 89 )  svfsurf
8545             ENDIF
8546             IF ( plant_canopy  .AND.  ncsfl > 0 )  THEN
8547                 WRITE ( 89 )  csf
8548                 WRITE ( 89 )  csfsurf
8549             ENDIF
8550             IF ( nmrtbl > 0 )  THEN
8551                WRITE ( 89 ) mrtsky
8552                WRITE ( 89 ) mrtskyt
8553                WRITE ( 89 ) mrtdsit
8554             ENDIF
8555             IF ( nmrtf > 0 )  THEN
8556                 WRITE ( 89 )  mrtf
8557                 WRITE ( 89 )  mrtft               
8558                 WRITE ( 89 )  mrtfsurf
8559             ENDIF
8560!
8561!--          Close binary file                 
8562             CALL close_file( 89 )
8563
8564          ENDIF
8565#if defined( __parallel )
8566          CALL MPI_BARRIER( comm2d, ierr )
8567#endif
8568       ENDDO
8569    END SUBROUTINE radiation_write_svf
8570
8571
8572!------------------------------------------------------------------------------!
8573!
8574! Description:
8575! ------------
8576!> Block of auxiliary subroutines:
8577!> 1. quicksort and corresponding comparison
8578!> 2. merge_and_grow_csf for implementation of "dynamical growing"
8579!>    array for csf
8580!------------------------------------------------------------------------------!
8581!-- quicksort.f -*-f90-*-
8582!-- Author: t-nissie, adaptation J.Resler
8583!-- License: GPLv3
8584!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8585    RECURSIVE SUBROUTINE quicksort_itarget(itarget, vffrac, ztransp, first, last)
8586        IMPLICIT NONE
8587        INTEGER(iwp), DIMENSION(:), INTENT(INOUT)   :: itarget
8588        REAL(wp), DIMENSION(:), INTENT(INOUT)       :: vffrac, ztransp
8589        INTEGER(iwp), INTENT(IN)                    :: first, last
8590        INTEGER(iwp)                                :: x, t
8591        INTEGER(iwp)                                :: i, j
8592        REAL(wp)                                    :: tr
8593
8594        IF ( first>=last ) RETURN
8595        x = itarget((first+last)/2)
8596        i = first
8597        j = last
8598        DO
8599            DO WHILE ( itarget(i) < x )
8600               i=i+1
8601            ENDDO
8602            DO WHILE ( x < itarget(j) )
8603                j=j-1
8604            ENDDO
8605            IF ( i >= j ) EXIT
8606            t = itarget(i);  itarget(i) = itarget(j);  itarget(j) = t
8607            tr = vffrac(i);  vffrac(i) = vffrac(j);  vffrac(j) = tr
8608            tr = ztransp(i);  ztransp(i) = ztransp(j);  ztransp(j) = tr
8609            i=i+1
8610            j=j-1
8611        ENDDO
8612        IF ( first < i-1 ) CALL quicksort_itarget(itarget, vffrac, ztransp, first, i-1)
8613        IF ( j+1 < last )  CALL quicksort_itarget(itarget, vffrac, ztransp, j+1, last)
8614    END SUBROUTINE quicksort_itarget
8615
8616    PURE FUNCTION svf_lt(svf1,svf2) result (res)
8617      TYPE (t_svf), INTENT(in) :: svf1,svf2
8618      LOGICAL                  :: res
8619      IF ( svf1%isurflt < svf2%isurflt  .OR.    &
8620          (svf1%isurflt == svf2%isurflt  .AND.  svf1%isurfs < svf2%isurfs) )  THEN
8621          res = .TRUE.
8622      ELSE
8623          res = .FALSE.
8624      ENDIF
8625    END FUNCTION svf_lt
8626
8627
8628!-- quicksort.f -*-f90-*-
8629!-- Author: t-nissie, adaptation J.Resler
8630!-- License: GPLv3
8631!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8632    RECURSIVE SUBROUTINE quicksort_svf(svfl, first, last)
8633        IMPLICIT NONE
8634        TYPE(t_svf), DIMENSION(:), INTENT(INOUT)  :: svfl
8635        INTEGER(iwp), INTENT(IN)                  :: first, last
8636        TYPE(t_svf)                               :: x, t
8637        INTEGER(iwp)                              :: i, j
8638
8639        IF ( first>=last ) RETURN
8640        x = svfl( (first+last) / 2 )
8641        i = first
8642        j = last
8643        DO
8644            DO while ( svf_lt(svfl(i),x) )
8645               i=i+1
8646            ENDDO
8647            DO while ( svf_lt(x,svfl(j)) )
8648                j=j-1
8649            ENDDO
8650            IF ( i >= j ) EXIT
8651            t = svfl(i);  svfl(i) = svfl(j);  svfl(j) = t
8652            i=i+1
8653            j=j-1
8654        ENDDO
8655        IF ( first < i-1 ) CALL quicksort_svf(svfl, first, i-1)
8656        IF ( j+1 < last )  CALL quicksort_svf(svfl, j+1, last)
8657    END SUBROUTINE quicksort_svf
8658
8659    PURE FUNCTION csf_lt(csf1,csf2) result (res)
8660      TYPE (t_csf), INTENT(in) :: csf1,csf2
8661      LOGICAL                  :: res
8662      IF ( csf1%ip < csf2%ip  .OR.    &
8663           (csf1%ip == csf2%ip  .AND.  csf1%itx < csf2%itx)  .OR.  &
8664           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity < csf2%ity)  .OR.  &
8665           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity == csf2%ity  .AND.   &
8666            csf1%itz < csf2%itz)  .OR.  &
8667           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity == csf2%ity  .AND.   &
8668            csf1%itz == csf2%itz  .AND.  csf1%isurfs < csf2%isurfs) )  THEN
8669          res = .TRUE.
8670      ELSE
8671          res = .FALSE.
8672      ENDIF
8673    END FUNCTION csf_lt
8674
8675
8676!-- quicksort.f -*-f90-*-
8677!-- Author: t-nissie, adaptation J.Resler
8678!-- License: GPLv3
8679!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8680    RECURSIVE SUBROUTINE quicksort_csf(csfl, first, last)
8681        IMPLICIT NONE
8682        TYPE(t_csf), DIMENSION(:), INTENT(INOUT)  :: csfl
8683        INTEGER(iwp), INTENT(IN)                  :: first, last
8684        TYPE(t_csf)                               :: x, t
8685        INTEGER(iwp)                              :: i, j
8686
8687        IF ( first>=last ) RETURN
8688        x = csfl( (first+last)/2 )
8689        i = first
8690        j = last
8691        DO
8692            DO while ( csf_lt(csfl(i),x) )
8693                i=i+1
8694            ENDDO
8695            DO while ( csf_lt(x,csfl(j)) )
8696                j=j-1
8697            ENDDO
8698            IF ( i >= j ) EXIT
8699            t = csfl(i);  csfl(i) = csfl(j);  csfl(j) = t
8700            i=i+1
8701            j=j-1
8702        ENDDO
8703        IF ( first < i-1 ) CALL quicksort_csf(csfl, first, i-1)
8704        IF ( j+1 < last )  CALL quicksort_csf(csfl, j+1, last)
8705    END SUBROUTINE quicksort_csf
8706
8707   
8708!------------------------------------------------------------------------------!
8709!
8710! Description:
8711! ------------
8712!> Grows the CSF array exponentially after it is full. During that, the ray
8713!> canopy sink factors with common source face and target plant canopy grid
8714!> cell are merged together so that the size doesn't grow out of control.
8715!------------------------------------------------------------------------------!
8716    SUBROUTINE merge_and_grow_csf(newsize)
8717        INTEGER(iwp), INTENT(in)                :: newsize  !< new array size after grow, must be >= ncsfl
8718                                                            !< or -1 to shrink to minimum
8719        INTEGER(iwp)                            :: iread, iwrite
8720        TYPE(t_csf), DIMENSION(:), POINTER      :: acsfnew
8721        CHARACTER(100)                          :: msg
8722
8723        IF ( newsize == -1 )  THEN
8724!--         merge in-place
8725            acsfnew => acsf
8726        ELSE
8727!--         allocate new array
8728            IF ( mcsf == 0 )  THEN
8729                ALLOCATE( acsf1(newsize) )
8730                acsfnew => acsf1
8731            ELSE
8732                ALLOCATE( acsf2(newsize) )
8733                acsfnew => acsf2
8734            ENDIF
8735        ENDIF
8736
8737        IF ( ncsfl >= 1 )  THEN
8738!--         sort csf in place (quicksort)
8739            CALL quicksort_csf(acsf,1,ncsfl)
8740
8741!--         while moving to a new array, aggregate canopy sink factor records with identical box & source
8742            acsfnew(1) = acsf(1)
8743            iwrite = 1
8744            DO iread = 2, ncsfl
8745!--             here acsf(kcsf) already has values from acsf(icsf)
8746                IF ( acsfnew(iwrite)%itx == acsf(iread)%itx &
8747                         .AND.  acsfnew(iwrite)%ity == acsf(iread)%ity &
8748                         .AND.  acsfnew(iwrite)%itz == acsf(iread)%itz &
8749                         .AND.  acsfnew(iwrite)%isurfs == acsf(iread)%isurfs )  THEN
8750
8751                    acsfnew(iwrite)%rcvf = acsfnew(iwrite)%rcvf + acsf(iread)%rcvf
8752!--                 advance reading index, keep writing index
8753                ELSE
8754!--                 not identical, just advance and copy
8755                    iwrite = iwrite + 1
8756                    acsfnew(iwrite) = acsf(iread)
8757                ENDIF
8758            ENDDO
8759            ncsfl = iwrite
8760        ENDIF
8761
8762        IF ( newsize == -1 )  THEN
8763!--         allocate new array and copy shrinked data
8764            IF ( mcsf == 0 )  THEN
8765                ALLOCATE( acsf1(ncsfl) )
8766                acsf1(1:ncsfl) = acsf2(1:ncsfl)
8767            ELSE
8768                ALLOCATE( acsf2(ncsfl) )
8769                acsf2(1:ncsfl) = acsf1(1:ncsfl)
8770            ENDIF
8771        ENDIF
8772
8773!--     deallocate old array
8774        IF ( mcsf == 0 )  THEN
8775            mcsf = 1
8776            acsf => acsf1
8777            DEALLOCATE( acsf2 )
8778        ELSE
8779            mcsf = 0
8780            acsf => acsf2
8781            DEALLOCATE( acsf1 )
8782        ENDIF
8783        ncsfla = newsize
8784
8785        WRITE(msg,'(A,2I12)') 'Grow acsf2:',ncsfl,ncsfla
8786        CALL radiation_write_debug_log( msg )
8787
8788    END SUBROUTINE merge_and_grow_csf
8789
8790   
8791!-- quicksort.f -*-f90-*-
8792!-- Author: t-nissie, adaptation J.Resler
8793!-- License: GPLv3
8794!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8795    RECURSIVE SUBROUTINE quicksort_csf2(kpcsflt, pcsflt, first, last)
8796        IMPLICIT NONE
8797        INTEGER(iwp), DIMENSION(:,:), INTENT(INOUT)  :: kpcsflt
8798        REAL(wp), DIMENSION(:,:), INTENT(INOUT)      :: pcsflt
8799        INTEGER(iwp), INTENT(IN)                     :: first, last
8800        REAL(wp), DIMENSION(ndcsf)                   :: t2
8801        INTEGER(iwp), DIMENSION(kdcsf)               :: x, t1
8802        INTEGER(iwp)                                 :: i, j
8803
8804        IF ( first>=last ) RETURN
8805        x = kpcsflt(:, (first+last)/2 )
8806        i = first
8807        j = last
8808        DO
8809            DO while ( csf_lt2(kpcsflt(:,i),x) )
8810                i=i+1
8811            ENDDO
8812            DO while ( csf_lt2(x,kpcsflt(:,j)) )
8813                j=j-1
8814            ENDDO
8815            IF ( i >= j ) EXIT
8816            t1 = kpcsflt(:,i);  kpcsflt(:,i) = kpcsflt(:,j);  kpcsflt(:,j) = t1
8817            t2 = pcsflt(:,i);  pcsflt(:,i) = pcsflt(:,j);  pcsflt(:,j) = t2
8818            i=i+1
8819            j=j-1
8820        ENDDO
8821        IF ( first < i-1 ) CALL quicksort_csf2(kpcsflt, pcsflt, first, i-1)
8822        IF ( j+1 < last )  CALL quicksort_csf2(kpcsflt, pcsflt, j+1, last)
8823    END SUBROUTINE quicksort_csf2
8824   
8825
8826    PURE FUNCTION csf_lt2(item1, item2) result(res)
8827        INTEGER(iwp), DIMENSION(kdcsf), INTENT(in)  :: item1, item2
8828        LOGICAL                                     :: res
8829        res = ( (item1(3) < item2(3))                                                        &
8830             .OR.  (item1(3) == item2(3)  .AND.  item1(2) < item2(2))                            &
8831             .OR.  (item1(3) == item2(3)  .AND.  item1(2) == item2(2)  .AND.  item1(1) < item2(1)) &
8832             .OR.  (item1(3) == item2(3)  .AND.  item1(2) == item2(2)  .AND.  item1(1) == item2(1) &
8833                 .AND.  item1(4) < item2(4)) )
8834    END FUNCTION csf_lt2
8835
8836    PURE FUNCTION searchsorted(athresh, val) result(ind)
8837        REAL(wp), DIMENSION(:), INTENT(IN)  :: athresh
8838        REAL(wp), INTENT(IN)                :: val
8839        INTEGER(iwp)                        :: ind
8840        INTEGER(iwp)                        :: i
8841
8842        DO i = LBOUND(athresh, 1), UBOUND(athresh, 1)
8843            IF ( val < athresh(i) ) THEN
8844                ind = i - 1
8845                RETURN
8846            ENDIF
8847        ENDDO
8848        ind = UBOUND(athresh, 1)
8849    END FUNCTION searchsorted
8850
8851
8852!------------------------------------------------------------------------------!
8853!
8854! Description:
8855! ------------
8856!> Subroutine for averaging 3D data
8857!------------------------------------------------------------------------------!
8858SUBROUTINE radiation_3d_data_averaging( mode, variable )
8859 
8860
8861    USE control_parameters
8862
8863    USE indices
8864
8865    USE kinds
8866
8867    IMPLICIT NONE
8868
8869    CHARACTER (LEN=*) ::  mode    !<
8870    CHARACTER (LEN=*) :: variable !<
8871
8872    LOGICAL      ::  match_lsm !< flag indicating natural-type surface
8873    LOGICAL      ::  match_usm !< flag indicating urban-type surface
8874   
8875    INTEGER(iwp) ::  i !<
8876    INTEGER(iwp) ::  j !<
8877    INTEGER(iwp) ::  k !<
8878    INTEGER(iwp) ::  l, m !< index of current surface element
8879
8880    INTEGER(iwp)                                       :: ids, idsint_u, idsint_l, isurf
8881    CHARACTER(LEN=varnamelength)                       :: var
8882
8883!-- find the real name of the variable
8884    ids = -1
8885    l = -1
8886    var = TRIM(variable)
8887    DO i = 0, nd-1
8888        k = len(TRIM(var))
8889        j = len(TRIM(dirname(i)))
8890        IF ( k-j+1 >= 1_iwp ) THEN
8891           IF ( TRIM(var(k-j+1:k)) == TRIM(dirname(i)) )  THEN
8892               ids = i
8893               idsint_u = dirint_u(ids)
8894               idsint_l = dirint_l(ids)
8895               var = var(:k-j)
8896               EXIT
8897           ENDIF
8898        ENDIF
8899    ENDDO
8900    IF ( ids == -1 )  THEN
8901        var = TRIM(variable)
8902    ENDIF
8903
8904    IF ( mode == 'allocate' )  THEN
8905
8906       SELECT CASE ( TRIM( var ) )
8907!--          block of large scale (e.g. RRTMG) radiation output variables
8908             CASE ( 'rad_net*' )
8909                IF ( .NOT. ALLOCATED( rad_net_av ) )  THEN
8910                   ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
8911                ENDIF
8912                rad_net_av = 0.0_wp
8913             
8914             CASE ( 'rad_lw_in*' )
8915                IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) )  THEN
8916                   ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
8917                ENDIF
8918                rad_lw_in_xy_av = 0.0_wp
8919               
8920             CASE ( 'rad_lw_out*' )
8921                IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) )  THEN
8922                   ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
8923                ENDIF
8924                rad_lw_out_xy_av = 0.0_wp
8925               
8926             CASE ( 'rad_sw_in*' )
8927                IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) )  THEN
8928                   ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
8929                ENDIF
8930                rad_sw_in_xy_av = 0.0_wp
8931               
8932             CASE ( 'rad_sw_out*' )
8933                IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) )  THEN
8934                   ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
8935                ENDIF
8936                rad_sw_out_xy_av = 0.0_wp               
8937
8938             CASE ( 'rad_lw_in' )
8939                IF ( .NOT. ALLOCATED( rad_lw_in_av ) )  THEN
8940                   ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8941                ENDIF
8942                rad_lw_in_av = 0.0_wp
8943
8944             CASE ( 'rad_lw_out' )
8945                IF ( .NOT. ALLOCATED( rad_lw_out_av ) )  THEN
8946                   ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8947                ENDIF
8948                rad_lw_out_av = 0.0_wp
8949
8950             CASE ( 'rad_lw_cs_hr' )
8951                IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) )  THEN
8952                   ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8953                ENDIF
8954                rad_lw_cs_hr_av = 0.0_wp
8955
8956             CASE ( 'rad_lw_hr' )
8957                IF ( .NOT. ALLOCATED( rad_lw_hr_av ) )  THEN
8958                   ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8959                ENDIF
8960                rad_lw_hr_av = 0.0_wp
8961
8962             CASE ( 'rad_sw_in' )
8963                IF ( .NOT. ALLOCATED( rad_sw_in_av ) )  THEN
8964                   ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8965                ENDIF
8966                rad_sw_in_av = 0.0_wp
8967
8968             CASE ( 'rad_sw_out' )
8969                IF ( .NOT. ALLOCATED( rad_sw_out_av ) )  THEN
8970                   ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8971                ENDIF
8972                rad_sw_out_av = 0.0_wp
8973
8974             CASE ( 'rad_sw_cs_hr' )
8975                IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) )  THEN
8976                   ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8977                ENDIF
8978                rad_sw_cs_hr_av = 0.0_wp
8979
8980             CASE ( 'rad_sw_hr' )
8981                IF ( .NOT. ALLOCATED( rad_sw_hr_av ) )  THEN
8982                   ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8983                ENDIF
8984                rad_sw_hr_av = 0.0_wp
8985
8986!--          block of RTM output variables
8987             CASE ( 'rtm_rad_net' )
8988!--              array of complete radiation balance
8989                 IF ( .NOT.  ALLOCATED(surfradnet_av) )  THEN
8990                     ALLOCATE( surfradnet_av(nsurfl) )
8991                     surfradnet_av = 0.0_wp
8992                 ENDIF
8993
8994             CASE ( 'rtm_rad_insw' )
8995!--                 array of sw radiation falling to surface after i-th reflection
8996                 IF ( .NOT.  ALLOCATED(surfinsw_av) )  THEN
8997                     ALLOCATE( surfinsw_av(nsurfl) )
8998                     surfinsw_av = 0.0_wp
8999                 ENDIF
9000
9001             CASE ( 'rtm_rad_inlw' )
9002!--                 array of lw radiation falling to surface after i-th reflection
9003                 IF ( .NOT.  ALLOCATED(surfinlw_av) )  THEN
9004                     ALLOCATE( surfinlw_av(nsurfl) )
9005                     surfinlw_av = 0.0_wp
9006                 ENDIF
9007
9008             CASE ( 'rtm_rad_inswdir' )
9009!--                 array of direct sw radiation falling to surface from sun
9010                 IF ( .NOT.  ALLOCATED(surfinswdir_av) )  THEN
9011                     ALLOCATE( surfinswdir_av(nsurfl) )
9012                     surfinswdir_av = 0.0_wp
9013                 ENDIF
9014
9015             CASE ( 'rtm_rad_inswdif' )
9016!--                 array of difusion sw radiation falling to surface from sky and borders of the domain
9017                 IF ( .NOT.  ALLOCATED(surfinswdif_av) )  THEN
9018                     ALLOCATE( surfinswdif_av(nsurfl) )
9019                     surfinswdif_av = 0.0_wp
9020                 ENDIF
9021
9022             CASE ( 'rtm_rad_inswref' )
9023!--                 array of sw radiation falling to surface from reflections
9024                 IF ( .NOT.  ALLOCATED(surfinswref_av) )  THEN
9025                     ALLOCATE( surfinswref_av(nsurfl) )
9026                     surfinswref_av = 0.0_wp
9027                 ENDIF
9028
9029             CASE ( 'rtm_rad_inlwdif' )
9030!--                 array of sw radiation falling to surface after i-th reflection
9031                IF ( .NOT.  ALLOCATED(surfinlwdif_av) )  THEN
9032                     ALLOCATE( surfinlwdif_av(nsurfl) )
9033                     surfinlwdif_av = 0.0_wp
9034                 ENDIF
9035
9036             CASE ( 'rtm_rad_inlwref' )
9037!--                 array of lw radiation falling to surface from reflections
9038                 IF ( .NOT.  ALLOCATED(surfinlwref_av) )  THEN
9039                     ALLOCATE( surfinlwref_av(nsurfl) )
9040                     surfinlwref_av = 0.0_wp
9041                 ENDIF
9042
9043             CASE ( 'rtm_rad_outsw' )
9044!--                 array of sw radiation emitted from surface after i-th reflection
9045                 IF ( .NOT.  ALLOCATED(surfoutsw_av) )  THEN
9046                     ALLOCATE( surfoutsw_av(nsurfl) )
9047                     surfoutsw_av = 0.0_wp
9048                 ENDIF
9049
9050             CASE ( 'rtm_rad_outlw' )
9051!--                 array of lw radiation emitted from surface after i-th reflection
9052                 IF ( .NOT.  ALLOCATED(surfoutlw_av) )  THEN
9053                     ALLOCATE( surfoutlw_av(nsurfl) )
9054                     surfoutlw_av = 0.0_wp
9055                 ENDIF
9056             CASE ( 'rtm_rad_ressw' )
9057!--                 array of residua of sw radiation absorbed in surface after last reflection
9058                 IF ( .NOT.  ALLOCATED(surfins_av) )  THEN
9059                     ALLOCATE( surfins_av(nsurfl) )
9060                     surfins_av = 0.0_wp
9061                 ENDIF
9062
9063             CASE ( 'rtm_rad_reslw' )
9064!--                 array of residua of lw radiation absorbed in surface after last reflection
9065                 IF ( .NOT.  ALLOCATED(surfinl_av) )  THEN
9066                     ALLOCATE( surfinl_av(nsurfl) )
9067                     surfinl_av = 0.0_wp
9068                 ENDIF
9069
9070             CASE ( 'rtm_rad_pc_inlw' )
9071!--                 array of of lw radiation absorbed in plant canopy
9072                 IF ( .NOT.  ALLOCATED(pcbinlw_av) )  THEN
9073                     ALLOCATE( pcbinlw_av(1:npcbl) )
9074                     pcbinlw_av = 0.0_wp
9075                 ENDIF
9076
9077             CASE ( 'rtm_rad_pc_insw' )
9078!--                 array of of sw radiation absorbed in plant canopy
9079                 IF ( .NOT.  ALLOCATED(pcbinsw_av) )  THEN
9080                     ALLOCATE( pcbinsw_av(1:npcbl) )
9081                     pcbinsw_av = 0.0_wp
9082                 ENDIF
9083
9084             CASE ( 'rtm_rad_pc_inswdir' )
9085!--                 array of of direct sw radiation absorbed in plant canopy
9086                 IF ( .NOT.  ALLOCATED(pcbinswdir_av) )  THEN
9087                     ALLOCATE( pcbinswdir_av(1:npcbl) )
9088                     pcbinswdir_av = 0.0_wp
9089                 ENDIF
9090
9091             CASE ( 'rtm_rad_pc_inswdif' )
9092!--                 array of of diffuse sw radiation absorbed in plant canopy
9093                 IF ( .NOT.  ALLOCATED(pcbinswdif_av) )  THEN
9094                     ALLOCATE( pcbinswdif_av(1:npcbl) )
9095                     pcbinswdif_av = 0.0_wp
9096                 ENDIF
9097
9098             CASE ( 'rtm_rad_pc_inswref' )
9099!--                 array of of reflected sw radiation absorbed in plant canopy
9100                 IF ( .NOT.  ALLOCATED(pcbinswref_av) )  THEN
9101                     ALLOCATE( pcbinswref_av(1:npcbl) )
9102                     pcbinswref_av = 0.0_wp
9103                 ENDIF
9104
9105             CASE ( 'rtm_mrt_sw' )
9106                IF ( .NOT. ALLOCATED( mrtinsw_av ) )  THEN
9107                   ALLOCATE( mrtinsw_av(nmrtbl) )
9108                ENDIF
9109                mrtinsw_av = 0.0_wp
9110
9111             CASE ( 'rtm_mrt_lw' )
9112                IF ( .NOT. ALLOCATED( mrtinlw_av ) )  THEN
9113                   ALLOCATE( mrtinlw_av(nmrtbl) )
9114                ENDIF
9115                mrtinlw_av = 0.0_wp
9116
9117             CASE ( 'rtm_mrt' )
9118                IF ( .NOT. ALLOCATED( mrt_av ) )  THEN
9119                   ALLOCATE( mrt_av(nmrtbl) )
9120                ENDIF
9121                mrt_av = 0.0_wp
9122
9123          CASE DEFAULT
9124             CONTINUE
9125
9126       END SELECT
9127
9128    ELSEIF ( mode == 'sum' )  THEN
9129
9130       SELECT CASE ( TRIM( var ) )
9131!--       block of large scale (e.g. RRTMG) radiation output variables
9132          CASE ( 'rad_net*' )
9133             IF ( ALLOCATED( rad_net_av ) ) THEN
9134                DO  i = nxl, nxr
9135                   DO  j = nys, nyn
9136                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9137                                  surf_lsm_h%end_index(j,i)
9138                      match_usm = surf_usm_h%start_index(j,i) <=               &
9139                                  surf_usm_h%end_index(j,i)
9140
9141                     IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9142                         m = surf_lsm_h%end_index(j,i)
9143                         rad_net_av(j,i) = rad_net_av(j,i) +                   &
9144                                         surf_lsm_h%rad_net(m)
9145                      ELSEIF ( match_usm )  THEN
9146                         m = surf_usm_h%end_index(j,i)
9147                         rad_net_av(j,i) = rad_net_av(j,i) +                   &
9148                                         surf_usm_h%rad_net(m)
9149                      ENDIF
9150                   ENDDO
9151                ENDDO
9152             ENDIF
9153
9154          CASE ( 'rad_lw_in*' )
9155             IF ( ALLOCATED( rad_lw_in_xy_av ) ) THEN
9156                DO  i = nxl, nxr
9157                   DO  j = nys, nyn
9158                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9159                                  surf_lsm_h%end_index(j,i)
9160                      match_usm = surf_usm_h%start_index(j,i) <=               &
9161                                  surf_usm_h%end_index(j,i)
9162
9163                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9164                         m = surf_lsm_h%end_index(j,i)
9165                         rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i) +         &
9166                                         surf_lsm_h%rad_lw_in(m)
9167                      ELSEIF ( match_usm )  THEN
9168                         m = surf_usm_h%end_index(j,i)
9169                         rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i) +         &
9170                                         surf_usm_h%rad_lw_in(m)
9171                      ENDIF
9172                   ENDDO
9173                ENDDO
9174             ENDIF
9175             
9176          CASE ( 'rad_lw_out*' )
9177             IF ( ALLOCATED( rad_lw_out_xy_av ) ) THEN
9178                DO  i = nxl, nxr
9179                   DO  j = nys, nyn
9180                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9181                                  surf_lsm_h%end_index(j,i)
9182                      match_usm = surf_usm_h%start_index(j,i) <=               &
9183                                  surf_usm_h%end_index(j,i)
9184
9185                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9186                         m = surf_lsm_h%end_index(j,i)
9187                         rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i) +       &
9188                                                 surf_lsm_h%rad_lw_out(m)
9189                      ELSEIF ( match_usm )  THEN
9190                         m = surf_usm_h%end_index(j,i)
9191                         rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i) +       &
9192                                                 surf_usm_h%rad_lw_out(m)
9193                      ENDIF
9194                   ENDDO
9195                ENDDO
9196             ENDIF
9197             
9198          CASE ( 'rad_sw_in*' )
9199             IF ( ALLOCATED( rad_sw_in_xy_av ) ) THEN
9200                DO  i = nxl, nxr
9201                   DO  j = nys, nyn
9202                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9203                                  surf_lsm_h%end_index(j,i)
9204                      match_usm = surf_usm_h%start_index(j,i) <=               &
9205                                  surf_usm_h%end_index(j,i)
9206
9207                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9208                         m = surf_lsm_h%end_index(j,i)
9209                         rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i) +         &
9210                                                surf_lsm_h%rad_sw_in(m)
9211                      ELSEIF ( match_usm )  THEN
9212                         m = surf_usm_h%end_index(j,i)
9213                         rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i) +         &
9214                                                surf_usm_h%rad_sw_in(m)
9215                      ENDIF
9216                   ENDDO
9217                ENDDO
9218             ENDIF
9219             
9220          CASE ( 'rad_sw_out*' )
9221             IF ( ALLOCATED( rad_sw_out_xy_av ) ) THEN
9222                DO  i = nxl, nxr
9223                   DO  j = nys, nyn
9224                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9225                                  surf_lsm_h%end_index(j,i)
9226                      match_usm = surf_usm_h%start_index(j,i) <=               &
9227                                  surf_usm_h%end_index(j,i)
9228
9229                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9230                         m = surf_lsm_h%end_index(j,i)
9231                         rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i) +       &
9232                                                 surf_lsm_h%rad_sw_out(m)
9233                      ELSEIF ( match_usm )  THEN
9234                         m = surf_usm_h%end_index(j,i)
9235                         rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i) +       &
9236                                                 surf_usm_h%rad_sw_out(m)
9237                      ENDIF
9238                   ENDDO
9239                ENDDO
9240             ENDIF
9241             
9242          CASE ( 'rad_lw_in' )
9243             IF ( ALLOCATED( rad_lw_in_av ) ) THEN
9244                DO  i = nxlg, nxrg
9245                   DO  j = nysg, nyng
9246                      DO  k = nzb, nzt+1
9247                         rad_lw_in_av(k,j,i) = rad_lw_in_av(k,j,i)             &
9248                                               + rad_lw_in(k,j,i)
9249                      ENDDO
9250                   ENDDO
9251                ENDDO
9252             ENDIF
9253
9254          CASE ( 'rad_lw_out' )
9255             IF ( ALLOCATED( rad_lw_out_av ) ) THEN
9256                DO  i = nxlg, nxrg
9257                   DO  j = nysg, nyng
9258                      DO  k = nzb, nzt+1
9259                         rad_lw_out_av(k,j,i) = rad_lw_out_av(k,j,i)           &
9260                                                + rad_lw_out(k,j,i)
9261                      ENDDO
9262                   ENDDO
9263                ENDDO
9264             ENDIF
9265
9266          CASE ( 'rad_lw_cs_hr' )
9267             IF ( ALLOCATED( rad_lw_cs_hr_av ) ) THEN
9268                DO  i = nxlg, nxrg
9269                   DO  j = nysg, nyng
9270                      DO  k = nzb, nzt+1
9271                         rad_lw_cs_hr_av(k,j,i) = rad_lw_cs_hr_av(k,j,i)       &
9272                                                  + rad_lw_cs_hr(k,j,i)
9273                      ENDDO
9274                   ENDDO
9275                ENDDO
9276             ENDIF
9277
9278          CASE ( 'rad_lw_hr' )
9279             IF ( ALLOCATED( rad_lw_hr_av ) ) THEN
9280                DO  i = nxlg, nxrg
9281                   DO  j = nysg, nyng
9282                      DO  k = nzb, nzt+1
9283                         rad_lw_hr_av(k,j,i) = rad_lw_hr_av(k,j,i)             &
9284                                               + rad_lw_hr(k,j,i)
9285                      ENDDO
9286                   ENDDO
9287                ENDDO
9288             ENDIF
9289
9290          CASE ( 'rad_sw_in' )
9291             IF ( ALLOCATED( rad_sw_in_av ) ) THEN
9292                DO  i = nxlg, nxrg
9293                   DO  j = nysg, nyng
9294                      DO  k = nzb, nzt+1
9295                         rad_sw_in_av(k,j,i) = rad_sw_in_av(k,j,i)             &
9296                                               + rad_sw_in(k,j,i)
9297                      ENDDO
9298                   ENDDO
9299                ENDDO
9300             ENDIF
9301
9302          CASE ( 'rad_sw_out' )
9303             IF ( ALLOCATED( rad_sw_out_av ) ) THEN
9304                DO  i = nxlg, nxrg
9305                   DO  j = nysg, nyng
9306                      DO  k = nzb, nzt+1
9307                         rad_sw_out_av(k,j,i) = rad_sw_out_av(k,j,i)           &
9308                                                + rad_sw_out(k,j,i)
9309                      ENDDO
9310                   ENDDO
9311                ENDDO
9312             ENDIF
9313
9314          CASE ( 'rad_sw_cs_hr' )
9315             IF ( ALLOCATED( rad_sw_cs_hr_av ) ) THEN
9316                DO  i = nxlg, nxrg
9317                   DO  j = nysg, nyng
9318                      DO  k = nzb, nzt+1
9319                         rad_sw_cs_hr_av(k,j,i) = rad_sw_cs_hr_av(k,j,i)       &
9320                                                  + rad_sw_cs_hr(k,j,i)
9321                      ENDDO
9322                   ENDDO
9323                ENDDO
9324             ENDIF
9325
9326          CASE ( 'rad_sw_hr' )
9327             IF ( ALLOCATED( rad_sw_hr_av ) ) THEN
9328                DO  i = nxlg, nxrg
9329                   DO  j = nysg, nyng
9330                      DO  k = nzb, nzt+1
9331                         rad_sw_hr_av(k,j,i) = rad_sw_hr_av(k,j,i)             &
9332                                               + rad_sw_hr(k,j,i)
9333                      ENDDO
9334                   ENDDO
9335                ENDDO
9336             ENDIF
9337
9338!--       block of RTM output variables
9339          CASE ( 'rtm_rad_net' )
9340!--           array of complete radiation balance
9341              DO isurf = dirstart(ids), dirend(ids)
9342                 IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9343                    surfradnet_av(isurf) = surfinsw(isurf) - surfoutsw(isurf) +  surfinlw(isurf) - surfoutlw(isurf)
9344                 ENDIF
9345              ENDDO
9346
9347          CASE ( 'rtm_rad_insw' )
9348!--           array of sw radiation falling to surface after i-th reflection
9349              DO isurf = dirstart(ids), dirend(ids)
9350                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9351                      surfinsw_av(isurf) = surfinsw_av(isurf) + surfinsw(isurf)
9352                  ENDIF
9353              ENDDO
9354
9355          CASE ( 'rtm_rad_inlw' )
9356!--           array of lw radiation falling to surface after i-th reflection
9357              DO isurf = dirstart(ids), dirend(ids)
9358                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9359                      surfinlw_av(isurf) = surfinlw_av(isurf) + surfinlw(isurf)
9360                  ENDIF
9361              ENDDO
9362
9363          CASE ( 'rtm_rad_inswdir' )
9364!--           array of direct sw radiation falling to surface from sun
9365              DO isurf = dirstart(ids), dirend(ids)
9366                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9367                      surfinswdir_av(isurf) = surfinswdir_av(isurf) + surfinswdir(isurf)
9368                  ENDIF
9369              ENDDO
9370
9371          CASE ( 'rtm_rad_inswdif' )
9372!--           array of difusion sw radiation falling to surface from sky and borders of the domain
9373              DO isurf = dirstart(ids), dirend(ids)
9374                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9375                      surfinswdif_av(isurf) = surfinswdif_av(isurf) + surfinswdif(isurf)
9376                  ENDIF
9377              ENDDO
9378
9379          CASE ( 'rtm_rad_inswref' )
9380!--           array of sw radiation falling to surface from reflections
9381              DO isurf = dirstart(ids), dirend(ids)
9382                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9383                      surfinswref_av(isurf) = surfinswref_av(isurf) + surfinsw(isurf) - &
9384                                          surfinswdir(isurf) - surfinswdif(isurf)
9385                  ENDIF
9386              ENDDO
9387
9388
9389          CASE ( 'rtm_rad_inlwdif' )
9390!--           array of sw radiation falling to surface after i-th reflection
9391              DO isurf = dirstart(ids), dirend(ids)
9392                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9393                      surfinlwdif_av(isurf) = surfinlwdif_av(isurf) + surfinlwdif(isurf)
9394                  ENDIF
9395              ENDDO
9396!
9397          CASE ( 'rtm_rad_inlwref' )
9398!--           array of lw radiation falling to surface from reflections
9399              DO isurf = dirstart(ids), dirend(ids)
9400                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9401                      surfinlwref_av(isurf) = surfinlwref_av(isurf) + &
9402                                          surfinlw(isurf) - surfinlwdif(isurf)
9403                  ENDIF
9404              ENDDO
9405
9406          CASE ( 'rtm_rad_outsw' )
9407!--           array of sw radiation emitted from surface after i-th reflection
9408              DO isurf = dirstart(ids), dirend(ids)
9409                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9410                      surfoutsw_av(isurf) = surfoutsw_av(isurf) + surfoutsw(isurf)
9411                  ENDIF
9412              ENDDO
9413
9414          CASE ( 'rtm_rad_outlw' )
9415!--           array of lw radiation emitted from surface after i-th reflection
9416              DO isurf = dirstart(ids), dirend(ids)
9417                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9418                      surfoutlw_av(isurf) = surfoutlw_av(isurf) + surfoutlw(isurf)
9419                  ENDIF
9420              ENDDO
9421
9422          CASE ( 'rtm_rad_ressw' )
9423!--           array of residua of sw radiation absorbed in surface after last reflection
9424              DO isurf = dirstart(ids), dirend(ids)
9425                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9426                      surfins_av(isurf) = surfins_av(isurf) + surfins(isurf)
9427                  ENDIF
9428              ENDDO
9429
9430          CASE ( 'rtm_rad_reslw' )
9431!--           array of residua of lw radiation absorbed in surface after last reflection
9432              DO isurf = dirstart(ids), dirend(ids)
9433                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9434                      surfinl_av(isurf) = surfinl_av(isurf) + surfinl(isurf)
9435                  ENDIF
9436              ENDDO
9437
9438          CASE ( 'rtm_rad_pc_inlw' )
9439              DO l = 1, npcbl
9440                 pcbinlw_av(l) = pcbinlw_av(l) + pcbinlw(l)
9441              ENDDO
9442
9443          CASE ( 'rtm_rad_pc_insw' )
9444              DO l = 1, npcbl
9445                 pcbinsw_av(l) = pcbinsw_av(l) + pcbinsw(l)
9446              ENDDO
9447
9448          CASE ( 'rtm_rad_pc_inswdir' )
9449              DO l = 1, npcbl
9450                 pcbinswdir_av(l) = pcbinswdir_av(l) + pcbinswdir(l)
9451              ENDDO
9452
9453          CASE ( 'rtm_rad_pc_inswdif' )
9454              DO l = 1, npcbl
9455                 pcbinswdif_av(l) = pcbinswdif_av(l) + pcbinswdif(l)
9456              ENDDO
9457
9458          CASE ( 'rtm_rad_pc_inswref' )
9459              DO l = 1, npcbl
9460                 pcbinswref_av(l) = pcbinswref_av(l) + pcbinsw(l) - pcbinswdir(l) - pcbinswdif(l)
9461              ENDDO
9462
9463          CASE ( 'rad_mrt_sw' )
9464             IF ( ALLOCATED( mrtinsw_av ) )  THEN
9465                mrtinsw_av(:) = mrtinsw_av(:) + mrtinsw(:)
9466             ENDIF
9467
9468          CASE ( 'rad_mrt_lw' )
9469             IF ( ALLOCATED( mrtinlw_av ) )  THEN
9470                mrtinlw_av(:) = mrtinlw_av(:) + mrtinlw(:)
9471             ENDIF
9472
9473          CASE ( 'rad_mrt' )
9474             IF ( ALLOCATED( mrt_av ) )  THEN
9475                mrt_av(:) = mrt_av(:) + mrt(:)
9476             ENDIF
9477
9478          CASE DEFAULT
9479             CONTINUE
9480
9481       END SELECT
9482
9483    ELSEIF ( mode == 'average' )  THEN
9484
9485       SELECT CASE ( TRIM( var ) )
9486!--       block of large scale (e.g. RRTMG) radiation output variables
9487          CASE ( 'rad_net*' )
9488             IF ( ALLOCATED( rad_net_av ) ) THEN
9489                DO  i = nxlg, nxrg
9490                   DO  j = nysg, nyng
9491                      rad_net_av(j,i) = rad_net_av(j,i)                        &
9492                                        / REAL( average_count_3d, KIND=wp )
9493                   ENDDO
9494                ENDDO
9495             ENDIF
9496             
9497          CASE ( 'rad_lw_in*' )
9498             IF ( ALLOCATED( rad_lw_in_xy_av ) ) THEN
9499                DO  i = nxlg, nxrg
9500                   DO  j = nysg, nyng
9501                      rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i)              &
9502                                        / REAL( average_count_3d, KIND=wp )
9503                   ENDDO
9504                ENDDO
9505             ENDIF
9506             
9507          CASE ( 'rad_lw_out*' )
9508             IF ( ALLOCATED( rad_lw_out_xy_av ) ) THEN
9509                DO  i = nxlg, nxrg
9510                   DO  j = nysg, nyng
9511                      rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i)            &
9512                                        / REAL( average_count_3d, KIND=wp )
9513                   ENDDO
9514                ENDDO
9515             ENDIF
9516             
9517          CASE ( 'rad_sw_in*' )
9518             IF ( ALLOCATED( rad_sw_in_xy_av ) ) THEN
9519                DO  i = nxlg, nxrg
9520                   DO  j = nysg, nyng
9521                      rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i)              &
9522                                        / REAL( average_count_3d, KIND=wp )
9523                   ENDDO
9524                ENDDO
9525             ENDIF
9526             
9527          CASE ( 'rad_sw_out*' )
9528             IF ( ALLOCATED( rad_sw_out_xy_av ) ) THEN
9529                DO  i = nxlg, nxrg
9530                   DO  j = nysg, nyng
9531                      rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i)             &
9532                                        / REAL( average_count_3d, KIND=wp )
9533                   ENDDO
9534                ENDDO
9535             ENDIF
9536
9537          CASE ( 'rad_lw_in' )
9538             IF ( ALLOCATED( rad_lw_in_av ) ) THEN
9539                DO  i = nxlg, nxrg
9540                   DO  j = nysg, nyng
9541                      DO  k = nzb, nzt+1
9542                         rad_lw_in_av(k,j,i) = rad_lw_in_av(k,j,i)             &
9543                                               / REAL( average_count_3d, KIND=wp )
9544                      ENDDO
9545                   ENDDO
9546                ENDDO
9547             ENDIF
9548
9549          CASE ( 'rad_lw_out' )
9550             IF ( ALLOCATED( rad_lw_out_av ) ) THEN
9551                DO  i = nxlg, nxrg
9552                   DO  j = nysg, nyng
9553                      DO  k = nzb, nzt+1
9554                         rad_lw_out_av(k,j,i) = rad_lw_out_av(k,j,i)           &
9555                                                / REAL( average_count_3d, KIND=wp )
9556                      ENDDO
9557                   ENDDO
9558                ENDDO
9559             ENDIF
9560
9561          CASE ( 'rad_lw_cs_hr' )
9562             IF ( ALLOCATED( rad_lw_cs_hr_av ) ) THEN
9563                DO  i = nxlg, nxrg
9564                   DO  j = nysg, nyng
9565                      DO  k = nzb, nzt+1
9566                         rad_lw_cs_hr_av(k,j,i) = rad_lw_cs_hr_av(k,j,i)       &
9567                                                / REAL( average_count_3d, KIND=wp )
9568                      ENDDO
9569                   ENDDO
9570                ENDDO
9571             ENDIF
9572
9573          CASE ( 'rad_lw_hr' )
9574             IF ( ALLOCATED( rad_lw_hr_av ) ) THEN
9575                DO  i = nxlg, nxrg
9576                   DO  j = nysg, nyng
9577                      DO  k = nzb, nzt+1
9578                         rad_lw_hr_av(k,j,i) = rad_lw_hr_av(k,j,i)             &
9579                                               / REAL( average_count_3d, KIND=wp )
9580                      ENDDO
9581                   ENDDO
9582                ENDDO
9583             ENDIF
9584
9585          CASE ( 'rad_sw_in' )
9586             IF ( ALLOCATED( rad_sw_in_av ) ) THEN
9587                DO  i = nxlg, nxrg
9588                   DO  j = nysg, nyng
9589                      DO  k = nzb, nzt+1
9590                         rad_sw_in_av(k,j,i) = rad_sw_in_av(k,j,i)             &
9591                                               / REAL( average_count_3d, KIND=wp )
9592                      ENDDO
9593                   ENDDO
9594                ENDDO
9595             ENDIF
9596
9597          CASE ( 'rad_sw_out' )
9598             IF ( ALLOCATED( rad_sw_out_av ) ) THEN
9599                DO  i = nxlg, nxrg
9600                   DO  j = nysg, nyng
9601                      DO  k = nzb, nzt+1
9602                         rad_sw_out_av(k,j,i) = rad_sw_out_av(k,j,i)           &
9603                                                / REAL( average_count_3d, KIND=wp )
9604                      ENDDO
9605                   ENDDO
9606                ENDDO
9607             ENDIF
9608
9609          CASE ( 'rad_sw_cs_hr' )
9610             IF ( ALLOCATED( rad_sw_cs_hr_av ) ) THEN
9611                DO  i = nxlg, nxrg
9612                   DO  j = nysg, nyng
9613                      DO  k = nzb, nzt+1
9614                         rad_sw_cs_hr_av(k,j,i) = rad_sw_cs_hr_av(k,j,i)       &
9615                                                / REAL( average_count_3d, KIND=wp )
9616                      ENDDO
9617                   ENDDO
9618                ENDDO
9619             ENDIF
9620
9621          CASE ( 'rad_sw_hr' )
9622             IF ( ALLOCATED( rad_sw_hr_av ) ) THEN
9623                DO  i = nxlg, nxrg
9624                   DO  j = nysg, nyng
9625                      DO  k = nzb, nzt+1
9626                         rad_sw_hr_av(k,j,i) = rad_sw_hr_av(k,j,i)             &
9627                                               / REAL( average_count_3d, KIND=wp )
9628                      ENDDO
9629                   ENDDO
9630                ENDDO
9631             ENDIF
9632
9633!--       block of RTM output variables
9634          CASE ( 'rtm_rad_net' )
9635!--           array of complete radiation balance
9636              DO isurf = dirstart(ids), dirend(ids)
9637                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9638                      surfradnet_av(isurf) = surfinsw_av(isurf) / REAL( average_count_3d, kind=wp )
9639                  ENDIF
9640              ENDDO
9641
9642          CASE ( 'rtm_rad_insw' )
9643!--           array of sw radiation falling to surface after i-th reflection
9644              DO isurf = dirstart(ids), dirend(ids)
9645                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9646                      surfinsw_av(isurf) = surfinsw_av(isurf) / REAL( average_count_3d, kind=wp )
9647                  ENDIF
9648              ENDDO
9649
9650          CASE ( 'rtm_rad_inlw' )
9651!--           array of lw radiation falling to surface after i-th reflection
9652              DO isurf = dirstart(ids), dirend(ids)
9653                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9654                      surfinlw_av(isurf) = surfinlw_av(isurf) / REAL( average_count_3d, kind=wp )
9655                  ENDIF
9656              ENDDO
9657
9658          CASE ( 'rtm_rad_inswdir' )
9659!--           array of direct sw radiation falling to surface from sun
9660              DO isurf = dirstart(ids), dirend(ids)
9661                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9662                      surfinswdir_av(isurf) = surfinswdir_av(isurf) / REAL( average_count_3d, kind=wp )
9663                  ENDIF
9664              ENDDO
9665
9666          CASE ( 'rtm_rad_inswdif' )
9667!--           array of difusion sw radiation falling to surface from sky and borders of the domain
9668              DO isurf = dirstart(ids), dirend(ids)
9669                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9670                      surfinswdif_av(isurf) = surfinswdif_av(isurf) / REAL( average_count_3d, kind=wp )
9671                  ENDIF
9672              ENDDO
9673
9674          CASE ( 'rtm_rad_inswref' )
9675!--           array of sw radiation falling to surface from reflections
9676              DO isurf = dirstart(ids), dirend(ids)
9677                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9678                      surfinswref_av(isurf) = surfinswref_av(isurf) / REAL( average_count_3d, kind=wp )
9679                  ENDIF
9680              ENDDO
9681
9682          CASE ( 'rtm_rad_inlwdif' )
9683!--           array of sw radiation falling to surface after i-th reflection
9684              DO isurf = dirstart(ids), dirend(ids)
9685                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9686                      surfinlwdif_av(isurf) = surfinlwdif_av(isurf) / REAL( average_count_3d, kind=wp )
9687                  ENDIF
9688              ENDDO
9689
9690          CASE ( 'rtm_rad_inlwref' )
9691!--           array of lw radiation falling to surface from reflections
9692              DO isurf = dirstart(ids), dirend(ids)
9693                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9694                      surfinlwref_av(isurf) = surfinlwref_av(isurf) / REAL( average_count_3d, kind=wp )
9695                  ENDIF
9696              ENDDO
9697
9698          CASE ( 'rtm_rad_outsw' )
9699!--           array of sw radiation emitted from surface after i-th reflection
9700              DO isurf = dirstart(ids), dirend(ids)
9701                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9702                      surfoutsw_av(isurf) = surfoutsw_av(isurf) / REAL( average_count_3d, kind=wp )
9703                  ENDIF
9704              ENDDO
9705
9706          CASE ( 'rtm_rad_outlw' )
9707!--           array of lw radiation emitted from surface after i-th reflection
9708              DO isurf = dirstart(ids), dirend(ids)
9709                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9710                      surfoutlw_av(isurf) = surfoutlw_av(isurf) / REAL( average_count_3d, kind=wp )
9711                  ENDIF
9712              ENDDO
9713
9714          CASE ( 'rtm_rad_ressw' )
9715!--           array of residua of sw radiation absorbed in surface after last reflection
9716              DO isurf = dirstart(ids), dirend(ids)
9717                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9718                      surfins_av(isurf) = surfins_av(isurf) / REAL( average_count_3d, kind=wp )
9719                  ENDIF
9720              ENDDO
9721
9722          CASE ( 'rtm_rad_reslw' )
9723!--           array of residua of lw radiation absorbed in surface after last reflection
9724              DO isurf = dirstart(ids), dirend(ids)
9725                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9726                      surfinl_av(isurf) = surfinl_av(isurf) / REAL( average_count_3d, kind=wp )
9727                  ENDIF
9728              ENDDO
9729
9730          CASE ( 'rtm_rad_pc_inlw' )
9731              DO l = 1, npcbl
9732                 pcbinlw_av(:) = pcbinlw_av(:) / REAL( average_count_3d, kind=wp )
9733              ENDDO
9734
9735          CASE ( 'rtm_rad_pc_insw' )
9736              DO l = 1, npcbl
9737                 pcbinsw_av(:) = pcbinsw_av(:) / REAL( average_count_3d, kind=wp )
9738              ENDDO
9739
9740          CASE ( 'rtm_rad_pc_inswdir' )
9741              DO l = 1, npcbl
9742                 pcbinswdir_av(:) = pcbinswdir_av(:) / REAL( average_count_3d, kind=wp )
9743              ENDDO
9744
9745          CASE ( 'rtm_rad_pc_inswdif' )
9746              DO l = 1, npcbl
9747                 pcbinswdif_av(:) = pcbinswdif_av(:) / REAL( average_count_3d, kind=wp )
9748              ENDDO
9749
9750          CASE ( 'rtm_rad_pc_inswref' )
9751              DO l = 1, npcbl
9752                 pcbinswref_av(:) = pcbinswref_av(:) / REAL( average_count_3d, kind=wp )
9753              ENDDO
9754
9755          CASE ( 'rad_mrt_lw' )
9756             IF ( ALLOCATED( mrtinlw_av ) )  THEN
9757                mrtinlw_av(:) = mrtinlw_av(:) / REAL( average_count_3d, KIND=wp )
9758             ENDIF
9759
9760          CASE ( 'rad_mrt' )
9761             IF ( ALLOCATED( mrt_av ) )  THEN
9762                mrt_av(:) = mrt_av(:) / REAL( average_count_3d, KIND=wp )
9763             ENDIF
9764
9765       END SELECT
9766
9767    ENDIF
9768
9769END SUBROUTINE radiation_3d_data_averaging
9770
9771
9772!------------------------------------------------------------------------------!
9773!
9774! Description:
9775! ------------
9776!> Subroutine defining appropriate grid for netcdf variables.
9777!> It is called out from subroutine netcdf.
9778!------------------------------------------------------------------------------!
9779SUBROUTINE radiation_define_netcdf_grid( variable, found, grid_x, grid_y, grid_z )
9780   
9781    IMPLICIT NONE
9782
9783    CHARACTER (LEN=*), INTENT(IN)  ::  variable    !<
9784    LOGICAL, INTENT(OUT)           ::  found       !<
9785    CHARACTER (LEN=*), INTENT(OUT) ::  grid_x      !<
9786    CHARACTER (LEN=*), INTENT(OUT) ::  grid_y      !<
9787    CHARACTER (LEN=*), INTENT(OUT) ::  grid_z      !<
9788
9789    CHARACTER (len=varnamelength)  :: var
9790
9791    found  = .TRUE.
9792
9793!
9794!-- Check for the grid
9795    var = TRIM(variable)
9796!-- RTM directional variables
9797    IF ( var(1:12) == 'rtm_rad_net_'  .OR.  var(1:13) == 'rtm_rad_insw_'  .OR.          &
9798         var(1:13) == 'rtm_rad_inlw_'  .OR.  var(1:16) == 'rtm_rad_inswdir_'  .OR.      &
9799         var(1:16) == 'rtm_rad_inswdif_'  .OR.  var(1:16) == 'rtm_rad_inswref_'  .OR.   &
9800         var(1:16) == 'rtm_rad_inlwdif_'  .OR.  var(1:16) == 'rtm_rad_inlwref_'  .OR.   &
9801         var(1:14) == 'rtm_rad_outsw_'  .OR.  var(1:14) == 'rtm_rad_outlw_'  .OR.       &
9802         var(1:14) == 'rtm_rad_ressw_'  .OR.  var(1:14) == 'rtm_rad_reslw_'  .OR.       &
9803         var == 'rtm_rad_pc_inlw'  .OR.                                                 &
9804         var == 'rtm_rad_pc_insw'  .OR.  var == 'rtm_rad_pc_inswdir'  .OR.              &
9805         var == 'rtm_rad_pc_inswdif'  .OR.  var == 'rtm_rad_pc_inswref'  .OR.           &
9806         var(1:7) == 'rtm_svf'  .OR.  var(1:7) == 'rtm_dif'  .OR.                       &
9807         var(1:9) == 'rtm_skyvf' .OR. var(1:10) == 'rtm_skyvft'  .OR.                   &
9808         var == 'rtm_mrt'  .OR.  var ==  'rtm_mrt_sw'  .OR.  var == 'rtm_mrt_lw' )  THEN
9809
9810         found = .TRUE.
9811         grid_x = 'x'
9812         grid_y = 'y'
9813         grid_z = 'zu'
9814    ELSE
9815
9816       SELECT CASE ( TRIM( var ) )
9817
9818          CASE ( 'rad_lw_cs_hr', 'rad_lw_hr', 'rad_sw_cs_hr', 'rad_sw_hr',        &
9819                 'rad_lw_cs_hr_xy', 'rad_lw_hr_xy', 'rad_sw_cs_hr_xy',            &
9820                 'rad_sw_hr_xy', 'rad_lw_cs_hr_xz', 'rad_lw_hr_xz',               &
9821                 'rad_sw_cs_hr_xz', 'rad_sw_hr_xz', 'rad_lw_cs_hr_yz',            &
9822                 'rad_lw_hr_yz', 'rad_sw_cs_hr_yz', 'rad_sw_hr_yz',               &
9823                 'rad_mrt', 'rad_mrt_sw', 'rad_mrt_lw' )
9824             grid_x = 'x'
9825             grid_y = 'y'
9826             grid_z = 'zu'
9827
9828          CASE ( 'rad_lw_in', 'rad_lw_out', 'rad_sw_in', 'rad_sw_out',            &
9829                 'rad_lw_in_xy', 'rad_lw_out_xy', 'rad_sw_in_xy','rad_sw_out_xy', &
9830                 'rad_lw_in_xz', 'rad_lw_out_xz', 'rad_sw_in_xz','rad_sw_out_xz', &
9831                 'rad_lw_in_yz', 'rad_lw_out_yz', 'rad_sw_in_yz','rad_sw_out_yz' )
9832             grid_x = 'x'
9833             grid_y = 'y'
9834             grid_z = 'zw'
9835
9836
9837          CASE DEFAULT
9838             found  = .FALSE.
9839             grid_x = 'none'
9840             grid_y = 'none'
9841             grid_z = 'none'
9842
9843           END SELECT
9844       ENDIF
9845
9846    END SUBROUTINE radiation_define_netcdf_grid
9847
9848!------------------------------------------------------------------------------!
9849!
9850! Description:
9851! ------------
9852!> Subroutine defining 2D output variables
9853!------------------------------------------------------------------------------!
9854 SUBROUTINE radiation_data_output_2d( av, variable, found, grid, mode,         &
9855                                      local_pf, two_d, nzb_do, nzt_do )
9856 
9857    USE indices
9858
9859    USE kinds
9860
9861
9862    IMPLICIT NONE
9863
9864    CHARACTER (LEN=*) ::  grid     !<
9865    CHARACTER (LEN=*) ::  mode     !<
9866    CHARACTER (LEN=*) ::  variable !<
9867
9868    INTEGER(iwp) ::  av !<
9869    INTEGER(iwp) ::  i  !<
9870    INTEGER(iwp) ::  j  !<
9871    INTEGER(iwp) ::  k  !<
9872    INTEGER(iwp) ::  m  !< index of surface element at grid point (j,i)
9873    INTEGER(iwp) ::  nzb_do   !<
9874    INTEGER(iwp) ::  nzt_do   !<
9875
9876    LOGICAL      ::  found !<
9877    LOGICAL      ::  two_d !< flag parameter that indicates 2D variables (horizontal cross sections)
9878
9879    REAL(wp) ::  fill_value = -999.0_wp    !< value for the _FillValue attribute
9880
9881    REAL(wp), DIMENSION(nxl:nxr,nys:nyn,nzb_do:nzt_do) ::  local_pf !<
9882
9883    found = .TRUE.
9884
9885    SELECT CASE ( TRIM( variable ) )
9886
9887       CASE ( 'rad_net*_xy' )        ! 2d-array
9888          IF ( av == 0 ) THEN
9889             DO  i = nxl, nxr
9890                DO  j = nys, nyn
9891!
9892!--                Obtain rad_net from its respective surface type
9893!--                Natural-type surfaces
9894                   DO  m = surf_lsm_h%start_index(j,i),                        &
9895                           surf_lsm_h%end_index(j,i) 
9896                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_net(m)
9897                   ENDDO
9898!
9899!--                Urban-type surfaces
9900                   DO  m = surf_usm_h%start_index(j,i),                        &
9901                           surf_usm_h%end_index(j,i) 
9902                      local_pf(i,j,nzb+1) = surf_usm_h%rad_net(m)
9903                   ENDDO
9904                ENDDO
9905             ENDDO
9906          ELSE
9907             IF ( .NOT. ALLOCATED( rad_net_av ) ) THEN
9908                ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
9909                rad_net_av = REAL( fill_value, KIND = wp )
9910             ENDIF
9911             DO  i = nxl, nxr
9912                DO  j = nys, nyn 
9913                   local_pf(i,j,nzb+1) = rad_net_av(j,i)
9914                ENDDO
9915             ENDDO
9916          ENDIF
9917          two_d = .TRUE.
9918          grid = 'zu1'
9919         
9920       CASE ( 'rad_lw_in*_xy' )        ! 2d-array
9921          IF ( av == 0 ) THEN
9922             DO  i = nxl, nxr
9923                DO  j = nys, nyn
9924!
9925!--                Obtain rad_net from its respective surface type
9926!--                Natural-type surfaces
9927                   DO  m = surf_lsm_h%start_index(j,i),                        &
9928                           surf_lsm_h%end_index(j,i) 
9929                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_lw_in(m)
9930                   ENDDO
9931!
9932!--                Urban-type surfaces
9933                   DO  m = surf_usm_h%start_index(j,i),                        &
9934                           surf_usm_h%end_index(j,i) 
9935                      local_pf(i,j,nzb+1) = surf_usm_h%rad_lw_in(m)
9936                   ENDDO
9937                ENDDO
9938             ENDDO
9939          ELSE
9940             IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) ) THEN
9941                ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
9942                rad_lw_in_xy_av = REAL( fill_value, KIND = wp )
9943             ENDIF
9944             DO  i = nxl, nxr
9945                DO  j = nys, nyn 
9946                   local_pf(i,j,nzb+1) = rad_lw_in_xy_av(j,i)
9947                ENDDO
9948             ENDDO
9949          ENDIF
9950          two_d = .TRUE.
9951          grid = 'zu1'
9952         
9953       CASE ( 'rad_lw_out*_xy' )        ! 2d-array
9954          IF ( av == 0 ) THEN
9955             DO  i = nxl, nxr
9956                DO  j = nys, nyn
9957!
9958!--                Obtain rad_net from its respective surface type
9959!--                Natural-type surfaces
9960                   DO  m = surf_lsm_h%start_index(j,i),                        &
9961                           surf_lsm_h%end_index(j,i) 
9962                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_lw_out(m)
9963                   ENDDO
9964!
9965!--                Urban-type surfaces
9966                   DO  m = surf_usm_h%start_index(j,i),                        &
9967                           surf_usm_h%end_index(j,i) 
9968                      local_pf(i,j,nzb+1) = surf_usm_h%rad_lw_out(m)
9969                   ENDDO
9970                ENDDO
9971             ENDDO
9972          ELSE
9973             IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) ) THEN
9974                ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
9975                rad_lw_out_xy_av = REAL( fill_value, KIND = wp )
9976             ENDIF
9977             DO  i = nxl, nxr
9978                DO  j = nys, nyn 
9979                   local_pf(i,j,nzb+1) = rad_lw_out_xy_av(j,i)
9980                ENDDO
9981             ENDDO
9982          ENDIF
9983          two_d = .TRUE.
9984          grid = 'zu1'
9985         
9986       CASE ( 'rad_sw_in*_xy' )        ! 2d-array
9987          IF ( av == 0 ) THEN
9988             DO  i = nxl, nxr
9989                DO  j = nys, nyn
9990!
9991!--                Obtain rad_net from its respective surface type
9992!--                Natural-type surfaces
9993                   DO  m = surf_lsm_h%start_index(j,i),                        &
9994                           surf_lsm_h%end_index(j,i) 
9995                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_sw_in(m)
9996                   ENDDO
9997!
9998!--                Urban-type surfaces
9999                   DO  m = surf_usm_h%start_index(j,i),                        &
10000                           surf_usm_h%end_index(j,i) 
10001                      local_pf(i,j,nzb+1) = surf_usm_h%rad_sw_in(m)
10002                   ENDDO
10003                ENDDO
10004             ENDDO
10005          ELSE
10006             IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) ) THEN
10007                ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
10008                rad_sw_in_xy_av = REAL( fill_value, KIND = wp )
10009             ENDIF
10010             DO  i = nxl, nxr
10011                DO  j = nys, nyn 
10012                   local_pf(i,j,nzb+1) = rad_sw_in_xy_av(j,i)
10013                ENDDO
10014             ENDDO
10015          ENDIF
10016          two_d = .TRUE.
10017          grid = 'zu1'
10018         
10019       CASE ( 'rad_sw_out*_xy' )        ! 2d-array
10020          IF ( av == 0 ) THEN
10021             DO  i = nxl, nxr
10022                DO  j = nys, nyn
10023!
10024!--                Obtain rad_net from its respective surface type
10025!--                Natural-type surfaces
10026                   DO  m = surf_lsm_h%start_index(j,i),                        &
10027                           surf_lsm_h%end_index(j,i) 
10028                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_sw_out(m)
10029                   ENDDO
10030!
10031!--                Urban-type surfaces
10032                   DO  m = surf_usm_h%start_index(j,i),                        &
10033                           surf_usm_h%end_index(j,i) 
10034                      local_pf(i,j,nzb+1) = surf_usm_h%rad_sw_out(m)
10035                   ENDDO
10036                ENDDO
10037             ENDDO
10038          ELSE
10039             IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) ) THEN
10040                ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
10041                rad_sw_out_xy_av = REAL( fill_value, KIND = wp )
10042             ENDIF
10043             DO  i = nxl, nxr
10044                DO  j = nys, nyn 
10045                   local_pf(i,j,nzb+1) = rad_sw_out_xy_av(j,i)
10046                ENDDO
10047             ENDDO
10048          ENDIF
10049          two_d = .TRUE.
10050          grid = 'zu1'         
10051         
10052       CASE ( 'rad_lw_in_xy', 'rad_lw_in_xz', 'rad_lw_in_yz' )
10053          IF ( av == 0 ) THEN
10054             DO  i = nxl, nxr
10055                DO  j = nys, nyn
10056                   DO  k = nzb_do, nzt_do
10057                      local_pf(i,j,k) = rad_lw_in(k,j,i)
10058                   ENDDO
10059                ENDDO
10060             ENDDO
10061          ELSE
10062            IF ( .NOT. ALLOCATED( rad_lw_in_av ) ) THEN
10063               ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10064               rad_lw_in_av = REAL( fill_value, KIND = wp )
10065            ENDIF
10066             DO  i = nxl, nxr
10067                DO  j = nys, nyn 
10068                   DO  k = nzb_do, nzt_do
10069                      local_pf(i,j,k) = rad_lw_in_av(k,j,i)
10070                   ENDDO
10071                ENDDO
10072             ENDDO
10073          ENDIF
10074          IF ( mode == 'xy' )  grid = 'zu'
10075
10076       CASE ( 'rad_lw_out_xy', 'rad_lw_out_xz', 'rad_lw_out_yz' )
10077          IF ( av == 0 ) THEN
10078             DO  i = nxl, nxr
10079                DO  j = nys, nyn
10080                   DO  k = nzb_do, nzt_do
10081                      local_pf(i,j,k) = rad_lw_out(k,j,i)
10082                   ENDDO
10083                ENDDO
10084             ENDDO
10085          ELSE
10086            IF ( .NOT. ALLOCATED( rad_lw_out_av ) ) THEN
10087               ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10088               rad_lw_out_av = REAL( fill_value, KIND = wp )
10089            ENDIF
10090             DO  i = nxl, nxr
10091                DO  j = nys, nyn 
10092                   DO  k = nzb_do, nzt_do
10093                      local_pf(i,j,k) = rad_lw_out_av(k,j,i)
10094                   ENDDO
10095                ENDDO
10096             ENDDO
10097          ENDIF   
10098          IF ( mode == 'xy' )  grid = 'zu'
10099
10100       CASE ( 'rad_lw_cs_hr_xy', 'rad_lw_cs_hr_xz', 'rad_lw_cs_hr_yz' )
10101          IF ( av == 0 ) THEN
10102             DO  i = nxl, nxr
10103                DO  j = nys, nyn
10104                   DO  k = nzb_do, nzt_do
10105                      local_pf(i,j,k) = rad_lw_cs_hr(k,j,i)
10106                   ENDDO
10107                ENDDO
10108             ENDDO
10109          ELSE
10110            IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) ) THEN
10111               ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10112               rad_lw_cs_hr_av = REAL( fill_value, KIND = wp )
10113            ENDIF
10114             DO  i = nxl, nxr
10115                DO  j = nys, nyn 
10116                   DO  k = nzb_do, nzt_do
10117                      local_pf(i,j,k) = rad_lw_cs_hr_av(k,j,i)
10118                   ENDDO
10119                ENDDO
10120             ENDDO
10121          ENDIF
10122          IF ( mode == 'xy' )  grid = 'zw'
10123
10124       CASE ( 'rad_lw_hr_xy', 'rad_lw_hr_xz', 'rad_lw_hr_yz' )
10125          IF ( av == 0 ) THEN
10126             DO  i = nxl, nxr
10127                DO  j = nys, nyn
10128                   DO  k = nzb_do, nzt_do
10129                      local_pf(i,j,k) = rad_lw_hr(k,j,i)
10130                   ENDDO
10131                ENDDO
10132             ENDDO
10133          ELSE
10134            IF ( .NOT. ALLOCATED( rad_lw_hr_av ) ) THEN
10135               ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10136               rad_lw_hr_av= REAL( fill_value, KIND = wp )
10137            ENDIF
10138             DO  i = nxl, nxr
10139                DO  j = nys, nyn 
10140                   DO  k = nzb_do, nzt_do
10141                      local_pf(i,j,k) = rad_lw_hr_av(k,j,i)
10142                   ENDDO
10143                ENDDO
10144             ENDDO
10145          ENDIF
10146          IF ( mode == 'xy' )  grid = 'zw'
10147
10148       CASE ( 'rad_sw_in_xy', 'rad_sw_in_xz', 'rad_sw_in_yz' )
10149          IF ( av == 0 ) THEN
10150             DO  i = nxl, nxr
10151                DO  j = nys, nyn
10152                   DO  k = nzb_do, nzt_do
10153                      local_pf(i,j,k) = rad_sw_in(k,j,i)
10154                   ENDDO
10155                ENDDO
10156             ENDDO
10157          ELSE
10158            IF ( .NOT. ALLOCATED( rad_sw_in_av ) ) THEN
10159               ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10160               rad_sw_in_av = REAL( fill_value, KIND = wp )
10161            ENDIF
10162             DO  i = nxl, nxr
10163                DO  j = nys, nyn 
10164                   DO  k = nzb_do, nzt_do
10165                      local_pf(i,j,k) = rad_sw_in_av(k,j,i)
10166                   ENDDO
10167                ENDDO
10168             ENDDO
10169          ENDIF
10170          IF ( mode == 'xy' )  grid = 'zu'
10171
10172       CASE ( 'rad_sw_out_xy', 'rad_sw_out_xz', 'rad_sw_out_yz' )
10173          IF ( av == 0 ) THEN
10174             DO  i = nxl, nxr
10175                DO  j = nys, nyn
10176                   DO  k = nzb_do, nzt_do
10177                      local_pf(i,j,k) = rad_sw_out(k,j,i)
10178                   ENDDO
10179                ENDDO
10180             ENDDO
10181          ELSE
10182            IF ( .NOT. ALLOCATED( rad_sw_out_av ) ) THEN
10183               ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10184               rad_sw_out_av = REAL( fill_value, KIND = wp )
10185            ENDIF
10186             DO  i = nxl, nxr
10187                DO  j = nys, nyn 
10188                   DO  k = nzb, nzt+1
10189                      local_pf(i,j,k) = rad_sw_out_av(k,j,i)
10190                   ENDDO
10191                ENDDO
10192             ENDDO
10193          ENDIF
10194          IF ( mode == 'xy' )  grid = 'zu'
10195
10196       CASE ( 'rad_sw_cs_hr_xy', 'rad_sw_cs_hr_xz', 'rad_sw_cs_hr_yz' )
10197          IF ( av == 0 ) THEN
10198             DO  i = nxl, nxr
10199                DO  j = nys, nyn
10200                   DO  k = nzb_do, nzt_do
10201                      local_pf(i,j,k) = rad_sw_cs_hr(k,j,i)
10202                   ENDDO
10203                ENDDO
10204             ENDDO
10205          ELSE
10206            IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) ) THEN
10207               ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10208               rad_sw_cs_hr_av = REAL( fill_value, KIND = wp )
10209            ENDIF
10210             DO  i = nxl, nxr
10211                DO  j = nys, nyn 
10212                   DO  k = nzb_do, nzt_do
10213                      local_pf(i,j,k) = rad_sw_cs_hr_av(k,j,i)
10214                   ENDDO
10215                ENDDO
10216             ENDDO
10217          ENDIF
10218          IF ( mode == 'xy' )  grid = 'zw'
10219
10220       CASE ( 'rad_sw_hr_xy', 'rad_sw_hr_xz', 'rad_sw_hr_yz' )
10221          IF ( av == 0 ) THEN
10222             DO  i = nxl, nxr
10223                DO  j = nys, nyn
10224                   DO  k = nzb_do, nzt_do
10225                      local_pf(i,j,k) = rad_sw_hr(k,j,i)
10226                   ENDDO
10227                ENDDO
10228             ENDDO
10229          ELSE
10230            IF ( .NOT. ALLOCATED( rad_sw_hr_av ) ) THEN
10231               ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10232               rad_sw_hr_av = REAL( fill_value, KIND = wp )
10233            ENDIF
10234             DO  i = nxl, nxr
10235                DO  j = nys, nyn 
10236                   DO  k = nzb_do, nzt_do
10237                      local_pf(i,j,k) = rad_sw_hr_av(k,j,i)
10238                   ENDDO
10239                ENDDO
10240             ENDDO
10241          ENDIF
10242          IF ( mode == 'xy' )  grid = 'zw'
10243
10244       CASE DEFAULT
10245          found = .FALSE.
10246          grid  = 'none'
10247
10248    END SELECT
10249 
10250 END SUBROUTINE radiation_data_output_2d
10251
10252
10253!------------------------------------------------------------------------------!
10254!
10255! Description:
10256! ------------
10257!> Subroutine defining 3D output variables
10258!------------------------------------------------------------------------------!
10259 SUBROUTINE radiation_data_output_3d( av, variable, found, local_pf, nzb_do, nzt_do )
10260 
10261
10262    USE indices
10263
10264    USE kinds
10265
10266
10267    IMPLICIT NONE
10268
10269    CHARACTER (LEN=*) ::  variable !<
10270
10271    INTEGER(iwp) ::  av          !<
10272    INTEGER(iwp) ::  i, j, k, l  !<
10273    INTEGER(iwp) ::  nzb_do      !<
10274    INTEGER(iwp) ::  nzt_do      !<
10275
10276    LOGICAL      ::  found       !<
10277
10278    REAL(wp)     ::  fill_value = -999.0_wp    !< value for the _FillValue attribute
10279
10280    REAL(sp), DIMENSION(nxl:nxr,nys:nyn,nzb_do:nzt_do) ::  local_pf !<
10281
10282    CHARACTER (len=varnamelength)                   :: var, surfid
10283    INTEGER(iwp)                                    :: ids,idsint_u,idsint_l,isurf,isvf,isurfs,isurflt,ipcgb
10284    INTEGER(iwp)                                    :: is, js, ks, istat
10285
10286    found = .TRUE.
10287
10288    ids = -1
10289    var = TRIM(variable)
10290    DO i = 0, nd-1
10291        k = len(TRIM(var))
10292        j = len(TRIM(dirname(i)))
10293        IF ( TRIM(var(k-j+1:k)) == TRIM(dirname(i)) )  THEN
10294            ids = i
10295            idsint_u = dirint_u(ids)
10296            idsint_l = dirint_l(ids)
10297            var = var(:k-j)
10298            EXIT
10299        ENDIF
10300    ENDDO
10301    IF ( ids == -1 )  THEN
10302        var = TRIM(variable)
10303    ENDIF
10304
10305    IF ( (var(1:8) == 'rtm_svf_'  .OR.  var(1:8) == 'rtm_dif_')  .AND.  len(TRIM(var)) >= 13 )  THEN
10306!--     svf values to particular surface
10307        surfid = var(9:)
10308        i = index(surfid,'_')
10309        j = index(surfid(i+1:),'_')
10310        READ(surfid(1:i-1),*, iostat=istat ) is
10311        IF ( istat == 0 )  THEN
10312            READ(surfid(i+1:i+j-1),*, iostat=istat ) js
10313        ENDIF
10314        IF ( istat == 0 )  THEN
10315            READ(surfid(i+j+1:),*, iostat=istat ) ks
10316        ENDIF
10317        IF ( istat == 0 )  THEN
10318            var = var(1:7)
10319        ENDIF
10320    ENDIF
10321
10322    local_pf = fill_value
10323
10324    SELECT CASE ( TRIM( var ) )
10325!--   block of large scale radiation model (e.g. RRTMG) output variables
10326      CASE ( 'rad_sw_in' )
10327         IF ( av == 0 )  THEN
10328            DO  i = nxl, nxr
10329               DO  j = nys, nyn
10330                  DO  k = nzb_do, nzt_do
10331                     local_pf(i,j,k) = rad_sw_in(k,j,i)
10332                  ENDDO
10333               ENDDO
10334            ENDDO
10335         ELSE
10336            IF ( .NOT. ALLOCATED( rad_sw_in_av ) ) THEN
10337               ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10338               rad_sw_in_av = REAL( fill_value, KIND = wp )
10339            ENDIF
10340            DO  i = nxl, nxr
10341               DO  j = nys, nyn
10342                  DO  k = nzb_do, nzt_do
10343                     local_pf(i,j,k) = rad_sw_in_av(k,j,i)
10344                  ENDDO
10345               ENDDO
10346            ENDDO
10347         ENDIF
10348
10349      CASE ( 'rad_sw_out' )
10350         IF ( av == 0 )  THEN
10351            DO  i = nxl, nxr
10352               DO  j = nys, nyn
10353                  DO  k = nzb_do, nzt_do
10354                     local_pf(i,j,k) = rad_sw_out(k,j,i)
10355                  ENDDO
10356               ENDDO
10357            ENDDO
10358         ELSE
10359            IF ( .NOT. ALLOCATED( rad_sw_out_av ) ) THEN
10360               ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10361               rad_sw_out_av = REAL( fill_value, KIND = wp )
10362            ENDIF
10363            DO  i = nxl, nxr
10364               DO  j = nys, nyn
10365                  DO  k = nzb_do, nzt_do
10366                     local_pf(i,j,k) = rad_sw_out_av(k,j,i)
10367                  ENDDO
10368               ENDDO
10369            ENDDO
10370         ENDIF
10371
10372      CASE ( 'rad_sw_cs_hr' )
10373         IF ( av == 0 )  THEN
10374            DO  i = nxl, nxr
10375               DO  j = nys, nyn
10376                  DO  k = nzb_do, nzt_do
10377                     local_pf(i,j,k) = rad_sw_cs_hr(k,j,i)
10378                  ENDDO
10379               ENDDO
10380            ENDDO
10381         ELSE
10382            IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) ) THEN
10383               ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10384               rad_sw_cs_hr_av = REAL( fill_value, KIND = wp )
10385            ENDIF
10386            DO  i = nxl, nxr
10387               DO  j = nys, nyn
10388                  DO  k = nzb_do, nzt_do
10389                     local_pf(i,j,k) = rad_sw_cs_hr_av(k,j,i)
10390                  ENDDO
10391               ENDDO
10392            ENDDO
10393         ENDIF
10394
10395      CASE ( 'rad_sw_hr' )
10396         IF ( av == 0 )  THEN
10397            DO  i = nxl, nxr
10398               DO  j = nys, nyn
10399                  DO  k = nzb_do, nzt_do
10400                     local_pf(i,j,k) = rad_sw_hr(k,j,i)
10401                  ENDDO
10402               ENDDO
10403            ENDDO
10404         ELSE
10405            IF ( .NOT. ALLOCATED( rad_sw_hr_av ) ) THEN
10406               ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10407               rad_sw_hr_av = REAL( fill_value, KIND = wp )
10408            ENDIF
10409            DO  i = nxl, nxr
10410               DO  j = nys, nyn
10411                  DO  k = nzb_do, nzt_do
10412                     local_pf(i,j,k) = rad_sw_hr_av(k,j,i)
10413                  ENDDO
10414               ENDDO
10415            ENDDO
10416         ENDIF
10417
10418      CASE ( 'rad_lw_in' )
10419         IF ( av == 0 )  THEN
10420            DO  i = nxl, nxr
10421               DO  j = nys, nyn
10422                  DO  k = nzb_do, nzt_do
10423                     local_pf(i,j,k) = rad_lw_in(k,j,i)
10424                  ENDDO
10425               ENDDO
10426            ENDDO
10427         ELSE
10428            IF ( .NOT. ALLOCATED( rad_lw_in_av ) ) THEN
10429               ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10430               rad_lw_in_av = REAL( fill_value, KIND = wp )
10431            ENDIF
10432            DO  i = nxl, nxr
10433               DO  j = nys, nyn
10434                  DO  k = nzb_do, nzt_do
10435                     local_pf(i,j,k) = rad_lw_in_av(k,j,i)
10436                  ENDDO
10437               ENDDO
10438            ENDDO
10439         ENDIF
10440
10441      CASE ( 'rad_lw_out' )
10442         IF ( av == 0 )  THEN
10443            DO  i = nxl, nxr
10444               DO  j = nys, nyn
10445                  DO  k = nzb_do, nzt_do
10446                     local_pf(i,j,k) = rad_lw_out(k,j,i)
10447                  ENDDO
10448               ENDDO
10449            ENDDO
10450         ELSE
10451            IF ( .NOT. ALLOCATED( rad_lw_out_av ) ) THEN
10452               ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10453               rad_lw_out_av = REAL( fill_value, KIND = wp )
10454            ENDIF
10455            DO  i = nxl, nxr
10456               DO  j = nys, nyn
10457                  DO  k = nzb_do, nzt_do
10458                     local_pf(i,j,k) = rad_lw_out_av(k,j,i)
10459                  ENDDO
10460               ENDDO
10461            ENDDO
10462         ENDIF
10463
10464      CASE ( 'rad_lw_cs_hr' )
10465         IF ( av == 0 )  THEN
10466            DO  i = nxl, nxr
10467               DO  j = nys, nyn
10468                  DO  k = nzb_do, nzt_do
10469                     local_pf(i,j,k) = rad_lw_cs_hr(k,j,i)
10470                  ENDDO
10471               ENDDO
10472            ENDDO
10473         ELSE
10474            IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) ) THEN
10475               ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10476               rad_lw_cs_hr_av = REAL( fill_value, KIND = wp )
10477            ENDIF
10478            DO  i = nxl, nxr
10479               DO  j = nys, nyn
10480                  DO  k = nzb_do, nzt_do
10481                     local_pf(i,j,k) = rad_lw_cs_hr_av(k,j,i)
10482                  ENDDO
10483               ENDDO
10484            ENDDO
10485         ENDIF
10486
10487      CASE ( 'rad_lw_hr' )
10488         IF ( av == 0 )  THEN
10489            DO  i = nxl, nxr
10490               DO  j = nys, nyn
10491                  DO  k = nzb_do, nzt_do
10492                     local_pf(i,j,k) = rad_lw_hr(k,j,i)
10493                  ENDDO
10494               ENDDO
10495            ENDDO
10496         ELSE
10497            IF ( .NOT. ALLOCATED( rad_lw_hr_av ) ) THEN
10498               ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10499              rad_lw_hr_av = REAL( fill_value, KIND = wp )
10500            ENDIF
10501            DO  i = nxl, nxr
10502               DO  j = nys, nyn
10503                  DO  k = nzb_do, nzt_do
10504                     local_pf(i,j,k) = rad_lw_hr_av(k,j,i)
10505                  ENDDO
10506               ENDDO
10507            ENDDO
10508         ENDIF
10509
10510!--   block of RTM output variables
10511!--   variables are intended mainly for debugging and detailed analyse purposes
10512      CASE ( 'rtm_skyvf' )
10513!--        sky view factor
10514         DO isurf = dirstart(ids), dirend(ids)
10515            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10516               local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = skyvf(isurf)
10517            ENDIF
10518         ENDDO
10519
10520      CASE ( 'rtm_skyvft' )
10521!--      sky view factor
10522         DO isurf = dirstart(ids), dirend(ids)
10523            IF ( surfl(id,isurf) == ids )  THEN
10524               local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = skyvft(isurf)
10525            ENDIF
10526         ENDDO
10527
10528      CASE ( 'rtm_svf', 'rtm_dif' )
10529!--      shape view factors or iradiance factors to selected surface
10530         IF ( TRIM(var)=='rtm_svf' )  THEN
10531             k = 1
10532         ELSE
10533             k = 2
10534         ENDIF
10535         DO isvf = 1, nsvfl
10536            isurflt = svfsurf(1, isvf)
10537            isurfs = svfsurf(2, isvf)
10538
10539            IF ( surf(ix,isurfs) == is  .AND.  surf(iy,isurfs) == js  .AND. surf(iz,isurfs) == ks  .AND. &
10540                 (surf(id,isurfs) == idsint_u .OR. surfl(id,isurfs) == idsint_l ) ) THEN
10541!--            correct source surface
10542               local_pf(surfl(ix,isurflt),surfl(iy,isurflt),surfl(iz,isurflt)) = svf(k,isvf)
10543            ENDIF
10544         ENDDO
10545
10546      CASE ( 'rtm_rad_net' )
10547!--     array of complete radiation balance
10548         DO isurf = dirstart(ids), dirend(ids)
10549            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10550               IF ( av == 0 )  THEN
10551                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = &
10552                         surfinsw(isurf) - surfoutsw(isurf) +  surfinlw(isurf) - surfoutlw(isurf)
10553               ELSE
10554                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfradnet_av(isurf)
10555               ENDIF
10556            ENDIF
10557         ENDDO
10558
10559      CASE ( 'rtm_rad_insw' )
10560!--      array of sw radiation falling to surface after i-th reflection
10561         DO isurf = dirstart(ids), dirend(ids)
10562            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10563               IF ( av == 0 )  THEN
10564                 local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinsw(isurf)
10565               ELSE
10566                 local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinsw_av(isurf)
10567               ENDIF
10568            ENDIF
10569         ENDDO
10570
10571      CASE ( 'rtm_rad_inlw' )
10572!--      array of lw radiation falling to surface after i-th reflection
10573         DO isurf = dirstart(ids), dirend(ids)
10574            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10575               IF ( av == 0 )  THEN
10576                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlw(isurf)
10577               ELSE
10578                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlw_av(isurf)
10579               ENDIF
10580             ENDIF
10581         ENDDO
10582
10583      CASE ( 'rtm_rad_inswdir' )
10584!--      array of direct sw radiation falling to surface from sun
10585         DO isurf = dirstart(ids), dirend(ids)
10586            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10587               IF ( av == 0 )  THEN
10588                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdir(isurf)
10589               ELSE
10590                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdir_av(isurf)
10591               ENDIF
10592            ENDIF
10593         ENDDO
10594
10595      CASE ( 'rtm_rad_inswdif' )
10596!--      array of difusion sw radiation falling to surface from sky and borders of the domain
10597         DO isurf = dirstart(ids), dirend(ids)
10598            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10599               IF ( av == 0 )  THEN
10600                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdif(isurf)
10601               ELSE
10602                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdif_av(isurf)
10603               ENDIF
10604            ENDIF
10605         ENDDO
10606
10607      CASE ( 'rtm_rad_inswref' )
10608!--      array of sw radiation falling to surface from reflections
10609         DO isurf = dirstart(ids), dirend(ids)
10610            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10611               IF ( av == 0 )  THEN
10612                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = &
10613                    surfinsw(isurf) - surfinswdir(isurf) - surfinswdif(isurf)
10614               ELSE
10615                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswref_av(isurf)
10616               ENDIF
10617            ENDIF
10618         ENDDO
10619
10620      CASE ( 'rtm_rad_inlwdif' )
10621!--      array of difusion lw radiation falling to surface from sky and borders of the domain
10622         DO isurf = dirstart(ids), dirend(ids)
10623            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10624               IF ( av == 0 )  THEN
10625                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlwdif(isurf)
10626               ELSE
10627                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlwdif_av(isurf)
10628               ENDIF
10629            ENDIF
10630         ENDDO
10631
10632      CASE ( 'rtm_rad_inlwref' )
10633!--      array of lw radiation falling to surface from reflections
10634         DO isurf = dirstart(ids), dirend(ids)
10635            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10636               IF ( av == 0 )  THEN
10637                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlw(isurf) - surfinlwdif(isurf)
10638               ELSE
10639                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlwref_av(isurf)
10640               ENDIF
10641            ENDIF
10642         ENDDO
10643
10644      CASE ( 'rtm_rad_outsw' )
10645!--      array of sw radiation emitted from surface after i-th reflection
10646         DO isurf = dirstart(ids), dirend(ids)
10647            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10648               IF ( av == 0 )  THEN
10649                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutsw(isurf)
10650               ELSE
10651                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutsw_av(isurf)
10652               ENDIF
10653            ENDIF
10654         ENDDO
10655
10656      CASE ( 'rtm_rad_outlw' )
10657!--      array of lw radiation emitted from surface after i-th reflection
10658         DO isurf = dirstart(ids), dirend(ids)
10659            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10660               IF ( av == 0 )  THEN
10661                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutlw(isurf)
10662               ELSE
10663                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutlw_av(isurf)
10664               ENDIF
10665            ENDIF
10666         ENDDO
10667
10668      CASE ( 'rtm_rad_ressw' )
10669!--      average of array of residua of sw radiation absorbed in surface after last reflection
10670         DO isurf = dirstart(ids), dirend(ids)
10671            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10672               IF ( av == 0 )  THEN
10673                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfins(isurf)
10674               ELSE
10675                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfins_av(isurf)
10676               ENDIF
10677            ENDIF
10678         ENDDO
10679
10680      CASE ( 'rtm_rad_reslw' )
10681!--      average of array of residua of lw radiation absorbed in surface after last reflection
10682         DO isurf = dirstart(ids), dirend(ids)
10683            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10684               IF ( av == 0 )  THEN
10685                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinl(isurf)
10686               ELSE
10687                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinl_av(isurf)
10688               ENDIF
10689            ENDIF
10690         ENDDO
10691
10692      CASE ( 'rtm_rad_pc_inlw' )
10693!--      array of lw radiation absorbed by plant canopy
10694         DO ipcgb = 1, npcbl
10695            IF ( av == 0 )  THEN
10696               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinlw(ipcgb)
10697            ELSE
10698               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinlw_av(ipcgb)
10699            ENDIF
10700         ENDDO
10701
10702      CASE ( 'rtm_rad_pc_insw' )
10703!--      array of sw radiation absorbed by plant canopy
10704         DO ipcgb = 1, npcbl
10705            IF ( av == 0 )  THEN
10706              local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinsw(ipcgb)
10707            ELSE
10708              local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinsw_av(ipcgb)
10709            ENDIF
10710         ENDDO
10711
10712      CASE ( 'rtm_rad_pc_inswdir' )
10713!--      array of direct sw radiation absorbed by plant canopy
10714         DO ipcgb = 1, npcbl
10715            IF ( av == 0 )  THEN
10716               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdir(ipcgb)
10717            ELSE
10718               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdir_av(ipcgb)
10719            ENDIF
10720         ENDDO
10721
10722      CASE ( 'rtm_rad_pc_inswdif' )
10723!--      array of diffuse sw radiation absorbed by plant canopy
10724         DO ipcgb = 1, npcbl
10725            IF ( av == 0 )  THEN
10726               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdif(ipcgb)
10727            ELSE
10728               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdif_av(ipcgb)
10729            ENDIF
10730         ENDDO
10731
10732      CASE ( 'rtm_rad_pc_inswref' )
10733!--      array of reflected sw radiation absorbed by plant canopy
10734         DO ipcgb = 1, npcbl
10735            IF ( av == 0 )  THEN
10736               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = &
10737                                    pcbinsw(ipcgb) - pcbinswdir(ipcgb) - pcbinswdif(ipcgb)
10738            ELSE
10739               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswref_av(ipcgb)
10740            ENDIF
10741         ENDDO
10742
10743      CASE ( 'rtm_mrt_sw' )
10744         local_pf = REAL( fill_value, KIND = wp )
10745         IF ( av == 0 )  THEN
10746            DO  l = 1, nmrtbl
10747               local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinsw(l)
10748            ENDDO
10749         ELSE
10750            IF ( ALLOCATED( mrtinsw_av ) ) THEN
10751               DO  l = 1, nmrtbl
10752                  local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinsw_av(l)
10753               ENDDO
10754            ENDIF
10755         ENDIF
10756
10757      CASE ( 'rtm_mrt_lw' )
10758         local_pf = REAL( fill_value, KIND = wp )
10759         IF ( av == 0 )  THEN
10760            DO  l = 1, nmrtbl
10761               local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinlw(l)
10762            ENDDO
10763         ELSE
10764            IF ( ALLOCATED( mrtinlw_av ) ) THEN
10765               DO  l = 1, nmrtbl
10766                  local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinlw_av(l)
10767               ENDDO
10768            ENDIF
10769         ENDIF
10770
10771      CASE ( 'rtm_mrt' )
10772         local_pf = REAL( fill_value, KIND = wp )
10773         IF ( av == 0 )  THEN
10774            DO  l = 1, nmrtbl
10775               local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrt(l)
10776            ENDDO
10777         ELSE
10778            IF ( ALLOCATED( mrt_av ) ) THEN
10779               DO  l = 1, nmrtbl
10780                  local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrt_av(l)
10781               ENDDO
10782            ENDIF
10783         ENDIF
10784
10785       CASE DEFAULT
10786          found = .FALSE.
10787
10788    END SELECT
10789
10790
10791 END SUBROUTINE radiation_data_output_3d
10792
10793!------------------------------------------------------------------------------!
10794!
10795! Description:
10796! ------------
10797!> Subroutine defining masked data output
10798!------------------------------------------------------------------------------!
10799 SUBROUTINE radiation_data_output_mask( av, variable, found, local_pf )
10800 
10801    USE control_parameters
10802       
10803    USE indices
10804   
10805    USE kinds
10806   
10807
10808    IMPLICIT NONE
10809
10810    CHARACTER (LEN=*) ::  variable   !<
10811
10812    CHARACTER(LEN=5) ::  grid        !< flag to distinquish between staggered grids
10813
10814    INTEGER(iwp) ::  av              !<
10815    INTEGER(iwp) ::  i               !<
10816    INTEGER(iwp) ::  j               !<
10817    INTEGER(iwp) ::  k               !<
10818    INTEGER(iwp) ::  topo_top_ind    !< k index of highest horizontal surface
10819
10820    LOGICAL ::  found                !< true if output array was found
10821    LOGICAL ::  resorted             !< true if array is resorted
10822
10823
10824    REAL(wp),                                                                  &
10825       DIMENSION(mask_size_l(mid,1),mask_size_l(mid,2),mask_size_l(mid,3)) ::  &
10826          local_pf   !<
10827
10828    REAL(wp), DIMENSION(:,:,:), POINTER ::  to_be_resorted  !< points to array which needs to be resorted for output
10829
10830
10831    found    = .TRUE.
10832    grid     = 's'
10833    resorted = .FALSE.
10834
10835    SELECT CASE ( TRIM( variable ) )
10836
10837
10838       CASE ( 'rad_lw_in' )
10839          IF ( av == 0 )  THEN
10840             to_be_resorted => rad_lw_in
10841          ELSE
10842             to_be_resorted => rad_lw_in_av
10843          ENDIF
10844
10845       CASE ( 'rad_lw_out' )
10846          IF ( av == 0 )  THEN
10847             to_be_resorted => rad_lw_out
10848          ELSE
10849             to_be_resorted => rad_lw_out_av
10850          ENDIF
10851
10852       CASE ( 'rad_lw_cs_hr' )
10853          IF ( av == 0 )  THEN
10854             to_be_resorted => rad_lw_cs_hr
10855          ELSE
10856             to_be_resorted => rad_lw_cs_hr_av
10857          ENDIF
10858
10859       CASE ( 'rad_lw_hr' )
10860          IF ( av == 0 )  THEN
10861             to_be_resorted => rad_lw_hr
10862          ELSE
10863             to_be_resorted => rad_lw_hr_av
10864          ENDIF
10865
10866       CASE ( 'rad_sw_in' )
10867          IF ( av == 0 )  THEN
10868             to_be_resorted => rad_sw_in
10869          ELSE
10870             to_be_resorted => rad_sw_in_av
10871          ENDIF
10872
10873       CASE ( 'rad_sw_out' )
10874          IF ( av == 0 )  THEN
10875             to_be_resorted => rad_sw_out
10876          ELSE
10877             to_be_resorted => rad_sw_out_av
10878          ENDIF
10879
10880       CASE ( 'rad_sw_cs_hr' )
10881          IF ( av == 0 )  THEN
10882             to_be_resorted => rad_sw_cs_hr
10883          ELSE
10884             to_be_resorted => rad_sw_cs_hr_av
10885          ENDIF
10886
10887       CASE ( 'rad_sw_hr' )
10888          IF ( av == 0 )  THEN
10889             to_be_resorted => rad_sw_hr
10890          ELSE
10891             to_be_resorted => rad_sw_hr_av
10892          ENDIF
10893
10894       CASE DEFAULT
10895          found = .FALSE.
10896
10897    END SELECT
10898
10899!
10900!-- Resort the array to be output, if not done above
10901    IF ( .NOT. resorted )  THEN
10902       IF ( .NOT. mask_surface(mid) )  THEN
10903!
10904!--       Default masked output
10905          DO  i = 1, mask_size_l(mid,1)
10906             DO  j = 1, mask_size_l(mid,2)
10907                DO  k = 1, mask_size_l(mid,3)
10908                   local_pf(i,j,k) =  to_be_resorted(mask_k(mid,k), &
10909                                      mask_j(mid,j),mask_i(mid,i))
10910                ENDDO
10911             ENDDO
10912          ENDDO
10913
10914       ELSE
10915!
10916!--       Terrain-following masked output
10917          DO  i = 1, mask_size_l(mid,1)
10918             DO  j = 1, mask_size_l(mid,2)
10919!
10920!--             Get k index of highest horizontal surface
10921                topo_top_ind = get_topography_top_index_ji( mask_j(mid,j), &
10922                                                            mask_i(mid,i), &
10923                                                            grid )
10924!
10925!--             Save output array
10926                DO  k = 1, mask_size_l(mid,3)
10927                   local_pf(i,j,k) = to_be_resorted(                       &
10928                                          MIN( topo_top_ind+mask_k(mid,k), &
10929                                               nzt+1 ),                    &
10930                                          mask_j(mid,j),                   &
10931                                          mask_i(mid,i)                     )
10932                ENDDO
10933             ENDDO
10934          ENDDO
10935
10936       ENDIF
10937    ENDIF
10938
10939
10940
10941 END SUBROUTINE radiation_data_output_mask
10942
10943
10944!------------------------------------------------------------------------------!
10945! Description:
10946! ------------
10947!> Subroutine writes local (subdomain) restart data
10948!------------------------------------------------------------------------------!
10949 SUBROUTINE radiation_wrd_local
10950
10951
10952    IMPLICIT NONE
10953
10954
10955    IF ( ALLOCATED( rad_net_av ) )  THEN
10956       CALL wrd_write_string( 'rad_net_av' )
10957       WRITE ( 14 )  rad_net_av
10958    ENDIF
10959   
10960    IF ( ALLOCATED( rad_lw_in_xy_av ) )  THEN
10961       CALL wrd_write_string( 'rad_lw_in_xy_av' )
10962       WRITE ( 14 )  rad_lw_in_xy_av
10963    ENDIF
10964   
10965    IF ( ALLOCATED( rad_lw_out_xy_av ) )  THEN
10966       CALL wrd_write_string( 'rad_lw_out_xy_av' )
10967       WRITE ( 14 )  rad_lw_out_xy_av
10968    ENDIF
10969   
10970    IF ( ALLOCATED( rad_sw_in_xy_av ) )  THEN
10971       CALL wrd_write_string( 'rad_sw_in_xy_av' )
10972       WRITE ( 14 )  rad_sw_in_xy_av
10973    ENDIF
10974   
10975    IF ( ALLOCATED( rad_sw_out_xy_av ) )  THEN
10976       CALL wrd_write_string( 'rad_sw_out_xy_av' )
10977       WRITE ( 14 )  rad_sw_out_xy_av
10978    ENDIF
10979
10980    IF ( ALLOCATED( rad_lw_in ) )  THEN
10981       CALL wrd_write_string( 'rad_lw_in' )
10982       WRITE ( 14 )  rad_lw_in
10983    ENDIF
10984
10985    IF ( ALLOCATED( rad_lw_in_av ) )  THEN
10986       CALL wrd_write_string( 'rad_lw_in_av' )
10987       WRITE ( 14 )  rad_lw_in_av
10988    ENDIF
10989
10990    IF ( ALLOCATED( rad_lw_out ) )  THEN
10991       CALL wrd_write_string( 'rad_lw_out' )
10992       WRITE ( 14 )  rad_lw_out
10993    ENDIF
10994
10995    IF ( ALLOCATED( rad_lw_out_av) )  THEN
10996       CALL wrd_write_string( 'rad_lw_out_av' )
10997       WRITE ( 14 )  rad_lw_out_av
10998    ENDIF
10999
11000    IF ( ALLOCATED( rad_lw_cs_hr) )  THEN
11001       CALL wrd_write_string( 'rad_lw_cs_hr' )
11002       WRITE ( 14 )  rad_lw_cs_hr
11003    ENDIF
11004
11005    IF ( ALLOCATED( rad_lw_cs_hr_av) )  THEN
11006       CALL wrd_write_string( 'rad_lw_cs_hr_av' )
11007       WRITE ( 14 )  rad_lw_cs_hr_av
11008    ENDIF
11009
11010    IF ( ALLOCATED( rad_lw_hr) )  THEN
11011       CALL wrd_write_string( 'rad_lw_hr' )
11012       WRITE ( 14 )  rad_lw_hr
11013    ENDIF
11014
11015    IF ( ALLOCATED( rad_lw_hr_av) )  THEN
11016       CALL wrd_write_string( 'rad_lw_hr_av' )
11017       WRITE ( 14 )  rad_lw_hr_av
11018    ENDIF
11019
11020    IF ( ALLOCATED( rad_sw_in) )  THEN
11021       CALL wrd_write_string( 'rad_sw_in' )
11022       WRITE ( 14 )  rad_sw_in
11023    ENDIF
11024
11025    IF ( ALLOCATED( rad_sw_in_av) )  THEN
11026       CALL wrd_write_string( 'rad_sw_in_av' )
11027       WRITE ( 14 )  rad_sw_in_av
11028    ENDIF
11029
11030    IF ( ALLOCATED( rad_sw_out) )  THEN
11031       CALL wrd_write_string( 'rad_sw_out' )
11032       WRITE ( 14 )  rad_sw_out
11033    ENDIF
11034
11035    IF ( ALLOCATED( rad_sw_out_av) )  THEN
11036       CALL wrd_write_string( 'rad_sw_out_av' )
11037       WRITE ( 14 )  rad_sw_out_av
11038    ENDIF
11039
11040    IF ( ALLOCATED( rad_sw_cs_hr) )  THEN
11041       CALL wrd_write_string( 'rad_sw_cs_hr' )
11042       WRITE ( 14 )  rad_sw_cs_hr
11043    ENDIF
11044
11045    IF ( ALLOCATED( rad_sw_cs_hr_av) )  THEN
11046       CALL wrd_write_string( 'rad_sw_cs_hr_av' )
11047       WRITE ( 14 )  rad_sw_cs_hr_av
11048    ENDIF
11049
11050    IF ( ALLOCATED( rad_sw_hr) )  THEN
11051       CALL wrd_write_string( 'rad_sw_hr' )
11052       WRITE ( 14 )  rad_sw_hr
11053    ENDIF
11054
11055    IF ( ALLOCATED( rad_sw_hr_av) )  THEN
11056       CALL wrd_write_string( 'rad_sw_hr_av' )
11057       WRITE ( 14 )  rad_sw_hr_av
11058    ENDIF
11059
11060
11061 END SUBROUTINE radiation_wrd_local
11062
11063!------------------------------------------------------------------------------!
11064! Description:
11065! ------------
11066!> Subroutine reads local (subdomain) restart data
11067!------------------------------------------------------------------------------!
11068 SUBROUTINE radiation_rrd_local( k, nxlf, nxlc, nxl_on_file, nxrf, nxrc,       &
11069                                nxr_on_file, nynf, nync, nyn_on_file, nysf,    &
11070                                nysc, nys_on_file, tmp_2d, tmp_3d, found )
11071 
11072
11073    USE control_parameters
11074       
11075    USE indices
11076   
11077    USE kinds
11078   
11079    USE pegrid
11080
11081
11082    IMPLICIT NONE
11083
11084    INTEGER(iwp) ::  k               !<
11085    INTEGER(iwp) ::  nxlc            !<
11086    INTEGER(iwp) ::  nxlf            !<
11087    INTEGER(iwp) ::  nxl_on_file     !<
11088    INTEGER(iwp) ::  nxrc            !<
11089    INTEGER(iwp) ::  nxrf            !<
11090    INTEGER(iwp) ::  nxr_on_file     !<
11091    INTEGER(iwp) ::  nync            !<
11092    INTEGER(iwp) ::  nynf            !<
11093    INTEGER(iwp) ::  nyn_on_file     !<
11094    INTEGER(iwp) ::  nysc            !<
11095    INTEGER(iwp) ::  nysf            !<
11096    INTEGER(iwp) ::  nys_on_file     !<
11097
11098    LOGICAL, INTENT(OUT)  :: found
11099
11100    REAL(wp), DIMENSION(nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_2d   !<
11101
11102    REAL(wp), DIMENSION(nzb:nzt+1,nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_3d   !<
11103
11104    REAL(wp), DIMENSION(0:0,nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_3d2   !<
11105
11106
11107    found = .TRUE.
11108
11109
11110    SELECT CASE ( restart_string(1:length) )
11111
11112       CASE ( 'rad_net_av' )
11113          IF ( .NOT. ALLOCATED( rad_net_av ) )  THEN
11114             ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
11115          ENDIF 
11116          IF ( k == 1 )  READ ( 13 )  tmp_2d
11117          rad_net_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =           &
11118                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11119                       
11120       CASE ( 'rad_lw_in_xy_av' )
11121          IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) )  THEN
11122             ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
11123          ENDIF 
11124          IF ( k == 1 )  READ ( 13 )  tmp_2d
11125          rad_lw_in_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =      &
11126                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11127                       
11128       CASE ( 'rad_lw_out_xy_av' )
11129          IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) )  THEN
11130             ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
11131          ENDIF 
11132          IF ( k == 1 )  READ ( 13 )  tmp_2d
11133          rad_lw_out_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =     &
11134                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11135                       
11136       CASE ( 'rad_sw_in_xy_av' )
11137          IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) )  THEN
11138             ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
11139          ENDIF 
11140          IF ( k == 1 )  READ ( 13 )  tmp_2d
11141          rad_sw_in_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =      &
11142                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11143                       
11144       CASE ( 'rad_sw_out_xy_av' )
11145          IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) )  THEN
11146             ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
11147          ENDIF 
11148          IF ( k == 1 )  READ ( 13 )  tmp_2d
11149          rad_sw_out_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =     &
11150                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11151                       
11152       CASE ( 'rad_lw_in' )
11153          IF ( .NOT. ALLOCATED( rad_lw_in ) )  THEN
11154             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11155                  radiation_scheme == 'constant')  THEN
11156                ALLOCATE( rad_lw_in(0:0,nysg:nyng,nxlg:nxrg) )
11157             ELSE
11158                ALLOCATE( rad_lw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11159             ENDIF
11160          ENDIF 
11161          IF ( k == 1 )  THEN
11162             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11163                  radiation_scheme == 'constant')  THEN
11164                READ ( 13 )  tmp_3d2
11165                rad_lw_in(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =   &
11166                   tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11167             ELSE
11168                READ ( 13 )  tmp_3d
11169                rad_lw_in(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11170                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11171             ENDIF
11172          ENDIF
11173
11174       CASE ( 'rad_lw_in_av' )
11175          IF ( .NOT. ALLOCATED( rad_lw_in_av ) )  THEN
11176             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11177                  radiation_scheme == 'constant')  THEN
11178                ALLOCATE( rad_lw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
11179             ELSE
11180                ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11181             ENDIF
11182          ENDIF 
11183          IF ( k == 1 )  THEN
11184             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11185                  radiation_scheme == 'constant')  THEN
11186                READ ( 13 )  tmp_3d2
11187                rad_lw_in_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =&
11188                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11189             ELSE
11190                READ ( 13 )  tmp_3d
11191                rad_lw_in_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11192                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11193             ENDIF
11194          ENDIF
11195
11196       CASE ( 'rad_lw_out' )
11197          IF ( .NOT. ALLOCATED( rad_lw_out ) )  THEN
11198             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11199                  radiation_scheme == 'constant')  THEN
11200                ALLOCATE( rad_lw_out(0:0,nysg:nyng,nxlg:nxrg) )
11201             ELSE
11202                ALLOCATE( rad_lw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11203             ENDIF
11204          ENDIF 
11205          IF ( k == 1 )  THEN
11206             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11207                  radiation_scheme == 'constant')  THEN
11208                READ ( 13 )  tmp_3d2
11209                rad_lw_out(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11210                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11211             ELSE
11212                READ ( 13 )  tmp_3d
11213                rad_lw_out(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =    &
11214                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11215             ENDIF
11216          ENDIF
11217
11218       CASE ( 'rad_lw_out_av' )
11219          IF ( .NOT. ALLOCATED( rad_lw_out_av ) )  THEN
11220             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11221                  radiation_scheme == 'constant')  THEN
11222                ALLOCATE( rad_lw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
11223             ELSE
11224                ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11225             ENDIF
11226          ENDIF 
11227          IF ( k == 1 )  THEN
11228             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11229                  radiation_scheme == 'constant')  THEN
11230                READ ( 13 )  tmp_3d2
11231                rad_lw_out_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) &
11232                   = tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11233             ELSE
11234                READ ( 13 )  tmp_3d
11235                rad_lw_out_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &
11236                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11237             ENDIF
11238          ENDIF
11239
11240       CASE ( 'rad_lw_cs_hr' )
11241          IF ( .NOT. ALLOCATED( rad_lw_cs_hr ) )  THEN
11242             ALLOCATE( rad_lw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11243          ENDIF
11244          IF ( k == 1 )  READ ( 13 )  tmp_3d
11245          rad_lw_cs_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11246                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11247
11248       CASE ( 'rad_lw_cs_hr_av' )
11249          IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) )  THEN
11250             ALLOCATE( rad_lw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11251          ENDIF
11252          IF ( k == 1 )  READ ( 13 )  tmp_3d
11253          rad_lw_cs_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11254                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11255
11256       CASE ( 'rad_lw_hr' )
11257          IF ( .NOT. ALLOCATED( rad_lw_hr ) )  THEN
11258             ALLOCATE( rad_lw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11259          ENDIF
11260          IF ( k == 1 )  READ ( 13 )  tmp_3d
11261          rad_lw_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =           &
11262                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11263
11264       CASE ( 'rad_lw_hr_av' )
11265          IF ( .NOT. ALLOCATED( rad_lw_hr_av ) )  THEN
11266             ALLOCATE( rad_lw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11267          ENDIF
11268          IF ( k == 1 )  READ ( 13 )  tmp_3d
11269          rad_lw_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11270                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11271
11272       CASE ( 'rad_sw_in' )
11273          IF ( .NOT. ALLOCATED( rad_sw_in ) )  THEN
11274             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11275                  radiation_scheme == 'constant')  THEN
11276                ALLOCATE( rad_sw_in(0:0,nysg:nyng,nxlg:nxrg) )
11277             ELSE
11278                ALLOCATE( rad_sw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11279             ENDIF
11280          ENDIF 
11281          IF ( k == 1 )  THEN
11282             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11283                  radiation_scheme == 'constant')  THEN
11284                READ ( 13 )  tmp_3d2
11285                rad_sw_in(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =   &
11286                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11287             ELSE
11288                READ ( 13 )  tmp_3d
11289                rad_sw_in(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11290                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11291             ENDIF
11292          ENDIF
11293
11294       CASE ( 'rad_sw_in_av' )
11295          IF ( .NOT. ALLOCATED( rad_sw_in_av ) )  THEN
11296             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11297                  radiation_scheme == 'constant')  THEN
11298                ALLOCATE( rad_sw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
11299             ELSE
11300                ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11301             ENDIF
11302          ENDIF 
11303          IF ( k == 1 )  THEN
11304             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11305                  radiation_scheme == 'constant')  THEN
11306                READ ( 13 )  tmp_3d2
11307                rad_sw_in_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =&
11308                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11309             ELSE
11310                READ ( 13 )  tmp_3d
11311                rad_sw_in_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11312                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11313             ENDIF
11314          ENDIF
11315
11316       CASE ( 'rad_sw_out' )
11317          IF ( .NOT. ALLOCATED( rad_sw_out ) )  THEN
11318             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11319                  radiation_scheme == 'constant')  THEN
11320                ALLOCATE( rad_sw_out(0:0,nysg:nyng,nxlg:nxrg) )
11321             ELSE
11322                ALLOCATE( rad_sw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11323             ENDIF
11324          ENDIF 
11325          IF ( k == 1 )  THEN
11326             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11327                  radiation_scheme == 'constant')  THEN
11328                READ ( 13 )  tmp_3d2
11329                rad_sw_out(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11330                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11331             ELSE
11332                READ ( 13 )  tmp_3d
11333                rad_sw_out(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =    &
11334                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11335             ENDIF
11336          ENDIF
11337
11338       CASE ( 'rad_sw_out_av' )
11339          IF ( .NOT. ALLOCATED( rad_sw_out_av ) )  THEN
11340             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11341                  radiation_scheme == 'constant')  THEN
11342                ALLOCATE( rad_sw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
11343             ELSE
11344                ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11345             ENDIF
11346          ENDIF 
11347          IF ( k == 1 )  THEN
11348             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11349                  radiation_scheme == 'constant')  THEN
11350                READ ( 13 )  tmp_3d2
11351                rad_sw_out_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) &
11352                   = tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11353             ELSE
11354                READ ( 13 )  tmp_3d
11355                rad_sw_out_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &
11356                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11357             ENDIF
11358          ENDIF
11359
11360       CASE ( 'rad_sw_cs_hr' )
11361          IF ( .NOT. ALLOCATED( rad_sw_cs_hr ) )  THEN
11362             ALLOCATE( rad_sw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11363          ENDIF
11364          IF ( k == 1 )  READ ( 13 )  tmp_3d
11365          rad_sw_cs_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11366                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11367
11368       CASE ( 'rad_sw_cs_hr_av' )
11369          IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) )  THEN
11370             ALLOCATE( rad_sw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11371          ENDIF
11372          IF ( k == 1 )  READ ( 13 )  tmp_3d
11373          rad_sw_cs_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11374                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11375
11376       CASE ( 'rad_sw_hr' )
11377          IF ( .NOT. ALLOCATED( rad_sw_hr ) )  THEN
11378             ALLOCATE( rad_sw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11379          ENDIF
11380          IF ( k == 1 )  READ ( 13 )  tmp_3d
11381          rad_sw_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =           &
11382                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11383
11384       CASE ( 'rad_sw_hr_av' )
11385          IF ( .NOT. ALLOCATED( rad_sw_hr_av ) )  THEN
11386             ALLOCATE( rad_sw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11387          ENDIF
11388          IF ( k == 1 )  READ ( 13 )  tmp_3d
11389          rad_lw_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11390                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11391
11392       CASE DEFAULT
11393
11394          found = .FALSE.
11395
11396    END SELECT
11397
11398 END SUBROUTINE radiation_rrd_local
11399
11400!------------------------------------------------------------------------------!
11401! Description:
11402! ------------
11403!> Subroutine writes debug information
11404!------------------------------------------------------------------------------!
11405 SUBROUTINE radiation_write_debug_log ( message )
11406    !> it writes debug log with time stamp
11407    CHARACTER(*)  :: message
11408    CHARACTER(15) :: dtc
11409    CHARACTER(8)  :: date
11410    CHARACTER(10) :: time
11411    CHARACTER(5)  :: zone
11412    CALL date_and_time(date, time, zone)
11413    dtc = date(7:8)//','//time(1:2)//':'//time(3:4)//':'//time(5:10)
11414    WRITE(9,'(2A)') dtc, TRIM(message)
11415    FLUSH(9)
11416 END SUBROUTINE radiation_write_debug_log
11417
11418 END MODULE radiation_model_mod
Note: See TracBrowser for help on using the repository browser.