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

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

Bugfixes for calculation and I/O of view factors

  • 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: 500.1 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 3754 2019-02-19 17:02:26Z kanani $
30! (resler, pavelkrc)
31! Bugfixes: add further required MRT factors to read/write_svf,
32! fix for aggregating view factors to eliminate local noise in reflected
33! irradiance at mutually close surfaces (corners, presence of trees) in the
34! angular discretization scheme.
35!
36! 3752 2019-02-19 09:37:22Z resler
37! added read/write number of MRT factors to the respective routines
38!
39! 3705 2019-01-29 19:56:39Z suehring
40! Make variables that are sampled in virtual measurement module public
41!
42! 3704 2019-01-29 19:51:41Z suehring
43! Some interface calls moved to module_interface + cleanup
44!
45! 3667 2019-01-10 14:26:24Z schwenkel
46! Modified check for rrtmg input files
47!
48! 3655 2019-01-07 16:51:22Z knoop
49! nopointer option removed
50!
51! 3633 2018-12-17 16:17:57Z schwenkel
52! Include check for rrtmg files
53!
54! 3630 2018-12-17 11:04:17Z knoop
55! - fix initialization of date and time after calling zenith
56! - fix a bug in radiation_solar_pos
57!
58! 3616 2018-12-10 09:44:36Z Salim
59! fix manipulation of time variables in radiation_presimulate_solar_pos
60!
61! 3608 2018-12-07 12:59:57Z suehring $
62! Bugfix radiation output
63!
64! 3607 2018-12-07 11:56:58Z suehring
65! Output of radiation-related quantities migrated to radiation_model_mod.
66!
67! 3589 2018-11-30 15:09:51Z suehring
68! Remove erroneous UTF encoding
69!
70! 3572 2018-11-28 11:40:28Z suehring
71! Add filling the short- and longwave radiation flux arrays (e.g. diffuse,
72! direct, reflected, resedual) for all surfaces. This is required to surface
73! outputs in suface_output_mod. (M. Salim)
74!
75! 3571 2018-11-28 09:24:03Z moh.hefny
76! Add an epsilon value to compare values in if statement to fix possible
77! precsion related errors in raytrace routines.
78!
79! 3524 2018-11-14 13:36:44Z raasch
80! missing cpp-directives added
81!
82! 3495 2018-11-06 15:22:17Z kanani
83! Resort control_parameters ONLY list,
84! From branch radiation@3491 moh.hefny:
85! bugfix in calculating the apparent solar positions by updating
86! the simulated time so that the actual time is correct.
87!
88! 3464 2018-10-30 18:08:55Z kanani
89! From branch resler@3462, pavelkrc:
90! add MRT shaping function for human
91!
92! 3449 2018-10-29 19:36:56Z suehring
93! New RTM version 3.0: (Pavel Krc, Jaroslav Resler, ICS, Prague)
94!   - Interaction of plant canopy with LW radiation
95!   - Transpiration from resolved plant canopy dependent on radiation
96!     called from RTM
97!
98!
99! 3435 2018-10-26 18:25:44Z gronemeier
100! - workaround: return unit=illegal in check_data_output for certain variables
101!   when check called from init_masks
102! - Use pointer in masked output to reduce code redundancies
103! - Add terrain-following masked output
104!
105! 3424 2018-10-25 07:29:10Z gronemeier
106! bugfix: add rad_lw_in, rad_lw_out, rad_sw_out to radiation_check_data_output
107!
108! 3378 2018-10-19 12:34:59Z kanani
109! merge from radiation branch (r3362) into trunk
110! (moh.hefny):
111! - removed read/write_svf_on_init and read_dist_max_svf (not used anymore)
112! - bugfix nzut > nzpt in calculating maxboxes
113!
114! 3372 2018-10-18 14:03:19Z raasch
115! bugfix: kind type of 2nd argument of mpi_win_allocate changed, misplaced
116!         __parallel directive
117!
118! 3351 2018-10-15 18:40:42Z suehring
119! Do not overwrite values of spectral and broadband albedo during initialization
120! if they are already initialized in the urban-surface model via ASCII input.
121!
122! 3337 2018-10-12 15:17:09Z kanani
123! - New RTM version 2.9: (Pavel Krc, Jaroslav Resler, ICS, Prague)
124!   added calculation of the MRT inside the RTM module
125!   MRT fluxes are consequently used in the new biometeorology module
126!   for calculation of biological indices (MRT, PET)
127!   Fixes of v. 2.5 and SVN trunk:
128!    - proper initialization of rad_net_l
129!    - make arrays nsurfs and surfstart TARGET to prevent some MPI problems
130!    - initialization of arrays used in MPI one-sided operation as 1-D arrays
131!      to prevent problems with some MPI/compiler combinations
132!    - fix indexing of target displacement in subroutine request_itarget to
133!      consider nzub
134!    - fix LAD dimmension range in PCB calculation
135!    - check ierr in all MPI calls
136!    - use proper per-gridbox sky and diffuse irradiance
137!    - fix shading for reflected irradiance
138!    - clear away the residuals of "atmospheric surfaces" implementation
139!    - fix rounding bug in raytrace_2d introduced in SVN trunk
140! - New RTM version 2.5: (Pavel Krc, Jaroslav Resler, ICS, Prague)
141!   can use angular discretization for all SVF
142!   (i.e. reflected and emitted radiation in addition to direct and diffuse),
143!   allowing for much better scaling wih high resoltion and/or complex terrain
144! - Unite array grow factors
145! - Fix slightly shifted terrain height in raytrace_2d
146! - Use more efficient MPI_Win_allocate for reverse gridsurf index
147! - Fix random MPI RMA bugs on Intel compilers
148! - Fix approx. double plant canopy sink values for reflected radiation
149! - Fix mostly missing plant canopy sinks for direct radiation
150! - Fix discretization errors for plant canopy sink in diffuse radiation
151! - Fix rounding errors in raytrace_2d
152!
153! 3274 2018-09-24 15:42:55Z knoop
154! Modularization of all bulk cloud physics code components
155!
156! 3272 2018-09-24 10:16:32Z suehring
157! - split direct and diffusion shortwave radiation using RRTMG rather than using
158!   calc_diffusion_radiation, in case of RRTMG
159! - removed the namelist variable split_diffusion_radiation. Now splitting depends
160!   on the choise of radiation radiation scheme
161! - removed calculating the rdiation flux for surfaces at the radiation scheme
162!   in case of using RTM since it will be calculated anyway in the radiation
163!   interaction routine.
164! - set SW radiation flux for surfaces to zero at night in case of no RTM is used
165! - precalculate the unit vector yxdir of ray direction to avoid the temporarly
166!   array allocation during the subroutine call
167! - fixed a bug in calculating the max number of boxes ray can cross in the domain
168!
169! 3264 2018-09-20 13:54:11Z moh.hefny
170! Bugfix in raytrace_2d calls
171!
172! 3248 2018-09-14 09:42:06Z sward
173! Minor formating changes
174!
175! 3246 2018-09-13 15:14:50Z sward
176! Added error handling for input namelist via parin_fail_message
177!
178! 3241 2018-09-12 15:02:00Z raasch
179! unused variables removed or commented
180!
181! 3233 2018-09-07 13:21:24Z schwenkel
182! Adapted for the use of cloud_droplets
183!
184! 3230 2018-09-05 09:29:05Z schwenkel
185! Bugfix in radiation_constant_surf: changed (10.0 - emissivity_urb) to
186! (1.0 - emissivity_urb)
187!
188! 3226 2018-08-31 12:27:09Z suehring
189! Bugfixes in calculation of sky-view factors and canopy-sink factors.
190!
191! 3186 2018-07-30 17:07:14Z suehring
192! Remove print statement
193!
194! 3180 2018-07-27 11:00:56Z suehring
195! Revise concept for calculation of effective radiative temperature and mapping
196! of radiative heating
197!
198! 3175 2018-07-26 14:07:38Z suehring
199! Bugfix for commit 3172
200!
201! 3173 2018-07-26 12:55:23Z suehring
202! Revise output of surface radiation quantities in case of overhanging
203! structures
204!
205! 3172 2018-07-26 12:06:06Z suehring
206! Bugfixes:
207!  - temporal work-around for calculation of effective radiative surface
208!    temperature
209!  - prevent positive solar radiation during nighttime
210!
211! 3170 2018-07-25 15:19:37Z suehring
212! Bugfix, map signle-column radiation forcing profiles on top of any topography
213!
214! 3156 2018-07-19 16:30:54Z knoop
215! Bugfix: replaced usage of the pt array with the surf%pt_surface array
216!
217! 3137 2018-07-17 06:44:21Z maronga
218! String length for trace_names fixed
219!
220! 3127 2018-07-15 08:01:25Z maronga
221! A few pavement parameters updated.
222!
223! 3123 2018-07-12 16:21:53Z suehring
224! Correct working precision for INTEGER number
225!
226! 3122 2018-07-11 21:46:41Z maronga
227! Bugfix: maximum distance for raytracing was set to  -999 m by default,
228! effectively switching off all surface reflections when max_raytracing_dist
229! was not explicitly set in namelist
230!
231! 3117 2018-07-11 09:59:11Z maronga
232! Bugfix: water vapor was not transfered to RRTMG when bulk_cloud_model = .F.
233! Bugfix: changed the calculation of RRTMG boundary conditions (Mohamed Salim)
234! Bugfix: dry residual atmosphere is replaced by standard RRTMG atmosphere
235!
236! 3116 2018-07-10 14:31:58Z suehring
237! Output of long/shortwave radiation at surface
238!
239! 3107 2018-07-06 15:55:51Z suehring
240! Bugfix, missing index for dz
241!
242! 3066 2018-06-12 08:55:55Z Giersch
243! Error message revised
244!
245! 3065 2018-06-12 07:03:02Z Giersch
246! dz was replaced by dz(1), error message concerning vertical stretching was
247! added 
248!
249! 3049 2018-05-29 13:52:36Z Giersch
250! Error messages revised
251!
252! 3045 2018-05-28 07:55:41Z Giersch
253! Error message revised
254!
255! 3026 2018-05-22 10:30:53Z schwenkel
256! Changed the name specific humidity to mixing ratio, since we are computing
257! mixing ratios.
258!
259! 3016 2018-05-09 10:53:37Z Giersch
260! Revised structure of reading svf data according to PALM coding standard:
261! svf_code_field/len and fsvf removed, error messages PA0493 and PA0494 added,
262! allocation status of output arrays checked.
263!
264! 3014 2018-05-09 08:42:38Z maronga
265! Introduced plant canopy height similar to urban canopy height to limit
266! the memory requirement to allocate lad.
267! Deactivated automatic setting of minimum raytracing distance.
268!
269! 3004 2018-04-27 12:33:25Z Giersch
270! Further allocation checks implemented (averaged data will be assigned to fill
271! values if no allocation happened so far)
272!
273! 2995 2018-04-19 12:13:16Z Giersch
274! IF-statement in radiation_init removed so that the calculation of radiative
275! fluxes at model start is done in any case, bugfix in
276! radiation_presimulate_solar_pos (end_time is the sum of end_time and the
277! spinup_time specified in the p3d_file ), list of variables/fields that have
278! to be written out or read in case of restarts has been extended
279!
280! 2977 2018-04-17 10:27:57Z kanani
281! Implement changes from branch radiation (r2948-2971) with minor modifications,
282! plus some formatting.
283! (moh.hefny):
284! - replaced plant_canopy by npcbl to check tree existence to avoid weird
285!   allocation of related arrays (after domain decomposition some domains
286!   contains no trees although plant_canopy (global parameter) is still TRUE).
287! - added a namelist parameter to force RTM settings
288! - enabled the option to switch radiation reflections off
289! - renamed surf_reflections to surface_reflections
290! - removed average_radiation flag from the namelist (now it is implicitly set
291!   in init_3d_model according to RTM)
292! - edited read and write sky view factors and CSF routines to account for
293!   the sub-domains which may not contain any of them
294!
295! 2967 2018-04-13 11:22:08Z raasch
296! bugfix: missing parallel cpp-directives added
297!
298! 2964 2018-04-12 16:04:03Z Giersch
299! Error message PA0491 has been introduced which could be previously found in
300! check_open. The variable numprocs_previous_run is only known in case of
301! initializing_actions == read_restart_data
302!
303! 2963 2018-04-12 14:47:44Z suehring
304! - Introduce index for vegetation/wall, pavement/green-wall and water/window
305!   surfaces, for clearer access of surface fraction, albedo, emissivity, etc. .
306! - Minor bugfix in initialization of albedo for window surfaces
307!
308! 2944 2018-04-03 16:20:18Z suehring
309! Fixed bad commit
310!
311! 2943 2018-04-03 16:17:10Z suehring
312! No read of nsurfl from SVF file since it is calculated in
313! radiation_interaction_init,
314! allocation of arrays in radiation_read_svf only if not yet allocated,
315! update of 2920 revision comment.
316!
317! 2932 2018-03-26 09:39:22Z maronga
318! renamed radiation_par to radiation_parameters
319!
320! 2930 2018-03-23 16:30:46Z suehring
321! Remove default surfaces from radiation model, does not make much sense to
322! apply radiation model without energy-balance solvers; Further, add check for
323! this.
324!
325! 2920 2018-03-22 11:22:01Z kanani
326! - Bugfix: Initialize pcbl array (=-1)
327! RTM version 2.0 (Jaroslav Resler, Pavel Krc, Mohamed Salim):
328! - new major version of radiation interactions
329! - substantially enhanced performance and scalability
330! - processing of direct and diffuse solar radiation separated from reflected
331!   radiation, removed virtual surfaces
332! - new type of sky discretization by azimuth and elevation angles
333! - diffuse radiation processed cumulatively using sky view factor
334! - used precalculated apparent solar positions for direct irradiance
335! - added new 2D raytracing process for processing whole vertical column at once
336!   to increase memory efficiency and decrease number of MPI RMA operations
337! - enabled limiting the number of view factors between surfaces by the distance
338!   and value
339! - fixing issues induced by transferring radiation interactions from
340!   urban_surface_mod to radiation_mod
341! - bugfixes and other minor enhancements
342!
343! 2906 2018-03-19 08:56:40Z Giersch
344! NAMELIST paramter read/write_svf_on_init have been removed, functions
345! check_open and close_file are used now for opening/closing files related to
346! svf data, adjusted unit number and error numbers
347!
348! 2894 2018-03-15 09:17:58Z Giersch
349! Calculations of the index range of the subdomain on file which overlaps with
350! the current subdomain are already done in read_restart_data_mod
351! radiation_read_restart_data was renamed to radiation_rrd_local and
352! radiation_last_actions was renamed to radiation_wrd_local, variable named
353! found has been introduced for checking if restart data was found, reading
354! of restart strings has been moved completely to read_restart_data_mod,
355! radiation_rrd_local is already inside the overlap loop programmed in
356! read_restart_data_mod, the marker *** end rad *** is not necessary anymore,
357! strings and their respective lengths are written out and read now in case of
358! restart runs to get rid of prescribed character lengths (Giersch)
359!
360! 2809 2018-02-15 09:55:58Z suehring
361! Bugfix for gfortran: Replace the function C_SIZEOF with STORAGE_SIZE
362!
363! 2753 2018-01-16 14:16:49Z suehring
364! Tile approach for spectral albedo implemented.
365!
366! 2746 2018-01-15 12:06:04Z suehring
367! Move flag plant canopy to modules
368!
369! 2724 2018-01-05 12:12:38Z maronga
370! Set default of average_radiation to .FALSE.
371!
372! 2723 2018-01-05 09:27:03Z maronga
373! Bugfix in calculation of rad_lw_out (clear-sky). First grid level was used
374! instead of the surface value
375!
376! 2718 2018-01-02 08:49:38Z maronga
377! Corrected "Former revisions" section
378!
379! 2707 2017-12-18 18:34:46Z suehring
380! Changes from last commit documented
381!
382! 2706 2017-12-18 18:33:49Z suehring
383! Bugfix, in average radiation case calculate exner function before using it.
384!
385! 2701 2017-12-15 15:40:50Z suehring
386! Changes from last commit documented
387!
388! 2698 2017-12-14 18:46:24Z suehring
389! Bugfix in get_topography_top_index
390!
391! 2696 2017-12-14 17:12:51Z kanani
392! - Change in file header (GPL part)
393! - Improved reading/writing of SVF from/to file (BM)
394! - Bugfixes concerning RRTMG as well as average_radiation options (M. Salim)
395! - Revised initialization of surface albedo and some minor bugfixes (MS)
396! - Update net radiation after running radiation interaction routine (MS)
397! - Revisions from M Salim included
398! - Adjustment to topography and surface structure (MS)
399! - Initialization of albedo and surface emissivity via input file (MS)
400! - albedo_pars extended (MS)
401!
402! 2604 2017-11-06 13:29:00Z schwenkel
403! bugfix for calculation of effective radius using morrison microphysics
404!
405! 2601 2017-11-02 16:22:46Z scharf
406! added emissivity to namelist
407!
408! 2575 2017-10-24 09:57:58Z maronga
409! Bugfix: calculation of shortwave and longwave albedos for RRTMG swapped
410!
411! 2547 2017-10-16 12:41:56Z schwenkel
412! extended by cloud_droplets option, minor bugfix and correct calculation of
413! cloud droplet number concentration
414!
415! 2544 2017-10-13 18:09:32Z maronga
416! Moved date and time quantitis to separate module date_and_time_mod
417!
418! 2512 2017-10-04 08:26:59Z raasch
419! upper bounds of cross section and 3d output changed from nx+1,ny+1 to nx,ny
420! no output of ghost layer data
421!
422! 2504 2017-09-27 10:36:13Z maronga
423! Updates pavement types and albedo parameters
424!
425! 2328 2017-08-03 12:34:22Z maronga
426! Emissivity can now be set individually for each pixel.
427! Albedo type can be inferred from land surface model.
428! Added default albedo type for bare soil
429!
430! 2318 2017-07-20 17:27:44Z suehring
431! Get topography top index via Function call
432!
433! 2317 2017-07-20 17:27:19Z suehring
434! Improved syntax layout
435!
436! 2298 2017-06-29 09:28:18Z raasch
437! type of write_binary changed from CHARACTER to LOGICAL
438!
439! 2296 2017-06-28 07:53:56Z maronga
440! Added output of rad_sw_out for radiation_scheme = 'constant'
441!
442! 2270 2017-06-09 12:18:47Z maronga
443! Numbering changed (2 timeseries removed)
444!
445! 2249 2017-06-06 13:58:01Z sward
446! Allow for RRTMG runs without humidity/cloud physics
447!
448! 2248 2017-06-06 13:52:54Z sward
449! Error no changed
450!
451! 2233 2017-05-30 18:08:54Z suehring
452!
453! 2232 2017-05-30 17:47:52Z suehring
454! Adjustments to new topography concept
455! Bugfix in read restart
456!
457! 2200 2017-04-11 11:37:51Z suehring
458! Bugfix in call of exchange_horiz_2d and read restart data
459!
460! 2163 2017-03-01 13:23:15Z schwenkel
461! Bugfix in radiation_check_data_output
462!
463! 2157 2017-02-22 15:10:35Z suehring
464! Bugfix in read_restart data
465!
466! 2011 2016-09-19 17:29:57Z kanani
467! Removed CALL of auxiliary SUBROUTINE get_usm_info,
468! flag urban_surface is now defined in module control_parameters.
469!
470! 2007 2016-08-24 15:47:17Z kanani
471! Added calculation of solar directional vector for new urban surface
472! model,
473! accounted for urban_surface model in radiation_check_parameters,
474! correction of comments for zenith angle.
475!
476! 2000 2016-08-20 18:09:15Z knoop
477! Forced header and separation lines into 80 columns
478!
479! 1976 2016-07-27 13:28:04Z maronga
480! Output of 2D/3D/masked data is now directly done within this module. The
481! radiation schemes have been simplified for better usability so that
482! rad_lw_in, rad_lw_out, rad_sw_in, and rad_sw_out are available independent of
483! the radiation code used.
484!
485! 1856 2016-04-13 12:56:17Z maronga
486! Bugfix: allocation of rad_lw_out for radiation_scheme = 'clear-sky'
487!
488! 1853 2016-04-11 09:00:35Z maronga
489! Added routine for radiation_scheme = constant.
490
491! 1849 2016-04-08 11:33:18Z hoffmann
492! Adapted for modularization of microphysics
493!
494! 1826 2016-04-07 12:01:39Z maronga
495! Further modularization.
496!
497! 1788 2016-03-10 11:01:04Z maronga
498! Added new albedo class for pavements / roads.
499!
500! 1783 2016-03-06 18:36:17Z raasch
501! palm-netcdf-module removed in order to avoid a circular module dependency,
502! netcdf-variables moved to netcdf-module, new routine netcdf_handle_error_rad
503! added
504!
505! 1757 2016-02-22 15:49:32Z maronga
506! Added parameter unscheduled_radiation_calls. Bugfix: interpolation of sounding
507! profiles for pressure and temperature above the LES domain.
508!
509! 1709 2015-11-04 14:47:01Z maronga
510! Bugfix: set initial value for rrtm_lwuflx_dt to zero, small formatting
511! corrections
512!
513! 1701 2015-11-02 07:43:04Z maronga
514! Bugfixes: wrong index for output of timeseries, setting of nz_snd_end
515!
516! 1691 2015-10-26 16:17:44Z maronga
517! Added option for spin-up runs without radiation (skip_time_do_radiation). Bugfix
518! in calculation of pressure profiles. Bugfix in calculation of trace gas profiles.
519! Added output of radiative heating rates.
520!
521! 1682 2015-10-07 23:56:08Z knoop
522! Code annotations made doxygen readable
523!
524! 1606 2015-06-29 10:43:37Z maronga
525! Added preprocessor directive __netcdf to allow for compiling without netCDF.
526! Note, however, that RRTMG cannot be used without netCDF.
527!
528! 1590 2015-05-08 13:56:27Z maronga
529! Bugfix: definition of character strings requires same length for all elements
530!
531! 1587 2015-05-04 14:19:01Z maronga
532! Added albedo class for snow
533!
534! 1585 2015-04-30 07:05:52Z maronga
535! Added support for RRTMG
536!
537! 1571 2015-03-12 16:12:49Z maronga
538! Added missing KIND attribute. Removed upper-case variable names
539!
540! 1551 2015-03-03 14:18:16Z maronga
541! Added support for data output. Various variables have been renamed. Added
542! interface for different radiation schemes (currently: clear-sky, constant, and
543! RRTM (not yet implemented).
544!
545! 1496 2014-12-02 17:25:50Z maronga
546! Initial revision
547!
548!
549! Description:
550! ------------
551!> Radiation models and interfaces
552!> @todo Replace dz(1) appropriatly to account for grid stretching
553!> @todo move variable definitions used in radiation_init only to the subroutine
554!>       as they are no longer required after initialization.
555!> @todo Output of full column vertical profiles used in RRTMG
556!> @todo Output of other rrtm arrays (such as volume mixing ratios)
557!> @todo Check for mis-used NINT() calls in raytrace_2d
558!>       RESULT: Original was correct (carefully verified formula), the change
559!>               to INT broke raytracing      -- P. Krc
560!> @todo Optimize radiation_tendency routines
561!>
562!> @note Many variables have a leading dummy dimension (0:0) in order to
563!>       match the assume-size shape expected by the RRTMG model.
564!------------------------------------------------------------------------------!
565 MODULE radiation_model_mod
566 
567    USE arrays_3d,                                                             &
568        ONLY:  dzw, hyp, nc, pt, p, q, ql, u, v, w, zu, zw, exner, d_exner
569
570    USE basic_constants_and_equations_mod,                                     &
571        ONLY:  c_p, g, lv_d_cp, l_v, pi, r_d, rho_l, solar_constant,      &
572               barometric_formula
573
574    USE calc_mean_profile_mod,                                                 &
575        ONLY:  calc_mean_profile
576
577    USE control_parameters,                                                    &
578        ONLY:  cloud_droplets, coupling_char, dz, dt_spinup, end_time,         &
579               humidity,                                                       &
580               initializing_actions, io_blocks, io_group,                      &
581               land_surface, large_scale_forcing,                              &
582               latitude, longitude, lsf_surf,                                  &
583               message_string, plant_canopy, pt_surface,                       &
584               rho_surface, simulated_time, spinup_time, surface_pressure,     &
585               read_svf, write_svf,                                            &
586               time_since_reference_point, urban_surface, varnamelength
587
588    USE cpulog,                                                                &
589        ONLY:  cpu_log, log_point, log_point_s
590
591    USE grid_variables,                                                        &
592         ONLY:  ddx, ddy, dx, dy 
593
594    USE date_and_time_mod,                                                     &
595        ONLY:  calc_date_and_time, d_hours_day, d_seconds_hour, d_seconds_year,&
596               day_of_year, d_seconds_year, day_of_month, day_of_year_init,    &
597               init_date_and_time, month_of_year, time_utc_init, time_utc
598
599    USE indices,                                                               &
600        ONLY:  nnx, nny, nx, nxl, nxlg, nxr, nxrg, ny, nyn, nyng, nys, nysg,   &
601               nzb, nzt
602
603    USE, INTRINSIC :: iso_c_binding
604
605    USE kinds
606
607    USE bulk_cloud_model_mod,                                                  &
608        ONLY:  bulk_cloud_model, microphysics_morrison, na_init, nc_const, sigma_gc
609
610#if defined ( __netcdf )
611    USE NETCDF
612#endif
613
614    USE netcdf_data_input_mod,                                                 &
615        ONLY:  albedo_type_f, albedo_pars_f, building_type_f, pavement_type_f, &
616               vegetation_type_f, water_type_f
617
618    USE plant_canopy_model_mod,                                                &
619        ONLY:  lad_s, pc_heating_rate, pc_transpiration_rate, pc_latent_rate,  &
620               plant_canopy_transpiration, pcm_calc_transpiration_rate
621
622    USE pegrid
623
624#if defined ( __rrtmg )
625    USE parrrsw,                                                               &
626        ONLY:  naerec, nbndsw
627
628    USE parrrtm,                                                               &
629        ONLY:  nbndlw
630
631    USE rrtmg_lw_init,                                                         &
632        ONLY:  rrtmg_lw_ini
633
634    USE rrtmg_sw_init,                                                         &
635        ONLY:  rrtmg_sw_ini
636
637    USE rrtmg_lw_rad,                                                          &
638        ONLY:  rrtmg_lw
639
640    USE rrtmg_sw_rad,                                                          &
641        ONLY:  rrtmg_sw
642#endif
643    USE statistics,                                                            &
644        ONLY:  hom
645
646    USE surface_mod,                                                           &
647        ONLY:  get_topography_top_index, get_topography_top_index_ji,          &
648               ind_pav_green, ind_veg_wall, ind_wat_win,                       &
649               surf_lsm_h, surf_lsm_v, surf_type, surf_usm_h, surf_usm_v,      &
650               vertical_surfaces_exist
651
652    IMPLICIT NONE
653
654    CHARACTER(10) :: radiation_scheme = 'clear-sky' ! 'constant', 'clear-sky', or 'rrtmg'
655
656!
657!-- Predefined Land surface classes (albedo_type) after Briegleb (1992)
658    CHARACTER(37), DIMENSION(0:33), PARAMETER :: albedo_type_name = (/      &
659                                   'user defined                         ', & !  0
660                                   'ocean                                ', & !  1
661                                   'mixed farming, tall grassland        ', & !  2
662                                   'tall/medium grassland                ', & !  3
663                                   'evergreen shrubland                  ', & !  4
664                                   'short grassland/meadow/shrubland     ', & !  5
665                                   'evergreen needleleaf forest          ', & !  6
666                                   'mixed deciduous evergreen forest     ', & !  7
667                                   'deciduous forest                     ', & !  8
668                                   'tropical evergreen broadleaved forest', & !  9
669                                   'medium/tall grassland/woodland       ', & ! 10
670                                   'desert, sandy                        ', & ! 11
671                                   'desert, rocky                        ', & ! 12
672                                   'tundra                               ', & ! 13
673                                   'land ice                             ', & ! 14
674                                   'sea ice                              ', & ! 15
675                                   'snow                                 ', & ! 16
676                                   'bare soil                            ', & ! 17
677                                   'asphalt/concrete mix                 ', & ! 18
678                                   'asphalt (asphalt concrete)           ', & ! 19
679                                   'concrete (Portland concrete)         ', & ! 20
680                                   'sett                                 ', & ! 21
681                                   'paving stones                        ', & ! 22
682                                   'cobblestone                          ', & ! 23
683                                   'metal                                ', & ! 24
684                                   'wood                                 ', & ! 25
685                                   'gravel                               ', & ! 26
686                                   'fine gravel                          ', & ! 27
687                                   'pebblestone                          ', & ! 28
688                                   'woodchips                            ', & ! 29
689                                   'tartan (sports)                      ', & ! 30
690                                   'artifical turf (sports)              ', & ! 31
691                                   'clay (sports)                        ', & ! 32
692                                   'building (dummy)                     '  & ! 33
693                                                         /)
694
695    REAL(wp), PARAMETER :: sigma_sb       = 5.67037321E-8_wp !< Stefan-Boltzmann constant
696
697    INTEGER(iwp) :: albedo_type  = 9999999, & !< Albedo surface type
698                    dots_rad     = 0          !< starting index for timeseries output
699
700    LOGICAL ::  unscheduled_radiation_calls = .TRUE., & !< flag parameter indicating whether additional calls of the radiation code are allowed
701                constant_albedo = .FALSE.,            & !< flag parameter indicating whether the albedo may change depending on zenith
702                force_radiation_call = .FALSE.,       & !< flag parameter for unscheduled radiation calls
703                lw_radiation = .TRUE.,                & !< flag parameter indicating whether longwave radiation shall be calculated
704                radiation = .FALSE.,                  & !< flag parameter indicating whether the radiation model is used
705                sun_up    = .TRUE.,                   & !< flag parameter indicating whether the sun is up or down
706                sw_radiation = .TRUE.,                & !< flag parameter indicating whether shortwave radiation shall be calculated
707                sun_direction = .FALSE.,              & !< flag parameter indicating whether solar direction shall be calculated
708                average_radiation = .FALSE.,          & !< flag to set the calculation of radiation averaging for the domain
709                radiation_interactions = .FALSE.,     & !< flag to activiate RTM (TRUE only if vertical urban/land surface and trees exist)
710                surface_reflections = .TRUE.,         & !< flag to switch the calculation of radiation interaction between surfaces.
711                                                        !< When it switched off, only the effect of buildings and trees shadow
712                                                        !< will be considered. However fewer SVFs are expected.
713                radiation_interactions_on = .TRUE.      !< namelist flag to force RTM activiation regardless to vertical urban/land surface and trees
714
715    REAL(wp) :: albedo = 9999999.9_wp,           & !< NAMELIST alpha
716                albedo_lw_dif = 9999999.9_wp,    & !< NAMELIST aldif
717                albedo_lw_dir = 9999999.9_wp,    & !< NAMELIST aldir
718                albedo_sw_dif = 9999999.9_wp,    & !< NAMELIST asdif
719                albedo_sw_dir = 9999999.9_wp,    & !< NAMELIST asdir
720                decl_1,                          & !< declination coef. 1
721                decl_2,                          & !< declination coef. 2
722                decl_3,                          & !< declination coef. 3
723                dt_radiation = 0.0_wp,           & !< radiation model timestep
724                emissivity = 9999999.9_wp,       & !< NAMELIST surface emissivity
725                lon = 0.0_wp,                    & !< longitude in radians
726                lat = 0.0_wp,                    & !< latitude in radians
727                net_radiation = 0.0_wp,          & !< net radiation at surface
728                skip_time_do_radiation = 0.0_wp, & !< Radiation model is not called before this time
729                sky_trans,                       & !< sky transmissivity
730                time_radiation = 0.0_wp            !< time since last call of radiation code
731
732
733    REAL(wp), DIMENSION(0:0) ::  zenith,         & !< cosine of solar zenith angle
734                                 sun_dir_lat,    & !< solar directional vector in latitudes
735                                 sun_dir_lon       !< solar directional vector in longitudes
736
737    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_net_av       !< average of net radiation (rad_net) at surface
738    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_lw_in_xy_av  !< average of incoming longwave radiation at surface
739    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_lw_out_xy_av !< average of outgoing longwave radiation at surface
740    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_sw_in_xy_av  !< average of incoming shortwave radiation at surface
741    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_sw_out_xy_av !< average of outgoing shortwave radiation at surface
742!
743!-- Land surface albedos for solar zenith angle of 60degree after Briegleb (1992)     
744!-- (shortwave, longwave, broadband):   sw,      lw,      bb,
745    REAL(wp), DIMENSION(0:2,1:33), PARAMETER :: albedo_pars = RESHAPE( (/& 
746                                   0.06_wp, 0.06_wp, 0.06_wp,            & !  1
747                                   0.09_wp, 0.28_wp, 0.19_wp,            & !  2
748                                   0.11_wp, 0.33_wp, 0.23_wp,            & !  3
749                                   0.11_wp, 0.33_wp, 0.23_wp,            & !  4
750                                   0.14_wp, 0.34_wp, 0.25_wp,            & !  5
751                                   0.06_wp, 0.22_wp, 0.14_wp,            & !  6
752                                   0.06_wp, 0.27_wp, 0.17_wp,            & !  7
753                                   0.06_wp, 0.31_wp, 0.19_wp,            & !  8
754                                   0.06_wp, 0.22_wp, 0.14_wp,            & !  9
755                                   0.06_wp, 0.28_wp, 0.18_wp,            & ! 10
756                                   0.35_wp, 0.51_wp, 0.43_wp,            & ! 11
757                                   0.24_wp, 0.40_wp, 0.32_wp,            & ! 12
758                                   0.10_wp, 0.27_wp, 0.19_wp,            & ! 13
759                                   0.90_wp, 0.65_wp, 0.77_wp,            & ! 14
760                                   0.90_wp, 0.65_wp, 0.77_wp,            & ! 15
761                                   0.95_wp, 0.70_wp, 0.82_wp,            & ! 16
762                                   0.08_wp, 0.08_wp, 0.08_wp,            & ! 17
763                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 18
764                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 19
765                                   0.30_wp, 0.30_wp, 0.30_wp,            & ! 20
766                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 21
767                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 22
768                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 23
769                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 24
770                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 25
771                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 26
772                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 27
773                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 28
774                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 29
775                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 30
776                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 31
777                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 32
778                                   0.17_wp, 0.17_wp, 0.17_wp             & ! 33
779                                 /), (/ 3, 33 /) )
780
781    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE, TARGET :: &
782                        rad_lw_cs_hr,                  & !< longwave clear sky radiation heating rate (K/s)
783                        rad_lw_cs_hr_av,               & !< average of rad_lw_cs_hr
784                        rad_lw_hr,                     & !< longwave radiation heating rate (K/s)
785                        rad_lw_hr_av,                  & !< average of rad_sw_hr
786                        rad_lw_in,                     & !< incoming longwave radiation (W/m2)
787                        rad_lw_in_av,                  & !< average of rad_lw_in
788                        rad_lw_out,                    & !< outgoing longwave radiation (W/m2)
789                        rad_lw_out_av,                 & !< average of rad_lw_out
790                        rad_sw_cs_hr,                  & !< shortwave clear sky radiation heating rate (K/s)
791                        rad_sw_cs_hr_av,               & !< average of rad_sw_cs_hr
792                        rad_sw_hr,                     & !< shortwave radiation heating rate (K/s)
793                        rad_sw_hr_av,                  & !< average of rad_sw_hr
794                        rad_sw_in,                     & !< incoming shortwave radiation (W/m2)
795                        rad_sw_in_av,                  & !< average of rad_sw_in
796                        rad_sw_out,                    & !< outgoing shortwave radiation (W/m2)
797                        rad_sw_out_av                    !< average of rad_sw_out
798
799
800!
801!-- Variables and parameters used in RRTMG only
802#if defined ( __rrtmg )
803    CHARACTER(LEN=12) :: rrtm_input_file = "RAD_SND_DATA" !< name of the NetCDF input file (sounding data)
804
805
806!
807!-- Flag parameters for RRTMGS (should not be changed)
808    INTEGER(iwp), PARAMETER :: rrtm_idrv     = 1, & !< flag for longwave upward flux calculation option (0,1)
809                               rrtm_inflglw  = 2, & !< flag for lw cloud optical properties (0,1,2)
810                               rrtm_iceflglw = 0, & !< flag for lw ice particle specifications (0,1,2,3)
811                               rrtm_liqflglw = 1, & !< flag for lw liquid droplet specifications
812                               rrtm_inflgsw  = 2, & !< flag for sw cloud optical properties (0,1,2)
813                               rrtm_iceflgsw = 0, & !< flag for sw ice particle specifications (0,1,2,3)
814                               rrtm_liqflgsw = 1    !< flag for sw liquid droplet specifications
815
816!
817!-- The following variables should be only changed with care, as this will
818!-- require further setting of some variables, which is currently not
819!-- implemented (aerosols, ice phase).
820    INTEGER(iwp) :: nzt_rad,           & !< upper vertical limit for radiation calculations
821                    rrtm_icld = 0,     & !< cloud flag (0: clear sky column, 1: cloudy column)
822                    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)
823
824    INTEGER(iwp) :: nc_stat !< local variable for storin the result of netCDF calls for error message handling
825
826    LOGICAL :: snd_exists = .FALSE.      !< flag parameter to check whether a user-defined input files exists
827    LOGICAL :: sw_exists = .FALSE.       !< flag parameter to check whether that required rrtmg sw file exists
828    LOGICAL :: lw_exists = .FALSE.       !< flag parameter to check whether that required rrtmg lw file exists
829
830
831    REAL(wp), PARAMETER :: mol_mass_air_d_wv = 1.607793_wp !< molecular weight dry air / water vapor
832
833    REAL(wp), DIMENSION(:), ALLOCATABLE :: hyp_snd,     & !< hypostatic pressure from sounding data (hPa)
834                                           rrtm_tsfc,   & !< dummy array for storing surface temperature
835                                           t_snd          !< actual temperature from sounding data (hPa)
836
837    REAL(wp), DIMENSION(:,:), ALLOCATABLE :: rrtm_ccl4vmr,   & !< CCL4 volume mixing ratio (g/mol)
838                                             rrtm_cfc11vmr,  & !< CFC11 volume mixing ratio (g/mol)
839                                             rrtm_cfc12vmr,  & !< CFC12 volume mixing ratio (g/mol)
840                                             rrtm_cfc22vmr,  & !< CFC22 volume mixing ratio (g/mol)
841                                             rrtm_ch4vmr,    & !< CH4 volume mixing ratio
842                                             rrtm_cicewp,    & !< in-cloud ice water path (g/m2)
843                                             rrtm_cldfr,     & !< cloud fraction (0,1)
844                                             rrtm_cliqwp,    & !< in-cloud liquid water path (g/m2)
845                                             rrtm_co2vmr,    & !< CO2 volume mixing ratio (g/mol)
846                                             rrtm_emis,      & !< surface emissivity (0-1) 
847                                             rrtm_h2ovmr,    & !< H2O volume mixing ratio
848                                             rrtm_n2ovmr,    & !< N2O volume mixing ratio
849                                             rrtm_o2vmr,     & !< O2 volume mixing ratio
850                                             rrtm_o3vmr,     & !< O3 volume mixing ratio
851                                             rrtm_play,      & !< pressure layers (hPa, zu-grid)
852                                             rrtm_plev,      & !< pressure layers (hPa, zw-grid)
853                                             rrtm_reice,     & !< cloud ice effective radius (microns)
854                                             rrtm_reliq,     & !< cloud water drop effective radius (microns)
855                                             rrtm_tlay,      & !< actual temperature (K, zu-grid)
856                                             rrtm_tlev,      & !< actual temperature (K, zw-grid)
857                                             rrtm_lwdflx,    & !< RRTM output of incoming longwave radiation flux (W/m2)
858                                             rrtm_lwdflxc,   & !< RRTM output of outgoing clear sky longwave radiation flux (W/m2)
859                                             rrtm_lwuflx,    & !< RRTM output of outgoing longwave radiation flux (W/m2)
860                                             rrtm_lwuflxc,   & !< RRTM output of incoming clear sky longwave radiation flux (W/m2)
861                                             rrtm_lwuflx_dt, & !< RRTM output of incoming clear sky longwave radiation flux (W/m2)
862                                             rrtm_lwuflxc_dt,& !< RRTM output of outgoing clear sky longwave radiation flux (W/m2)
863                                             rrtm_lwhr,      & !< RRTM output of longwave radiation heating rate (K/d)
864                                             rrtm_lwhrc,     & !< RRTM output of incoming longwave clear sky radiation heating rate (K/d)
865                                             rrtm_swdflx,    & !< RRTM output of incoming shortwave radiation flux (W/m2)
866                                             rrtm_swdflxc,   & !< RRTM output of outgoing clear sky shortwave radiation flux (W/m2)
867                                             rrtm_swuflx,    & !< RRTM output of outgoing shortwave radiation flux (W/m2)
868                                             rrtm_swuflxc,   & !< RRTM output of incoming clear sky shortwave radiation flux (W/m2)
869                                             rrtm_swhr,      & !< RRTM output of shortwave radiation heating rate (K/d)
870                                             rrtm_swhrc,     & !< RRTM output of incoming shortwave clear sky radiation heating rate (K/d)
871                                             rrtm_dirdflux,  & !< RRTM output of incoming direct shortwave (W/m2)
872                                             rrtm_difdflux     !< RRTM output of incoming diffuse shortwave (W/m2)
873
874    REAL(wp), DIMENSION(1) ::                rrtm_aldif,     & !< surface albedo for longwave diffuse radiation
875                                             rrtm_aldir,     & !< surface albedo for longwave direct radiation
876                                             rrtm_asdif,     & !< surface albedo for shortwave diffuse radiation
877                                             rrtm_asdir        !< surface albedo for shortwave direct radiation
878
879!
880!-- Definition of arrays that are currently not used for calling RRTMG (due to setting of flag parameters)
881    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::  rad_lw_cs_in,   & !< incoming clear sky longwave radiation (W/m2) (not used)
882                                                rad_lw_cs_out,  & !< outgoing clear sky longwave radiation (W/m2) (not used)
883                                                rad_sw_cs_in,   & !< incoming clear sky shortwave radiation (W/m2) (not used)
884                                                rad_sw_cs_out,  & !< outgoing clear sky shortwave radiation (W/m2) (not used)
885                                                rrtm_lw_tauaer, & !< lw aerosol optical depth
886                                                rrtm_lw_taucld, & !< lw in-cloud optical depth
887                                                rrtm_sw_taucld, & !< sw in-cloud optical depth
888                                                rrtm_sw_ssacld, & !< sw in-cloud single scattering albedo
889                                                rrtm_sw_asmcld, & !< sw in-cloud asymmetry parameter
890                                                rrtm_sw_fsfcld, & !< sw in-cloud forward scattering fraction
891                                                rrtm_sw_tauaer, & !< sw aerosol optical depth
892                                                rrtm_sw_ssaaer, & !< sw aerosol single scattering albedo
893                                                rrtm_sw_asmaer, & !< sw aerosol asymmetry parameter
894                                                rrtm_sw_ecaer     !< sw aerosol optical detph at 0.55 microns (rrtm_iaer = 6 only)
895
896#endif
897!
898!-- Parameters of urban and land surface models
899    INTEGER(iwp)                                   ::  nzu                                !< number of layers of urban surface (will be calculated)
900    INTEGER(iwp)                                   ::  nzp                                !< number of layers of plant canopy (will be calculated)
901    INTEGER(iwp)                                   ::  nzub,nzut                          !< bottom and top layer of urban surface (will be calculated)
902    INTEGER(iwp)                                   ::  nzpt                               !< top layer of plant canopy (will be calculated)
903!-- parameters of urban and land surface models
904    INTEGER(iwp), PARAMETER                        ::  nzut_free = 3                      !< number of free layers above top of of topography
905    INTEGER(iwp), PARAMETER                        ::  ndsvf = 2                          !< number of dimensions of real values in SVF
906    INTEGER(iwp), PARAMETER                        ::  idsvf = 2                          !< number of dimensions of integer values in SVF
907    INTEGER(iwp), PARAMETER                        ::  ndcsf = 1                          !< number of dimensions of real values in CSF
908    INTEGER(iwp), PARAMETER                        ::  idcsf = 2                          !< number of dimensions of integer values in CSF
909    INTEGER(iwp), PARAMETER                        ::  kdcsf = 4                          !< number of dimensions of integer values in CSF calculation array
910    INTEGER(iwp), PARAMETER                        ::  id = 1                             !< position of d-index in surfl and surf
911    INTEGER(iwp), PARAMETER                        ::  iz = 2                             !< position of k-index in surfl and surf
912    INTEGER(iwp), PARAMETER                        ::  iy = 3                             !< position of j-index in surfl and surf
913    INTEGER(iwp), PARAMETER                        ::  ix = 4                             !< position of i-index in surfl and surf
914
915    INTEGER(iwp), PARAMETER                        ::  nsurf_type = 10                    !< number of surf types incl. phys.(land+urban) & (atm.,sky,boundary) surfaces - 1
916
917    INTEGER(iwp), PARAMETER                        ::  iup_u    = 0                       !< 0 - index of urban upward surface (ground or roof)
918    INTEGER(iwp), PARAMETER                        ::  idown_u  = 1                       !< 1 - index of urban downward surface (overhanging)
919    INTEGER(iwp), PARAMETER                        ::  inorth_u = 2                       !< 2 - index of urban northward facing wall
920    INTEGER(iwp), PARAMETER                        ::  isouth_u = 3                       !< 3 - index of urban southward facing wall
921    INTEGER(iwp), PARAMETER                        ::  ieast_u  = 4                       !< 4 - index of urban eastward facing wall
922    INTEGER(iwp), PARAMETER                        ::  iwest_u  = 5                       !< 5 - index of urban westward facing wall
923
924    INTEGER(iwp), PARAMETER                        ::  iup_l    = 6                       !< 6 - index of land upward surface (ground or roof)
925    INTEGER(iwp), PARAMETER                        ::  inorth_l = 7                       !< 7 - index of land northward facing wall
926    INTEGER(iwp), PARAMETER                        ::  isouth_l = 8                       !< 8 - index of land southward facing wall
927    INTEGER(iwp), PARAMETER                        ::  ieast_l  = 9                       !< 9 - index of land eastward facing wall
928    INTEGER(iwp), PARAMETER                        ::  iwest_l  = 10                      !< 10- index of land westward facing wall
929
930    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  idir = (/0, 0,0, 0,1,-1,0,0, 0,1,-1/)   !< surface normal direction x indices
931    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  jdir = (/0, 0,1,-1,0, 0,0,1,-1,0, 0/)   !< surface normal direction y indices
932    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  kdir = (/1,-1,0, 0,0, 0,1,0, 0,0, 0/)   !< surface normal direction z indices
933    REAL(wp),     DIMENSION(0:nsurf_type)          :: facearea                            !< area of single face in respective
934                                                                                          !< direction (will be calc'd)
935
936
937!-- indices and sizes of urban and land surface models
938    INTEGER(iwp)                                   ::  startland        !< start index of block of land and roof surfaces
939    INTEGER(iwp)                                   ::  endland          !< end index of block of land and roof surfaces
940    INTEGER(iwp)                                   ::  nlands           !< number of land and roof surfaces in local processor
941    INTEGER(iwp)                                   ::  startwall        !< start index of block of wall surfaces
942    INTEGER(iwp)                                   ::  endwall          !< end index of block of wall surfaces
943    INTEGER(iwp)                                   ::  nwalls           !< number of wall surfaces in local processor
944
945!-- indices needed for RTM netcdf output subroutines
946    INTEGER(iwp), PARAMETER                        :: nd = 5
947    CHARACTER(LEN=6), DIMENSION(0:nd-1), PARAMETER :: dirname = (/ '_roof ', '_south', '_north', '_west ', '_east ' /)
948    INTEGER(iwp), DIMENSION(0:nd-1), PARAMETER     :: dirint_u = (/ iup_u, isouth_u, inorth_u, iwest_u, ieast_u /)
949    INTEGER(iwp), DIMENSION(0:nd-1), PARAMETER     :: dirint_l = (/ iup_l, isouth_l, inorth_l, iwest_l, ieast_l /)
950    INTEGER(iwp), DIMENSION(0:nd-1)                :: dirstart
951    INTEGER(iwp), DIMENSION(0:nd-1)                :: dirend
952
953!-- indices and sizes of urban and land surface models
954    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surfl_l          !< coordinates of i-th local surface in local grid - surfl[:,k] = [d, z, y, x]
955    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surf_l           !< coordinates of i-th surface in grid - surf[:,k] = [d, z, y, x]
956    INTEGER(iwp), DIMENSION(:,:), POINTER          ::  surfl            !< coordinates of i-th local surface in local grid - surfl[:,k] = [d, z, y, x]
957    INTEGER(iwp), DIMENSION(:,:), POINTER          ::  surf             !< coordinates of i-th surface in grid - surf[:,k] = [d, z, y, x]
958    INTEGER(iwp)                                   ::  nsurfl           !< number of all surfaces in local processor
959    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  nsurfs           !< array of number of all surfaces in individual processors
960    INTEGER(iwp)                                   ::  nsurf            !< global number of surfaces in index array of surfaces (nsurf = proc nsurfs)
961    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surfstart        !< starts of blocks of surfaces for individual processors in array surf (indexed from 1)
962                                                                        !< respective block for particular processor is surfstart[iproc+1]+1 : surfstart[iproc+1]+nsurfs[iproc+1]
963
964!-- block variables needed for calculation of the plant canopy model inside the urban surface model
965    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pct              !< top layer of the plant canopy
966    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pch              !< heights of the plant canopy
967    INTEGER(iwp)                                   ::  npcbl = 0        !< number of the plant canopy gridboxes in local processor
968    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pcbl             !< k,j,i coordinates of l-th local plant canopy box pcbl[:,l] = [k, j, i]
969    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinsw          !< array of absorbed sw radiation for local plant canopy box
970    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdir       !< array of absorbed direct sw radiation for local plant canopy box
971    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdif       !< array of absorbed diffusion sw radiation for local plant canopy box
972    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinlw          !< array of absorbed lw radiation for local plant canopy box
973
974!-- configuration parameters (they can be setup in PALM config)
975    LOGICAL                                        ::  raytrace_mpi_rma = .TRUE.          !< use MPI RMA to access LAD and gridsurf from remote processes during raytracing
976    LOGICAL                                        ::  rad_angular_discretization = .TRUE.!< whether to use fixed resolution discretization of view factors for
977                                                                                          !< reflected radiation (as opposed to all mutually visible pairs)
978    LOGICAL                                        ::  plant_lw_interact = .TRUE.         !< whether plant canopy interacts with LW radiation (in addition to SW)
979    INTEGER(iwp)                                   ::  mrt_nlevels = 0                    !< number of vertical boxes above surface for which to calculate MRT
980    LOGICAL                                        ::  mrt_skip_roof = .TRUE.             !< do not calculate MRT above roof surfaces
981    LOGICAL                                        ::  mrt_include_sw = .TRUE.            !< should MRT calculation include SW radiation as well?
982    LOGICAL                                        ::  mrt_geom_human = .TRUE.            !< MRT direction weights simulate human body instead of a sphere
983    INTEGER(iwp)                                   ::  nrefsteps = 3                      !< number of reflection steps to perform
984    REAL(wp), PARAMETER                            ::  ext_coef = 0.6_wp                  !< extinction coefficient (a.k.a. alpha)
985    INTEGER(iwp), PARAMETER                        ::  rad_version_len = 10               !< length of identification string of rad version
986    CHARACTER(rad_version_len), PARAMETER          ::  rad_version = 'RAD v. 3.0'         !< identification of version of binary svf and restart files
987    INTEGER(iwp)                                   ::  raytrace_discrete_elevs = 40       !< number of discretization steps for elevation (nadir to zenith)
988    INTEGER(iwp)                                   ::  raytrace_discrete_azims = 80       !< number of discretization steps for azimuth (out of 360 degrees)
989    REAL(wp)                                       ::  max_raytracing_dist = -999.0_wp    !< maximum distance for raytracing (in metres)
990    REAL(wp)                                       ::  min_irrf_value = 1e-6_wp           !< minimum potential irradiance factor value for raytracing
991    REAL(wp), DIMENSION(1:30)                      ::  svfnorm_report_thresh = 1e21_wp    !< thresholds of SVF normalization values to report
992    INTEGER(iwp)                                   ::  svfnorm_report_num                 !< number of SVF normalization thresholds to report
993
994!-- radiation related arrays to be used in radiation_interaction routine
995    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_sw_in_dir    !< direct sw radiation
996    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_sw_in_diff   !< diffusion sw radiation
997    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_lw_in_diff   !< diffusion lw radiation
998
999!-- parameters required for RRTMG lower boundary condition
1000    REAL(wp)                   :: albedo_urb      !< albedo value retuned to RRTMG boundary cond.
1001    REAL(wp)                   :: emissivity_urb  !< emissivity value retuned to RRTMG boundary cond.
1002    REAL(wp)                   :: t_rad_urb       !< temperature value retuned to RRTMG boundary cond.
1003
1004!-- type for calculation of svf
1005    TYPE t_svf
1006        INTEGER(iwp)                               :: isurflt           !<
1007        INTEGER(iwp)                               :: isurfs            !<
1008        REAL(wp)                                   :: rsvf              !<
1009        REAL(wp)                                   :: rtransp           !<
1010    END TYPE
1011
1012!-- type for calculation of csf
1013    TYPE t_csf
1014        INTEGER(iwp)                               :: ip                !<
1015        INTEGER(iwp)                               :: itx               !<
1016        INTEGER(iwp)                               :: ity               !<
1017        INTEGER(iwp)                               :: itz               !<
1018        INTEGER(iwp)                               :: isurfs            !< Idx of source face / -1 for sky
1019        REAL(wp)                                   :: rcvf              !< Canopy view factor for faces /
1020                                                                        !< canopy sink factor for sky (-1)
1021    END TYPE
1022
1023!-- arrays storing the values of USM
1024    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  svfsurf          !< svfsurf[:,isvf] = index of target and source surface for svf[isvf]
1025    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  svf              !< array of shape view factors+direct irradiation factors for local surfaces
1026    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfins          !< array of sw radiation falling to local surface after i-th reflection
1027    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinl          !< array of lw radiation for local surface after i-th reflection
1028
1029    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  skyvf            !< array of sky view factor for each local surface
1030    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  skyvft           !< array of sky view factor including transparency for each local surface
1031    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsitrans         !< dsidir[isvfl,i] = path transmittance of i-th
1032                                                                        !< direction of direct solar irradiance per target surface
1033    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsitransc        !< dtto per plant canopy box
1034    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsidir           !< dsidir[:,i] = unit vector of i-th
1035                                                                        !< direction of direct solar irradiance
1036    INTEGER(iwp)                                   ::  ndsidir          !< number of apparent solar directions used
1037    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  dsidir_rev       !< dsidir_rev[ielev,iazim] = i for dsidir or -1 if not present
1038
1039    INTEGER(iwp)                                   ::  nmrtbl           !< No. of local grid boxes for which MRT is calculated
1040    INTEGER(iwp)                                   ::  nmrtf            !< number of MRT factors for local processor
1041    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  mrtbl            !< coordinates of i-th local MRT box - surfl[:,i] = [z, y, x]
1042    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  mrtfsurf         !< mrtfsurf[:,imrtf] = index of target MRT box and source surface for mrtf[imrtf]
1043    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtf             !< array of MRT factors for each local MRT box
1044    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtft            !< array of MRT factors including transparency for each local MRT box
1045    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtsky           !< array of sky view factor for each local MRT box
1046    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtskyt          !< array of sky view factor including transparency for each local MRT box
1047    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  mrtdsit          !< array of direct solar transparencies for each local MRT box
1048    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinsw          !< mean SW radiant flux for each MRT box
1049    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinlw          !< mean LW radiant flux for each MRT box
1050    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrt              !< mean radiant temperature for each MRT box
1051    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinsw_av       !< time average mean SW radiant flux for each MRT box
1052    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinlw_av       !< time average mean LW radiant flux for each MRT box
1053    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrt_av           !< time average mean radiant temperature for each MRT box
1054
1055    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinsw         !< array of sw radiation falling to local surface including radiation from reflections
1056    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlw         !< array of lw radiation falling to local surface including radiation from reflections
1057    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdir      !< array of direct sw radiation falling to local surface
1058    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdif      !< array of diffuse sw radiation from sky and model boundary falling to local surface
1059    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwdif      !< array of diffuse lw radiation from sky and model boundary falling to local surface
1060   
1061                                                                        !< Outward radiation is only valid for nonvirtual surfaces
1062    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsl        !< array of reflected sw radiation for local surface in i-th reflection
1063    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutll        !< array of reflected + emitted lw radiation for local surface in i-th reflection
1064    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfouts         !< array of reflected sw radiation for all surfaces in i-th reflection
1065    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutl         !< array of reflected + emitted lw radiation for all surfaces in i-th reflection
1066    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlg         !< global array of incoming lw radiation from plant canopy
1067    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsw        !< array of total sw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1068    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutlw        !< array of total lw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1069    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfemitlwl      !< array of emitted lw radiation for local surface used to calculate effective surface temperature for radiation model
1070
1071!-- block variables needed for calculation of the plant canopy model inside the urban surface model
1072    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  csfsurf          !< csfsurf[:,icsf] = index of target surface and csf grid index for csf[icsf]
1073    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  csf              !< array of plant canopy sink fators + direct irradiation factors (transparency)
1074    REAL(wp), DIMENSION(:,:,:), POINTER            ::  sub_lad          !< subset of lad_s within urban surface, transformed to plain Z coordinate
1075    REAL(wp), DIMENSION(:), POINTER                ::  sub_lad_g        !< sub_lad globalized (used to avoid MPI RMA calls in raytracing)
1076    REAL(wp)                                       ::  prototype_lad    !< prototype leaf area density for computing effective optical depth
1077    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  nzterr, plantt   !< temporary global arrays for raytracing
1078    INTEGER(iwp)                                   ::  plantt_max
1079
1080!-- arrays and variables for calculation of svf and csf
1081    TYPE(t_svf), DIMENSION(:), POINTER             ::  asvf             !< pointer to growing svc array
1082    TYPE(t_csf), DIMENSION(:), POINTER             ::  acsf             !< pointer to growing csf array
1083    TYPE(t_svf), DIMENSION(:), POINTER             ::  amrtf            !< pointer to growing mrtf array
1084    TYPE(t_svf), DIMENSION(:), ALLOCATABLE, TARGET ::  asvf1, asvf2     !< realizations of svf array
1085    TYPE(t_csf), DIMENSION(:), ALLOCATABLE, TARGET ::  acsf1, acsf2     !< realizations of csf array
1086    TYPE(t_svf), DIMENSION(:), ALLOCATABLE, TARGET ::  amrtf1, amrtf2   !< realizations of mftf array
1087    INTEGER(iwp)                                   ::  nsvfla           !< dimmension of array allocated for storage of svf in local processor
1088    INTEGER(iwp)                                   ::  ncsfla           !< dimmension of array allocated for storage of csf in local processor
1089    INTEGER(iwp)                                   ::  nmrtfa           !< dimmension of array allocated for storage of mrt
1090    INTEGER(iwp)                                   ::  msvf, mcsf, mmrtf!< mod for swapping the growing array
1091    INTEGER(iwp), PARAMETER                        ::  gasize = 100000  !< initial size of growing arrays
1092    REAL(wp), PARAMETER                            ::  grow_factor = 1.4_wp !< growth factor of growing arrays
1093    INTEGER(iwp)                                   ::  nsvfl            !< number of svf for local processor
1094    INTEGER(iwp)                                   ::  ncsfl            !< no. of csf in local processor
1095                                                                        !< needed only during calc_svf but must be here because it is
1096                                                                        !< shared between subroutines calc_svf and raytrace
1097    INTEGER(iwp), DIMENSION(:,:,:,:), POINTER      ::  gridsurf         !< reverse index of local surfl[d,k,j,i] (for case rad_angular_discretization)
1098    INTEGER(iwp), DIMENSION(:,:,:), ALLOCATABLE    ::  gridpcbl         !< reverse index of local pcbl[k,j,i]
1099    INTEGER(iwp), PARAMETER                        ::  nsurf_type_u = 6 !< number of urban surf types (used in gridsurf)
1100
1101!-- temporary arrays for calculation of csf in raytracing
1102    INTEGER(iwp)                                   ::  maxboxesg        !< max number of boxes ray can cross in the domain
1103    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  boxes            !< coordinates of gridboxes being crossed by ray
1104    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  crlens           !< array of crossing lengths of ray for particular grid boxes
1105    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  lad_ip           !< array of numbers of process where lad is stored
1106#if defined( __parallel )
1107    INTEGER(kind=MPI_ADDRESS_KIND), &
1108                  DIMENSION(:), ALLOCATABLE        ::  lad_disp         !< array of displaycements of lad in local array of proc lad_ip
1109    INTEGER(iwp)                                   ::  win_lad          !< MPI RMA window for leaf area density
1110    INTEGER(iwp)                                   ::  win_gridsurf     !< MPI RMA window for reverse grid surface index
1111#endif
1112    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  lad_s_ray        !< array of received lad_s for appropriate gridboxes crossed by ray
1113    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  target_surfl
1114    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  rt2_track
1115    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rt2_track_lad
1116    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  rt2_track_dist
1117    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  rt2_dist
1118
1119!-- arrays for time averages
1120    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfradnet_av    !< average of net radiation to local surface including radiation from reflections
1121    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinsw_av      !< average of sw radiation falling to local surface including radiation from reflections
1122    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlw_av      !< average of lw radiation falling to local surface including radiation from reflections
1123    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdir_av   !< average of direct sw radiation falling to local surface
1124    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdif_av   !< average of diffuse sw radiation from sky and model boundary falling to local surface
1125    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwdif_av   !< average of diffuse lw radiation from sky and model boundary falling to local surface
1126    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswref_av   !< average of sw radiation falling to surface from reflections
1127    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwref_av   !< average of lw radiation falling to surface from reflections
1128    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsw_av     !< average of total sw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1129    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutlw_av     !< average of total lw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1130    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfins_av       !< average of array of residua of sw radiation absorbed in surface after last reflection
1131    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinl_av       !< average of array of residua of lw radiation absorbed in surface after last reflection
1132    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinlw_av       !< Average of pcbinlw
1133    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinsw_av       !< Average of pcbinsw
1134    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdir_av    !< Average of pcbinswdir
1135    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdif_av    !< Average of pcbinswdif
1136    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswref_av    !< Average of pcbinswref
1137
1138
1139!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1140!-- Energy balance variables
1141!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1142!-- parameters of the land, roof and wall surfaces
1143    REAL(wp), DIMENSION(:), ALLOCATABLE            :: albedo_surf        !< albedo of the surface
1144    REAL(wp), DIMENSION(:), ALLOCATABLE            :: emiss_surf         !< emissivity of the wall surface
1145
1146
1147    INTERFACE radiation_check_data_output
1148       MODULE PROCEDURE radiation_check_data_output
1149    END INTERFACE radiation_check_data_output
1150
1151    INTERFACE radiation_check_data_output_ts
1152       MODULE PROCEDURE radiation_check_data_output_ts
1153    END INTERFACE radiation_check_data_output_ts
1154
1155    INTERFACE radiation_check_data_output_pr
1156       MODULE PROCEDURE radiation_check_data_output_pr
1157    END INTERFACE radiation_check_data_output_pr
1158 
1159    INTERFACE radiation_check_parameters
1160       MODULE PROCEDURE radiation_check_parameters
1161    END INTERFACE radiation_check_parameters
1162 
1163    INTERFACE radiation_clearsky
1164       MODULE PROCEDURE radiation_clearsky
1165    END INTERFACE radiation_clearsky
1166 
1167    INTERFACE radiation_constant
1168       MODULE PROCEDURE radiation_constant
1169    END INTERFACE radiation_constant
1170 
1171    INTERFACE radiation_control
1172       MODULE PROCEDURE radiation_control
1173    END INTERFACE radiation_control
1174
1175    INTERFACE radiation_3d_data_averaging
1176       MODULE PROCEDURE radiation_3d_data_averaging
1177    END INTERFACE radiation_3d_data_averaging
1178
1179    INTERFACE radiation_data_output_2d
1180       MODULE PROCEDURE radiation_data_output_2d
1181    END INTERFACE radiation_data_output_2d
1182
1183    INTERFACE radiation_data_output_3d
1184       MODULE PROCEDURE radiation_data_output_3d
1185    END INTERFACE radiation_data_output_3d
1186
1187    INTERFACE radiation_data_output_mask
1188       MODULE PROCEDURE radiation_data_output_mask
1189    END INTERFACE radiation_data_output_mask
1190
1191    INTERFACE radiation_define_netcdf_grid
1192       MODULE PROCEDURE radiation_define_netcdf_grid
1193    END INTERFACE radiation_define_netcdf_grid
1194
1195    INTERFACE radiation_header
1196       MODULE PROCEDURE radiation_header
1197    END INTERFACE radiation_header 
1198 
1199    INTERFACE radiation_init
1200       MODULE PROCEDURE radiation_init
1201    END INTERFACE radiation_init
1202
1203    INTERFACE radiation_parin
1204       MODULE PROCEDURE radiation_parin
1205    END INTERFACE radiation_parin
1206   
1207    INTERFACE radiation_rrtmg
1208       MODULE PROCEDURE radiation_rrtmg
1209    END INTERFACE radiation_rrtmg
1210
1211    INTERFACE radiation_tendency
1212       MODULE PROCEDURE radiation_tendency
1213       MODULE PROCEDURE radiation_tendency_ij
1214    END INTERFACE radiation_tendency
1215
1216    INTERFACE radiation_rrd_local
1217       MODULE PROCEDURE radiation_rrd_local
1218    END INTERFACE radiation_rrd_local
1219
1220    INTERFACE radiation_wrd_local
1221       MODULE PROCEDURE radiation_wrd_local
1222    END INTERFACE radiation_wrd_local
1223
1224    INTERFACE radiation_interaction
1225       MODULE PROCEDURE radiation_interaction
1226    END INTERFACE radiation_interaction
1227
1228    INTERFACE radiation_interaction_init
1229       MODULE PROCEDURE radiation_interaction_init
1230    END INTERFACE radiation_interaction_init
1231 
1232    INTERFACE radiation_presimulate_solar_pos
1233       MODULE PROCEDURE radiation_presimulate_solar_pos
1234    END INTERFACE radiation_presimulate_solar_pos
1235
1236    INTERFACE radiation_radflux_gridbox
1237       MODULE PROCEDURE radiation_radflux_gridbox
1238    END INTERFACE radiation_radflux_gridbox
1239
1240    INTERFACE radiation_calc_svf
1241       MODULE PROCEDURE radiation_calc_svf
1242    END INTERFACE radiation_calc_svf
1243
1244    INTERFACE radiation_write_svf
1245       MODULE PROCEDURE radiation_write_svf
1246    END INTERFACE radiation_write_svf
1247
1248    INTERFACE radiation_read_svf
1249       MODULE PROCEDURE radiation_read_svf
1250    END INTERFACE radiation_read_svf
1251
1252
1253    SAVE
1254
1255    PRIVATE
1256
1257!
1258!-- Public functions / NEEDS SORTING
1259    PUBLIC radiation_check_data_output, radiation_check_data_output_pr,        &
1260           radiation_check_data_output_ts,                                     &
1261           radiation_check_parameters, radiation_control,                      &
1262           radiation_header, radiation_init, radiation_parin,                  &
1263           radiation_3d_data_averaging, radiation_tendency,                    &
1264           radiation_data_output_2d, radiation_data_output_3d,                 &
1265           radiation_define_netcdf_grid, radiation_wrd_local,                  &
1266           radiation_rrd_local, radiation_data_output_mask,                    &
1267           radiation_radflux_gridbox, radiation_calc_svf, radiation_write_svf, &
1268           radiation_interaction, radiation_interaction_init,                  &
1269           radiation_read_svf, radiation_presimulate_solar_pos
1270           
1271
1272   
1273!
1274!-- Public variables and constants / NEEDS SORTING
1275    PUBLIC albedo, albedo_type, decl_1, decl_2, decl_3, dots_rad, dt_radiation,&
1276           emissivity, force_radiation_call, lat, lon, mrt_geom_human,         &
1277           mrt_include_sw, mrt_nlevels, mrtbl, mrtinsw, mrtinlw, nmrtbl,       &
1278           rad_net_av, radiation, radiation_scheme, rad_lw_in,                 &
1279           rad_lw_in_av, rad_lw_out, rad_lw_out_av,                            &
1280           rad_lw_cs_hr, rad_lw_cs_hr_av, rad_lw_hr, rad_lw_hr_av, rad_sw_in,  &
1281           rad_sw_in_av, rad_sw_out, rad_sw_out_av, rad_sw_cs_hr,              &
1282           rad_sw_cs_hr_av, rad_sw_hr, rad_sw_hr_av, sigma_sb, solar_constant, &
1283           skip_time_do_radiation, time_radiation, unscheduled_radiation_calls,&
1284           zenith, calc_zenith, sun_direction, sun_dir_lat, sun_dir_lon,       &
1285           idir, jdir, kdir, id, iz, iy, ix,                                   &
1286           iup_u, inorth_u, isouth_u, ieast_u, iwest_u,                        &
1287           iup_l, inorth_l, isouth_l, ieast_l, iwest_l,                        &
1288           nsurf_type, nzub, nzut, nzu, pch, nsurf,                            &
1289           idsvf, ndsvf, idcsf, ndcsf, kdcsf, pct,                             &
1290           radiation_interactions, startwall, startland, endland, endwall,     &
1291           skyvf, skyvft, radiation_interactions_on, average_radiation,        &
1292           rad_sw_in_diff, rad_sw_in_dir
1293
1294
1295#if defined ( __rrtmg )
1296    PUBLIC rrtm_aldif, rrtm_aldir, rrtm_asdif, rrtm_asdir
1297#endif
1298
1299 CONTAINS
1300
1301
1302!------------------------------------------------------------------------------!
1303! Description:
1304! ------------
1305!> This subroutine controls the calls of the radiation schemes
1306!------------------------------------------------------------------------------!
1307    SUBROUTINE radiation_control
1308 
1309 
1310       IMPLICIT NONE
1311
1312
1313       SELECT CASE ( TRIM( radiation_scheme ) )
1314
1315          CASE ( 'constant' )
1316             CALL radiation_constant
1317         
1318          CASE ( 'clear-sky' ) 
1319             CALL radiation_clearsky
1320       
1321          CASE ( 'rrtmg' )
1322             CALL radiation_rrtmg
1323
1324          CASE DEFAULT
1325
1326       END SELECT
1327
1328
1329    END SUBROUTINE radiation_control
1330
1331!------------------------------------------------------------------------------!
1332! Description:
1333! ------------
1334!> Check data output for radiation model
1335!------------------------------------------------------------------------------!
1336    SUBROUTINE radiation_check_data_output( variable, unit, i, ilen, k )
1337 
1338 
1339       USE control_parameters,                                                 &
1340           ONLY: data_output, message_string
1341
1342       IMPLICIT NONE
1343
1344       CHARACTER (LEN=*) ::  unit          !<
1345       CHARACTER (LEN=*) ::  variable      !<
1346
1347       INTEGER(iwp) :: i, j, k, l
1348       INTEGER(iwp) :: ilen
1349       CHARACTER(LEN=varnamelength) :: var          !< TRIM(variable)
1350
1351       var = TRIM(variable)
1352
1353!--    first process diractional variables
1354       IF ( var(1:12) == 'rtm_rad_net_'  .OR.  var(1:13) == 'rtm_rad_insw_'  .OR.        &
1355            var(1:13) == 'rtm_rad_inlw_'  .OR.  var(1:16) == 'rtm_rad_inswdir_'  .OR.    &
1356            var(1:16) == 'rtm_rad_inswdif_'  .OR.  var(1:16) == 'rtm_rad_inswref_'  .OR. &
1357            var(1:16) == 'rtm_rad_inlwdif_'  .OR.  var(1:16) == 'rtm_rad_inlwref_'  .OR. &
1358            var(1:14) == 'rtm_rad_outsw_'  .OR.  var(1:14) == 'rtm_rad_outlw_'  .OR.     &
1359            var(1:14) == 'rtm_rad_ressw_'  .OR.  var(1:14) == 'rtm_rad_reslw_'  ) THEN
1360          IF ( .NOT.  radiation ) THEN
1361                message_string = 'output of "' // TRIM( var ) // '" require'&
1362                                 // 's radiation = .TRUE.'
1363                CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1364          ENDIF
1365          unit = 'W/m2'
1366       ELSE IF ( var(1:7) == 'rtm_svf'  .OR.  var(1:7) == 'rtm_dif'  .OR.                &
1367                 var(1:9) == 'rtm_skyvf' .OR. var(1:9) == 'rtm_skyvft' )  THEN
1368          IF ( .NOT.  radiation ) THEN
1369                message_string = 'output of "' // TRIM( var ) // '" require'&
1370                                 // 's radiation = .TRUE.'
1371                CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1372          ENDIF
1373          unit = '1'
1374       ELSE
1375!--       non-directional variables
1376          SELECT CASE ( TRIM( var ) )
1377             CASE ( 'rad_lw_cs_hr', 'rad_lw_hr', 'rad_lw_in', 'rad_lw_out', &
1378                    'rad_sw_cs_hr', 'rad_sw_hr', 'rad_sw_in', 'rad_sw_out'  )
1379                IF (  .NOT.  radiation  .OR.  radiation_scheme /= 'rrtmg' )  THEN
1380                   message_string = '"output of "' // TRIM( var ) // '" requi' // &
1381                                    'res radiation = .TRUE. and ' //              &
1382                                    'radiation_scheme = "rrtmg"'
1383                   CALL message( 'check_parameters', 'PA0406', 1, 2, 0, 6, 0 )
1384                ENDIF
1385                unit = 'K/h'
1386
1387             CASE ( 'rad_net*', 'rrtm_aldif*', 'rrtm_aldir*', 'rrtm_asdif*',      &
1388                    'rrtm_asdir*', 'rad_lw_in*', 'rad_lw_out*', 'rad_sw_in*',     &
1389                    'rad_sw_out*')
1390                IF ( i == 0 .AND. ilen == 0 .AND. k == 0)  THEN
1391                   ! Workaround for masked output (calls with i=ilen=k=0)
1392                   unit = 'illegal'
1393                   RETURN
1394                ENDIF
1395                IF ( k == 0  .OR.  data_output(i)(ilen-2:ilen) /= '_xy' )  THEN
1396                   message_string = 'illegal value for data_output: "' //         &
1397                                    TRIM( var ) // '" & only 2d-horizontal ' //   &
1398                                    'cross sections are allowed for this value'
1399                   CALL message( 'check_parameters', 'PA0111', 1, 2, 0, 6, 0 )
1400                ENDIF
1401                IF (  .NOT.  radiation  .OR.  radiation_scheme /= "rrtmg" )  THEN
1402                   IF ( TRIM( var ) == 'rrtm_aldif*'  .OR.                        &
1403                        TRIM( var ) == 'rrtm_aldir*'  .OR.                        &
1404                        TRIM( var ) == 'rrtm_asdif*'  .OR.                        &
1405                        TRIM( var ) == 'rrtm_asdir*'      )                       &
1406                   THEN
1407                      message_string = 'output of "' // TRIM( var ) // '" require'&
1408                                       // 's radiation = .TRUE. and radiation_sch'&
1409                                       // 'eme = "rrtmg"'
1410                      CALL message( 'check_parameters', 'PA0409', 1, 2, 0, 6, 0 )
1411                   ENDIF
1412                ENDIF
1413
1414                IF ( TRIM( var ) == 'rad_net*'      ) unit = 'W/m2'
1415                IF ( TRIM( var ) == 'rad_lw_in*'    ) unit = 'W/m2'
1416                IF ( TRIM( var ) == 'rad_lw_out*'   ) unit = 'W/m2'
1417                IF ( TRIM( var ) == 'rad_sw_in*'    ) unit = 'W/m2'
1418                IF ( TRIM( var ) == 'rad_sw_out*'   ) unit = 'W/m2'
1419                IF ( TRIM( var ) == 'rad_sw_in'     ) unit = 'W/m2'
1420                IF ( TRIM( var ) == 'rrtm_aldif*'   ) unit = ''
1421                IF ( TRIM( var ) == 'rrtm_aldir*'   ) unit = ''
1422                IF ( TRIM( var ) == 'rrtm_asdif*'   ) unit = ''
1423                IF ( TRIM( var ) == 'rrtm_asdir*'   ) unit = ''
1424
1425             CASE ( 'rtm_rad_pc_inlw', 'rtm_rad_pc_insw', 'rtm_rad_pc_inswdir', &
1426                    'rtm_rad_pc_inswdif', 'rtm_rad_pc_inswref')
1427                IF ( .NOT.  radiation ) THEN
1428                   message_string = 'output of "' // TRIM( var ) // '" require'&
1429                                    // 's radiation = .TRUE.'
1430                   CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1431                ENDIF
1432                unit = 'W'
1433
1434             CASE ( 'rtm_mrt', 'rtm_mrt_sw', 'rtm_mrt_lw'  )
1435                IF ( i == 0 .AND. ilen == 0 .AND. k == 0)  THEN
1436                   ! Workaround for masked output (calls with i=ilen=k=0)
1437                   unit = 'illegal'
1438                   RETURN
1439                ENDIF
1440
1441                IF ( .NOT.  radiation ) THEN
1442                   message_string = 'output of "' // TRIM( var ) // '" require'&
1443                                    // 's radiation = .TRUE.'
1444                   CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1445                ENDIF
1446                IF ( mrt_nlevels == 0 ) THEN
1447                   message_string = 'output of "' // TRIM( var ) // '" require'&
1448                                    // 's mrt_nlevels > 0'
1449                   CALL message( 'check_parameters', 'PA0510', 1, 2, 0, 6, 0 )
1450                ENDIF
1451                IF ( TRIM( var ) == 'rtm_mrt_sw'  .AND.  .NOT. mrt_include_sw ) THEN
1452                   message_string = 'output of "' // TRIM( var ) // '" require'&
1453                                    // 's rtm_mrt_sw = .TRUE.'
1454                   CALL message( 'check_parameters', 'PA0511', 1, 2, 0, 6, 0 )
1455                ENDIF
1456                IF ( TRIM( var ) == 'rtm_mrt' ) THEN
1457                   unit = 'K'
1458                ELSE
1459                   unit = 'W m-2'
1460                ENDIF
1461
1462             CASE DEFAULT
1463                unit = 'illegal'
1464
1465          END SELECT
1466       ENDIF
1467
1468    END SUBROUTINE radiation_check_data_output
1469
1470
1471!------------------------------------------------------------------------------!
1472! Description:
1473! ------------
1474!> Set module-specific timeseries units and labels
1475!------------------------------------------------------------------------------!
1476 SUBROUTINE radiation_check_data_output_ts( dots_max, dots_num, dots_label, dots_unit )
1477
1478
1479   INTEGER(iwp),      INTENT(IN)     ::  dots_max
1480   INTEGER(iwp),      INTENT(INOUT)  ::  dots_num
1481   CHARACTER (LEN=*), DIMENSION(dots_max), INTENT(INOUT)  :: dots_label
1482   CHARACTER (LEN=*), DIMENSION(dots_max), INTENT(INOUT)  :: dots_unit
1483
1484!
1485!-- Temporary solution to add LSM and radiation time series to the default
1486!-- output
1487    IF ( land_surface  .OR.  radiation )  THEN
1488       IF ( TRIM( radiation_scheme ) == 'rrtmg' )  THEN
1489          dots_num = dots_num + 15
1490       ELSE
1491          dots_num = dots_num + 11
1492       ENDIF
1493    ENDIF
1494
1495
1496 END SUBROUTINE radiation_check_data_output_ts
1497
1498!------------------------------------------------------------------------------!
1499! Description:
1500! ------------
1501!> Check data output of profiles for radiation model
1502!------------------------------------------------------------------------------! 
1503    SUBROUTINE radiation_check_data_output_pr( variable, var_count, unit,      &
1504               dopr_unit )
1505 
1506       USE arrays_3d,                                                          &
1507           ONLY: zu
1508
1509       USE control_parameters,                                                 &
1510           ONLY: data_output_pr, message_string
1511
1512       USE indices
1513
1514       USE profil_parameter
1515
1516       USE statistics
1517
1518       IMPLICIT NONE
1519   
1520       CHARACTER (LEN=*) ::  unit      !<
1521       CHARACTER (LEN=*) ::  variable  !<
1522       CHARACTER (LEN=*) ::  dopr_unit !< local value of dopr_unit
1523 
1524       INTEGER(iwp) ::  var_count     !<
1525
1526       SELECT CASE ( TRIM( variable ) )
1527       
1528         CASE ( 'rad_net' )
1529             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme == 'constant' )&
1530             THEN
1531                message_string = 'data_output_pr = ' //                        &
1532                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1533                                 'not available for radiation = .FALSE. or ' //&
1534                                 'radiation_scheme = "constant"'
1535                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1536             ELSE
1537                dopr_index(var_count) = 99
1538                dopr_unit  = 'W/m2'
1539                hom(:,2,99,:)  = SPREAD( zw, 2, statistic_regions+1 )
1540                unit = dopr_unit
1541             ENDIF
1542
1543          CASE ( 'rad_lw_in' )
1544             IF ( (  .NOT.  radiation)  .OR.  radiation_scheme == 'constant' ) &
1545             THEN
1546                message_string = 'data_output_pr = ' //                        &
1547                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1548                                 'not available for radiation = .FALSE. or ' //&
1549                                 'radiation_scheme = "constant"'
1550                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1551             ELSE
1552                dopr_index(var_count) = 100
1553                dopr_unit  = 'W/m2'
1554                hom(:,2,100,:)  = SPREAD( zw, 2, statistic_regions+1 )
1555                unit = dopr_unit 
1556             ENDIF
1557
1558          CASE ( 'rad_lw_out' )
1559             IF ( (  .NOT. radiation )  .OR.  radiation_scheme == 'constant' ) &
1560             THEN
1561                message_string = 'data_output_pr = ' //                        &
1562                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1563                                 'not available for radiation = .FALSE. or ' //&
1564                                 'radiation_scheme = "constant"'
1565                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1566             ELSE
1567                dopr_index(var_count) = 101
1568                dopr_unit  = 'W/m2'
1569                hom(:,2,101,:)  = SPREAD( zw, 2, statistic_regions+1 )
1570                unit = dopr_unit   
1571             ENDIF
1572
1573          CASE ( 'rad_sw_in' )
1574             IF ( (  .NOT. radiation )  .OR.  radiation_scheme == 'constant' ) &
1575             THEN
1576                message_string = 'data_output_pr = ' //                        &
1577                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1578                                 'not available for radiation = .FALSE. or ' //&
1579                                 'radiation_scheme = "constant"'
1580                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1581             ELSE
1582                dopr_index(var_count) = 102
1583                dopr_unit  = 'W/m2'
1584                hom(:,2,102,:)  = SPREAD( zw, 2, statistic_regions+1 )
1585                unit = dopr_unit
1586             ENDIF
1587
1588          CASE ( 'rad_sw_out')
1589             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme == 'constant' )&
1590             THEN
1591                message_string = 'data_output_pr = ' //                        &
1592                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1593                                 'not available for radiation = .FALSE. or ' //&
1594                                 'radiation_scheme = "constant"'
1595                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1596             ELSE
1597                dopr_index(var_count) = 103
1598                dopr_unit  = 'W/m2'
1599                hom(:,2,103,:)  = SPREAD( zw, 2, statistic_regions+1 )
1600                unit = dopr_unit
1601             ENDIF
1602
1603          CASE ( 'rad_lw_cs_hr' )
1604             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1605             THEN
1606                message_string = 'data_output_pr = ' //                        &
1607                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1608                                 'not available for radiation = .FALSE. or ' //&
1609                                 'radiation_scheme /= "rrtmg"'
1610                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1611             ELSE
1612                dopr_index(var_count) = 104
1613                dopr_unit  = 'K/h'
1614                hom(:,2,104,:)  = SPREAD( zu, 2, statistic_regions+1 )
1615                unit = dopr_unit
1616             ENDIF
1617
1618          CASE ( 'rad_lw_hr' )
1619             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1620             THEN
1621                message_string = 'data_output_pr = ' //                        &
1622                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1623                                 'not available for radiation = .FALSE. or ' //&
1624                                 'radiation_scheme /= "rrtmg"'
1625                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1626             ELSE
1627                dopr_index(var_count) = 105
1628                dopr_unit  = 'K/h'
1629                hom(:,2,105,:)  = SPREAD( zu, 2, statistic_regions+1 )
1630                unit = dopr_unit
1631             ENDIF
1632
1633          CASE ( 'rad_sw_cs_hr' )
1634             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1635             THEN
1636                message_string = 'data_output_pr = ' //                        &
1637                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1638                                 'not available for radiation = .FALSE. or ' //&
1639                                 'radiation_scheme /= "rrtmg"'
1640                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1641             ELSE
1642                dopr_index(var_count) = 106
1643                dopr_unit  = 'K/h'
1644                hom(:,2,106,:)  = SPREAD( zu, 2, statistic_regions+1 )
1645                unit = dopr_unit
1646             ENDIF
1647
1648          CASE ( 'rad_sw_hr' )
1649             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1650             THEN
1651                message_string = 'data_output_pr = ' //                        &
1652                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1653                                 'not available for radiation = .FALSE. or ' //&
1654                                 'radiation_scheme /= "rrtmg"'
1655                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1656             ELSE
1657                dopr_index(var_count) = 107
1658                dopr_unit  = 'K/h'
1659                hom(:,2,107,:)  = SPREAD( zu, 2, statistic_regions+1 )
1660                unit = dopr_unit
1661             ENDIF
1662
1663
1664          CASE DEFAULT
1665             unit = 'illegal'
1666
1667       END SELECT
1668
1669
1670    END SUBROUTINE radiation_check_data_output_pr
1671 
1672 
1673!------------------------------------------------------------------------------!
1674! Description:
1675! ------------
1676!> Check parameters routine for radiation model
1677!------------------------------------------------------------------------------!
1678    SUBROUTINE radiation_check_parameters
1679
1680       USE control_parameters,                                                 &
1681           ONLY: land_surface, message_string, urban_surface
1682
1683       USE netcdf_data_input_mod,                                              &
1684           ONLY:  input_pids_static                 
1685   
1686       IMPLICIT NONE
1687       
1688!
1689!--    In case no urban-surface or land-surface model is applied, usage of
1690!--    a radiation model make no sense.         
1691       IF ( .NOT. land_surface  .AND.  .NOT. urban_surface )  THEN
1692          message_string = 'Usage of radiation module is only allowed if ' //  &
1693                           'land-surface and/or urban-surface model is applied.'
1694          CALL message( 'check_parameters', 'PA0486', 1, 2, 0, 6, 0 )
1695       ENDIF
1696
1697       IF ( radiation_scheme /= 'constant'   .AND.                             &
1698            radiation_scheme /= 'clear-sky'  .AND.                             &
1699            radiation_scheme /= 'rrtmg' )  THEN
1700          message_string = 'unknown radiation_scheme = '//                     &
1701                           TRIM( radiation_scheme )
1702          CALL message( 'check_parameters', 'PA0405', 1, 2, 0, 6, 0 )
1703       ELSEIF ( radiation_scheme == 'rrtmg' )  THEN
1704#if ! defined ( __rrtmg )
1705          message_string = 'radiation_scheme = "rrtmg" requires ' //           & 
1706                           'compilation of PALM with pre-processor ' //        &
1707                           'directive -D__rrtmg'
1708          CALL message( 'check_parameters', 'PA0407', 1, 2, 0, 6, 0 )
1709#endif
1710#if defined ( __rrtmg ) && ! defined( __netcdf )
1711          message_string = 'radiation_scheme = "rrtmg" requires ' //           & 
1712                           'the use of NetCDF (preprocessor directive ' //     &
1713                           '-D__netcdf'
1714          CALL message( 'check_parameters', 'PA0412', 1, 2, 0, 6, 0 )
1715#endif
1716
1717       ENDIF
1718!
1719!--    Checks performed only if data is given via namelist only.
1720       IF ( .NOT. input_pids_static )  THEN
1721          IF ( albedo_type == 0  .AND.  albedo == 9999999.9_wp  .AND.          &
1722               radiation_scheme == 'clear-sky')  THEN
1723             message_string = 'radiation_scheme = "clear-sky" in combination'//& 
1724                              'with albedo_type = 0 requires setting of'//     &
1725                              'albedo /= 9999999.9'
1726             CALL message( 'check_parameters', 'PA0410', 1, 2, 0, 6, 0 )
1727          ENDIF
1728
1729          IF ( albedo_type == 0  .AND.  radiation_scheme == 'rrtmg'  .AND.     &
1730             ( albedo_lw_dif == 9999999.9_wp .OR. albedo_lw_dir == 9999999.9_wp&
1731          .OR. albedo_sw_dif == 9999999.9_wp .OR. albedo_sw_dir == 9999999.9_wp& 
1732             ) ) THEN
1733             message_string = 'radiation_scheme = "rrtmg" in combination' //   & 
1734                              'with albedo_type = 0 requires setting of ' //   &
1735                              'albedo_lw_dif /= 9999999.9' //                  &
1736                              'albedo_lw_dir /= 9999999.9' //                  &
1737                              'albedo_sw_dif /= 9999999.9 and' //              &
1738                              'albedo_sw_dir /= 9999999.9'
1739             CALL message( 'check_parameters', 'PA0411', 1, 2, 0, 6, 0 )
1740          ENDIF
1741       ENDIF
1742!
1743!--    Parallel rad_angular_discretization without raytrace_mpi_rma is not implemented
1744#if defined( __parallel )     
1745       IF ( rad_angular_discretization  .AND.  .NOT. raytrace_mpi_rma )  THEN
1746          message_string = 'rad_angular_discretization can only be used ' //  &
1747                           'together with raytrace_mpi_rma or when ' //  &
1748                           'no parallelization is applied.'
1749          CALL message( 'check_parameters', 'PA0486', 1, 2, 0, 6, 0 )
1750       ENDIF
1751#endif
1752
1753       IF ( cloud_droplets  .AND.   radiation_scheme == 'rrtmg'  .AND.         &
1754            average_radiation ) THEN
1755          message_string = 'average_radiation = .T. with radiation_scheme'//   & 
1756                           '= "rrtmg" in combination cloud_droplets = .T.'//   &
1757                           'is not implementd'
1758          CALL message( 'check_parameters', 'PA0560', 1, 2, 0, 6, 0 )
1759       ENDIF
1760
1761!
1762!--    Incialize svf normalization reporting histogram
1763       svfnorm_report_num = 1
1764       DO WHILE ( svfnorm_report_thresh(svfnorm_report_num) < 1e20_wp          &
1765                   .AND. svfnorm_report_num <= 30 )
1766          svfnorm_report_num = svfnorm_report_num + 1
1767       ENDDO
1768       svfnorm_report_num = svfnorm_report_num - 1
1769
1770
1771 
1772    END SUBROUTINE radiation_check_parameters 
1773 
1774 
1775!------------------------------------------------------------------------------!
1776! Description:
1777! ------------
1778!> Initialization of the radiation model
1779!------------------------------------------------------------------------------!
1780    SUBROUTINE radiation_init
1781   
1782       IMPLICIT NONE
1783
1784       INTEGER(iwp) ::  i         !< running index x-direction
1785       INTEGER(iwp) ::  ioff      !< offset in x between surface element reference grid point in atmosphere and actual surface
1786       INTEGER(iwp) ::  j         !< running index y-direction
1787       INTEGER(iwp) ::  joff      !< offset in y between surface element reference grid point in atmosphere and actual surface
1788       INTEGER(iwp) ::  l         !< running index for orientation of vertical surfaces
1789       INTEGER(iwp) ::  m         !< running index for surface elements
1790#if defined( __rrtmg )
1791       INTEGER(iwp) ::  ind_type  !< running index for subgrid-surface tiles
1792#endif
1793
1794!
1795!--    Activate radiation_interactions according to the existence of vertical surfaces and/or trees.
1796!--    The namelist parameter radiation_interactions_on can override this behavior.
1797!--    (This check cannot be performed in check_parameters, because vertical_surfaces_exist is first set in
1798!--    init_surface_arrays.)
1799       IF ( radiation_interactions_on )  THEN
1800          IF ( vertical_surfaces_exist  .OR.  plant_canopy )  THEN
1801             radiation_interactions    = .TRUE.
1802             average_radiation         = .TRUE.
1803          ELSE
1804             radiation_interactions_on = .FALSE.   !< reset namelist parameter: no interactions
1805                                                   !< calculations necessary in case of flat surface
1806          ENDIF
1807       ELSEIF ( vertical_surfaces_exist  .OR.  plant_canopy )  THEN
1808          message_string = 'radiation_interactions_on is set to .FALSE. although '     // &
1809                           'vertical surfaces and/or trees exist. The model will run ' // &
1810                           'without RTM (no shadows, no radiation reflections)'
1811          CALL message( 'init_3d_model', 'PA0348', 0, 1, 0, 6, 0 )
1812       ENDIF
1813!
1814!--    If required, initialize radiation interactions between surfaces
1815!--    via sky-view factors. This must be done before radiation is initialized.
1816       IF ( radiation_interactions )  CALL radiation_interaction_init
1817
1818!
1819!--    Initialize radiation model
1820       CALL location_message( 'initializing radiation model', .FALSE. )
1821
1822!
1823!--    Allocate array for storing the surface net radiation
1824       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_net )  .AND.                      &
1825                  surf_lsm_h%ns > 0  )   THEN
1826          ALLOCATE( surf_lsm_h%rad_net(1:surf_lsm_h%ns) )
1827          surf_lsm_h%rad_net = 0.0_wp 
1828       ENDIF
1829       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_net )  .AND.                      &
1830                  surf_usm_h%ns > 0  )  THEN
1831          ALLOCATE( surf_usm_h%rad_net(1:surf_usm_h%ns) )
1832          surf_usm_h%rad_net = 0.0_wp 
1833       ENDIF
1834       DO  l = 0, 3
1835          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_net )  .AND.                &
1836                     surf_lsm_v(l)%ns > 0  )  THEN
1837             ALLOCATE( surf_lsm_v(l)%rad_net(1:surf_lsm_v(l)%ns) )
1838             surf_lsm_v(l)%rad_net = 0.0_wp 
1839          ENDIF
1840          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_net )  .AND.                &
1841                     surf_usm_v(l)%ns > 0  )  THEN
1842             ALLOCATE( surf_usm_v(l)%rad_net(1:surf_usm_v(l)%ns) )
1843             surf_usm_v(l)%rad_net = 0.0_wp 
1844          ENDIF
1845       ENDDO
1846
1847
1848!
1849!--    Allocate array for storing the surface longwave (out) radiation change
1850       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_lw_out_change_0 )  .AND.          &
1851                  surf_lsm_h%ns > 0  )   THEN
1852          ALLOCATE( surf_lsm_h%rad_lw_out_change_0(1:surf_lsm_h%ns) )
1853          surf_lsm_h%rad_lw_out_change_0 = 0.0_wp 
1854       ENDIF
1855       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_lw_out_change_0 )  .AND.          &
1856                  surf_usm_h%ns > 0  )  THEN
1857          ALLOCATE( surf_usm_h%rad_lw_out_change_0(1:surf_usm_h%ns) )
1858          surf_usm_h%rad_lw_out_change_0 = 0.0_wp 
1859       ENDIF
1860       DO  l = 0, 3
1861          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_lw_out_change_0 )  .AND.    &
1862                     surf_lsm_v(l)%ns > 0  )  THEN
1863             ALLOCATE( surf_lsm_v(l)%rad_lw_out_change_0(1:surf_lsm_v(l)%ns) )
1864             surf_lsm_v(l)%rad_lw_out_change_0 = 0.0_wp 
1865          ENDIF
1866          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_lw_out_change_0 )  .AND.    &
1867                     surf_usm_v(l)%ns > 0  )  THEN
1868             ALLOCATE( surf_usm_v(l)%rad_lw_out_change_0(1:surf_usm_v(l)%ns) )
1869             surf_usm_v(l)%rad_lw_out_change_0 = 0.0_wp 
1870          ENDIF
1871       ENDDO
1872
1873!
1874!--    Allocate surface arrays for incoming/outgoing short/longwave radiation
1875       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_sw_in )  .AND.                    &
1876                  surf_lsm_h%ns > 0  )   THEN
1877          ALLOCATE( surf_lsm_h%rad_sw_in(1:surf_lsm_h%ns)  )
1878          ALLOCATE( surf_lsm_h%rad_sw_out(1:surf_lsm_h%ns) )
1879          ALLOCATE( surf_lsm_h%rad_sw_dir(1:surf_lsm_h%ns) )
1880          ALLOCATE( surf_lsm_h%rad_sw_dif(1:surf_lsm_h%ns) )
1881          ALLOCATE( surf_lsm_h%rad_sw_ref(1:surf_lsm_h%ns) )
1882          ALLOCATE( surf_lsm_h%rad_sw_res(1:surf_lsm_h%ns) )
1883          ALLOCATE( surf_lsm_h%rad_lw_in(1:surf_lsm_h%ns)  )
1884          ALLOCATE( surf_lsm_h%rad_lw_out(1:surf_lsm_h%ns) )
1885          ALLOCATE( surf_lsm_h%rad_lw_dif(1:surf_lsm_h%ns) )
1886          ALLOCATE( surf_lsm_h%rad_lw_ref(1:surf_lsm_h%ns) )
1887          ALLOCATE( surf_lsm_h%rad_lw_res(1:surf_lsm_h%ns) )
1888          surf_lsm_h%rad_sw_in  = 0.0_wp 
1889          surf_lsm_h%rad_sw_out = 0.0_wp 
1890          surf_lsm_h%rad_sw_dir = 0.0_wp 
1891          surf_lsm_h%rad_sw_dif = 0.0_wp 
1892          surf_lsm_h%rad_sw_ref = 0.0_wp 
1893          surf_lsm_h%rad_sw_res = 0.0_wp 
1894          surf_lsm_h%rad_lw_in  = 0.0_wp 
1895          surf_lsm_h%rad_lw_out = 0.0_wp 
1896          surf_lsm_h%rad_lw_dif = 0.0_wp 
1897          surf_lsm_h%rad_lw_ref = 0.0_wp 
1898          surf_lsm_h%rad_lw_res = 0.0_wp 
1899       ENDIF
1900       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_sw_in )  .AND.                    &
1901                  surf_usm_h%ns > 0  )  THEN
1902          ALLOCATE( surf_usm_h%rad_sw_in(1:surf_usm_h%ns)  )
1903          ALLOCATE( surf_usm_h%rad_sw_out(1:surf_usm_h%ns) )
1904          ALLOCATE( surf_usm_h%rad_sw_dir(1:surf_usm_h%ns) )
1905          ALLOCATE( surf_usm_h%rad_sw_dif(1:surf_usm_h%ns) )
1906          ALLOCATE( surf_usm_h%rad_sw_ref(1:surf_usm_h%ns) )
1907          ALLOCATE( surf_usm_h%rad_sw_res(1:surf_usm_h%ns) )
1908          ALLOCATE( surf_usm_h%rad_lw_in(1:surf_usm_h%ns)  )
1909          ALLOCATE( surf_usm_h%rad_lw_out(1:surf_usm_h%ns) )
1910          ALLOCATE( surf_usm_h%rad_lw_dif(1:surf_usm_h%ns) )
1911          ALLOCATE( surf_usm_h%rad_lw_ref(1:surf_usm_h%ns) )
1912          ALLOCATE( surf_usm_h%rad_lw_res(1:surf_usm_h%ns) )
1913          surf_usm_h%rad_sw_in  = 0.0_wp 
1914          surf_usm_h%rad_sw_out = 0.0_wp 
1915          surf_usm_h%rad_sw_dir = 0.0_wp 
1916          surf_usm_h%rad_sw_dif = 0.0_wp 
1917          surf_usm_h%rad_sw_ref = 0.0_wp 
1918          surf_usm_h%rad_sw_res = 0.0_wp 
1919          surf_usm_h%rad_lw_in  = 0.0_wp 
1920          surf_usm_h%rad_lw_out = 0.0_wp 
1921          surf_usm_h%rad_lw_dif = 0.0_wp 
1922          surf_usm_h%rad_lw_ref = 0.0_wp 
1923          surf_usm_h%rad_lw_res = 0.0_wp 
1924       ENDIF
1925       DO  l = 0, 3
1926          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_sw_in )  .AND.              &
1927                     surf_lsm_v(l)%ns > 0  )  THEN
1928             ALLOCATE( surf_lsm_v(l)%rad_sw_in(1:surf_lsm_v(l)%ns)  )
1929             ALLOCATE( surf_lsm_v(l)%rad_sw_out(1:surf_lsm_v(l)%ns) )
1930             ALLOCATE( surf_lsm_v(l)%rad_sw_dir(1:surf_lsm_v(l)%ns) )
1931             ALLOCATE( surf_lsm_v(l)%rad_sw_dif(1:surf_lsm_v(l)%ns) )
1932             ALLOCATE( surf_lsm_v(l)%rad_sw_ref(1:surf_lsm_v(l)%ns) )
1933             ALLOCATE( surf_lsm_v(l)%rad_sw_res(1:surf_lsm_v(l)%ns) )
1934
1935             ALLOCATE( surf_lsm_v(l)%rad_lw_in(1:surf_lsm_v(l)%ns)  )
1936             ALLOCATE( surf_lsm_v(l)%rad_lw_out(1:surf_lsm_v(l)%ns) )
1937             ALLOCATE( surf_lsm_v(l)%rad_lw_dif(1:surf_lsm_v(l)%ns) )
1938             ALLOCATE( surf_lsm_v(l)%rad_lw_ref(1:surf_lsm_v(l)%ns) )
1939             ALLOCATE( surf_lsm_v(l)%rad_lw_res(1:surf_lsm_v(l)%ns) )
1940
1941             surf_lsm_v(l)%rad_sw_in  = 0.0_wp 
1942             surf_lsm_v(l)%rad_sw_out = 0.0_wp
1943             surf_lsm_v(l)%rad_sw_dir = 0.0_wp
1944             surf_lsm_v(l)%rad_sw_dif = 0.0_wp
1945             surf_lsm_v(l)%rad_sw_ref = 0.0_wp
1946             surf_lsm_v(l)%rad_sw_res = 0.0_wp
1947
1948             surf_lsm_v(l)%rad_lw_in  = 0.0_wp 
1949             surf_lsm_v(l)%rad_lw_out = 0.0_wp 
1950             surf_lsm_v(l)%rad_lw_dif = 0.0_wp 
1951             surf_lsm_v(l)%rad_lw_ref = 0.0_wp 
1952             surf_lsm_v(l)%rad_lw_res = 0.0_wp 
1953          ENDIF
1954          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_sw_in )  .AND.              &
1955                     surf_usm_v(l)%ns > 0  )  THEN
1956             ALLOCATE( surf_usm_v(l)%rad_sw_in(1:surf_usm_v(l)%ns)  )
1957             ALLOCATE( surf_usm_v(l)%rad_sw_out(1:surf_usm_v(l)%ns) )
1958             ALLOCATE( surf_usm_v(l)%rad_sw_dir(1:surf_usm_v(l)%ns) )
1959             ALLOCATE( surf_usm_v(l)%rad_sw_dif(1:surf_usm_v(l)%ns) )
1960             ALLOCATE( surf_usm_v(l)%rad_sw_ref(1:surf_usm_v(l)%ns) )
1961             ALLOCATE( surf_usm_v(l)%rad_sw_res(1:surf_usm_v(l)%ns) )
1962             ALLOCATE( surf_usm_v(l)%rad_lw_in(1:surf_usm_v(l)%ns)  )
1963             ALLOCATE( surf_usm_v(l)%rad_lw_out(1:surf_usm_v(l)%ns) )
1964             ALLOCATE( surf_usm_v(l)%rad_lw_dif(1:surf_usm_v(l)%ns) )
1965             ALLOCATE( surf_usm_v(l)%rad_lw_ref(1:surf_usm_v(l)%ns) )
1966             ALLOCATE( surf_usm_v(l)%rad_lw_res(1:surf_usm_v(l)%ns) )
1967             surf_usm_v(l)%rad_sw_in  = 0.0_wp 
1968             surf_usm_v(l)%rad_sw_out = 0.0_wp
1969             surf_usm_v(l)%rad_sw_dir = 0.0_wp
1970             surf_usm_v(l)%rad_sw_dif = 0.0_wp
1971             surf_usm_v(l)%rad_sw_ref = 0.0_wp
1972             surf_usm_v(l)%rad_sw_res = 0.0_wp
1973             surf_usm_v(l)%rad_lw_in  = 0.0_wp 
1974             surf_usm_v(l)%rad_lw_out = 0.0_wp 
1975             surf_usm_v(l)%rad_lw_dif = 0.0_wp 
1976             surf_usm_v(l)%rad_lw_ref = 0.0_wp 
1977             surf_usm_v(l)%rad_lw_res = 0.0_wp 
1978          ENDIF
1979       ENDDO
1980!
1981!--    Fix net radiation in case of radiation_scheme = 'constant'
1982       IF ( radiation_scheme == 'constant' )  THEN
1983          IF ( ALLOCATED( surf_lsm_h%rad_net ) )                               &
1984             surf_lsm_h%rad_net    = net_radiation
1985          IF ( ALLOCATED( surf_usm_h%rad_net ) )                               &
1986             surf_usm_h%rad_net    = net_radiation
1987!
1988!--       Todo: weight with inclination angle
1989          DO  l = 0, 3
1990             IF ( ALLOCATED( surf_lsm_v(l)%rad_net ) )                         &
1991                surf_lsm_v(l)%rad_net = net_radiation
1992             IF ( ALLOCATED( surf_usm_v(l)%rad_net ) )                         &
1993                surf_usm_v(l)%rad_net = net_radiation
1994          ENDDO
1995!          radiation = .FALSE.
1996!
1997!--    Calculate orbital constants
1998       ELSE
1999          decl_1 = SIN(23.45_wp * pi / 180.0_wp)
2000          decl_2 = 2.0_wp * pi / 365.0_wp
2001          decl_3 = decl_2 * 81.0_wp
2002          lat    = latitude * pi / 180.0_wp
2003          lon    = longitude * pi / 180.0_wp
2004       ENDIF
2005
2006       IF ( radiation_scheme == 'clear-sky'  .OR.                              &
2007            radiation_scheme == 'constant')  THEN
2008
2009
2010!
2011!--       Allocate arrays for incoming/outgoing short/longwave radiation
2012          IF ( .NOT. ALLOCATED ( rad_sw_in ) )  THEN
2013             ALLOCATE ( rad_sw_in(0:0,nysg:nyng,nxlg:nxrg) )
2014          ENDIF
2015          IF ( .NOT. ALLOCATED ( rad_sw_out ) )  THEN
2016             ALLOCATE ( rad_sw_out(0:0,nysg:nyng,nxlg:nxrg) )
2017          ENDIF
2018
2019          IF ( .NOT. ALLOCATED ( rad_lw_in ) )  THEN
2020             ALLOCATE ( rad_lw_in(0:0,nysg:nyng,nxlg:nxrg) )
2021          ENDIF
2022          IF ( .NOT. ALLOCATED ( rad_lw_out ) )  THEN
2023             ALLOCATE ( rad_lw_out(0:0,nysg:nyng,nxlg:nxrg) )
2024          ENDIF
2025
2026!
2027!--       Allocate average arrays for incoming/outgoing short/longwave radiation
2028          IF ( .NOT. ALLOCATED ( rad_sw_in_av ) )  THEN
2029             ALLOCATE ( rad_sw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
2030          ENDIF
2031          IF ( .NOT. ALLOCATED ( rad_sw_out_av ) )  THEN
2032             ALLOCATE ( rad_sw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
2033          ENDIF
2034
2035          IF ( .NOT. ALLOCATED ( rad_lw_in_av ) )  THEN
2036             ALLOCATE ( rad_lw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
2037          ENDIF
2038          IF ( .NOT. ALLOCATED ( rad_lw_out_av ) )  THEN
2039             ALLOCATE ( rad_lw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
2040          ENDIF
2041!
2042!--       Allocate arrays for broadband albedo, and level 1 initialization
2043!--       via namelist paramter, unless not already allocated.
2044          IF ( .NOT. ALLOCATED(surf_lsm_h%albedo) )  THEN
2045             ALLOCATE( surf_lsm_h%albedo(0:2,1:surf_lsm_h%ns)     )
2046             surf_lsm_h%albedo    = albedo
2047          ENDIF
2048          IF ( .NOT. ALLOCATED(surf_usm_h%albedo) )  THEN
2049             ALLOCATE( surf_usm_h%albedo(0:2,1:surf_usm_h%ns)     )
2050             surf_usm_h%albedo    = albedo
2051          ENDIF
2052
2053          DO  l = 0, 3
2054             IF ( .NOT. ALLOCATED( surf_lsm_v(l)%albedo ) )  THEN
2055                ALLOCATE( surf_lsm_v(l)%albedo(0:2,1:surf_lsm_v(l)%ns) )
2056                surf_lsm_v(l)%albedo = albedo
2057             ENDIF
2058             IF ( .NOT. ALLOCATED( surf_usm_v(l)%albedo ) )  THEN
2059                ALLOCATE( surf_usm_v(l)%albedo(0:2,1:surf_usm_v(l)%ns) )
2060                surf_usm_v(l)%albedo = albedo
2061             ENDIF
2062          ENDDO
2063!
2064!--       Level 2 initialization of broadband albedo via given albedo_type.
2065!--       Only if albedo_type is non-zero. In case of urban surface and
2066!--       input data is read from ASCII file, albedo_type will be zero, so that
2067!--       albedo won't be overwritten.
2068          DO  m = 1, surf_lsm_h%ns
2069             IF ( surf_lsm_h%albedo_type(ind_veg_wall,m) /= 0 )                &
2070                surf_lsm_h%albedo(ind_veg_wall,m) =                            &
2071                           albedo_pars(2,surf_lsm_h%albedo_type(ind_veg_wall,m))
2072             IF ( surf_lsm_h%albedo_type(ind_pav_green,m) /= 0 )               &
2073                surf_lsm_h%albedo(ind_pav_green,m) =                           &
2074                           albedo_pars(2,surf_lsm_h%albedo_type(ind_pav_green,m))
2075             IF ( surf_lsm_h%albedo_type(ind_wat_win,m) /= 0 )                 &
2076                surf_lsm_h%albedo(ind_wat_win,m) =                             &
2077                           albedo_pars(2,surf_lsm_h%albedo_type(ind_wat_win,m))
2078          ENDDO
2079          DO  m = 1, surf_usm_h%ns
2080             IF ( surf_usm_h%albedo_type(ind_veg_wall,m) /= 0 )                &
2081                surf_usm_h%albedo(ind_veg_wall,m) =                            &
2082                           albedo_pars(2,surf_usm_h%albedo_type(ind_veg_wall,m))
2083             IF ( surf_usm_h%albedo_type(ind_pav_green,m) /= 0 )               &
2084                surf_usm_h%albedo(ind_pav_green,m) =                           &
2085                           albedo_pars(2,surf_usm_h%albedo_type(ind_pav_green,m))
2086             IF ( surf_usm_h%albedo_type(ind_wat_win,m) /= 0 )                 &
2087                surf_usm_h%albedo(ind_wat_win,m) =                             &
2088                           albedo_pars(2,surf_usm_h%albedo_type(ind_wat_win,m))
2089          ENDDO
2090
2091          DO  l = 0, 3
2092             DO  m = 1, surf_lsm_v(l)%ns
2093                IF ( surf_lsm_v(l)%albedo_type(ind_veg_wall,m) /= 0 )          &
2094                   surf_lsm_v(l)%albedo(ind_veg_wall,m) =                      &
2095                        albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_veg_wall,m))
2096                IF ( surf_lsm_v(l)%albedo_type(ind_pav_green,m) /= 0 )         &
2097                   surf_lsm_v(l)%albedo(ind_pav_green,m) =                     &
2098                        albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_pav_green,m))
2099                IF ( surf_lsm_v(l)%albedo_type(ind_wat_win,m) /= 0 )           &
2100                   surf_lsm_v(l)%albedo(ind_wat_win,m) =                       &
2101                        albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_wat_win,m))
2102             ENDDO
2103             DO  m = 1, surf_usm_v(l)%ns
2104                IF ( surf_usm_v(l)%albedo_type(ind_veg_wall,m) /= 0 )          &
2105                   surf_usm_v(l)%albedo(ind_veg_wall,m) =                      &
2106                        albedo_pars(2,surf_usm_v(l)%albedo_type(ind_veg_wall,m))
2107                IF ( surf_usm_v(l)%albedo_type(ind_pav_green,m) /= 0 )         &
2108                   surf_usm_v(l)%albedo(ind_pav_green,m) =                     &
2109                        albedo_pars(2,surf_usm_v(l)%albedo_type(ind_pav_green,m))
2110                IF ( surf_usm_v(l)%albedo_type(ind_wat_win,m) /= 0 )           &
2111                   surf_usm_v(l)%albedo(ind_wat_win,m) =                       &
2112                        albedo_pars(2,surf_usm_v(l)%albedo_type(ind_wat_win,m))
2113             ENDDO
2114          ENDDO
2115
2116!
2117!--       Level 3 initialization at grid points where albedo type is zero.
2118!--       This case, albedo is taken from file. In case of constant radiation
2119!--       or clear sky, only broadband albedo is given.
2120          IF ( albedo_pars_f%from_file )  THEN
2121!
2122!--          Horizontal surfaces
2123             DO  m = 1, surf_lsm_h%ns
2124                i = surf_lsm_h%i(m)
2125                j = surf_lsm_h%j(m)
2126                IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2127                   IF ( surf_lsm_h%albedo_type(ind_veg_wall,m) == 0 )          &
2128                      surf_lsm_h%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2129                   IF ( surf_lsm_h%albedo_type(ind_pav_green,m) == 0 )         &
2130                      surf_lsm_h%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2131                   IF ( surf_lsm_h%albedo_type(ind_wat_win,m) == 0 )           &
2132                      surf_lsm_h%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2133                ENDIF
2134             ENDDO
2135             DO  m = 1, surf_usm_h%ns
2136                i = surf_usm_h%i(m)
2137                j = surf_usm_h%j(m)
2138                IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2139                   IF ( surf_usm_h%albedo_type(ind_veg_wall,m) == 0 )          &
2140                      surf_usm_h%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2141                   IF ( surf_usm_h%albedo_type(ind_pav_green,m) == 0 )         &
2142                      surf_usm_h%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2143                   IF ( surf_usm_h%albedo_type(ind_wat_win,m) == 0 )           &
2144                      surf_usm_h%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2145                ENDIF
2146             ENDDO 
2147!
2148!--          Vertical surfaces           
2149             DO  l = 0, 3
2150
2151                ioff = surf_lsm_v(l)%ioff
2152                joff = surf_lsm_v(l)%joff
2153                DO  m = 1, surf_lsm_v(l)%ns
2154                   i = surf_lsm_v(l)%i(m) + ioff
2155                   j = surf_lsm_v(l)%j(m) + joff
2156                   IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2157                      IF ( surf_lsm_v(l)%albedo_type(ind_veg_wall,m) == 0 )    &
2158                         surf_lsm_v(l)%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2159                      IF ( surf_lsm_v(l)%albedo_type(ind_pav_green,m) == 0 )   &
2160                         surf_lsm_v(l)%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2161                      IF ( surf_lsm_v(l)%albedo_type(ind_wat_win,m) == 0 )     &
2162                         surf_lsm_v(l)%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2163                   ENDIF
2164                ENDDO
2165
2166                ioff = surf_usm_v(l)%ioff
2167                joff = surf_usm_v(l)%joff
2168                DO  m = 1, surf_usm_h%ns
2169                   i = surf_usm_h%i(m) + joff
2170                   j = surf_usm_h%j(m) + joff
2171                   IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2172                      IF ( surf_usm_v(l)%albedo_type(ind_veg_wall,m) == 0 )    &
2173                         surf_usm_v(l)%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2174                      IF ( surf_usm_v(l)%albedo_type(ind_pav_green,m) == 0 )   &
2175                         surf_usm_v(l)%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2176                      IF ( surf_usm_v(l)%albedo_type(ind_wat_win,m) == 0 )     &
2177                         surf_lsm_v(l)%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2178                   ENDIF
2179                ENDDO
2180             ENDDO
2181
2182          ENDIF 
2183!
2184!--    Initialization actions for RRTMG
2185       ELSEIF ( radiation_scheme == 'rrtmg' )  THEN
2186#if defined ( __rrtmg )
2187!
2188!--       Allocate albedos for short/longwave radiation, horizontal surfaces
2189!--       for wall/green/window (USM) or vegetation/pavement/water surfaces
2190!--       (LSM).
2191          ALLOCATE ( surf_lsm_h%aldif(0:2,1:surf_lsm_h%ns)       )
2192          ALLOCATE ( surf_lsm_h%aldir(0:2,1:surf_lsm_h%ns)       )
2193          ALLOCATE ( surf_lsm_h%asdif(0:2,1:surf_lsm_h%ns)       )
2194          ALLOCATE ( surf_lsm_h%asdir(0:2,1:surf_lsm_h%ns)       )
2195          ALLOCATE ( surf_lsm_h%rrtm_aldif(0:2,1:surf_lsm_h%ns)  )
2196          ALLOCATE ( surf_lsm_h%rrtm_aldir(0:2,1:surf_lsm_h%ns)  )
2197          ALLOCATE ( surf_lsm_h%rrtm_asdif(0:2,1:surf_lsm_h%ns)  )
2198          ALLOCATE ( surf_lsm_h%rrtm_asdir(0:2,1:surf_lsm_h%ns)  )
2199
2200          ALLOCATE ( surf_usm_h%aldif(0:2,1:surf_usm_h%ns)       )
2201          ALLOCATE ( surf_usm_h%aldir(0:2,1:surf_usm_h%ns)       )
2202          ALLOCATE ( surf_usm_h%asdif(0:2,1:surf_usm_h%ns)       )
2203          ALLOCATE ( surf_usm_h%asdir(0:2,1:surf_usm_h%ns)       )
2204          ALLOCATE ( surf_usm_h%rrtm_aldif(0:2,1:surf_usm_h%ns)  )
2205          ALLOCATE ( surf_usm_h%rrtm_aldir(0:2,1:surf_usm_h%ns)  )
2206          ALLOCATE ( surf_usm_h%rrtm_asdif(0:2,1:surf_usm_h%ns)  )
2207          ALLOCATE ( surf_usm_h%rrtm_asdir(0:2,1:surf_usm_h%ns)  )
2208
2209!
2210!--       Allocate broadband albedo (temporary for the current radiation
2211!--       implementations)
2212          IF ( .NOT. ALLOCATED(surf_lsm_h%albedo) )                            &
2213             ALLOCATE( surf_lsm_h%albedo(0:2,1:surf_lsm_h%ns)     )
2214          IF ( .NOT. ALLOCATED(surf_usm_h%albedo) )                            &
2215             ALLOCATE( surf_usm_h%albedo(0:2,1:surf_usm_h%ns)     )
2216
2217!
2218!--       Allocate albedos for short/longwave radiation, vertical surfaces
2219          DO  l = 0, 3
2220
2221             ALLOCATE ( surf_lsm_v(l)%aldif(0:2,1:surf_lsm_v(l)%ns)      )
2222             ALLOCATE ( surf_lsm_v(l)%aldir(0:2,1:surf_lsm_v(l)%ns)      )
2223             ALLOCATE ( surf_lsm_v(l)%asdif(0:2,1:surf_lsm_v(l)%ns)      )
2224             ALLOCATE ( surf_lsm_v(l)%asdir(0:2,1:surf_lsm_v(l)%ns)      )
2225
2226             ALLOCATE ( surf_lsm_v(l)%rrtm_aldif(0:2,1:surf_lsm_v(l)%ns) )
2227             ALLOCATE ( surf_lsm_v(l)%rrtm_aldir(0:2,1:surf_lsm_v(l)%ns) )
2228             ALLOCATE ( surf_lsm_v(l)%rrtm_asdif(0:2,1:surf_lsm_v(l)%ns) )
2229             ALLOCATE ( surf_lsm_v(l)%rrtm_asdir(0:2,1:surf_lsm_v(l)%ns) )
2230
2231             ALLOCATE ( surf_usm_v(l)%aldif(0:2,1:surf_usm_v(l)%ns)      )
2232             ALLOCATE ( surf_usm_v(l)%aldir(0:2,1:surf_usm_v(l)%ns)      )
2233             ALLOCATE ( surf_usm_v(l)%asdif(0:2,1:surf_usm_v(l)%ns)      )
2234             ALLOCATE ( surf_usm_v(l)%asdir(0:2,1:surf_usm_v(l)%ns)      )
2235
2236             ALLOCATE ( surf_usm_v(l)%rrtm_aldif(0:2,1:surf_usm_v(l)%ns) )
2237             ALLOCATE ( surf_usm_v(l)%rrtm_aldir(0:2,1:surf_usm_v(l)%ns) )
2238             ALLOCATE ( surf_usm_v(l)%rrtm_asdif(0:2,1:surf_usm_v(l)%ns) )
2239             ALLOCATE ( surf_usm_v(l)%rrtm_asdir(0:2,1:surf_usm_v(l)%ns) )
2240!
2241!--          Allocate broadband albedo (temporary for the current radiation
2242!--          implementations)
2243             IF ( .NOT. ALLOCATED( surf_lsm_v(l)%albedo ) )                    &
2244                ALLOCATE( surf_lsm_v(l)%albedo(0:2,1:surf_lsm_v(l)%ns) )
2245             IF ( .NOT. ALLOCATED( surf_usm_v(l)%albedo ) )                    &
2246                ALLOCATE( surf_usm_v(l)%albedo(0:2,1:surf_usm_v(l)%ns) )
2247
2248          ENDDO
2249!
2250!--       Level 1 initialization of spectral albedos via namelist
2251!--       paramters. Please note, this case all surface tiles are initialized
2252!--       the same.
2253          IF ( surf_lsm_h%ns > 0 )  THEN
2254             surf_lsm_h%aldif  = albedo_lw_dif
2255             surf_lsm_h%aldir  = albedo_lw_dir
2256             surf_lsm_h%asdif  = albedo_sw_dif
2257             surf_lsm_h%asdir  = albedo_sw_dir
2258             surf_lsm_h%albedo = albedo_sw_dif
2259          ENDIF
2260          IF ( surf_usm_h%ns > 0 )  THEN
2261             IF ( surf_usm_h%albedo_from_ascii )  THEN
2262                surf_usm_h%aldif  = surf_usm_h%albedo
2263                surf_usm_h%aldir  = surf_usm_h%albedo
2264                surf_usm_h%asdif  = surf_usm_h%albedo
2265                surf_usm_h%asdir  = surf_usm_h%albedo
2266             ELSE
2267                surf_usm_h%aldif  = albedo_lw_dif
2268                surf_usm_h%aldir  = albedo_lw_dir
2269                surf_usm_h%asdif  = albedo_sw_dif
2270                surf_usm_h%asdir  = albedo_sw_dir
2271                surf_usm_h%albedo = albedo_sw_dif
2272             ENDIF
2273          ENDIF
2274
2275          DO  l = 0, 3
2276
2277             IF ( surf_lsm_v(l)%ns > 0 )  THEN
2278                surf_lsm_v(l)%aldif  = albedo_lw_dif
2279                surf_lsm_v(l)%aldir  = albedo_lw_dir
2280                surf_lsm_v(l)%asdif  = albedo_sw_dif
2281                surf_lsm_v(l)%asdir  = albedo_sw_dir
2282                surf_lsm_v(l)%albedo = albedo_sw_dif
2283             ENDIF
2284
2285             IF ( surf_usm_v(l)%ns > 0 )  THEN
2286                IF ( surf_usm_v(l)%albedo_from_ascii )  THEN
2287                   surf_usm_v(l)%aldif  = surf_usm_v(l)%albedo
2288                   surf_usm_v(l)%aldir  = surf_usm_v(l)%albedo
2289                   surf_usm_v(l)%asdif  = surf_usm_v(l)%albedo
2290                   surf_usm_v(l)%asdir  = surf_usm_v(l)%albedo
2291                ELSE
2292                   surf_usm_v(l)%aldif  = albedo_lw_dif
2293                   surf_usm_v(l)%aldir  = albedo_lw_dir
2294                   surf_usm_v(l)%asdif  = albedo_sw_dif
2295                   surf_usm_v(l)%asdir  = albedo_sw_dir
2296                ENDIF
2297             ENDIF
2298          ENDDO
2299
2300!
2301!--       Level 2 initialization of spectral albedos via albedo_type.
2302!--       Please note, for natural- and urban-type surfaces, a tile approach
2303!--       is applied so that the resulting albedo is calculated via the weighted
2304!--       average of respective surface fractions.
2305          DO  m = 1, surf_lsm_h%ns
2306!
2307!--          Spectral albedos for vegetation/pavement/water surfaces
2308             DO  ind_type = 0, 2
2309                IF ( surf_lsm_h%albedo_type(ind_type,m) /= 0 )  THEN
2310                   surf_lsm_h%aldif(ind_type,m) =                              &
2311                               albedo_pars(0,surf_lsm_h%albedo_type(ind_type,m))
2312                   surf_lsm_h%asdif(ind_type,m) =                              &
2313                               albedo_pars(1,surf_lsm_h%albedo_type(ind_type,m))
2314                   surf_lsm_h%aldir(ind_type,m) =                              &
2315                               albedo_pars(0,surf_lsm_h%albedo_type(ind_type,m))
2316                   surf_lsm_h%asdir(ind_type,m) =                              &
2317                               albedo_pars(1,surf_lsm_h%albedo_type(ind_type,m))
2318                   surf_lsm_h%albedo(ind_type,m) =                             &
2319                               albedo_pars(2,surf_lsm_h%albedo_type(ind_type,m))
2320                ENDIF
2321             ENDDO
2322
2323          ENDDO
2324!
2325!--       For urban surface only if albedo has not been already initialized
2326!--       in the urban-surface model via the ASCII file.
2327          IF ( .NOT. surf_usm_h%albedo_from_ascii )  THEN
2328             DO  m = 1, surf_usm_h%ns
2329!
2330!--             Spectral albedos for wall/green/window surfaces
2331                DO  ind_type = 0, 2
2332                   IF ( surf_usm_h%albedo_type(ind_type,m) /= 0 )  THEN
2333                      surf_usm_h%aldif(ind_type,m) =                           &
2334                               albedo_pars(0,surf_usm_h%albedo_type(ind_type,m))
2335                      surf_usm_h%asdif(ind_type,m) =                           &
2336                               albedo_pars(1,surf_usm_h%albedo_type(ind_type,m))
2337                      surf_usm_h%aldir(ind_type,m) =                           &
2338                               albedo_pars(0,surf_usm_h%albedo_type(ind_type,m))
2339                      surf_usm_h%asdir(ind_type,m) =                           &
2340                               albedo_pars(1,surf_usm_h%albedo_type(ind_type,m))
2341                      surf_usm_h%albedo(ind_type,m) =                          &
2342                               albedo_pars(2,surf_usm_h%albedo_type(ind_type,m))
2343                   ENDIF
2344                ENDDO
2345
2346             ENDDO
2347          ENDIF
2348
2349          DO l = 0, 3
2350
2351             DO  m = 1, surf_lsm_v(l)%ns
2352!
2353!--             Spectral albedos for vegetation/pavement/water surfaces
2354                DO  ind_type = 0, 2
2355                   IF ( surf_lsm_v(l)%albedo_type(ind_type,m) /= 0 )  THEN
2356                      surf_lsm_v(l)%aldif(ind_type,m) =                        &
2357                            albedo_pars(0,surf_lsm_v(l)%albedo_type(ind_type,m))
2358                      surf_lsm_v(l)%asdif(ind_type,m) =                        &
2359                            albedo_pars(1,surf_lsm_v(l)%albedo_type(ind_type,m))
2360                      surf_lsm_v(l)%aldir(ind_type,m) =                        &
2361                            albedo_pars(0,surf_lsm_v(l)%albedo_type(ind_type,m))
2362                      surf_lsm_v(l)%asdir(ind_type,m) =                        &
2363                            albedo_pars(1,surf_lsm_v(l)%albedo_type(ind_type,m))
2364                      surf_lsm_v(l)%albedo(ind_type,m) =                       &
2365                            albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_type,m))
2366                   ENDIF
2367                ENDDO
2368             ENDDO
2369!
2370!--          For urban surface only if albedo has not been already initialized
2371!--          in the urban-surface model via the ASCII file.
2372             IF ( .NOT. surf_usm_v(l)%albedo_from_ascii )  THEN
2373                DO  m = 1, surf_usm_v(l)%ns
2374!
2375!--                Spectral albedos for wall/green/window surfaces
2376                   DO  ind_type = 0, 2
2377                      IF ( surf_usm_v(l)%albedo_type(ind_type,m) /= 0 )  THEN
2378                         surf_usm_v(l)%aldif(ind_type,m) =                     &
2379                            albedo_pars(0,surf_usm_v(l)%albedo_type(ind_type,m))
2380                         surf_usm_v(l)%asdif(ind_type,m) =                     &
2381                            albedo_pars(1,surf_usm_v(l)%albedo_type(ind_type,m))
2382                         surf_usm_v(l)%aldir(ind_type,m) =                     &
2383                            albedo_pars(0,surf_usm_v(l)%albedo_type(ind_type,m))
2384                         surf_usm_v(l)%asdir(ind_type,m) =                     &
2385                            albedo_pars(1,surf_usm_v(l)%albedo_type(ind_type,m))
2386                         surf_usm_v(l)%albedo(ind_type,m) =                    &
2387                            albedo_pars(2,surf_usm_v(l)%albedo_type(ind_type,m))
2388                      ENDIF
2389                   ENDDO
2390
2391                ENDDO
2392             ENDIF
2393          ENDDO
2394!
2395!--       Level 3 initialization at grid points where albedo type is zero.
2396!--       This case, spectral albedos are taken from file if available
2397          IF ( albedo_pars_f%from_file )  THEN
2398!
2399!--          Horizontal
2400             DO  m = 1, surf_lsm_h%ns
2401                i = surf_lsm_h%i(m)
2402                j = surf_lsm_h%j(m)
2403!
2404!--             Spectral albedos for vegetation/pavement/water surfaces
2405                DO  ind_type = 0, 2
2406                   IF ( surf_lsm_h%albedo_type(ind_type,m) == 0 )  THEN
2407                      IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2408                         surf_lsm_h%albedo(ind_type,m) =                       &
2409                                                albedo_pars_f%pars_xy(1,j,i)
2410                      IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2411                         surf_lsm_h%aldir(ind_type,m) =                        &
2412                                                albedo_pars_f%pars_xy(1,j,i)
2413                      IF ( albedo_pars_f%pars_xy(2,j,i) /= albedo_pars_f%fill )&
2414                         surf_lsm_h%aldif(ind_type,m) =                        &
2415                                                albedo_pars_f%pars_xy(2,j,i)
2416                      IF ( albedo_pars_f%pars_xy(3,j,i) /= albedo_pars_f%fill )&
2417                         surf_lsm_h%asdir(ind_type,m) =                        &
2418                                                albedo_pars_f%pars_xy(3,j,i)
2419                      IF ( albedo_pars_f%pars_xy(4,j,i) /= albedo_pars_f%fill )&
2420                         surf_lsm_h%asdif(ind_type,m) =                        &
2421                                                albedo_pars_f%pars_xy(4,j,i)
2422                   ENDIF
2423                ENDDO
2424             ENDDO
2425!
2426!--          For urban surface only if albedo has not been already initialized
2427!--          in the urban-surface model via the ASCII file.
2428             IF ( .NOT. surf_usm_h%albedo_from_ascii )  THEN
2429                DO  m = 1, surf_usm_h%ns
2430                   i = surf_usm_h%i(m)
2431                   j = surf_usm_h%j(m)
2432!
2433!--                Spectral albedos for wall/green/window surfaces
2434                   DO  ind_type = 0, 2
2435                      IF ( surf_usm_h%albedo_type(ind_type,m) == 0 )  THEN
2436                         IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2437                            surf_usm_h%albedo(ind_type,m) =                       &
2438                                                albedo_pars_f%pars_xy(1,j,i)
2439                         IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2440                            surf_usm_h%aldir(ind_type,m) =                        &
2441                                                albedo_pars_f%pars_xy(1,j,i)
2442                         IF ( albedo_pars_f%pars_xy(2,j,i) /= albedo_pars_f%fill )&
2443                            surf_usm_h%aldif(ind_type,m) =                        &
2444                                                albedo_pars_f%pars_xy(2,j,i)
2445                         IF ( albedo_pars_f%pars_xy(3,j,i) /= albedo_pars_f%fill )&
2446                            surf_usm_h%asdir(ind_type,m) =                        &
2447                                                albedo_pars_f%pars_xy(3,j,i)
2448                         IF ( albedo_pars_f%pars_xy(4,j,i) /= albedo_pars_f%fill )&
2449                            surf_usm_h%asdif(ind_type,m) =                        &
2450                                                albedo_pars_f%pars_xy(4,j,i)
2451                      ENDIF
2452                   ENDDO
2453
2454                ENDDO
2455             ENDIF
2456!
2457!--          Vertical
2458             DO  l = 0, 3
2459                ioff = surf_lsm_v(l)%ioff
2460                joff = surf_lsm_v(l)%joff
2461
2462                DO  m = 1, surf_lsm_v(l)%ns
2463                   i = surf_lsm_v(l)%i(m)
2464                   j = surf_lsm_v(l)%j(m)
2465!
2466!--                Spectral albedos for vegetation/pavement/water surfaces
2467                   DO  ind_type = 0, 2
2468                      IF ( surf_lsm_v(l)%albedo_type(ind_type,m) == 0 )  THEN
2469                         IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2470                              albedo_pars_f%fill )                             &
2471                            surf_lsm_v(l)%albedo(ind_type,m) =                 &
2472                                          albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2473                         IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2474                              albedo_pars_f%fill )                             &
2475                            surf_lsm_v(l)%aldir(ind_type,m) =                  &
2476                                          albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2477                         IF ( albedo_pars_f%pars_xy(2,j+joff,i+ioff) /=        &
2478                              albedo_pars_f%fill )                             &
2479                            surf_lsm_v(l)%aldif(ind_type,m) =                  &
2480                                          albedo_pars_f%pars_xy(2,j+joff,i+ioff)
2481                         IF ( albedo_pars_f%pars_xy(3,j+joff,i+ioff) /=        &
2482                              albedo_pars_f%fill )                             &
2483                            surf_lsm_v(l)%asdir(ind_type,m) =                  &
2484                                          albedo_pars_f%pars_xy(3,j+joff,i+ioff)
2485                         IF ( albedo_pars_f%pars_xy(4,j+joff,i+ioff) /=        &
2486                              albedo_pars_f%fill )                             &
2487                            surf_lsm_v(l)%asdif(ind_type,m) =                  &
2488                                          albedo_pars_f%pars_xy(4,j+joff,i+ioff)
2489                      ENDIF
2490                   ENDDO
2491                ENDDO
2492!
2493!--             For urban surface only if albedo has not been already initialized
2494!--             in the urban-surface model via the ASCII file.
2495                IF ( .NOT. surf_usm_v(l)%albedo_from_ascii )  THEN
2496                   ioff = surf_usm_v(l)%ioff
2497                   joff = surf_usm_v(l)%joff
2498
2499                   DO  m = 1, surf_usm_v(l)%ns
2500                      i = surf_usm_v(l)%i(m)
2501                      j = surf_usm_v(l)%j(m)
2502!
2503!--                   Spectral albedos for wall/green/window surfaces
2504                      DO  ind_type = 0, 2
2505                         IF ( surf_usm_v(l)%albedo_type(ind_type,m) == 0 )  THEN
2506                            IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2507                                 albedo_pars_f%fill )                             &
2508                               surf_usm_v(l)%albedo(ind_type,m) =                 &
2509                                             albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2510                            IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2511                                 albedo_pars_f%fill )                             &
2512                               surf_usm_v(l)%aldir(ind_type,m) =                  &
2513                                             albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2514                            IF ( albedo_pars_f%pars_xy(2,j+joff,i+ioff) /=        &
2515                                 albedo_pars_f%fill )                             &
2516                               surf_usm_v(l)%aldif(ind_type,m) =                  &
2517                                             albedo_pars_f%pars_xy(2,j+joff,i+ioff)
2518                            IF ( albedo_pars_f%pars_xy(3,j+joff,i+ioff) /=        &
2519                                 albedo_pars_f%fill )                             &
2520                               surf_usm_v(l)%asdir(ind_type,m) =                  &
2521                                             albedo_pars_f%pars_xy(3,j+joff,i+ioff)
2522                            IF ( albedo_pars_f%pars_xy(4,j+joff,i+ioff) /=        &
2523                                 albedo_pars_f%fill )                             &
2524                               surf_usm_v(l)%asdif(ind_type,m) =                  &
2525                                             albedo_pars_f%pars_xy(4,j+joff,i+ioff)
2526                         ENDIF
2527                      ENDDO
2528
2529                   ENDDO
2530                ENDIF
2531             ENDDO
2532
2533          ENDIF
2534
2535!
2536!--       Calculate initial values of current (cosine of) the zenith angle and
2537!--       whether the sun is up
2538          CALL calc_zenith     
2539          ! readjust date and time to its initial value
2540          CALL init_date_and_time
2541!
2542!--       Calculate initial surface albedo for different surfaces
2543          IF ( .NOT. constant_albedo )  THEN
2544#if defined( __netcdf )
2545!
2546!--          Horizontally aligned natural and urban surfaces
2547             CALL calc_albedo( surf_lsm_h    )
2548             CALL calc_albedo( surf_usm_h    )
2549!
2550!--          Vertically aligned natural and urban surfaces
2551             DO  l = 0, 3
2552                CALL calc_albedo( surf_lsm_v(l) )
2553                CALL calc_albedo( surf_usm_v(l) )
2554             ENDDO
2555#endif
2556          ELSE
2557!
2558!--          Initialize sun-inclination independent spectral albedos
2559!--          Horizontal surfaces
2560             IF ( surf_lsm_h%ns > 0 )  THEN
2561                surf_lsm_h%rrtm_aldir = surf_lsm_h%aldir
2562                surf_lsm_h%rrtm_asdir = surf_lsm_h%asdir
2563                surf_lsm_h%rrtm_aldif = surf_lsm_h%aldif
2564                surf_lsm_h%rrtm_asdif = surf_lsm_h%asdif
2565             ENDIF
2566             IF ( surf_usm_h%ns > 0 )  THEN
2567                surf_usm_h%rrtm_aldir = surf_usm_h%aldir
2568                surf_usm_h%rrtm_asdir = surf_usm_h%asdir
2569                surf_usm_h%rrtm_aldif = surf_usm_h%aldif
2570                surf_usm_h%rrtm_asdif = surf_usm_h%asdif
2571             ENDIF
2572!
2573!--          Vertical surfaces
2574             DO  l = 0, 3
2575                IF ( surf_lsm_v(l)%ns > 0 )  THEN
2576                   surf_lsm_v(l)%rrtm_aldir = surf_lsm_v(l)%aldir
2577                   surf_lsm_v(l)%rrtm_asdir = surf_lsm_v(l)%asdir
2578                   surf_lsm_v(l)%rrtm_aldif = surf_lsm_v(l)%aldif
2579                   surf_lsm_v(l)%rrtm_asdif = surf_lsm_v(l)%asdif
2580                ENDIF
2581                IF ( surf_usm_v(l)%ns > 0 )  THEN
2582                   surf_usm_v(l)%rrtm_aldir = surf_usm_v(l)%aldir
2583                   surf_usm_v(l)%rrtm_asdir = surf_usm_v(l)%asdir
2584                   surf_usm_v(l)%rrtm_aldif = surf_usm_v(l)%aldif
2585                   surf_usm_v(l)%rrtm_asdif = surf_usm_v(l)%asdif
2586                ENDIF
2587             ENDDO
2588
2589          ENDIF
2590
2591!
2592!--       Allocate 3d arrays of radiative fluxes and heating rates
2593          IF ( .NOT. ALLOCATED ( rad_sw_in ) )  THEN
2594             ALLOCATE ( rad_sw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2595             rad_sw_in = 0.0_wp
2596          ENDIF
2597
2598          IF ( .NOT. ALLOCATED ( rad_sw_in_av ) )  THEN
2599             ALLOCATE ( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2600          ENDIF
2601
2602          IF ( .NOT. ALLOCATED ( rad_sw_out ) )  THEN
2603             ALLOCATE ( rad_sw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2604             rad_sw_out = 0.0_wp
2605          ENDIF
2606
2607          IF ( .NOT. ALLOCATED ( rad_sw_out_av ) )  THEN
2608             ALLOCATE ( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2609          ENDIF
2610
2611          IF ( .NOT. ALLOCATED ( rad_sw_hr ) )  THEN
2612             ALLOCATE ( rad_sw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2613             rad_sw_hr = 0.0_wp
2614          ENDIF
2615
2616          IF ( .NOT. ALLOCATED ( rad_sw_hr_av ) )  THEN
2617             ALLOCATE ( rad_sw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2618             rad_sw_hr_av = 0.0_wp
2619          ENDIF
2620
2621          IF ( .NOT. ALLOCATED ( rad_sw_cs_hr ) )  THEN
2622             ALLOCATE ( rad_sw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2623             rad_sw_cs_hr = 0.0_wp
2624          ENDIF
2625
2626          IF ( .NOT. ALLOCATED ( rad_sw_cs_hr_av ) )  THEN
2627             ALLOCATE ( rad_sw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2628             rad_sw_cs_hr_av = 0.0_wp
2629          ENDIF
2630
2631          IF ( .NOT. ALLOCATED ( rad_lw_in ) )  THEN
2632             ALLOCATE ( rad_lw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2633             rad_lw_in     = 0.0_wp
2634          ENDIF
2635
2636          IF ( .NOT. ALLOCATED ( rad_lw_in_av ) )  THEN
2637             ALLOCATE ( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2638          ENDIF
2639
2640          IF ( .NOT. ALLOCATED ( rad_lw_out ) )  THEN
2641             ALLOCATE ( rad_lw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2642            rad_lw_out    = 0.0_wp
2643          ENDIF
2644
2645          IF ( .NOT. ALLOCATED ( rad_lw_out_av ) )  THEN
2646             ALLOCATE ( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2647          ENDIF
2648
2649          IF ( .NOT. ALLOCATED ( rad_lw_hr ) )  THEN
2650             ALLOCATE ( rad_lw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2651             rad_lw_hr = 0.0_wp
2652          ENDIF
2653
2654          IF ( .NOT. ALLOCATED ( rad_lw_hr_av ) )  THEN
2655             ALLOCATE ( rad_lw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2656             rad_lw_hr_av = 0.0_wp
2657          ENDIF
2658
2659          IF ( .NOT. ALLOCATED ( rad_lw_cs_hr ) )  THEN
2660             ALLOCATE ( rad_lw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2661             rad_lw_cs_hr = 0.0_wp
2662          ENDIF
2663
2664          IF ( .NOT. ALLOCATED ( rad_lw_cs_hr_av ) )  THEN
2665             ALLOCATE ( rad_lw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2666             rad_lw_cs_hr_av = 0.0_wp
2667          ENDIF
2668
2669          ALLOCATE ( rad_sw_cs_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2670          ALLOCATE ( rad_sw_cs_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2671          rad_sw_cs_in  = 0.0_wp
2672          rad_sw_cs_out = 0.0_wp
2673
2674          ALLOCATE ( rad_lw_cs_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2675          ALLOCATE ( rad_lw_cs_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2676          rad_lw_cs_in  = 0.0_wp
2677          rad_lw_cs_out = 0.0_wp
2678
2679!
2680!--       Allocate 1-element array for surface temperature
2681!--       (RRTMG anticipates an array as passed argument).
2682          ALLOCATE ( rrtm_tsfc(1) )
2683!
2684!--       Allocate surface emissivity.
2685!--       Values will be given directly before calling rrtm_lw.
2686          ALLOCATE ( rrtm_emis(0:0,1:nbndlw+1) )
2687
2688!
2689!--       Initialize RRTMG, before check if files are existent
2690          INQUIRE( FILE='rrtmg_lw.nc', EXIST=lw_exists )
2691          IF ( .NOT. lw_exists )  THEN
2692             message_string = 'Input file rrtmg_lw.nc' //                &
2693                            '&for rrtmg missing. ' // &
2694                            '&Please provide <jobname>_lsw file in the INPUT directory.'
2695             CALL message( 'radiation_init', 'PA0583', 1, 2, 0, 6, 0 )
2696          ENDIF         
2697          INQUIRE( FILE='rrtmg_sw.nc', EXIST=sw_exists )
2698          IF ( .NOT. sw_exists )  THEN
2699             message_string = 'Input file rrtmg_sw.nc' //                &
2700                            '&for rrtmg missing. ' // &
2701                            '&Please provide <jobname>_rsw file in the INPUT directory.'
2702             CALL message( 'radiation_init', 'PA0584', 1, 2, 0, 6, 0 )
2703          ENDIF         
2704         
2705          IF ( lw_radiation )  CALL rrtmg_lw_ini ( c_p )
2706          IF ( sw_radiation )  CALL rrtmg_sw_ini ( c_p )
2707         
2708!
2709!--       Set input files for RRTMG
2710          INQUIRE(FILE="RAD_SND_DATA", EXIST=snd_exists) 
2711          IF ( .NOT. snd_exists )  THEN
2712             rrtm_input_file = "rrtmg_lw.nc"
2713          ENDIF
2714
2715!
2716!--       Read vertical layers for RRTMG from sounding data
2717!--       The routine provides nzt_rad, hyp_snd(1:nzt_rad),
2718!--       t_snd(nzt+2:nzt_rad), rrtm_play(1:nzt_rad), rrtm_plev(1_nzt_rad+1),
2719!--       rrtm_tlay(nzt+2:nzt_rad), rrtm_tlev(nzt+2:nzt_rad+1)
2720          CALL read_sounding_data
2721
2722!
2723!--       Read trace gas profiles from file. This routine provides
2724!--       the rrtm_ arrays (1:nzt_rad+1)
2725          CALL read_trace_gas_data
2726#endif
2727       ENDIF
2728
2729!
2730!--    Perform user actions if required
2731       CALL user_init_radiation
2732
2733!
2734!--    Calculate radiative fluxes at model start
2735       SELECT CASE ( TRIM( radiation_scheme ) )
2736
2737          CASE ( 'rrtmg' )
2738             CALL radiation_rrtmg
2739
2740          CASE ( 'clear-sky' )
2741             CALL radiation_clearsky
2742
2743          CASE ( 'constant' )
2744             CALL radiation_constant
2745
2746          CASE DEFAULT
2747
2748       END SELECT
2749
2750! readjust date and time to its initial value
2751       CALL init_date_and_time
2752
2753       CALL location_message( 'finished', .TRUE. )
2754
2755!
2756!--    Find all discretized apparent solar positions for radiation interaction.
2757       IF ( radiation_interactions )  CALL radiation_presimulate_solar_pos
2758
2759!
2760!--    If required, read or calculate and write out the SVF
2761       IF ( radiation_interactions .AND. read_svf)  THEN
2762!
2763!--       Read sky-view factors and further required data from file
2764          CALL location_message( '    Start reading SVF from file', .FALSE. )
2765          CALL radiation_read_svf()
2766          CALL location_message( '    Reading SVF from file has finished', .TRUE. )
2767
2768       ELSEIF ( radiation_interactions .AND. .NOT. read_svf)  THEN
2769!
2770!--       calculate SFV and CSF
2771          CALL location_message( '    Start calculation of SVF', .FALSE. )
2772          CALL radiation_calc_svf()
2773          CALL location_message( '    Calculation of SVF has finished', .TRUE. )
2774       ENDIF
2775
2776       IF ( radiation_interactions .AND. write_svf)  THEN
2777!
2778!--       Write svf, csf svfsurf and csfsurf data to file
2779          CALL location_message( '    Start writing SVF in file', .FALSE. )
2780          CALL radiation_write_svf()
2781          CALL location_message( '    Writing SVF in file has finished', .TRUE. )
2782       ENDIF
2783
2784!
2785!--    Adjust radiative fluxes. In case of urban and land surfaces, also
2786!--    call an initial interaction.
2787       IF ( radiation_interactions )  THEN
2788          CALL radiation_interaction
2789       ENDIF
2790
2791       RETURN
2792
2793    END SUBROUTINE radiation_init
2794
2795
2796!------------------------------------------------------------------------------!
2797! Description:
2798! ------------
2799!> A simple clear sky radiation model
2800!------------------------------------------------------------------------------!
2801    SUBROUTINE radiation_clearsky
2802
2803
2804       IMPLICIT NONE
2805
2806       INTEGER(iwp) ::  l         !< running index for surface orientation
2807       REAL(wp)     ::  pt1       !< potential temperature at first grid level or mean value at urban layer top
2808       REAL(wp)     ::  pt1_l     !< potential temperature at first grid level or mean value at urban layer top at local subdomain
2809       REAL(wp)     ::  ql1       !< liquid water mixing ratio at first grid level or mean value at urban layer top
2810       REAL(wp)     ::  ql1_l     !< liquid water mixing ratio at first grid level or mean value at urban layer top at local subdomain
2811
2812       TYPE(surf_type), POINTER ::  surf !< pointer on respective surface type, used to generalize routine   
2813
2814!
2815!--    Calculate current zenith angle
2816       CALL calc_zenith
2817
2818!
2819!--    Calculate sky transmissivity
2820       sky_trans = 0.6_wp + 0.2_wp * zenith(0)
2821
2822!
2823!--    Calculate value of the Exner function at model surface
2824!
2825!--    In case averaged radiation is used, calculate mean temperature and
2826!--    liquid water mixing ratio at the urban-layer top.
2827       IF ( average_radiation ) THEN
2828          pt1   = 0.0_wp
2829          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1   = 0.0_wp
2830
2831          pt1_l = SUM( pt(nzut,nys:nyn,nxl:nxr) )
2832          IF ( bulk_cloud_model  .OR.  cloud_droplets  )  ql1_l = SUM( ql(nzut,nys:nyn,nxl:nxr) )
2833
2834#if defined( __parallel )     
2835          IF ( collective_wait )  CALL MPI_BARRIER( comm2d, ierr )
2836          CALL MPI_ALLREDUCE( pt1_l, pt1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
2837          IF ( ierr /= 0 ) THEN
2838              WRITE(9,*) 'Error MPI_AllReduce1:', ierr, pt1_l, pt1
2839              FLUSH(9)
2840          ENDIF
2841
2842          IF ( bulk_cloud_model  .OR.  cloud_droplets ) THEN
2843              CALL MPI_ALLREDUCE( ql1_l, ql1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
2844              IF ( ierr /= 0 ) THEN
2845                  WRITE(9,*) 'Error MPI_AllReduce2:', ierr, ql1_l, ql1
2846                  FLUSH(9)
2847              ENDIF
2848          ENDIF
2849#else
2850          pt1 = pt1_l 
2851          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1 = ql1_l
2852#endif
2853
2854          IF ( bulk_cloud_model  .OR.  cloud_droplets  )  pt1 = pt1 + lv_d_cp / exner(nzut) * ql1
2855!
2856!--       Finally, divide by number of grid points
2857          pt1 = pt1 / REAL( ( nx + 1 ) * ( ny + 1 ), KIND=wp )
2858       ENDIF
2859!
2860!--    Call clear-sky calculation for each surface orientation.
2861!--    First, horizontal surfaces
2862       surf => surf_lsm_h
2863       CALL radiation_clearsky_surf
2864       surf => surf_usm_h
2865       CALL radiation_clearsky_surf
2866!
2867!--    Vertical surfaces
2868       DO  l = 0, 3
2869          surf => surf_lsm_v(l)
2870          CALL radiation_clearsky_surf
2871          surf => surf_usm_v(l)
2872          CALL radiation_clearsky_surf
2873       ENDDO
2874
2875       CONTAINS
2876
2877          SUBROUTINE radiation_clearsky_surf
2878
2879             IMPLICIT NONE
2880
2881             INTEGER(iwp) ::  i         !< index x-direction
2882             INTEGER(iwp) ::  j         !< index y-direction
2883             INTEGER(iwp) ::  k         !< index z-direction
2884             INTEGER(iwp) ::  m         !< running index for surface elements
2885
2886             IF ( surf%ns < 1 )  RETURN
2887
2888!
2889!--          Calculate radiation fluxes and net radiation (rad_net) assuming
2890!--          homogeneous urban radiation conditions.
2891             IF ( average_radiation ) THEN       
2892
2893                k = nzut
2894
2895                surf%rad_sw_in  = solar_constant * sky_trans * zenith(0)
2896                surf%rad_sw_out = albedo_urb * surf%rad_sw_in
2897               
2898                surf%rad_lw_in  = 0.8_wp * sigma_sb * (pt1 * exner(k+1))**4
2899
2900                surf%rad_lw_out = emissivity_urb * sigma_sb * (t_rad_urb)**4   &
2901                                    + (1.0_wp - emissivity_urb) * surf%rad_lw_in
2902
2903                surf%rad_net = surf%rad_sw_in - surf%rad_sw_out                &
2904                             + surf%rad_lw_in - surf%rad_lw_out
2905
2906                surf%rad_lw_out_change_0 = 3.0_wp * emissivity_urb * sigma_sb  &
2907                                           * (t_rad_urb)**3
2908
2909!
2910!--          Calculate radiation fluxes and net radiation (rad_net) for each surface
2911!--          element.
2912             ELSE
2913
2914                DO  m = 1, surf%ns
2915                   i = surf%i(m)
2916                   j = surf%j(m)
2917                   k = surf%k(m)
2918
2919                   surf%rad_sw_in(m) = solar_constant * sky_trans * zenith(0)
2920
2921!
2922!--                Weighted average according to surface fraction.
2923!--                ATTENTION: when radiation interactions are switched on the
2924!--                calculated fluxes below are not actually used as they are
2925!--                overwritten in radiation_interaction.
2926                   surf%rad_sw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
2927                                          surf%albedo(ind_veg_wall,m)          &
2928                                        + surf%frac(ind_pav_green,m) *         &
2929                                          surf%albedo(ind_pav_green,m)         &
2930                                        + surf%frac(ind_wat_win,m)   *         &
2931                                          surf%albedo(ind_wat_win,m) )         &
2932                                        * surf%rad_sw_in(m)
2933
2934                   surf%rad_lw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
2935                                          surf%emissivity(ind_veg_wall,m)      &
2936                                        + surf%frac(ind_pav_green,m) *         &
2937                                          surf%emissivity(ind_pav_green,m)     &
2938                                        + surf%frac(ind_wat_win,m)   *         &
2939                                          surf%emissivity(ind_wat_win,m)       &
2940                                        )                                      &
2941                                        * sigma_sb                             &
2942                                        * ( surf%pt_surface(m) * exner(nzb) )**4
2943
2944                   surf%rad_lw_out_change_0(m) =                               &
2945                                      ( surf%frac(ind_veg_wall,m)  *           &
2946                                        surf%emissivity(ind_veg_wall,m)        &
2947                                      + surf%frac(ind_pav_green,m) *           &
2948                                        surf%emissivity(ind_pav_green,m)       &
2949                                      + surf%frac(ind_wat_win,m)   *           &
2950                                        surf%emissivity(ind_wat_win,m)         &
2951                                      ) * 3.0_wp * sigma_sb                    &
2952                                      * ( surf%pt_surface(m) * exner(nzb) )** 3
2953
2954
2955                   IF ( bulk_cloud_model  .OR.  cloud_droplets  )  THEN
2956                      pt1 = pt(k,j,i) + lv_d_cp / exner(k) * ql(k,j,i)
2957                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb * (pt1 * exner(k))**4
2958                   ELSE
2959                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb * (pt(k,j,i) * exner(k))**4
2960                   ENDIF
2961
2962                   surf%rad_net(m) = surf%rad_sw_in(m) - surf%rad_sw_out(m)    &
2963                                   + surf%rad_lw_in(m) - surf%rad_lw_out(m)
2964
2965                ENDDO
2966
2967             ENDIF
2968
2969!
2970!--          Fill out values in radiation arrays
2971             DO  m = 1, surf%ns
2972                i = surf%i(m)
2973                j = surf%j(m)
2974                rad_sw_in(0,j,i) = surf%rad_sw_in(m)
2975                rad_sw_out(0,j,i) = surf%rad_sw_out(m)
2976                rad_lw_in(0,j,i) = surf%rad_lw_in(m)
2977                rad_lw_out(0,j,i) = surf%rad_lw_out(m)
2978             ENDDO
2979 
2980          END SUBROUTINE radiation_clearsky_surf
2981
2982    END SUBROUTINE radiation_clearsky
2983
2984
2985!------------------------------------------------------------------------------!
2986! Description:
2987! ------------
2988!> This scheme keeps the prescribed net radiation constant during the run
2989!------------------------------------------------------------------------------!
2990    SUBROUTINE radiation_constant
2991
2992
2993       IMPLICIT NONE
2994
2995       INTEGER(iwp) ::  l         !< running index for surface orientation
2996
2997       REAL(wp)     ::  pt1       !< potential temperature at first grid level or mean value at urban layer top
2998       REAL(wp)     ::  pt1_l     !< potential temperature at first grid level or mean value at urban layer top at local subdomain
2999       REAL(wp)     ::  ql1       !< liquid water mixing ratio at first grid level or mean value at urban layer top
3000       REAL(wp)     ::  ql1_l     !< liquid water mixing ratio at first grid level or mean value at urban layer top at local subdomain
3001
3002       TYPE(surf_type), POINTER ::  surf !< pointer on respective surface type, used to generalize routine
3003
3004!
3005!--    In case averaged radiation is used, calculate mean temperature and
3006!--    liquid water mixing ratio at the urban-layer top.
3007       IF ( average_radiation ) THEN   
3008          pt1   = 0.0_wp
3009          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1   = 0.0_wp
3010
3011          pt1_l = SUM( pt(nzut,nys:nyn,nxl:nxr) )
3012          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1_l = SUM( ql(nzut,nys:nyn,nxl:nxr) )
3013
3014#if defined( __parallel )     
3015          IF ( collective_wait )  CALL MPI_BARRIER( comm2d, ierr )
3016          CALL MPI_ALLREDUCE( pt1_l, pt1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
3017          IF ( ierr /= 0 ) THEN
3018              WRITE(9,*) 'Error MPI_AllReduce3:', ierr, pt1_l, pt1
3019              FLUSH(9)
3020          ENDIF
3021          IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
3022             CALL MPI_ALLREDUCE( ql1_l, ql1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
3023             IF ( ierr /= 0 ) THEN
3024                 WRITE(9,*) 'Error MPI_AllReduce4:', ierr, ql1_l, ql1
3025                 FLUSH(9)
3026             ENDIF
3027          ENDIF
3028#else
3029          pt1 = pt1_l
3030          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1 = ql1_l
3031#endif
3032          IF ( bulk_cloud_model  .OR.  cloud_droplets )  pt1 = pt1 + lv_d_cp / exner(nzut+1) * ql1
3033!
3034!--       Finally, divide by number of grid points
3035          pt1 = pt1 / REAL( ( nx + 1 ) * ( ny + 1 ), KIND=wp )
3036       ENDIF
3037
3038!
3039!--    First, horizontal surfaces
3040       surf => surf_lsm_h
3041       CALL radiation_constant_surf
3042       surf => surf_usm_h
3043       CALL radiation_constant_surf
3044!
3045!--    Vertical surfaces
3046       DO  l = 0, 3
3047          surf => surf_lsm_v(l)
3048          CALL radiation_constant_surf
3049          surf => surf_usm_v(l)
3050          CALL radiation_constant_surf
3051       ENDDO
3052
3053       CONTAINS
3054
3055          SUBROUTINE radiation_constant_surf
3056
3057             IMPLICIT NONE
3058
3059             INTEGER(iwp) ::  i         !< index x-direction
3060             INTEGER(iwp) ::  ioff      !< offset between surface element and adjacent grid point along x
3061             INTEGER(iwp) ::  j         !< index y-direction
3062             INTEGER(iwp) ::  joff      !< offset between surface element and adjacent grid point along y
3063             INTEGER(iwp) ::  k         !< index z-direction
3064             INTEGER(iwp) ::  koff      !< offset between surface element and adjacent grid point along z
3065             INTEGER(iwp) ::  m         !< running index for surface elements
3066
3067             IF ( surf%ns < 1 )  RETURN
3068
3069!--          Calculate homogenoeus urban radiation fluxes
3070             IF ( average_radiation ) THEN
3071
3072                surf%rad_net = net_radiation
3073
3074                surf%rad_lw_in  = 0.8_wp * sigma_sb * (pt1 * exner(nzut+1))**4
3075
3076                surf%rad_lw_out = emissivity_urb * sigma_sb * (t_rad_urb)**4   &
3077                                    + ( 1.0_wp - emissivity_urb )             & ! shouldn't be this a bulk value -- emissivity_urb?
3078                                    * surf%rad_lw_in
3079
3080                surf%rad_lw_out_change_0 = 3.0_wp * emissivity_urb * sigma_sb  &
3081                                           * t_rad_urb**3
3082
3083                surf%rad_sw_in = ( surf%rad_net - surf%rad_lw_in               &
3084                                     + surf%rad_lw_out )                       &
3085                                     / ( 1.0_wp - albedo_urb )
3086
3087                surf%rad_sw_out =  albedo_urb * surf%rad_sw_in
3088
3089!
3090!--          Calculate radiation fluxes for each surface element
3091             ELSE
3092!
3093!--             Determine index offset between surface element and adjacent
3094!--             atmospheric grid point
3095                ioff = surf%ioff
3096                joff = surf%joff
3097                koff = surf%koff
3098
3099!
3100!--             Prescribe net radiation and estimate the remaining radiative fluxes
3101                DO  m = 1, surf%ns
3102                   i = surf%i(m)
3103                   j = surf%j(m)
3104                   k = surf%k(m)
3105
3106                   surf%rad_net(m) = net_radiation
3107
3108                   IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
3109                      pt1 = pt(k,j,i) + lv_d_cp / exner(k) * ql(k,j,i)
3110                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb * (pt1 * exner(k))**4
3111                   ELSE
3112                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb *                 &
3113                                             ( pt(k,j,i) * exner(k) )**4
3114                   ENDIF
3115
3116!
3117!--                Weighted average according to surface fraction.
3118                   surf%rad_lw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
3119                                          surf%emissivity(ind_veg_wall,m)      &
3120                                        + surf%frac(ind_pav_green,m) *         &
3121                                          surf%emissivity(ind_pav_green,m)     &
3122                                        + surf%frac(ind_wat_win,m)   *         &
3123                                          surf%emissivity(ind_wat_win,m)       &
3124                                        )                                      &
3125                                      * sigma_sb                               &
3126                                      * ( surf%pt_surface(m) * exner(nzb) )**4
3127
3128                   surf%rad_sw_in(m) = ( surf%rad_net(m) - surf%rad_lw_in(m)   &
3129                                       + surf%rad_lw_out(m) )                  &
3130                                       / ( 1.0_wp -                            &
3131                                          ( surf%frac(ind_veg_wall,m)  *       &
3132                                            surf%albedo(ind_veg_wall,m)        &
3133                                         +  surf%frac(ind_pav_green,m) *       &
3134                                            surf%albedo(ind_pav_green,m)       &
3135                                         +  surf%frac(ind_wat_win,m)   *       &
3136                                            surf%albedo(ind_wat_win,m) )       &
3137                                         )
3138
3139                   surf%rad_sw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
3140                                          surf%albedo(ind_veg_wall,m)          &
3141                                        + surf%frac(ind_pav_green,m) *         &
3142                                          surf%albedo(ind_pav_green,m)         &
3143                                        + surf%frac(ind_wat_win,m)   *         &
3144                                          surf%albedo(ind_wat_win,m) )         &
3145                                      * surf%rad_sw_in(m)
3146
3147                ENDDO
3148
3149             ENDIF
3150
3151!
3152!--          Fill out values in radiation arrays
3153             DO  m = 1, surf%ns
3154                i = surf%i(m)
3155                j = surf%j(m)
3156                rad_sw_in(0,j,i) = surf%rad_sw_in(m)
3157                rad_sw_out(0,j,i) = surf%rad_sw_out(m)
3158                rad_lw_in(0,j,i) = surf%rad_lw_in(m)
3159                rad_lw_out(0,j,i) = surf%rad_lw_out(m)
3160             ENDDO
3161
3162          END SUBROUTINE radiation_constant_surf
3163         
3164
3165    END SUBROUTINE radiation_constant
3166
3167!------------------------------------------------------------------------------!
3168! Description:
3169! ------------
3170!> Header output for radiation model
3171!------------------------------------------------------------------------------!
3172    SUBROUTINE radiation_header ( io )
3173
3174
3175       IMPLICIT NONE
3176 
3177       INTEGER(iwp), INTENT(IN) ::  io            !< Unit of the output file
3178   
3179
3180       
3181!
3182!--    Write radiation model header
3183       WRITE( io, 3 )
3184
3185       IF ( radiation_scheme == "constant" )  THEN
3186          WRITE( io, 4 ) net_radiation
3187       ELSEIF ( radiation_scheme == "clear-sky" )  THEN
3188          WRITE( io, 5 )
3189       ELSEIF ( radiation_scheme == "rrtmg" )  THEN
3190          WRITE( io, 6 )
3191          IF ( .NOT. lw_radiation )  WRITE( io, 10 )
3192          IF ( .NOT. sw_radiation )  WRITE( io, 11 )
3193       ENDIF
3194
3195       IF ( albedo_type_f%from_file  .OR.  vegetation_type_f%from_file  .OR.   &
3196            pavement_type_f%from_file  .OR.  water_type_f%from_file  .OR.      &
3197            building_type_f%from_file )  THEN
3198             WRITE( io, 13 )
3199       ELSE 
3200          IF ( albedo_type == 0 )  THEN
3201             WRITE( io, 7 ) albedo
3202          ELSE
3203             WRITE( io, 8 ) TRIM( albedo_type_name(albedo_type) )
3204          ENDIF
3205       ENDIF
3206       IF ( constant_albedo )  THEN
3207          WRITE( io, 9 )
3208       ENDIF
3209       
3210       WRITE( io, 12 ) dt_radiation
3211 
3212
3213 3 FORMAT (//' Radiation model information:'/                                  &
3214              ' ----------------------------'/)
3215 4 FORMAT ('    --> Using constant net radiation: net_radiation = ', F6.2,     &
3216           // 'W/m**2')
3217 5 FORMAT ('    --> Simple radiation scheme for clear sky is used (no clouds,',&
3218                   ' default)')
3219 6 FORMAT ('    --> RRTMG scheme is used')
3220 7 FORMAT (/'    User-specific surface albedo: albedo =', F6.3)
3221 8 FORMAT (/'    Albedo is set for land surface type: ', A)
3222 9 FORMAT (/'    --> Albedo is fixed during the run')
322310 FORMAT (/'    --> Longwave radiation is disabled')
322411 FORMAT (/'    --> Shortwave radiation is disabled.')
322512 FORMAT  ('    Timestep: dt_radiation = ', F6.2, '  s')
322613 FORMAT (/'    Albedo is set individually for each xy-location, according ', &
3227                 'to given surface type.')
3228
3229
3230    END SUBROUTINE radiation_header
3231   
3232
3233!------------------------------------------------------------------------------!
3234! Description:
3235! ------------
3236!> Parin for &radiation_parameters for radiation model
3237!------------------------------------------------------------------------------!
3238    SUBROUTINE radiation_parin
3239
3240
3241       IMPLICIT NONE
3242
3243       CHARACTER (LEN=80) ::  line  !< dummy string that contains the current line of the parameter file
3244       
3245       NAMELIST /radiation_par/   albedo, albedo_lw_dif, albedo_lw_dir,         &
3246                                  albedo_sw_dif, albedo_sw_dir, albedo_type,    &
3247                                  constant_albedo, dt_radiation, emissivity,    &
3248                                  lw_radiation, max_raytracing_dist,            &
3249                                  min_irrf_value, mrt_geom_human,               &
3250                                  mrt_include_sw, mrt_nlevels,                  &
3251                                  mrt_skip_roof, net_radiation, nrefsteps,      &
3252                                  plant_lw_interact, rad_angular_discretization,&
3253                                  radiation_interactions_on, radiation_scheme,  &
3254                                  raytrace_discrete_azims,                      &
3255                                  raytrace_discrete_elevs, raytrace_mpi_rma,    &
3256                                  skip_time_do_radiation, surface_reflections,  &
3257                                  svfnorm_report_thresh, sw_radiation,          &
3258                                  unscheduled_radiation_calls
3259
3260   
3261       NAMELIST /radiation_parameters/ albedo, albedo_lw_dif, albedo_lw_dir,    &
3262                                  albedo_sw_dif, albedo_sw_dir, albedo_type,    &
3263                                  constant_albedo, dt_radiation, emissivity,    &
3264                                  lw_radiation, max_raytracing_dist,            &
3265                                  min_irrf_value, mrt_geom_human,               &
3266                                  mrt_include_sw, mrt_nlevels,                  &
3267                                  mrt_skip_roof, net_radiation, nrefsteps,      &
3268                                  plant_lw_interact, rad_angular_discretization,&
3269                                  radiation_interactions_on, radiation_scheme,  &
3270                                  raytrace_discrete_azims,                      &
3271                                  raytrace_discrete_elevs, raytrace_mpi_rma,    &
3272                                  skip_time_do_radiation, surface_reflections,  &
3273                                  svfnorm_report_thresh, sw_radiation,          &
3274                                  unscheduled_radiation_calls
3275   
3276       line = ' '
3277       
3278!
3279!--    Try to find radiation model namelist
3280       REWIND ( 11 )
3281       line = ' '
3282       DO WHILE ( INDEX( line, '&radiation_parameters' ) == 0 )
3283          READ ( 11, '(A)', END=12 )  line
3284       ENDDO
3285       BACKSPACE ( 11 )
3286
3287!
3288!--    Read user-defined namelist
3289       READ ( 11, radiation_parameters, ERR = 10 )
3290
3291!
3292!--    Set flag that indicates that the radiation model is switched on
3293       radiation = .TRUE.
3294
3295       GOTO 14
3296
3297 10    BACKSPACE( 11 )
3298       READ( 11 , '(A)') line
3299       CALL parin_fail_message( 'radiation_parameters', line )
3300!
3301!--    Try to find old namelist
3302 12    REWIND ( 11 )
3303       line = ' '
3304       DO WHILE ( INDEX( line, '&radiation_par' ) == 0 )
3305          READ ( 11, '(A)', END=14 )  line
3306       ENDDO
3307       BACKSPACE ( 11 )
3308
3309!
3310!--    Read user-defined namelist
3311       READ ( 11, radiation_par, ERR = 13, END = 14 )
3312
3313       message_string = 'namelist radiation_par is deprecated and will be ' // &
3314                     'removed in near future. Please use namelist ' //         &
3315                     'radiation_parameters instead'
3316       CALL message( 'radiation_parin', 'PA0487', 0, 1, 0, 6, 0 )
3317
3318!
3319!--    Set flag that indicates that the radiation model is switched on
3320       radiation = .TRUE.
3321
3322       IF ( .NOT.  radiation_interactions_on  .AND.  surface_reflections )  THEN
3323          message_string = 'surface_reflections is allowed only when '      // &
3324               'radiation_interactions_on is set to TRUE'
3325          CALL message( 'radiation_parin', 'PA0293',1, 2, 0, 6, 0 )
3326       ENDIF
3327
3328       GOTO 14
3329
3330 13    BACKSPACE( 11 )
3331       READ( 11 , '(A)') line
3332       CALL parin_fail_message( 'radiation_par', line )
3333
3334 14    CONTINUE
3335       
3336    END SUBROUTINE radiation_parin
3337
3338
3339!------------------------------------------------------------------------------!
3340! Description:
3341! ------------
3342!> Implementation of the RRTMG radiation_scheme
3343!------------------------------------------------------------------------------!
3344    SUBROUTINE radiation_rrtmg
3345
3346#if defined ( __rrtmg )
3347       USE indices,                                                            &
3348           ONLY:  nbgp
3349
3350       USE particle_attributes,                                                &
3351           ONLY:  grid_particles, number_of_particles, particles,              &
3352                  particle_advection_start, prt_count
3353
3354       IMPLICIT NONE
3355
3356
3357       INTEGER(iwp) ::  i, j, k, l, m, n !< loop indices
3358       INTEGER(iwp) ::  k_topo     !< topography top index
3359
3360       REAL(wp)     ::  nc_rad, &    !< number concentration of cloud droplets
3361                        s_r2,   &    !< weighted sum over all droplets with r^2
3362                        s_r3         !< weighted sum over all droplets with r^3
3363
3364       REAL(wp), DIMENSION(0:nzt+1) :: pt_av, q_av, ql_av
3365!
3366!--    Just dummy arguments
3367       REAL(wp), DIMENSION(:,:,:), ALLOCATABLE :: rrtm_lw_taucld_dum,          &
3368                                                  rrtm_lw_tauaer_dum,          &
3369                                                  rrtm_sw_taucld_dum,          &
3370                                                  rrtm_sw_ssacld_dum,          &
3371                                                  rrtm_sw_asmcld_dum,          &
3372                                                  rrtm_sw_fsfcld_dum,          &
3373                                                  rrtm_sw_tauaer_dum,          &
3374                                                  rrtm_sw_ssaaer_dum,          &
3375                                                  rrtm_sw_asmaer_dum,          &
3376                                                  rrtm_sw_ecaer_dum
3377
3378!
3379!--    Calculate current (cosine of) zenith angle and whether the sun is up
3380       CALL calc_zenith     
3381!
3382!--    Calculate surface albedo. In case average radiation is applied,
3383!--    this is not required.
3384#if defined( __netcdf )
3385       IF ( .NOT. constant_albedo )  THEN
3386!
3387!--       Horizontally aligned default, natural and urban surfaces
3388          CALL calc_albedo( surf_lsm_h    )
3389          CALL calc_albedo( surf_usm_h    )
3390!
3391!--       Vertically aligned default, natural and urban surfaces
3392          DO  l = 0, 3
3393             CALL calc_albedo( surf_lsm_v(l) )
3394             CALL calc_albedo( surf_usm_v(l) )
3395          ENDDO
3396       ENDIF
3397#endif
3398
3399!
3400!--    Prepare input data for RRTMG
3401
3402!
3403!--    In case of large scale forcing with surface data, calculate new pressure
3404!--    profile. nzt_rad might be modified by these calls and all required arrays
3405!--    will then be re-allocated
3406       IF ( large_scale_forcing  .AND.  lsf_surf )  THEN
3407          CALL read_sounding_data
3408          CALL read_trace_gas_data
3409       ENDIF
3410
3411
3412       IF ( average_radiation ) THEN
3413
3414          rrtm_asdir(1)  = albedo_urb
3415          rrtm_asdif(1)  = albedo_urb
3416          rrtm_aldir(1)  = albedo_urb
3417          rrtm_aldif(1)  = albedo_urb
3418
3419          rrtm_emis = emissivity_urb
3420!
3421!--       Calculate mean pt profile. Actually, only one height level is required.
3422          CALL calc_mean_profile( pt, 4 )
3423          pt_av = hom(:, 1, 4, 0)
3424         
3425          IF ( humidity )  THEN
3426             CALL calc_mean_profile( q, 41 )
3427             q_av  = hom(:, 1, 41, 0)
3428          ENDIF
3429!
3430!--       Prepare profiles of temperature and H2O volume mixing ratio
3431          rrtm_tlev(0,nzb+1) = t_rad_urb
3432
3433          IF ( bulk_cloud_model )  THEN
3434
3435             CALL calc_mean_profile( ql, 54 )
3436             ! average ql is now in hom(:, 1, 54, 0)
3437             ql_av = hom(:, 1, 54, 0)
3438             
3439             DO k = nzb+1, nzt+1
3440                rrtm_tlay(0,k) = pt_av(k) * ( (hyp(k) ) / 100000._wp       &
3441                                 )**.286_wp + lv_d_cp * ql_av(k)
3442                rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * (q_av(k) - ql_av(k))
3443             ENDDO
3444          ELSE
3445             DO k = nzb+1, nzt+1
3446                rrtm_tlay(0,k) = pt_av(k) * ( (hyp(k) ) / 100000._wp       &
3447                                 )**.286_wp
3448             ENDDO
3449
3450             IF ( humidity )  THEN
3451                DO k = nzb+1, nzt+1
3452                   rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * q_av(k)
3453                ENDDO
3454             ELSE
3455                rrtm_h2ovmr(0,nzb+1:nzt+1) = 0.0_wp
3456             ENDIF
3457          ENDIF
3458
3459!
3460!--       Avoid temperature/humidity jumps at the top of the LES domain by
3461!--       linear interpolation from nzt+2 to nzt+7
3462          DO k = nzt+2, nzt+7
3463             rrtm_tlay(0,k) = rrtm_tlay(0,nzt+1)                            &
3464                           + ( rrtm_tlay(0,nzt+8) - rrtm_tlay(0,nzt+1) )    &
3465                           / ( rrtm_play(0,nzt+8) - rrtm_play(0,nzt+1) )    &
3466                           * ( rrtm_play(0,k) - rrtm_play(0,nzt+1) )
3467
3468             rrtm_h2ovmr(0,k) = rrtm_h2ovmr(0,nzt+1)                        &
3469                           + ( rrtm_h2ovmr(0,nzt+8) - rrtm_h2ovmr(0,nzt+1) )&
3470                           / ( rrtm_play(0,nzt+8)   - rrtm_play(0,nzt+1)   )&
3471                           * ( rrtm_play(0,k) - rrtm_play(0,nzt+1) )
3472
3473          ENDDO
3474
3475!--       Linear interpolate to zw grid
3476          DO k = nzb+2, nzt+8
3477             rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k) -        &
3478                                rrtm_tlay(0,k-1))                           &
3479                                / ( rrtm_play(0,k) - rrtm_play(0,k-1) )     &
3480                                * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
3481          ENDDO
3482
3483
3484!
3485!--       Calculate liquid water path and cloud fraction for each column.
3486!--       Note that LWP is required in g/m2 instead of kg/kg m.
3487          rrtm_cldfr  = 0.0_wp
3488          rrtm_reliq  = 0.0_wp
3489          rrtm_cliqwp = 0.0_wp
3490          rrtm_icld   = 0
3491
3492          IF ( bulk_cloud_model )  THEN
3493             DO k = nzb+1, nzt+1
3494                rrtm_cliqwp(0,k) =  ql_av(k) * 1000._wp *                   &
3495                                    (rrtm_plev(0,k) - rrtm_plev(0,k+1))     &
3496                                    * 100._wp / g 
3497
3498                IF ( rrtm_cliqwp(0,k) > 0._wp )  THEN
3499                   rrtm_cldfr(0,k) = 1._wp
3500                   IF ( rrtm_icld == 0 )  rrtm_icld = 1
3501
3502!
3503!--                Calculate cloud droplet effective radius
3504                   rrtm_reliq(0,k) = 1.0E6_wp * ( 3.0_wp * ql_av(k)         &
3505                                     * rho_surface                          &
3506                                     / ( 4.0_wp * pi * nc_const * rho_l )   &
3507                                     )**0.33333333333333_wp                 &
3508                                     * EXP( LOG( sigma_gc )**2 )
3509!
3510!--                Limit effective radius
3511                   IF ( rrtm_reliq(0,k) > 0.0_wp )  THEN
3512                      rrtm_reliq(0,k) = MAX(rrtm_reliq(0,k),2.5_wp)
3513                      rrtm_reliq(0,k) = MIN(rrtm_reliq(0,k),60.0_wp)
3514                   ENDIF
3515                ENDIF
3516             ENDDO
3517          ENDIF
3518
3519!
3520!--       Set surface temperature
3521          rrtm_tsfc = t_rad_urb
3522         
3523          IF ( lw_radiation )  THEN       
3524         
3525             CALL rrtmg_lw( 1, nzt_rad      , rrtm_icld    , rrtm_idrv      ,&
3526             rrtm_play       , rrtm_plev    , rrtm_tlay    , rrtm_tlev      ,&
3527             rrtm_tsfc       , rrtm_h2ovmr  , rrtm_o3vmr   , rrtm_co2vmr    ,&
3528             rrtm_ch4vmr     , rrtm_n2ovmr  , rrtm_o2vmr   , rrtm_cfc11vmr  ,&
3529             rrtm_cfc12vmr   , rrtm_cfc22vmr, rrtm_ccl4vmr , rrtm_emis      ,&
3530             rrtm_inflglw    , rrtm_iceflglw, rrtm_liqflglw, rrtm_cldfr     ,&
3531             rrtm_lw_taucld  , rrtm_cicewp  , rrtm_cliqwp  , rrtm_reice     ,& 
3532             rrtm_reliq      , rrtm_lw_tauaer,                               &
3533             rrtm_lwuflx     , rrtm_lwdflx  , rrtm_lwhr  ,                   &
3534             rrtm_lwuflxc    , rrtm_lwdflxc , rrtm_lwhrc ,                   &
3535             rrtm_lwuflx_dt  ,  rrtm_lwuflxc_dt )
3536
3537!
3538!--          Save fluxes
3539             DO k = nzb, nzt+1
3540                rad_lw_in(k,:,:)  = rrtm_lwdflx(0,k)
3541                rad_lw_out(k,:,:) = rrtm_lwuflx(0,k)
3542             ENDDO
3543             rad_lw_in_diff(:,:) = rad_lw_in(0,:,:)
3544!
3545!--          Save heating rates (convert from K/d to K/h).
3546!--          Further, even though an aggregated radiation is computed, map
3547!--          signle-column profiles on top of any topography, in order to
3548!--          obtain correct near surface radiation heating/cooling rates.
3549             DO  i = nxl, nxr
3550                DO  j = nys, nyn
3551                   k_topo = get_topography_top_index_ji( j, i, 's' )
3552                   DO k = k_topo+1, nzt+1
3553                      rad_lw_hr(k,j,i)     = rrtm_lwhr(0,k-k_topo)  * d_hours_day
3554                      rad_lw_cs_hr(k,j,i)  = rrtm_lwhrc(0,k-k_topo) * d_hours_day
3555                   ENDDO
3556                ENDDO
3557             ENDDO
3558
3559          ENDIF
3560
3561          IF ( sw_radiation .AND. sun_up )  THEN
3562             CALL rrtmg_sw( 1, nzt_rad      , rrtm_icld     , rrtm_iaer      ,&
3563             rrtm_play      , rrtm_plev     , rrtm_tlay     , rrtm_tlev      ,&
3564             rrtm_tsfc      , rrtm_h2ovmr   , rrtm_o3vmr    , rrtm_co2vmr    ,&
3565             rrtm_ch4vmr    , rrtm_n2ovmr   , rrtm_o2vmr    , rrtm_asdir     ,&
3566             rrtm_asdif     , rrtm_aldir    , rrtm_aldif    , zenith         ,&
3567             0.0_wp         , day_of_year   , solar_constant, rrtm_inflgsw   ,&
3568             rrtm_iceflgsw  , rrtm_liqflgsw , rrtm_cldfr    , rrtm_sw_taucld ,&
3569             rrtm_sw_ssacld , rrtm_sw_asmcld, rrtm_sw_fsfcld, rrtm_cicewp    ,&
3570             rrtm_cliqwp    , rrtm_reice    , rrtm_reliq    , rrtm_sw_tauaer ,&
3571             rrtm_sw_ssaaer , rrtm_sw_asmaer, rrtm_sw_ecaer , rrtm_swuflx    ,&
3572             rrtm_swdflx    , rrtm_swhr     , rrtm_swuflxc  , rrtm_swdflxc   ,&
3573             rrtm_swhrc     , rrtm_dirdflux , rrtm_difdflux )
3574 
3575!
3576!--          Save fluxes:
3577!--          - whole domain
3578             DO k = nzb, nzt+1
3579                rad_sw_in(k,:,:)  = rrtm_swdflx(0,k)
3580                rad_sw_out(k,:,:) = rrtm_swuflx(0,k)
3581             ENDDO
3582!--          - direct and diffuse SW at urban-surface-layer (required by RTM)
3583             rad_sw_in_dir(:,:) = rrtm_dirdflux(0,nzb)
3584             rad_sw_in_diff(:,:) = rrtm_difdflux(0,nzb)
3585
3586!
3587!--          Save heating rates (convert from K/d to K/s)
3588             DO k = nzb+1, nzt+1
3589                rad_sw_hr(k,:,:)     = rrtm_swhr(0,k)  * d_hours_day
3590                rad_sw_cs_hr(k,:,:)  = rrtm_swhrc(0,k) * d_hours_day
3591             ENDDO
3592!
3593!--       Solar radiation is zero during night
3594          ELSE
3595             rad_sw_in  = 0.0_wp
3596             rad_sw_out = 0.0_wp
3597             rad_sw_in_dir(:,:) = 0.0_wp
3598             rad_sw_in_diff(:,:) = 0.0_wp
3599          ENDIF
3600!
3601!--    RRTMG is called for each (j,i) grid point separately, starting at the
3602!--    highest topography level. Here no RTM is used since average_radiation is false
3603       ELSE
3604!
3605!--       Loop over all grid points
3606          DO i = nxl, nxr
3607             DO j = nys, nyn
3608
3609!
3610!--             Prepare profiles of temperature and H2O volume mixing ratio
3611                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
3612                   rrtm_tlev(0,nzb+1) = surf_lsm_h%pt_surface(m) * exner(nzb)
3613                ENDDO
3614                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
3615                   rrtm_tlev(0,nzb+1) = surf_usm_h%pt_surface(m) * exner(nzb)
3616                ENDDO
3617
3618
3619                IF ( bulk_cloud_model )  THEN
3620                   DO k = nzb+1, nzt+1
3621                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)                    &
3622                                        + lv_d_cp * ql(k,j,i)
3623                      rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * (q(k,j,i) - ql(k,j,i))
3624                   ENDDO
3625                ELSEIF ( cloud_droplets )  THEN
3626                   DO k = nzb+1, nzt+1
3627                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)                     &
3628                                        + lv_d_cp * ql(k,j,i)
3629                      rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * q(k,j,i) 
3630                   ENDDO
3631                ELSE
3632                   DO k = nzb+1, nzt+1
3633                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)
3634                   ENDDO
3635
3636                   IF ( humidity )  THEN
3637                      DO k = nzb+1, nzt+1
3638                         rrtm_h2ovmr(0,k) =  mol_mass_air_d_wv * q(k,j,i)
3639                      ENDDO   
3640                   ELSE
3641                      rrtm_h2ovmr(0,nzb+1:nzt+1) = 0.0_wp
3642                   ENDIF
3643                ENDIF
3644
3645!
3646!--             Avoid temperature/humidity jumps at the top of the LES domain by
3647!--             linear interpolation from nzt+2 to nzt+7
3648                DO k = nzt+2, nzt+7
3649                   rrtm_tlay(0,k) = rrtm_tlay(0,nzt+1)                         &
3650                                 + ( rrtm_tlay(0,nzt+8) - rrtm_tlay(0,nzt+1) ) &
3651                                 / ( rrtm_play(0,nzt+8) - rrtm_play(0,nzt+1) ) &
3652                                 * ( rrtm_play(0,k)     - rrtm_play(0,nzt+1) )
3653
3654                   rrtm_h2ovmr(0,k) = rrtm_h2ovmr(0,nzt+1)                     &
3655                              + ( rrtm_h2ovmr(0,nzt+8) - rrtm_h2ovmr(0,nzt+1) )&
3656                              / ( rrtm_play(0,nzt+8)   - rrtm_play(0,nzt+1)   )&
3657                              * ( rrtm_play(0,k)       - rrtm_play(0,nzt+1) )
3658
3659                ENDDO
3660
3661!--             Linear interpolate to zw grid
3662                DO k = nzb+2, nzt+8
3663                   rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k) -     &
3664                                      rrtm_tlay(0,k-1))                        &
3665                                      / ( rrtm_play(0,k) - rrtm_play(0,k-1) )  &
3666                                      * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
3667                ENDDO
3668
3669
3670!
3671!--             Calculate liquid water path and cloud fraction for each column.
3672!--             Note that LWP is required in g/m2 instead of kg/kg m.
3673                rrtm_cldfr  = 0.0_wp
3674                rrtm_reliq  = 0.0_wp
3675                rrtm_cliqwp = 0.0_wp
3676                rrtm_icld   = 0
3677
3678                IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
3679                   DO k = nzb+1, nzt+1
3680                      rrtm_cliqwp(0,k) =  ql(k,j,i) * 1000.0_wp *              &
3681                                          (rrtm_plev(0,k) - rrtm_plev(0,k+1))  &
3682                                          * 100.0_wp / g 
3683
3684                      IF ( rrtm_cliqwp(0,k) > 0.0_wp )  THEN
3685                         rrtm_cldfr(0,k) = 1.0_wp
3686                         IF ( rrtm_icld == 0 )  rrtm_icld = 1
3687
3688!
3689!--                      Calculate cloud droplet effective radius
3690                         IF ( bulk_cloud_model )  THEN
3691!
3692!--                         Calculete effective droplet radius. In case of using
3693!--                         cloud_scheme = 'morrison' and a non reasonable number
3694!--                         of cloud droplets the inital aerosol number 
3695!--                         concentration is considered.
3696                            IF ( microphysics_morrison )  THEN
3697                               IF ( nc(k,j,i) > 1.0E-20_wp )  THEN
3698                                  nc_rad = nc(k,j,i)
3699                               ELSE
3700                                  nc_rad = na_init
3701                               ENDIF
3702                            ELSE
3703                               nc_rad = nc_const
3704                            ENDIF 
3705
3706                            rrtm_reliq(0,k) = 1.0E6_wp * ( 3.0_wp * ql(k,j,i)     &
3707                                              * rho_surface                       &
3708                                              / ( 4.0_wp * pi * nc_rad * rho_l )  &
3709                                              )**0.33333333333333_wp              &
3710                                              * EXP( LOG( sigma_gc )**2 )
3711
3712                         ELSEIF ( cloud_droplets )  THEN
3713                            number_of_particles = prt_count(k,j,i)
3714
3715                            IF (number_of_particles <= 0)  CYCLE
3716                            particles => grid_particles(k,j,i)%particles(1:number_of_particles)
3717                            s_r2 = 0.0_wp
3718                            s_r3 = 0.0_wp
3719
3720                            DO  n = 1, number_of_particles
3721                               IF ( particles(n)%particle_mask )  THEN
3722                                  s_r2 = s_r2 + particles(n)%radius**2 *       &
3723                                         particles(n)%weight_factor
3724                                  s_r3 = s_r3 + particles(n)%radius**3 *       &
3725                                         particles(n)%weight_factor
3726                               ENDIF
3727                            ENDDO
3728
3729                            IF ( s_r2 > 0.0_wp )  rrtm_reliq(0,k) = s_r3 / s_r2
3730
3731                         ENDIF
3732
3733!
3734!--                      Limit effective radius
3735                         IF ( rrtm_reliq(0,k) > 0.0_wp )  THEN
3736                            rrtm_reliq(0,k) = MAX(rrtm_reliq(0,k),2.5_wp)
3737                            rrtm_reliq(0,k) = MIN(rrtm_reliq(0,k),60.0_wp)
3738                        ENDIF
3739                      ENDIF
3740                   ENDDO
3741                ENDIF
3742
3743!
3744!--             Write surface emissivity and surface temperature at current
3745!--             surface element on RRTMG-shaped array.
3746!--             Please note, as RRTMG is a single column model, surface attributes
3747!--             are only obtained from horizontally aligned surfaces (for
3748!--             simplicity). Taking surface attributes from horizontal and
3749!--             vertical walls would lead to multiple solutions. 
3750!--             Moreover, for natural- and urban-type surfaces, several surface
3751!--             classes can exist at a surface element next to each other.
3752!--             To obtain bulk parameters, apply a weighted average for these
3753!--             surfaces.
3754                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
3755                   rrtm_emis = surf_lsm_h%frac(ind_veg_wall,m)  *              &
3756                               surf_lsm_h%emissivity(ind_veg_wall,m)  +        &
3757                               surf_lsm_h%frac(ind_pav_green,m) *              &
3758                               surf_lsm_h%emissivity(ind_pav_green,m) +        & 
3759                               surf_lsm_h%frac(ind_wat_win,m)   *              &
3760                               surf_lsm_h%emissivity(ind_wat_win,m)
3761                   rrtm_tsfc = surf_lsm_h%pt_surface(m) * exner(nzb)
3762                ENDDO             
3763                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
3764                   rrtm_emis = surf_usm_h%frac(ind_veg_wall,m)  *              &
3765                               surf_usm_h%emissivity(ind_veg_wall,m)  +        &
3766                               surf_usm_h%frac(ind_pav_green,m) *              &
3767                               surf_usm_h%emissivity(ind_pav_green,m) +        & 
3768                               surf_usm_h%frac(ind_wat_win,m)   *              &
3769                               surf_usm_h%emissivity(ind_wat_win,m)
3770                   rrtm_tsfc = surf_usm_h%pt_surface(m) * exner(nzb)
3771                ENDDO
3772!
3773!--             Obtain topography top index (lower bound of RRTMG)
3774                k_topo = get_topography_top_index_ji( j, i, 's' )
3775
3776                IF ( lw_radiation )  THEN
3777!
3778!--                Due to technical reasons, copy optical depth to dummy arguments
3779!--                which are allocated on the exact size as the rrtmg_lw is called.
3780!--                As one dimesion is allocated with zero size, compiler complains
3781!--                that rank of the array does not match that of the
3782!--                assumed-shaped arguments in the RRTMG library. In order to
3783!--                avoid this, write to dummy arguments and give pass the entire
3784!--                dummy array. Seems to be the only existing work-around. 
3785                   ALLOCATE( rrtm_lw_taucld_dum(1:nbndlw+1,0:0,k_topo+1:nzt_rad+1) )
3786                   ALLOCATE( rrtm_lw_tauaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndlw+1) )
3787
3788                   rrtm_lw_taucld_dum =                                        &
3789                               rrtm_lw_taucld(1:nbndlw+1,0:0,k_topo+1:nzt_rad+1)
3790                   rrtm_lw_tauaer_dum =                                        &
3791                               rrtm_lw_tauaer(0:0,k_topo+1:nzt_rad+1,1:nbndlw+1)
3792
3793                   CALL rrtmg_lw( 1,                                           &                                       
3794                                  nzt_rad-k_topo,                              &
3795                                  rrtm_icld,                                   &
3796                                  rrtm_idrv,                                   &
3797                                  rrtm_play(:,k_topo+1:nzt_rad+1),             &
3798                                  rrtm_plev(:,k_topo+1:nzt_rad+2),             &
3799                                  rrtm_tlay(:,k_topo+1:nzt_rad+1),             &
3800                                  rrtm_tlev(:,k_topo+1:nzt_rad+2),             &
3801                                  rrtm_tsfc,                                   &
3802                                  rrtm_h2ovmr(:,k_topo+1:nzt_rad+1),           &
3803                                  rrtm_o3vmr(:,k_topo+1:nzt_rad+1),            &
3804                                  rrtm_co2vmr(:,k_topo+1:nzt_rad+1),           &
3805                                  rrtm_ch4vmr(:,k_topo+1:nzt_rad+1),           &
3806                                  rrtm_n2ovmr(:,k_topo+1:nzt_rad+1),           &
3807                                  rrtm_o2vmr(:,k_topo+1:nzt_rad+1),            &
3808                                  rrtm_cfc11vmr(:,k_topo+1:nzt_rad+1),         &
3809                                  rrtm_cfc12vmr(:,k_topo+1:nzt_rad+1),         &
3810                                  rrtm_cfc22vmr(:,k_topo+1:nzt_rad+1),         &
3811                                  rrtm_ccl4vmr(:,k_topo+1:nzt_rad+1),          &
3812                                  rrtm_emis,                                   &
3813                                  rrtm_inflglw,                                &
3814                                  rrtm_iceflglw,                               &
3815                                  rrtm_liqflglw,                               &
3816                                  rrtm_cldfr(:,k_topo+1:nzt_rad+1),            &
3817                                  rrtm_lw_taucld_dum,                          &
3818                                  rrtm_cicewp(:,k_topo+1:nzt_rad+1),           &
3819                                  rrtm_cliqwp(:,k_topo+1:nzt_rad+1),           &
3820                                  rrtm_reice(:,k_topo+1:nzt_rad+1),            & 
3821                                  rrtm_reliq(:,k_topo+1:nzt_rad+1),            &
3822                                  rrtm_lw_tauaer_dum,                          &
3823                                  rrtm_lwuflx(:,k_topo:nzt_rad+1),             &
3824                                  rrtm_lwdflx(:,k_topo:nzt_rad+1),             &
3825                                  rrtm_lwhr(:,k_topo+1:nzt_rad+1),             &
3826                                  rrtm_lwuflxc(:,k_topo:nzt_rad+1),            &
3827                                  rrtm_lwdflxc(:,k_topo:nzt_rad+1),            &
3828                                  rrtm_lwhrc(:,k_topo+1:nzt_rad+1),            &
3829                                  rrtm_lwuflx_dt(:,k_topo:nzt_rad+1),          &
3830                                  rrtm_lwuflxc_dt(:,k_topo:nzt_rad+1) )
3831
3832                   DEALLOCATE ( rrtm_lw_taucld_dum )
3833                   DEALLOCATE ( rrtm_lw_tauaer_dum )
3834!
3835!--                Save fluxes
3836                   DO k = k_topo, nzt+1
3837                      rad_lw_in(k,j,i)  = rrtm_lwdflx(0,k)
3838                      rad_lw_out(k,j,i) = rrtm_lwuflx(0,k)
3839                   ENDDO
3840
3841!
3842!--                Save heating rates (convert from K/d to K/h)
3843                   DO k = k_topo+1, nzt+1
3844                      rad_lw_hr(k,j,i)     = rrtm_lwhr(0,k-k_topo)  * d_hours_day
3845                      rad_lw_cs_hr(k,j,i)  = rrtm_lwhrc(0,k-k_topo) * d_hours_day
3846                   ENDDO
3847
3848!
3849!--                Save surface radiative fluxes and change in LW heating rate
3850!--                onto respective surface elements
3851!--                Horizontal surfaces
3852                   DO  m = surf_lsm_h%start_index(j,i),                        &
3853                           surf_lsm_h%end_index(j,i)
3854                      surf_lsm_h%rad_lw_in(m)           = rrtm_lwdflx(0,k_topo)
3855                      surf_lsm_h%rad_lw_out(m)          = rrtm_lwuflx(0,k_topo)
3856                      surf_lsm_h%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k_topo)
3857                   ENDDO             
3858                   DO  m = surf_usm_h%start_index(j,i),                        &
3859                           surf_usm_h%end_index(j,i)
3860                      surf_usm_h%rad_lw_in(m)           = rrtm_lwdflx(0,k_topo)
3861                      surf_usm_h%rad_lw_out(m)          = rrtm_lwuflx(0,k_topo)
3862                      surf_usm_h%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k_topo)
3863                   ENDDO 
3864!
3865!--                Vertical surfaces. Fluxes are obtain at vertical level of the
3866!--                respective surface element
3867                   DO  l = 0, 3
3868                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
3869                              surf_lsm_v(l)%end_index(j,i)
3870                         k                                    = surf_lsm_v(l)%k(m)
3871                         surf_lsm_v(l)%rad_lw_in(m)           = rrtm_lwdflx(0,k)
3872                         surf_lsm_v(l)%rad_lw_out(m)          = rrtm_lwuflx(0,k)
3873                         surf_lsm_v(l)%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k)
3874                      ENDDO             
3875                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
3876                              surf_usm_v(l)%end_index(j,i)
3877                         k                                    = surf_usm_v(l)%k(m)
3878                         surf_usm_v(l)%rad_lw_in(m)           = rrtm_lwdflx(0,k)
3879                         surf_usm_v(l)%rad_lw_out(m)          = rrtm_lwuflx(0,k)
3880                         surf_usm_v(l)%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k)
3881                      ENDDO 
3882                   ENDDO
3883
3884                ENDIF
3885
3886                IF ( sw_radiation .AND. sun_up )  THEN
3887!
3888!--                Get albedo for direct/diffusive long/shortwave radiation at
3889!--                current (y,x)-location from surface variables.
3890!--                Only obtain it from horizontal surfaces, as RRTMG is a single
3891!--                column model
3892!--                (Please note, only one loop will entered, controlled by
3893!--                start-end index.)
3894                   DO  m = surf_lsm_h%start_index(j,i),                        &
3895                           surf_lsm_h%end_index(j,i)
3896                      rrtm_asdir(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3897                                            surf_lsm_h%rrtm_asdir(:,m) )
3898                      rrtm_asdif(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3899                                            surf_lsm_h%rrtm_asdif(:,m) )
3900                      rrtm_aldir(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3901                                            surf_lsm_h%rrtm_aldir(:,m) )
3902                      rrtm_aldif(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3903                                            surf_lsm_h%rrtm_aldif(:,m) )
3904                   ENDDO             
3905                   DO  m = surf_usm_h%start_index(j,i),                        &
3906                           surf_usm_h%end_index(j,i)
3907                      rrtm_asdir(1)  = SUM( surf_usm_h%frac(:,m) *             &
3908                                            surf_usm_h%rrtm_asdir(:,m) )
3909                      rrtm_asdif(1)  = SUM( surf_usm_h%frac(:,m) *             &
3910                                            surf_usm_h%rrtm_asdif(:,m) )
3911                      rrtm_aldir(1)  = SUM( surf_usm_h%frac(:,m) *             &
3912                                            surf_usm_h%rrtm_aldir(:,m) )
3913                      rrtm_aldif(1)  = SUM( surf_usm_h%frac(:,m) *             &
3914                                            surf_usm_h%rrtm_aldif(:,m) )
3915                   ENDDO
3916!
3917!--                Due to technical reasons, copy optical depths and other
3918!--                to dummy arguments which are allocated on the exact size as the
3919!--                rrtmg_sw is called.
3920!--                As one dimesion is allocated with zero size, compiler complains
3921!--                that rank of the array does not match that of the
3922!--                assumed-shaped arguments in the RRTMG library. In order to
3923!--                avoid this, write to dummy arguments and give pass the entire
3924!--                dummy array. Seems to be the only existing work-around. 
3925                   ALLOCATE( rrtm_sw_taucld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3926                   ALLOCATE( rrtm_sw_ssacld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3927                   ALLOCATE( rrtm_sw_asmcld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3928                   ALLOCATE( rrtm_sw_fsfcld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3929                   ALLOCATE( rrtm_sw_tauaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3930                   ALLOCATE( rrtm_sw_ssaaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3931                   ALLOCATE( rrtm_sw_asmaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3932                   ALLOCATE( rrtm_sw_ecaer_dum(0:0,k_topo+1:nzt_rad+1,1:naerec+1)  )
3933     
3934                   rrtm_sw_taucld_dum = rrtm_sw_taucld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3935                   rrtm_sw_ssacld_dum = rrtm_sw_ssacld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3936                   rrtm_sw_asmcld_dum = rrtm_sw_asmcld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3937                   rrtm_sw_fsfcld_dum = rrtm_sw_fsfcld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3938                   rrtm_sw_tauaer_dum = rrtm_sw_tauaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3939                   rrtm_sw_ssaaer_dum = rrtm_sw_ssaaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3940                   rrtm_sw_asmaer_dum = rrtm_sw_asmaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3941                   rrtm_sw_ecaer_dum  = rrtm_sw_ecaer(0:0,k_topo+1:nzt_rad+1,1:naerec+1)
3942
3943                   CALL rrtmg_sw( 1,                                           &
3944                                  nzt_rad-k_topo,                              &
3945                                  rrtm_icld,                                   &
3946                                  rrtm_iaer,                                   &
3947                                  rrtm_play(:,k_topo+1:nzt_rad+1),             &
3948                                  rrtm_plev(:,k_topo+1:nzt_rad+2),             &
3949                                  rrtm_tlay(:,k_topo+1:nzt_rad+1),             &
3950                                  rrtm_tlev(:,k_topo+1:nzt_rad+2),             &
3951                                  rrtm_tsfc,                                   &
3952                                  rrtm_h2ovmr(:,k_topo+1:nzt_rad+1),           &                               
3953                                  rrtm_o3vmr(:,k_topo+1:nzt_rad+1),            &       
3954                                  rrtm_co2vmr(:,k_topo+1:nzt_rad+1),           &
3955                                  rrtm_ch4vmr(:,k_topo+1:nzt_rad+1),           &
3956                                  rrtm_n2ovmr(:,k_topo+1:nzt_rad+1),           &
3957                                  rrtm_o2vmr(:,k_topo+1:nzt_rad+1),            &
3958                                  rrtm_asdir,                                  & 
3959                                  rrtm_asdif,                                  &
3960                                  rrtm_aldir,                                  &
3961                                  rrtm_aldif,                                  &
3962                                  zenith,                                      &
3963                                  0.0_wp,                                      &
3964                                  day_of_year,                                 &
3965                                  solar_constant,                              &
3966                                  rrtm_inflgsw,                                &
3967                                  rrtm_iceflgsw,                               &
3968                                  rrtm_liqflgsw,                               &
3969                                  rrtm_cldfr(:,k_topo+1:nzt_rad+1),            &
3970                                  rrtm_sw_taucld_dum,                          &
3971                                  rrtm_sw_ssacld_dum,                          &
3972                                  rrtm_sw_asmcld_dum,                          &
3973                                  rrtm_sw_fsfcld_dum,                          &
3974                                  rrtm_cicewp(:,k_topo+1:nzt_rad+1),           &
3975                                  rrtm_cliqwp(:,k_topo+1:nzt_rad+1),           &
3976                                  rrtm_reice(:,k_topo+1:nzt_rad+1),            &
3977                                  rrtm_reliq(:,k_topo+1:nzt_rad+1),            &
3978                                  rrtm_sw_tauaer_dum,                          &
3979                                  rrtm_sw_ssaaer_dum,                          &
3980                                  rrtm_sw_asmaer_dum,                          &
3981                                  rrtm_sw_ecaer_dum,                           &
3982                                  rrtm_swuflx(:,k_topo:nzt_rad+1),             & 
3983                                  rrtm_swdflx(:,k_topo:nzt_rad+1),             & 
3984                                  rrtm_swhr(:,k_topo+1:nzt_rad+1),             & 
3985                                  rrtm_swuflxc(:,k_topo:nzt_rad+1),            & 
3986                                  rrtm_swdflxc(:,k_topo:nzt_rad+1),            &
3987                                  rrtm_swhrc(:,k_topo+1:nzt_rad+1),            &
3988                                  rrtm_dirdflux(:,k_topo:nzt_rad+1),           &
3989                                  rrtm_difdflux(:,k_topo:nzt_rad+1) )
3990
3991                   DEALLOCATE( rrtm_sw_taucld_dum )
3992                   DEALLOCATE( rrtm_sw_ssacld_dum )
3993                   DEALLOCATE( rrtm_sw_asmcld_dum )
3994                   DEALLOCATE( rrtm_sw_fsfcld_dum )
3995                   DEALLOCATE( rrtm_sw_tauaer_dum )
3996                   DEALLOCATE( rrtm_sw_ssaaer_dum )
3997                   DEALLOCATE( rrtm_sw_asmaer_dum )
3998                   DEALLOCATE( rrtm_sw_ecaer_dum )
3999!
4000!--                Save fluxes
4001                   DO k = nzb, nzt+1
4002                      rad_sw_in(k,j,i)  = rrtm_swdflx(0,k)
4003                      rad_sw_out(k,j,i) = rrtm_swuflx(0,k)
4004                   ENDDO
4005!
4006!--                Save heating rates (convert from K/d to K/s)
4007                   DO k = nzb+1, nzt+1
4008                      rad_sw_hr(k,j,i)     = rrtm_swhr(0,k)  * d_hours_day
4009                      rad_sw_cs_hr(k,j,i)  = rrtm_swhrc(0,k) * d_hours_day
4010                   ENDDO
4011
4012!
4013!--                Save surface radiative fluxes onto respective surface elements
4014!--                Horizontal surfaces
4015                   DO  m = surf_lsm_h%start_index(j,i),                        &
4016                           surf_lsm_h%end_index(j,i)
4017                      surf_lsm_h%rad_sw_in(m)     = rrtm_swdflx(0,k_topo)
4018                      surf_lsm_h%rad_sw_out(m)    = rrtm_swuflx(0,k_topo)
4019                   ENDDO             
4020                   DO  m = surf_usm_h%start_index(j,i),                        &
4021                           surf_usm_h%end_index(j,i)
4022                      surf_usm_h%rad_sw_in(m)     = rrtm_swdflx(0,k_topo)
4023                      surf_usm_h%rad_sw_out(m)    = rrtm_swuflx(0,k_topo)
4024                   ENDDO 
4025!
4026!--                Vertical surfaces. Fluxes are obtain at respective vertical
4027!--                level of the surface element
4028                   DO  l = 0, 3
4029                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
4030                              surf_lsm_v(l)%end_index(j,i)
4031                         k                           = surf_lsm_v(l)%k(m)
4032                         surf_lsm_v(l)%rad_sw_in(m)  = rrtm_swdflx(0,k)
4033                         surf_lsm_v(l)%rad_sw_out(m) = rrtm_swuflx(0,k)
4034                      ENDDO             
4035                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
4036                              surf_usm_v(l)%end_index(j,i)
4037                         k                           = surf_usm_v(l)%k(m)
4038                         surf_usm_v(l)%rad_sw_in(m)  = rrtm_swdflx(0,k)
4039                         surf_usm_v(l)%rad_sw_out(m) = rrtm_swuflx(0,k)
4040                      ENDDO 
4041                   ENDDO
4042!
4043!--             Solar radiation is zero during night
4044                ELSE
4045                   rad_sw_in  = 0.0_wp
4046                   rad_sw_out = 0.0_wp
4047!--             !!!!!!!! ATTENSION !!!!!!!!!!!!!!!
4048!--             Surface radiative fluxes should be also set to zero here                 
4049!--                Save surface radiative fluxes onto respective surface elements
4050!--                Horizontal surfaces
4051                   DO  m = surf_lsm_h%start_index(j,i),                        &
4052                           surf_lsm_h%end_index(j,i)
4053                      surf_lsm_h%rad_sw_in(m)     = 0.0_wp
4054                      surf_lsm_h%rad_sw_out(m)    = 0.0_wp
4055                   ENDDO             
4056                   DO  m = surf_usm_h%start_index(j,i),                        &
4057                           surf_usm_h%end_index(j,i)
4058                      surf_usm_h%rad_sw_in(m)     = 0.0_wp
4059                      surf_usm_h%rad_sw_out(m)    = 0.0_wp
4060                   ENDDO 
4061!
4062!--                Vertical surfaces. Fluxes are obtain at respective vertical
4063!--                level of the surface element
4064                   DO  l = 0, 3
4065                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
4066                              surf_lsm_v(l)%end_index(j,i)
4067                         k                           = surf_lsm_v(l)%k(m)
4068                         surf_lsm_v(l)%rad_sw_in(m)  = 0.0_wp
4069                         surf_lsm_v(l)%rad_sw_out(m) = 0.0_wp
4070                      ENDDO             
4071                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
4072                              surf_usm_v(l)%end_index(j,i)
4073                         k                           = surf_usm_v(l)%k(m)
4074                         surf_usm_v(l)%rad_sw_in(m)  = 0.0_wp
4075                         surf_usm_v(l)%rad_sw_out(m) = 0.0_wp
4076                      ENDDO 
4077                   ENDDO
4078                ENDIF
4079
4080             ENDDO
4081          ENDDO
4082
4083       ENDIF
4084!
4085!--    Finally, calculate surface net radiation for surface elements.
4086       IF (  .NOT.  radiation_interactions  ) THEN
4087!--       First, for horizontal surfaces   
4088          DO  m = 1, surf_lsm_h%ns
4089             surf_lsm_h%rad_net(m) = surf_lsm_h%rad_sw_in(m)                   &
4090                                   - surf_lsm_h%rad_sw_out(m)                  &
4091                                   + surf_lsm_h%rad_lw_in(m)                   &
4092                                   - surf_lsm_h%rad_lw_out(m)
4093          ENDDO
4094          DO  m = 1, surf_usm_h%ns
4095             surf_usm_h%rad_net(m) = surf_usm_h%rad_sw_in(m)                   &
4096                                   - surf_usm_h%rad_sw_out(m)                  &
4097                                   + surf_usm_h%rad_lw_in(m)                   &
4098                                   - surf_usm_h%rad_lw_out(m)
4099          ENDDO
4100!
4101!--       Vertical surfaces.
4102!--       Todo: weight with azimuth and zenith angle according to their orientation!
4103          DO  l = 0, 3     
4104             DO  m = 1, surf_lsm_v(l)%ns
4105                surf_lsm_v(l)%rad_net(m) = surf_lsm_v(l)%rad_sw_in(m)          &
4106                                         - surf_lsm_v(l)%rad_sw_out(m)         &
4107                                         + surf_lsm_v(l)%rad_lw_in(m)          &
4108                                         - surf_lsm_v(l)%rad_lw_out(m)
4109             ENDDO
4110             DO  m = 1, surf_usm_v(l)%ns
4111                surf_usm_v(l)%rad_net(m) = surf_usm_v(l)%rad_sw_in(m)          &
4112                                         - surf_usm_v(l)%rad_sw_out(m)         &
4113                                         + surf_usm_v(l)%rad_lw_in(m)          &
4114                                         - surf_usm_v(l)%rad_lw_out(m)
4115             ENDDO
4116          ENDDO
4117       ENDIF
4118
4119
4120       CALL exchange_horiz( rad_lw_in,  nbgp )
4121       CALL exchange_horiz( rad_lw_out, nbgp )
4122       CALL exchange_horiz( rad_lw_hr,    nbgp )
4123       CALL exchange_horiz( rad_lw_cs_hr, nbgp )
4124
4125       CALL exchange_horiz( rad_sw_in,  nbgp )
4126       CALL exchange_horiz( rad_sw_out, nbgp ) 
4127       CALL exchange_horiz( rad_sw_hr,    nbgp )
4128       CALL exchange_horiz( rad_sw_cs_hr, nbgp )
4129
4130#endif
4131
4132    END SUBROUTINE radiation_rrtmg
4133
4134
4135!------------------------------------------------------------------------------!
4136! Description:
4137! ------------
4138!> Calculate the cosine of the zenith angle (variable is called zenith)
4139!------------------------------------------------------------------------------!
4140    SUBROUTINE calc_zenith
4141
4142       IMPLICIT NONE
4143
4144       REAL(wp) ::  declination,  & !< solar declination angle
4145                    hour_angle      !< solar hour angle
4146!
4147!--    Calculate current day and time based on the initial values and simulation
4148!--    time
4149       CALL calc_date_and_time
4150
4151!
4152!--    Calculate solar declination and hour angle   
4153       declination = ASIN( decl_1 * SIN(decl_2 * REAL(day_of_year, KIND=wp) - decl_3) )
4154       hour_angle  = 2.0_wp * pi * (time_utc / 86400.0_wp) + lon - pi
4155
4156!
4157!--    Calculate cosine of solar zenith angle
4158       zenith(0) = SIN(lat) * SIN(declination) + COS(lat) * COS(declination)   &
4159                                            * COS(hour_angle)
4160       zenith(0) = MAX(0.0_wp,zenith(0))
4161
4162!
4163!--    Calculate solar directional vector
4164       IF ( sun_direction )  THEN
4165
4166!
4167!--       Direction in longitudes equals to sin(solar_azimuth) * sin(zenith)
4168          sun_dir_lon(0) = -SIN(hour_angle) * COS(declination)
4169
4170!
4171!--       Direction in latitues equals to cos(solar_azimuth) * sin(zenith)
4172          sun_dir_lat(0) = SIN(declination) * COS(lat) - COS(hour_angle) &
4173                              * COS(declination) * SIN(lat)
4174       ENDIF
4175
4176!
4177!--    Check if the sun is up (otheriwse shortwave calculations can be skipped)
4178       IF ( zenith(0) > 0.0_wp )  THEN
4179          sun_up = .TRUE.
4180       ELSE
4181          sun_up = .FALSE.
4182       END IF
4183
4184    END SUBROUTINE calc_zenith
4185
4186#if defined ( __rrtmg ) && defined ( __netcdf )
4187!------------------------------------------------------------------------------!
4188! Description:
4189! ------------
4190!> Calculates surface albedo components based on Briegleb (1992) and
4191!> Briegleb et al. (1986)
4192!------------------------------------------------------------------------------!
4193    SUBROUTINE calc_albedo( surf )
4194
4195        IMPLICIT NONE
4196
4197        INTEGER(iwp)    ::  ind_type !< running index surface tiles
4198        INTEGER(iwp)    ::  m        !< running index surface elements
4199
4200        TYPE(surf_type) ::  surf !< treated surfaces
4201
4202        IF ( sun_up  .AND.  .NOT. average_radiation )  THEN
4203
4204           DO  m = 1, surf%ns
4205!
4206!--           Loop over surface elements
4207              DO  ind_type = 0, SIZE( surf%albedo_type, 1 ) - 1
4208           
4209!
4210!--              Ocean
4211                 IF ( surf%albedo_type(ind_type,m) == 1 )  THEN
4212                    surf%rrtm_aldir(ind_type,m) = 0.026_wp /                    &
4213                                                ( zenith(0)**1.7_wp + 0.065_wp )&
4214                                     + 0.15_wp * ( zenith(0) - 0.1_wp )         &
4215                                               * ( zenith(0) - 0.5_wp )         &
4216                                               * ( zenith(0) - 1.0_wp )
4217                    surf%rrtm_asdir(ind_type,m) = surf%rrtm_aldir(ind_type,m)
4218!
4219!--              Snow
4220                 ELSEIF ( surf%albedo_type(ind_type,m) == 16 )  THEN
4221                    IF ( zenith(0) < 0.5_wp )  THEN
4222                       surf%rrtm_aldir(ind_type,m) =                           &
4223                                 0.5_wp * ( 1.0_wp - surf%aldif(ind_type,m) )  &
4224                                        * ( 3.0_wp / ( 1.0_wp + 4.0_wp         &
4225                                        * zenith(0) ) ) - 1.0_wp
4226                       surf%rrtm_asdir(ind_type,m) =                           &
4227                                 0.5_wp * ( 1.0_wp - surf%asdif(ind_type,m) )  &
4228                                        * ( 3.0_wp / ( 1.0_wp + 4.0_wp         &
4229                                        * zenith(0) ) ) - 1.0_wp
4230
4231                       surf%rrtm_aldir(ind_type,m) =                           &
4232                                       MIN(0.98_wp, surf%rrtm_aldir(ind_type,m))
4233                       surf%rrtm_asdir(ind_type,m) =                           &
4234                                       MIN(0.98_wp, surf%rrtm_asdir(ind_type,m))
4235                    ELSE
4236                       surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4237                       surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4238                    ENDIF
4239!
4240!--              Sea ice
4241                 ELSEIF ( surf%albedo_type(ind_type,m) == 15 )  THEN
4242                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4243                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4244
4245!
4246!--              Asphalt
4247                 ELSEIF ( surf%albedo_type(ind_type,m) == 17 )  THEN
4248                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4249                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4250
4251
4252!
4253!--              Bare soil
4254                 ELSEIF ( surf%albedo_type(ind_type,m) == 18 )  THEN
4255                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4256                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4257
4258!
4259!--              Land surfaces
4260                 ELSE
4261                    SELECT CASE ( surf%albedo_type(ind_type,m) )
4262
4263!
4264!--                    Surface types with strong zenith dependence
4265                       CASE ( 1, 2, 3, 4, 11, 12, 13 )
4266                          surf%rrtm_aldir(ind_type,m) =                        &
4267                                surf%aldif(ind_type,m) * 1.4_wp /              &
4268                                           ( 1.0_wp + 0.8_wp * zenith(0) )
4269                          surf%rrtm_asdir(ind_type,m) =                        &
4270                                surf%asdif(ind_type,m) * 1.4_wp /              &
4271                                           ( 1.0_wp + 0.8_wp * zenith(0) )
4272!
4273!--                    Surface types with weak zenith dependence
4274                       CASE ( 5, 6, 7, 8, 9, 10, 14 )
4275                          surf%rrtm_aldir(ind_type,m) =                        &
4276                                surf%aldif(ind_type,m) * 1.1_wp /              &
4277                                           ( 1.0_wp + 0.2_wp * zenith(0) )
4278                          surf%rrtm_asdir(ind_type,m) =                        &
4279                                surf%asdif(ind_type,m) * 1.1_wp /              &
4280                                           ( 1.0_wp + 0.2_wp * zenith(0) )
4281
4282                       CASE DEFAULT
4283
4284                    END SELECT
4285                 ENDIF
4286!
4287!--              Diffusive albedo is taken from Table 2
4288                 surf%rrtm_aldif(ind_type,m) = surf%aldif(ind_type,m)
4289                 surf%rrtm_asdif(ind_type,m) = surf%asdif(ind_type,m)
4290              ENDDO
4291           ENDDO
4292!
4293!--     Set albedo in case of average radiation
4294        ELSEIF ( sun_up  .AND.  average_radiation )  THEN
4295           surf%rrtm_asdir = albedo_urb
4296           surf%rrtm_asdif = albedo_urb
4297           surf%rrtm_aldir = albedo_urb
4298           surf%rrtm_aldif = albedo_urb 
4299!
4300!--     Darkness
4301        ELSE
4302           surf%rrtm_aldir = 0.0_wp
4303           surf%rrtm_asdir = 0.0_wp
4304           surf%rrtm_aldif = 0.0_wp
4305           surf%rrtm_asdif = 0.0_wp
4306        ENDIF
4307
4308    END SUBROUTINE calc_albedo
4309
4310!------------------------------------------------------------------------------!
4311! Description:
4312! ------------
4313!> Read sounding data (pressure and temperature) from RADIATION_DATA.
4314!------------------------------------------------------------------------------!
4315    SUBROUTINE read_sounding_data
4316
4317       IMPLICIT NONE
4318
4319       INTEGER(iwp) :: id,           & !< NetCDF id of input file
4320                       id_dim_zrad,  & !< pressure level id in the NetCDF file
4321                       id_var,       & !< NetCDF variable id
4322                       k,            & !< loop index
4323                       nz_snd,       & !< number of vertical levels in the sounding data
4324                       nz_snd_start, & !< start vertical index for sounding data to be used
4325                       nz_snd_end      !< end vertical index for souding data to be used
4326
4327       REAL(wp) :: t_surface           !< actual surface temperature
4328
4329       REAL(wp), DIMENSION(:), ALLOCATABLE ::  hyp_snd_tmp, & !< temporary hydrostatic pressure profile (sounding)
4330                                               t_snd_tmp      !< temporary temperature profile (sounding)
4331
4332!
4333!--    In case of updates, deallocate arrays first (sufficient to check one
4334!--    array as the others are automatically allocated). This is required
4335!--    because nzt_rad might change during the update
4336       IF ( ALLOCATED ( hyp_snd ) )  THEN
4337          DEALLOCATE( hyp_snd )
4338          DEALLOCATE( t_snd )
4339          DEALLOCATE ( rrtm_play )
4340          DEALLOCATE ( rrtm_plev )
4341          DEALLOCATE ( rrtm_tlay )
4342          DEALLOCATE ( rrtm_tlev )
4343
4344          DEALLOCATE ( rrtm_cicewp )
4345          DEALLOCATE ( rrtm_cldfr )
4346          DEALLOCATE ( rrtm_cliqwp )
4347          DEALLOCATE ( rrtm_reice )
4348          DEALLOCATE ( rrtm_reliq )
4349          DEALLOCATE ( rrtm_lw_taucld )
4350          DEALLOCATE ( rrtm_lw_tauaer )
4351
4352          DEALLOCATE ( rrtm_lwdflx  )
4353          DEALLOCATE ( rrtm_lwdflxc )
4354          DEALLOCATE ( rrtm_lwuflx  )
4355          DEALLOCATE ( rrtm_lwuflxc )
4356          DEALLOCATE ( rrtm_lwuflx_dt )
4357          DEALLOCATE ( rrtm_lwuflxc_dt )
4358          DEALLOCATE ( rrtm_lwhr  )
4359          DEALLOCATE ( rrtm_lwhrc )
4360
4361          DEALLOCATE ( rrtm_sw_taucld )
4362          DEALLOCATE ( rrtm_sw_ssacld )
4363          DEALLOCATE ( rrtm_sw_asmcld )
4364          DEALLOCATE ( rrtm_sw_fsfcld )
4365          DEALLOCATE ( rrtm_sw_tauaer )
4366          DEALLOCATE ( rrtm_sw_ssaaer )
4367          DEALLOCATE ( rrtm_sw_asmaer ) 
4368          DEALLOCATE ( rrtm_sw_ecaer )   
4369 
4370          DEALLOCATE ( rrtm_swdflx  )
4371          DEALLOCATE ( rrtm_swdflxc )
4372          DEALLOCATE ( rrtm_swuflx  )
4373          DEALLOCATE ( rrtm_swuflxc )
4374          DEALLOCATE ( rrtm_swhr  )
4375          DEALLOCATE ( rrtm_swhrc )
4376          DEALLOCATE ( rrtm_dirdflux )
4377          DEALLOCATE ( rrtm_difdflux )
4378
4379       ENDIF
4380
4381!
4382!--    Open file for reading
4383       nc_stat = NF90_OPEN( rrtm_input_file, NF90_NOWRITE, id )
4384       CALL netcdf_handle_error_rad( 'read_sounding_data', 549 )
4385
4386!
4387!--    Inquire dimension of z axis and save in nz_snd
4388       nc_stat = NF90_INQ_DIMID( id, "Pressure", id_dim_zrad )
4389       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim_zrad, len = nz_snd )
4390       CALL netcdf_handle_error_rad( 'read_sounding_data', 551 )
4391
4392!
4393! !--    Allocate temporary array for storing pressure data
4394       ALLOCATE( hyp_snd_tmp(1:nz_snd) )
4395       hyp_snd_tmp = 0.0_wp
4396
4397
4398!--    Read pressure from file
4399       nc_stat = NF90_INQ_VARID( id, "Pressure", id_var )
4400       nc_stat = NF90_GET_VAR( id, id_var, hyp_snd_tmp(:), start = (/1/),      &
4401                               count = (/nz_snd/) )
4402       CALL netcdf_handle_error_rad( 'read_sounding_data', 552 )
4403
4404!
4405!--    Allocate temporary array for storing temperature data
4406       ALLOCATE( t_snd_tmp(1:nz_snd) )
4407       t_snd_tmp = 0.0_wp
4408
4409!
4410!--    Read temperature from file
4411       nc_stat = NF90_INQ_VARID( id, "ReferenceTemperature", id_var )
4412       nc_stat = NF90_GET_VAR( id, id_var, t_snd_tmp(:), start = (/1/),        &
4413                               count = (/nz_snd/) )
4414       CALL netcdf_handle_error_rad( 'read_sounding_data', 553 )
4415
4416!
4417!--    Calculate start of sounding data
4418       nz_snd_start = nz_snd + 1
4419       nz_snd_end   = nz_snd + 1
4420
4421!
4422!--    Start filling vertical dimension at 10hPa above the model domain (hyp is
4423!--    in Pa, hyp_snd in hPa).
4424       DO  k = 1, nz_snd
4425          IF ( hyp_snd_tmp(k) < ( hyp(nzt+1) - 1000.0_wp) * 0.01_wp )  THEN
4426             nz_snd_start = k
4427             EXIT
4428          END IF
4429       END DO
4430
4431       IF ( nz_snd_start <= nz_snd )  THEN
4432          nz_snd_end = nz_snd
4433       END IF
4434
4435
4436!
4437!--    Calculate of total grid points for RRTMG calculations
4438       nzt_rad = nzt + nz_snd_end - nz_snd_start + 1
4439
4440!
4441!--    Save data above LES domain in hyp_snd, t_snd
4442       ALLOCATE( hyp_snd(nzb+1:nzt_rad) )
4443       ALLOCATE( t_snd(nzb+1:nzt_rad)   )
4444       hyp_snd = 0.0_wp
4445       t_snd = 0.0_wp
4446
4447       hyp_snd(nzt+2:nzt_rad) = hyp_snd_tmp(nz_snd_start+1:nz_snd_end)
4448       t_snd(nzt+2:nzt_rad)   = t_snd_tmp(nz_snd_start+1:nz_snd_end)
4449
4450       nc_stat = NF90_CLOSE( id )
4451
4452!
4453!--    Calculate pressure levels on zu and zw grid. Sounding data is added at
4454!--    top of the LES domain. This routine does not consider horizontal or
4455!--    vertical variability of pressure and temperature
4456       ALLOCATE ( rrtm_play(0:0,nzb+1:nzt_rad+1)   )
4457       ALLOCATE ( rrtm_plev(0:0,nzb+1:nzt_rad+2)   )
4458
4459       t_surface = pt_surface * exner(nzb)
4460       DO k = nzb+1, nzt+1
4461          rrtm_play(0,k) = hyp(k) * 0.01_wp
4462          rrtm_plev(0,k) = barometric_formula(zw(k-1),                         &
4463                              pt_surface * exner(nzb), &
4464                              surface_pressure )
4465       ENDDO
4466
4467       DO k = nzt+2, nzt_rad
4468          rrtm_play(0,k) = hyp_snd(k)
4469          rrtm_plev(0,k) = 0.5_wp * ( rrtm_play(0,k) + rrtm_play(0,k-1) )
4470       ENDDO
4471       rrtm_plev(0,nzt_rad+1) = MAX( 0.5 * hyp_snd(nzt_rad),                   &
4472                                   1.5 * hyp_snd(nzt_rad)                      &
4473                                 - 0.5 * hyp_snd(nzt_rad-1) )
4474       rrtm_plev(0,nzt_rad+2)  = MIN( 1.0E-4_wp,                               &
4475                                      0.25_wp * rrtm_plev(0,nzt_rad+1) )
4476
4477       rrtm_play(0,nzt_rad+1) = 0.5 * rrtm_plev(0,nzt_rad+1)
4478
4479!
4480!--    Calculate temperature/humidity levels at top of the LES domain.
4481!--    Currently, the temperature is taken from sounding data (might lead to a
4482!--    temperature jump at interface. To do: Humidity is currently not
4483!--    calculated above the LES domain.
4484       ALLOCATE ( rrtm_tlay(0:0,nzb+1:nzt_rad+1)   )
4485       ALLOCATE ( rrtm_tlev(0:0,nzb+1:nzt_rad+2)   )
4486
4487       DO k = nzt+8, nzt_rad
4488          rrtm_tlay(0,k)   = t_snd(k)
4489       ENDDO
4490       rrtm_tlay(0,nzt_rad+1) = 2.0_wp * rrtm_tlay(0,nzt_rad)                  &
4491                                - rrtm_tlay(0,nzt_rad-1)
4492       DO k = nzt+9, nzt_rad+1
4493          rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k)                &
4494                             - rrtm_tlay(0,k-1))                               &
4495                             / ( rrtm_play(0,k) - rrtm_play(0,k-1) )           &
4496                             * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
4497       ENDDO
4498
4499       rrtm_tlev(0,nzt_rad+2)   = 2.0_wp * rrtm_tlay(0,nzt_rad+1)              &
4500                                  - rrtm_tlev(0,nzt_rad)
4501!
4502!--    Allocate remaining RRTMG arrays
4503       ALLOCATE ( rrtm_cicewp(0:0,nzb+1:nzt_rad+1) )
4504       ALLOCATE ( rrtm_cldfr(0:0,nzb+1:nzt_rad+1) )
4505       ALLOCATE ( rrtm_cliqwp(0:0,nzb+1:nzt_rad+1) )
4506       ALLOCATE ( rrtm_reice(0:0,nzb+1:nzt_rad+1) )
4507       ALLOCATE ( rrtm_reliq(0:0,nzb+1:nzt_rad+1) )
4508       ALLOCATE ( rrtm_lw_taucld(1:nbndlw+1,0:0,nzb+1:nzt_rad+1) )
4509       ALLOCATE ( rrtm_lw_tauaer(0:0,nzb+1:nzt_rad+1,1:nbndlw+1) )
4510       ALLOCATE ( rrtm_sw_taucld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4511       ALLOCATE ( rrtm_sw_ssacld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4512       ALLOCATE ( rrtm_sw_asmcld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4513       ALLOCATE ( rrtm_sw_fsfcld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4514       ALLOCATE ( rrtm_sw_tauaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) )
4515       ALLOCATE ( rrtm_sw_ssaaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) )
4516       ALLOCATE ( rrtm_sw_asmaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) ) 
4517       ALLOCATE ( rrtm_sw_ecaer(0:0,nzb+1:nzt_rad+1,1:naerec+1) )   
4518
4519!
4520!--    The ice phase is currently not considered in PALM
4521       rrtm_cicewp = 0.0_wp
4522       rrtm_reice  = 0.0_wp
4523
4524!
4525!--    Set other parameters (move to NAMELIST parameters in the future)
4526       rrtm_lw_tauaer = 0.0_wp
4527       rrtm_lw_taucld = 0.0_wp
4528       rrtm_sw_taucld = 0.0_wp
4529       rrtm_sw_ssacld = 0.0_wp
4530       rrtm_sw_asmcld = 0.0_wp
4531       rrtm_sw_fsfcld = 0.0_wp
4532       rrtm_sw_tauaer = 0.0_wp
4533       rrtm_sw_ssaaer = 0.0_wp
4534       rrtm_sw_asmaer = 0.0_wp
4535       rrtm_sw_ecaer  = 0.0_wp
4536
4537
4538       ALLOCATE ( rrtm_swdflx(0:0,nzb:nzt_rad+1)  )
4539       ALLOCATE ( rrtm_swuflx(0:0,nzb:nzt_rad+1)  )
4540       ALLOCATE ( rrtm_swhr(0:0,nzb+1:nzt_rad+1)  )
4541       ALLOCATE ( rrtm_swuflxc(0:0,nzb:nzt_rad+1) )
4542       ALLOCATE ( rrtm_swdflxc(0:0,nzb:nzt_rad+1) )
4543       ALLOCATE ( rrtm_swhrc(0:0,nzb+1:nzt_rad+1) )
4544       ALLOCATE ( rrtm_dirdflux(0:0,nzb:nzt_rad+1) )
4545       ALLOCATE ( rrtm_difdflux(0:0,nzb:nzt_rad+1) )
4546
4547       rrtm_swdflx  = 0.0_wp
4548       rrtm_swuflx  = 0.0_wp
4549       rrtm_swhr    = 0.0_wp 
4550       rrtm_swuflxc = 0.0_wp
4551       rrtm_swdflxc = 0.0_wp
4552       rrtm_swhrc   = 0.0_wp
4553       rrtm_dirdflux = 0.0_wp
4554       rrtm_difdflux = 0.0_wp
4555
4556       ALLOCATE ( rrtm_lwdflx(0:0,nzb:nzt_rad+1)  )
4557       ALLOCATE ( rrtm_lwuflx(0:0,nzb:nzt_rad+1)  )
4558       ALLOCATE ( rrtm_lwhr(0:0,nzb+1:nzt_rad+1)  )
4559       ALLOCATE ( rrtm_lwuflxc(0:0,nzb:nzt_rad+1) )
4560       ALLOCATE ( rrtm_lwdflxc(0:0,nzb:nzt_rad+1) )
4561       ALLOCATE ( rrtm_lwhrc(0:0,nzb+1:nzt_rad+1) )
4562
4563       rrtm_lwdflx  = 0.0_wp
4564       rrtm_lwuflx  = 0.0_wp
4565       rrtm_lwhr    = 0.0_wp 
4566       rrtm_lwuflxc = 0.0_wp
4567       rrtm_lwdflxc = 0.0_wp
4568       rrtm_lwhrc   = 0.0_wp
4569
4570       ALLOCATE ( rrtm_lwuflx_dt(0:0,nzb:nzt_rad+1) )
4571       ALLOCATE ( rrtm_lwuflxc_dt(0:0,nzb:nzt_rad+1) )
4572
4573       rrtm_lwuflx_dt = 0.0_wp
4574       rrtm_lwuflxc_dt = 0.0_wp
4575
4576    END SUBROUTINE read_sounding_data
4577
4578
4579!------------------------------------------------------------------------------!
4580! Description:
4581! ------------
4582!> Read trace gas data from file
4583!------------------------------------------------------------------------------!
4584    SUBROUTINE read_trace_gas_data
4585
4586       USE rrsw_ncpar
4587
4588       IMPLICIT NONE
4589
4590       INTEGER(iwp), PARAMETER :: num_trace_gases = 10 !< number of trace gases (absorbers)
4591
4592       CHARACTER(LEN=5), DIMENSION(num_trace_gases), PARAMETER ::              & !< trace gas names
4593           trace_names = (/'O3   ', 'CO2  ', 'CH4  ', 'N2O  ', 'O2   ',        &
4594                           'CFC11', 'CFC12', 'CFC22', 'CCL4 ', 'H2O  '/)
4595
4596       INTEGER(iwp) :: id,     & !< NetCDF id
4597                       k,      & !< loop index
4598                       m,      & !< loop index
4599                       n,      & !< loop index
4600                       nabs,   & !< number of absorbers
4601                       np,     & !< number of pressure levels
4602                       id_abs, & !< NetCDF id of the respective absorber
4603                       id_dim, & !< NetCDF id of asborber's dimension
4604                       id_var    !< NetCDf id ot the absorber
4605
4606       REAL(wp) :: p_mls_l, p_mls_u, p_wgt_l, p_wgt_u, p_mls_m
4607
4608
4609       REAL(wp), DIMENSION(:), ALLOCATABLE   ::  p_mls,          & !< pressure levels for the absorbers
4610                                                 rrtm_play_tmp,  & !< temporary array for pressure zu-levels
4611                                                 rrtm_plev_tmp,  & !< temporary array for pressure zw-levels
4612                                                 trace_path_tmp    !< temporary array for storing trace gas path data
4613
4614       REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  trace_mls,      & !< array for storing the absorber amounts
4615                                                 trace_mls_path, & !< array for storing trace gas path data
4616                                                 trace_mls_tmp     !< temporary array for storing trace gas data
4617
4618
4619!
4620!--    In case of updates, deallocate arrays first (sufficient to check one
4621!--    array as the others are automatically allocated)
4622       IF ( ALLOCATED ( rrtm_o3vmr ) )  THEN
4623          DEALLOCATE ( rrtm_o3vmr  )
4624          DEALLOCATE ( rrtm_co2vmr )
4625          DEALLOCATE ( rrtm_ch4vmr )
4626          DEALLOCATE ( rrtm_n2ovmr )
4627          DEALLOCATE ( rrtm_o2vmr  )
4628          DEALLOCATE ( rrtm_cfc11vmr )
4629          DEALLOCATE ( rrtm_cfc12vmr )
4630          DEALLOCATE ( rrtm_cfc22vmr )
4631          DEALLOCATE ( rrtm_ccl4vmr  )
4632          DEALLOCATE ( rrtm_h2ovmr  )     
4633       ENDIF
4634
4635!
4636!--    Allocate trace gas profiles
4637       ALLOCATE ( rrtm_o3vmr(0:0,1:nzt_rad+1)  )
4638       ALLOCATE ( rrtm_co2vmr(0:0,1:nzt_rad+1) )
4639       ALLOCATE ( rrtm_ch4vmr(0:0,1:nzt_rad+1) )
4640       ALLOCATE ( rrtm_n2ovmr(0:0,1:nzt_rad+1) )
4641       ALLOCATE ( rrtm_o2vmr(0:0,1:nzt_rad+1)  )
4642       ALLOCATE ( rrtm_cfc11vmr(0:0,1:nzt_rad+1) )
4643       ALLOCATE ( rrtm_cfc12vmr(0:0,1:nzt_rad+1) )
4644       ALLOCATE ( rrtm_cfc22vmr(0:0,1:nzt_rad+1) )
4645       ALLOCATE ( rrtm_ccl4vmr(0:0,1:nzt_rad+1)  )
4646       ALLOCATE ( rrtm_h2ovmr(0:0,1:nzt_rad+1)  )
4647
4648!
4649!--    Open file for reading
4650       nc_stat = NF90_OPEN( rrtm_input_file, NF90_NOWRITE, id )
4651       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 549 )
4652!
4653!--    Inquire dimension ids and dimensions
4654       nc_stat = NF90_INQ_DIMID( id, "Pressure", id_dim )
4655       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4656       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim, len = np) 
4657       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4658
4659       nc_stat = NF90_INQ_DIMID( id, "Absorber", id_dim )
4660       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4661       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim, len = nabs ) 
4662       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4663   
4664
4665!
4666!--    Allocate pressure, and trace gas arrays     
4667       ALLOCATE( p_mls(1:np) )
4668       ALLOCATE( trace_mls(1:num_trace_gases,1:np) ) 
4669       ALLOCATE( trace_mls_tmp(1:nabs,1:np) ) 
4670
4671
4672       nc_stat = NF90_INQ_VARID( id, "Pressure", id_var )
4673       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4674       nc_stat = NF90_GET_VAR( id, id_var, p_mls )
4675       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4676
4677       nc_stat = NF90_INQ_VARID( id, "AbsorberAmountMLS", id_var )
4678       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4679       nc_stat = NF90_GET_VAR( id, id_var, trace_mls_tmp )
4680       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4681
4682
4683!
4684!--    Write absorber amounts (mls) to trace_mls
4685       DO n = 1, num_trace_gases
4686          CALL getAbsorberIndex( TRIM( trace_names(n) ), id_abs )
4687
4688          trace_mls(n,1:np) = trace_mls_tmp(id_abs,1:np)
4689
4690!
4691!--       Replace missing values by zero
4692          WHERE ( trace_mls(n,:) > 2.0_wp ) 
4693             trace_mls(n,:) = 0.0_wp
4694          END WHERE
4695       END DO
4696
4697       DEALLOCATE ( trace_mls_tmp )
4698
4699       nc_stat = NF90_CLOSE( id )
4700       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 551 )
4701
4702!
4703!--    Add extra pressure level for calculations of the trace gas paths
4704       ALLOCATE ( rrtm_play_tmp(1:nzt_rad+1) )
4705       ALLOCATE ( rrtm_plev_tmp(1:nzt_rad+2) )
4706
4707       rrtm_play_tmp(1:nzt_rad)   = rrtm_play(0,1:nzt_rad) 
4708       rrtm_plev_tmp(1:nzt_rad+1) = rrtm_plev(0,1:nzt_rad+1)
4709       rrtm_play_tmp(nzt_rad+1)   = rrtm_plev(0,nzt_rad+1) * 0.5_wp
4710       rrtm_plev_tmp(nzt_rad+2)   = MIN( 1.0E-4_wp, 0.25_wp                    &
4711                                         * rrtm_plev(0,nzt_rad+1) )
4712 
4713!
4714!--    Calculate trace gas path (zero at surface) with interpolation to the
4715!--    sounding levels
4716       ALLOCATE ( trace_mls_path(1:nzt_rad+2,1:num_trace_gases) )
4717
4718       trace_mls_path(nzb+1,:) = 0.0_wp
4719       
4720       DO k = nzb+2, nzt_rad+2
4721          DO m = 1, num_trace_gases
4722             trace_mls_path(k,m) = trace_mls_path(k-1,m)
4723
4724!
4725!--          When the pressure level is higher than the trace gas pressure
4726!--          level, assume that
4727             IF ( rrtm_plev_tmp(k-1) > p_mls(1) )  THEN             
4728               
4729                trace_mls_path(k,m) = trace_mls_path(k,m) + trace_mls(m,1)     &
4730                                      * ( rrtm_plev_tmp(k-1)                   &
4731                                          - MAX( p_mls(1), rrtm_plev_tmp(k) )  &
4732                                        ) / g
4733             ENDIF
4734
4735!
4736!--          Integrate for each sounding level from the contributing p_mls
4737!--          levels
4738             DO n = 2, np
4739!
4740!--             Limit p_mls so that it is within the model level
4741                p_mls_u = MIN( rrtm_plev_tmp(k-1),                             &
4742                          MAX( rrtm_plev_tmp(k), p_mls(n) ) )
4743                p_mls_l = MIN( rrtm_plev_tmp(k-1),                             &
4744                          MAX( rrtm_plev_tmp(k), p_mls(n-1) ) )
4745
4746                IF ( p_mls_l > p_mls_u )  THEN
4747
4748!
4749!--                Calculate weights for interpolation
4750                   p_mls_m = 0.5_wp * (p_mls_l + p_mls_u)
4751                   p_wgt_u = (p_mls(n-1) - p_mls_m) / (p_mls(n-1) - p_mls(n))
4752                   p_wgt_l = (p_mls_m - p_mls(n))   / (p_mls(n-1) - p_mls(n))
4753
4754!
4755!--                Add level to trace gas path
4756                   trace_mls_path(k,m) = trace_mls_path(k,m)                   &
4757                                         +  ( p_wgt_u * trace_mls(m,n)         &
4758                                            + p_wgt_l * trace_mls(m,n-1) )     &
4759                                         * (p_mls_l - p_mls_u) / g
4760                ENDIF
4761             ENDDO
4762
4763             IF ( rrtm_plev_tmp(k) < p_mls(np) )  THEN
4764                trace_mls_path(k,m) = trace_mls_path(k,m) + trace_mls(m,np)    &
4765                                      * ( MIN( rrtm_plev_tmp(k-1), p_mls(np) ) &
4766                                          - rrtm_plev_tmp(k)                   &
4767                                        ) / g 
4768             ENDIF 
4769          ENDDO
4770       ENDDO
4771
4772
4773!
4774!--    Prepare trace gas path profiles
4775       ALLOCATE ( trace_path_tmp(1:nzt_rad+1) )
4776
4777       DO m = 1, num_trace_gases
4778
4779          trace_path_tmp(1:nzt_rad+1) = ( trace_mls_path(2:nzt_rad+2,m)        &
4780                                       - trace_mls_path(1:nzt_rad+1,m) ) * g   &
4781                                       / ( rrtm_plev_tmp(1:nzt_rad+1)          &
4782                                       - rrtm_plev_tmp(2:nzt_rad+2) )
4783
4784!
4785!--       Save trace gas paths to the respective arrays
4786          SELECT CASE ( TRIM( trace_names(m) ) )
4787
4788             CASE ( 'O3' )
4789
4790                rrtm_o3vmr(0,:) = trace_path_tmp(:)
4791
4792             CASE ( 'CO2' )
4793
4794                rrtm_co2vmr(0,:) = trace_path_tmp(:)
4795
4796             CASE ( 'CH4' )
4797
4798                rrtm_ch4vmr(0,:) = trace_path_tmp(:)
4799
4800             CASE ( 'N2O' )
4801
4802                rrtm_n2ovmr(0,:) = trace_path_tmp(:)
4803
4804             CASE ( 'O2' )
4805
4806                rrtm_o2vmr(0,:) = trace_path_tmp(:)
4807
4808             CASE ( 'CFC11' )
4809
4810                rrtm_cfc11vmr(0,:) = trace_path_tmp(:)
4811
4812             CASE ( 'CFC12' )
4813
4814                rrtm_cfc12vmr(0,:) = trace_path_tmp(:)
4815
4816             CASE ( 'CFC22' )
4817
4818                rrtm_cfc22vmr(0,:) = trace_path_tmp(:)
4819
4820             CASE ( 'CCL4' )
4821
4822                rrtm_ccl4vmr(0,:) = trace_path_tmp(:)
4823
4824             CASE ( 'H2O' )
4825
4826                rrtm_h2ovmr(0,:) = trace_path_tmp(:)
4827               
4828             CASE DEFAULT
4829
4830          END SELECT
4831
4832       ENDDO
4833
4834       DEALLOCATE ( trace_path_tmp )
4835       DEALLOCATE ( trace_mls_path )
4836       DEALLOCATE ( rrtm_play_tmp )
4837       DEALLOCATE ( rrtm_plev_tmp )
4838       DEALLOCATE ( trace_mls )
4839       DEALLOCATE ( p_mls )
4840
4841    END SUBROUTINE read_trace_gas_data
4842
4843
4844    SUBROUTINE netcdf_handle_error_rad( routine_name, errno )
4845
4846       USE control_parameters,                                                 &
4847           ONLY:  message_string
4848
4849       USE NETCDF
4850
4851       USE pegrid
4852
4853       IMPLICIT NONE
4854
4855       CHARACTER(LEN=6) ::  message_identifier
4856       CHARACTER(LEN=*) ::  routine_name
4857
4858       INTEGER(iwp) ::  errno
4859
4860       IF ( nc_stat /= NF90_NOERR )  THEN
4861
4862          WRITE( message_identifier, '(''NC'',I4.4)' )  errno
4863          message_string = TRIM( NF90_STRERROR( nc_stat ) )
4864
4865          CALL message( routine_name, message_identifier, 2, 2, 0, 6, 1 )
4866
4867       ENDIF
4868
4869    END SUBROUTINE netcdf_handle_error_rad
4870#endif
4871
4872
4873!------------------------------------------------------------------------------!
4874! Description:
4875! ------------
4876!> Calculate temperature tendency due to radiative cooling/heating.
4877!> Cache-optimized version.
4878!------------------------------------------------------------------------------!
4879 SUBROUTINE radiation_tendency_ij ( i, j, tend )
4880
4881    IMPLICIT NONE
4882
4883    INTEGER(iwp) :: i, j, k !< loop indices
4884
4885    REAL(wp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg) :: tend !< pt tendency term
4886
4887    IF ( radiation_scheme == 'rrtmg' )  THEN
4888#if defined  ( __rrtmg )
4889!
4890!--    Calculate tendency based on heating rate
4891       DO k = nzb+1, nzt+1
4892          tend(k,j,i) = tend(k,j,i) + (rad_lw_hr(k,j,i) + rad_sw_hr(k,j,i))    &
4893                                         * d_exner(k) * d_seconds_hour
4894       ENDDO
4895#endif
4896    ENDIF
4897
4898    END SUBROUTINE radiation_tendency_ij
4899
4900
4901!------------------------------------------------------------------------------!
4902! Description:
4903! ------------
4904!> Calculate temperature tendency due to radiative cooling/heating.
4905!> Vector-optimized version
4906!------------------------------------------------------------------------------!
4907 SUBROUTINE radiation_tendency ( tend )
4908
4909    USE indices,                                                               &
4910        ONLY:  nxl, nxr, nyn, nys
4911
4912    IMPLICIT NONE
4913
4914    INTEGER(iwp) :: i, j, k !< loop indices
4915
4916    REAL(wp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg) :: tend !< pt tendency term
4917
4918    IF ( radiation_scheme == 'rrtmg' )  THEN
4919#if defined  ( __rrtmg )
4920!
4921!--    Calculate tendency based on heating rate
4922       DO  i = nxl, nxr
4923          DO  j = nys, nyn
4924             DO k = nzb+1, nzt+1
4925                tend(k,j,i) = tend(k,j,i) + ( rad_lw_hr(k,j,i)                 &
4926                                          +  rad_sw_hr(k,j,i) ) * d_exner(k)   &
4927                                          * d_seconds_hour
4928             ENDDO
4929          ENDDO
4930       ENDDO
4931#endif
4932    ENDIF
4933
4934
4935 END SUBROUTINE radiation_tendency
4936
4937!------------------------------------------------------------------------------!
4938! Description:
4939! ------------
4940!> This subroutine calculates interaction of the solar radiation
4941!> with urban and land surfaces and updates all surface heatfluxes.
4942!> It calculates also the required parameters for RRTMG lower BC.
4943!>
4944!> For more info. see Resler et al. 2017
4945!>
4946!> The new version 2.0 was radically rewriten, the discretization scheme
4947!> has been changed. This new version significantly improves effectivity
4948!> of the paralelization and the scalability of the model.
4949!------------------------------------------------------------------------------!
4950
4951 SUBROUTINE radiation_interaction
4952
4953     IMPLICIT NONE
4954
4955     INTEGER(iwp)                      :: i, j, k, kk, is, js, d, ku, refstep, m, mm, l, ll
4956     INTEGER(iwp)                      :: isurf, isurfsrc, isvf, icsf, ipcgb
4957     INTEGER(iwp)                      :: imrt, imrtf
4958     INTEGER(iwp)                      :: isd                !< solar direction number
4959     INTEGER(iwp)                      :: pc_box_dimshift    !< transform for best accuracy
4960     INTEGER(iwp), DIMENSION(0:3)      :: reorder = (/ 1, 0, 3, 2 /)
4961     
4962     REAL(wp), DIMENSION(3,3)          :: mrot               !< grid rotation matrix (zyx)
4963     REAL(wp), DIMENSION(3,0:nsurf_type):: vnorm             !< face direction normal vectors (zyx)
4964     REAL(wp), DIMENSION(3)            :: sunorig            !< grid rotated solar direction unit vector (zyx)
4965     REAL(wp), DIMENSION(3)            :: sunorig_grid       !< grid squashed solar direction unit vector (zyx)
4966     REAL(wp), DIMENSION(0:nsurf_type) :: costheta           !< direct irradiance factor of solar angle
4967     REAL(wp), DIMENSION(nzub:nzut)    :: pchf_prep          !< precalculated factor for canopy temperature tendency
4968     REAL(wp), PARAMETER               :: alpha = 0._wp      !< grid rotation (TODO: add to namelist or remove)
4969     REAL(wp)                          :: pc_box_area, pc_abs_frac, pc_abs_eff
4970     REAL(wp)                          :: asrc               !< area of source face
4971     REAL(wp)                          :: pcrad              !< irradiance from plant canopy
4972     REAL(wp)                          :: pabsswl  = 0.0_wp  !< total absorbed SW radiation energy in local processor (W)
4973     REAL(wp)                          :: pabssw   = 0.0_wp  !< total absorbed SW radiation energy in all processors (W)
4974     REAL(wp)                          :: pabslwl  = 0.0_wp  !< total absorbed LW radiation energy in local processor (W)
4975     REAL(wp)                          :: pabslw   = 0.0_wp  !< total absorbed LW radiation energy in all processors (W)
4976     REAL(wp)                          :: pemitlwl = 0.0_wp  !< total emitted LW radiation energy in all processors (W)
4977     REAL(wp)                          :: pemitlw  = 0.0_wp  !< total emitted LW radiation energy in all processors (W)
4978     REAL(wp)                          :: pinswl   = 0.0_wp  !< total received SW radiation energy in local processor (W)
4979     REAL(wp)                          :: pinsw    = 0.0_wp  !< total received SW radiation energy in all processor (W)
4980     REAL(wp)                          :: pinlwl   = 0.0_wp  !< total received LW radiation energy in local processor (W)
4981     REAL(wp)                          :: pinlw    = 0.0_wp  !< total received LW radiation energy in all processor (W)
4982     REAL(wp)                          :: emiss_sum_surfl    !< sum of emissisivity of surfaces in local processor
4983     REAL(wp)                          :: emiss_sum_surf     !< sum of emissisivity of surfaces in all processor
4984     REAL(wp)                          :: area_surfl         !< total area of surfaces in local processor
4985     REAL(wp)                          :: area_surf          !< total area of surfaces in all processor
4986     REAL(wp)                          :: area_hor           !< total horizontal area of domain in all processor
4987
4988
4989     IF ( plant_canopy )  THEN
4990         pchf_prep(:) = r_d * exner(nzub:nzut)                                 &
4991                     / (c_p * hyp(nzub:nzut) * dx*dy*dz(1)) !< equals to 1 / (rho * c_p * Vbox * T)
4992     ENDIF
4993
4994     sun_direction = .TRUE.
4995     CALL calc_zenith  !< required also for diffusion radiation
4996
4997!--     prepare rotated normal vectors and irradiance factor
4998     vnorm(1,:) = kdir(:)
4999     vnorm(2,:) = jdir(:)
5000     vnorm(3,:) = idir(:)
5001     mrot(1, :) = (/ 1._wp,  0._wp,      0._wp      /)
5002     mrot(2, :) = (/ 0._wp,  COS(alpha), SIN(alpha) /)
5003     mrot(3, :) = (/ 0._wp, -SIN(alpha), COS(alpha) /)
5004     sunorig = (/ zenith(0), sun_dir_lat, sun_dir_lon /)
5005     sunorig = MATMUL(mrot, sunorig)
5006     DO d = 0, nsurf_type
5007         costheta(d) = DOT_PRODUCT(sunorig, vnorm(:,d))
5008     ENDDO
5009
5010     IF ( zenith(0) > 0 )  THEN
5011!--      now we will "squash" the sunorig vector by grid box size in
5012!--      each dimension, so that this new direction vector will allow us
5013!--      to traverse the ray path within grid coordinates directly
5014         sunorig_grid = (/ sunorig(1)/dz(1), sunorig(2)/dy, sunorig(3)/dx /)
5015!--      sunorig_grid = sunorig_grid / norm2(sunorig_grid)
5016         sunorig_grid = sunorig_grid / SQRT(SUM(sunorig_grid**2))
5017
5018         IF ( npcbl > 0 )  THEN
5019!--         precompute effective box depth with prototype Leaf Area Density
5020            pc_box_dimshift = MAXLOC(ABS(sunorig), 1) - 1
5021            CALL box_absorb(CSHIFT((/dz(1),dy,dx/), pc_box_dimshift),       &
5022                                60, prototype_lad,                          &
5023                                CSHIFT(ABS(sunorig), pc_box_dimshift),      &
5024                                pc_box_area, pc_abs_frac)
5025            pc_box_area = pc_box_area * ABS(sunorig(pc_box_dimshift+1)      &
5026                          / sunorig(1))
5027            pc_abs_eff = LOG(1._wp - pc_abs_frac) / prototype_lad
5028         ENDIF
5029     ENDIF
5030
5031!--  if radiation scheme is not RRTMG, split diffusion and direct part of the solar downward radiation
5032!--  comming from radiation model and store it in 2D arrays
5033     IF (  radiation_scheme /= 'rrtmg'  )  CALL calc_diffusion_radiation
5034
5035!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5036!--     First pass: direct + diffuse irradiance + thermal
5037!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5038     surfinswdir   = 0._wp !nsurfl
5039     surfins       = 0._wp !nsurfl
5040     surfinl       = 0._wp !nsurfl
5041     surfoutsl(:)  = 0.0_wp !start-end
5042     surfoutll(:)  = 0.0_wp !start-end
5043     IF ( nmrtbl > 0 )  THEN
5044        mrtinsw(:) = 0._wp
5045        mrtinlw(:) = 0._wp
5046     ENDIF
5047     surfinlg(:)  = 0._wp !global
5048
5049
5050!--  Set up thermal radiation from surfaces
5051!--  emiss_surf is defined only for surfaces for which energy balance is calculated
5052!--  Workaround: reorder surface data type back on 1D array including all surfaces,
5053!--  which implies to reorder horizontal and vertical surfaces
5054!
5055!--  Horizontal walls
5056     mm = 1
5057     DO  i = nxl, nxr
5058        DO  j = nys, nyn
5059!--           urban
5060           DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
5061              surfoutll(mm) = SUM ( surf_usm_h%frac(:,m) *                  &
5062                                    surf_usm_h%emissivity(:,m) )            &
5063                                  * sigma_sb                                &
5064                                  * surf_usm_h%pt_surface(m)**4
5065              albedo_surf(mm) = SUM ( surf_usm_h%frac(:,m) *                &
5066                                      surf_usm_h%albedo(:,m) )
5067              emiss_surf(mm)  = SUM ( surf_usm_h%frac(:,m) *                &
5068                                      surf_usm_h%emissivity(:,m) )
5069              mm = mm + 1
5070           ENDDO
5071!--           land
5072           DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
5073              surfoutll(mm) = SUM ( surf_lsm_h%frac(:,m) *                  &
5074                                    surf_lsm_h%emissivity(:,m) )            &
5075                                  * sigma_sb                                &
5076                                  * surf_lsm_h%pt_surface(m)**4
5077              albedo_surf(mm) = SUM ( surf_lsm_h%frac(:,m) *                &
5078                                      surf_lsm_h%albedo(:,m) )
5079              emiss_surf(mm)  = SUM ( surf_lsm_h%frac(:,m) *                &
5080                                      surf_lsm_h%emissivity(:,m) )
5081              mm = mm + 1
5082           ENDDO
5083        ENDDO
5084     ENDDO
5085!
5086!--     Vertical walls
5087     DO  i = nxl, nxr
5088        DO  j = nys, nyn
5089           DO  ll = 0, 3
5090              l = reorder(ll)
5091!--              urban
5092              DO  m = surf_usm_v(l)%start_index(j,i),                       &
5093                      surf_usm_v(l)%end_index(j,i)
5094                 surfoutll(mm) = SUM ( surf_usm_v(l)%frac(:,m) *            &
5095                                       surf_usm_v(l)%emissivity(:,m) )      &
5096                                  * sigma_sb                                &
5097                                  * surf_usm_v(l)%pt_surface(m)**4
5098                 albedo_surf(mm) = SUM ( surf_usm_v(l)%frac(:,m) *          &
5099                                         surf_usm_v(l)%albedo(:,m) )
5100                 emiss_surf(mm)  = SUM ( surf_usm_v(l)%frac(:,m) *          &
5101                                         surf_usm_v(l)%emissivity(:,m) )
5102                 mm = mm + 1
5103              ENDDO
5104!--              land
5105              DO  m = surf_lsm_v(l)%start_index(j,i),                       &
5106                      surf_lsm_v(l)%end_index(j,i)
5107                 surfoutll(mm) = SUM ( surf_lsm_v(l)%frac(:,m) *            &
5108                                       surf_lsm_v(l)%emissivity(:,m) )      &
5109                                  * sigma_sb                                &
5110                                  * surf_lsm_v(l)%pt_surface(m)**4
5111                 albedo_surf(mm) = SUM ( surf_lsm_v(l)%frac(:,m) *          &
5112                                         surf_lsm_v(l)%albedo(:,m) )
5113                 emiss_surf(mm)  = SUM ( surf_lsm_v(l)%frac(:,m) *          &
5114                                         surf_lsm_v(l)%emissivity(:,m) )
5115                 mm = mm + 1
5116              ENDDO
5117           ENDDO
5118        ENDDO
5119     ENDDO
5120
5121#if defined( __parallel )
5122!--     might be optimized and gather only values relevant for current processor
5123     CALL MPI_AllGatherv(surfoutll, nsurfl, MPI_REAL, &
5124                         surfoutl, nsurfs, surfstart, MPI_REAL, comm2d, ierr) !nsurf global
5125     IF ( ierr /= 0 ) THEN
5126         WRITE(9,*) 'Error MPI_AllGatherv1:', ierr, SIZE(surfoutll), nsurfl, &
5127                     SIZE(surfoutl), nsurfs, surfstart
5128         FLUSH(9)
5129     ENDIF
5130#else
5131     surfoutl(:) = surfoutll(:) !nsurf global
5132#endif
5133
5134     IF ( surface_reflections)  THEN
5135        DO  isvf = 1, nsvfl
5136           isurf = svfsurf(1, isvf)
5137           k     = surfl(iz, isurf)
5138           j     = surfl(iy, isurf)
5139           i     = surfl(ix, isurf)
5140           isurfsrc = svfsurf(2, isvf)
5141!
5142!--        For surface-to-surface factors we calculate thermal radiation in 1st pass
5143           IF ( plant_lw_interact )  THEN
5144              surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * svf(2,isvf) * surfoutl(isurfsrc)
5145           ELSE
5146              surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * surfoutl(isurfsrc)
5147           ENDIF
5148        ENDDO
5149     ENDIF
5150!
5151!--  diffuse radiation using sky view factor
5152     DO isurf = 1, nsurfl
5153        j = surfl(iy, isurf)
5154        i = surfl(ix, isurf)
5155        surfinswdif(isurf) = rad_sw_in_diff(j,i) * skyvft(isurf)
5156        IF ( plant_lw_interact )  THEN
5157           surfinlwdif(isurf) = rad_lw_in_diff(j,i) * skyvft(isurf)
5158        ELSE
5159           surfinlwdif(isurf) = rad_lw_in_diff(j,i) * skyvf(isurf)
5160        ENDIF
5161     ENDDO
5162!
5163!--  MRT diffuse irradiance
5164     DO  imrt = 1, nmrtbl
5165        j = mrtbl(iy, imrt)
5166        i = mrtbl(ix, imrt)
5167        mrtinsw(imrt) = mrtskyt(imrt) * rad_sw_in_diff(j,i)
5168        mrtinlw(imrt) = mrtsky(imrt) * rad_lw_in_diff(j,i)
5169     ENDDO
5170
5171     !-- direct radiation
5172     IF ( zenith(0) > 0 )  THEN
5173        !--Identify solar direction vector (discretized number) 1)
5174        !--
5175        j = FLOOR(ACOS(zenith(0)) / pi * raytrace_discrete_elevs)
5176        i = MODULO(NINT(ATAN2(sun_dir_lon(0), sun_dir_lat(0))               &
5177                        / (2._wp*pi) * raytrace_discrete_azims-.5_wp, iwp), &
5178                   raytrace_discrete_azims)
5179        isd = dsidir_rev(j, i)
5180!-- TODO: check if isd = -1 to report that this solar position is not precalculated
5181        DO isurf = 1, nsurfl
5182           j = surfl(iy, isurf)
5183           i = surfl(ix, isurf)
5184           surfinswdir(isurf) = rad_sw_in_dir(j,i) *                        &
5185                costheta(surfl(id, isurf)) * dsitrans(isurf, isd) / zenith(0)
5186        ENDDO
5187!
5188!--     MRT direct irradiance
5189        DO  imrt = 1, nmrtbl
5190           j = mrtbl(iy, imrt)
5191           i = mrtbl(ix, imrt)
5192           mrtinsw(imrt) = mrtinsw(imrt) + mrtdsit(imrt, isd) * rad_sw_in_dir(j,i) &
5193                                     / zenith(0) / 4._wp ! normal to sphere
5194        ENDDO
5195     ENDIF
5196!
5197!--  MRT first pass thermal
5198     DO  imrtf = 1, nmrtf
5199        imrt = mrtfsurf(1, imrtf)
5200        isurfsrc = mrtfsurf(2, imrtf)
5201        mrtinlw(imrt) = mrtinlw(imrt) + mrtf(imrtf) * surfoutl(isurfsrc)
5202     ENDDO
5203
5204     IF ( npcbl > 0 )  THEN
5205
5206         pcbinswdir(:) = 0._wp
5207         pcbinswdif(:) = 0._wp
5208         pcbinlw(:) = 0._wp
5209!
5210!--      pcsf first pass
5211         DO icsf = 1, ncsfl
5212             ipcgb = csfsurf(1, icsf)
5213             i = pcbl(ix,ipcgb)
5214             j = pcbl(iy,ipcgb)
5215             k = pcbl(iz,ipcgb)
5216             isurfsrc = csfsurf(2, icsf)
5217
5218             IF ( isurfsrc == -1 )  THEN
5219!
5220!--             Diffuse rad from sky.
5221                pcbinswdif(ipcgb) = csf(1,icsf) * rad_sw_in_diff(j,i)
5222!
5223!--             Absorbed diffuse LW from sky minus emitted to sky
5224                IF ( plant_lw_interact )  THEN
5225                   pcbinlw(ipcgb) = csf(1,icsf)                                  &
5226                                       * (rad_lw_in_diff(j, i)                   &
5227                                          - sigma_sb * (pt(k,j,i)*exner(k))**4)
5228                ENDIF
5229!
5230!--             Direct rad
5231                IF ( zenith(0) > 0 )  THEN
5232!--                Estimate directed box absorption
5233                   pc_abs_frac = 1._wp - exp(pc_abs_eff * lad_s(k,j,i))
5234!
5235!--                isd has already been established, see 1)
5236                   pcbinswdir(ipcgb) = rad_sw_in_dir(j, i) * pc_box_area &
5237                                       * pc_abs_frac * dsitransc(ipcgb, isd)
5238                ENDIF
5239             ELSE
5240                IF ( plant_lw_interact )  THEN
5241!
5242!--                Thermal emission from plan canopy towards respective face
5243                   pcrad = sigma_sb * (pt(k,j,i) * exner(k))**4 * csf(1,icsf)
5244                   surfinlg(isurfsrc) = surfinlg(isurfsrc) + pcrad
5245!
5246!--                Remove the flux above + absorb LW from first pass from surfaces
5247                   asrc = facearea(surf(id, isurfsrc))
5248                   pcbinlw(ipcgb) = pcbinlw(ipcgb)                      &
5249                                    + (csf(1,icsf) * surfoutl(isurfsrc) & ! Absorb from first pass surf emit
5250                                       - pcrad)                         & ! Remove emitted heatflux
5251                                    * asrc
5252                ENDIF
5253             ENDIF
5254         ENDDO
5255
5256         pcbinsw(:) = pcbinswdir(:) + pcbinswdif(:)
5257     ENDIF
5258
5259     IF ( plant_lw_interact )  THEN
5260!
5261!--     Exchange incoming lw radiation from plant canopy
5262#if defined( __parallel )
5263        CALL MPI_Allreduce(MPI_IN_PLACE, surfinlg, nsurf, MPI_REAL, MPI_SUM, comm2d, ierr)
5264        IF ( ierr /= 0 )  THEN
5265           WRITE (9,*) 'Error MPI_Allreduce:', ierr
5266           FLUSH(9)
5267        ENDIF
5268        surfinl(:) = surfinl(:) + surfinlg(surfstart(myid)+1:surfstart(myid+1))
5269#else
5270        surfinl(:) = surfinl(:) + surfinlg(:)
5271#endif
5272     ENDIF
5273
5274     surfins = surfinswdir + surfinswdif
5275     surfinl = surfinl + surfinlwdif
5276     surfinsw = surfins
5277     surfinlw = surfinl
5278     surfoutsw = 0.0_wp
5279     surfoutlw = surfoutll
5280     surfemitlwl = surfoutll
5281
5282     IF ( .NOT.  surface_reflections )  THEN
5283!
5284!--     Set nrefsteps to 0 to disable reflections       
5285        nrefsteps = 0
5286        surfoutsl = albedo_surf * surfins
5287        surfoutll = (1._wp - emiss_surf) * surfinl
5288        surfoutsw = surfoutsw + surfoutsl
5289        surfoutlw = surfoutlw + surfoutll
5290     ENDIF
5291
5292!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5293!--     Next passes - reflections
5294!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5295     DO refstep = 1, nrefsteps
5296
5297         surfoutsl = albedo_surf * surfins
5298!--         for non-transparent surfaces, longwave albedo is 1 - emissivity
5299         surfoutll = (1._wp - emiss_surf) * surfinl
5300
5301#if defined( __parallel )
5302         CALL MPI_AllGatherv(surfoutsl, nsurfl, MPI_REAL, &
5303             surfouts, nsurfs, surfstart, MPI_REAL, comm2d, ierr)
5304         IF ( ierr /= 0 ) THEN
5305             WRITE(9,*) 'Error MPI_AllGatherv2:', ierr, SIZE(surfoutsl), nsurfl, &
5306                        SIZE(surfouts), nsurfs, surfstart
5307             FLUSH(9)
5308         ENDIF
5309
5310         CALL MPI_AllGatherv(surfoutll, nsurfl, MPI_REAL, &
5311             surfoutl, nsurfs, surfstart, MPI_REAL, comm2d, ierr)
5312         IF ( ierr /= 0 ) THEN
5313             WRITE(9,*) 'Error MPI_AllGatherv3:', ierr, SIZE(surfoutll), nsurfl, &
5314                        SIZE(surfoutl), nsurfs, surfstart
5315             FLUSH(9)
5316         ENDIF
5317
5318#else
5319         surfouts = surfoutsl
5320         surfoutl = surfoutll
5321#endif
5322
5323!--         reset for next pass input
5324         surfins = 0._wp
5325         surfinl = 0._wp
5326
5327!--         reflected radiation
5328         DO isvf = 1, nsvfl
5329             isurf = svfsurf(1, isvf)
5330             isurfsrc = svfsurf(2, isvf)
5331             surfins(isurf) = surfins(isurf) + svf(1,isvf) * svf(2,isvf) * surfouts(isurfsrc)
5332             IF ( plant_lw_interact )  THEN
5333                surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * svf(2,isvf) * surfoutl(isurfsrc)
5334             ELSE
5335                surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * surfoutl(isurfsrc)
5336             ENDIF
5337         ENDDO
5338!
5339!--      NOTE: PC absorbtion and MRT from reflected can both be done at once
5340!--      after all reflections if we do one more MPI_ALLGATHERV on surfout.
5341!--      Advantage: less local computation. Disadvantage: one more collective
5342!--      MPI call.
5343!
5344!--      Radiation absorbed by plant canopy
5345         DO  icsf = 1, ncsfl
5346             ipcgb = csfsurf(1, icsf)
5347             isurfsrc = csfsurf(2, icsf)
5348             IF ( isurfsrc == -1 )  CYCLE ! sky->face only in 1st pass, not here
5349!
5350!--          Calculate source surface area. If the `surf' array is removed
5351!--          before timestepping starts (future version), then asrc must be
5352!--          stored within `csf'
5353             asrc = facearea(surf(id, isurfsrc))
5354             pcbinsw(ipcgb) = pcbinsw(ipcgb) + csf(1,icsf) * surfouts(isurfsrc) * asrc
5355             IF ( plant_lw_interact )  THEN
5356                pcbinlw(ipcgb) = pcbinlw(ipcgb) + csf(1,icsf) * surfoutl(isurfsrc) * asrc
5357             ENDIF
5358         ENDDO
5359!
5360!--      MRT reflected
5361         DO  imrtf = 1, nmrtf
5362            imrt = mrtfsurf(1, imrtf)
5363            isurfsrc = mrtfsurf(2, imrtf)
5364            mrtinsw(imrt) = mrtinsw(imrt) + mrtft(imrtf) * surfouts(isurfsrc)
5365            mrtinlw(imrt) = mrtinlw(imrt) + mrtf(imrtf) * surfoutl(isurfsrc)
5366         ENDDO
5367
5368         surfinsw = surfinsw  + surfins
5369         surfinlw = surfinlw  + surfinl
5370         surfoutsw = surfoutsw + surfoutsl
5371         surfoutlw = surfoutlw + surfoutll
5372
5373     ENDDO ! refstep
5374
5375!--  push heat flux absorbed by plant canopy to respective 3D arrays
5376     IF ( npcbl > 0 )  THEN
5377         pc_heating_rate(:,:,:) = 0.0_wp
5378         DO ipcgb = 1, npcbl
5379             j = pcbl(iy, ipcgb)
5380             i = pcbl(ix, ipcgb)
5381             k = pcbl(iz, ipcgb)
5382!
5383!--          Following expression equals former kk = k - nzb_s_inner(j,i)
5384             kk = k - get_topography_top_index_ji( j, i, 's' )  !- lad arrays are defined flat
5385             pc_heating_rate(kk, j, i) = (pcbinsw(ipcgb) + pcbinlw(ipcgb)) &
5386                 * pchf_prep(k) * pt(k, j, i) !-- = dT/dt
5387         ENDDO
5388
5389         IF ( humidity .AND. plant_canopy_transpiration ) THEN
5390!--          Calculation of plant canopy transpiration rate and correspondidng latent heat rate
5391             pc_transpiration_rate(:,:,:) = 0.0_wp
5392             pc_latent_rate(:,:,:) = 0.0_wp
5393             DO ipcgb = 1, npcbl
5394                 i = pcbl(ix, ipcgb)
5395                 j = pcbl(iy, ipcgb)
5396                 k = pcbl(iz, ipcgb)
5397                 kk = k - get_topography_top_index_ji( j, i, 's' )  !- lad arrays are defined flat
5398                 CALL pcm_calc_transpiration_rate( i, j, k, kk, pcbinsw(ipcgb), pcbinlw(ipcgb), &
5399                                                   pc_transpiration_rate(kk,j,i), pc_latent_rate(kk,j,i) )
5400              ENDDO
5401         ENDIF
5402     ENDIF
5403!
5404!--  Calculate black body MRT (after all reflections)
5405     IF ( nmrtbl > 0 )  THEN
5406        IF ( mrt_include_sw )  THEN
5407           mrt(:) = ((mrtinsw(:) + mrtinlw(:)) / sigma_sb) ** .25_wp
5408        ELSE
5409           mrt(:) = (mrtinlw(:) / sigma_sb) ** .25_wp
5410        ENDIF
5411     ENDIF
5412!
5413!--     Transfer radiation arrays required for energy balance to the respective data types
5414     DO  i = 1, nsurfl
5415        m  = surfl(5,i)
5416!
5417!--     (1) Urban surfaces
5418!--     upward-facing
5419        IF ( surfl(1,i) == iup_u )  THEN
5420           surf_usm_h%rad_sw_in(m)  = surfinsw(i)
5421           surf_usm_h%rad_sw_out(m) = surfoutsw(i)
5422           surf_usm_h%rad_sw_dir(m) = surfinswdir(i)
5423           surf_usm_h%rad_sw_dif(m) = surfinswdif(i)
5424           surf_usm_h%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -        &
5425                                      surfinswdif(i)
5426           surf_usm_h%rad_sw_res(m) = surfins(i)
5427           surf_usm_h%rad_lw_in(m)  = surfinlw(i)
5428           surf_usm_h%rad_lw_out(m) = surfoutlw(i)
5429           surf_usm_h%rad_net(m)    = surfinsw(i) - surfoutsw(i) +          &
5430                                      surfinlw(i) - surfoutlw(i)
5431           surf_usm_h%rad_net_l(m)  = surf_usm_h%rad_net(m)
5432           surf_usm_h%rad_lw_dif(m) = surfinlwdif(i)
5433           surf_usm_h%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5434           surf_usm_h%rad_lw_res(m) = surfinl(i)
5435!
5436!--     northward-facding
5437        ELSEIF ( surfl(1,i) == inorth_u )  THEN
5438           surf_usm_v(0)%rad_sw_in(m)  = surfinsw(i)
5439           surf_usm_v(0)%rad_sw_out(m) = surfoutsw(i)
5440           surf_usm_v(0)%rad_sw_dir(m) = surfinswdir(i)
5441           surf_usm_v(0)%rad_sw_dif(m) = surfinswdif(i)
5442           surf_usm_v(0)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5443                                         surfinswdif(i)
5444           surf_usm_v(0)%rad_sw_res(m) = surfins(i)
5445           surf_usm_v(0)%rad_lw_in(m)  = surfinlw(i)
5446           surf_usm_v(0)%rad_lw_out(m) = surfoutlw(i)
5447           surf_usm_v(0)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5448                                         surfinlw(i) - surfoutlw(i)
5449           surf_usm_v(0)%rad_net_l(m)  = surf_usm_v(0)%rad_net(m)
5450           surf_usm_v(0)%rad_lw_dif(m) = surfinlwdif(i)
5451           surf_usm_v(0)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5452           surf_usm_v(0)%rad_lw_res(m) = surfinl(i)
5453!
5454!--     southward-facding
5455        ELSEIF ( surfl(1,i) == isouth_u )  THEN
5456           surf_usm_v(1)%rad_sw_in(m)  = surfinsw(i)
5457           surf_usm_v(1)%rad_sw_out(m) = surfoutsw(i)
5458           surf_usm_v(1)%rad_sw_dir(m) = surfinswdir(i)
5459           surf_usm_v(1)%rad_sw_dif(m) = surfinswdif(i)
5460           surf_usm_v(1)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5461                                         surfinswdif(i)
5462           surf_usm_v(1)%rad_sw_res(m) = surfins(i)
5463           surf_usm_v(1)%rad_lw_in(m)  = surfinlw(i)
5464           surf_usm_v(1)%rad_lw_out(m) = surfoutlw(i)
5465           surf_usm_v(1)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5466                                         surfinlw(i) - surfoutlw(i)
5467           surf_usm_v(1)%rad_net_l(m)  = surf_usm_v(1)%rad_net(m)
5468           surf_usm_v(1)%rad_lw_dif(m) = surfinlwdif(i)
5469           surf_usm_v(1)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5470           surf_usm_v(1)%rad_lw_res(m) = surfinl(i)
5471!
5472!--     eastward-facing
5473        ELSEIF ( surfl(1,i) == ieast_u )  THEN
5474           surf_usm_v(2)%rad_sw_in(m)  = surfinsw(i)
5475           surf_usm_v(2)%rad_sw_out(m) = surfoutsw(i)
5476           surf_usm_v(2)%rad_sw_dir(m) = surfinswdir(i)
5477           surf_usm_v(2)%rad_sw_dif(m) = surfinswdif(i)
5478           surf_usm_v(2)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5479                                         surfinswdif(i)
5480           surf_usm_v(2)%rad_sw_res(m) = surfins(i)
5481           surf_usm_v(2)%rad_lw_in(m)  = surfinlw(i)
5482           surf_usm_v(2)%rad_lw_out(m) = surfoutlw(i)
5483           surf_usm_v(2)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5484                                         surfinlw(i) - surfoutlw(i)
5485           surf_usm_v(2)%rad_net_l(m)  = surf_usm_v(2)%rad_net(m)
5486           surf_usm_v(2)%rad_lw_dif(m) = surfinlwdif(i)
5487           surf_usm_v(2)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5488           surf_usm_v(2)%rad_lw_res(m) = surfinl(i)
5489!
5490!--     westward-facding
5491        ELSEIF ( surfl(1,i) == iwest_u )  THEN
5492           surf_usm_v(3)%rad_sw_in(m)  = surfinsw(i)
5493           surf_usm_v(3)%rad_sw_out(m) = surfoutsw(i)
5494           surf_usm_v(3)%rad_sw_dir(m) = surfinswdir(i)
5495           surf_usm_v(3)%rad_sw_dif(m) = surfinswdif(i)
5496           surf_usm_v(3)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5497                                         surfinswdif(i)
5498           surf_usm_v(3)%rad_sw_res(m) = surfins(i)
5499           surf_usm_v(3)%rad_lw_in(m)  = surfinlw(i)
5500           surf_usm_v(3)%rad_lw_out(m) = surfoutlw(i)
5501           surf_usm_v(3)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5502                                         surfinlw(i) - surfoutlw(i)
5503           surf_usm_v(3)%rad_net_l(m)  = surf_usm_v(3)%rad_net(m)
5504           surf_usm_v(3)%rad_lw_dif(m) = surfinlwdif(i)
5505           surf_usm_v(3)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5506           surf_usm_v(3)%rad_lw_res(m) = surfinl(i)
5507!
5508!--     (2) land surfaces
5509!--     upward-facing
5510        ELSEIF ( surfl(1,i) == iup_l )  THEN
5511           surf_lsm_h%rad_sw_in(m)  = surfinsw(i)
5512           surf_lsm_h%rad_sw_out(m) = surfoutsw(i)
5513           surf_lsm_h%rad_sw_dir(m) = surfinswdir(i)
5514           surf_lsm_h%rad_sw_dif(m) = surfinswdif(i)
5515           surf_lsm_h%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -        &
5516                                         surfinswdif(i)
5517           surf_lsm_h%rad_sw_res(m) = surfins(i)
5518           surf_lsm_h%rad_lw_in(m)  = surfinlw(i)
5519           surf_lsm_h%rad_lw_out(m) = surfoutlw(i)
5520           surf_lsm_h%rad_net(m)    = surfinsw(i) - surfoutsw(i) +          &
5521                                      surfinlw(i) - surfoutlw(i)
5522           surf_lsm_h%rad_lw_dif(m) = surfinlwdif(i)
5523           surf_lsm_h%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5524           surf_lsm_h%rad_lw_res(m) = surfinl(i)
5525!
5526!--     northward-facding
5527        ELSEIF ( surfl(1,i) == inorth_l )  THEN
5528           surf_lsm_v(0)%rad_sw_in(m)  = surfinsw(i)
5529           surf_lsm_v(0)%rad_sw_out(m) = surfoutsw(i)
5530           surf_lsm_v(0)%rad_sw_dir(m) = surfinswdir(i)
5531           surf_lsm_v(0)%rad_sw_dif(m) = surfinswdif(i)
5532           surf_lsm_v(0)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5533                                         surfinswdif(i)
5534           surf_lsm_v(0)%rad_sw_res(m) = surfins(i)
5535           surf_lsm_v(0)%rad_lw_in(m)  = surfinlw(i)
5536           surf_lsm_v(0)%rad_lw_out(m) = surfoutlw(i)
5537           surf_lsm_v(0)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5538                                         surfinlw(i) - surfoutlw(i)
5539           surf_lsm_v(0)%rad_lw_dif(m) = surfinlwdif(i)
5540           surf_lsm_v(0)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5541           surf_lsm_v(0)%rad_lw_res(m) = surfinl(i)
5542!
5543!--     southward-facding
5544        ELSEIF ( surfl(1,i) == isouth_l )  THEN
5545           surf_lsm_v(1)%rad_sw_in(m)  = surfinsw(i)
5546           surf_lsm_v(1)%rad_sw_out(m) = surfoutsw(i)
5547           surf_lsm_v(1)%rad_sw_dir(m) = surfinswdir(i)
5548           surf_lsm_v(1)%rad_sw_dif(m) = surfinswdif(i)
5549           surf_lsm_v(1)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5550                                         surfinswdif(i)
5551           surf_lsm_v(1)%rad_sw_res(m) = surfins(i)
5552           surf_lsm_v(1)%rad_lw_in(m)  = surfinlw(i)
5553           surf_lsm_v(1)%rad_lw_out(m) = surfoutlw(i)
5554           surf_lsm_v(1)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5555                                         surfinlw(i) - surfoutlw(i)
5556           surf_lsm_v(1)%rad_lw_dif(m) = surfinlwdif(i)
5557           surf_lsm_v(1)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5558           surf_lsm_v(1)%rad_lw_res(m) = surfinl(i)
5559!
5560!--     eastward-facing
5561        ELSEIF ( surfl(1,i) == ieast_l )  THEN
5562           surf_lsm_v(2)%rad_sw_in(m)  = surfinsw(i)
5563           surf_lsm_v(2)%rad_sw_out(m) = surfoutsw(i)
5564           surf_lsm_v(2)%rad_sw_dir(m) = surfinswdir(i)
5565           surf_lsm_v(2)%rad_sw_dif(m) = surfinswdif(i)
5566           surf_lsm_v(2)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5567                                         surfinswdif(i)
5568           surf_lsm_v(2)%rad_sw_res(m) = surfins(i)
5569           surf_lsm_v(2)%rad_lw_in(m)  = surfinlw(i)
5570           surf_lsm_v(2)%rad_lw_out(m) = surfoutlw(i)
5571           surf_lsm_v(2)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5572                                         surfinlw(i) - surfoutlw(i)
5573           surf_lsm_v(2)%rad_lw_dif(m) = surfinlwdif(i)
5574           surf_lsm_v(2)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5575           surf_lsm_v(2)%rad_lw_res(m) = surfinl(i)
5576!
5577!--     westward-facing
5578        ELSEIF ( surfl(1,i) == iwest_l )  THEN
5579           surf_lsm_v(3)%rad_sw_in(m)  = surfinsw(i)
5580           surf_lsm_v(3)%rad_sw_out(m) = surfoutsw(i)
5581           surf_lsm_v(3)%rad_sw_dir(m) = surfinswdir(i)
5582           surf_lsm_v(3)%rad_sw_dif(m) = surfinswdif(i)
5583           surf_lsm_v(3)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5584                                         surfinswdif(i)
5585           surf_lsm_v(3)%rad_sw_res(m) = surfins(i)
5586           surf_lsm_v(3)%rad_lw_in(m)  = surfinlw(i)
5587           surf_lsm_v(3)%rad_lw_out(m) = surfoutlw(i)
5588           surf_lsm_v(3)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5589                                         surfinlw(i) - surfoutlw(i)
5590           surf_lsm_v(3)%rad_lw_dif(m) = surfinlwdif(i)
5591           surf_lsm_v(3)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5592           surf_lsm_v(3)%rad_lw_res(m) = surfinl(i)
5593        ENDIF
5594
5595     ENDDO
5596
5597     DO  m = 1, surf_usm_h%ns
5598        surf_usm_h%surfhf(m) = surf_usm_h%rad_sw_in(m)  +                   &
5599                               surf_usm_h%rad_lw_in(m)  -                   &
5600                               surf_usm_h%rad_sw_out(m) -                   &
5601                               surf_usm_h%rad_lw_out(m)
5602     ENDDO
5603     DO  m = 1, surf_lsm_h%ns
5604        surf_lsm_h%surfhf(m) = surf_lsm_h%rad_sw_in(m)  +                   &
5605                               surf_lsm_h%rad_lw_in(m)  -                   &
5606                               surf_lsm_h%rad_sw_out(m) -                   &
5607                               surf_lsm_h%rad_lw_out(m)
5608     ENDDO
5609
5610     DO  l = 0, 3
5611!--     urban
5612        DO  m = 1, surf_usm_v(l)%ns
5613           surf_usm_v(l)%surfhf(m) = surf_usm_v(l)%rad_sw_in(m)  +          &
5614                                     surf_usm_v(l)%rad_lw_in(m)  -          &
5615                                     surf_usm_v(l)%rad_sw_out(m) -          &
5616                                     surf_usm_v(l)%rad_lw_out(m)
5617        ENDDO
5618!--     land
5619        DO  m = 1, surf_lsm_v(l)%ns
5620           surf_lsm_v(l)%surfhf(m) = surf_lsm_v(l)%rad_sw_in(m)  +          &
5621                                     surf_lsm_v(l)%rad_lw_in(m)  -          &
5622                                     surf_lsm_v(l)%rad_sw_out(m) -          &
5623                                     surf_lsm_v(l)%rad_lw_out(m)
5624
5625        ENDDO
5626     ENDDO
5627!
5628!--  Calculate the average temperature, albedo, and emissivity for urban/land
5629!--  domain when using average_radiation in the respective radiation model
5630
5631!--  calculate horizontal area
5632! !!! ATTENTION!!! uniform grid is assumed here
5633     area_hor = (nx+1) * (ny+1) * dx * dy
5634!
5635!--  absorbed/received SW & LW and emitted LW energy of all physical
5636!--  surfaces (land and urban) in local processor
5637     pinswl = 0._wp
5638     pinlwl = 0._wp
5639     pabsswl = 0._wp
5640     pabslwl = 0._wp
5641     pemitlwl = 0._wp
5642     emiss_sum_surfl = 0._wp
5643     area_surfl = 0._wp
5644     DO  i = 1, nsurfl
5645        d = surfl(id, i)
5646!--  received SW & LW
5647        pinswl = pinswl + (surfinswdir(i) + surfinswdif(i)) * facearea(d)
5648        pinlwl = pinlwl + surfinlwdif(i) * facearea(d)
5649!--   absorbed SW & LW
5650        pabsswl = pabsswl + (1._wp - albedo_surf(i)) *                   &
5651                                                surfinsw(i) * facearea(d)
5652        pabslwl = pabslwl + emiss_surf(i) * surfinlw(i) * facearea(d)
5653!--   emitted LW
5654        pemitlwl = pemitlwl + surfemitlwl(i) * facearea(d)
5655!--   emissivity and area sum
5656        emiss_sum_surfl = emiss_sum_surfl + emiss_surf(i) * facearea(d)
5657        area_surfl = area_surfl + facearea(d)
5658     END DO
5659!
5660!--  add the absorbed SW energy by plant canopy
5661     IF ( npcbl > 0 )  THEN
5662        pabsswl = pabsswl + SUM(pcbinsw)
5663        pabslwl = pabslwl + SUM(pcbinlw)
5664        pinswl = pinswl + SUM(pcbinswdir) + SUM(pcbinswdif)
5665     ENDIF
5666!
5667!--  gather all rad flux energy in all processors
5668#if defined( __parallel )
5669     CALL MPI_ALLREDUCE( pinswl, pinsw, 1, MPI_REAL, MPI_SUM, comm2d, ierr)
5670     IF ( ierr /= 0 ) THEN
5671         WRITE(9,*) 'Error MPI_AllReduce5:', ierr, pinswl, pinsw
5672         FLUSH(9)
5673     ENDIF
5674     CALL MPI_ALLREDUCE( pinlwl, pinlw, 1, MPI_REAL, MPI_SUM, comm2d, ierr)
5675     IF ( ierr /= 0 ) THEN
5676         WRITE(9,*) 'Error MPI_AllReduce6:', ierr, pinlwl, pinlw
5677         FLUSH(9)
5678     ENDIF
5679     CALL MPI_ALLREDUCE( pabsswl, pabssw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5680     IF ( ierr /= 0 ) THEN
5681         WRITE(9,*) 'Error MPI_AllReduce7:', ierr, pabsswl, pabssw
5682         FLUSH(9)
5683     ENDIF
5684     CALL MPI_ALLREDUCE( pabslwl, pabslw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5685     IF ( ierr /= 0 ) THEN
5686         WRITE(9,*) 'Error MPI_AllReduce8:', ierr, pabslwl, pabslw
5687         FLUSH(9)
5688     ENDIF
5689     CALL MPI_ALLREDUCE( pemitlwl, pemitlw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5690     IF ( ierr /= 0 ) THEN
5691         WRITE(9,*) 'Error MPI_AllReduce8:', ierr, pemitlwl, pemitlw
5692         FLUSH(9)
5693     ENDIF
5694     CALL MPI_ALLREDUCE( emiss_sum_surfl, emiss_sum_surf, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5695     IF ( ierr /= 0 ) THEN
5696         WRITE(9,*) 'Error MPI_AllReduce9:', ierr, emiss_sum_surfl, emiss_sum_surf
5697         FLUSH(9)
5698     ENDIF
5699     CALL MPI_ALLREDUCE( area_surfl, area_surf, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5700     IF ( ierr /= 0 ) THEN
5701         WRITE(9,*) 'Error MPI_AllReduce10:', ierr, area_surfl, area_surf
5702         FLUSH(9)
5703     ENDIF
5704#else
5705     pinsw = pinswl
5706     pinlw = pinlwl
5707     pabssw = pabsswl
5708     pabslw = pabslwl
5709     pemitlw = pemitlwl
5710     emiss_sum_surf = emiss_sum_surfl
5711     area_surf = area_surfl
5712#endif
5713
5714!--  (1) albedo
5715     IF ( pinsw /= 0.0_wp )  &
5716          albedo_urb = (pinsw - pabssw) / pinsw
5717!--  (2) average emmsivity
5718     IF ( area_surf /= 0.0_wp ) &
5719          emissivity_urb = emiss_sum_surf / area_surf
5720!
5721!--  Temporally comment out calculation of effective radiative temperature.
5722!--  See below for more explanation.
5723!--  (3) temperature
5724!--   first we calculate an effective horizontal area to account for
5725!--   the effect of vertical surfaces (which contributes to LW emission)
5726!--   We simply use the ratio of the total LW to the incoming LW flux
5727      area_hor = pinlw/rad_lw_in_diff(nyn,nxl)
5728      t_rad_urb = ( (pemitlw - pabslw + emissivity_urb*pinlw) / &
5729           (emissivity_urb*sigma_sb * area_hor) )**0.25_wp
5730
5731    CONTAINS
5732
5733!------------------------------------------------------------------------------!
5734!> Calculates radiation absorbed by box with given size and LAD.
5735!>
5736!> Simulates resol**2 rays (by equally spacing a bounding horizontal square
5737!> conatining all possible rays that would cross the box) and calculates
5738!> average transparency per ray. Returns fraction of absorbed radiation flux
5739!> and area for which this fraction is effective.
5740!------------------------------------------------------------------------------!
5741    PURE SUBROUTINE box_absorb(boxsize, resol, dens, uvec, area, absorb)
5742       IMPLICIT NONE
5743
5744       REAL(wp), DIMENSION(3), INTENT(in) :: &
5745            boxsize, &      !< z, y, x size of box in m
5746            uvec            !< z, y, x unit vector of incoming flux
5747       INTEGER(iwp), INTENT(in) :: &
5748            resol           !< No. of rays in x and y dimensions
5749       REAL(wp), INTENT(in) :: &
5750            dens            !< box density (e.g. Leaf Area Density)
5751       REAL(wp), INTENT(out) :: &
5752            area, &         !< horizontal area for flux absorbtion
5753            absorb          !< fraction of absorbed flux
5754       REAL(wp) :: &
5755            xshift, yshift, &
5756            xmin, xmax, ymin, ymax, &
5757            xorig, yorig, &
5758            dx1, dy1, dz1, dx2, dy2, dz2, &
5759            crdist, &
5760            transp
5761       INTEGER(iwp) :: &
5762            i, j
5763
5764       xshift = uvec(3) / uvec(1) * boxsize(1)
5765       xmin = min(0._wp, -xshift)
5766       xmax = boxsize(3) + max(0._wp, -xshift)
5767       yshift = uvec(2) / uvec(1) * boxsize(1)
5768       ymin = min(0._wp, -yshift)
5769       ymax = boxsize(2) + max(0._wp, -yshift)
5770
5771       transp = 0._wp
5772       DO i = 1, resol
5773          xorig = xmin + (xmax-xmin) * (i-.5_wp) / resol
5774          DO j = 1, resol
5775             yorig = ymin + (ymax-ymin) * (j-.5_wp) / resol
5776
5777             dz1 = 0._wp
5778             dz2 = boxsize(1)/uvec(1)
5779
5780             IF ( uvec(2) > 0._wp )  THEN
5781                dy1 = -yorig             / uvec(2) !< crossing with y=0
5782                dy2 = (boxsize(2)-yorig) / uvec(2) !< crossing with y=boxsize(2)
5783             ELSE !uvec(2)==0
5784                dy1 = -huge(1._wp)
5785                dy2 = huge(1._wp)
5786             ENDIF
5787
5788             IF ( uvec(3) > 0._wp )  THEN
5789                dx1 = -xorig             / uvec(3) !< crossing with x=0
5790                dx2 = (boxsize(3)-xorig) / uvec(3) !< crossing with x=boxsize(3)
5791             ELSE !uvec(3)==0
5792                dx1 = -huge(1._wp)
5793                dx2 = huge(1._wp)
5794             ENDIF
5795
5796             crdist = max(0._wp, (min(dz2, dy2, dx2) - max(dz1, dy1, dx1)))
5797             transp = transp + exp(-ext_coef * dens * crdist)
5798          ENDDO
5799       ENDDO
5800       transp = transp / resol**2
5801       area = (boxsize(3)+xshift)*(boxsize(2)+yshift)
5802       absorb = 1._wp - transp
5803
5804    END SUBROUTINE box_absorb
5805
5806!------------------------------------------------------------------------------!
5807! Description:
5808! ------------
5809!> This subroutine splits direct and diffusion dw radiation
5810!> It sould not be called in case the radiation model already does it
5811!> It follows <CITATION>
5812!------------------------------------------------------------------------------!
5813    SUBROUTINE calc_diffusion_radiation 
5814   
5815        REAL(wp), PARAMETER                          :: lowest_solarUp = 0.1_wp  !< limit the sun elevation to protect stability of the calculation
5816        INTEGER(iwp)                                 :: i, j
5817        REAL(wp)                                     ::  year_angle              !< angle
5818        REAL(wp)                                     ::  etr                     !< extraterestrial radiation
5819        REAL(wp)                                     ::  corrected_solarUp       !< corrected solar up radiation
5820        REAL(wp)                                     ::  horizontalETR           !< horizontal extraterestrial radiation
5821        REAL(wp)                                     ::  clearnessIndex          !< clearness index
5822        REAL(wp)                                     ::  diff_frac               !< diffusion fraction of the radiation
5823
5824       
5825!--     Calculate current day and time based on the initial values and simulation time
5826        year_angle = ( (day_of_year_init * 86400) + time_utc_init              &
5827                        + time_since_reference_point )  * d_seconds_year       &
5828                        * 2.0_wp * pi
5829       
5830        etr = solar_constant * (1.00011_wp +                                   &
5831                          0.034221_wp * cos(year_angle) +                      &
5832                          0.001280_wp * sin(year_angle) +                      &
5833                          0.000719_wp * cos(2.0_wp * year_angle) +             &
5834                          0.000077_wp * sin(2.0_wp * year_angle))
5835       
5836!--   
5837!--     Under a very low angle, we keep extraterestrial radiation at
5838!--     the last small value, therefore the clearness index will be pushed
5839!--     towards 0 while keeping full continuity.
5840!--   
5841        IF ( zenith(0) <= lowest_solarUp )  THEN
5842            corrected_solarUp = lowest_solarUp
5843        ELSE
5844            corrected_solarUp = zenith(0)
5845        ENDIF
5846       
5847        horizontalETR = etr * corrected_solarUp
5848       
5849        DO i = nxl, nxr
5850            DO j = nys, nyn
5851                clearnessIndex = rad_sw_in(0,j,i) / horizontalETR
5852                diff_frac = 1.0_wp / (1.0_wp + exp(-5.0033_wp + 8.6025_wp * clearnessIndex))
5853                rad_sw_in_diff(j,i) = rad_sw_in(0,j,i) * diff_frac
5854                rad_sw_in_dir(j,i)  = rad_sw_in(0,j,i) * (1.0_wp - diff_frac)
5855                rad_lw_in_diff(j,i) = rad_lw_in(0,j,i)
5856            ENDDO
5857        ENDDO
5858       
5859    END SUBROUTINE calc_diffusion_radiation
5860
5861
5862 END SUBROUTINE radiation_interaction
5863   
5864!------------------------------------------------------------------------------!
5865! Description:
5866! ------------
5867!> This subroutine initializes structures needed for radiative transfer
5868!> model. This model calculates transformation processes of the
5869!> radiation inside urban and land canopy layer. The module includes also
5870!> the interaction of the radiation with the resolved plant canopy.
5871!>
5872!> For more info. see Resler et al. 2017
5873!>
5874!> The new version 2.0 was radically rewriten, the discretization scheme
5875!> has been changed. This new version significantly improves effectivity
5876!> of the paralelization and the scalability of the model.
5877!>
5878!------------------------------------------------------------------------------!
5879    SUBROUTINE radiation_interaction_init
5880
5881       USE control_parameters,                                                 &
5882           ONLY:  dz_stretch_level_start
5883           
5884       USE netcdf_data_input_mod,                                              &
5885           ONLY:  leaf_area_density_f
5886
5887       USE plant_canopy_model_mod,                                             &
5888           ONLY:  pch_index, lad_s
5889
5890       IMPLICIT NONE
5891
5892       INTEGER(iwp) :: i, j, k, l, m, d
5893       INTEGER(iwp) :: k_topo     !< vertical index indicating topography top for given (j,i)
5894       INTEGER(iwp) :: nzptl, nzubl, nzutl, isurf, ipcgb, imrt
5895       REAL(wp)     :: mrl
5896#if defined( __parallel )
5897       INTEGER(iwp), DIMENSION(:), POINTER       ::  gridsurf_rma   !< fortran pointer, but lower bounds are 1
5898       TYPE(c_ptr)                               ::  gridsurf_rma_p !< allocated c pointer
5899       INTEGER(iwp)                              ::  minfo          !< MPI RMA window info handle
5900#endif
5901
5902!
5903!--     precalculate face areas for different face directions using normal vector
5904        DO d = 0, nsurf_type
5905            facearea(d) = 1._wp
5906            IF ( idir(d) == 0 ) facearea(d) = facearea(d) * dx
5907            IF ( jdir(d) == 0 ) facearea(d) = facearea(d) * dy
5908            IF ( kdir(d) == 0 ) facearea(d) = facearea(d) * dz(1)
5909        ENDDO
5910!
5911!--    Find nzub, nzut, nzu via wall_flag_0 array (nzb_s_inner will be
5912!--    removed later). The following contruct finds the lowest / largest index
5913!--    for any upward-facing wall (see bit 12).
5914       nzubl = MINVAL( get_topography_top_index( 's' ) )
5915       nzutl = MAXVAL( get_topography_top_index( 's' ) )
5916
5917       nzubl = MAX( nzubl, nzb )
5918
5919       IF ( plant_canopy )  THEN
5920!--        allocate needed arrays
5921           ALLOCATE( pct(nys:nyn,nxl:nxr) )
5922           ALLOCATE( pch(nys:nyn,nxl:nxr) )
5923
5924!--        calculate plant canopy height
5925           npcbl = 0
5926           pct   = 0
5927           pch   = 0
5928           DO i = nxl, nxr
5929               DO j = nys, nyn
5930!
5931!--                Find topography top index
5932                   k_topo = get_topography_top_index_ji( j, i, 's' )
5933
5934                   DO k = nzt+1, 0, -1
5935                       IF ( lad_s(k,j,i) /= 0.0_wp )  THEN
5936!--                        we are at the top of the pcs
5937                           pct(j,i) = k + k_topo
5938                           pch(j,i) = k
5939                           npcbl = npcbl + pch(j,i)
5940                           EXIT
5941                       ENDIF
5942                   ENDDO
5943               ENDDO
5944           ENDDO
5945
5946           nzutl = MAX( nzutl, MAXVAL( pct ) )
5947           nzptl = MAXVAL( pct )
5948!--        code of plant canopy model uses parameter pch_index
5949!--        we need to setup it here to right value
5950!--        (pch_index, lad_s and other arrays in PCM are defined flat)
5951           pch_index = MERGE( leaf_area_density_f%nz - 1, MAXVAL( pch ),       &
5952                              leaf_area_density_f%from_file )
5953
5954           prototype_lad = MAXVAL( lad_s ) * .9_wp  !< better be *1.0 if lad is either 0 or maxval(lad) everywhere
5955           IF ( prototype_lad <= 0._wp ) prototype_lad = .3_wp
5956           !WRITE(message_string, '(a,f6.3)') 'Precomputing effective box optical ' &
5957           !    // 'depth using prototype leaf area density = ', prototype_lad
5958           !CALL message('radiation_interaction_init', 'PA0520', 0, 0, -1, 6, 0)
5959       ENDIF
5960
5961       nzutl = MIN( nzutl + nzut_free, nzt )
5962
5963#if defined( __parallel )
5964       CALL MPI_AllReduce(nzubl, nzub, 1, MPI_INTEGER, MPI_MIN, comm2d, ierr )
5965       IF ( ierr /= 0 ) THEN
5966           WRITE(9,*) 'Error MPI_AllReduce11:', ierr, nzubl, nzub
5967           FLUSH(9)
5968       ENDIF
5969       CALL MPI_AllReduce(nzutl, nzut, 1, MPI_INTEGER, MPI_MAX, comm2d, ierr )
5970       IF ( ierr /= 0 ) THEN
5971           WRITE(9,*) 'Error MPI_AllReduce12:', ierr, nzutl, nzut
5972           FLUSH(9)
5973       ENDIF
5974       CALL MPI_AllReduce(nzptl, nzpt, 1, MPI_INTEGER, MPI_MAX, comm2d, ierr )
5975       IF ( ierr /= 0 ) THEN
5976           WRITE(9,*) 'Error MPI_AllReduce13:', ierr, nzptl, nzpt
5977           FLUSH(9)
5978       ENDIF
5979#else
5980       nzub = nzubl
5981       nzut = nzutl
5982       nzpt = nzptl
5983#endif
5984!
5985!--    Stretching (non-uniform grid spacing) is not considered in the radiation
5986!--    model. Therefore, vertical stretching has to be applied above the area
5987!--    where the parts of the radiation model which assume constant grid spacing
5988!--    are active. ABS (...) is required because the default value of
5989!--    dz_stretch_level_start is -9999999.9_wp (negative).
5990       IF ( ABS( dz_stretch_level_start(1) ) <= zw(nzut) ) THEN
5991          WRITE( message_string, * ) 'The lowest level where vertical ',       &
5992                                     'stretching is applied have to be ',      &
5993                                     'greater than ', zw(nzut)
5994          CALL message( 'radiation_interaction_init', 'PA0496', 1, 2, 0, 6, 0 )
5995       ENDIF 
5996!
5997!--    global number of urban and plant layers
5998       nzu = nzut - nzub + 1
5999       nzp = nzpt - nzub + 1
6000!
6001!--    check max_raytracing_dist relative to urban surface layer height
6002       mrl = 2.0_wp * nzu * dz(1)
6003!--    set max_raytracing_dist to double the urban surface layer height, if not set
6004       IF ( max_raytracing_dist == -999.0_wp ) THEN
6005          max_raytracing_dist = mrl
6006       ENDIF
6007!--    check if max_raytracing_dist set too low (here we only warn the user. Other
6008!      option is to correct the value again to double the urban surface layer height)
6009       IF ( max_raytracing_dist  <  mrl ) THEN
6010          WRITE(message_string, '(a,f6.1)') 'Max_raytracing_dist is set less than ', &
6011               'double the urban surface layer height, i.e. ', mrl
6012          CALL message('radiation_interaction_init', 'PA0521', 0, 0, -1, 6, 0)
6013       ENDIF
6014!        IF ( max_raytracing_dist <= mrl ) THEN
6015!           IF ( max_raytracing_dist /= -999.0_wp ) THEN
6016! !--          max_raytracing_dist too low
6017!              WRITE(message_string, '(a,f6.1)') 'Max_raytracing_dist too low, ' &
6018!                    // 'override to value ', mrl
6019!              CALL message('radiation_interaction_init', 'PA0521', 0, 0, -1, 6, 0)
6020!           ENDIF
6021!           max_raytracing_dist = mrl
6022!        ENDIF
6023!
6024!--    allocate urban surfaces grid
6025!--    calc number of surfaces in local proc
6026       CALL location_message( '    calculation of indices for surfaces', .TRUE. )
6027       nsurfl = 0
6028!
6029!--    Number of horizontal surfaces including land- and roof surfaces in both USM and LSM. Note that
6030!--    All horizontal surface elements are already counted in surface_mod.
6031       startland = 1
6032       nsurfl    = surf_usm_h%ns + surf_lsm_h%ns
6033       endland   = nsurfl
6034       nlands    = endland - startland + 1
6035
6036!
6037!--    Number of vertical surfaces in both USM and LSM. Note that all vertical surface elements are
6038!--    already counted in surface_mod.
6039       startwall = nsurfl+1
6040       DO  i = 0,3
6041          nsurfl = nsurfl + surf_usm_v(i)%ns + surf_lsm_v(i)%ns
6042       ENDDO
6043       endwall = nsurfl
6044       nwalls  = endwall - startwall + 1
6045       dirstart = (/ startland, startwall, startwall, startwall, startwall /)
6046       dirend = (/ endland, endwall, endwall, endwall, endwall /)
6047
6048!--    fill gridpcbl and pcbl
6049       IF ( npcbl > 0 )  THEN
6050           ALLOCATE( pcbl(iz:ix, 1:npcbl) )
6051           ALLOCATE( gridpcbl(nzub:nzpt,nys:nyn,nxl:nxr) )
6052           pcbl = -1
6053           gridpcbl(:,:,:) = 0
6054           ipcgb = 0
6055           DO i = nxl, nxr
6056               DO j = nys, nyn
6057!
6058!--                Find topography top index
6059                   k_topo = get_topography_top_index_ji( j, i, 's' )
6060
6061                   DO k = k_topo + 1, pct(j,i)
6062                       ipcgb = ipcgb + 1
6063                       gridpcbl(k,j,i) = ipcgb
6064                       pcbl(:,ipcgb) = (/ k, j, i /)
6065                   ENDDO
6066               ENDDO
6067           ENDDO
6068           ALLOCATE( pcbinsw( 1:npcbl ) )
6069           ALLOCATE( pcbinswdir( 1:npcbl ) )
6070           ALLOCATE( pcbinswdif( 1:npcbl ) )
6071           ALLOCATE( pcbinlw( 1:npcbl ) )
6072       ENDIF
6073
6074!--    fill surfl (the ordering of local surfaces given by the following
6075!--    cycles must not be altered, certain file input routines may depend
6076!--    on it)
6077       ALLOCATE(surfl_l(5*nsurfl))  ! is it necessary to allocate it with (5,nsurfl)?
6078       surfl(1:5,1:nsurfl) => surfl_l(1:5*nsurfl)
6079       isurf = 0
6080       IF ( rad_angular_discretization )  THEN
6081!
6082!--       Allocate and fill the reverse indexing array gridsurf
6083#if defined( __parallel )
6084!
6085!--       raytrace_mpi_rma is asserted
6086
6087          CALL MPI_Info_create(minfo, ierr)
6088          IF ( ierr /= 0 ) THEN
6089              WRITE(9,*) 'Error MPI_Info_create1:', ierr
6090              FLUSH(9)
6091          ENDIF
6092          CALL MPI_Info_set(minfo, 'accumulate_ordering', '', ierr)
6093          IF ( ierr /= 0 ) THEN
6094              WRITE(9,*) 'Error MPI_Info_set1:', ierr
6095              FLUSH(9)
6096          ENDIF
6097          CALL MPI_Info_set(minfo, 'accumulate_ops', 'same_op', ierr)
6098          IF ( ierr /= 0 ) THEN
6099              WRITE(9,*) 'Error MPI_Info_set2:', ierr
6100              FLUSH(9)
6101          ENDIF
6102          CALL MPI_Info_set(minfo, 'same_size', 'true', ierr)
6103          IF ( ierr /= 0 ) THEN
6104              WRITE(9,*) 'Error MPI_Info_set3:', ierr
6105              FLUSH(9)
6106          ENDIF
6107          CALL MPI_Info_set(minfo, 'same_disp_unit', 'true', ierr)
6108          IF ( ierr /= 0 ) THEN
6109              WRITE(9,*) 'Error MPI_Info_set4:', ierr
6110              FLUSH(9)
6111          ENDIF
6112
6113          CALL MPI_Win_allocate(INT(STORAGE_SIZE(1_iwp)/8*nsurf_type_u*nzu*nny*nnx, &
6114                                    kind=MPI_ADDRESS_KIND), STORAGE_SIZE(1_iwp)/8,  &
6115                                minfo, comm2d, gridsurf_rma_p, win_gridsurf, ierr)
6116          IF ( ierr /= 0 ) THEN
6117              WRITE(9,*) 'Error MPI_Win_allocate1:', ierr, &
6118                 INT(STORAGE_SIZE(1_iwp)/8*nsurf_type_u*nzu*nny*nnx,kind=MPI_ADDRESS_KIND), &
6119                 STORAGE_SIZE(1_iwp)/8, win_gridsurf
6120              FLUSH(9)
6121          ENDIF
6122
6123          CALL MPI_Info_free(minfo, ierr)
6124          IF ( ierr /= 0 ) THEN
6125              WRITE(9,*) 'Error MPI_Info_free1:', ierr
6126              FLUSH(9)
6127          ENDIF
6128
6129!
6130!--       On Intel compilers, calling c_f_pointer to transform a C pointer
6131!--       directly to a multi-dimensional Fotran pointer leads to strange
6132!--       errors on dimension boundaries. However, transforming to a 1D
6133!--       pointer and then redirecting a multidimensional pointer to it works
6134!--       fine.
6135          CALL c_f_pointer(gridsurf_rma_p, gridsurf_rma, (/ nsurf_type_u*nzu*nny*nnx /))
6136          gridsurf(0:nsurf_type_u-1, nzub:nzut, nys:nyn, nxl:nxr) =>                &
6137                     gridsurf_rma(1:nsurf_type_u*nzu*nny*nnx)
6138#else
6139          ALLOCATE(gridsurf(0:nsurf_type_u-1,nzub:nzut,nys:nyn,nxl:nxr) )
6140#endif
6141          gridsurf(:,:,:,:) = -999
6142       ENDIF
6143
6144!--    add horizontal surface elements (land and urban surfaces)
6145!--    TODO: add urban overhanging surfaces (idown_u)
6146       DO i = nxl, nxr
6147           DO j = nys, nyn
6148              DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
6149                 k = surf_usm_h%k(m)
6150                 isurf = isurf + 1
6151                 surfl(:,isurf) = (/iup_u,k,j,i,m/)
6152                 IF ( rad_angular_discretization ) THEN
6153                    gridsurf(iup_u,k,j,i) = isurf
6154                 ENDIF
6155              ENDDO
6156
6157              DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6158                 k = surf_lsm_h%k(m)
6159                 isurf = isurf + 1
6160                 surfl(:,isurf) = (/iup_l,k,j,i,m/)
6161                 IF ( rad_angular_discretization ) THEN
6162                    gridsurf(iup_u,k,j,i) = isurf
6163                 ENDIF
6164              ENDDO
6165
6166           ENDDO
6167       ENDDO
6168
6169!--    add vertical surface elements (land and urban surfaces)
6170!--    TODO: remove the hard coding of l = 0 to l = idirection
6171       DO i = nxl, nxr
6172           DO j = nys, nyn
6173              l = 0
6174              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6175                 k = surf_usm_v(l)%k(m)
6176                 isurf = isurf + 1
6177                 surfl(:,isurf) = (/inorth_u,k,j,i,m/)
6178                 IF ( rad_angular_discretization ) THEN
6179                    gridsurf(inorth_u,k,j,i) = isurf
6180                 ENDIF
6181              ENDDO
6182              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6183                 k = surf_lsm_v(l)%k(m)
6184                 isurf = isurf + 1
6185                 surfl(:,isurf) = (/inorth_l,k,j,i,m/)
6186                 IF ( rad_angular_discretization ) THEN
6187                    gridsurf(inorth_u,k,j,i) = isurf
6188                 ENDIF
6189              ENDDO
6190
6191              l = 1
6192              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6193                 k = surf_usm_v(l)%k(m)
6194                 isurf = isurf + 1
6195                 surfl(:,isurf) = (/isouth_u,k,j,i,m/)
6196                 IF ( rad_angular_discretization ) THEN
6197                    gridsurf(isouth_u,k,j,i) = isurf
6198                 ENDIF
6199              ENDDO
6200              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6201                 k = surf_lsm_v(l)%k(m)
6202                 isurf = isurf + 1
6203                 surfl(:,isurf) = (/isouth_l,k,j,i,m/)
6204                 IF ( rad_angular_discretization ) THEN
6205                    gridsurf(isouth_u,k,j,i) = isurf
6206                 ENDIF
6207              ENDDO
6208
6209              l = 2
6210              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6211                 k = surf_usm_v(l)%k(m)
6212                 isurf = isurf + 1
6213                 surfl(:,isurf) = (/ieast_u,k,j,i,m/)
6214                 IF ( rad_angular_discretization ) THEN
6215                    gridsurf(ieast_u,k,j,i) = isurf
6216                 ENDIF
6217              ENDDO
6218              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6219                 k = surf_lsm_v(l)%k(m)
6220                 isurf = isurf + 1
6221                 surfl(:,isurf) = (/ieast_l,k,j,i,m/)
6222                 IF ( rad_angular_discretization ) THEN
6223                    gridsurf(ieast_u,k,j,i) = isurf
6224                 ENDIF
6225              ENDDO
6226
6227              l = 3
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) = (/iwest_u,k,j,i,m/)
6232                 IF ( rad_angular_discretization ) THEN
6233                    gridsurf(iwest_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) = (/iwest_l,k,j,i,m/)
6240                 IF ( rad_angular_discretization ) THEN
6241                    gridsurf(iwest_u,k,j,i) = isurf
6242                 ENDIF
6243              ENDDO
6244           ENDDO
6245       ENDDO
6246!
6247!--    Add local MRT boxes for specified number of levels
6248       nmrtbl = 0
6249       IF ( mrt_nlevels > 0 )  THEN
6250          DO  i = nxl, nxr
6251             DO  j = nys, nyn
6252                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
6253!
6254!--                Skip roof if requested
6255                   IF ( mrt_skip_roof  .AND.  surf_usm_h%isroof_surf(m) )  CYCLE
6256!
6257!--                Cycle over specified no of levels
6258                   nmrtbl = nmrtbl + mrt_nlevels
6259                ENDDO
6260!
6261!--             Dtto for LSM
6262                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6263                   nmrtbl = nmrtbl + mrt_nlevels
6264                ENDDO
6265             ENDDO
6266          ENDDO
6267
6268          ALLOCATE( mrtbl(iz:ix,nmrtbl), mrtsky(nmrtbl), mrtskyt(nmrtbl), &
6269                    mrtinsw(nmrtbl), mrtinlw(nmrtbl), mrt(nmrtbl) )
6270
6271          imrt = 0
6272          DO  i = nxl, nxr
6273             DO  j = nys, nyn
6274                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
6275!
6276!--                Skip roof if requested
6277                   IF ( mrt_skip_roof  .AND.  surf_usm_h%isroof_surf(m) )  CYCLE
6278!
6279!--                Cycle over specified no of levels
6280                   l = surf_usm_h%k(m)
6281                   DO  k = l, l + mrt_nlevels - 1
6282                      imrt = imrt + 1
6283                      mrtbl(:,imrt) = (/k,j,i/)
6284                   ENDDO
6285                ENDDO
6286!
6287!--             Dtto for LSM
6288                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6289                   l = surf_lsm_h%k(m)
6290                   DO  k = l, l + mrt_nlevels - 1
6291                      imrt = imrt + 1
6292                      mrtbl(:,imrt) = (/k,j,i/)
6293                   ENDDO
6294                ENDDO
6295             ENDDO
6296          ENDDO
6297       ENDIF
6298
6299!
6300!--    broadband albedo of the land, roof and wall surface
6301!--    for domain border and sky set artifically to 1.0
6302!--    what allows us to calculate heat flux leaving over
6303!--    side and top borders of the domain
6304       ALLOCATE ( albedo_surf(nsurfl) )
6305       albedo_surf = 1.0_wp
6306!
6307!--    Also allocate further array for emissivity with identical order of
6308!--    surface elements as radiation arrays.
6309       ALLOCATE ( emiss_surf(nsurfl)  )
6310
6311
6312!
6313!--    global array surf of indices of surfaces and displacement index array surfstart
6314       ALLOCATE(nsurfs(0:numprocs-1))
6315
6316#if defined( __parallel )
6317       CALL MPI_Allgather(nsurfl,1,MPI_INTEGER,nsurfs,1,MPI_INTEGER,comm2d,ierr)
6318       IF ( ierr /= 0 ) THEN
6319         WRITE(9,*) 'Error MPI_AllGather1:', ierr, nsurfl, nsurfs
6320         FLUSH(9)
6321     ENDIF
6322
6323#else
6324       nsurfs(0) = nsurfl
6325#endif
6326       ALLOCATE(surfstart(0:numprocs))
6327       k = 0
6328       DO i=0,numprocs-1
6329           surfstart(i) = k
6330           k = k+nsurfs(i)
6331       ENDDO
6332       surfstart(numprocs) = k
6333       nsurf = k
6334       ALLOCATE(surf_l(5*nsurf))
6335       surf(1:5,1:nsurf) => surf_l(1:5*nsurf)
6336
6337#if defined( __parallel )
6338       CALL MPI_AllGatherv(surfl_l, nsurfl*5, MPI_INTEGER, surf_l, nsurfs*5, &
6339           surfstart(0:numprocs-1)*5, MPI_INTEGER, comm2d, ierr)
6340       IF ( ierr /= 0 ) THEN
6341           WRITE(9,*) 'Error MPI_AllGatherv4:', ierr, SIZE(surfl_l), nsurfl*5, &
6342                      SIZE(surf_l), nsurfs*5, surfstart(0:numprocs-1)*5
6343           FLUSH(9)
6344       ENDIF
6345#else
6346       surf = surfl
6347#endif
6348
6349!--
6350!--    allocation of the arrays for direct and diffusion radiation
6351       CALL location_message( '    allocation of radiation arrays', .TRUE. )
6352!--    rad_sw_in, rad_lw_in are computed in radiation model,
6353!--    splitting of direct and diffusion part is done
6354!--    in calc_diffusion_radiation for now
6355
6356       ALLOCATE( rad_sw_in_dir(nysg:nyng,nxlg:nxrg) )
6357       ALLOCATE( rad_sw_in_diff(nysg:nyng,nxlg:nxrg) )
6358       ALLOCATE( rad_lw_in_diff(nysg:nyng,nxlg:nxrg) )
6359       rad_sw_in_dir  = 0.0_wp
6360       rad_sw_in_diff = 0.0_wp
6361       rad_lw_in_diff = 0.0_wp
6362
6363!--    allocate radiation arrays
6364       ALLOCATE( surfins(nsurfl) )
6365       ALLOCATE( surfinl(nsurfl) )
6366       ALLOCATE( surfinsw(nsurfl) )
6367       ALLOCATE( surfinlw(nsurfl) )
6368       ALLOCATE( surfinswdir(nsurfl) )
6369       ALLOCATE( surfinswdif(nsurfl) )
6370       ALLOCATE( surfinlwdif(nsurfl) )
6371       ALLOCATE( surfoutsl(nsurfl) )
6372       ALLOCATE( surfoutll(nsurfl) )
6373       ALLOCATE( surfoutsw(nsurfl) )
6374       ALLOCATE( surfoutlw(nsurfl) )
6375       ALLOCATE( surfouts(nsurf) )
6376       ALLOCATE( surfoutl(nsurf) )
6377       ALLOCATE( surfinlg(nsurf) )
6378       ALLOCATE( skyvf(nsurfl) )
6379       ALLOCATE( skyvft(nsurfl) )
6380       ALLOCATE( surfemitlwl(nsurfl) )
6381
6382!
6383!--    In case of average_radiation, aggregated surface albedo and emissivity,
6384!--    also set initial value for t_rad_urb.
6385!--    For now set an arbitrary initial value.
6386       IF ( average_radiation )  THEN
6387          albedo_urb = 0.1_wp
6388          emissivity_urb = 0.9_wp
6389          t_rad_urb = pt_surface
6390       ENDIF
6391
6392    END SUBROUTINE radiation_interaction_init
6393
6394!------------------------------------------------------------------------------!
6395! Description:
6396! ------------
6397!> Calculates shape view factors (SVF), plant sink canopy factors (PCSF),
6398!> sky-view factors, discretized path for direct solar radiation, MRT factors
6399!> and other preprocessed data needed for radiation_interaction.
6400!------------------------------------------------------------------------------!
6401    SUBROUTINE radiation_calc_svf
6402   
6403        IMPLICIT NONE
6404       
6405        INTEGER(iwp)                                  :: i, j, k, d, ip, jp
6406        INTEGER(iwp)                                  :: isvf, ksvf, icsf, kcsf, npcsfl, isvf_surflt, imrt, imrtf, ipcgb
6407        INTEGER(iwp)                                  :: sd, td
6408        INTEGER(iwp)                                  :: iaz, izn      !< azimuth, zenith counters
6409        INTEGER(iwp)                                  :: naz, nzn      !< azimuth, zenith num of steps
6410        REAL(wp)                                      :: az0, zn0      !< starting azimuth/zenith
6411        REAL(wp)                                      :: azs, zns      !< azimuth/zenith cycle step
6412        REAL(wp)                                      :: az1, az2      !< relative azimuth of section borders
6413        REAL(wp)                                      :: azmid         !< ray (center) azimuth
6414        REAL(wp)                                      :: yxlen         !< |yxdir|
6415        REAL(wp), DIMENSION(2)                        :: yxdir         !< y,x *unit* vector of ray direction (in grid units)
6416        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zdirs         !< directions in z (tangent of elevation)
6417        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zcent         !< zenith angle centers
6418        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zbdry         !< zenith angle boundaries
6419        REAL(wp), DIMENSION(:), ALLOCATABLE           :: vffrac        !< view factor fractions for individual rays
6420        REAL(wp), DIMENSION(:), ALLOCATABLE           :: vffrac0       !< dtto (original values)
6421        REAL(wp), DIMENSION(:), ALLOCATABLE           :: ztransp       !< array of transparency in z steps
6422        INTEGER(iwp)                                  :: lowest_free_ray !< index into zdirs
6423        INTEGER(iwp), DIMENSION(:), ALLOCATABLE       :: itarget       !< face indices of detected obstacles
6424        INTEGER(iwp)                                  :: itarg0, itarg1
6425
6426        INTEGER(iwp)                                  :: udim
6427        INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET:: nzterrl_l
6428        INTEGER(iwp), DIMENSION(:,:), POINTER         :: nzterrl
6429        REAL(wp),     DIMENSION(:), ALLOCATABLE,TARGET:: csflt_l, pcsflt_l
6430        REAL(wp),     DIMENSION(:,:), POINTER         :: csflt, pcsflt
6431        INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET:: kcsflt_l,kpcsflt_l
6432        INTEGER(iwp), DIMENSION(:,:), POINTER         :: kcsflt,kpcsflt
6433        INTEGER(iwp), DIMENSION(:), ALLOCATABLE       :: icsflt,dcsflt,ipcsflt,dpcsflt
6434        REAL(wp), DIMENSION(3)                        :: uv
6435        LOGICAL                                       :: visible
6436        REAL(wp), DIMENSION(3)                        :: sa, ta          !< real coordinates z,y,x of source and target
6437        REAL(wp)                                      :: difvf           !< differential view factor
6438        REAL(wp)                                      :: transparency, rirrf, sqdist, svfsum
6439        INTEGER(iwp)                                  :: isurflt, isurfs, isurflt_prev
6440        INTEGER(idp)                                  :: ray_skip_maxdist, ray_skip_minval !< skipped raytracing counts
6441        INTEGER(iwp)                                  :: max_track_len !< maximum 2d track length
6442        INTEGER(iwp)                                  :: minfo
6443        REAL(wp), DIMENSION(:), POINTER               :: lad_s_rma       !< fortran 1D pointer
6444        TYPE(c_ptr)                                   :: lad_s_rma_p     !< allocated c pointer
6445#if defined( __parallel )
6446        INTEGER(kind=MPI_ADDRESS_KIND)                :: size_lad_rma
6447#endif
6448!   
6449        INTEGER(iwp), DIMENSION(0:svfnorm_report_num) :: svfnorm_counts
6450        CHARACTER(200)                                :: msg
6451
6452!--     calculation of the SVF
6453        CALL location_message( '    calculation of SVF and CSF', .TRUE. )
6454        CALL radiation_write_debug_log('Start calculation of SVF and CSF')
6455
6456!--     initialize variables and temporary arrays for calculation of svf and csf
6457        nsvfl  = 0
6458        ncsfl  = 0
6459        nsvfla = gasize
6460        msvf   = 1
6461        ALLOCATE( asvf1(nsvfla) )
6462        asvf => asvf1
6463        IF ( plant_canopy )  THEN
6464            ncsfla = gasize
6465            mcsf   = 1
6466            ALLOCATE( acsf1(ncsfla) )
6467            acsf => acsf1
6468        ENDIF
6469        nmrtf = 0
6470        IF ( mrt_nlevels > 0 )  THEN
6471           nmrtfa = gasize
6472           mmrtf = 1
6473           ALLOCATE ( amrtf1(nmrtfa) )
6474           amrtf => amrtf1
6475        ENDIF
6476        ray_skip_maxdist = 0
6477        ray_skip_minval = 0
6478       
6479!--     initialize temporary terrain and plant canopy height arrays (global 2D array!)
6480        ALLOCATE( nzterr(0:(nx+1)*(ny+1)-1) )
6481#if defined( __parallel )
6482        !ALLOCATE( nzterrl(nys:nyn,nxl:nxr) )
6483        ALLOCATE( nzterrl_l((nyn-nys+1)*(nxr-nxl+1)) )
6484        nzterrl(nys:nyn,nxl:nxr) => nzterrl_l(1:(nyn-nys+1)*(nxr-nxl+1))
6485        nzterrl = get_topography_top_index( 's' )
6486        CALL MPI_AllGather( nzterrl_l, nnx*nny, MPI_INTEGER, &
6487                            nzterr, nnx*nny, MPI_INTEGER, comm2d, ierr )
6488        IF ( ierr /= 0 ) THEN
6489            WRITE(9,*) 'Error MPI_AllGather1:', ierr, SIZE(nzterrl_l), nnx*nny, &
6490                       SIZE(nzterr), nnx*nny
6491            FLUSH(9)
6492        ENDIF
6493        DEALLOCATE(nzterrl_l)
6494#else
6495        nzterr = RESHAPE( get_topography_top_index( 's' ), (/(nx+1)*(ny+1)/) )
6496#endif
6497        IF ( plant_canopy )  THEN
6498            ALLOCATE( plantt(0:(nx+1)*(ny+1)-1) )
6499            maxboxesg = nx + ny + nzp + 1
6500            max_track_len = nx + ny + 1
6501!--         temporary arrays storing values for csf calculation during raytracing
6502            ALLOCATE( boxes(3, maxboxesg) )
6503            ALLOCATE( crlens(maxboxesg) )
6504
6505#if defined( __parallel )
6506            CALL MPI_AllGather( pct, nnx*nny, MPI_INTEGER, &
6507                                plantt, nnx*nny, MPI_INTEGER, comm2d, ierr )
6508            IF ( ierr /= 0 ) THEN
6509                WRITE(9,*) 'Error MPI_AllGather2:', ierr, SIZE(pct), nnx*nny, &
6510                           SIZE(plantt), nnx*nny
6511                FLUSH(9)
6512            ENDIF
6513
6514!--         temporary arrays storing values for csf calculation during raytracing
6515            ALLOCATE( lad_ip(maxboxesg) )
6516            ALLOCATE( lad_disp(maxboxesg) )
6517
6518            IF ( raytrace_mpi_rma )  THEN
6519                ALLOCATE( lad_s_ray(maxboxesg) )
6520               
6521                ! set conditions for RMA communication
6522                CALL MPI_Info_create(minfo, ierr)
6523                IF ( ierr /= 0 ) THEN
6524                    WRITE(9,*) 'Error MPI_Info_create2:', ierr
6525                    FLUSH(9)
6526                ENDIF
6527                CALL MPI_Info_set(minfo, 'accumulate_ordering', '', ierr)
6528                IF ( ierr /= 0 ) THEN
6529                    WRITE(9,*) 'Error MPI_Info_set5:', ierr
6530                    FLUSH(9)
6531                ENDIF
6532                CALL MPI_Info_set(minfo, 'accumulate_ops', 'same_op', ierr)
6533                IF ( ierr /= 0 ) THEN
6534                    WRITE(9,*) 'Error MPI_Info_set6:', ierr
6535                    FLUSH(9)
6536                ENDIF
6537                CALL MPI_Info_set(minfo, 'same_size', 'true', ierr)
6538                IF ( ierr /= 0 ) THEN
6539                    WRITE(9,*) 'Error MPI_Info_set7:', ierr
6540                    FLUSH(9)
6541                ENDIF
6542                CALL MPI_Info_set(minfo, 'same_disp_unit', 'true', ierr)
6543                IF ( ierr /= 0 ) THEN
6544                    WRITE(9,*) 'Error MPI_Info_set8:', ierr
6545                    FLUSH(9)
6546                ENDIF
6547
6548!--             Allocate and initialize the MPI RMA window
6549!--             must be in accordance with allocation of lad_s in plant_canopy_model
6550!--             optimization of memory should be done
6551!--             Argument X of function STORAGE_SIZE(X) needs arbitrary REAL(wp) value, set to 1.0_wp for now
6552                size_lad_rma = STORAGE_SIZE(1.0_wp)/8*nnx*nny*nzp
6553                CALL MPI_Win_allocate(size_lad_rma, STORAGE_SIZE(1.0_wp)/8, minfo, comm2d, &
6554                                        lad_s_rma_p, win_lad, ierr)
6555                IF ( ierr /= 0 ) THEN
6556                    WRITE(9,*) 'Error MPI_Win_allocate2:', ierr, size_lad_rma, &
6557                                STORAGE_SIZE(1.0_wp)/8, win_lad
6558                    FLUSH(9)
6559                ENDIF
6560                CALL c_f_pointer(lad_s_rma_p, lad_s_rma, (/ nzp*nny*nnx /))
6561                sub_lad(nzub:nzpt, nys:nyn, nxl:nxr) => lad_s_rma(1:nzp*nny*nnx)
6562            ELSE
6563                ALLOCATE(sub_lad(nzub:nzpt, nys:nyn, nxl:nxr))
6564            ENDIF
6565#else
6566            plantt = RESHAPE( pct(nys:nyn,nxl:nxr), (/(nx+1)*(ny+1)/) )
6567            ALLOCATE(sub_lad(nzub:nzpt, nys:nyn, nxl:nxr))
6568#endif
6569            plantt_max = MAXVAL(plantt)
6570            ALLOCATE( rt2_track(2, max_track_len), rt2_track_lad(nzub:plantt_max, max_track_len), &
6571                      rt2_track_dist(0:max_track_len), rt2_dist(plantt_max-nzub+2) )
6572
6573            sub_lad(:,:,:) = 0._wp
6574            DO i = nxl, nxr
6575                DO j = nys, nyn
6576                    k = get_topography_top_index_ji( j, i, 's' )
6577
6578                    sub_lad(k:nzpt, j, i) = lad_s(0:nzpt-k, j, i)
6579                ENDDO
6580            ENDDO
6581
6582#if defined( __parallel )
6583            IF ( raytrace_mpi_rma )  THEN
6584                CALL MPI_Info_free(minfo, ierr)
6585                IF ( ierr /= 0 ) THEN
6586                    WRITE(9,*) 'Error MPI_Info_free2:', ierr
6587                    FLUSH(9)
6588                ENDIF
6589                CALL MPI_Win_lock_all(0, win_lad, ierr)
6590                IF ( ierr /= 0 ) THEN
6591                    WRITE(9,*) 'Error MPI_Win_lock_all1:', ierr, win_lad
6592                    FLUSH(9)
6593                ENDIF
6594               
6595            ELSE
6596                ALLOCATE( sub_lad_g(0:(nx+1)*(ny+1)*nzp-1) )
6597                CALL MPI_AllGather( sub_lad, nnx*nny*nzp, MPI_REAL, &
6598                                    sub_lad_g, nnx*nny*nzp, MPI_REAL, comm2d, ierr )
6599                IF ( ierr /= 0 ) THEN
6600                    WRITE(9,*) 'Error MPI_AllGather3:', ierr, SIZE(sub_lad), &
6601                                nnx*nny*nzp, SIZE(sub_lad_g), nnx*nny*nzp
6602                    FLUSH(9)
6603                ENDIF
6604            ENDIF
6605#endif
6606        ENDIF
6607
6608!--     prepare the MPI_Win for collecting the surface indices
6609!--     from the reverse index arrays gridsurf from processors of target surfaces
6610#if defined( __parallel )
6611        IF ( rad_angular_discretization )  THEN
6612!
6613!--         raytrace_mpi_rma is asserted
6614            CALL MPI_Win_lock_all(0, win_gridsurf, ierr)
6615            IF ( ierr /= 0 ) THEN
6616                WRITE(9,*) 'Error MPI_Win_lock_all2:', ierr, win_gridsurf
6617                FLUSH(9)
6618            ENDIF
6619        ENDIF
6620#endif
6621
6622
6623        !--Directions opposite to face normals are not even calculated,
6624        !--they must be preset to 0
6625        !--
6626        dsitrans(:,:) = 0._wp
6627       
6628        DO isurflt = 1, nsurfl
6629!--         determine face centers
6630            td = surfl(id, isurflt)
6631            ta = (/ REAL(surfl(iz, isurflt), wp) - 0.5_wp * kdir(td),  &
6632                      REAL(surfl(iy, isurflt), wp) - 0.5_wp * jdir(td),  &
6633                      REAL(surfl(ix, isurflt), wp) - 0.5_wp * idir(td)  /)
6634
6635            !--Calculate sky view factor and raytrace DSI paths
6636            skyvf(isurflt) = 0._wp
6637            skyvft(isurflt) = 0._wp
6638
6639            !--Select a proper half-sphere for 2D raytracing
6640            SELECT CASE ( td )
6641               CASE ( iup_u, iup_l )
6642                  az0 = 0._wp
6643                  naz = raytrace_discrete_azims
6644                  azs = 2._wp * pi / REAL(naz, wp)
6645                  zn0 = 0._wp
6646                  nzn = raytrace_discrete_elevs / 2
6647                  zns = pi / 2._wp / REAL(nzn, wp)
6648               CASE ( isouth_u, isouth_l )
6649                  az0 = pi / 2._wp
6650                  naz = raytrace_discrete_azims / 2
6651                  azs = pi / REAL(naz, wp)
6652                  zn0 = 0._wp
6653                  nzn = raytrace_discrete_elevs
6654                  zns = pi / REAL(nzn, wp)
6655               CASE ( inorth_u, inorth_l )
6656                  az0 = - pi / 2._wp
6657                  naz = raytrace_discrete_azims / 2
6658                  azs = pi / REAL(naz, wp)
6659                  zn0 = 0._wp
6660                  nzn = raytrace_discrete_elevs
6661                  zns = pi / REAL(nzn, wp)
6662               CASE ( iwest_u, iwest_l )
6663                  az0 = pi
6664                  naz = raytrace_discrete_azims / 2
6665                  azs = pi / REAL(naz, wp)
6666                  zn0 = 0._wp
6667                  nzn = raytrace_discrete_elevs
6668                  zns = pi / REAL(nzn, wp)
6669               CASE ( ieast_u, ieast_l )
6670                  az0 = 0._wp
6671                  naz = raytrace_discrete_azims / 2
6672                  azs = pi / REAL(naz, wp)
6673                  zn0 = 0._wp
6674                  nzn = raytrace_discrete_elevs
6675                  zns = pi / REAL(nzn, wp)
6676               CASE DEFAULT
6677                  WRITE(message_string, *) 'ERROR: the surface type ', td,     &
6678                                           ' is not supported for calculating',&
6679                                           ' SVF'
6680                  CALL message( 'radiation_calc_svf', 'PA0488', 1, 2, 0, 6, 0 )
6681            END SELECT
6682
6683            ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), zbdry(0:nzn), vffrac(1:nzn*naz), &
6684                       ztransp(1:nzn*naz), itarget(1:nzn*naz) )   !FIXME allocate itarget only
6685                                                                  !in case of rad_angular_discretization
6686
6687            itarg0 = 1
6688            itarg1 = nzn
6689            zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
6690            zbdry(:) = (/( zn0+REAL(izn,wp)*zns, izn=0, nzn )/)
6691            IF ( td == iup_u  .OR.  td == iup_l )  THEN
6692               vffrac(1:nzn) = (COS(2 * zbdry(0:nzn-1)) - COS(2 * zbdry(1:nzn))) / 2._wp / REAL(naz, wp)
6693!
6694!--            For horizontal target, vf fractions are constant per azimuth
6695               DO iaz = 1, naz-1
6696                  vffrac(iaz*nzn+1:(iaz+1)*nzn) = vffrac(1:nzn)
6697               ENDDO
6698!--            sum of whole vffrac equals 1, verified
6699            ENDIF
6700!
6701!--         Calculate sky-view factor and direct solar visibility using 2D raytracing
6702            DO iaz = 1, naz
6703               azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
6704               IF ( td /= iup_u  .AND.  td /= iup_l )  THEN
6705                  az2 = REAL(iaz, wp) * azs - pi/2._wp
6706                  az1 = az2 - azs
6707                  !TODO precalculate after 1st line
6708                  vffrac(itarg0:itarg1) = (SIN(az2) - SIN(az1))               &
6709                              * (zbdry(1:nzn) - zbdry(0:nzn-1)                &
6710                                 + SIN(zbdry(0:nzn-1))*COS(zbdry(0:nzn-1))    &
6711                                 - SIN(zbdry(1:nzn))*COS(zbdry(1:nzn)))       &
6712                              / (2._wp * pi)
6713!--               sum of whole vffrac equals 1, verified
6714               ENDIF
6715               yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
6716               yxlen = SQRT(SUM(yxdir(:)**2))
6717               zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
6718               yxdir(:) = yxdir(:) / yxlen
6719
6720               CALL raytrace_2d(ta, yxdir, nzn, zdirs,                        &
6721                                    surfstart(myid) + isurflt, facearea(td),  &
6722                                    vffrac(itarg0:itarg1), .TRUE., .TRUE.,    &
6723                                    .FALSE., lowest_free_ray,                 &
6724                                    ztransp(itarg0:itarg1),                   &
6725                                    itarget(itarg0:itarg1))
6726
6727               skyvf(isurflt) = skyvf(isurflt) + &
6728                                SUM(vffrac(itarg0:itarg0+lowest_free_ray-1))
6729               skyvft(isurflt) = skyvft(isurflt) + &
6730                                 SUM(ztransp(itarg0:itarg0+lowest_free_ray-1) &
6731                                             * vffrac(itarg0:itarg0+lowest_free_ray-1))
6732 
6733!--            Save direct solar transparency
6734               j = MODULO(NINT(azmid/                                          &
6735                               (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
6736                          raytrace_discrete_azims)
6737
6738               DO k = 1, raytrace_discrete_elevs/2
6739                  i = dsidir_rev(k-1, j)
6740                  IF ( i /= -1  .AND.  k <= lowest_free_ray )  &
6741                     dsitrans(isurflt, i) = ztransp(itarg0+k-1)
6742               ENDDO
6743
6744!
6745!--            Advance itarget indices
6746               itarg0 = itarg1 + 1
6747               itarg1 = itarg1 + nzn
6748            ENDDO
6749
6750            IF ( rad_angular_discretization )  THEN
6751!--            sort itarget by face id
6752               CALL quicksort_itarget(itarget,vffrac,ztransp,1,nzn*naz)
6753!
6754!--            For aggregation, we need fractions multiplied by transmissivities
6755               ztransp(:) = vffrac(:) * ztransp(:)
6756!
6757!--            find the first valid position
6758               itarg0 = 1
6759               DO WHILE ( itarg0 <= nzn*naz )
6760                  IF ( itarget(itarg0) /= -1 )  EXIT
6761                  itarg0 = itarg0 + 1
6762               ENDDO
6763
6764               DO  i = itarg0, nzn*naz
6765!
6766!--               For duplicate values, only sum up vf fraction value
6767                  IF ( i < nzn*naz )  THEN
6768                     IF ( itarget(i+1) == itarget(i) )  THEN
6769                        vffrac(i+1) = vffrac(i+1) + vffrac(i)
6770                        ztransp(i+1) = ztransp(i+1) + ztransp(i)
6771                        CYCLE
6772                     ENDIF
6773                  ENDIF
6774!
6775!--               write to the svf array
6776                  nsvfl = nsvfl + 1
6777!--               check dimmension of asvf array and enlarge it if needed
6778                  IF ( nsvfla < nsvfl )  THEN
6779                     k = CEILING(REAL(nsvfla, kind=wp) * grow_factor)
6780                     IF ( msvf == 0 )  THEN
6781                        msvf = 1
6782                        ALLOCATE( asvf1(k) )
6783                        asvf => asvf1
6784                        asvf1(1:nsvfla) = asvf2
6785                        DEALLOCATE( asvf2 )
6786                     ELSE
6787                        msvf = 0
6788                        ALLOCATE( asvf2(k) )
6789                        asvf => asvf2
6790                        asvf2(1:nsvfla) = asvf1
6791                        DEALLOCATE( asvf1 )
6792                     ENDIF
6793
6794                     WRITE (msg,'(A,3I12)') 'Grow asvf:',nsvfl,nsvfla,k
6795                     CALL radiation_write_debug_log( msg )
6796                     
6797                     nsvfla = k
6798                  ENDIF
6799!--               write svf values into the array
6800                  asvf(nsvfl)%isurflt = isurflt
6801                  asvf(nsvfl)%isurfs = itarget(i)
6802                  asvf(nsvfl)%rsvf = vffrac(i)
6803                  asvf(nsvfl)%rtransp = ztransp(i) / vffrac(i)
6804               END DO
6805
6806            ENDIF ! rad_angular_discretization
6807
6808            DEALLOCATE ( zdirs, zcent, zbdry, vffrac, ztransp, itarget ) !FIXME itarget shall be allocated only
6809                                                                  !in case of rad_angular_discretization
6810!
6811!--         Following calculations only required for surface_reflections
6812            IF ( surface_reflections  .AND.  .NOT. rad_angular_discretization )  THEN
6813
6814               DO  isurfs = 1, nsurf
6815                  IF ( .NOT.  surface_facing(surfl(ix, isurflt), surfl(iy, isurflt), &
6816                     surfl(iz, isurflt), surfl(id, isurflt), &
6817                     surf(ix, isurfs), surf(iy, isurfs), &
6818                     surf(iz, isurfs), surf(id, isurfs)) )  THEN
6819                     CYCLE
6820                  ENDIF
6821                 
6822                  sd = surf(id, isurfs)
6823                  sa = (/ REAL(surf(iz, isurfs), wp) - 0.5_wp * kdir(sd),  &
6824                          REAL(surf(iy, isurfs), wp) - 0.5_wp * jdir(sd),  &
6825                          REAL(surf(ix, isurfs), wp) - 0.5_wp * idir(sd)  /)
6826
6827!--               unit vector source -> target
6828                  uv = (/ (ta(1)-sa(1))*dz(1), (ta(2)-sa(2))*dy, (ta(3)-sa(3))*dx /)
6829                  sqdist = SUM(uv(:)**2)
6830                  uv = uv / SQRT(sqdist)
6831
6832!--               reject raytracing above max distance
6833                  IF ( SQRT(sqdist) > max_raytracing_dist ) THEN
6834                     ray_skip_maxdist = ray_skip_maxdist + 1
6835                     CYCLE
6836                  ENDIF
6837                 
6838                  difvf = dot_product((/ kdir(sd), jdir(sd), idir(sd) /), uv) & ! cosine of source normal and direction
6839                      * dot_product((/ kdir(td), jdir(td), idir(td) /), -uv) &  ! cosine of target normal and reverse direction
6840                      / (pi * sqdist) ! square of distance between centers
6841!
6842!--               irradiance factor (our unshaded shape view factor) = view factor per differential target area * source area
6843                  rirrf = difvf * facearea(sd)
6844
6845!--               reject raytracing for potentially too small view factor values
6846                  IF ( rirrf < min_irrf_value ) THEN
6847                      ray_skip_minval = ray_skip_minval + 1
6848                      CYCLE
6849                  ENDIF
6850
6851!--               raytrace + process plant canopy sinks within
6852                  CALL raytrace(sa, ta, isurfs, difvf, facearea(td), .TRUE., &
6853                                visible, transparency)
6854
6855                  IF ( .NOT.  visible ) CYCLE
6856                 ! rsvf = rirrf * transparency
6857
6858!--               write to the svf array
6859                  nsvfl = nsvfl + 1
6860!--               check dimmension of asvf array and enlarge it if needed
6861                  IF ( nsvfla < nsvfl )  THEN
6862                     k = CEILING(REAL(nsvfla, kind=wp) * grow_factor)
6863                     IF ( msvf == 0 )  THEN
6864                        msvf = 1
6865                        ALLOCATE( asvf1(k) )
6866                        asvf => asvf1
6867                        asvf1(1:nsvfla) = asvf2
6868                        DEALLOCATE( asvf2 )
6869                     ELSE
6870                        msvf = 0
6871                        ALLOCATE( asvf2(k) )
6872                        asvf => asvf2
6873                        asvf2(1:nsvfla) = asvf1
6874                        DEALLOCATE( asvf1 )
6875                     ENDIF
6876
6877                     WRITE(msg,'(A,3I12)') 'Grow asvf:',nsvfl,nsvfla,k
6878                     CALL radiation_write_debug_log( msg )
6879                     
6880                     nsvfla = k
6881                  ENDIF
6882!--               write svf values into the array
6883                  asvf(nsvfl)%isurflt = isurflt
6884                  asvf(nsvfl)%isurfs = isurfs
6885                  asvf(nsvfl)%rsvf = rirrf !we postopne multiplication by transparency
6886                  asvf(nsvfl)%rtransp = transparency !a.k.a. Direct Irradiance Factor
6887               ENDDO
6888            ENDIF
6889        ENDDO
6890
6891!--
6892!--     Raytrace to canopy boxes to fill dsitransc TODO optimize
6893        dsitransc(:,:) = 0._wp
6894        az0 = 0._wp
6895        naz = raytrace_discrete_azims
6896        azs = 2._wp * pi / REAL(naz, wp)
6897        zn0 = 0._wp
6898        nzn = raytrace_discrete_elevs / 2
6899        zns = pi / 2._wp / REAL(nzn, wp)
6900        ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), vffrac(1:nzn), ztransp(1:nzn), &
6901               itarget(1:nzn) )
6902        zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
6903        vffrac(:) = 0._wp
6904
6905        DO  ipcgb = 1, npcbl
6906           ta = (/ REAL(pcbl(iz, ipcgb), wp),  &
6907                   REAL(pcbl(iy, ipcgb), wp),  &
6908                   REAL(pcbl(ix, ipcgb), wp) /)
6909!--        Calculate direct solar visibility using 2D raytracing
6910           DO  iaz = 1, naz
6911              azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
6912              yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
6913              yxlen = SQRT(SUM(yxdir(:)**2))
6914              zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
6915              yxdir(:) = yxdir(:) / yxlen
6916              CALL raytrace_2d(ta, yxdir, nzn, zdirs,                                &
6917                                   -999, -999._wp, vffrac, .FALSE., .FALSE., .TRUE., &
6918                                   lowest_free_ray, ztransp, itarget)
6919
6920!--           Save direct solar transparency
6921              j = MODULO(NINT(azmid/                                         &
6922                             (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
6923                         raytrace_discrete_azims)
6924              DO  k = 1, raytrace_discrete_elevs/2
6925                 i = dsidir_rev(k-1, j)
6926                 IF ( i /= -1  .AND.  k <= lowest_free_ray ) &
6927                    dsitransc(ipcgb, i) = ztransp(k)
6928              ENDDO
6929           ENDDO
6930        ENDDO
6931        DEALLOCATE ( zdirs, zcent, vffrac, ztransp, itarget )
6932!--
6933!--     Raytrace to MRT boxes
6934        IF ( nmrtbl > 0 )  THEN
6935           mrtdsit(:,:) = 0._wp
6936           mrtsky(:) = 0._wp
6937           mrtskyt(:) = 0._wp
6938           az0 = 0._wp
6939           naz = raytrace_discrete_azims
6940           azs = 2._wp * pi / REAL(naz, wp)
6941           zn0 = 0._wp
6942           nzn = raytrace_discrete_elevs
6943           zns = pi / REAL(nzn, wp)
6944           ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), zbdry(0:nzn), vffrac(1:nzn*naz), vffrac0(1:nzn), &
6945                      ztransp(1:nzn*naz), itarget(1:nzn*naz) )   !FIXME allocate itarget only
6946                                                                 !in case of rad_angular_discretization
6947
6948           zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
6949           zbdry(:) = (/( zn0+REAL(izn,wp)*zns, izn=0, nzn )/)
6950           vffrac0(:) = (COS(zbdry(0:nzn-1)) - COS(zbdry(1:nzn))) / 2._wp / REAL(naz, wp)
6951           !
6952           !--Modify direction weights to simulate human body (lower weight for top-down)
6953           IF ( mrt_geom_human )  THEN
6954              vffrac0(:) = vffrac0(:) * MAX(0._wp, SIN(zcent(:))*0.88_wp + COS(zcent(:))*0.12_wp)
6955              vffrac0(:) = vffrac0(:) / (SUM(vffrac0) * REAL(naz, wp))
6956           ENDIF
6957
6958           DO  imrt = 1, nmrtbl
6959              ta = (/ REAL(mrtbl(iz, imrt), wp),  &
6960                      REAL(mrtbl(iy, imrt), wp),  &
6961                      REAL(mrtbl(ix, imrt), wp) /)
6962!
6963!--           vf fractions are constant per azimuth
6964              DO iaz = 0, naz-1
6965                 vffrac(iaz*nzn+1:(iaz+1)*nzn) = vffrac0(:)
6966              ENDDO
6967!--           sum of whole vffrac equals 1, verified
6968              itarg0 = 1
6969              itarg1 = nzn
6970!
6971!--           Calculate sky-view factor and direct solar visibility using 2D raytracing
6972              DO  iaz = 1, naz
6973                 azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
6974                 yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
6975                 yxlen = SQRT(SUM(yxdir(:)**2))
6976                 zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
6977                 yxdir(:) = yxdir(:) / yxlen
6978
6979                 CALL raytrace_2d(ta, yxdir, nzn, zdirs,                         &
6980                                  -999, -999._wp, vffrac(itarg0:itarg1), .TRUE., &
6981                                  .FALSE., .TRUE., lowest_free_ray,              &
6982                                  ztransp(itarg0:itarg1),                        &
6983                                  itarget(itarg0:itarg1))
6984
6985!--              Sky view factors for MRT
6986                 mrtsky(imrt) = mrtsky(imrt) + &
6987                                  SUM(vffrac(itarg0:itarg0+lowest_free_ray-1))
6988                 mrtskyt(imrt) = mrtskyt(imrt) + &
6989                                   SUM(ztransp(itarg0:itarg0+lowest_free_ray-1) &
6990                                               * vffrac(itarg0:itarg0+lowest_free_ray-1))
6991!--              Direct solar transparency for MRT
6992                 j = MODULO(NINT(azmid/                                         &
6993                                (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
6994                            raytrace_discrete_azims)
6995                 DO  k = 1, raytrace_discrete_elevs/2
6996                    i = dsidir_rev(k-1, j)
6997                    IF ( i /= -1  .AND.  k <= lowest_free_ray ) &
6998                       mrtdsit(imrt, i) = ztransp(itarg0+k-1)
6999                 ENDDO
7000!
7001!--              Advance itarget indices
7002                 itarg0 = itarg1 + 1
7003                 itarg1 = itarg1 + nzn
7004              ENDDO
7005
7006!--           sort itarget by face id
7007              CALL quicksort_itarget(itarget,vffrac,ztransp,1,nzn*naz)
7008!
7009!--           find the first valid position
7010              itarg0 = 1
7011              DO WHILE ( itarg0 <= nzn*naz )
7012                 IF ( itarget(itarg0) /= -1 )  EXIT
7013                 itarg0 = itarg0 + 1
7014              ENDDO
7015
7016              DO  i = itarg0, nzn*naz
7017!
7018!--              For duplicate values, only sum up vf fraction value
7019                 IF ( i < nzn*naz )  THEN
7020                    IF ( itarget(i+1) == itarget(i) )  THEN
7021                       vffrac(i+1) = vffrac(i+1) + vffrac(i)
7022                       CYCLE
7023                    ENDIF
7024                 ENDIF
7025!
7026!--              write to the mrtf array
7027                 nmrtf = nmrtf + 1
7028!--              check dimmension of mrtf array and enlarge it if needed
7029                 IF ( nmrtfa < nmrtf )  THEN
7030                    k = CEILING(REAL(nmrtfa, kind=wp) * grow_factor)
7031                    IF ( mmrtf == 0 )  THEN
7032                       mmrtf = 1
7033                       ALLOCATE( amrtf1(k) )
7034                       amrtf => amrtf1
7035                       amrtf1(1:nmrtfa) = amrtf2
7036                       DEALLOCATE( amrtf2 )
7037                    ELSE
7038                       mmrtf = 0
7039                       ALLOCATE( amrtf2(k) )
7040                       amrtf => amrtf2
7041                       amrtf2(1:nmrtfa) = amrtf1
7042                       DEALLOCATE( amrtf1 )
7043                    ENDIF
7044
7045                    WRITE (msg,'(A,3I12)') 'Grow amrtf:', nmrtf, nmrtfa, k
7046                    CALL radiation_write_debug_log( msg )
7047
7048                    nmrtfa = k
7049                 ENDIF
7050!--              write mrtf values into the array
7051                 amrtf(nmrtf)%isurflt = imrt
7052                 amrtf(nmrtf)%isurfs = itarget(i)
7053                 amrtf(nmrtf)%rsvf = vffrac(i)
7054                 amrtf(nmrtf)%rtransp = ztransp(i)
7055              ENDDO ! itarg
7056
7057           ENDDO ! imrt
7058           DEALLOCATE ( zdirs, zcent, zbdry, vffrac, vffrac0, ztransp, itarget )
7059!
7060!--        Move MRT factors to final arrays
7061           ALLOCATE ( mrtf(nmrtf), mrtft(nmrtf), mrtfsurf(2,nmrtf) )
7062           DO  imrtf = 1, nmrtf
7063              mrtf(imrtf) = amrtf(imrtf)%rsvf
7064              mrtft(imrtf) = amrtf(imrtf)%rsvf * amrtf(imrtf)%rtransp
7065              mrtfsurf(:,imrtf) = (/amrtf(imrtf)%isurflt, amrtf(imrtf)%isurfs /)
7066           ENDDO
7067           IF ( ALLOCATED(amrtf1) )  DEALLOCATE( amrtf1 )
7068           IF ( ALLOCATED(amrtf2) )  DEALLOCATE( amrtf2 )
7069        ENDIF ! nmrtbl > 0
7070
7071        IF ( rad_angular_discretization )  THEN
7072#if defined( __parallel )
7073!--        finalize MPI_RMA communication established to get global index of the surface from grid indices
7074!--        flush all MPI window pending requests
7075           CALL MPI_Win_flush_all(win_gridsurf, ierr)
7076           IF ( ierr /= 0 ) THEN
7077               WRITE(9,*) 'Error MPI_Win_flush_all1:', ierr, win_gridsurf
7078               FLUSH(9)
7079           ENDIF
7080!--        unlock MPI window
7081           CALL MPI_Win_unlock_all(win_gridsurf, ierr)
7082           IF ( ierr /= 0 ) THEN
7083               WRITE(9,*) 'Error MPI_Win_unlock_all1:', ierr, win_gridsurf
7084               FLUSH(9)
7085           ENDIF
7086!--        free MPI window
7087           CALL MPI_Win_free(win_gridsurf, ierr)
7088           IF ( ierr /= 0 ) THEN
7089               WRITE(9,*) 'Error MPI_Win_free1:', ierr, win_gridsurf
7090               FLUSH(9)
7091           ENDIF
7092#else
7093           DEALLOCATE ( gridsurf )
7094#endif
7095        ENDIF
7096
7097        CALL radiation_write_debug_log( 'End of calculation SVF' )
7098        WRITE(msg, *) 'Raytracing skipped for maximum distance of ', &
7099           max_raytracing_dist, ' m on ', ray_skip_maxdist, ' pairs.'
7100        CALL radiation_write_debug_log( msg )
7101        WRITE(msg, *) 'Raytracing skipped for minimum potential value of ', &
7102           min_irrf_value , ' on ', ray_skip_minval, ' pairs.'
7103        CALL radiation_write_debug_log( msg )
7104
7105        CALL location_message( '    waiting for completion of SVF and CSF calculation in all processes', .TRUE. )
7106!--     deallocate temporary global arrays
7107        DEALLOCATE(nzterr)
7108       
7109        IF ( plant_canopy )  THEN
7110!--         finalize mpi_rma communication and deallocate temporary arrays
7111#if defined( __parallel )
7112            IF ( raytrace_mpi_rma )  THEN
7113                CALL MPI_Win_flush_all(win_lad, ierr)
7114                IF ( ierr /= 0 ) THEN
7115                    WRITE(9,*) 'Error MPI_Win_flush_all2:', ierr, win_lad
7116                    FLUSH(9)
7117                ENDIF
7118!--             unlock MPI window
7119                CALL MPI_Win_unlock_all(win_lad, ierr)
7120                IF ( ierr /= 0 ) THEN
7121                    WRITE(9,*) 'Error MPI_Win_unlock_all2:', ierr, win_lad
7122                    FLUSH(9)
7123                ENDIF
7124!--             free MPI window
7125                CALL MPI_Win_free(win_lad, ierr)
7126                IF ( ierr /= 0 ) THEN
7127                    WRITE(9,*) 'Error MPI_Win_free2:', ierr, win_lad
7128                    FLUSH(9)
7129                ENDIF
7130!--             deallocate temporary arrays storing values for csf calculation during raytracing
7131                DEALLOCATE( lad_s_ray )
7132!--             sub_lad is the pointer to lad_s_rma in case of raytrace_mpi_rma
7133!--             and must not be deallocated here
7134            ELSE
7135                DEALLOCATE(sub_lad)
7136                DEALLOCATE(sub_lad_g)
7137            ENDIF
7138#else
7139            DEALLOCATE(sub_lad)
7140#endif
7141            DEALLOCATE( boxes )
7142            DEALLOCATE( crlens )
7143            DEALLOCATE( plantt )
7144            DEALLOCATE( rt2_track, rt2_track_lad, rt2_track_dist, rt2_dist )
7145        ENDIF
7146
7147        CALL location_message( '    calculation of the complete SVF array', .TRUE. )
7148
7149        IF ( rad_angular_discretization )  THEN
7150           CALL radiation_write_debug_log( 'Load svf from the structure array to plain arrays' )
7151           ALLOCATE( svf(ndsvf,nsvfl) )
7152           ALLOCATE( svfsurf(idsvf,nsvfl) )
7153
7154           DO isvf = 1, nsvfl
7155               svf(:, isvf) = (/ asvf(isvf)%rsvf, asvf(isvf)%rtransp /)
7156               svfsurf(:, isvf) = (/ asvf(isvf)%isurflt, asvf(isvf)%isurfs /)
7157           ENDDO
7158        ELSE
7159           CALL radiation_write_debug_log( 'Start SVF sort' )
7160!--        sort svf ( a version of quicksort )
7161           CALL quicksort_svf(asvf,1,nsvfl)
7162
7163           !< load svf from the structure array to plain arrays
7164           CALL radiation_write_debug_log( 'Load svf from the structure array to plain arrays' )
7165           ALLOCATE( svf(ndsvf,nsvfl) )
7166           ALLOCATE( svfsurf(idsvf,nsvfl) )
7167           svfnorm_counts(:) = 0._wp
7168           isurflt_prev = -1
7169           ksvf = 1
7170           svfsum = 0._wp
7171           DO isvf = 1, nsvfl
7172!--            normalize svf per target face
7173               IF ( asvf(ksvf)%isurflt /= isurflt_prev )  THEN
7174                   IF ( isurflt_prev /= -1  .AND.  svfsum /= 0._wp )  THEN
7175                       !< update histogram of logged svf normalization values
7176                       i = searchsorted(svfnorm_report_thresh, svfsum / (1._wp-skyvf(isurflt_prev)))
7177                       svfnorm_counts(i) = svfnorm_counts(i) + 1
7178
7179                       svf(1, isvf_surflt:isvf-1) = svf(1, isvf_surflt:isvf-1) / svfsum * (1._wp-skyvf(isurflt_prev))
7180                   ENDIF
7181                   isurflt_prev = asvf(ksvf)%isurflt
7182                   isvf_surflt = isvf
7183                   svfsum = asvf(ksvf)%rsvf !?? / asvf(ksvf)%rtransp
7184               ELSE
7185                   svfsum = svfsum + asvf(ksvf)%rsvf !?? / asvf(ksvf)%rtransp
7186               ENDIF
7187
7188               svf(:, isvf) = (/ asvf(ksvf)%rsvf, asvf(ksvf)%rtransp /)
7189               svfsurf(:, isvf) = (/ asvf(ksvf)%isurflt, asvf(ksvf)%isurfs /)
7190
7191!--            next element
7192               ksvf = ksvf + 1
7193           ENDDO
7194
7195           IF ( isurflt_prev /= -1  .AND.  svfsum /= 0._wp )  THEN
7196               i = searchsorted(svfnorm_report_thresh, svfsum / (1._wp-skyvf(isurflt_prev)))
7197               svfnorm_counts(i) = svfnorm_counts(i) + 1
7198
7199               svf(1, isvf_surflt:nsvfl) = svf(1, isvf_surflt:nsvfl) / svfsum * (1._wp-skyvf(isurflt_prev))
7200           ENDIF
7201           WRITE(9, *) 'SVF normalization histogram:', svfnorm_counts,  &
7202                       'on thresholds:', svfnorm_report_thresh(1:svfnorm_report_num), '(val < thresh <= val)'
7203           !TODO we should be able to deallocate skyvf, from now on we only need skyvft
7204        ENDIF ! rad_angular_discretization
7205
7206!--     deallocate temporary asvf array
7207!--     DEALLOCATE(asvf) - ifort has a problem with deallocation of allocatable target
7208!--     via pointing pointer - we need to test original targets
7209        IF ( ALLOCATED(asvf1) )  THEN
7210            DEALLOCATE(asvf1)
7211        ENDIF
7212        IF ( ALLOCATED(asvf2) )  THEN
7213            DEALLOCATE(asvf2)
7214        ENDIF
7215
7216        npcsfl = 0
7217        IF ( plant_canopy )  THEN
7218
7219            CALL location_message( '    calculation of the complete CSF array', .TRUE. )
7220            CALL radiation_write_debug_log( 'Calculation of the complete CSF array' )
7221!--         sort and merge csf for the last time, keeping the array size to minimum
7222            CALL merge_and_grow_csf(-1)
7223           
7224!--         aggregate csb among processors
7225!--         allocate necessary arrays
7226            udim = max(ncsfl,1)
7227            ALLOCATE( csflt_l(ndcsf*udim) )
7228            csflt(1:ndcsf,1:udim) => csflt_l(1:ndcsf*udim)
7229            ALLOCATE( kcsflt_l(kdcsf*udim) )
7230            kcsflt(1:kdcsf,1:udim) => kcsflt_l(1:kdcsf*udim)
7231            ALLOCATE( icsflt(0:numprocs-1) )
7232            ALLOCATE( dcsflt(0:numprocs-1) )
7233            ALLOCATE( ipcsflt(0:numprocs-1) )
7234            ALLOCATE( dpcsflt(0:numprocs-1) )
7235           
7236!--         fill out arrays of csf values and
7237!--         arrays of number of elements and displacements
7238!--         for particular precessors
7239            icsflt = 0
7240            dcsflt = 0
7241            ip = -1
7242            j = -1
7243            d = 0
7244            DO kcsf = 1, ncsfl
7245                j = j+1
7246                IF ( acsf(kcsf)%ip /= ip )  THEN
7247!--                 new block of the processor
7248!--                 number of elements of previous block
7249                    IF ( ip>=0) icsflt(ip) = j
7250                    d = d+j
7251!--                 blank blocks
7252                    DO jp = ip+1, acsf(kcsf)%ip-1
7253!--                     number of elements is zero, displacement is equal to previous
7254                        icsflt(jp) = 0
7255                        dcsflt(jp) = d
7256                    ENDDO
7257!--                 the actual block
7258                    ip = acsf(kcsf)%ip
7259                    dcsflt(ip) = d
7260                    j = 0
7261                ENDIF
7262                csflt(1,kcsf) = acsf(kcsf)%rcvf
7263!--             fill out integer values of itz,ity,itx,isurfs
7264                kcsflt(1,kcsf) = acsf(kcsf)%itz
7265                kcsflt(2,kcsf) = acsf(kcsf)%ity
7266                kcsflt(3,kcsf) = acsf(kcsf)%itx
7267                kcsflt(4,kcsf) = acsf(kcsf)%isurfs
7268            ENDDO
7269!--         last blank blocks at the end of array
7270            j = j+1
7271            IF ( ip>=0 ) icsflt(ip) = j
7272            d = d+j
7273            DO jp = ip+1, numprocs-1
7274!--             number of elements is zero, displacement is equal to previous
7275                icsflt(jp) = 0
7276                dcsflt(jp) = d
7277            ENDDO
7278           
7279!--         deallocate temporary acsf array
7280!--         DEALLOCATE(acsf) - ifort has a problem with deallocation of allocatable target
7281!--         via pointing pointer - we need to test original targets
7282            IF ( ALLOCATED(acsf1) )  THEN
7283                DEALLOCATE(acsf1)
7284            ENDIF
7285            IF ( ALLOCATED(acsf2) )  THEN
7286                DEALLOCATE(acsf2)
7287            ENDIF
7288                   
7289#if defined( __parallel )
7290!--         scatter and gather the number of elements to and from all processor
7291!--         and calculate displacements
7292            CALL radiation_write_debug_log( 'Scatter and gather the number of elements to and from all processor' )
7293            CALL MPI_AlltoAll(icsflt,1,MPI_INTEGER,ipcsflt,1,MPI_INTEGER,comm2d, ierr)
7294            IF ( ierr /= 0 ) THEN
7295                WRITE(9,*) 'Error MPI_AlltoAll1:', ierr, SIZE(icsflt), SIZE(ipcsflt)
7296                FLUSH(9)
7297            ENDIF
7298
7299            npcsfl = SUM(ipcsflt)
7300            d = 0
7301            DO i = 0, numprocs-1
7302                dpcsflt(i) = d
7303                d = d + ipcsflt(i)
7304            ENDDO
7305
7306!--         exchange csf fields between processors
7307            CALL radiation_write_debug_log( 'Exchange csf fields between processors' )
7308            udim = max(npcsfl,1)
7309            ALLOCATE( pcsflt_l(ndcsf*udim) )
7310            pcsflt(1:ndcsf,1:udim) => pcsflt_l(1:ndcsf*udim)
7311            ALLOCATE( kpcsflt_l(kdcsf*udim) )
7312            kpcsflt(1:kdcsf,1:udim) => kpcsflt_l(1:kdcsf*udim)
7313            CALL MPI_AlltoAllv(csflt_l, ndcsf*icsflt, ndcsf*dcsflt, MPI_REAL, &
7314                pcsflt_l, ndcsf*ipcsflt, ndcsf*dpcsflt, MPI_REAL, comm2d, ierr)
7315            IF ( ierr /= 0 ) THEN
7316                WRITE(9,*) 'Error MPI_AlltoAllv1:', ierr, SIZE(ipcsflt), ndcsf*icsflt, &
7317                            ndcsf*dcsflt, SIZE(pcsflt_l),ndcsf*ipcsflt, ndcsf*dpcsflt
7318                FLUSH(9)
7319            ENDIF
7320
7321            CALL MPI_AlltoAllv(kcsflt_l, kdcsf*icsflt, kdcsf*dcsflt, MPI_INTEGER, &
7322                kpcsflt_l, kdcsf*ipcsflt, kdcsf*dpcsflt, MPI_INTEGER, comm2d, ierr)
7323            IF ( ierr /= 0 ) THEN
7324                WRITE(9,*) 'Error MPI_AlltoAllv2:', ierr, SIZE(kcsflt_l),kdcsf*icsflt, &
7325                           kdcsf*dcsflt, SIZE(kpcsflt_l), kdcsf*ipcsflt, kdcsf*dpcsflt
7326                FLUSH(9)
7327            ENDIF
7328           
7329#else
7330            npcsfl = ncsfl
7331            ALLOCATE( pcsflt(ndcsf,max(npcsfl,ndcsf)) )
7332            ALLOCATE( kpcsflt(kdcsf,max(npcsfl,kdcsf)) )
7333            pcsflt = csflt
7334            kpcsflt = kcsflt
7335#endif
7336
7337!--         deallocate temporary arrays
7338            DEALLOCATE( csflt_l )
7339            DEALLOCATE( kcsflt_l )
7340            DEALLOCATE( icsflt )
7341            DEALLOCATE( dcsflt )
7342            DEALLOCATE( ipcsflt )
7343            DEALLOCATE( dpcsflt )
7344
7345!--         sort csf ( a version of quicksort )
7346            CALL radiation_write_debug_log( 'Sort csf' )
7347            CALL quicksort_csf2(kpcsflt, pcsflt, 1, npcsfl)
7348
7349!--         aggregate canopy sink factor records with identical box & source
7350!--         againg across all values from all processors
7351            CALL radiation_write_debug_log( 'Aggregate canopy sink factor records with identical box' )
7352
7353            IF ( npcsfl > 0 )  THEN
7354                icsf = 1 !< reading index
7355                kcsf = 1 !< writing index
7356                DO while (icsf < npcsfl)
7357!--                 here kpcsf(kcsf) already has values from kpcsf(icsf)
7358                    IF ( kpcsflt(3,icsf) == kpcsflt(3,icsf+1)  .AND.  &
7359                         kpcsflt(2,icsf) == kpcsflt(2,icsf+1)  .AND.  &
7360                         kpcsflt(1,icsf) == kpcsflt(1,icsf+1)  .AND.  &
7361                         kpcsflt(4,icsf) == kpcsflt(4,icsf+1) )  THEN
7362
7363                        pcsflt(1,kcsf) = pcsflt(1,kcsf) + pcsflt(1,icsf+1)
7364
7365!--                     advance reading index, keep writing index
7366                        icsf = icsf + 1
7367                    ELSE
7368!--                     not identical, just advance and copy
7369                        icsf = icsf + 1
7370                        kcsf = kcsf + 1
7371                        kpcsflt(:,kcsf) = kpcsflt(:,icsf)
7372                        pcsflt(:,kcsf) = pcsflt(:,icsf)
7373                    ENDIF
7374                ENDDO
7375!--             last written item is now also the last item in valid part of array
7376                npcsfl = kcsf
7377            ENDIF
7378
7379            ncsfl = npcsfl
7380            IF ( ncsfl > 0 )  THEN
7381                ALLOCATE( csf(ndcsf,ncsfl) )
7382                ALLOCATE( csfsurf(idcsf,ncsfl) )
7383                DO icsf = 1, ncsfl
7384                    csf(:,icsf) = pcsflt(:,icsf)
7385                    csfsurf(1,icsf) =  gridpcbl(kpcsflt(1,icsf),kpcsflt(2,icsf),kpcsflt(3,icsf))
7386                    csfsurf(2,icsf) =  kpcsflt(4,icsf)
7387                ENDDO
7388            ENDIF
7389           
7390!--         deallocation of temporary arrays
7391            IF ( npcbl > 0 )  DEALLOCATE( gridpcbl )
7392            DEALLOCATE( pcsflt_l )
7393            DEALLOCATE( kpcsflt_l )
7394            CALL radiation_write_debug_log( 'End of aggregate csf' )
7395           
7396        ENDIF
7397
7398#if defined( __parallel )
7399        CALL MPI_BARRIER( comm2d, ierr )
7400#endif
7401        CALL radiation_write_debug_log( 'End of radiation_calc_svf (after mpi_barrier)' )
7402
7403        RETURN
7404       
7405!        WRITE( message_string, * )  &
7406!            'I/O error when processing shape view factors / ',  &
7407!            'plant canopy sink factors / direct irradiance factors.'
7408!        CALL message( 'init_urban_surface', 'PA0502', 2, 2, 0, 6, 0 )
7409       
7410    END SUBROUTINE radiation_calc_svf
7411
7412   
7413!------------------------------------------------------------------------------!
7414! Description:
7415! ------------
7416!> Raytracing for detecting obstacles and calculating compound canopy sink
7417!> factors. (A simple obstacle detection would only need to process faces in
7418!> 3 dimensions without any ordering.)
7419!> Assumtions:
7420!> -----------
7421!> 1. The ray always originates from a face midpoint (only one coordinate equals
7422!>    *.5, i.e. wall) and doesn't travel parallel to the surface (that would mean
7423!>    shape factor=0). Therefore, the ray may never travel exactly along a face
7424!>    or an edge.
7425!> 2. From grid bottom to urban surface top the grid has to be *equidistant*
7426!>    within each of the dimensions, including vertical (but the resolution
7427!>    doesn't need to be the same in all three dimensions).
7428!------------------------------------------------------------------------------!
7429    SUBROUTINE raytrace(src, targ, isrc, difvf, atarg, create_csf, visible, transparency)
7430        IMPLICIT NONE
7431
7432        REAL(wp), DIMENSION(3), INTENT(in)     :: src, targ    !< real coordinates z,y,x
7433        INTEGER(iwp), INTENT(in)               :: isrc         !< index of source face for csf
7434        REAL(wp), INTENT(in)                   :: difvf        !< differential view factor for csf
7435        REAL(wp), INTENT(in)                   :: atarg        !< target surface area for csf
7436        LOGICAL, INTENT(in)                    :: create_csf   !< whether to generate new CSFs during raytracing
7437        LOGICAL, INTENT(out)                   :: visible
7438        REAL(wp), INTENT(out)                  :: transparency !< along whole path
7439        INTEGER(iwp)                           :: i, k, d
7440        INTEGER(iwp)                           :: seldim       !< dimension to be incremented
7441        INTEGER(iwp)                           :: ncsb         !< no of written plant canopy sinkboxes
7442        INTEGER(iwp)                           :: maxboxes     !< max no of gridboxes visited
7443        REAL(wp)                               :: distance     !< euclidean along path
7444        REAL(wp)                               :: crlen        !< length of gridbox crossing
7445        REAL(wp)                               :: lastdist     !< beginning of current crossing
7446        REAL(wp)                               :: nextdist     !< end of current crossing
7447        REAL(wp)                               :: realdist     !< distance in meters per unit distance
7448        REAL(wp)                               :: crmid        !< midpoint of crossing
7449        REAL(wp)                               :: cursink      !< sink factor for current canopy box
7450        REAL(wp), DIMENSION(3)                 :: delta        !< path vector
7451        REAL(wp), DIMENSION(3)                 :: uvect        !< unit vector
7452        REAL(wp), DIMENSION(3)                 :: dimnextdist  !< distance for each dimension increments
7453        INTEGER(iwp), DIMENSION(3)             :: box          !< gridbox being crossed
7454        INTEGER(iwp), DIMENSION(3)             :: dimnext      !< next dimension increments along path
7455        INTEGER(iwp), DIMENSION(3)             :: dimdelta     !< dimension direction = +- 1
7456        INTEGER(iwp)                           :: px, py       !< number of processors in x and y dir before
7457                                                               !< the processor in the question
7458        INTEGER(iwp)                           :: ip           !< number of processor where gridbox reside
7459        INTEGER(iwp)                           :: ig           !< 1D index of gridbox in global 2D array
7460       
7461        REAL(wp)                               :: eps = 1E-10_wp !< epsilon for value comparison
7462        REAL(wp)                               :: lad_s_target   !< recieved lad_s of particular grid box
7463
7464!
7465!--     Maximum number of gridboxes visited equals to maximum number of boundaries crossed in each dimension plus one. That's also
7466!--     the maximum number of plant canopy boxes written. We grow the acsf array accordingly using exponential factor.
7467        maxboxes = SUM(ABS(NINT(targ, iwp) - NINT(src, iwp))) + 1
7468        IF ( plant_canopy  .AND.  ncsfl + maxboxes > ncsfla )  THEN
7469!--         use this code for growing by fixed exponential increments (equivalent to case where ncsfl always increases by 1)
7470!--         k = CEILING(grow_factor ** real(CEILING(log(real(ncsfl + maxboxes, kind=wp)) &
7471!--                                                / log(grow_factor)), kind=wp))
7472!--         or use this code to simply always keep some extra space after growing
7473            k = CEILING(REAL(ncsfl + maxboxes, kind=wp) * grow_factor)
7474
7475            CALL merge_and_grow_csf(k)
7476        ENDIF
7477       
7478        transparency = 1._wp
7479        ncsb = 0
7480
7481        delta(:) = targ(:) - src(:)
7482        distance = SQRT(SUM(delta(:)**2))
7483        IF ( distance == 0._wp )  THEN
7484            visible = .TRUE.
7485            RETURN
7486        ENDIF
7487        uvect(:) = delta(:) / distance
7488        realdist = SQRT(SUM( (uvect(:)*(/dz(1),dy,dx/))**2 ))
7489
7490        lastdist = 0._wp
7491
7492!--     Since all face coordinates have values *.5 and we'd like to use
7493!--     integers, all these have .5 added
7494        DO d = 1, 3
7495            IF ( uvect(d) == 0._wp )  THEN
7496                dimnext(d) = 999999999
7497                dimdelta(d) = 999999999
7498                dimnextdist(d) = 1.0E20_wp
7499            ELSE IF ( uvect(d) > 0._wp )  THEN
7500                dimnext(d) = CEILING(src(d) + .5_wp)
7501                dimdelta(d) = 1
7502                dimnextdist(d) = (dimnext(d) - .5_wp - src(d)) / uvect(d)
7503            ELSE
7504                dimnext(d) = FLOOR(src(d) + .5_wp)
7505                dimdelta(d) = -1
7506                dimnextdist(d) = (dimnext(d) - .5_wp - src(d)) / uvect(d)
7507            ENDIF
7508        ENDDO
7509
7510        DO
7511!--         along what dimension will the next wall crossing be?
7512            seldim = minloc(dimnextdist, 1)
7513            nextdist = dimnextdist(seldim)
7514            IF ( nextdist > distance ) nextdist = distance
7515
7516            crlen = nextdist - lastdist
7517            IF ( crlen > .001_wp )  THEN
7518                crmid = (lastdist + nextdist) * .5_wp
7519                box = NINT(src(:) + uvect(:) * crmid, iwp)
7520
7521!--             calculate index of the grid with global indices (box(2),box(3))
7522!--             in the array nzterr and plantt and id of the coresponding processor
7523                px = box(3)/nnx
7524                py = box(2)/nny
7525                ip = px*pdims(2)+py
7526                ig = ip*nnx*nny + (box(3)-px*nnx)*nny + box(2)-py*nny
7527                IF ( box(1) <= nzterr(ig) )  THEN
7528                    visible = .FALSE.
7529                    RETURN
7530                ENDIF
7531
7532                IF ( plant_canopy )  THEN
7533                    IF ( box(1) <= plantt(ig) )  THEN
7534                        ncsb = ncsb + 1
7535                        boxes(:,ncsb) = box
7536                        crlens(ncsb) = crlen
7537#if defined( __parallel )
7538                        lad_ip(ncsb) = ip
7539                        lad_disp(ncsb) = (box(3)-px*nnx)*(nny*nzp) + (box(2)-py*nny)*nzp + box(1)-nzub
7540#endif
7541                    ENDIF
7542                ENDIF
7543            ENDIF
7544
7545            IF ( ABS(distance - nextdist) < eps )  EXIT
7546            lastdist = nextdist
7547            dimnext(seldim) = dimnext(seldim) + dimdelta(seldim)
7548            dimnextdist(seldim) = (dimnext(seldim) - .5_wp - src(seldim)) / uvect(seldim)
7549        ENDDO
7550       
7551        IF ( plant_canopy )  THEN
7552#if defined( __parallel )
7553            IF ( raytrace_mpi_rma )  THEN
7554!--             send requests for lad_s to appropriate processor
7555                CALL cpu_log( log_point_s(77), 'rad_rma_lad', 'start' )
7556                DO i = 1, ncsb
7557                    CALL MPI_Get(lad_s_ray(i), 1, MPI_REAL, lad_ip(i), lad_disp(i), &
7558                                 1, MPI_REAL, win_lad, ierr)
7559                    IF ( ierr /= 0 )  THEN
7560                        WRITE(9,*) 'Error MPI_Get1:', ierr, lad_s_ray(i), &
7561                                   lad_ip(i), lad_disp(i), win_lad
7562                        FLUSH(9)
7563                    ENDIF
7564                ENDDO
7565               
7566!--             wait for all pending local requests complete
7567                CALL MPI_Win_flush_local_all(win_lad, ierr)
7568                IF ( ierr /= 0 )  THEN
7569                    WRITE(9,*) 'Error MPI_Win_flush_local_all1:', ierr, win_lad
7570                    FLUSH(9)
7571                ENDIF
7572                CALL cpu_log( log_point_s(77), 'rad_rma_lad', 'stop' )
7573               
7574            ENDIF
7575#endif
7576
7577!--         calculate csf and transparency
7578            DO i = 1, ncsb
7579#if defined( __parallel )
7580                IF ( raytrace_mpi_rma )  THEN
7581                    lad_s_target = lad_s_ray(i)
7582                ELSE
7583                    lad_s_target = sub_lad_g(lad_ip(i)*nnx*nny*nzp + lad_disp(i))
7584                ENDIF
7585#else
7586                lad_s_target = sub_lad(boxes(1,i),boxes(2,i),boxes(3,i))
7587#endif
7588                cursink = 1._wp - exp(-ext_coef * lad_s_target * crlens(i)*realdist)
7589
7590                IF ( create_csf )  THEN
7591!--                 write svf values into the array
7592                    ncsfl = ncsfl + 1
7593                    acsf(ncsfl)%ip = lad_ip(i)
7594                    acsf(ncsfl)%itx = boxes(3,i)
7595                    acsf(ncsfl)%ity = boxes(2,i)
7596                    acsf(ncsfl)%itz = boxes(1,i)
7597                    acsf(ncsfl)%isurfs = isrc
7598                    acsf(ncsfl)%rcvf = cursink*transparency*difvf*atarg
7599                ENDIF  !< create_csf
7600
7601                transparency = transparency * (1._wp - cursink)
7602               
7603            ENDDO
7604        ENDIF
7605       
7606        visible = .TRUE.
7607
7608    END SUBROUTINE raytrace
7609   
7610 
7611!------------------------------------------------------------------------------!
7612! Description:
7613! ------------
7614!> A new, more efficient version of ray tracing algorithm that processes a whole
7615!> arc instead of a single ray.
7616!>
7617!> In all comments, horizon means tangent of horizon angle, i.e.
7618!> vertical_delta / horizontal_distance
7619!------------------------------------------------------------------------------!
7620   SUBROUTINE raytrace_2d(origin, yxdir, nrays, zdirs, iorig, aorig, vffrac,  &
7621                              calc_svf, create_csf, skip_1st_pcb,             &
7622                              lowest_free_ray, transparency, itarget)
7623      IMPLICIT NONE
7624
7625      REAL(wp), DIMENSION(3), INTENT(IN)     ::  origin        !< z,y,x coordinates of ray origin
7626      REAL(wp), DIMENSION(2), INTENT(IN)     ::  yxdir         !< y,x *unit* vector of ray direction (in grid units)
7627      INTEGER(iwp)                           ::  nrays         !< number of rays (z directions) to raytrace
7628      REAL(wp), DIMENSION(nrays), INTENT(IN) ::  zdirs         !< list of z directions to raytrace (z/hdist, grid, zenith->nadir)
7629      INTEGER(iwp), INTENT(in)               ::  iorig         !< index of origin face for csf
7630      REAL(wp), INTENT(in)                   ::  aorig         !< origin face area for csf
7631      REAL(wp), DIMENSION(nrays), INTENT(in) ::  vffrac        !< view factor fractions of each ray for csf
7632      LOGICAL, INTENT(in)                    ::  calc_svf      !< whether to calculate SFV (identify obstacle surfaces)
7633      LOGICAL, INTENT(in)                    ::  create_csf    !< whether to create canopy sink factors
7634      LOGICAL, INTENT(in)                    ::  skip_1st_pcb  !< whether to skip first plant canopy box during raytracing
7635      INTEGER(iwp), INTENT(out)              ::  lowest_free_ray !< index into zdirs
7636      REAL(wp), DIMENSION(nrays), INTENT(OUT) ::  transparency !< transparencies of zdirs paths
7637      INTEGER(iwp), DIMENSION(nrays), INTENT(OUT) ::  itarget  !< global indices of target faces for zdirs
7638
7639      INTEGER(iwp), DIMENSION(nrays)         ::  target_procs
7640      REAL(wp)                               ::  horizon       !< highest horizon found after raytracing (z/hdist)
7641      INTEGER(iwp)                           ::  i, k, l, d
7642      INTEGER(iwp)                           ::  seldim       !< dimension to be incremented
7643      REAL(wp), DIMENSION(2)                 ::  yxorigin     !< horizontal copy of origin (y,x)
7644      REAL(wp)                               ::  distance     !< euclidean along path
7645      REAL(wp)                               ::  lastdist     !< beginning of current crossing
7646      REAL(wp)                               ::  nextdist     !< end of current crossing
7647      REAL(wp)                               ::  crmid        !< midpoint of crossing
7648      REAL(wp)                               ::  horz_entry   !< horizon at entry to column
7649      REAL(wp)                               ::  horz_exit    !< horizon at exit from column
7650      REAL(wp)                               ::  bdydim       !< boundary for current dimension
7651      REAL(wp), DIMENSION(2)                 ::  crossdist    !< distances to boundary for dimensions
7652      REAL(wp), DIMENSION(2)                 ::  dimnextdist  !< distance for each dimension increments
7653      INTEGER(iwp), DIMENSION(2)             ::  column       !< grid column being crossed
7654      INTEGER(iwp), DIMENSION(2)             ::  dimnext      !< next dimension increments along path
7655      INTEGER(iwp), DIMENSION(2)             ::  dimdelta     !< dimension direction = +- 1
7656      INTEGER(iwp)                           ::  px, py       !< number of processors in x and y dir before
7657                                                              !< the processor in the question
7658      INTEGER(iwp)                           ::  ip           !< number of processor where gridbox reside
7659      INTEGER(iwp)                           ::  ig           !< 1D index of gridbox in global 2D array
7660      INTEGER(iwp)                           ::  wcount       !< RMA window item count
7661      INTEGER(iwp)                           ::  maxboxes     !< max no of CSF created
7662      INTEGER(iwp)                           ::  nly          !< maximum  plant canopy height
7663      INTEGER(iwp)                           ::  ntrack
7664     
7665      INTEGER(iwp)                           ::  zb0
7666      INTEGER(iwp)                           ::  zb1
7667      INTEGER(iwp)                           ::  nz
7668      INTEGER(iwp)                           ::  iz
7669      INTEGER(iwp)                           ::  zsgn
7670      INTEGER(iwp)                           ::  lowest_lad   !< lowest column cell for which we need LAD
7671      INTEGER(iwp)                           ::  lastdir      !< wall direction before hitting this column
7672      INTEGER(iwp), DIMENSION(2)             ::  lastcolumn
7673
7674#if defined( __parallel )
7675      INTEGER(MPI_ADDRESS_KIND)              ::  wdisp        !< RMA window displacement
7676#endif
7677     
7678      REAL(wp)                               ::  eps = 1E-10_wp !< epsilon for value comparison
7679      REAL(wp)                               ::  zbottom, ztop !< urban surface boundary in real numbers
7680      REAL(wp)                               ::  zorig         !< z coordinate of ray column entry
7681      REAL(wp)                               ::  zexit         !< z coordinate of ray column exit
7682      REAL(wp)                               ::  qdist         !< ratio of real distance to z coord difference
7683      REAL(wp)                               ::  dxxyy         !< square of real horizontal distance
7684      REAL(wp)                               ::  curtrans      !< transparency of current PC box crossing
7685     
7686
7687     
7688      yxorigin(:) = origin(2:3)
7689      transparency(:) = 1._wp !-- Pre-set the all rays to transparent before reducing
7690      horizon = -HUGE(1._wp)
7691      lowest_free_ray = nrays
7692      IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7693         ALLOCATE(target_surfl(nrays))
7694         target_surfl(:) = -1
7695         lastdir = -999
7696         lastcolumn(:) = -999
7697      ENDIF
7698
7699!--   Determine distance to boundary (in 2D xy)
7700      IF ( yxdir(1) > 0._wp )  THEN
7701         bdydim = ny + .5_wp !< north global boundary
7702         crossdist(1) = (bdydim - yxorigin(1)) / yxdir(1)
7703      ELSEIF ( yxdir(1) == 0._wp )  THEN
7704         crossdist(1) = HUGE(1._wp)
7705      ELSE
7706          bdydim = -.5_wp !< south global boundary
7707          crossdist(1) = (bdydim - yxorigin(1)) / yxdir(1)
7708      ENDIF
7709
7710      IF ( yxdir(2) > 0._wp )  THEN
7711          bdydim = nx + .5_wp !< east global boundary
7712          crossdist(2) = (bdydim - yxorigin(2)) / yxdir(2)
7713      ELSEIF ( yxdir(2) == 0._wp )  THEN
7714         crossdist(2) = HUGE(1._wp)
7715      ELSE
7716          bdydim = -.5_wp !< west global boundary
7717          crossdist(2) = (bdydim - yxorigin(2)) / yxdir(2)
7718      ENDIF
7719      distance = minval(crossdist, 1)
7720
7721      IF ( plant_canopy )  THEN
7722         rt2_track_dist(0) = 0._wp
7723         rt2_track_lad(:,:) = 0._wp
7724         nly = plantt_max - nzub + 1
7725      ENDIF
7726
7727      lastdist = 0._wp
7728
7729!--   Since all face coordinates have values *.5 and we'd like to use
7730!--   integers, all these have .5 added
7731      DO  d = 1, 2
7732          IF ( yxdir(d) == 0._wp )  THEN
7733              dimnext(d) = HUGE(1_iwp)
7734              dimdelta(d) = HUGE(1_iwp)
7735              dimnextdist(d) = HUGE(1._wp)
7736          ELSE IF ( yxdir(d) > 0._wp )  THEN
7737              dimnext(d) = FLOOR(yxorigin(d) + .5_wp) + 1
7738              dimdelta(d) = 1
7739              dimnextdist(d) = (dimnext(d) - .5_wp - yxorigin(d)) / yxdir(d)
7740          ELSE
7741              dimnext(d) = CEILING(yxorigin(d) + .5_wp) - 1
7742              dimdelta(d) = -1
7743              dimnextdist(d) = (dimnext(d) - .5_wp - yxorigin(d)) / yxdir(d)
7744          ENDIF
7745      ENDDO
7746
7747      ntrack = 0
7748      DO
7749!--      along what dimension will the next wall crossing be?
7750         seldim = minloc(dimnextdist, 1)
7751         nextdist = dimnextdist(seldim)
7752         IF ( nextdist > distance )  nextdist = distance
7753
7754         IF ( nextdist > lastdist )  THEN
7755            ntrack = ntrack + 1
7756            crmid = (lastdist + nextdist) * .5_wp
7757            column = NINT(yxorigin(:) + yxdir(:) * crmid, iwp)
7758
7759!--         calculate index of the grid with global indices (column(1),column(2))
7760!--         in the array nzterr and plantt and id of the coresponding processor
7761            px = column(2)/nnx
7762            py = column(1)/nny
7763            ip = px*pdims(2)+py
7764            ig = ip*nnx*nny + (column(2)-px*nnx)*nny + column(1)-py*nny
7765
7766            IF ( lastdist == 0._wp )  THEN
7767               horz_entry = -HUGE(1._wp)
7768            ELSE
7769               horz_entry = (REAL(nzterr(ig), wp) + .5_wp - origin(1)) / lastdist
7770            ENDIF
7771            horz_exit = (REAL(nzterr(ig), wp) + .5_wp - origin(1)) / nextdist
7772
7773            IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7774!
7775!--            Identify vertical obstacles hit by rays in current column
7776               DO WHILE ( lowest_free_ray > 0 )
7777                  IF ( zdirs(lowest_free_ray) > horz_entry )  EXIT
7778!
7779!--               This may only happen after 1st column, so lastdir and lastcolumn are valid
7780                  CALL request_itarget(lastdir,                                         &
7781                        CEILING(-0.5_wp + origin(1) + zdirs(lowest_free_ray)*lastdist), &
7782                        lastcolumn(1), lastcolumn(2),                                   &
7783                        target_surfl(lowest_free_ray), target_procs(lowest_free_ray))
7784                  lowest_free_ray = lowest_free_ray - 1
7785               ENDDO
7786!
7787!--            Identify horizontal obstacles hit by rays in current column
7788               DO WHILE ( lowest_free_ray > 0 )
7789                  IF ( zdirs(lowest_free_ray) > horz_exit )  EXIT
7790                  CALL request_itarget(iup_u, nzterr(ig)+1, column(1), column(2), &
7791                                       target_surfl(lowest_free_ray),           &
7792                                       target_procs(lowest_free_ray))
7793                  lowest_free_ray = lowest_free_ray - 1
7794               ENDDO
7795            ENDIF
7796
7797            horizon = MAX(horizon, horz_entry, horz_exit)
7798
7799            IF ( plant_canopy )  THEN
7800               rt2_track(:, ntrack) = column(:)
7801               rt2_track_dist(ntrack) = nextdist
7802            ENDIF
7803         ENDIF
7804
7805         IF ( nextdist + eps >= distance )  EXIT
7806
7807         IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7808!
7809!--         Save wall direction of coming building column (= this air column)
7810            IF ( seldim == 1 )  THEN
7811               IF ( dimdelta(seldim) == 1 )  THEN
7812                  lastdir = isouth_u
7813               ELSE
7814                  lastdir = inorth_u
7815               ENDIF
7816            ELSE
7817               IF ( dimdelta(seldim) == 1 )  THEN
7818                  lastdir = iwest_u
7819               ELSE
7820                  lastdir = ieast_u
7821               ENDIF
7822            ENDIF
7823            lastcolumn = column
7824         ENDIF
7825         lastdist = nextdist
7826         dimnext(seldim) = dimnext(seldim) + dimdelta(seldim)
7827         dimnextdist(seldim) = (dimnext(seldim) - .5_wp - yxorigin(seldim)) / yxdir(seldim)
7828      ENDDO
7829
7830      IF ( plant_canopy )  THEN
7831!--      Request LAD WHERE applicable
7832!--     
7833#if defined( __parallel )
7834         IF ( raytrace_mpi_rma )  THEN
7835!--         send requests for lad_s to appropriate processor
7836            !CALL cpu_log( log_point_s(77), 'usm_init_rma', 'start' )
7837            DO  i = 1, ntrack
7838               px = rt2_track(2,i)/nnx
7839               py = rt2_track(1,i)/nny
7840               ip = px*pdims(2)+py
7841               ig = ip*nnx*nny + (rt2_track(2,i)-px*nnx)*nny + rt2_track(1,i)-py*nny
7842
7843               IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7844!
7845!--               For fixed view resolution, we need plant canopy even for rays
7846!--               to opposing surfaces
7847                  lowest_lad = nzterr(ig) + 1
7848               ELSE
7849!
7850!--               We only need LAD for rays directed above horizon (to sky)
7851                  lowest_lad = CEILING( -0.5_wp + origin(1) +            &
7852                                    MIN( horizon * rt2_track_dist(i-1),  & ! entry
7853                                         horizon * rt2_track_dist(i)   ) ) ! exit
7854               ENDIF
7855!
7856!--            Skip asking for LAD where all plant canopy is under requested level
7857               IF ( plantt(ig) < lowest_lad )  CYCLE
7858
7859               wdisp = (rt2_track(2,i)-px*nnx)*(nny*nzp) + (rt2_track(1,i)-py*nny)*nzp + lowest_lad-nzub
7860               wcount = plantt(ig)-lowest_lad+1
7861               ! TODO send request ASAP - even during raytracing
7862               CALL MPI_Get(rt2_track_lad(lowest_lad:plantt(ig), i), wcount, MPI_REAL, ip,    &
7863                            wdisp, wcount, MPI_REAL, win_lad, ierr)
7864               IF ( ierr /= 0 )  THEN
7865                  WRITE(9,*) 'Error MPI_Get2:', ierr, rt2_track_lad(lowest_lad:plantt(ig), i), &
7866                             wcount, ip, wdisp, win_lad
7867                  FLUSH(9)
7868               ENDIF
7869            ENDDO
7870
7871!--         wait for all pending local requests complete
7872            ! TODO WAIT selectively for each column later when needed
7873            CALL MPI_Win_flush_local_all(win_lad, ierr)
7874            IF ( ierr /= 0 )  THEN
7875               WRITE(9,*) 'Error MPI_Win_flush_local_all2:', ierr, win_lad
7876               FLUSH(9)
7877            ENDIF
7878            !CALL cpu_log( log_point_s(77), 'usm_init_rma', 'stop' )
7879
7880         ELSE ! raytrace_mpi_rma = .F.
7881            DO  i = 1, ntrack
7882               px = rt2_track(2,i)/nnx
7883               py = rt2_track(1,i)/nny
7884               ip = px*pdims(2)+py
7885               ig = ip*nnx*nny*nzp + (rt2_track(2,i)-px*nnx)*(nny*nzp) + (rt2_track(1,i)-py*nny)*nzp
7886               rt2_track_lad(nzub:plantt_max, i) = sub_lad_g(ig:ig+nly-1)
7887            ENDDO
7888         ENDIF
7889#else
7890         DO  i = 1, ntrack
7891            rt2_track_lad(nzub:plantt_max, i) = sub_lad(rt2_track(1,i), rt2_track(2,i), nzub:plantt_max)
7892         ENDDO
7893#endif
7894      ENDIF ! plant_canopy
7895
7896      IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7897#if defined( __parallel )
7898!--      wait for all gridsurf requests to complete
7899         CALL MPI_Win_flush_local_all(win_gridsurf, ierr)
7900         IF ( ierr /= 0 )  THEN
7901            WRITE(9,*) 'Error MPI_Win_flush_local_all3:', ierr, win_gridsurf
7902            FLUSH(9)
7903         ENDIF
7904#endif
7905!
7906!--      recalculate local surf indices into global ones
7907         DO i = 1, nrays
7908            IF ( target_surfl(i) == -1 )  THEN
7909               itarget(i) = -1
7910            ELSE
7911               itarget(i) = target_surfl(i) + surfstart(target_procs(i))
7912            ENDIF
7913         ENDDO
7914         
7915         DEALLOCATE( target_surfl )
7916         
7917      ELSE
7918         itarget(:) = -1
7919      ENDIF ! rad_angular_discretization
7920
7921      IF ( plant_canopy )  THEN
7922!--      Skip the PCB around origin if requested (for MRT, the PCB might not be there)
7923!--     
7924         IF ( skip_1st_pcb  .AND.  NINT(origin(1)) <= plantt_max )  THEN
7925            rt2_track_lad(NINT(origin(1), iwp), 1) = 0._wp
7926         ENDIF
7927
7928!--      Assert that we have space allocated for CSFs
7929!--     
7930         maxboxes = (ntrack + MAX(CEILING(origin(1)-.5_wp) - nzub,          &
7931                                  nzut - CEILING(origin(1)-.5_wp))) * nrays
7932         IF ( ncsfl + maxboxes > ncsfla )  THEN
7933!--         use this code for growing by fixed exponential increments (equivalent to case where ncsfl always increases by 1)
7934!--         k = CEILING(grow_factor ** real(CEILING(log(real(ncsfl + maxboxes, kind=wp)) &
7935!--                                                / log(grow_factor)), kind=wp))
7936!--         or use this code to simply always keep some extra space after growing
7937            k = CEILING(REAL(ncsfl + maxboxes, kind=wp) * grow_factor)
7938            CALL merge_and_grow_csf(k)
7939         ENDIF
7940
7941!--      Calculate transparencies and store new CSFs
7942!--     
7943         zbottom = REAL(nzub, wp) - .5_wp
7944         ztop = REAL(plantt_max, wp) + .5_wp
7945
7946!--      Reverse direction of radiation (face->sky), only when calc_svf
7947!--     
7948         IF ( calc_svf )  THEN
7949            DO  i = 1, ntrack ! for each column
7950               dxxyy = ((dy*yxdir(1))**2 + (dx*yxdir(2))**2) * (rt2_track_dist(i)-rt2_track_dist(i-1))**2
7951               px = rt2_track(2,i)/nnx
7952               py = rt2_track(1,i)/nny
7953               ip = px*pdims(2)+py
7954
7955               DO  k = 1, nrays ! for each ray
7956!
7957!--               NOTE 6778:
7958!--               With traditional svf discretization, CSFs under the horizon
7959!--               (i.e. for surface to surface radiation)  are created in
7960!--               raytrace(). With rad_angular_discretization, we must create
7961!--               CSFs under horizon only for one direction, otherwise we would
7962!--               have duplicate amount of energy. Although we could choose
7963!--               either of the two directions (they differ only by
7964!--               discretization error with no bias), we choose the the backward
7965!--               direction, because it tends to cumulate high canopy sink
7966!--               factors closer to raytrace origin, i.e. it should potentially
7967!--               cause less moiree.
7968                  IF ( .NOT. rad_angular_discretization )  THEN
7969                     IF ( zdirs(k) <= horizon )  CYCLE
7970                  ENDIF
7971
7972                  zorig = origin(1) + zdirs(k) * rt2_track_dist(i-1)
7973                  IF ( zorig <= zbottom  .OR.  zorig >= ztop )  CYCLE
7974
7975                  zsgn = INT(SIGN(1._wp, zdirs(k)), iwp)
7976                  rt2_dist(1) = 0._wp
7977                  IF ( zdirs(k) == 0._wp )  THEN ! ray is exactly horizontal
7978                     nz = 2
7979                     rt2_dist(nz) = SQRT(dxxyy)
7980                     iz = CEILING(-.5_wp + zorig, iwp)
7981                  ELSE
7982                     zexit = MIN(MAX(origin(1) + zdirs(k) * rt2_track_dist(i), zbottom), ztop)
7983
7984                     zb0 = FLOOR(  zorig * zsgn - .5_wp) + 1  ! because it must be greater than orig
7985                     zb1 = CEILING(zexit * zsgn - .5_wp) - 1  ! because it must be smaller than exit
7986                     nz = MAX(zb1 - zb0 + 3, 2)
7987                     rt2_dist(nz) = SQRT(((zexit-zorig)*dz(1))**2 + dxxyy)
7988                     qdist = rt2_dist(nz) / (zexit-zorig)
7989                     rt2_dist(2:nz-1) = (/( ((REAL(l, wp) + .5_wp) * zsgn - zorig) * qdist , l = zb0, zb1 )/)
7990                     iz = zb0 * zsgn
7991                  ENDIF
7992
7993                  DO  l = 2, nz
7994                     IF ( rt2_track_lad(iz, i) > 0._wp )  THEN
7995                        curtrans = exp(-ext_coef * rt2_track_lad(iz, i) * (rt2_dist(l)-rt2_dist(l-1)))
7996
7997                        IF ( create_csf )  THEN
7998                           ncsfl = ncsfl + 1
7999                           acsf(ncsfl)%ip = ip
8000                           acsf(ncsfl)%itx = rt2_track(2,i)
8001                           acsf(ncsfl)%ity = rt2_track(1,i)
8002                           acsf(ncsfl)%itz = iz
8003                           acsf(ncsfl)%isurfs = iorig
8004                           acsf(ncsfl)%rcvf = (1._wp - curtrans)*transparency(k)*vffrac(k)
8005                        ENDIF
8006
8007                        transparency(k) = transparency(k) * curtrans
8008                     ENDIF
8009                     iz = iz + zsgn
8010                  ENDDO ! l = 1, nz - 1
8011               ENDDO ! k = 1, nrays
8012            ENDDO ! i = 1, ntrack
8013
8014            transparency(1:lowest_free_ray) = 1._wp !-- Reset rays above horizon to transparent (see NOTE 6778)
8015         ENDIF
8016
8017!--      Forward direction of radiation (sky->face), always
8018!--     
8019         DO  i = ntrack, 1, -1 ! for each column backwards
8020            dxxyy = ((dy*yxdir(1))**2 + (dx*yxdir(2))**2) * (rt2_track_dist(i)-rt2_track_dist(i-1))**2
8021            px = rt2_track(2,i)/nnx
8022            py = rt2_track(1,i)/nny
8023            ip = px*pdims(2)+py
8024
8025            DO  k = 1, nrays ! for each ray
8026!
8027!--            See NOTE 6778 above
8028               IF ( zdirs(k) <= horizon )  CYCLE
8029
8030               zexit = origin(1) + zdirs(k) * rt2_track_dist(i-1)
8031               IF ( zexit <= zbottom  .OR.  zexit >= ztop )  CYCLE
8032
8033               zsgn = -INT(SIGN(1._wp, zdirs(k)), iwp)
8034               rt2_dist(1) = 0._wp
8035               IF ( zdirs(k) == 0._wp )  THEN ! ray is exactly horizontal
8036                  nz = 2
8037                  rt2_dist(nz) = SQRT(dxxyy)
8038                  iz = NINT(zexit, iwp)
8039               ELSE
8040                  zorig = MIN(MAX(origin(1) + zdirs(k) * rt2_track_dist(i), zbottom), ztop)
8041
8042                  zb0 = FLOOR(  zorig * zsgn - .5_wp) + 1  ! because it must be greater than orig
8043                  zb1 = CEILING(zexit * zsgn - .5_wp) - 1  ! because it must be smaller than exit
8044                  nz = MAX(zb1 - zb0 + 3, 2)
8045                  rt2_dist(nz) = SQRT(((zexit-zorig)*dz(1))**2 + dxxyy)
8046                  qdist = rt2_dist(nz) / (zexit-zorig)
8047                  rt2_dist(2:nz-1) = (/( ((REAL(l, wp) + .5_wp) * zsgn - zorig) * qdist , l = zb0, zb1 )/)
8048                  iz = zb0 * zsgn
8049               ENDIF
8050
8051               DO  l = 2, nz
8052                  IF ( rt2_track_lad(iz, i) > 0._wp )  THEN
8053                     curtrans = exp(-ext_coef * rt2_track_lad(iz, i) * (rt2_dist(l)-rt2_dist(l-1)))
8054
8055                     IF ( create_csf )  THEN
8056                        ncsfl = ncsfl + 1
8057                        acsf(ncsfl)%ip = ip
8058                        acsf(ncsfl)%itx = rt2_track(2,i)
8059                        acsf(ncsfl)%ity = rt2_track(1,i)
8060                        acsf(ncsfl)%itz = iz
8061                        IF ( itarget(k) /= -1 ) STOP 1 !FIXME remove after test
8062                        acsf(ncsfl)%isurfs = -1
8063                        acsf(ncsfl)%rcvf = (1._wp - curtrans)*transparency(k)*aorig*vffrac(k)
8064                     ENDIF  ! create_csf
8065
8066                     transparency(k) = transparency(k) * curtrans
8067                  ENDIF
8068                  iz = iz + zsgn
8069               ENDDO ! l = 1, nz - 1
8070            ENDDO ! k = 1, nrays
8071         ENDDO ! i = 1, ntrack
8072      ENDIF ! plant_canopy
8073
8074      IF ( .NOT. (rad_angular_discretization  .AND.  calc_svf) )  THEN
8075!
8076!--      Just update lowest_free_ray according to horizon
8077         DO WHILE ( lowest_free_ray > 0 )
8078            IF ( zdirs(lowest_free_ray) > horizon )  EXIT
8079            lowest_free_ray = lowest_free_ray - 1
8080         ENDDO
8081      ENDIF
8082
8083   CONTAINS
8084
8085      SUBROUTINE request_itarget( d, z, y, x, isurfl, iproc )
8086
8087         INTEGER(iwp), INTENT(in)            ::  d, z, y, x
8088         INTEGER(iwp), TARGET, INTENT(out)   ::  isurfl
8089         INTEGER(iwp), INTENT(out)           ::  iproc
8090#if defined( __parallel )
8091#else
8092         INTEGER(iwp)                        ::  target_displ  !< index of the grid in the local gridsurf array
8093#endif
8094         INTEGER(iwp)                        ::  px, py        !< number of processors in x and y direction
8095                                                               !< before the processor in the question
8096#if defined( __parallel )
8097         INTEGER(KIND=MPI_ADDRESS_KIND)      ::  target_displ  !< index of the grid in the local gridsurf array
8098
8099!
8100!--      Calculate target processor and index in the remote local target gridsurf array
8101         px = x / nnx
8102         py = y / nny
8103         iproc = px * pdims(2) + py
8104         target_displ = ((x-px*nnx) * nny + y - py*nny ) * nzu * nsurf_type_u +&
8105                        ( z-nzub ) * nsurf_type_u + d
8106!
8107!--      Send MPI_Get request to obtain index target_surfl(i)
8108         CALL MPI_GET( isurfl, 1, MPI_INTEGER, iproc, target_displ,            &
8109                       1, MPI_INTEGER, win_gridsurf, ierr)
8110         IF ( ierr /= 0 )  THEN
8111            WRITE( 9,* ) 'Error MPI_Get3:', ierr, isurfl, iproc, target_displ, &
8112                         win_gridsurf
8113            FLUSH( 9 )
8114         ENDIF
8115#else
8116!--      set index target_surfl(i)
8117         isurfl = gridsurf(d,z,y,x)
8118#endif
8119
8120      END SUBROUTINE request_itarget
8121
8122   END SUBROUTINE raytrace_2d
8123 
8124
8125!------------------------------------------------------------------------------!
8126!
8127! Description:
8128! ------------
8129!> Calculates apparent solar positions for all timesteps and stores discretized
8130!> positions.
8131!------------------------------------------------------------------------------!
8132   SUBROUTINE radiation_presimulate_solar_pos
8133
8134      IMPLICIT NONE
8135
8136      INTEGER(iwp)                              ::  it, i, j
8137      INTEGER(iwp)                              ::  day_of_month_prev,month_of_year_prev
8138      REAL(wp)                                  ::  tsrp_prev
8139      REAL(wp)                                  ::  simulated_time_prev
8140      REAL(wp), DIMENSION(:,:), ALLOCATABLE     ::  dsidir_tmp       !< dsidir_tmp[:,i] = unit vector of i-th
8141                                                                     !< appreant solar direction
8142
8143      ALLOCATE ( dsidir_rev(0:raytrace_discrete_elevs/2-1,                 &
8144                            0:raytrace_discrete_azims-1) )
8145      dsidir_rev(:,:) = -1
8146      ALLOCATE ( dsidir_tmp(3,                                             &
8147                     raytrace_discrete_elevs/2*raytrace_discrete_azims) )
8148      ndsidir = 0
8149
8150!
8151!--   We will artificialy update time_since_reference_point and return to
8152!--   true value later
8153      tsrp_prev = time_since_reference_point
8154      simulated_time_prev = simulated_time
8155      day_of_month_prev = day_of_month
8156      month_of_year_prev = month_of_year
8157      sun_direction = .TRUE.
8158
8159!
8160!--   Process spinup time if configured
8161      IF ( spinup_time > 0._wp )  THEN
8162         DO  it = 0, CEILING(spinup_time / dt_spinup)
8163            time_since_reference_point = -spinup_time + REAL(it, wp) * dt_spinup
8164            simulated_time = simulated_time + dt_spinup
8165            CALL simulate_pos
8166         ENDDO
8167      ENDIF
8168!
8169!--   Process simulation time
8170      DO  it = 0, CEILING(( end_time - spinup_time ) / dt_radiation)
8171         time_since_reference_point = REAL(it, wp) * dt_radiation
8172         simulated_time = simulated_time + dt_radiation
8173         CALL simulate_pos
8174      ENDDO
8175!
8176!--   Return date and time to its original values
8177      time_since_reference_point = tsrp_prev
8178      simulated_time = simulated_time_prev
8179      day_of_month = day_of_month_prev
8180      month_of_year = month_of_year_prev
8181      CALL init_date_and_time
8182
8183!--   Allocate global vars which depend on ndsidir
8184      ALLOCATE ( dsidir ( 3, ndsidir ) )
8185      dsidir(:,:) = dsidir_tmp(:, 1:ndsidir)
8186      DEALLOCATE ( dsidir_tmp )
8187
8188      ALLOCATE ( dsitrans(nsurfl, ndsidir) )
8189      ALLOCATE ( dsitransc(npcbl, ndsidir) )
8190      IF ( nmrtbl > 0 )  ALLOCATE ( mrtdsit(nmrtbl, ndsidir) )
8191
8192      WRITE ( message_string, * ) 'Precalculated', ndsidir, ' solar positions', &
8193                                  'from', it, ' timesteps.'
8194      CALL message( 'radiation_presimulate_solar_pos', 'UI0013', 0, 0, 0, 6, 0 )
8195
8196      CONTAINS
8197
8198      !------------------------------------------------------------------------!
8199      ! Description:
8200      ! ------------
8201      !> Simuates a single position
8202      !------------------------------------------------------------------------!
8203      SUBROUTINE simulate_pos
8204         IMPLICIT NONE
8205!
8206!--      Update apparent solar position based on modified t_s_r_p
8207         CALL calc_zenith
8208         IF ( zenith(0) > 0 )  THEN
8209!--         
8210!--         Identify solar direction vector (discretized number) 1)
8211            i = MODULO(NINT(ATAN2(sun_dir_lon(0), sun_dir_lat(0))               &
8212                            / (2._wp*pi) * raytrace_discrete_azims-.5_wp, iwp), &
8213                       raytrace_discrete_azims)
8214            j = FLOOR(ACOS(zenith(0)) / pi * raytrace_discrete_elevs)
8215            IF ( dsidir_rev(j, i) == -1 )  THEN
8216               ndsidir = ndsidir + 1
8217               dsidir_tmp(:, ndsidir) =                                              &
8218                     (/ COS((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs), &
8219                        SIN((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs)  &
8220                      * COS((REAL(i,wp)+.5_wp) * 2_wp*pi / raytrace_discrete_azims), &
8221                        SIN((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs)  &
8222                      * SIN((REAL(i,wp)+.5_wp) * 2_wp*pi / raytrace_discrete_azims) /)
8223               dsidir_rev(j, i) = ndsidir
8224            ENDIF
8225         ENDIF
8226      END SUBROUTINE simulate_pos
8227
8228   END SUBROUTINE radiation_presimulate_solar_pos
8229
8230
8231
8232!------------------------------------------------------------------------------!
8233! Description:
8234! ------------
8235!> Determines whether two faces are oriented towards each other. Since the
8236!> surfaces follow the gird box surfaces, it checks first whether the two surfaces
8237!> are directed in the same direction, then it checks if the two surfaces are
8238!> located in confronted direction but facing away from each other, e.g. <--| |-->
8239!------------------------------------------------------------------------------!
8240    PURE LOGICAL FUNCTION surface_facing(x, y, z, d, x2, y2, z2, d2)
8241        IMPLICIT NONE
8242        INTEGER(iwp),   INTENT(in)  :: x, y, z, d, x2, y2, z2, d2
8243     
8244        surface_facing = .FALSE.
8245
8246!-- first check: are the two surfaces directed in the same direction
8247        IF ( (d==iup_u  .OR.  d==iup_l )                             &
8248             .AND. (d2==iup_u  .OR. d2==iup_l) ) RETURN
8249        IF ( (d==isouth_u  .OR.  d==isouth_l ) &
8250             .AND.  (d2==isouth_u  .OR.  d2==isouth_l) ) RETURN
8251        IF ( (d==inorth_u  .OR.  d==inorth_l ) &
8252             .AND.  (d2==inorth_u  .OR.  d2==inorth_l) ) RETURN
8253        IF ( (d==iwest_u  .OR.  d==iwest_l )     &
8254             .AND.  (d2==iwest_u  .OR.  d2==iwest_l ) ) RETURN
8255        IF ( (d==ieast_u  .OR.  d==ieast_l )     &
8256             .AND.  (d2==ieast_u  .OR.  d2==ieast_l ) ) RETURN
8257
8258!-- second check: are surfaces facing away from each other
8259        SELECT CASE (d)
8260            CASE (iup_u, iup_l)                     !< upward facing surfaces
8261                IF ( z2 < z ) RETURN
8262            CASE (isouth_u, isouth_l)               !< southward facing surfaces
8263                IF ( y2 > y ) RETURN
8264            CASE (inorth_u, inorth_l)               !< northward facing surfaces
8265                IF ( y2 < y ) RETURN
8266            CASE (iwest_u, iwest_l)                 !< westward facing surfaces
8267                IF ( x2 > x ) RETURN
8268            CASE (ieast_u, ieast_l)                 !< eastward facing surfaces
8269                IF ( x2 < x ) RETURN
8270        END SELECT
8271
8272        SELECT CASE (d2)
8273            CASE (iup_u)                            !< ground, roof
8274                IF ( z < z2 ) RETURN
8275            CASE (isouth_u, isouth_l)               !< south facing
8276                IF ( y > y2 ) RETURN
8277            CASE (inorth_u, inorth_l)               !< north facing
8278                IF ( y < y2 ) RETURN
8279            CASE (iwest_u, iwest_l)                 !< west facing
8280                IF ( x > x2 ) RETURN
8281            CASE (ieast_u, ieast_l)                 !< east facing
8282                IF ( x < x2 ) RETURN
8283            CASE (-1)
8284                CONTINUE
8285        END SELECT
8286
8287        surface_facing = .TRUE.
8288       
8289    END FUNCTION surface_facing
8290
8291
8292!------------------------------------------------------------------------------!
8293!
8294! Description:
8295! ------------
8296!> Reads svf, svfsurf, csf, csfsurf and mrt factors data from saved file
8297!> SVF means sky view factors and CSF means canopy sink factors
8298!------------------------------------------------------------------------------!
8299    SUBROUTINE radiation_read_svf
8300
8301       IMPLICIT NONE
8302       
8303       CHARACTER(rad_version_len)   :: rad_version_field
8304       
8305       INTEGER(iwp)                 :: i
8306       INTEGER(iwp)                 :: ndsidir_from_file = 0
8307       INTEGER(iwp)                 :: npcbl_from_file = 0
8308       INTEGER(iwp)                 :: nsurfl_from_file = 0
8309       INTEGER(iwp)                 :: nmrtbl_from_file = 0
8310       
8311       DO  i = 0, io_blocks-1
8312          IF ( i == io_group )  THEN
8313
8314!
8315!--          numprocs_previous_run is only known in case of reading restart
8316!--          data. If a new initial run which reads svf data is started the
8317!--          following query will be skipped
8318             IF ( initializing_actions == 'read_restart_data' ) THEN
8319
8320                IF ( numprocs_previous_run /= numprocs ) THEN
8321                   WRITE( message_string, * ) 'A different number of ',        &
8322                                              'processors between the run ',   &
8323                                              'that has written the svf data ',&
8324                                              'and the one that will read it ',&
8325                                              'is not allowed' 
8326                   CALL message( 'check_open', 'PA0491', 1, 2, 0, 6, 0 )
8327                ENDIF
8328
8329             ENDIF
8330             
8331!
8332!--          Open binary file
8333             CALL check_open( 88 )
8334
8335!
8336!--          read and check version
8337             READ ( 88 ) rad_version_field
8338             IF ( TRIM(rad_version_field) /= TRIM(rad_version) )  THEN
8339                 WRITE( message_string, * ) 'Version of binary SVF file "',    &
8340                             TRIM(rad_version_field), '" does not match ',     &
8341                             'the version of model "', TRIM(rad_version), '"'
8342                 CALL message( 'radiation_read_svf', 'PA0482', 1, 2, 0, 6, 0 )
8343             ENDIF
8344             
8345!
8346!--          read nsvfl, ncsfl, nsurfl, nmrtf
8347             READ ( 88 ) nsvfl, ncsfl, nsurfl_from_file, npcbl_from_file,      &
8348                         ndsidir_from_file, nmrtbl_from_file, nmrtf
8349             
8350             IF ( nsvfl < 0  .OR.  ncsfl < 0 )  THEN
8351                 WRITE( message_string, * ) 'Wrong number of SVF or CSF'
8352                 CALL message( 'radiation_read_svf', 'PA0483', 1, 2, 0, 6, 0 )
8353             ELSE
8354                 WRITE(message_string,*) '    Number of SVF, CSF, and nsurfl ',&
8355                                         'to read', nsvfl, ncsfl,              &
8356                                         nsurfl_from_file
8357                 CALL location_message( message_string, .TRUE. )
8358             ENDIF
8359             
8360             IF ( nsurfl_from_file /= nsurfl )  THEN
8361                 WRITE( message_string, * ) 'nsurfl from SVF file does not ',  &
8362                                            'match calculated nsurfl from ',   &
8363                                            'radiation_interaction_init'
8364                 CALL message( 'radiation_read_svf', 'PA0490', 1, 2, 0, 6, 0 )
8365             ENDIF
8366             
8367             IF ( npcbl_from_file /= npcbl )  THEN
8368                 WRITE( message_string, * ) 'npcbl from SVF file does not ',   &
8369                                            'match calculated npcbl from ',    &
8370                                            'radiation_interaction_init'
8371                 CALL message( 'radiation_read_svf', 'PA0493', 1, 2, 0, 6, 0 )
8372             ENDIF
8373             
8374             IF ( ndsidir_from_file /= ndsidir )  THEN
8375                 WRITE( message_string, * ) 'ndsidir from SVF file does not ', &
8376                                            'match calculated ndsidir from ',  &
8377                                            'radiation_presimulate_solar_pos'
8378                 CALL message( 'radiation_read_svf', 'PA0494', 1, 2, 0, 6, 0 )
8379             ENDIF
8380             IF ( nmrtbl_from_file /= nmrtbl )  THEN
8381                 WRITE( message_string, * ) 'nmrtbl from SVF file does not ',  &
8382                                            'match calculated nmrtbl from ',   &
8383                                            'radiation_interaction_init'
8384                 CALL message( 'radiation_read_svf', 'PA0494', 1, 2, 0, 6, 0 )
8385             ELSE
8386                 WRITE(message_string,*) '    Number of nmrtf to read ', nmrtf
8387                 CALL location_message( message_string, .TRUE. )
8388             ENDIF
8389             
8390!
8391!--          Arrays skyvf, skyvft, dsitrans and dsitransc are allready
8392!--          allocated in radiation_interaction_init and
8393!--          radiation_presimulate_solar_pos
8394             IF ( nsurfl > 0 )  THEN
8395                READ(88) skyvf
8396                READ(88) skyvft
8397                READ(88) dsitrans 
8398             ENDIF
8399             
8400             IF ( plant_canopy  .AND.  npcbl > 0 ) THEN
8401                READ ( 88 )  dsitransc
8402             ENDIF
8403             
8404!
8405!--          The allocation of svf, svfsurf, csf, csfsurf, mrtf, mrtft, and
8406!--          mrtfsurf happens in routine radiation_calc_svf which is not
8407!--          called if the program enters radiation_read_svf. Therefore
8408!--          these arrays has to allocate in the following
8409             IF ( nsvfl > 0 )  THEN
8410                ALLOCATE( svf(ndsvf,nsvfl) )
8411                ALLOCATE( svfsurf(idsvf,nsvfl) )
8412                READ(88) svf
8413                READ(88) svfsurf
8414             ENDIF
8415
8416             IF ( plant_canopy  .AND.  ncsfl > 0 )  THEN
8417                ALLOCATE( csf(ndcsf,ncsfl) )
8418                ALLOCATE( csfsurf(idcsf,ncsfl) )
8419                READ(88) csf
8420                READ(88) csfsurf
8421             ENDIF
8422
8423             IF ( nmrtbl > 0 )  THEN
8424                READ(88) mrtsky
8425                READ(88) mrtskyt
8426                READ(88) mrtdsit
8427             ENDIF
8428
8429             IF ( nmrtf > 0 )  THEN
8430                ALLOCATE ( mrtf(nmrtf) )
8431                ALLOCATE ( mrtft(nmrtf) )
8432                ALLOCATE ( mrtfsurf(2,nmrtf) )
8433                READ(88) mrtf
8434                READ(88) mrtft
8435                READ(88) mrtfsurf
8436             ENDIF
8437             
8438!
8439!--          Close binary file                 
8440             CALL close_file( 88 )
8441               
8442          ENDIF
8443#if defined( __parallel )
8444          CALL MPI_BARRIER( comm2d, ierr )
8445#endif
8446       ENDDO
8447
8448    END SUBROUTINE radiation_read_svf
8449
8450
8451!------------------------------------------------------------------------------!
8452!
8453! Description:
8454! ------------
8455!> Subroutine stores svf, svfsurf, csf, csfsurf and mrt data to a file.
8456!------------------------------------------------------------------------------!
8457    SUBROUTINE radiation_write_svf
8458
8459       IMPLICIT NONE
8460       
8461       INTEGER(iwp)        :: i
8462
8463       DO  i = 0, io_blocks-1
8464          IF ( i == io_group )  THEN
8465!
8466!--          Open binary file
8467             CALL check_open( 89 )
8468
8469             WRITE ( 89 )  rad_version
8470             WRITE ( 89 )  nsvfl, ncsfl, nsurfl, npcbl, ndsidir, nmrtbl, nmrtf
8471             IF ( nsurfl > 0 ) THEN
8472                WRITE ( 89 )  skyvf
8473                WRITE ( 89 )  skyvft
8474                WRITE ( 89 )  dsitrans
8475             ENDIF
8476             IF ( npcbl > 0 ) THEN
8477                WRITE ( 89 )  dsitransc
8478             ENDIF
8479             IF ( nsvfl > 0 ) THEN
8480                WRITE ( 89 )  svf
8481                WRITE ( 89 )  svfsurf
8482             ENDIF
8483             IF ( plant_canopy  .AND.  ncsfl > 0 )  THEN
8484                 WRITE ( 89 )  csf
8485                 WRITE ( 89 )  csfsurf
8486             ENDIF
8487             IF ( nmrtbl > 0 )  THEN
8488                WRITE ( 89 ) mrtsky
8489                WRITE ( 89 ) mrtskyt
8490                WRITE ( 89 ) mrtdsit
8491             ENDIF
8492             IF ( nmrtf > 0 )  THEN
8493                 WRITE ( 89 )  mrtf
8494                 WRITE ( 89 )  mrtft               
8495                 WRITE ( 89 )  mrtfsurf
8496             ENDIF
8497!
8498!--          Close binary file                 
8499             CALL close_file( 89 )
8500
8501          ENDIF
8502#if defined( __parallel )
8503          CALL MPI_BARRIER( comm2d, ierr )
8504#endif
8505       ENDDO
8506    END SUBROUTINE radiation_write_svf
8507
8508
8509!------------------------------------------------------------------------------!
8510!
8511! Description:
8512! ------------
8513!> Block of auxiliary subroutines:
8514!> 1. quicksort and corresponding comparison
8515!> 2. merge_and_grow_csf for implementation of "dynamical growing"
8516!>    array for csf
8517!------------------------------------------------------------------------------!
8518!-- quicksort.f -*-f90-*-
8519!-- Author: t-nissie, adaptation J.Resler
8520!-- License: GPLv3
8521!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8522    RECURSIVE SUBROUTINE quicksort_itarget(itarget, vffrac, ztransp, first, last)
8523        IMPLICIT NONE
8524        INTEGER(iwp), DIMENSION(:), INTENT(INOUT)   :: itarget
8525        REAL(wp), DIMENSION(:), INTENT(INOUT)       :: vffrac, ztransp
8526        INTEGER(iwp), INTENT(IN)                    :: first, last
8527        INTEGER(iwp)                                :: x, t
8528        INTEGER(iwp)                                :: i, j
8529        REAL(wp)                                    :: tr
8530
8531        IF ( first>=last ) RETURN
8532        x = itarget((first+last)/2)
8533        i = first
8534        j = last
8535        DO
8536            DO WHILE ( itarget(i) < x )
8537               i=i+1
8538            ENDDO
8539            DO WHILE ( x < itarget(j) )
8540                j=j-1
8541            ENDDO
8542            IF ( i >= j ) EXIT
8543            t = itarget(i);  itarget(i) = itarget(j);  itarget(j) = t
8544            tr = vffrac(i);  vffrac(i) = vffrac(j);  vffrac(j) = tr
8545            tr = ztransp(i);  ztransp(i) = ztransp(j);  ztransp(j) = tr
8546            i=i+1
8547            j=j-1
8548        ENDDO
8549        IF ( first < i-1 ) CALL quicksort_itarget(itarget, vffrac, ztransp, first, i-1)
8550        IF ( j+1 < last )  CALL quicksort_itarget(itarget, vffrac, ztransp, j+1, last)
8551    END SUBROUTINE quicksort_itarget
8552
8553    PURE FUNCTION svf_lt(svf1,svf2) result (res)
8554      TYPE (t_svf), INTENT(in) :: svf1,svf2
8555      LOGICAL                  :: res
8556      IF ( svf1%isurflt < svf2%isurflt  .OR.    &
8557          (svf1%isurflt == svf2%isurflt  .AND.  svf1%isurfs < svf2%isurfs) )  THEN
8558          res = .TRUE.
8559      ELSE
8560          res = .FALSE.
8561      ENDIF
8562    END FUNCTION svf_lt
8563
8564
8565!-- quicksort.f -*-f90-*-
8566!-- Author: t-nissie, adaptation J.Resler
8567!-- License: GPLv3
8568!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8569    RECURSIVE SUBROUTINE quicksort_svf(svfl, first, last)
8570        IMPLICIT NONE
8571        TYPE(t_svf), DIMENSION(:), INTENT(INOUT)  :: svfl
8572        INTEGER(iwp), INTENT(IN)                  :: first, last
8573        TYPE(t_svf)                               :: x, t
8574        INTEGER(iwp)                              :: i, j
8575
8576        IF ( first>=last ) RETURN
8577        x = svfl( (first+last) / 2 )
8578        i = first
8579        j = last
8580        DO
8581            DO while ( svf_lt(svfl(i),x) )
8582               i=i+1
8583            ENDDO
8584            DO while ( svf_lt(x,svfl(j)) )
8585                j=j-1
8586            ENDDO
8587            IF ( i >= j ) EXIT
8588            t = svfl(i);  svfl(i) = svfl(j);  svfl(j) = t
8589            i=i+1
8590            j=j-1
8591        ENDDO
8592        IF ( first < i-1 ) CALL quicksort_svf(svfl, first, i-1)
8593        IF ( j+1 < last )  CALL quicksort_svf(svfl, j+1, last)
8594    END SUBROUTINE quicksort_svf
8595
8596    PURE FUNCTION csf_lt(csf1,csf2) result (res)
8597      TYPE (t_csf), INTENT(in) :: csf1,csf2
8598      LOGICAL                  :: res
8599      IF ( csf1%ip < csf2%ip  .OR.    &
8600           (csf1%ip == csf2%ip  .AND.  csf1%itx < csf2%itx)  .OR.  &
8601           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity < csf2%ity)  .OR.  &
8602           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity == csf2%ity  .AND.   &
8603            csf1%itz < csf2%itz)  .OR.  &
8604           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity == csf2%ity  .AND.   &
8605            csf1%itz == csf2%itz  .AND.  csf1%isurfs < csf2%isurfs) )  THEN
8606          res = .TRUE.
8607      ELSE
8608          res = .FALSE.
8609      ENDIF
8610    END FUNCTION csf_lt
8611
8612
8613!-- quicksort.f -*-f90-*-
8614!-- Author: t-nissie, adaptation J.Resler
8615!-- License: GPLv3
8616!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8617    RECURSIVE SUBROUTINE quicksort_csf(csfl, first, last)
8618        IMPLICIT NONE
8619        TYPE(t_csf), DIMENSION(:), INTENT(INOUT)  :: csfl
8620        INTEGER(iwp), INTENT(IN)                  :: first, last
8621        TYPE(t_csf)                               :: x, t
8622        INTEGER(iwp)                              :: i, j
8623
8624        IF ( first>=last ) RETURN
8625        x = csfl( (first+last)/2 )
8626        i = first
8627        j = last
8628        DO
8629            DO while ( csf_lt(csfl(i),x) )
8630                i=i+1
8631            ENDDO
8632            DO while ( csf_lt(x,csfl(j)) )
8633                j=j-1
8634            ENDDO
8635            IF ( i >= j ) EXIT
8636            t = csfl(i);  csfl(i) = csfl(j);  csfl(j) = t
8637            i=i+1
8638            j=j-1
8639        ENDDO
8640        IF ( first < i-1 ) CALL quicksort_csf(csfl, first, i-1)
8641        IF ( j+1 < last )  CALL quicksort_csf(csfl, j+1, last)
8642    END SUBROUTINE quicksort_csf
8643
8644   
8645    SUBROUTINE merge_and_grow_csf(newsize)
8646        INTEGER(iwp), INTENT(in)                :: newsize  !< new array size after grow, must be >= ncsfl
8647                                                            !< or -1 to shrink to minimum
8648        INTEGER(iwp)                            :: iread, iwrite
8649        TYPE(t_csf), DIMENSION(:), POINTER      :: acsfnew
8650        CHARACTER(100)                          :: msg
8651
8652        IF ( newsize == -1 )  THEN
8653!--         merge in-place
8654            acsfnew => acsf
8655        ELSE
8656!--         allocate new array
8657            IF ( mcsf == 0 )  THEN
8658                ALLOCATE( acsf1(newsize) )
8659                acsfnew => acsf1
8660            ELSE
8661                ALLOCATE( acsf2(newsize) )
8662                acsfnew => acsf2
8663            ENDIF
8664        ENDIF
8665
8666        IF ( ncsfl >= 1 )  THEN
8667!--         sort csf in place (quicksort)
8668            CALL quicksort_csf(acsf,1,ncsfl)
8669
8670!--         while moving to a new array, aggregate canopy sink factor records with identical box & source
8671            acsfnew(1) = acsf(1)
8672            iwrite = 1
8673            DO iread = 2, ncsfl
8674!--             here acsf(kcsf) already has values from acsf(icsf)
8675                IF ( acsfnew(iwrite)%itx == acsf(iread)%itx &
8676                         .AND.  acsfnew(iwrite)%ity == acsf(iread)%ity &
8677                         .AND.  acsfnew(iwrite)%itz == acsf(iread)%itz &
8678                         .AND.  acsfnew(iwrite)%isurfs == acsf(iread)%isurfs )  THEN
8679
8680                    acsfnew(iwrite)%rcvf = acsfnew(iwrite)%rcvf + acsf(iread)%rcvf
8681!--                 advance reading index, keep writing index
8682                ELSE
8683!--                 not identical, just advance and copy
8684                    iwrite = iwrite + 1
8685                    acsfnew(iwrite) = acsf(iread)
8686                ENDIF
8687            ENDDO
8688            ncsfl = iwrite
8689        ENDIF
8690
8691        IF ( newsize == -1 )  THEN
8692!--         allocate new array and copy shrinked data
8693            IF ( mcsf == 0 )  THEN
8694                ALLOCATE( acsf1(ncsfl) )
8695                acsf1(1:ncsfl) = acsf2(1:ncsfl)
8696            ELSE
8697                ALLOCATE( acsf2(ncsfl) )
8698                acsf2(1:ncsfl) = acsf1(1:ncsfl)
8699            ENDIF
8700        ENDIF
8701
8702!--     deallocate old array
8703        IF ( mcsf == 0 )  THEN
8704            mcsf = 1
8705            acsf => acsf1
8706            DEALLOCATE( acsf2 )
8707        ELSE
8708            mcsf = 0
8709            acsf => acsf2
8710            DEALLOCATE( acsf1 )
8711        ENDIF
8712        ncsfla = newsize
8713
8714        WRITE(msg,'(A,2I12)') 'Grow acsf2:',ncsfl,ncsfla
8715        CALL radiation_write_debug_log( msg )
8716
8717    END SUBROUTINE merge_and_grow_csf
8718
8719   
8720!-- quicksort.f -*-f90-*-
8721!-- Author: t-nissie, adaptation J.Resler
8722!-- License: GPLv3
8723!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8724    RECURSIVE SUBROUTINE quicksort_csf2(kpcsflt, pcsflt, first, last)
8725        IMPLICIT NONE
8726        INTEGER(iwp), DIMENSION(:,:), INTENT(INOUT)  :: kpcsflt
8727        REAL(wp), DIMENSION(:,:), INTENT(INOUT)      :: pcsflt
8728        INTEGER(iwp), INTENT(IN)                     :: first, last
8729        REAL(wp), DIMENSION(ndcsf)                   :: t2
8730        INTEGER(iwp), DIMENSION(kdcsf)               :: x, t1
8731        INTEGER(iwp)                                 :: i, j
8732
8733        IF ( first>=last ) RETURN
8734        x = kpcsflt(:, (first+last)/2 )
8735        i = first
8736        j = last
8737        DO
8738            DO while ( csf_lt2(kpcsflt(:,i),x) )
8739                i=i+1
8740            ENDDO
8741            DO while ( csf_lt2(x,kpcsflt(:,j)) )
8742                j=j-1
8743            ENDDO
8744            IF ( i >= j ) EXIT
8745            t1 = kpcsflt(:,i);  kpcsflt(:,i) = kpcsflt(:,j);  kpcsflt(:,j) = t1
8746            t2 = pcsflt(:,i);  pcsflt(:,i) = pcsflt(:,j);  pcsflt(:,j) = t2
8747            i=i+1
8748            j=j-1
8749        ENDDO
8750        IF ( first < i-1 ) CALL quicksort_csf2(kpcsflt, pcsflt, first, i-1)
8751        IF ( j+1 < last )  CALL quicksort_csf2(kpcsflt, pcsflt, j+1, last)
8752    END SUBROUTINE quicksort_csf2
8753   
8754
8755    PURE FUNCTION csf_lt2(item1, item2) result(res)
8756        INTEGER(iwp), DIMENSION(kdcsf), INTENT(in)  :: item1, item2
8757        LOGICAL                                     :: res
8758        res = ( (item1(3) < item2(3))                                                        &
8759             .OR.  (item1(3) == item2(3)  .AND.  item1(2) < item2(2))                            &
8760             .OR.  (item1(3) == item2(3)  .AND.  item1(2) == item2(2)  .AND.  item1(1) < item2(1)) &
8761             .OR.  (item1(3) == item2(3)  .AND.  item1(2) == item2(2)  .AND.  item1(1) == item2(1) &
8762                 .AND.  item1(4) < item2(4)) )
8763    END FUNCTION csf_lt2
8764
8765    PURE FUNCTION searchsorted(athresh, val) result(ind)
8766        REAL(wp), DIMENSION(:), INTENT(IN)  :: athresh
8767        REAL(wp), INTENT(IN)                :: val
8768        INTEGER(iwp)                        :: ind
8769        INTEGER(iwp)                        :: i
8770
8771        DO i = LBOUND(athresh, 1), UBOUND(athresh, 1)
8772            IF ( val < athresh(i) ) THEN
8773                ind = i - 1
8774                RETURN
8775            ENDIF
8776        ENDDO
8777        ind = UBOUND(athresh, 1)
8778    END FUNCTION searchsorted
8779
8780!------------------------------------------------------------------------------!
8781! Description:
8782! ------------
8783!
8784!> radiation_radflux_gridbox subroutine gives the sw and lw radiation fluxes at the
8785!> faces of a gridbox defined at i,j,k and located in the urban layer.
8786!> The total sw and the diffuse sw radiation as well as the lw radiation fluxes at
8787!> the gridbox 6 faces are stored in sw_gridbox, swd_gridbox, and lw_gridbox arrays,
8788!> respectively, in the following order:
8789!>  up_face, down_face, north_face, south_face, east_face, west_face
8790!>
8791!> The subroutine reports also how successful was the search process via the parameter
8792!> i_feedback as follow:
8793!> - i_feedback =  1 : successful
8794!> - i_feedback = -1 : unsuccessful; the requisted point is outside the urban domain
8795!> - i_feedback =  0 : uncomplete; some gridbox faces fluxes are missing
8796!>
8797!>
8798!> It is called outside from usm_urban_surface_mod whenever the radiation fluxes
8799!> are needed.
8800!>
8801!> This routine is not used so far. However, it may serve as an interface for radiation
8802!> fluxes of urban and land surfaces
8803!>
8804!> TODO:
8805!>    - Compare performance when using some combination of the Fortran intrinsic
8806!>      functions, e.g. MINLOC, MAXLOC, ALL, ANY and COUNT functions, which search
8807!>      surfl array for elements meeting user-specified criterion, i.e. i,j,k
8808!>    - Report non-found or incomplete radiation fluxes arrays , if any, at the
8809!>      gridbox faces in an error message form
8810!>
8811!------------------------------------------------------------------------------!
8812    SUBROUTINE radiation_radflux_gridbox(i,j,k,sw_gridbox,swd_gridbox,lw_gridbox,i_feedback)
8813       
8814        IMPLICIT NONE
8815
8816        INTEGER(iwp),                 INTENT(in)  :: i,j,k                 !< gridbox indices at which fluxes are required
8817        INTEGER(iwp)                              :: ii,jj,kk,d            !< surface indices and type
8818        INTEGER(iwp)                              :: l                     !< surface id
8819        REAL(wp)    , DIMENSION(1:6), INTENT(out) :: sw_gridbox,lw_gridbox !< total sw and lw radiation fluxes of 6 faces of a gridbox, w/m2
8820        REAL(wp)    , DIMENSION(1:6), INTENT(out) :: swd_gridbox           !< diffuse sw radiation from sky and model boundary of 6 faces of a gridbox, w/m2
8821        INTEGER(iwp),                 INTENT(out) :: i_feedback            !< feedback to report how the search was successful
8822
8823
8824!-- initialize variables
8825        i_feedback  = -999999
8826        sw_gridbox  = -999999.9_wp
8827        lw_gridbox  = -999999.9_wp
8828        swd_gridbox = -999999.9_wp
8829       
8830!-- check the requisted grid indices
8831        IF ( k < nzb   .OR.  k > nzut  .OR.   &
8832             j < nysg  .OR.  j > nyng  .OR.   &
8833             i < nxlg  .OR.  i > nxrg         &
8834             ) THEN
8835           i_feedback = -1
8836           RETURN
8837        ENDIF
8838
8839!-- search for the required grid and formulate the fluxes at the 6 gridbox faces
8840        DO l = 1, nsurfl
8841            ii = surfl(ix,l)
8842            jj = surfl(iy,l)
8843            kk = surfl(iz,l)
8844
8845            IF ( ii == i  .AND.  jj == j  .AND.  kk == k ) THEN
8846               d = surfl(id,l)
8847
8848               SELECT CASE ( d )
8849
8850               CASE (iup_u,iup_l)                          !- gridbox up_facing face
8851                  sw_gridbox(1) = surfinsw(l)
8852                  lw_gridbox(1) = surfinlw(l)
8853                  swd_gridbox(1) = surfinswdif(l)
8854
8855               CASE (inorth_u,inorth_l)                    !- gridbox north_facing face
8856                  sw_gridbox(3) = surfinsw(l)
8857                  lw_gridbox(3) = surfinlw(l)
8858                  swd_gridbox(3) = surfinswdif(l)
8859
8860               CASE (isouth_u,isouth_l)                    !- gridbox south_facing face
8861                  sw_gridbox(4) = surfinsw(l)
8862                  lw_gridbox(4) = surfinlw(l)
8863                  swd_gridbox(4) = surfinswdif(l)
8864
8865               CASE (ieast_u,ieast_l)                      !- gridbox east_facing face
8866                  sw_gridbox(5) = surfinsw(l)
8867                  lw_gridbox(5) = surfinlw(l)
8868                  swd_gridbox(5) = surfinswdif(l)
8869
8870               CASE (iwest_u,iwest_l)                      !- gridbox west_facing face
8871                  sw_gridbox(6) = surfinsw(l)
8872                  lw_gridbox(6) = surfinlw(l)
8873                  swd_gridbox(6) = surfinswdif(l)
8874
8875               END SELECT
8876
8877            ENDIF
8878
8879        IF ( ALL( sw_gridbox(:)  /= -999999.9_wp )  ) EXIT
8880        ENDDO
8881
8882!-- check the completeness of the fluxes at all gidbox faces       
8883!-- TODO: report non-found or incomplete rad fluxes arrays in an error message form
8884        IF ( ANY( sw_gridbox(:)  <= -999999.9_wp )  .OR.   &
8885             ANY( swd_gridbox(:) <= -999999.9_wp )  .OR.   &
8886             ANY( lw_gridbox(:)  <= -999999.9_wp ) ) THEN
8887           i_feedback = 0
8888        ELSE
8889           i_feedback = 1
8890        ENDIF
8891       
8892        RETURN
8893       
8894    END SUBROUTINE radiation_radflux_gridbox
8895
8896!------------------------------------------------------------------------------!
8897!
8898! Description:
8899! ------------
8900!> Subroutine for averaging 3D data
8901!------------------------------------------------------------------------------!
8902SUBROUTINE radiation_3d_data_averaging( mode, variable )
8903 
8904
8905    USE control_parameters
8906
8907    USE indices
8908
8909    USE kinds
8910
8911    IMPLICIT NONE
8912
8913    CHARACTER (LEN=*) ::  mode    !<
8914    CHARACTER (LEN=*) :: variable !<
8915
8916    LOGICAL      ::  match_lsm !< flag indicating natural-type surface
8917    LOGICAL      ::  match_usm !< flag indicating urban-type surface
8918   
8919    INTEGER(iwp) ::  i !<
8920    INTEGER(iwp) ::  j !<
8921    INTEGER(iwp) ::  k !<
8922    INTEGER(iwp) ::  l, m !< index of current surface element
8923
8924    INTEGER(iwp)                                       :: ids, idsint_u, idsint_l, isurf
8925    CHARACTER(LEN=varnamelength)                       :: var
8926
8927!-- find the real name of the variable
8928    ids = -1
8929    l = -1
8930    var = TRIM(variable)
8931    DO i = 0, nd-1
8932        k = len(TRIM(var))
8933        j = len(TRIM(dirname(i)))
8934        IF ( k-j+1 >= 1_iwp ) THEN
8935           IF ( TRIM(var(k-j+1:k)) == TRIM(dirname(i)) )  THEN
8936               ids = i
8937               idsint_u = dirint_u(ids)
8938               idsint_l = dirint_l(ids)
8939               var = var(:k-j)
8940               EXIT
8941           ENDIF
8942        ENDIF
8943    ENDDO
8944    IF ( ids == -1 )  THEN
8945        var = TRIM(variable)
8946    ENDIF
8947
8948    IF ( mode == 'allocate' )  THEN
8949
8950       SELECT CASE ( TRIM( var ) )
8951!--          block of large scale (e.g. RRTMG) radiation output variables
8952             CASE ( 'rad_net*' )
8953                IF ( .NOT. ALLOCATED( rad_net_av ) )  THEN
8954                   ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
8955                ENDIF
8956                rad_net_av = 0.0_wp
8957             
8958             CASE ( 'rad_lw_in*' )
8959                IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) )  THEN
8960                   ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
8961                ENDIF
8962                rad_lw_in_xy_av = 0.0_wp
8963               
8964             CASE ( 'rad_lw_out*' )
8965                IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) )  THEN
8966                   ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
8967                ENDIF
8968                rad_lw_out_xy_av = 0.0_wp
8969               
8970             CASE ( 'rad_sw_in*' )
8971                IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) )  THEN
8972                   ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
8973                ENDIF
8974                rad_sw_in_xy_av = 0.0_wp
8975               
8976             CASE ( 'rad_sw_out*' )
8977                IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) )  THEN
8978                   ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
8979                ENDIF
8980                rad_sw_out_xy_av = 0.0_wp               
8981
8982             CASE ( 'rad_lw_in' )
8983                IF ( .NOT. ALLOCATED( rad_lw_in_av ) )  THEN
8984                   ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8985                ENDIF
8986                rad_lw_in_av = 0.0_wp
8987
8988             CASE ( 'rad_lw_out' )
8989                IF ( .NOT. ALLOCATED( rad_lw_out_av ) )  THEN
8990                   ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8991                ENDIF
8992                rad_lw_out_av = 0.0_wp
8993
8994             CASE ( 'rad_lw_cs_hr' )
8995                IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) )  THEN
8996                   ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8997                ENDIF
8998                rad_lw_cs_hr_av = 0.0_wp
8999
9000             CASE ( 'rad_lw_hr' )
9001                IF ( .NOT. ALLOCATED( rad_lw_hr_av ) )  THEN
9002                   ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9003                ENDIF
9004                rad_lw_hr_av = 0.0_wp
9005
9006             CASE ( 'rad_sw_in' )
9007                IF ( .NOT. ALLOCATED( rad_sw_in_av ) )  THEN
9008                   ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9009                ENDIF
9010                rad_sw_in_av = 0.0_wp
9011
9012             CASE ( 'rad_sw_out' )
9013                IF ( .NOT. ALLOCATED( rad_sw_out_av ) )  THEN
9014                   ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9015                ENDIF
9016                rad_sw_out_av = 0.0_wp
9017
9018             CASE ( 'rad_sw_cs_hr' )
9019                IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) )  THEN
9020                   ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9021                ENDIF
9022                rad_sw_cs_hr_av = 0.0_wp
9023
9024             CASE ( 'rad_sw_hr' )
9025                IF ( .NOT. ALLOCATED( rad_sw_hr_av ) )  THEN
9026                   ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9027                ENDIF
9028                rad_sw_hr_av = 0.0_wp
9029
9030!--          block of RTM output variables
9031             CASE ( 'rtm_rad_net' )
9032!--              array of complete radiation balance
9033                 IF ( .NOT.  ALLOCATED(surfradnet_av) )  THEN
9034                     ALLOCATE( surfradnet_av(nsurfl) )
9035                     surfradnet_av = 0.0_wp
9036                 ENDIF
9037
9038             CASE ( 'rtm_rad_insw' )
9039!--                 array of sw radiation falling to surface after i-th reflection
9040                 IF ( .NOT.  ALLOCATED(surfinsw_av) )  THEN
9041                     ALLOCATE( surfinsw_av(nsurfl) )
9042                     surfinsw_av = 0.0_wp
9043                 ENDIF
9044
9045             CASE ( 'rtm_rad_inlw' )
9046!--                 array of lw radiation falling to surface after i-th reflection
9047                 IF ( .NOT.  ALLOCATED(surfinlw_av) )  THEN
9048                     ALLOCATE( surfinlw_av(nsurfl) )
9049                     surfinlw_av = 0.0_wp
9050                 ENDIF
9051
9052             CASE ( 'rtm_rad_inswdir' )
9053!--                 array of direct sw radiation falling to surface from sun
9054                 IF ( .NOT.  ALLOCATED(surfinswdir_av) )  THEN
9055                     ALLOCATE( surfinswdir_av(nsurfl) )
9056                     surfinswdir_av = 0.0_wp
9057                 ENDIF
9058
9059             CASE ( 'rtm_rad_inswdif' )
9060!--                 array of difusion sw radiation falling to surface from sky and borders of the domain
9061                 IF ( .NOT.  ALLOCATED(surfinswdif_av) )  THEN
9062                     ALLOCATE( surfinswdif_av(nsurfl) )
9063                     surfinswdif_av = 0.0_wp
9064                 ENDIF
9065
9066             CASE ( 'rtm_rad_inswref' )
9067!--                 array of sw radiation falling to surface from reflections
9068                 IF ( .NOT.  ALLOCATED(surfinswref_av) )  THEN
9069                     ALLOCATE( surfinswref_av(nsurfl) )
9070                     surfinswref_av = 0.0_wp
9071                 ENDIF
9072
9073             CASE ( 'rtm_rad_inlwdif' )
9074!--                 array of sw radiation falling to surface after i-th reflection
9075                IF ( .NOT.  ALLOCATED(surfinlwdif_av) )  THEN
9076                     ALLOCATE( surfinlwdif_av(nsurfl) )
9077                     surfinlwdif_av = 0.0_wp
9078                 ENDIF
9079
9080             CASE ( 'rtm_rad_inlwref' )
9081!--                 array of lw radiation falling to surface from reflections
9082                 IF ( .NOT.  ALLOCATED(surfinlwref_av) )  THEN
9083                     ALLOCATE( surfinlwref_av(nsurfl) )
9084                     surfinlwref_av = 0.0_wp
9085                 ENDIF
9086
9087             CASE ( 'rtm_rad_outsw' )
9088!--                 array of sw radiation emitted from surface after i-th reflection
9089                 IF ( .NOT.  ALLOCATED(surfoutsw_av) )  THEN
9090                     ALLOCATE( surfoutsw_av(nsurfl) )
9091                     surfoutsw_av = 0.0_wp
9092                 ENDIF
9093
9094             CASE ( 'rtm_rad_outlw' )
9095!--                 array of lw radiation emitted from surface after i-th reflection
9096                 IF ( .NOT.  ALLOCATED(surfoutlw_av) )  THEN
9097                     ALLOCATE( surfoutlw_av(nsurfl) )
9098                     surfoutlw_av = 0.0_wp
9099                 ENDIF
9100             CASE ( 'rtm_rad_ressw' )
9101!--                 array of residua of sw radiation absorbed in surface after last reflection
9102                 IF ( .NOT.  ALLOCATED(surfins_av) )  THEN
9103                     ALLOCATE( surfins_av(nsurfl) )
9104                     surfins_av = 0.0_wp
9105                 ENDIF
9106
9107             CASE ( 'rtm_rad_reslw' )
9108!--                 array of residua of lw radiation absorbed in surface after last reflection
9109                 IF ( .NOT.  ALLOCATED(surfinl_av) )  THEN
9110                     ALLOCATE( surfinl_av(nsurfl) )
9111                     surfinl_av = 0.0_wp
9112                 ENDIF
9113
9114             CASE ( 'rtm_rad_pc_inlw' )
9115!--                 array of of lw radiation absorbed in plant canopy
9116                 IF ( .NOT.  ALLOCATED(pcbinlw_av) )  THEN
9117                     ALLOCATE( pcbinlw_av(1:npcbl) )
9118                     pcbinlw_av = 0.0_wp
9119                 ENDIF
9120
9121             CASE ( 'rtm_rad_pc_insw' )
9122!--                 array of of sw radiation absorbed in plant canopy
9123                 IF ( .NOT.  ALLOCATED(pcbinsw_av) )  THEN
9124                     ALLOCATE( pcbinsw_av(1:npcbl) )
9125                     pcbinsw_av = 0.0_wp
9126                 ENDIF
9127
9128             CASE ( 'rtm_rad_pc_inswdir' )
9129!--                 array of of direct sw radiation absorbed in plant canopy
9130                 IF ( .NOT.  ALLOCATED(pcbinswdir_av) )  THEN
9131                     ALLOCATE( pcbinswdir_av(1:npcbl) )
9132                     pcbinswdir_av = 0.0_wp
9133                 ENDIF
9134
9135             CASE ( 'rtm_rad_pc_inswdif' )
9136!--                 array of of diffuse sw radiation absorbed in plant canopy
9137                 IF ( .NOT.  ALLOCATED(pcbinswdif_av) )  THEN
9138                     ALLOCATE( pcbinswdif_av(1:npcbl) )
9139                     pcbinswdif_av = 0.0_wp
9140                 ENDIF
9141
9142             CASE ( 'rtm_rad_pc_inswref' )
9143!--                 array of of reflected sw radiation absorbed in plant canopy
9144                 IF ( .NOT.  ALLOCATED(pcbinswref_av) )  THEN
9145                     ALLOCATE( pcbinswref_av(1:npcbl) )
9146                     pcbinswref_av = 0.0_wp
9147                 ENDIF
9148
9149             CASE ( 'rtm_mrt_sw' )
9150                IF ( .NOT. ALLOCATED( mrtinsw_av ) )  THEN
9151                   ALLOCATE( mrtinsw_av(nmrtbl) )
9152                ENDIF
9153                mrtinsw_av = 0.0_wp
9154
9155             CASE ( 'rtm_mrt_lw' )
9156                IF ( .NOT. ALLOCATED( mrtinlw_av ) )  THEN
9157                   ALLOCATE( mrtinlw_av(nmrtbl) )
9158                ENDIF
9159                mrtinlw_av = 0.0_wp
9160
9161             CASE ( 'rtm_mrt' )
9162                IF ( .NOT. ALLOCATED( mrt_av ) )  THEN
9163                   ALLOCATE( mrt_av(nmrtbl) )
9164                ENDIF
9165                mrt_av = 0.0_wp
9166
9167          CASE DEFAULT
9168             CONTINUE
9169
9170       END SELECT
9171
9172    ELSEIF ( mode == 'sum' )  THEN
9173
9174       SELECT CASE ( TRIM( var ) )
9175!--       block of large scale (e.g. RRTMG) radiation output variables
9176          CASE ( 'rad_net*' )
9177             IF ( ALLOCATED( rad_net_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_net_av(j,i) = rad_net_av(j,i) +                   &
9188                                         surf_lsm_h%rad_net(m)
9189                      ELSEIF ( match_usm )  THEN
9190                         m = surf_usm_h%end_index(j,i)
9191                         rad_net_av(j,i) = rad_net_av(j,i) +                   &
9192                                         surf_usm_h%rad_net(m)
9193                      ENDIF
9194                   ENDDO
9195                ENDDO
9196             ENDIF
9197
9198          CASE ( 'rad_lw_in*' )
9199             IF ( ALLOCATED( rad_lw_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_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i) +         &
9210                                         surf_lsm_h%rad_lw_in(m)
9211                      ELSEIF ( match_usm )  THEN
9212                         m = surf_usm_h%end_index(j,i)
9213                         rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i) +         &
9214                                         surf_usm_h%rad_lw_in(m)
9215                      ENDIF
9216                   ENDDO
9217                ENDDO
9218             ENDIF
9219             
9220          CASE ( 'rad_lw_out*' )
9221             IF ( ALLOCATED( rad_lw_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_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i) +       &
9232                                                 surf_lsm_h%rad_lw_out(m)
9233                      ELSEIF ( match_usm )  THEN
9234                         m = surf_usm_h%end_index(j,i)
9235                         rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i) +       &
9236                                                 surf_usm_h%rad_lw_out(m)
9237                      ENDIF
9238                   ENDDO
9239                ENDDO
9240             ENDIF
9241             
9242          CASE ( 'rad_sw_in*' )
9243             IF ( ALLOCATED( rad_sw_in_xy_av ) ) THEN
9244                DO  i = nxl, nxr
9245                   DO  j = nys, nyn
9246                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9247                                  surf_lsm_h%end_index(j,i)
9248                      match_usm = surf_usm_h%start_index(j,i) <=               &
9249                                  surf_usm_h%end_index(j,i)
9250
9251                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9252                         m = surf_lsm_h%end_index(j,i)
9253                         rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i) +         &
9254                                                surf_lsm_h%rad_sw_in(m)
9255                      ELSEIF ( match_usm )  THEN
9256                         m = surf_usm_h%end_index(j,i)
9257                         rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i) +         &
9258                                                surf_usm_h%rad_sw_in(m)
9259                      ENDIF
9260                   ENDDO
9261                ENDDO
9262             ENDIF
9263             
9264          CASE ( 'rad_sw_out*' )
9265             IF ( ALLOCATED( rad_sw_out_xy_av ) ) THEN
9266                DO  i = nxl, nxr
9267                   DO  j = nys, nyn
9268                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9269                                  surf_lsm_h%end_index(j,i)
9270                      match_usm = surf_usm_h%start_index(j,i) <=               &
9271                                  surf_usm_h%end_index(j,i)
9272
9273                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9274                         m = surf_lsm_h%end_index(j,i)
9275                         rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i) +       &
9276                                                 surf_lsm_h%rad_sw_out(m)
9277                      ELSEIF ( match_usm )  THEN
9278                         m = surf_usm_h%end_index(j,i)
9279                         rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i) +       &
9280                                                 surf_usm_h%rad_sw_out(m)
9281                      ENDIF
9282                   ENDDO
9283                ENDDO
9284             ENDIF
9285             
9286          CASE ( 'rad_lw_in' )
9287             IF ( ALLOCATED( rad_lw_in_av ) ) THEN
9288                DO  i = nxlg, nxrg
9289                   DO  j = nysg, nyng
9290                      DO  k = nzb, nzt+1
9291                         rad_lw_in_av(k,j,i) = rad_lw_in_av(k,j,i)             &
9292                                               + rad_lw_in(k,j,i)
9293                      ENDDO
9294                   ENDDO
9295                ENDDO
9296             ENDIF
9297
9298          CASE ( 'rad_lw_out' )
9299             IF ( ALLOCATED( rad_lw_out_av ) ) THEN
9300                DO  i = nxlg, nxrg
9301                   DO  j = nysg, nyng
9302                      DO  k = nzb, nzt+1
9303                         rad_lw_out_av(k,j,i) = rad_lw_out_av(k,j,i)           &
9304                                                + rad_lw_out(k,j,i)
9305                      ENDDO
9306                   ENDDO
9307                ENDDO
9308             ENDIF
9309
9310          CASE ( 'rad_lw_cs_hr' )
9311             IF ( ALLOCATED( rad_lw_cs_hr_av ) ) THEN
9312                DO  i = nxlg, nxrg
9313                   DO  j = nysg, nyng
9314                      DO  k = nzb, nzt+1
9315                         rad_lw_cs_hr_av(k,j,i) = rad_lw_cs_hr_av(k,j,i)       &
9316                                                  + rad_lw_cs_hr(k,j,i)
9317                      ENDDO
9318                   ENDDO
9319                ENDDO
9320             ENDIF
9321
9322          CASE ( 'rad_lw_hr' )
9323             IF ( ALLOCATED( rad_lw_hr_av ) ) THEN
9324                DO  i = nxlg, nxrg
9325                   DO  j = nysg, nyng
9326                      DO  k = nzb, nzt+1
9327                         rad_lw_hr_av(k,j,i) = rad_lw_hr_av(k,j,i)             &
9328                                               + rad_lw_hr(k,j,i)
9329                      ENDDO
9330                   ENDDO
9331                ENDDO
9332             ENDIF
9333
9334          CASE ( 'rad_sw_in' )
9335             IF ( ALLOCATED( rad_sw_in_av ) ) THEN
9336                DO  i = nxlg, nxrg
9337                   DO  j = nysg, nyng
9338                      DO  k = nzb, nzt+1
9339                         rad_sw_in_av(k,j,i) = rad_sw_in_av(k,j,i)             &
9340                                               + rad_sw_in(k,j,i)
9341                      ENDDO
9342                   ENDDO
9343                ENDDO
9344             ENDIF
9345
9346          CASE ( 'rad_sw_out' )
9347             IF ( ALLOCATED( rad_sw_out_av ) ) THEN
9348                DO  i = nxlg, nxrg
9349                   DO  j = nysg, nyng
9350                      DO  k = nzb, nzt+1
9351                         rad_sw_out_av(k,j,i) = rad_sw_out_av(k,j,i)           &
9352                                                + rad_sw_out(k,j,i)
9353                      ENDDO
9354                   ENDDO
9355                ENDDO
9356             ENDIF
9357
9358          CASE ( 'rad_sw_cs_hr' )
9359             IF ( ALLOCATED( rad_sw_cs_hr_av ) ) THEN
9360                DO  i = nxlg, nxrg
9361                   DO  j = nysg, nyng
9362                      DO  k = nzb, nzt+1
9363                         rad_sw_cs_hr_av(k,j,i) = rad_sw_cs_hr_av(k,j,i)       &
9364                                                  + rad_sw_cs_hr(k,j,i)
9365                      ENDDO
9366                   ENDDO
9367                ENDDO
9368             ENDIF
9369
9370          CASE ( 'rad_sw_hr' )
9371             IF ( ALLOCATED( rad_sw_hr_av ) ) THEN
9372                DO  i = nxlg, nxrg
9373                   DO  j = nysg, nyng
9374                      DO  k = nzb, nzt+1
9375                         rad_sw_hr_av(k,j,i) = rad_sw_hr_av(k,j,i)             &
9376                                               + rad_sw_hr(k,j,i)
9377                      ENDDO
9378                   ENDDO
9379                ENDDO
9380             ENDIF
9381
9382!--       block of RTM output variables
9383          CASE ( 'rtm_rad_net' )
9384!--           array of complete radiation balance
9385              DO isurf = dirstart(ids), dirend(ids)
9386                 IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9387                    surfradnet_av(isurf) = surfinsw(isurf) - surfoutsw(isurf) +  surfinlw(isurf) - surfoutlw(isurf)
9388                 ENDIF
9389              ENDDO
9390
9391          CASE ( 'rtm_rad_insw' )
9392!--           array of sw radiation falling to surface after i-th reflection
9393              DO isurf = dirstart(ids), dirend(ids)
9394                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9395                      surfinsw_av(isurf) = surfinsw_av(isurf) + surfinsw(isurf)
9396                  ENDIF
9397              ENDDO
9398
9399          CASE ( 'rtm_rad_inlw' )
9400!--           array of lw radiation falling to surface after i-th reflection
9401              DO isurf = dirstart(ids), dirend(ids)
9402                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9403                      surfinlw_av(isurf) = surfinlw_av(isurf) + surfinlw(isurf)
9404                  ENDIF
9405              ENDDO
9406
9407          CASE ( 'rtm_rad_inswdir' )
9408!--           array of direct sw radiation falling to surface from sun
9409              DO isurf = dirstart(ids), dirend(ids)
9410                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9411                      surfinswdir_av(isurf) = surfinswdir_av(isurf) + surfinswdir(isurf)
9412                  ENDIF
9413              ENDDO
9414
9415          CASE ( 'rtm_rad_inswdif' )
9416!--           array of difusion sw radiation falling to surface from sky and borders of the domain
9417              DO isurf = dirstart(ids), dirend(ids)
9418                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9419                      surfinswdif_av(isurf) = surfinswdif_av(isurf) + surfinswdif(isurf)
9420                  ENDIF
9421              ENDDO
9422
9423          CASE ( 'rtm_rad_inswref' )
9424!--           array of sw radiation falling to surface from reflections
9425              DO isurf = dirstart(ids), dirend(ids)
9426                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9427                      surfinswref_av(isurf) = surfinswref_av(isurf) + surfinsw(isurf) - &
9428                                          surfinswdir(isurf) - surfinswdif(isurf)
9429                  ENDIF
9430              ENDDO
9431
9432
9433          CASE ( 'rtm_rad_inlwdif' )
9434!--           array of sw radiation falling to surface after i-th reflection
9435              DO isurf = dirstart(ids), dirend(ids)
9436                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9437                      surfinlwdif_av(isurf) = surfinlwdif_av(isurf) + surfinlwdif(isurf)
9438                  ENDIF
9439              ENDDO
9440!
9441          CASE ( 'rtm_rad_inlwref' )
9442!--           array of lw radiation falling to surface from reflections
9443              DO isurf = dirstart(ids), dirend(ids)
9444                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9445                      surfinlwref_av(isurf) = surfinlwref_av(isurf) + &
9446                                          surfinlw(isurf) - surfinlwdif(isurf)
9447                  ENDIF
9448              ENDDO
9449
9450          CASE ( 'rtm_rad_outsw' )
9451!--           array of sw radiation emitted from surface after i-th reflection
9452              DO isurf = dirstart(ids), dirend(ids)
9453                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9454                      surfoutsw_av(isurf) = surfoutsw_av(isurf) + surfoutsw(isurf)
9455                  ENDIF
9456              ENDDO
9457
9458          CASE ( 'rtm_rad_outlw' )
9459!--           array of lw radiation emitted from surface after i-th reflection
9460              DO isurf = dirstart(ids), dirend(ids)
9461                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9462                      surfoutlw_av(isurf) = surfoutlw_av(isurf) + surfoutlw(isurf)
9463                  ENDIF
9464              ENDDO
9465
9466          CASE ( 'rtm_rad_ressw' )
9467!--           array of residua of sw radiation absorbed in surface after last reflection
9468              DO isurf = dirstart(ids), dirend(ids)
9469                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9470                      surfins_av(isurf) = surfins_av(isurf) + surfins(isurf)
9471                  ENDIF
9472              ENDDO
9473
9474          CASE ( 'rtm_rad_reslw' )
9475!--           array of residua of lw radiation absorbed in surface after last reflection
9476              DO isurf = dirstart(ids), dirend(ids)
9477                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9478                      surfinl_av(isurf) = surfinl_av(isurf) + surfinl(isurf)
9479                  ENDIF
9480              ENDDO
9481
9482          CASE ( 'rtm_rad_pc_inlw' )
9483              DO l = 1, npcbl
9484                 pcbinlw_av(l) = pcbinlw_av(l) + pcbinlw(l)
9485              ENDDO
9486
9487          CASE ( 'rtm_rad_pc_insw' )
9488              DO l = 1, npcbl
9489                 pcbinsw_av(l) = pcbinsw_av(l) + pcbinsw(l)
9490              ENDDO
9491
9492          CASE ( 'rtm_rad_pc_inswdir' )
9493              DO l = 1, npcbl
9494                 pcbinswdir_av(l) = pcbinswdir_av(l) + pcbinswdir(l)
9495              ENDDO
9496
9497          CASE ( 'rtm_rad_pc_inswdif' )
9498              DO l = 1, npcbl
9499                 pcbinswdif_av(l) = pcbinswdif_av(l) + pcbinswdif(l)
9500              ENDDO
9501
9502          CASE ( 'rtm_rad_pc_inswref' )
9503              DO l = 1, npcbl
9504                 pcbinswref_av(l) = pcbinswref_av(l) + pcbinsw(l) - pcbinswdir(l) - pcbinswdif(l)
9505              ENDDO
9506
9507          CASE ( 'rad_mrt_sw' )
9508             IF ( ALLOCATED( mrtinsw_av ) )  THEN
9509                mrtinsw_av(:) = mrtinsw_av(:) + mrtinsw(:)
9510             ENDIF
9511
9512          CASE ( 'rad_mrt_lw' )
9513             IF ( ALLOCATED( mrtinlw_av ) )  THEN
9514                mrtinlw_av(:) = mrtinlw_av(:) + mrtinlw(:)
9515             ENDIF
9516
9517          CASE ( 'rad_mrt' )
9518             IF ( ALLOCATED( mrt_av ) )  THEN
9519                mrt_av(:) = mrt_av(:) + mrt(:)
9520             ENDIF
9521
9522          CASE DEFAULT
9523             CONTINUE
9524
9525       END SELECT
9526
9527    ELSEIF ( mode == 'average' )  THEN
9528
9529       SELECT CASE ( TRIM( var ) )
9530!--       block of large scale (e.g. RRTMG) radiation output variables
9531          CASE ( 'rad_net*' )
9532             IF ( ALLOCATED( rad_net_av ) ) THEN
9533                DO  i = nxlg, nxrg
9534                   DO  j = nysg, nyng
9535                      rad_net_av(j,i) = rad_net_av(j,i)                        &
9536                                        / REAL( average_count_3d, KIND=wp )
9537                   ENDDO
9538                ENDDO
9539             ENDIF
9540             
9541          CASE ( 'rad_lw_in*' )
9542             IF ( ALLOCATED( rad_lw_in_xy_av ) ) THEN
9543                DO  i = nxlg, nxrg
9544                   DO  j = nysg, nyng
9545                      rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i)              &
9546                                        / REAL( average_count_3d, KIND=wp )
9547                   ENDDO
9548                ENDDO
9549             ENDIF
9550             
9551          CASE ( 'rad_lw_out*' )
9552             IF ( ALLOCATED( rad_lw_out_xy_av ) ) THEN
9553                DO  i = nxlg, nxrg
9554                   DO  j = nysg, nyng
9555                      rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i)            &
9556                                        / REAL( average_count_3d, KIND=wp )
9557                   ENDDO
9558                ENDDO
9559             ENDIF
9560             
9561          CASE ( 'rad_sw_in*' )
9562             IF ( ALLOCATED( rad_sw_in_xy_av ) ) THEN
9563                DO  i = nxlg, nxrg
9564                   DO  j = nysg, nyng
9565                      rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i)              &
9566                                        / REAL( average_count_3d, KIND=wp )
9567                   ENDDO
9568                ENDDO
9569             ENDIF
9570             
9571          CASE ( 'rad_sw_out*' )
9572             IF ( ALLOCATED( rad_sw_out_xy_av ) ) THEN
9573                DO  i = nxlg, nxrg
9574                   DO  j = nysg, nyng
9575                      rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i)             &
9576                                        / REAL( average_count_3d, KIND=wp )
9577                   ENDDO
9578                ENDDO
9579             ENDIF
9580
9581          CASE ( 'rad_lw_in' )
9582             IF ( ALLOCATED( rad_lw_in_av ) ) THEN
9583                DO  i = nxlg, nxrg
9584                   DO  j = nysg, nyng
9585                      DO  k = nzb, nzt+1
9586                         rad_lw_in_av(k,j,i) = rad_lw_in_av(k,j,i)             &
9587                                               / REAL( average_count_3d, KIND=wp )
9588                      ENDDO
9589                   ENDDO
9590                ENDDO
9591             ENDIF
9592
9593          CASE ( 'rad_lw_out' )
9594             IF ( ALLOCATED( rad_lw_out_av ) ) THEN
9595                DO  i = nxlg, nxrg
9596                   DO  j = nysg, nyng
9597                      DO  k = nzb, nzt+1
9598                         rad_lw_out_av(k,j,i) = rad_lw_out_av(k,j,i)           &
9599                                                / REAL( average_count_3d, KIND=wp )
9600                      ENDDO
9601                   ENDDO
9602                ENDDO
9603             ENDIF
9604
9605          CASE ( 'rad_lw_cs_hr' )
9606             IF ( ALLOCATED( rad_lw_cs_hr_av ) ) THEN
9607                DO  i = nxlg, nxrg
9608                   DO  j = nysg, nyng
9609                      DO  k = nzb, nzt+1
9610                         rad_lw_cs_hr_av(k,j,i) = rad_lw_cs_hr_av(k,j,i)       &
9611                                                / REAL( average_count_3d, KIND=wp )
9612                      ENDDO
9613                   ENDDO
9614                ENDDO
9615             ENDIF
9616
9617          CASE ( 'rad_lw_hr' )
9618             IF ( ALLOCATED( rad_lw_hr_av ) ) THEN
9619                DO  i = nxlg, nxrg
9620                   DO  j = nysg, nyng
9621                      DO  k = nzb, nzt+1
9622                         rad_lw_hr_av(k,j,i) = rad_lw_hr_av(k,j,i)             &
9623                                               / REAL( average_count_3d, KIND=wp )
9624                      ENDDO
9625                   ENDDO
9626                ENDDO
9627             ENDIF
9628
9629          CASE ( 'rad_sw_in' )
9630             IF ( ALLOCATED( rad_sw_in_av ) ) THEN
9631                DO  i = nxlg, nxrg
9632                   DO  j = nysg, nyng
9633                      DO  k = nzb, nzt+1
9634                         rad_sw_in_av(k,j,i) = rad_sw_in_av(k,j,i)             &
9635                                               / REAL( average_count_3d, KIND=wp )
9636                      ENDDO
9637                   ENDDO
9638                ENDDO
9639             ENDIF
9640
9641          CASE ( 'rad_sw_out' )
9642             IF ( ALLOCATED( rad_sw_out_av ) ) THEN
9643                DO  i = nxlg, nxrg
9644                   DO  j = nysg, nyng
9645                      DO  k = nzb, nzt+1
9646                         rad_sw_out_av(k,j,i) = rad_sw_out_av(k,j,i)           &
9647                                                / REAL( average_count_3d, KIND=wp )
9648                      ENDDO
9649                   ENDDO
9650                ENDDO
9651             ENDIF
9652
9653          CASE ( 'rad_sw_cs_hr' )
9654             IF ( ALLOCATED( rad_sw_cs_hr_av ) ) THEN
9655                DO  i = nxlg, nxrg
9656                   DO  j = nysg, nyng
9657                      DO  k = nzb, nzt+1
9658                         rad_sw_cs_hr_av(k,j,i) = rad_sw_cs_hr_av(k,j,i)       &
9659                                                / REAL( average_count_3d, KIND=wp )
9660                      ENDDO
9661                   ENDDO
9662                ENDDO
9663             ENDIF
9664
9665          CASE ( 'rad_sw_hr' )
9666             IF ( ALLOCATED( rad_sw_hr_av ) ) THEN
9667                DO  i = nxlg, nxrg
9668                   DO  j = nysg, nyng
9669                      DO  k = nzb, nzt+1
9670                         rad_sw_hr_av(k,j,i) = rad_sw_hr_av(k,j,i)             &
9671                                               / REAL( average_count_3d, KIND=wp )
9672                      ENDDO
9673                   ENDDO
9674                ENDDO
9675             ENDIF
9676
9677!--       block of RTM output variables
9678          CASE ( 'rtm_rad_net' )
9679!--           array of complete radiation balance
9680              DO isurf = dirstart(ids), dirend(ids)
9681                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9682                      surfradnet_av(isurf) = surfinsw_av(isurf) / REAL( average_count_3d, kind=wp )
9683                  ENDIF
9684              ENDDO
9685
9686          CASE ( 'rtm_rad_insw' )
9687!--           array of sw radiation falling to surface after i-th reflection
9688              DO isurf = dirstart(ids), dirend(ids)
9689                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9690                      surfinsw_av(isurf) = surfinsw_av(isurf) / REAL( average_count_3d, kind=wp )
9691                  ENDIF
9692              ENDDO
9693
9694          CASE ( 'rtm_rad_inlw' )
9695!--           array of lw radiation falling to surface after i-th reflection
9696              DO isurf = dirstart(ids), dirend(ids)
9697                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9698                      surfinlw_av(isurf) = surfinlw_av(isurf) / REAL( average_count_3d, kind=wp )
9699                  ENDIF
9700              ENDDO
9701
9702          CASE ( 'rtm_rad_inswdir' )
9703!--           array of direct sw radiation falling to surface from sun
9704              DO isurf = dirstart(ids), dirend(ids)
9705                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9706                      surfinswdir_av(isurf) = surfinswdir_av(isurf) / REAL( average_count_3d, kind=wp )
9707                  ENDIF
9708              ENDDO
9709
9710          CASE ( 'rtm_rad_inswdif' )
9711!--           array of difusion sw radiation falling to surface from sky and borders of the domain
9712              DO isurf = dirstart(ids), dirend(ids)
9713                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9714                      surfinswdif_av(isurf) = surfinswdif_av(isurf) / REAL( average_count_3d, kind=wp )
9715                  ENDIF
9716              ENDDO
9717
9718          CASE ( 'rtm_rad_inswref' )
9719!--           array of sw radiation falling to surface from reflections
9720              DO isurf = dirstart(ids), dirend(ids)
9721                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9722                      surfinswref_av(isurf) = surfinswref_av(isurf) / REAL( average_count_3d, kind=wp )
9723                  ENDIF
9724              ENDDO
9725
9726          CASE ( 'rtm_rad_inlwdif' )
9727!--           array of sw radiation falling to surface after i-th reflection
9728              DO isurf = dirstart(ids), dirend(ids)
9729                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9730                      surfinlwdif_av(isurf) = surfinlwdif_av(isurf) / REAL( average_count_3d, kind=wp )
9731                  ENDIF
9732              ENDDO
9733
9734          CASE ( 'rtm_rad_inlwref' )
9735!--           array of lw radiation falling to surface from reflections
9736              DO isurf = dirstart(ids), dirend(ids)
9737                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9738                      surfinlwref_av(isurf) = surfinlwref_av(isurf) / REAL( average_count_3d, kind=wp )
9739                  ENDIF
9740              ENDDO
9741
9742          CASE ( 'rtm_rad_outsw' )
9743!--           array of sw radiation emitted from surface after i-th reflection
9744              DO isurf = dirstart(ids), dirend(ids)
9745                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9746                      surfoutsw_av(isurf) = surfoutsw_av(isurf) / REAL( average_count_3d, kind=wp )
9747                  ENDIF
9748              ENDDO
9749
9750          CASE ( 'rtm_rad_outlw' )
9751!--           array of lw radiation emitted from surface after i-th reflection
9752              DO isurf = dirstart(ids), dirend(ids)
9753                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9754                      surfoutlw_av(isurf) = surfoutlw_av(isurf) / REAL( average_count_3d, kind=wp )
9755                  ENDIF
9756              ENDDO
9757
9758          CASE ( 'rtm_rad_ressw' )
9759!--           array of residua of sw radiation absorbed in surface after last reflection
9760              DO isurf = dirstart(ids), dirend(ids)
9761                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9762                      surfins_av(isurf) = surfins_av(isurf) / REAL( average_count_3d, kind=wp )
9763                  ENDIF
9764              ENDDO
9765
9766          CASE ( 'rtm_rad_reslw' )
9767!--           array of residua of lw radiation absorbed in surface after last reflection
9768              DO isurf = dirstart(ids), dirend(ids)
9769                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9770                      surfinl_av(isurf) = surfinl_av(isurf) / REAL( average_count_3d, kind=wp )
9771                  ENDIF
9772              ENDDO
9773
9774          CASE ( 'rtm_rad_pc_inlw' )
9775              DO l = 1, npcbl
9776                 pcbinlw_av(:) = pcbinlw_av(:) / REAL( average_count_3d, kind=wp )
9777              ENDDO
9778
9779          CASE ( 'rtm_rad_pc_insw' )
9780              DO l = 1, npcbl
9781                 pcbinsw_av(:) = pcbinsw_av(:) / REAL( average_count_3d, kind=wp )
9782              ENDDO
9783
9784          CASE ( 'rtm_rad_pc_inswdir' )
9785              DO l = 1, npcbl
9786                 pcbinswdir_av(:) = pcbinswdir_av(:) / REAL( average_count_3d, kind=wp )
9787              ENDDO
9788
9789          CASE ( 'rtm_rad_pc_inswdif' )
9790              DO l = 1, npcbl
9791                 pcbinswdif_av(:) = pcbinswdif_av(:) / REAL( average_count_3d, kind=wp )
9792              ENDDO
9793
9794          CASE ( 'rtm_rad_pc_inswref' )
9795              DO l = 1, npcbl
9796                 pcbinswref_av(:) = pcbinswref_av(:) / REAL( average_count_3d, kind=wp )
9797              ENDDO
9798
9799          CASE ( 'rad_mrt_lw' )
9800             IF ( ALLOCATED( mrtinlw_av ) )  THEN
9801                mrtinlw_av(:) = mrtinlw_av(:) / REAL( average_count_3d, KIND=wp )
9802             ENDIF
9803
9804          CASE ( 'rad_mrt' )
9805             IF ( ALLOCATED( mrt_av ) )  THEN
9806                mrt_av(:) = mrt_av(:) / REAL( average_count_3d, KIND=wp )
9807             ENDIF
9808
9809       END SELECT
9810
9811    ENDIF
9812
9813END SUBROUTINE radiation_3d_data_averaging
9814
9815
9816!------------------------------------------------------------------------------!
9817!
9818! Description:
9819! ------------
9820!> Subroutine defining appropriate grid for netcdf variables.
9821!> It is called out from subroutine netcdf.
9822!------------------------------------------------------------------------------!
9823SUBROUTINE radiation_define_netcdf_grid( variable, found, grid_x, grid_y, grid_z )
9824   
9825    IMPLICIT NONE
9826
9827    CHARACTER (LEN=*), INTENT(IN)  ::  variable    !<
9828    LOGICAL, INTENT(OUT)           ::  found       !<
9829    CHARACTER (LEN=*), INTENT(OUT) ::  grid_x      !<
9830    CHARACTER (LEN=*), INTENT(OUT) ::  grid_y      !<
9831    CHARACTER (LEN=*), INTENT(OUT) ::  grid_z      !<
9832
9833    CHARACTER (len=varnamelength)  :: var
9834
9835    found  = .TRUE.
9836
9837!
9838!-- Check for the grid
9839    var = TRIM(variable)
9840!-- RTM directional variables
9841    IF ( var(1:12) == 'rtm_rad_net_'  .OR.  var(1:13) == 'rtm_rad_insw_'  .OR.          &
9842         var(1:13) == 'rtm_rad_inlw_'  .OR.  var(1:16) == 'rtm_rad_inswdir_'  .OR.      &
9843         var(1:16) == 'rtm_rad_inswdif_'  .OR.  var(1:16) == 'rtm_rad_inswref_'  .OR.   &
9844         var(1:16) == 'rtm_rad_inlwdif_'  .OR.  var(1:16) == 'rtm_rad_inlwref_'  .OR.   &
9845         var(1:14) == 'rtm_rad_outsw_'  .OR.  var(1:14) == 'rtm_rad_outlw_'  .OR.       &
9846         var(1:14) == 'rtm_rad_ressw_'  .OR.  var(1:14) == 'rtm_rad_reslw_'  .OR.       &
9847         var == 'rtm_rad_pc_inlw'  .OR.                                                 &
9848         var == 'rtm_rad_pc_insw'  .OR.  var == 'rtm_rad_pc_inswdir'  .OR.              &
9849         var == 'rtm_rad_pc_inswdif'  .OR.  var == 'rtm_rad_pc_inswref'  .OR.           &
9850         var(1:7) == 'rtm_svf'  .OR.  var(1:7) == 'rtm_dif'  .OR.                       &
9851         var(1:9) == 'rtm_skyvf' .OR. var(1:10) == 'rtm_skyvft'  .OR.                   &
9852         var == 'rtm_mrt'  .OR.  var ==  'rtm_mrt_sw'  .OR.  var == 'rtm_mrt_lw' )  THEN
9853
9854         found = .TRUE.
9855         grid_x = 'x'
9856         grid_y = 'y'
9857         grid_z = 'zu'
9858    ELSE
9859
9860       SELECT CASE ( TRIM( var ) )
9861
9862          CASE ( 'rad_lw_cs_hr', 'rad_lw_hr', 'rad_sw_cs_hr', 'rad_sw_hr',        &
9863                 'rad_lw_cs_hr_xy', 'rad_lw_hr_xy', 'rad_sw_cs_hr_xy',            &
9864                 'rad_sw_hr_xy', 'rad_lw_cs_hr_xz', 'rad_lw_hr_xz',               &
9865                 'rad_sw_cs_hr_xz', 'rad_sw_hr_xz', 'rad_lw_cs_hr_yz',            &
9866                 'rad_lw_hr_yz', 'rad_sw_cs_hr_yz', 'rad_sw_hr_yz',               &
9867                 'rad_mrt', 'rad_mrt_sw', 'rad_mrt_lw' )
9868             grid_x = 'x'
9869             grid_y = 'y'
9870             grid_z = 'zu'
9871
9872          CASE ( 'rad_lw_in', 'rad_lw_out', 'rad_sw_in', 'rad_sw_out',            &
9873                 'rad_lw_in_xy', 'rad_lw_out_xy', 'rad_sw_in_xy','rad_sw_out_xy', &
9874                 'rad_lw_in_xz', 'rad_lw_out_xz', 'rad_sw_in_xz','rad_sw_out_xz', &
9875                 'rad_lw_in_yz', 'rad_lw_out_yz', 'rad_sw_in_yz','rad_sw_out_yz' )
9876             grid_x = 'x'
9877             grid_y = 'y'
9878             grid_z = 'zw'
9879
9880
9881          CASE DEFAULT
9882             found  = .FALSE.
9883             grid_x = 'none'
9884             grid_y = 'none'
9885             grid_z = 'none'
9886
9887           END SELECT
9888       ENDIF
9889
9890    END SUBROUTINE radiation_define_netcdf_grid
9891
9892!------------------------------------------------------------------------------!
9893!
9894! Description:
9895! ------------
9896!> Subroutine defining 2D output variables
9897!------------------------------------------------------------------------------!
9898 SUBROUTINE radiation_data_output_2d( av, variable, found, grid, mode,         &
9899                                      local_pf, two_d, nzb_do, nzt_do )
9900 
9901    USE indices
9902
9903    USE kinds
9904
9905
9906    IMPLICIT NONE
9907
9908    CHARACTER (LEN=*) ::  grid     !<
9909    CHARACTER (LEN=*) ::  mode     !<
9910    CHARACTER (LEN=*) ::  variable !<
9911
9912    INTEGER(iwp) ::  av !<
9913    INTEGER(iwp) ::  i  !<
9914    INTEGER(iwp) ::  j  !<
9915    INTEGER(iwp) ::  k  !<
9916    INTEGER(iwp) ::  m  !< index of surface element at grid point (j,i)
9917    INTEGER(iwp) ::  nzb_do   !<
9918    INTEGER(iwp) ::  nzt_do   !<
9919
9920    LOGICAL      ::  found !<
9921    LOGICAL      ::  two_d !< flag parameter that indicates 2D variables (horizontal cross sections)
9922
9923    REAL(wp) ::  fill_value = -999.0_wp    !< value for the _FillValue attribute
9924
9925    REAL(wp), DIMENSION(nxl:nxr,nys:nyn,nzb_do:nzt_do) ::  local_pf !<
9926
9927    found = .TRUE.
9928
9929    SELECT CASE ( TRIM( variable ) )
9930
9931       CASE ( 'rad_net*_xy' )        ! 2d-array
9932          IF ( av == 0 ) THEN
9933             DO  i = nxl, nxr
9934                DO  j = nys, nyn
9935!
9936!--                Obtain rad_net from its respective surface type
9937!--                Natural-type surfaces
9938                   DO  m = surf_lsm_h%start_index(j,i),                        &
9939                           surf_lsm_h%end_index(j,i) 
9940                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_net(m)
9941                   ENDDO
9942!
9943!--                Urban-type surfaces
9944                   DO  m = surf_usm_h%start_index(j,i),                        &
9945                           surf_usm_h%end_index(j,i) 
9946                      local_pf(i,j,nzb+1) = surf_usm_h%rad_net(m)
9947                   ENDDO
9948                ENDDO
9949             ENDDO
9950          ELSE
9951             IF ( .NOT. ALLOCATED( rad_net_av ) ) THEN
9952                ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
9953                rad_net_av = REAL( fill_value, KIND = wp )
9954             ENDIF
9955             DO  i = nxl, nxr
9956                DO  j = nys, nyn 
9957                   local_pf(i,j,nzb+1) = rad_net_av(j,i)
9958                ENDDO
9959             ENDDO
9960          ENDIF
9961          two_d = .TRUE.
9962          grid = 'zu1'
9963         
9964       CASE ( 'rad_lw_in*_xy' )        ! 2d-array
9965          IF ( av == 0 ) THEN
9966             DO  i = nxl, nxr
9967                DO  j = nys, nyn
9968!
9969!--                Obtain rad_net from its respective surface type
9970!--                Natural-type surfaces
9971                   DO  m = surf_lsm_h%start_index(j,i),                        &
9972                           surf_lsm_h%end_index(j,i) 
9973                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_lw_in(m)
9974                   ENDDO
9975!
9976!--                Urban-type surfaces
9977                   DO  m = surf_usm_h%start_index(j,i),                        &
9978                           surf_usm_h%end_index(j,i) 
9979                      local_pf(i,j,nzb+1) = surf_usm_h%rad_lw_in(m)
9980                   ENDDO
9981                ENDDO
9982             ENDDO
9983          ELSE
9984             IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) ) THEN
9985                ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
9986                rad_lw_in_xy_av = REAL( fill_value, KIND = wp )
9987             ENDIF
9988             DO  i = nxl, nxr
9989                DO  j = nys, nyn 
9990                   local_pf(i,j,nzb+1) = rad_lw_in_xy_av(j,i)
9991                ENDDO
9992             ENDDO
9993          ENDIF
9994          two_d = .TRUE.
9995          grid = 'zu1'
9996         
9997       CASE ( 'rad_lw_out*_xy' )        ! 2d-array
9998          IF ( av == 0 ) THEN
9999             DO  i = nxl, nxr
10000                DO  j = nys, nyn
10001!
10002!--                Obtain rad_net from its respective surface type
10003!--                Natural-type surfaces
10004                   DO  m = surf_lsm_h%start_index(j,i),                        &
10005                           surf_lsm_h%end_index(j,i) 
10006                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_lw_out(m)
10007                   ENDDO
10008!
10009!--                Urban-type surfaces
10010                   DO  m = surf_usm_h%start_index(j,i),                        &
10011                           surf_usm_h%end_index(j,i) 
10012                      local_pf(i,j,nzb+1) = surf_usm_h%rad_lw_out(m)
10013                   ENDDO
10014                ENDDO
10015             ENDDO
10016          ELSE
10017             IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) ) THEN
10018                ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
10019                rad_lw_out_xy_av = REAL( fill_value, KIND = wp )
10020             ENDIF
10021             DO  i = nxl, nxr
10022                DO  j = nys, nyn 
10023                   local_pf(i,j,nzb+1) = rad_lw_out_xy_av(j,i)
10024                ENDDO
10025             ENDDO
10026          ENDIF
10027          two_d = .TRUE.
10028          grid = 'zu1'
10029         
10030       CASE ( 'rad_sw_in*_xy' )        ! 2d-array
10031          IF ( av == 0 ) THEN
10032             DO  i = nxl, nxr
10033                DO  j = nys, nyn
10034!
10035!--                Obtain rad_net from its respective surface type
10036!--                Natural-type surfaces
10037                   DO  m = surf_lsm_h%start_index(j,i),                        &
10038                           surf_lsm_h%end_index(j,i) 
10039                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_sw_in(m)
10040                   ENDDO
10041!
10042!--                Urban-type surfaces
10043                   DO  m = surf_usm_h%start_index(j,i),                        &
10044                           surf_usm_h%end_index(j,i) 
10045                      local_pf(i,j,nzb+1) = surf_usm_h%rad_sw_in(m)
10046                   ENDDO
10047                ENDDO
10048             ENDDO
10049          ELSE
10050             IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) ) THEN
10051                ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
10052                rad_sw_in_xy_av = REAL( fill_value, KIND = wp )
10053             ENDIF
10054             DO  i = nxl, nxr
10055                DO  j = nys, nyn 
10056                   local_pf(i,j,nzb+1) = rad_sw_in_xy_av(j,i)
10057                ENDDO
10058             ENDDO
10059          ENDIF
10060          two_d = .TRUE.
10061          grid = 'zu1'
10062         
10063       CASE ( 'rad_sw_out*_xy' )        ! 2d-array
10064          IF ( av == 0 ) THEN
10065             DO  i = nxl, nxr
10066                DO  j = nys, nyn
10067!
10068!--                Obtain rad_net from its respective surface type
10069!--                Natural-type surfaces
10070                   DO  m = surf_lsm_h%start_index(j,i),                        &
10071                           surf_lsm_h%end_index(j,i) 
10072                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_sw_out(m)
10073                   ENDDO
10074!
10075!--                Urban-type surfaces
10076                   DO  m = surf_usm_h%start_index(j,i),                        &
10077                           surf_usm_h%end_index(j,i) 
10078                      local_pf(i,j,nzb+1) = surf_usm_h%rad_sw_out(m)
10079                   ENDDO
10080                ENDDO
10081             ENDDO
10082          ELSE
10083             IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) ) THEN
10084                ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
10085                rad_sw_out_xy_av = REAL( fill_value, KIND = wp )
10086             ENDIF
10087             DO  i = nxl, nxr
10088                DO  j = nys, nyn 
10089                   local_pf(i,j,nzb+1) = rad_sw_out_xy_av(j,i)
10090                ENDDO
10091             ENDDO
10092          ENDIF
10093          two_d = .TRUE.
10094          grid = 'zu1'         
10095         
10096       CASE ( 'rad_lw_in_xy', 'rad_lw_in_xz', 'rad_lw_in_yz' )
10097          IF ( av == 0 ) THEN
10098             DO  i = nxl, nxr
10099                DO  j = nys, nyn
10100                   DO  k = nzb_do, nzt_do
10101                      local_pf(i,j,k) = rad_lw_in(k,j,i)
10102                   ENDDO
10103                ENDDO
10104             ENDDO
10105          ELSE
10106            IF ( .NOT. ALLOCATED( rad_lw_in_av ) ) THEN
10107               ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10108               rad_lw_in_av = REAL( fill_value, KIND = wp )
10109            ENDIF
10110             DO  i = nxl, nxr
10111                DO  j = nys, nyn 
10112                   DO  k = nzb_do, nzt_do
10113                      local_pf(i,j,k) = rad_lw_in_av(k,j,i)
10114                   ENDDO
10115                ENDDO
10116             ENDDO
10117          ENDIF
10118          IF ( mode == 'xy' )  grid = 'zu'
10119
10120       CASE ( 'rad_lw_out_xy', 'rad_lw_out_xz', 'rad_lw_out_yz' )
10121          IF ( av == 0 ) THEN
10122             DO  i = nxl, nxr
10123                DO  j = nys, nyn
10124                   DO  k = nzb_do, nzt_do
10125                      local_pf(i,j,k) = rad_lw_out(k,j,i)
10126                   ENDDO
10127                ENDDO
10128             ENDDO
10129          ELSE
10130            IF ( .NOT. ALLOCATED( rad_lw_out_av ) ) THEN
10131               ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10132               rad_lw_out_av = REAL( fill_value, KIND = wp )
10133            ENDIF
10134             DO  i = nxl, nxr
10135                DO  j = nys, nyn 
10136                   DO  k = nzb_do, nzt_do
10137                      local_pf(i,j,k) = rad_lw_out_av(k,j,i)
10138                   ENDDO
10139                ENDDO
10140             ENDDO
10141          ENDIF   
10142          IF ( mode == 'xy' )  grid = 'zu'
10143
10144       CASE ( 'rad_lw_cs_hr_xy', 'rad_lw_cs_hr_xz', 'rad_lw_cs_hr_yz' )
10145          IF ( av == 0 ) THEN
10146             DO  i = nxl, nxr
10147                DO  j = nys, nyn
10148                   DO  k = nzb_do, nzt_do
10149                      local_pf(i,j,k) = rad_lw_cs_hr(k,j,i)
10150                   ENDDO
10151                ENDDO
10152             ENDDO
10153          ELSE
10154            IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) ) THEN
10155               ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10156               rad_lw_cs_hr_av = REAL( fill_value, KIND = wp )
10157            ENDIF
10158             DO  i = nxl, nxr
10159                DO  j = nys, nyn 
10160                   DO  k = nzb_do, nzt_do
10161                      local_pf(i,j,k) = rad_lw_cs_hr_av(k,j,i)
10162                   ENDDO
10163                ENDDO
10164             ENDDO
10165          ENDIF
10166          IF ( mode == 'xy' )  grid = 'zw'
10167
10168       CASE ( 'rad_lw_hr_xy', 'rad_lw_hr_xz', 'rad_lw_hr_yz' )
10169          IF ( av == 0 ) THEN
10170             DO  i = nxl, nxr
10171                DO  j = nys, nyn
10172                   DO  k = nzb_do, nzt_do
10173                      local_pf(i,j,k) = rad_lw_hr(k,j,i)
10174                   ENDDO
10175                ENDDO
10176             ENDDO
10177          ELSE
10178            IF ( .NOT. ALLOCATED( rad_lw_hr_av ) ) THEN
10179               ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10180               rad_lw_hr_av= REAL( fill_value, KIND = wp )
10181            ENDIF
10182             DO  i = nxl, nxr
10183                DO  j = nys, nyn 
10184                   DO  k = nzb_do, nzt_do
10185                      local_pf(i,j,k) = rad_lw_hr_av(k,j,i)
10186                   ENDDO
10187                ENDDO
10188             ENDDO
10189          ENDIF
10190          IF ( mode == 'xy' )  grid = 'zw'
10191
10192       CASE ( 'rad_sw_in_xy', 'rad_sw_in_xz', 'rad_sw_in_yz' )
10193          IF ( av == 0 ) THEN
10194             DO  i = nxl, nxr
10195                DO  j = nys, nyn
10196                   DO  k = nzb_do, nzt_do
10197                      local_pf(i,j,k) = rad_sw_in(k,j,i)
10198                   ENDDO
10199                ENDDO
10200             ENDDO
10201          ELSE
10202            IF ( .NOT. ALLOCATED( rad_sw_in_av ) ) THEN
10203               ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10204               rad_sw_in_av = REAL( fill_value, KIND = wp )
10205            ENDIF
10206             DO  i = nxl, nxr
10207                DO  j = nys, nyn 
10208                   DO  k = nzb_do, nzt_do
10209                      local_pf(i,j,k) = rad_sw_in_av(k,j,i)
10210                   ENDDO
10211                ENDDO
10212             ENDDO
10213          ENDIF
10214          IF ( mode == 'xy' )  grid = 'zu'
10215
10216       CASE ( 'rad_sw_out_xy', 'rad_sw_out_xz', 'rad_sw_out_yz' )
10217          IF ( av == 0 ) THEN
10218             DO  i = nxl, nxr
10219                DO  j = nys, nyn
10220                   DO  k = nzb_do, nzt_do
10221                      local_pf(i,j,k) = rad_sw_out(k,j,i)
10222                   ENDDO
10223                ENDDO
10224             ENDDO
10225          ELSE
10226            IF ( .NOT. ALLOCATED( rad_sw_out_av ) ) THEN
10227               ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10228               rad_sw_out_av = REAL( fill_value, KIND = wp )
10229            ENDIF
10230             DO  i = nxl, nxr
10231                DO  j = nys, nyn 
10232                   DO  k = nzb, nzt+1
10233                      local_pf(i,j,k) = rad_sw_out_av(k,j,i)
10234                   ENDDO
10235                ENDDO
10236             ENDDO
10237          ENDIF
10238          IF ( mode == 'xy' )  grid = 'zu'
10239
10240       CASE ( 'rad_sw_cs_hr_xy', 'rad_sw_cs_hr_xz', 'rad_sw_cs_hr_yz' )
10241          IF ( av == 0 ) THEN
10242             DO  i = nxl, nxr
10243                DO  j = nys, nyn
10244                   DO  k = nzb_do, nzt_do
10245                      local_pf(i,j,k) = rad_sw_cs_hr(k,j,i)
10246                   ENDDO
10247                ENDDO
10248             ENDDO
10249          ELSE
10250            IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) ) THEN
10251               ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10252               rad_sw_cs_hr_av = REAL( fill_value, KIND = wp )
10253            ENDIF
10254             DO  i = nxl, nxr
10255                DO  j = nys, nyn 
10256                   DO  k = nzb_do, nzt_do
10257                      local_pf(i,j,k) = rad_sw_cs_hr_av(k,j,i)
10258                   ENDDO
10259                ENDDO
10260             ENDDO
10261          ENDIF
10262          IF ( mode == 'xy' )  grid = 'zw'
10263
10264       CASE ( 'rad_sw_hr_xy', 'rad_sw_hr_xz', 'rad_sw_hr_yz' )
10265          IF ( av == 0 ) THEN
10266             DO  i = nxl, nxr
10267                DO  j = nys, nyn
10268                   DO  k = nzb_do, nzt_do
10269                      local_pf(i,j,k) = rad_sw_hr(k,j,i)
10270                   ENDDO
10271                ENDDO
10272             ENDDO
10273          ELSE
10274            IF ( .NOT. ALLOCATED( rad_sw_hr_av ) ) THEN
10275               ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10276               rad_sw_hr_av = REAL( fill_value, KIND = wp )
10277            ENDIF
10278             DO  i = nxl, nxr
10279                DO  j = nys, nyn 
10280                   DO  k = nzb_do, nzt_do
10281                      local_pf(i,j,k) = rad_sw_hr_av(k,j,i)
10282                   ENDDO
10283                ENDDO
10284             ENDDO
10285          ENDIF
10286          IF ( mode == 'xy' )  grid = 'zw'
10287
10288       CASE DEFAULT
10289          found = .FALSE.
10290          grid  = 'none'
10291
10292    END SELECT
10293 
10294 END SUBROUTINE radiation_data_output_2d
10295
10296
10297!------------------------------------------------------------------------------!
10298!
10299! Description:
10300! ------------
10301!> Subroutine defining 3D output variables
10302!------------------------------------------------------------------------------!
10303 SUBROUTINE radiation_data_output_3d( av, variable, found, local_pf, nzb_do, nzt_do )
10304 
10305
10306    USE indices
10307
10308    USE kinds
10309
10310
10311    IMPLICIT NONE
10312
10313    CHARACTER (LEN=*) ::  variable !<
10314
10315    INTEGER(iwp) ::  av          !<
10316    INTEGER(iwp) ::  i, j, k, l  !<
10317    INTEGER(iwp) ::  nzb_do      !<
10318    INTEGER(iwp) ::  nzt_do      !<
10319
10320    LOGICAL      ::  found       !<
10321
10322    REAL(wp)     ::  fill_value = -999.0_wp    !< value for the _FillValue attribute
10323
10324    REAL(sp), DIMENSION(nxl:nxr,nys:nyn,nzb_do:nzt_do) ::  local_pf !<
10325
10326    CHARACTER (len=varnamelength)                   :: var, surfid
10327    INTEGER(iwp)                                    :: ids,idsint_u,idsint_l,isurf,isvf,isurfs,isurflt,ipcgb
10328    INTEGER(iwp)                                    :: is, js, ks, istat
10329
10330    found = .TRUE.
10331
10332    ids = -1
10333    var = TRIM(variable)
10334    DO i = 0, nd-1
10335        k = len(TRIM(var))
10336        j = len(TRIM(dirname(i)))
10337        IF ( TRIM(var(k-j+1:k)) == TRIM(dirname(i)) )  THEN
10338            ids = i
10339            idsint_u = dirint_u(ids)
10340            idsint_l = dirint_l(ids)
10341            var = var(:k-j)
10342            EXIT
10343        ENDIF
10344    ENDDO
10345    IF ( ids == -1 )  THEN
10346        var = TRIM(variable)
10347    ENDIF
10348
10349    IF ( (var(1:8) == 'rtm_svf_'  .OR.  var(1:8) == 'rtm_dif_')  .AND.  len(TRIM(var)) >= 13 )  THEN
10350!--     svf values to particular surface
10351        surfid = var(9:)
10352        i = index(surfid,'_')
10353        j = index(surfid(i+1:),'_')
10354        READ(surfid(1:i-1),*, iostat=istat ) is
10355        IF ( istat == 0 )  THEN
10356            READ(surfid(i+1:i+j-1),*, iostat=istat ) js
10357        ENDIF
10358        IF ( istat == 0 )  THEN
10359            READ(surfid(i+j+1:),*, iostat=istat ) ks
10360        ENDIF
10361        IF ( istat == 0 )  THEN
10362            var = var(1:7)
10363        ENDIF
10364    ENDIF
10365
10366    local_pf = fill_value
10367
10368    SELECT CASE ( TRIM( var ) )
10369!--   block of large scale radiation model (e.g. RRTMG) output variables
10370      CASE ( 'rad_sw_in' )
10371         IF ( av == 0 )  THEN
10372            DO  i = nxl, nxr
10373               DO  j = nys, nyn
10374                  DO  k = nzb_do, nzt_do
10375                     local_pf(i,j,k) = rad_sw_in(k,j,i)
10376                  ENDDO
10377               ENDDO
10378            ENDDO
10379         ELSE
10380            IF ( .NOT. ALLOCATED( rad_sw_in_av ) ) THEN
10381               ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10382               rad_sw_in_av = REAL( fill_value, KIND = wp )
10383            ENDIF
10384            DO  i = nxl, nxr
10385               DO  j = nys, nyn
10386                  DO  k = nzb_do, nzt_do
10387                     local_pf(i,j,k) = rad_sw_in_av(k,j,i)
10388                  ENDDO
10389               ENDDO
10390            ENDDO
10391         ENDIF
10392
10393      CASE ( 'rad_sw_out' )
10394         IF ( av == 0 )  THEN
10395            DO  i = nxl, nxr
10396               DO  j = nys, nyn
10397                  DO  k = nzb_do, nzt_do
10398                     local_pf(i,j,k) = rad_sw_out(k,j,i)
10399                  ENDDO
10400               ENDDO
10401            ENDDO
10402         ELSE
10403            IF ( .NOT. ALLOCATED( rad_sw_out_av ) ) THEN
10404               ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10405               rad_sw_out_av = REAL( fill_value, KIND = wp )
10406            ENDIF
10407            DO  i = nxl, nxr
10408               DO  j = nys, nyn
10409                  DO  k = nzb_do, nzt_do
10410                     local_pf(i,j,k) = rad_sw_out_av(k,j,i)
10411                  ENDDO
10412               ENDDO
10413            ENDDO
10414         ENDIF
10415
10416      CASE ( 'rad_sw_cs_hr' )
10417         IF ( av == 0 )  THEN
10418            DO  i = nxl, nxr
10419               DO  j = nys, nyn
10420                  DO  k = nzb_do, nzt_do
10421                     local_pf(i,j,k) = rad_sw_cs_hr(k,j,i)
10422                  ENDDO
10423               ENDDO
10424            ENDDO
10425         ELSE
10426            IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) ) THEN
10427               ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10428               rad_sw_cs_hr_av = REAL( fill_value, KIND = wp )
10429            ENDIF
10430            DO  i = nxl, nxr
10431               DO  j = nys, nyn
10432                  DO  k = nzb_do, nzt_do
10433                     local_pf(i,j,k) = rad_sw_cs_hr_av(k,j,i)
10434                  ENDDO
10435               ENDDO
10436            ENDDO
10437         ENDIF
10438
10439      CASE ( 'rad_sw_hr' )
10440         IF ( av == 0 )  THEN
10441            DO  i = nxl, nxr
10442               DO  j = nys, nyn
10443                  DO  k = nzb_do, nzt_do
10444                     local_pf(i,j,k) = rad_sw_hr(k,j,i)
10445                  ENDDO
10446               ENDDO
10447            ENDDO
10448         ELSE
10449            IF ( .NOT. ALLOCATED( rad_sw_hr_av ) ) THEN
10450               ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10451               rad_sw_hr_av = REAL( fill_value, KIND = wp )
10452            ENDIF
10453            DO  i = nxl, nxr
10454               DO  j = nys, nyn
10455                  DO  k = nzb_do, nzt_do
10456                     local_pf(i,j,k) = rad_sw_hr_av(k,j,i)
10457                  ENDDO
10458               ENDDO
10459            ENDDO
10460         ENDIF
10461
10462      CASE ( 'rad_lw_in' )
10463         IF ( av == 0 )  THEN
10464            DO  i = nxl, nxr
10465               DO  j = nys, nyn
10466                  DO  k = nzb_do, nzt_do
10467                     local_pf(i,j,k) = rad_lw_in(k,j,i)
10468                  ENDDO
10469               ENDDO
10470            ENDDO
10471         ELSE
10472            IF ( .NOT. ALLOCATED( rad_lw_in_av ) ) THEN
10473               ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10474               rad_lw_in_av = REAL( fill_value, KIND = wp )
10475            ENDIF
10476            DO  i = nxl, nxr
10477               DO  j = nys, nyn
10478                  DO  k = nzb_do, nzt_do
10479                     local_pf(i,j,k) = rad_lw_in_av(k,j,i)
10480                  ENDDO
10481               ENDDO
10482            ENDDO
10483         ENDIF
10484
10485      CASE ( 'rad_lw_out' )
10486         IF ( av == 0 )  THEN
10487            DO  i = nxl, nxr
10488               DO  j = nys, nyn
10489                  DO  k = nzb_do, nzt_do
10490                     local_pf(i,j,k) = rad_lw_out(k,j,i)
10491                  ENDDO
10492               ENDDO
10493            ENDDO
10494         ELSE
10495            IF ( .NOT. ALLOCATED( rad_lw_out_av ) ) THEN
10496               ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10497               rad_lw_out_av = REAL( fill_value, KIND = wp )
10498            ENDIF
10499            DO  i = nxl, nxr
10500               DO  j = nys, nyn
10501                  DO  k = nzb_do, nzt_do
10502                     local_pf(i,j,k) = rad_lw_out_av(k,j,i)
10503                  ENDDO
10504               ENDDO
10505            ENDDO
10506         ENDIF
10507
10508      CASE ( 'rad_lw_cs_hr' )
10509         IF ( av == 0 )  THEN
10510            DO  i = nxl, nxr
10511               DO  j = nys, nyn
10512                  DO  k = nzb_do, nzt_do
10513                     local_pf(i,j,k) = rad_lw_cs_hr(k,j,i)
10514                  ENDDO
10515               ENDDO
10516            ENDDO
10517         ELSE
10518            IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) ) THEN
10519               ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10520               rad_lw_cs_hr_av = REAL( fill_value, KIND = wp )
10521            ENDIF
10522            DO  i = nxl, nxr
10523               DO  j = nys, nyn
10524                  DO  k = nzb_do, nzt_do
10525                     local_pf(i,j,k) = rad_lw_cs_hr_av(k,j,i)
10526                  ENDDO
10527               ENDDO
10528            ENDDO
10529         ENDIF
10530
10531      CASE ( 'rad_lw_hr' )
10532         IF ( av == 0 )  THEN
10533            DO  i = nxl, nxr
10534               DO  j = nys, nyn
10535                  DO  k = nzb_do, nzt_do
10536                     local_pf(i,j,k) = rad_lw_hr(k,j,i)
10537                  ENDDO
10538               ENDDO
10539            ENDDO
10540         ELSE
10541            IF ( .NOT. ALLOCATED( rad_lw_hr_av ) ) THEN
10542               ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10543              rad_lw_hr_av = REAL( fill_value, KIND = wp )
10544            ENDIF
10545            DO  i = nxl, nxr
10546               DO  j = nys, nyn
10547                  DO  k = nzb_do, nzt_do
10548                     local_pf(i,j,k) = rad_lw_hr_av(k,j,i)
10549                  ENDDO
10550               ENDDO
10551            ENDDO
10552         ENDIF
10553
10554!--   block of RTM output variables
10555!--   variables are intended mainly for debugging and detailed analyse purposes
10556      CASE ( 'rtm_skyvf' )
10557!--        sky view factor
10558         DO isurf = dirstart(ids), dirend(ids)
10559            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10560               local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = skyvf(isurf)
10561            ENDIF
10562         ENDDO
10563
10564      CASE ( 'rtm_skyvft' )
10565!--      sky view factor
10566         DO isurf = dirstart(ids), dirend(ids)
10567            IF ( surfl(id,isurf) == ids )  THEN
10568               local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = skyvft(isurf)
10569            ENDIF
10570         ENDDO
10571
10572      CASE ( 'rtm_svf', 'rtm_dif' )
10573!--      shape view factors or iradiance factors to selected surface
10574         IF ( TRIM(var)=='rtm_svf' )  THEN
10575             k = 1
10576         ELSE
10577             k = 2
10578         ENDIF
10579         DO isvf = 1, nsvfl
10580            isurflt = svfsurf(1, isvf)
10581            isurfs = svfsurf(2, isvf)
10582
10583            IF ( surf(ix,isurfs) == is  .AND.  surf(iy,isurfs) == js  .AND. surf(iz,isurfs) == ks  .AND. &
10584                 (surf(id,isurfs) == idsint_u .OR. surfl(id,isurfs) == idsint_l ) ) THEN
10585!--            correct source surface
10586               local_pf(surfl(ix,isurflt),surfl(iy,isurflt),surfl(iz,isurflt)) = svf(k,isvf)
10587            ENDIF
10588         ENDDO
10589
10590      CASE ( 'rtm_rad_net' )
10591!--     array of complete radiation balance
10592         DO isurf = dirstart(ids), dirend(ids)
10593            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10594               IF ( av == 0 )  THEN
10595                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = &
10596                         surfinsw(isurf) - surfoutsw(isurf) +  surfinlw(isurf) - surfoutlw(isurf)
10597               ELSE
10598                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfradnet_av(isurf)
10599               ENDIF
10600            ENDIF
10601         ENDDO
10602
10603      CASE ( 'rtm_rad_insw' )
10604!--      array of sw radiation falling to surface after i-th reflection
10605         DO isurf = dirstart(ids), dirend(ids)
10606            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10607               IF ( av == 0 )  THEN
10608                 local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinsw(isurf)
10609               ELSE
10610                 local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinsw_av(isurf)
10611               ENDIF
10612            ENDIF
10613         ENDDO
10614
10615      CASE ( 'rtm_rad_inlw' )
10616!--      array of lw radiation falling to surface after i-th reflection
10617         DO isurf = dirstart(ids), dirend(ids)
10618            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10619               IF ( av == 0 )  THEN
10620                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlw(isurf)
10621               ELSE
10622                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlw_av(isurf)
10623               ENDIF
10624             ENDIF
10625         ENDDO
10626
10627      CASE ( 'rtm_rad_inswdir' )
10628!--      array of direct sw radiation falling to surface from sun
10629         DO isurf = dirstart(ids), dirend(ids)
10630            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10631               IF ( av == 0 )  THEN
10632                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdir(isurf)
10633               ELSE
10634                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdir_av(isurf)
10635               ENDIF
10636            ENDIF
10637         ENDDO
10638
10639      CASE ( 'rtm_rad_inswdif' )
10640!--      array of difusion sw radiation falling to surface from sky and borders of the domain
10641         DO isurf = dirstart(ids), dirend(ids)
10642            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10643               IF ( av == 0 )  THEN
10644                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdif(isurf)
10645               ELSE
10646                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdif_av(isurf)
10647               ENDIF
10648            ENDIF
10649         ENDDO
10650
10651      CASE ( 'rtm_rad_inswref' )
10652!--      array of sw radiation falling to surface from reflections
10653         DO isurf = dirstart(ids), dirend(ids)
10654            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10655               IF ( av == 0 )  THEN
10656                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = &
10657                    surfinsw(isurf) - surfinswdir(isurf) - surfinswdif(isurf)
10658               ELSE
10659                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswref_av(isurf)
10660               ENDIF
10661            ENDIF
10662         ENDDO
10663
10664      CASE ( 'rtm_rad_inlwdif' )
10665!--      array of difusion lw radiation falling to surface from sky and borders of the domain
10666         DO isurf = dirstart(ids), dirend(ids)
10667            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10668               IF ( av == 0 )  THEN
10669                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlwdif(isurf)
10670               ELSE
10671                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlwdif_av(isurf)
10672               ENDIF
10673            ENDIF
10674         ENDDO
10675
10676      CASE ( 'rtm_rad_inlwref' )
10677!--      array of lw radiation falling to surface from reflections
10678         DO isurf = dirstart(ids), dirend(ids)
10679            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10680               IF ( av == 0 )  THEN
10681                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlw(isurf) - surfinlwdif(isurf)
10682               ELSE
10683                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlwref_av(isurf)
10684               ENDIF
10685            ENDIF
10686         ENDDO
10687
10688      CASE ( 'rtm_rad_outsw' )
10689!--      array of sw radiation emitted from surface after i-th reflection
10690         DO isurf = dirstart(ids), dirend(ids)
10691            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10692               IF ( av == 0 )  THEN
10693                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutsw(isurf)
10694               ELSE
10695                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutsw_av(isurf)
10696               ENDIF
10697            ENDIF
10698         ENDDO
10699
10700      CASE ( 'rtm_rad_outlw' )
10701!--      array of lw radiation emitted from surface after i-th reflection
10702         DO isurf = dirstart(ids), dirend(ids)
10703            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10704               IF ( av == 0 )  THEN
10705                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutlw(isurf)
10706               ELSE
10707                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutlw_av(isurf)
10708               ENDIF
10709            ENDIF
10710         ENDDO
10711
10712      CASE ( 'rtm_rad_ressw' )
10713!--      average of array of residua of sw radiation absorbed in surface after last reflection
10714         DO isurf = dirstart(ids), dirend(ids)
10715            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10716               IF ( av == 0 )  THEN
10717                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfins(isurf)
10718               ELSE
10719                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfins_av(isurf)
10720               ENDIF
10721            ENDIF
10722         ENDDO
10723
10724      CASE ( 'rtm_rad_reslw' )
10725!--      average of array of residua of lw radiation absorbed in surface after last reflection
10726         DO isurf = dirstart(ids), dirend(ids)
10727            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10728               IF ( av == 0 )  THEN
10729                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinl(isurf)
10730               ELSE
10731                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinl_av(isurf)
10732               ENDIF
10733            ENDIF
10734         ENDDO
10735
10736      CASE ( 'rtm_rad_pc_inlw' )
10737!--      array of lw radiation absorbed by plant canopy
10738         DO ipcgb = 1, npcbl
10739            IF ( av == 0 )  THEN
10740               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinlw(ipcgb)
10741            ELSE
10742               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinlw_av(ipcgb)
10743            ENDIF
10744         ENDDO
10745
10746      CASE ( 'rtm_rad_pc_insw' )
10747!--      array of sw radiation absorbed by plant canopy
10748         DO ipcgb = 1, npcbl
10749            IF ( av == 0 )  THEN
10750              local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinsw(ipcgb)
10751            ELSE
10752              local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinsw_av(ipcgb)
10753            ENDIF
10754         ENDDO
10755
10756      CASE ( 'rtm_rad_pc_inswdir' )
10757!--      array of direct sw radiation absorbed by plant canopy
10758         DO ipcgb = 1, npcbl
10759            IF ( av == 0 )  THEN
10760               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdir(ipcgb)
10761            ELSE
10762               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdir_av(ipcgb)
10763            ENDIF
10764         ENDDO
10765
10766      CASE ( 'rtm_rad_pc_inswdif' )
10767!--      array of diffuse sw radiation absorbed by plant canopy
10768         DO ipcgb = 1, npcbl
10769            IF ( av == 0 )  THEN
10770               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdif(ipcgb)
10771            ELSE
10772               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdif_av(ipcgb)
10773            ENDIF
10774         ENDDO
10775
10776      CASE ( 'rtm_rad_pc_inswref' )
10777!--      array of reflected sw radiation absorbed by plant canopy
10778         DO ipcgb = 1, npcbl
10779            IF ( av == 0 )  THEN
10780               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = &
10781                                    pcbinsw(ipcgb) - pcbinswdir(ipcgb) - pcbinswdif(ipcgb)
10782            ELSE
10783               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswref_av(ipcgb)
10784            ENDIF
10785         ENDDO
10786
10787      CASE ( 'rtm_mrt_sw' )
10788         local_pf = REAL( fill_value, KIND = wp )
10789         IF ( av == 0 )  THEN
10790            DO  l = 1, nmrtbl
10791               local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinsw(l)
10792            ENDDO
10793         ELSE
10794            IF ( ALLOCATED( mrtinsw_av ) ) THEN
10795               DO  l = 1, nmrtbl
10796                  local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinsw_av(l)
10797               ENDDO
10798            ENDIF
10799         ENDIF
10800
10801      CASE ( 'rtm_mrt_lw' )
10802         local_pf = REAL( fill_value, KIND = wp )
10803         IF ( av == 0 )  THEN
10804            DO  l = 1, nmrtbl
10805               local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinlw(l)
10806            ENDDO
10807         ELSE
10808            IF ( ALLOCATED( mrtinlw_av ) ) THEN
10809               DO  l = 1, nmrtbl
10810                  local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinlw_av(l)
10811               ENDDO
10812            ENDIF
10813         ENDIF
10814
10815      CASE ( 'rtm_mrt' )
10816         local_pf = REAL( fill_value, KIND = wp )
10817         IF ( av == 0 )  THEN
10818            DO  l = 1, nmrtbl
10819               local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrt(l)
10820            ENDDO
10821         ELSE
10822            IF ( ALLOCATED( mrt_av ) ) THEN
10823               DO  l = 1, nmrtbl
10824                  local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrt_av(l)
10825               ENDDO
10826            ENDIF
10827         ENDIF
10828
10829       CASE DEFAULT
10830          found = .FALSE.
10831
10832    END SELECT
10833
10834
10835 END SUBROUTINE radiation_data_output_3d
10836
10837!------------------------------------------------------------------------------!
10838!
10839! Description:
10840! ------------
10841!> Subroutine defining masked data output
10842!------------------------------------------------------------------------------!
10843 SUBROUTINE radiation_data_output_mask( av, variable, found, local_pf )
10844 
10845    USE control_parameters
10846       
10847    USE indices
10848   
10849    USE kinds
10850   
10851
10852    IMPLICIT NONE
10853
10854    CHARACTER (LEN=*) ::  variable   !<
10855
10856    CHARACTER(LEN=5) ::  grid        !< flag to distinquish between staggered grids
10857
10858    INTEGER(iwp) ::  av              !<
10859    INTEGER(iwp) ::  i               !<
10860    INTEGER(iwp) ::  j               !<
10861    INTEGER(iwp) ::  k               !<
10862    INTEGER(iwp) ::  topo_top_ind    !< k index of highest horizontal surface
10863
10864    LOGICAL ::  found                !< true if output array was found
10865    LOGICAL ::  resorted             !< true if array is resorted
10866
10867
10868    REAL(wp),                                                                  &
10869       DIMENSION(mask_size_l(mid,1),mask_size_l(mid,2),mask_size_l(mid,3)) ::  &
10870          local_pf   !<
10871
10872    REAL(wp), DIMENSION(:,:,:), POINTER ::  to_be_resorted  !< points to array which needs to be resorted for output
10873
10874
10875    found    = .TRUE.
10876    grid     = 's'
10877    resorted = .FALSE.
10878
10879    SELECT CASE ( TRIM( variable ) )
10880
10881
10882       CASE ( 'rad_lw_in' )
10883          IF ( av == 0 )  THEN
10884             to_be_resorted => rad_lw_in
10885          ELSE
10886             to_be_resorted => rad_lw_in_av
10887          ENDIF
10888
10889       CASE ( 'rad_lw_out' )
10890          IF ( av == 0 )  THEN
10891             to_be_resorted => rad_lw_out
10892          ELSE
10893             to_be_resorted => rad_lw_out_av
10894          ENDIF
10895
10896       CASE ( 'rad_lw_cs_hr' )
10897          IF ( av == 0 )  THEN
10898             to_be_resorted => rad_lw_cs_hr
10899          ELSE
10900             to_be_resorted => rad_lw_cs_hr_av
10901          ENDIF
10902
10903       CASE ( 'rad_lw_hr' )
10904          IF ( av == 0 )  THEN
10905             to_be_resorted => rad_lw_hr
10906          ELSE
10907             to_be_resorted => rad_lw_hr_av
10908          ENDIF
10909
10910       CASE ( 'rad_sw_in' )
10911          IF ( av == 0 )  THEN
10912             to_be_resorted => rad_sw_in
10913          ELSE
10914             to_be_resorted => rad_sw_in_av
10915          ENDIF
10916
10917       CASE ( 'rad_sw_out' )
10918          IF ( av == 0 )  THEN
10919             to_be_resorted => rad_sw_out
10920          ELSE
10921             to_be_resorted => rad_sw_out_av
10922          ENDIF
10923
10924       CASE ( 'rad_sw_cs_hr' )
10925          IF ( av == 0 )  THEN
10926             to_be_resorted => rad_sw_cs_hr
10927          ELSE
10928             to_be_resorted => rad_sw_cs_hr_av
10929          ENDIF
10930
10931       CASE ( 'rad_sw_hr' )
10932          IF ( av == 0 )  THEN
10933             to_be_resorted => rad_sw_hr
10934          ELSE
10935             to_be_resorted => rad_sw_hr_av
10936          ENDIF
10937
10938       CASE DEFAULT
10939          found = .FALSE.
10940
10941    END SELECT
10942
10943!
10944!-- Resort the array to be output, if not done above
10945    IF ( .NOT. resorted )  THEN
10946       IF ( .NOT. mask_surface(mid) )  THEN
10947!
10948!--       Default masked output
10949          DO  i = 1, mask_size_l(mid,1)
10950             DO  j = 1, mask_size_l(mid,2)
10951                DO  k = 1, mask_size_l(mid,3)
10952                   local_pf(i,j,k) =  to_be_resorted(mask_k(mid,k), &
10953                                      mask_j(mid,j),mask_i(mid,i))
10954                ENDDO
10955             ENDDO
10956          ENDDO
10957
10958       ELSE
10959!
10960!--       Terrain-following masked output
10961          DO  i = 1, mask_size_l(mid,1)
10962             DO  j = 1, mask_size_l(mid,2)
10963!
10964!--             Get k index of highest horizontal surface
10965                topo_top_ind = get_topography_top_index_ji( mask_j(mid,j), &
10966                                                            mask_i(mid,i), &
10967                                                            grid )
10968!
10969!--             Save output array
10970                DO  k = 1, mask_size_l(mid,3)
10971                   local_pf(i,j,k) = to_be_resorted(                       &
10972                                          MIN( topo_top_ind+mask_k(mid,k), &
10973                                               nzt+1 ),                    &
10974                                          mask_j(mid,j),                   &
10975                                          mask_i(mid,i)                     )
10976                ENDDO
10977             ENDDO
10978          ENDDO
10979
10980       ENDIF
10981    ENDIF
10982
10983
10984
10985 END SUBROUTINE radiation_data_output_mask
10986
10987
10988!------------------------------------------------------------------------------!
10989! Description:
10990! ------------
10991!> Subroutine writes local (subdomain) restart data
10992!------------------------------------------------------------------------------!
10993 SUBROUTINE radiation_wrd_local
10994
10995
10996    IMPLICIT NONE
10997
10998
10999    IF ( ALLOCATED( rad_net_av ) )  THEN
11000       CALL wrd_write_string( 'rad_net_av' )
11001       WRITE ( 14 )  rad_net_av
11002    ENDIF
11003   
11004    IF ( ALLOCATED( rad_lw_in_xy_av ) )  THEN
11005       CALL wrd_write_string( 'rad_lw_in_xy_av' )
11006       WRITE ( 14 )  rad_lw_in_xy_av
11007    ENDIF
11008   
11009    IF ( ALLOCATED( rad_lw_out_xy_av ) )  THEN
11010       CALL wrd_write_string( 'rad_lw_out_xy_av' )
11011       WRITE ( 14 )  rad_lw_out_xy_av
11012    ENDIF
11013   
11014    IF ( ALLOCATED( rad_sw_in_xy_av ) )  THEN
11015       CALL wrd_write_string( 'rad_sw_in_xy_av' )
11016       WRITE ( 14 )  rad_sw_in_xy_av
11017    ENDIF
11018   
11019    IF ( ALLOCATED( rad_sw_out_xy_av ) )  THEN
11020       CALL wrd_write_string( 'rad_sw_out_xy_av' )
11021       WRITE ( 14 )  rad_sw_out_xy_av
11022    ENDIF
11023
11024    IF ( ALLOCATED( rad_lw_in ) )  THEN
11025       CALL wrd_write_string( 'rad_lw_in' )
11026       WRITE ( 14 )  rad_lw_in
11027    ENDIF
11028
11029    IF ( ALLOCATED( rad_lw_in_av ) )  THEN
11030       CALL wrd_write_string( 'rad_lw_in_av' )
11031       WRITE ( 14 )  rad_lw_in_av
11032    ENDIF
11033
11034    IF ( ALLOCATED( rad_lw_out ) )  THEN
11035       CALL wrd_write_string( 'rad_lw_out' )
11036       WRITE ( 14 )  rad_lw_out
11037    ENDIF
11038
11039    IF ( ALLOCATED( rad_lw_out_av) )  THEN
11040       CALL wrd_write_string( 'rad_lw_out_av' )
11041       WRITE ( 14 )  rad_lw_out_av
11042    ENDIF
11043
11044    IF ( ALLOCATED( rad_lw_cs_hr) )  THEN
11045       CALL wrd_write_string( 'rad_lw_cs_hr' )
11046       WRITE ( 14 )  rad_lw_cs_hr
11047    ENDIF
11048
11049    IF ( ALLOCATED( rad_lw_cs_hr_av) )  THEN
11050       CALL wrd_write_string( 'rad_lw_cs_hr_av' )
11051       WRITE ( 14 )  rad_lw_cs_hr_av
11052    ENDIF
11053
11054    IF ( ALLOCATED( rad_lw_hr) )  THEN
11055       CALL wrd_write_string( 'rad_lw_hr' )
11056       WRITE ( 14 )  rad_lw_hr
11057    ENDIF
11058
11059    IF ( ALLOCATED( rad_lw_hr_av) )  THEN
11060       CALL wrd_write_string( 'rad_lw_hr_av' )
11061       WRITE ( 14 )  rad_lw_hr_av
11062    ENDIF
11063
11064    IF ( ALLOCATED( rad_sw_in) )  THEN
11065       CALL wrd_write_string( 'rad_sw_in' )
11066       WRITE ( 14 )  rad_sw_in
11067    ENDIF
11068
11069    IF ( ALLOCATED( rad_sw_in_av) )  THEN
11070       CALL wrd_write_string( 'rad_sw_in_av' )
11071       WRITE ( 14 )  rad_sw_in_av
11072    ENDIF
11073
11074    IF ( ALLOCATED( rad_sw_out) )  THEN
11075       CALL wrd_write_string( 'rad_sw_out' )
11076       WRITE ( 14 )  rad_sw_out
11077    ENDIF
11078
11079    IF ( ALLOCATED( rad_sw_out_av) )  THEN
11080       CALL wrd_write_string( 'rad_sw_out_av' )
11081       WRITE ( 14 )  rad_sw_out_av
11082    ENDIF
11083
11084    IF ( ALLOCATED( rad_sw_cs_hr) )  THEN
11085       CALL wrd_write_string( 'rad_sw_cs_hr' )
11086       WRITE ( 14 )  rad_sw_cs_hr
11087    ENDIF
11088
11089    IF ( ALLOCATED( rad_sw_cs_hr_av) )  THEN
11090       CALL wrd_write_string( 'rad_sw_cs_hr_av' )
11091       WRITE ( 14 )  rad_sw_cs_hr_av
11092    ENDIF
11093
11094    IF ( ALLOCATED( rad_sw_hr) )  THEN
11095       CALL wrd_write_string( 'rad_sw_hr' )
11096       WRITE ( 14 )  rad_sw_hr
11097    ENDIF
11098
11099    IF ( ALLOCATED( rad_sw_hr_av) )  THEN
11100       CALL wrd_write_string( 'rad_sw_hr_av' )
11101       WRITE ( 14 )  rad_sw_hr_av
11102    ENDIF
11103
11104
11105 END SUBROUTINE radiation_wrd_local
11106
11107!------------------------------------------------------------------------------!
11108! Description:
11109! ------------
11110!> Subroutine reads local (subdomain) restart data
11111!------------------------------------------------------------------------------!
11112 SUBROUTINE radiation_rrd_local( i, k, nxlf, nxlc, nxl_on_file, nxrf, nxrc,    &
11113                                nxr_on_file, nynf, nync, nyn_on_file, nysf,    &
11114                                nysc, nys_on_file, tmp_2d, tmp_3d, found )
11115 
11116
11117    USE control_parameters
11118       
11119    USE indices
11120   
11121    USE kinds
11122   
11123    USE pegrid
11124
11125
11126    IMPLICIT NONE
11127
11128    INTEGER(iwp) ::  i               !<
11129    INTEGER(iwp) ::  k               !<
11130    INTEGER(iwp) ::  nxlc            !<
11131    INTEGER(iwp) ::  nxlf            !<
11132    INTEGER(iwp) ::  nxl_on_file     !<
11133    INTEGER(iwp) ::  nxrc            !<
11134    INTEGER(iwp) ::  nxrf            !<
11135    INTEGER(iwp) ::  nxr_on_file     !<
11136    INTEGER(iwp) ::  nync            !<
11137    INTEGER(iwp) ::  nynf            !<
11138    INTEGER(iwp) ::  nyn_on_file     !<
11139    INTEGER(iwp) ::  nysc            !<
11140    INTEGER(iwp) ::  nysf            !<
11141    INTEGER(iwp) ::  nys_on_file     !<
11142
11143    LOGICAL, INTENT(OUT)  :: found
11144
11145    REAL(wp), DIMENSION(nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_2d   !<
11146
11147    REAL(wp), DIMENSION(nzb:nzt+1,nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_3d   !<
11148
11149    REAL(wp), DIMENSION(0:0,nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_3d2   !<
11150
11151
11152    found = .TRUE.
11153
11154
11155    SELECT CASE ( restart_string(1:length) )
11156
11157       CASE ( 'rad_net_av' )
11158          IF ( .NOT. ALLOCATED( rad_net_av ) )  THEN
11159             ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
11160          ENDIF 
11161          IF ( k == 1 )  READ ( 13 )  tmp_2d
11162          rad_net_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =           &
11163                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11164                       
11165       CASE ( 'rad_lw_in_xy_av' )
11166          IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) )  THEN
11167             ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
11168          ENDIF 
11169          IF ( k == 1 )  READ ( 13 )  tmp_2d
11170          rad_lw_in_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =      &
11171                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11172                       
11173       CASE ( 'rad_lw_out_xy_av' )
11174          IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) )  THEN
11175             ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
11176          ENDIF 
11177          IF ( k == 1 )  READ ( 13 )  tmp_2d
11178          rad_lw_out_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =     &
11179                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11180                       
11181       CASE ( 'rad_sw_in_xy_av' )
11182          IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) )  THEN
11183             ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
11184          ENDIF 
11185          IF ( k == 1 )  READ ( 13 )  tmp_2d
11186          rad_sw_in_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =      &
11187                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11188                       
11189       CASE ( 'rad_sw_out_xy_av' )
11190          IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) )  THEN
11191             ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
11192          ENDIF 
11193          IF ( k == 1 )  READ ( 13 )  tmp_2d
11194          rad_sw_out_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =     &
11195                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11196                       
11197       CASE ( 'rad_lw_in' )
11198          IF ( .NOT. ALLOCATED( rad_lw_in ) )  THEN
11199             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11200                  radiation_scheme == 'constant')  THEN
11201                ALLOCATE( rad_lw_in(0:0,nysg:nyng,nxlg:nxrg) )
11202             ELSE
11203                ALLOCATE( rad_lw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11204             ENDIF
11205          ENDIF 
11206          IF ( k == 1 )  THEN
11207             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11208                  radiation_scheme == 'constant')  THEN
11209                READ ( 13 )  tmp_3d2
11210                rad_lw_in(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =   &
11211                   tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11212             ELSE
11213                READ ( 13 )  tmp_3d
11214                rad_lw_in(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11215                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11216             ENDIF
11217          ENDIF
11218
11219       CASE ( 'rad_lw_in_av' )
11220          IF ( .NOT. ALLOCATED( rad_lw_in_av ) )  THEN
11221             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11222                  radiation_scheme == 'constant')  THEN
11223                ALLOCATE( rad_lw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
11224             ELSE
11225                ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11226             ENDIF
11227          ENDIF 
11228          IF ( k == 1 )  THEN
11229             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11230                  radiation_scheme == 'constant')  THEN
11231                READ ( 13 )  tmp_3d2
11232                rad_lw_in_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =&
11233                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11234             ELSE
11235                READ ( 13 )  tmp_3d
11236                rad_lw_in_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11237                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11238             ENDIF
11239          ENDIF
11240
11241       CASE ( 'rad_lw_out' )
11242          IF ( .NOT. ALLOCATED( rad_lw_out ) )  THEN
11243             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11244                  radiation_scheme == 'constant')  THEN
11245                ALLOCATE( rad_lw_out(0:0,nysg:nyng,nxlg:nxrg) )
11246             ELSE
11247                ALLOCATE( rad_lw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11248             ENDIF
11249          ENDIF 
11250          IF ( k == 1 )  THEN
11251             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11252                  radiation_scheme == 'constant')  THEN
11253                READ ( 13 )  tmp_3d2
11254                rad_lw_out(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11255                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11256             ELSE
11257                READ ( 13 )  tmp_3d
11258                rad_lw_out(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =    &
11259                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11260             ENDIF
11261          ENDIF
11262
11263       CASE ( 'rad_lw_out_av' )
11264          IF ( .NOT. ALLOCATED( rad_lw_out_av ) )  THEN
11265             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11266                  radiation_scheme == 'constant')  THEN
11267                ALLOCATE( rad_lw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
11268             ELSE
11269                ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11270             ENDIF
11271          ENDIF 
11272          IF ( k == 1 )  THEN
11273             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11274                  radiation_scheme == 'constant')  THEN
11275                READ ( 13 )  tmp_3d2
11276                rad_lw_out_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) &
11277                   = tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11278             ELSE
11279                READ ( 13 )  tmp_3d
11280                rad_lw_out_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &
11281                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11282             ENDIF
11283          ENDIF
11284
11285       CASE ( 'rad_lw_cs_hr' )
11286          IF ( .NOT. ALLOCATED( rad_lw_cs_hr ) )  THEN
11287             ALLOCATE( rad_lw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11288          ENDIF
11289          IF ( k == 1 )  READ ( 13 )  tmp_3d
11290          rad_lw_cs_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11291                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11292
11293       CASE ( 'rad_lw_cs_hr_av' )
11294          IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) )  THEN
11295             ALLOCATE( rad_lw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11296          ENDIF
11297          IF ( k == 1 )  READ ( 13 )  tmp_3d
11298          rad_lw_cs_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11299                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11300
11301       CASE ( 'rad_lw_hr' )
11302          IF ( .NOT. ALLOCATED( rad_lw_hr ) )  THEN
11303             ALLOCATE( rad_lw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11304          ENDIF
11305          IF ( k == 1 )  READ ( 13 )  tmp_3d
11306          rad_lw_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =           &
11307                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11308
11309       CASE ( 'rad_lw_hr_av' )
11310          IF ( .NOT. ALLOCATED( rad_lw_hr_av ) )  THEN
11311             ALLOCATE( rad_lw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11312          ENDIF
11313          IF ( k == 1 )  READ ( 13 )  tmp_3d
11314          rad_lw_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11315                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11316
11317       CASE ( 'rad_sw_in' )
11318          IF ( .NOT. ALLOCATED( rad_sw_in ) )  THEN
11319             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11320                  radiation_scheme == 'constant')  THEN
11321                ALLOCATE( rad_sw_in(0:0,nysg:nyng,nxlg:nxrg) )
11322             ELSE
11323                ALLOCATE( rad_sw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11324             ENDIF
11325          ENDIF 
11326          IF ( k == 1 )  THEN
11327             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11328                  radiation_scheme == 'constant')  THEN
11329                READ ( 13 )  tmp_3d2
11330                rad_sw_in(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =   &
11331                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11332             ELSE
11333                READ ( 13 )  tmp_3d
11334                rad_sw_in(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11335                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11336             ENDIF
11337          ENDIF
11338
11339       CASE ( 'rad_sw_in_av' )
11340          IF ( .NOT. ALLOCATED( rad_sw_in_av ) )  THEN
11341             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11342                  radiation_scheme == 'constant')  THEN
11343                ALLOCATE( rad_sw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
11344             ELSE
11345                ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11346             ENDIF
11347          ENDIF 
11348          IF ( k == 1 )  THEN
11349             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11350                  radiation_scheme == 'constant')  THEN
11351                READ ( 13 )  tmp_3d2
11352                rad_sw_in_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =&
11353                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11354             ELSE
11355                READ ( 13 )  tmp_3d
11356                rad_sw_in_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11357                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11358             ENDIF
11359          ENDIF
11360
11361       CASE ( 'rad_sw_out' )
11362          IF ( .NOT. ALLOCATED( rad_sw_out ) )  THEN
11363             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11364                  radiation_scheme == 'constant')  THEN
11365                ALLOCATE( rad_sw_out(0:0,nysg:nyng,nxlg:nxrg) )
11366             ELSE
11367                ALLOCATE( rad_sw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11368             ENDIF
11369          ENDIF 
11370          IF ( k == 1 )  THEN
11371             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11372                  radiation_scheme == 'constant')  THEN
11373                READ ( 13 )  tmp_3d2
11374                rad_sw_out(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11375                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11376             ELSE
11377                READ ( 13 )  tmp_3d
11378                rad_sw_out(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =    &
11379                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11380             ENDIF
11381          ENDIF
11382
11383       CASE ( 'rad_sw_out_av' )
11384          IF ( .NOT. ALLOCATED( rad_sw_out_av ) )  THEN
11385             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11386                  radiation_scheme == 'constant')  THEN
11387                ALLOCATE( rad_sw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
11388             ELSE
11389                ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11390             ENDIF
11391          ENDIF 
11392          IF ( k == 1 )  THEN
11393             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11394                  radiation_scheme == 'constant')  THEN
11395                READ ( 13 )  tmp_3d2
11396                rad_sw_out_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) &
11397                   = tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11398             ELSE
11399                READ ( 13 )  tmp_3d
11400                rad_sw_out_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &
11401                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11402             ENDIF
11403          ENDIF
11404
11405       CASE ( 'rad_sw_cs_hr' )
11406          IF ( .NOT. ALLOCATED( rad_sw_cs_hr ) )  THEN
11407             ALLOCATE( rad_sw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11408          ENDIF
11409          IF ( k == 1 )  READ ( 13 )  tmp_3d
11410          rad_sw_cs_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11411                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11412
11413       CASE ( 'rad_sw_cs_hr_av' )
11414          IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) )  THEN
11415             ALLOCATE( rad_sw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11416          ENDIF
11417          IF ( k == 1 )  READ ( 13 )  tmp_3d
11418          rad_sw_cs_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11419                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11420
11421       CASE ( 'rad_sw_hr' )
11422          IF ( .NOT. ALLOCATED( rad_sw_hr ) )  THEN
11423             ALLOCATE( rad_sw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11424          ENDIF
11425          IF ( k == 1 )  READ ( 13 )  tmp_3d
11426          rad_sw_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =           &
11427                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11428
11429       CASE ( 'rad_sw_hr_av' )
11430          IF ( .NOT. ALLOCATED( rad_sw_hr_av ) )  THEN
11431             ALLOCATE( rad_sw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11432          ENDIF
11433          IF ( k == 1 )  READ ( 13 )  tmp_3d
11434          rad_lw_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11435                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11436
11437       CASE DEFAULT
11438
11439          found = .FALSE.
11440
11441    END SELECT
11442
11443 END SUBROUTINE radiation_rrd_local
11444
11445!------------------------------------------------------------------------------!
11446! Description:
11447! ------------
11448!> Subroutine writes debug information
11449!------------------------------------------------------------------------------!
11450 SUBROUTINE radiation_write_debug_log ( message )
11451    !> it writes debug log with time stamp
11452    CHARACTER(*)  :: message
11453    CHARACTER(15) :: dtc
11454    CHARACTER(8)  :: date
11455    CHARACTER(10) :: time
11456    CHARACTER(5)  :: zone
11457    CALL date_and_time(date, time, zone)
11458    dtc = date(7:8)//','//time(1:2)//':'//time(3:4)//':'//time(5:10)
11459    WRITE(9,'(2A)') dtc, TRIM(message)
11460    FLUSH(9)
11461 END SUBROUTINE radiation_write_debug_log
11462
11463 END MODULE radiation_model_mod
Note: See TracBrowser for help on using the repository browser.