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

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

Output of radiation-related quantities migrated from urban_surface_model_mod to radiation_model_mod

  • 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: 491.4 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-2018 Leibniz Universitaet Hannover
21!------------------------------------------------------------------------------!
22!
23! Current revisions:
24! ------------------
25!
26!
27! Former revisions:
28! -----------------
29! $Id: radiation_model_mod.f90 3607 2018-12-07 11:56:58Z suehring $
30! Output of radiation-related quantities migrated to radiation_model_mod.
31!
32! 3589 2018-11-30 15:09:51Z suehring
33! Remove erroneous UTF encoding
34!
35! 3572 2018-11-28 11:40:28Z suehring
36! Add filling the short- and longwave radiation flux arrays (e.g. diffuse,
37! direct, reflected, resedual) for all surfaces. This is required to surface
38! outputs in suface_output_mod. (M. Salim)
39!
40! 3571 2018-11-28 09:24:03Z moh.hefny
41! Add an epsilon value to compare values in if statement to fix possible
42! precsion related errors in raytrace routines.
43!
44! 3524 2018-11-14 13:36:44Z raasch
45! missing cpp-directives added
46!
47! 3495 2018-11-06 15:22:17Z kanani
48! Resort control_parameters ONLY list,
49! From branch radiation@3491 moh.hefny:
50! bugfix in calculating the apparent solar positions by updating
51! the simulated time so that the actual time is correct.
52!
53! 3464 2018-10-30 18:08:55Z kanani
54! From branch resler@3462, pavelkrc:
55! add MRT shaping function for human
56!
57! 3449 2018-10-29 19:36:56Z suehring
58! New RTM version 3.0: (Pavel Krc, Jaroslav Resler, ICS, Prague)
59!   - Interaction of plant canopy with LW radiation
60!   - Transpiration from resolved plant canopy dependent on radiation
61!     called from RTM
62!
63!
64! 3435 2018-10-26 18:25:44Z gronemeier
65! - workaround: return unit=illegal in check_data_output for certain variables
66!   when check called from init_masks
67! - Use pointer in masked output to reduce code redundancies
68! - Add terrain-following masked output
69!
70! 3424 2018-10-25 07:29:10Z gronemeier
71! bugfix: add rad_lw_in, rad_lw_out, rad_sw_out to radiation_check_data_output
72!
73! 3378 2018-10-19 12:34:59Z kanani
74! merge from radiation branch (r3362) into trunk
75! (moh.hefny):
76! - removed read/write_svf_on_init and read_dist_max_svf (not used anymore)
77! - bugfix nzut > nzpt in calculating maxboxes
78!
79! 3372 2018-10-18 14:03:19Z raasch
80! bugfix: kind type of 2nd argument of mpi_win_allocate changed, misplaced
81!         __parallel directive
82!
83! 3351 2018-10-15 18:40:42Z suehring
84! Do not overwrite values of spectral and broadband albedo during initialization
85! if they are already initialized in the urban-surface model via ASCII input.
86!
87! 3337 2018-10-12 15:17:09Z kanani
88! - New RTM version 2.9: (Pavel Krc, Jaroslav Resler, ICS, Prague)
89!   added calculation of the MRT inside the RTM module
90!   MRT fluxes are consequently used in the new biometeorology module
91!   for calculation of biological indices (MRT, PET)
92!   Fixes of v. 2.5 and SVN trunk:
93!    - proper initialization of rad_net_l
94!    - make arrays nsurfs and surfstart TARGET to prevent some MPI problems
95!    - initialization of arrays used in MPI one-sided operation as 1-D arrays
96!      to prevent problems with some MPI/compiler combinations
97!    - fix indexing of target displacement in subroutine request_itarget to
98!      consider nzub
99!    - fix LAD dimmension range in PCB calculation
100!    - check ierr in all MPI calls
101!    - use proper per-gridbox sky and diffuse irradiance
102!    - fix shading for reflected irradiance
103!    - clear away the residuals of "atmospheric surfaces" implementation
104!    - fix rounding bug in raytrace_2d introduced in SVN trunk
105! - New RTM version 2.5: (Pavel Krc, Jaroslav Resler, ICS, Prague)
106!   can use angular discretization for all SVF
107!   (i.e. reflected and emitted radiation in addition to direct and diffuse),
108!   allowing for much better scaling wih high resoltion and/or complex terrain
109! - Unite array grow factors
110! - Fix slightly shifted terrain height in raytrace_2d
111! - Use more efficient MPI_Win_allocate for reverse gridsurf index
112! - Fix random MPI RMA bugs on Intel compilers
113! - Fix approx. double plant canopy sink values for reflected radiation
114! - Fix mostly missing plant canopy sinks for direct radiation
115! - Fix discretization errors for plant canopy sink in diffuse radiation
116! - Fix rounding errors in raytrace_2d
117!
118! 3274 2018-09-24 15:42:55Z knoop
119! Modularization of all bulk cloud physics code components
120!
121! 3272 2018-09-24 10:16:32Z suehring
122! - split direct and diffusion shortwave radiation using RRTMG rather than using
123!   calc_diffusion_radiation, in case of RRTMG
124! - removed the namelist variable split_diffusion_radiation. Now splitting depends
125!   on the choise of radiation radiation scheme
126! - removed calculating the rdiation flux for surfaces at the radiation scheme
127!   in case of using RTM since it will be calculated anyway in the radiation
128!   interaction routine.
129! - set SW radiation flux for surfaces to zero at night in case of no RTM is used
130! - precalculate the unit vector yxdir of ray direction to avoid the temporarly
131!   array allocation during the subroutine call
132! - fixed a bug in calculating the max number of boxes ray can cross in the domain
133!
134! 3264 2018-09-20 13:54:11Z moh.hefny
135! Bugfix in raytrace_2d calls
136!
137! 3248 2018-09-14 09:42:06Z sward
138! Minor formating changes
139!
140! 3246 2018-09-13 15:14:50Z sward
141! Added error handling for input namelist via parin_fail_message
142!
143! 3241 2018-09-12 15:02:00Z raasch
144! unused variables removed or commented
145!
146! 3233 2018-09-07 13:21:24Z schwenkel
147! Adapted for the use of cloud_droplets
148!
149! 3230 2018-09-05 09:29:05Z schwenkel
150! Bugfix in radiation_constant_surf: changed (10.0 - emissivity_urb) to
151! (1.0 - emissivity_urb)
152!
153! 3226 2018-08-31 12:27:09Z suehring
154! Bugfixes in calculation of sky-view factors and canopy-sink factors.
155!
156! 3186 2018-07-30 17:07:14Z suehring
157! Remove print statement
158!
159! 3180 2018-07-27 11:00:56Z suehring
160! Revise concept for calculation of effective radiative temperature and mapping
161! of radiative heating
162!
163! 3175 2018-07-26 14:07:38Z suehring
164! Bugfix for commit 3172
165!
166! 3173 2018-07-26 12:55:23Z suehring
167! Revise output of surface radiation quantities in case of overhanging
168! structures
169!
170! 3172 2018-07-26 12:06:06Z suehring
171! Bugfixes:
172!  - temporal work-around for calculation of effective radiative surface
173!    temperature
174!  - prevent positive solar radiation during nighttime
175!
176! 3170 2018-07-25 15:19:37Z suehring
177! Bugfix, map signle-column radiation forcing profiles on top of any topography
178!
179! 3156 2018-07-19 16:30:54Z knoop
180! Bugfix: replaced usage of the pt array with the surf%pt_surface array
181!
182! 3137 2018-07-17 06:44:21Z maronga
183! String length for trace_names fixed
184!
185! 3127 2018-07-15 08:01:25Z maronga
186! A few pavement parameters updated.
187!
188! 3123 2018-07-12 16:21:53Z suehring
189! Correct working precision for INTEGER number
190!
191! 3122 2018-07-11 21:46:41Z maronga
192! Bugfix: maximum distance for raytracing was set to  -999 m by default,
193! effectively switching off all surface reflections when max_raytracing_dist
194! was not explicitly set in namelist
195!
196! 3117 2018-07-11 09:59:11Z maronga
197! Bugfix: water vapor was not transfered to RRTMG when bulk_cloud_model = .F.
198! Bugfix: changed the calculation of RRTMG boundary conditions (Mohamed Salim)
199! Bugfix: dry residual atmosphere is replaced by standard RRTMG atmosphere
200!
201! 3116 2018-07-10 14:31:58Z suehring
202! Output of long/shortwave radiation at surface
203!
204! 3107 2018-07-06 15:55:51Z suehring
205! Bugfix, missing index for dz
206!
207! 3066 2018-06-12 08:55:55Z Giersch
208! Error message revised
209!
210! 3065 2018-06-12 07:03:02Z Giersch
211! dz was replaced by dz(1), error message concerning vertical stretching was
212! added 
213!
214! 3049 2018-05-29 13:52:36Z Giersch
215! Error messages revised
216!
217! 3045 2018-05-28 07:55:41Z Giersch
218! Error message revised
219!
220! 3026 2018-05-22 10:30:53Z schwenkel
221! Changed the name specific humidity to mixing ratio, since we are computing
222! mixing ratios.
223!
224! 3016 2018-05-09 10:53:37Z Giersch
225! Revised structure of reading svf data according to PALM coding standard:
226! svf_code_field/len and fsvf removed, error messages PA0493 and PA0494 added,
227! allocation status of output arrays checked.
228!
229! 3014 2018-05-09 08:42:38Z maronga
230! Introduced plant canopy height similar to urban canopy height to limit
231! the memory requirement to allocate lad.
232! Deactivated automatic setting of minimum raytracing distance.
233!
234! 3004 2018-04-27 12:33:25Z Giersch
235! Further allocation checks implemented (averaged data will be assigned to fill
236! values if no allocation happened so far)
237!
238! 2995 2018-04-19 12:13:16Z Giersch
239! IF-statement in radiation_init removed so that the calculation of radiative
240! fluxes at model start is done in any case, bugfix in
241! radiation_presimulate_solar_pos (end_time is the sum of end_time and the
242! spinup_time specified in the p3d_file ), list of variables/fields that have
243! to be written out or read in case of restarts has been extended
244!
245! 2977 2018-04-17 10:27:57Z kanani
246! Implement changes from branch radiation (r2948-2971) with minor modifications,
247! plus some formatting.
248! (moh.hefny):
249! - replaced plant_canopy by npcbl to check tree existence to avoid weird
250!   allocation of related arrays (after domain decomposition some domains
251!   contains no trees although plant_canopy (global parameter) is still TRUE).
252! - added a namelist parameter to force RTM settings
253! - enabled the option to switch radiation reflections off
254! - renamed surf_reflections to surface_reflections
255! - removed average_radiation flag from the namelist (now it is implicitly set
256!   in init_3d_model according to RTM)
257! - edited read and write sky view factors and CSF routines to account for
258!   the sub-domains which may not contain any of them
259!
260! 2967 2018-04-13 11:22:08Z raasch
261! bugfix: missing parallel cpp-directives added
262!
263! 2964 2018-04-12 16:04:03Z Giersch
264! Error message PA0491 has been introduced which could be previously found in
265! check_open. The variable numprocs_previous_run is only known in case of
266! initializing_actions == read_restart_data
267!
268! 2963 2018-04-12 14:47:44Z suehring
269! - Introduce index for vegetation/wall, pavement/green-wall and water/window
270!   surfaces, for clearer access of surface fraction, albedo, emissivity, etc. .
271! - Minor bugfix in initialization of albedo for window surfaces
272!
273! 2944 2018-04-03 16:20:18Z suehring
274! Fixed bad commit
275!
276! 2943 2018-04-03 16:17:10Z suehring
277! No read of nsurfl from SVF file since it is calculated in
278! radiation_interaction_init,
279! allocation of arrays in radiation_read_svf only if not yet allocated,
280! update of 2920 revision comment.
281!
282! 2932 2018-03-26 09:39:22Z maronga
283! renamed radiation_par to radiation_parameters
284!
285! 2930 2018-03-23 16:30:46Z suehring
286! Remove default surfaces from radiation model, does not make much sense to
287! apply radiation model without energy-balance solvers; Further, add check for
288! this.
289!
290! 2920 2018-03-22 11:22:01Z kanani
291! - Bugfix: Initialize pcbl array (=-1)
292! RTM version 2.0 (Jaroslav Resler, Pavel Krc, Mohamed Salim):
293! - new major version of radiation interactions
294! - substantially enhanced performance and scalability
295! - processing of direct and diffuse solar radiation separated from reflected
296!   radiation, removed virtual surfaces
297! - new type of sky discretization by azimuth and elevation angles
298! - diffuse radiation processed cumulatively using sky view factor
299! - used precalculated apparent solar positions for direct irradiance
300! - added new 2D raytracing process for processing whole vertical column at once
301!   to increase memory efficiency and decrease number of MPI RMA operations
302! - enabled limiting the number of view factors between surfaces by the distance
303!   and value
304! - fixing issues induced by transferring radiation interactions from
305!   urban_surface_mod to radiation_mod
306! - bugfixes and other minor enhancements
307!
308! 2906 2018-03-19 08:56:40Z Giersch
309! NAMELIST paramter read/write_svf_on_init have been removed, functions
310! check_open and close_file are used now for opening/closing files related to
311! svf data, adjusted unit number and error numbers
312!
313! 2894 2018-03-15 09:17:58Z Giersch
314! Calculations of the index range of the subdomain on file which overlaps with
315! the current subdomain are already done in read_restart_data_mod
316! radiation_read_restart_data was renamed to radiation_rrd_local and
317! radiation_last_actions was renamed to radiation_wrd_local, variable named
318! found has been introduced for checking if restart data was found, reading
319! of restart strings has been moved completely to read_restart_data_mod,
320! radiation_rrd_local is already inside the overlap loop programmed in
321! read_restart_data_mod, the marker *** end rad *** is not necessary anymore,
322! strings and their respective lengths are written out and read now in case of
323! restart runs to get rid of prescribed character lengths (Giersch)
324!
325! 2809 2018-02-15 09:55:58Z suehring
326! Bugfix for gfortran: Replace the function C_SIZEOF with STORAGE_SIZE
327!
328! 2753 2018-01-16 14:16:49Z suehring
329! Tile approach for spectral albedo implemented.
330!
331! 2746 2018-01-15 12:06:04Z suehring
332! Move flag plant canopy to modules
333!
334! 2724 2018-01-05 12:12:38Z maronga
335! Set default of average_radiation to .FALSE.
336!
337! 2723 2018-01-05 09:27:03Z maronga
338! Bugfix in calculation of rad_lw_out (clear-sky). First grid level was used
339! instead of the surface value
340!
341! 2718 2018-01-02 08:49:38Z maronga
342! Corrected "Former revisions" section
343!
344! 2707 2017-12-18 18:34:46Z suehring
345! Changes from last commit documented
346!
347! 2706 2017-12-18 18:33:49Z suehring
348! Bugfix, in average radiation case calculate exner function before using it.
349!
350! 2701 2017-12-15 15:40:50Z suehring
351! Changes from last commit documented
352!
353! 2698 2017-12-14 18:46:24Z suehring
354! Bugfix in get_topography_top_index
355!
356! 2696 2017-12-14 17:12:51Z kanani
357! - Change in file header (GPL part)
358! - Improved reading/writing of SVF from/to file (BM)
359! - Bugfixes concerning RRTMG as well as average_radiation options (M. Salim)
360! - Revised initialization of surface albedo and some minor bugfixes (MS)
361! - Update net radiation after running radiation interaction routine (MS)
362! - Revisions from M Salim included
363! - Adjustment to topography and surface structure (MS)
364! - Initialization of albedo and surface emissivity via input file (MS)
365! - albedo_pars extended (MS)
366!
367! 2604 2017-11-06 13:29:00Z schwenkel
368! bugfix for calculation of effective radius using morrison microphysics
369!
370! 2601 2017-11-02 16:22:46Z scharf
371! added emissivity to namelist
372!
373! 2575 2017-10-24 09:57:58Z maronga
374! Bugfix: calculation of shortwave and longwave albedos for RRTMG swapped
375!
376! 2547 2017-10-16 12:41:56Z schwenkel
377! extended by cloud_droplets option, minor bugfix and correct calculation of
378! cloud droplet number concentration
379!
380! 2544 2017-10-13 18:09:32Z maronga
381! Moved date and time quantitis to separate module date_and_time_mod
382!
383! 2512 2017-10-04 08:26:59Z raasch
384! upper bounds of cross section and 3d output changed from nx+1,ny+1 to nx,ny
385! no output of ghost layer data
386!
387! 2504 2017-09-27 10:36:13Z maronga
388! Updates pavement types and albedo parameters
389!
390! 2328 2017-08-03 12:34:22Z maronga
391! Emissivity can now be set individually for each pixel.
392! Albedo type can be inferred from land surface model.
393! Added default albedo type for bare soil
394!
395! 2318 2017-07-20 17:27:44Z suehring
396! Get topography top index via Function call
397!
398! 2317 2017-07-20 17:27:19Z suehring
399! Improved syntax layout
400!
401! 2298 2017-06-29 09:28:18Z raasch
402! type of write_binary changed from CHARACTER to LOGICAL
403!
404! 2296 2017-06-28 07:53:56Z maronga
405! Added output of rad_sw_out for radiation_scheme = 'constant'
406!
407! 2270 2017-06-09 12:18:47Z maronga
408! Numbering changed (2 timeseries removed)
409!
410! 2249 2017-06-06 13:58:01Z sward
411! Allow for RRTMG runs without humidity/cloud physics
412!
413! 2248 2017-06-06 13:52:54Z sward
414! Error no changed
415!
416! 2233 2017-05-30 18:08:54Z suehring
417!
418! 2232 2017-05-30 17:47:52Z suehring
419! Adjustments to new topography concept
420! Bugfix in read restart
421!
422! 2200 2017-04-11 11:37:51Z suehring
423! Bugfix in call of exchange_horiz_2d and read restart data
424!
425! 2163 2017-03-01 13:23:15Z schwenkel
426! Bugfix in radiation_check_data_output
427!
428! 2157 2017-02-22 15:10:35Z suehring
429! Bugfix in read_restart data
430!
431! 2011 2016-09-19 17:29:57Z kanani
432! Removed CALL of auxiliary SUBROUTINE get_usm_info,
433! flag urban_surface is now defined in module control_parameters.
434!
435! 2007 2016-08-24 15:47:17Z kanani
436! Added calculation of solar directional vector for new urban surface
437! model,
438! accounted for urban_surface model in radiation_check_parameters,
439! correction of comments for zenith angle.
440!
441! 2000 2016-08-20 18:09:15Z knoop
442! Forced header and separation lines into 80 columns
443!
444! 1976 2016-07-27 13:28:04Z maronga
445! Output of 2D/3D/masked data is now directly done within this module. The
446! radiation schemes have been simplified for better usability so that
447! rad_lw_in, rad_lw_out, rad_sw_in, and rad_sw_out are available independent of
448! the radiation code used.
449!
450! 1856 2016-04-13 12:56:17Z maronga
451! Bugfix: allocation of rad_lw_out for radiation_scheme = 'clear-sky'
452!
453! 1853 2016-04-11 09:00:35Z maronga
454! Added routine for radiation_scheme = constant.
455
456! 1849 2016-04-08 11:33:18Z hoffmann
457! Adapted for modularization of microphysics
458!
459! 1826 2016-04-07 12:01:39Z maronga
460! Further modularization.
461!
462! 1788 2016-03-10 11:01:04Z maronga
463! Added new albedo class for pavements / roads.
464!
465! 1783 2016-03-06 18:36:17Z raasch
466! palm-netcdf-module removed in order to avoid a circular module dependency,
467! netcdf-variables moved to netcdf-module, new routine netcdf_handle_error_rad
468! added
469!
470! 1757 2016-02-22 15:49:32Z maronga
471! Added parameter unscheduled_radiation_calls. Bugfix: interpolation of sounding
472! profiles for pressure and temperature above the LES domain.
473!
474! 1709 2015-11-04 14:47:01Z maronga
475! Bugfix: set initial value for rrtm_lwuflx_dt to zero, small formatting
476! corrections
477!
478! 1701 2015-11-02 07:43:04Z maronga
479! Bugfixes: wrong index for output of timeseries, setting of nz_snd_end
480!
481! 1691 2015-10-26 16:17:44Z maronga
482! Added option for spin-up runs without radiation (skip_time_do_radiation). Bugfix
483! in calculation of pressure profiles. Bugfix in calculation of trace gas profiles.
484! Added output of radiative heating rates.
485!
486! 1682 2015-10-07 23:56:08Z knoop
487! Code annotations made doxygen readable
488!
489! 1606 2015-06-29 10:43:37Z maronga
490! Added preprocessor directive __netcdf to allow for compiling without netCDF.
491! Note, however, that RRTMG cannot be used without netCDF.
492!
493! 1590 2015-05-08 13:56:27Z maronga
494! Bugfix: definition of character strings requires same length for all elements
495!
496! 1587 2015-05-04 14:19:01Z maronga
497! Added albedo class for snow
498!
499! 1585 2015-04-30 07:05:52Z maronga
500! Added support for RRTMG
501!
502! 1571 2015-03-12 16:12:49Z maronga
503! Added missing KIND attribute. Removed upper-case variable names
504!
505! 1551 2015-03-03 14:18:16Z maronga
506! Added support for data output. Various variables have been renamed. Added
507! interface for different radiation schemes (currently: clear-sky, constant, and
508! RRTM (not yet implemented).
509!
510! 1496 2014-12-02 17:25:50Z maronga
511! Initial revision
512!
513!
514! Description:
515! ------------
516!> Radiation models and interfaces
517!> @todo Replace dz(1) appropriatly to account for grid stretching
518!> @todo move variable definitions used in radiation_init only to the subroutine
519!>       as they are no longer required after initialization.
520!> @todo Output of full column vertical profiles used in RRTMG
521!> @todo Output of other rrtm arrays (such as volume mixing ratios)
522!> @todo Check for mis-used NINT() calls in raytrace_2d
523!>       RESULT: Original was correct (carefully verified formula), the change
524!>               to INT broke raytracing      -- P. Krc
525!> @todo Optimize radiation_tendency routines
526!>
527!> @note Many variables have a leading dummy dimension (0:0) in order to
528!>       match the assume-size shape expected by the RRTMG model.
529!------------------------------------------------------------------------------!
530 MODULE radiation_model_mod
531 
532    USE arrays_3d,                                                             &
533        ONLY:  dzw, hyp, nc, pt, p, q, ql, u, v, w, zu, zw, exner, d_exner
534
535    USE basic_constants_and_equations_mod,                                     &
536        ONLY:  c_p, g, lv_d_cp, l_v, pi, r_d, rho_l, solar_constant,      &
537               barometric_formula
538
539    USE calc_mean_profile_mod,                                                 &
540        ONLY:  calc_mean_profile
541
542    USE control_parameters,                                                    &
543        ONLY:  cloud_droplets, coupling_char, dz, dt_spinup, end_time,         &
544               humidity,                                                       &
545               initializing_actions, io_blocks, io_group,                      &
546               land_surface, large_scale_forcing,                              &
547               latitude, longitude, lsf_surf,                                  &
548               message_string, plant_canopy, pt_surface,                       &
549               rho_surface, simulated_time, spinup_time, surface_pressure,     &
550               time_since_reference_point, urban_surface, varnamelength
551
552    USE cpulog,                                                                &
553        ONLY:  cpu_log, log_point, log_point_s
554
555    USE grid_variables,                                                        &
556         ONLY:  ddx, ddy, dx, dy 
557
558    USE date_and_time_mod,                                                     &
559        ONLY:  calc_date_and_time, d_hours_day, d_seconds_hour, day_of_year,   &
560               d_seconds_year, day_of_year_init, time_utc_init, time_utc
561
562    USE indices,                                                               &
563        ONLY:  nnx, nny, nx, nxl, nxlg, nxr, nxrg, ny, nyn, nyng, nys, nysg,   &
564               nzb, nzt
565
566    USE, INTRINSIC :: iso_c_binding
567
568    USE kinds
569
570    USE bulk_cloud_model_mod,                                                  &
571        ONLY:  bulk_cloud_model, microphysics_morrison, na_init, nc_const, sigma_gc
572
573#if defined ( __netcdf )
574    USE NETCDF
575#endif
576
577    USE netcdf_data_input_mod,                                                 &
578        ONLY:  albedo_type_f, albedo_pars_f, building_type_f, pavement_type_f, &
579               vegetation_type_f, water_type_f
580
581    USE plant_canopy_model_mod,                                                &
582        ONLY:  lad_s, pc_heating_rate, pc_transpiration_rate, pc_latent_rate,  &
583               plant_canopy_transpiration, pcm_calc_transpiration_rate
584
585    USE pegrid
586
587#if defined ( __rrtmg )
588    USE parrrsw,                                                               &
589        ONLY:  naerec, nbndsw
590
591    USE parrrtm,                                                               &
592        ONLY:  nbndlw
593
594    USE rrtmg_lw_init,                                                         &
595        ONLY:  rrtmg_lw_ini
596
597    USE rrtmg_sw_init,                                                         &
598        ONLY:  rrtmg_sw_ini
599
600    USE rrtmg_lw_rad,                                                          &
601        ONLY:  rrtmg_lw
602
603    USE rrtmg_sw_rad,                                                          &
604        ONLY:  rrtmg_sw
605#endif
606    USE statistics,                                                            &
607        ONLY:  hom
608
609    USE surface_mod,                                                           &
610        ONLY:  get_topography_top_index, get_topography_top_index_ji,          &
611               ind_pav_green, ind_veg_wall, ind_wat_win,                       &
612               surf_lsm_h, surf_lsm_v, surf_type, surf_usm_h, surf_usm_v
613
614    IMPLICIT NONE
615
616    CHARACTER(10) :: radiation_scheme = 'clear-sky' ! 'constant', 'clear-sky', or 'rrtmg'
617
618!
619!-- Predefined Land surface classes (albedo_type) after Briegleb (1992)
620    CHARACTER(37), DIMENSION(0:33), PARAMETER :: albedo_type_name = (/      &
621                                   'user defined                         ', & !  0
622                                   'ocean                                ', & !  1
623                                   'mixed farming, tall grassland        ', & !  2
624                                   'tall/medium grassland                ', & !  3
625                                   'evergreen shrubland                  ', & !  4
626                                   'short grassland/meadow/shrubland     ', & !  5
627                                   'evergreen needleleaf forest          ', & !  6
628                                   'mixed deciduous evergreen forest     ', & !  7
629                                   'deciduous forest                     ', & !  8
630                                   'tropical evergreen broadleaved forest', & !  9
631                                   'medium/tall grassland/woodland       ', & ! 10
632                                   'desert, sandy                        ', & ! 11
633                                   'desert, rocky                        ', & ! 12
634                                   'tundra                               ', & ! 13
635                                   'land ice                             ', & ! 14
636                                   'sea ice                              ', & ! 15
637                                   'snow                                 ', & ! 16
638                                   'bare soil                            ', & ! 17
639                                   'asphalt/concrete mix                 ', & ! 18
640                                   'asphalt (asphalt concrete)           ', & ! 19
641                                   'concrete (Portland concrete)         ', & ! 20
642                                   'sett                                 ', & ! 21
643                                   'paving stones                        ', & ! 22
644                                   'cobblestone                          ', & ! 23
645                                   'metal                                ', & ! 24
646                                   'wood                                 ', & ! 25
647                                   'gravel                               ', & ! 26
648                                   'fine gravel                          ', & ! 27
649                                   'pebblestone                          ', & ! 28
650                                   'woodchips                            ', & ! 29
651                                   'tartan (sports)                      ', & ! 30
652                                   'artifical turf (sports)              ', & ! 31
653                                   'clay (sports)                        ', & ! 32
654                                   'building (dummy)                     '  & ! 33
655                                                         /)
656
657    REAL(wp), PARAMETER :: sigma_sb       = 5.67037321E-8_wp !< Stefan-Boltzmann constant
658
659    INTEGER(iwp) :: albedo_type  = 9999999, & !< Albedo surface type
660                    dots_rad     = 0          !< starting index for timeseries output
661
662    LOGICAL ::  unscheduled_radiation_calls = .TRUE., & !< flag parameter indicating whether additional calls of the radiation code are allowed
663                constant_albedo = .FALSE.,            & !< flag parameter indicating whether the albedo may change depending on zenith
664                force_radiation_call = .FALSE.,       & !< flag parameter for unscheduled radiation calls
665                lw_radiation = .TRUE.,                & !< flag parameter indicating whether longwave radiation shall be calculated
666                radiation = .FALSE.,                  & !< flag parameter indicating whether the radiation model is used
667                sun_up    = .TRUE.,                   & !< flag parameter indicating whether the sun is up or down
668                sw_radiation = .TRUE.,                & !< flag parameter indicating whether shortwave radiation shall be calculated
669                sun_direction = .FALSE.,              & !< flag parameter indicating whether solar direction shall be calculated
670                average_radiation = .FALSE.,          & !< flag to set the calculation of radiation averaging for the domain
671                radiation_interactions = .FALSE.,     & !< flag to activiate RTM (TRUE only if vertical urban/land surface and trees exist)
672                surface_reflections = .TRUE.,         & !< flag to switch the calculation of radiation interaction between surfaces.
673                                                        !< When it switched off, only the effect of buildings and trees shadow
674                                                        !< will be considered. However fewer SVFs are expected.
675                radiation_interactions_on = .TRUE.      !< namelist flag to force RTM activiation regardless to vertical urban/land surface and trees
676
677    REAL(wp) :: albedo = 9999999.9_wp,           & !< NAMELIST alpha
678                albedo_lw_dif = 9999999.9_wp,    & !< NAMELIST aldif
679                albedo_lw_dir = 9999999.9_wp,    & !< NAMELIST aldir
680                albedo_sw_dif = 9999999.9_wp,    & !< NAMELIST asdif
681                albedo_sw_dir = 9999999.9_wp,    & !< NAMELIST asdir
682                decl_1,                          & !< declination coef. 1
683                decl_2,                          & !< declination coef. 2
684                decl_3,                          & !< declination coef. 3
685                dt_radiation = 0.0_wp,           & !< radiation model timestep
686                emissivity = 9999999.9_wp,       & !< NAMELIST surface emissivity
687                lon = 0.0_wp,                    & !< longitude in radians
688                lat = 0.0_wp,                    & !< latitude in radians
689                net_radiation = 0.0_wp,          & !< net radiation at surface
690                skip_time_do_radiation = 0.0_wp, & !< Radiation model is not called before this time
691                sky_trans,                       & !< sky transmissivity
692                time_radiation = 0.0_wp            !< time since last call of radiation code
693
694
695    REAL(wp), DIMENSION(0:0) ::  zenith,         & !< cosine of solar zenith angle
696                                 sun_dir_lat,    & !< solar directional vector in latitudes
697                                 sun_dir_lon       !< solar directional vector in longitudes
698
699    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_net_av       !< average of net radiation (rad_net) at surface
700    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_lw_in_xy_av  !< average of incoming longwave radiation at surface
701    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_lw_out_xy_av !< average of outgoing longwave radiation at surface
702    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_sw_in_xy_av  !< average of incoming shortwave radiation at surface
703    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_sw_out_xy_av !< average of outgoing shortwave radiation at surface
704!
705!-- Land surface albedos for solar zenith angle of 60degree after Briegleb (1992)     
706!-- (shortwave, longwave, broadband):   sw,      lw,      bb,
707    REAL(wp), DIMENSION(0:2,1:33), PARAMETER :: albedo_pars = RESHAPE( (/& 
708                                   0.06_wp, 0.06_wp, 0.06_wp,            & !  1
709                                   0.09_wp, 0.28_wp, 0.19_wp,            & !  2
710                                   0.11_wp, 0.33_wp, 0.23_wp,            & !  3
711                                   0.11_wp, 0.33_wp, 0.23_wp,            & !  4
712                                   0.14_wp, 0.34_wp, 0.25_wp,            & !  5
713                                   0.06_wp, 0.22_wp, 0.14_wp,            & !  6
714                                   0.06_wp, 0.27_wp, 0.17_wp,            & !  7
715                                   0.06_wp, 0.31_wp, 0.19_wp,            & !  8
716                                   0.06_wp, 0.22_wp, 0.14_wp,            & !  9
717                                   0.06_wp, 0.28_wp, 0.18_wp,            & ! 10
718                                   0.35_wp, 0.51_wp, 0.43_wp,            & ! 11
719                                   0.24_wp, 0.40_wp, 0.32_wp,            & ! 12
720                                   0.10_wp, 0.27_wp, 0.19_wp,            & ! 13
721                                   0.90_wp, 0.65_wp, 0.77_wp,            & ! 14
722                                   0.90_wp, 0.65_wp, 0.77_wp,            & ! 15
723                                   0.95_wp, 0.70_wp, 0.82_wp,            & ! 16
724                                   0.08_wp, 0.08_wp, 0.08_wp,            & ! 17
725                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 18
726                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 19
727                                   0.30_wp, 0.30_wp, 0.30_wp,            & ! 20
728                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 21
729                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 22
730                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 23
731                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 24
732                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 25
733                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 26
734                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 27
735                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 28
736                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 29
737                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 30
738                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 31
739                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 32
740                                   0.17_wp, 0.17_wp, 0.17_wp             & ! 33
741                                 /), (/ 3, 33 /) )
742
743    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE, TARGET :: &
744                        rad_lw_cs_hr,                  & !< longwave clear sky radiation heating rate (K/s)
745                        rad_lw_cs_hr_av,               & !< average of rad_lw_cs_hr
746                        rad_lw_hr,                     & !< longwave radiation heating rate (K/s)
747                        rad_lw_hr_av,                  & !< average of rad_sw_hr
748                        rad_lw_in,                     & !< incoming longwave radiation (W/m2)
749                        rad_lw_in_av,                  & !< average of rad_lw_in
750                        rad_lw_out,                    & !< outgoing longwave radiation (W/m2)
751                        rad_lw_out_av,                 & !< average of rad_lw_out
752                        rad_sw_cs_hr,                  & !< shortwave clear sky radiation heating rate (K/s)
753                        rad_sw_cs_hr_av,               & !< average of rad_sw_cs_hr
754                        rad_sw_hr,                     & !< shortwave radiation heating rate (K/s)
755                        rad_sw_hr_av,                  & !< average of rad_sw_hr
756                        rad_sw_in,                     & !< incoming shortwave radiation (W/m2)
757                        rad_sw_in_av,                  & !< average of rad_sw_in
758                        rad_sw_out,                    & !< outgoing shortwave radiation (W/m2)
759                        rad_sw_out_av                    !< average of rad_sw_out
760
761
762!
763!-- Variables and parameters used in RRTMG only
764#if defined ( __rrtmg )
765    CHARACTER(LEN=12) :: rrtm_input_file = "RAD_SND_DATA" !< name of the NetCDF input file (sounding data)
766
767
768!
769!-- Flag parameters for RRTMGS (should not be changed)
770    INTEGER(iwp), PARAMETER :: rrtm_idrv     = 1, & !< flag for longwave upward flux calculation option (0,1)
771                               rrtm_inflglw  = 2, & !< flag for lw cloud optical properties (0,1,2)
772                               rrtm_iceflglw = 0, & !< flag for lw ice particle specifications (0,1,2,3)
773                               rrtm_liqflglw = 1, & !< flag for lw liquid droplet specifications
774                               rrtm_inflgsw  = 2, & !< flag for sw cloud optical properties (0,1,2)
775                               rrtm_iceflgsw = 0, & !< flag for sw ice particle specifications (0,1,2,3)
776                               rrtm_liqflgsw = 1    !< flag for sw liquid droplet specifications
777
778!
779!-- The following variables should be only changed with care, as this will
780!-- require further setting of some variables, which is currently not
781!-- implemented (aerosols, ice phase).
782    INTEGER(iwp) :: nzt_rad,           & !< upper vertical limit for radiation calculations
783                    rrtm_icld = 0,     & !< cloud flag (0: clear sky column, 1: cloudy column)
784                    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)
785
786    INTEGER(iwp) :: nc_stat !< local variable for storin the result of netCDF calls for error message handling
787
788    LOGICAL :: snd_exists = .FALSE.      !< flag parameter to check whether a user-defined input files exists
789
790    REAL(wp), PARAMETER :: mol_mass_air_d_wv = 1.607793_wp !< molecular weight dry air / water vapor
791
792    REAL(wp), DIMENSION(:), ALLOCATABLE :: hyp_snd,     & !< hypostatic pressure from sounding data (hPa)
793                                           rrtm_tsfc,   & !< dummy array for storing surface temperature
794                                           t_snd          !< actual temperature from sounding data (hPa)
795
796    REAL(wp), DIMENSION(:,:), ALLOCATABLE :: rrtm_ccl4vmr,   & !< CCL4 volume mixing ratio (g/mol)
797                                             rrtm_cfc11vmr,  & !< CFC11 volume mixing ratio (g/mol)
798                                             rrtm_cfc12vmr,  & !< CFC12 volume mixing ratio (g/mol)
799                                             rrtm_cfc22vmr,  & !< CFC22 volume mixing ratio (g/mol)
800                                             rrtm_ch4vmr,    & !< CH4 volume mixing ratio
801                                             rrtm_cicewp,    & !< in-cloud ice water path (g/m2)
802                                             rrtm_cldfr,     & !< cloud fraction (0,1)
803                                             rrtm_cliqwp,    & !< in-cloud liquid water path (g/m2)
804                                             rrtm_co2vmr,    & !< CO2 volume mixing ratio (g/mol)
805                                             rrtm_emis,      & !< surface emissivity (0-1) 
806                                             rrtm_h2ovmr,    & !< H2O volume mixing ratio
807                                             rrtm_n2ovmr,    & !< N2O volume mixing ratio
808                                             rrtm_o2vmr,     & !< O2 volume mixing ratio
809                                             rrtm_o3vmr,     & !< O3 volume mixing ratio
810                                             rrtm_play,      & !< pressure layers (hPa, zu-grid)
811                                             rrtm_plev,      & !< pressure layers (hPa, zw-grid)
812                                             rrtm_reice,     & !< cloud ice effective radius (microns)
813                                             rrtm_reliq,     & !< cloud water drop effective radius (microns)
814                                             rrtm_tlay,      & !< actual temperature (K, zu-grid)
815                                             rrtm_tlev,      & !< actual temperature (K, zw-grid)
816                                             rrtm_lwdflx,    & !< RRTM output of incoming longwave radiation flux (W/m2)
817                                             rrtm_lwdflxc,   & !< RRTM output of outgoing clear sky longwave radiation flux (W/m2)
818                                             rrtm_lwuflx,    & !< RRTM output of outgoing longwave radiation flux (W/m2)
819                                             rrtm_lwuflxc,   & !< RRTM output of incoming clear sky longwave radiation flux (W/m2)
820                                             rrtm_lwuflx_dt, & !< RRTM output of incoming clear sky longwave radiation flux (W/m2)
821                                             rrtm_lwuflxc_dt,& !< RRTM output of outgoing clear sky longwave radiation flux (W/m2)
822                                             rrtm_lwhr,      & !< RRTM output of longwave radiation heating rate (K/d)
823                                             rrtm_lwhrc,     & !< RRTM output of incoming longwave clear sky radiation heating rate (K/d)
824                                             rrtm_swdflx,    & !< RRTM output of incoming shortwave radiation flux (W/m2)
825                                             rrtm_swdflxc,   & !< RRTM output of outgoing clear sky shortwave radiation flux (W/m2)
826                                             rrtm_swuflx,    & !< RRTM output of outgoing shortwave radiation flux (W/m2)
827                                             rrtm_swuflxc,   & !< RRTM output of incoming clear sky shortwave radiation flux (W/m2)
828                                             rrtm_swhr,      & !< RRTM output of shortwave radiation heating rate (K/d)
829                                             rrtm_swhrc,     & !< RRTM output of incoming shortwave clear sky radiation heating rate (K/d)
830                                             rrtm_dirdflux,  & !< RRTM output of incoming direct shortwave (W/m2)
831                                             rrtm_difdflux     !< RRTM output of incoming diffuse shortwave (W/m2)
832
833    REAL(wp), DIMENSION(1) ::                rrtm_aldif,     & !< surface albedo for longwave diffuse radiation
834                                             rrtm_aldir,     & !< surface albedo for longwave direct radiation
835                                             rrtm_asdif,     & !< surface albedo for shortwave diffuse radiation
836                                             rrtm_asdir        !< surface albedo for shortwave direct radiation
837
838!
839!-- Definition of arrays that are currently not used for calling RRTMG (due to setting of flag parameters)
840    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::  rad_lw_cs_in,   & !< incoming clear sky longwave radiation (W/m2) (not used)
841                                                rad_lw_cs_out,  & !< outgoing clear sky longwave radiation (W/m2) (not used)
842                                                rad_sw_cs_in,   & !< incoming clear sky shortwave radiation (W/m2) (not used)
843                                                rad_sw_cs_out,  & !< outgoing clear sky shortwave radiation (W/m2) (not used)
844                                                rrtm_lw_tauaer, & !< lw aerosol optical depth
845                                                rrtm_lw_taucld, & !< lw in-cloud optical depth
846                                                rrtm_sw_taucld, & !< sw in-cloud optical depth
847                                                rrtm_sw_ssacld, & !< sw in-cloud single scattering albedo
848                                                rrtm_sw_asmcld, & !< sw in-cloud asymmetry parameter
849                                                rrtm_sw_fsfcld, & !< sw in-cloud forward scattering fraction
850                                                rrtm_sw_tauaer, & !< sw aerosol optical depth
851                                                rrtm_sw_ssaaer, & !< sw aerosol single scattering albedo
852                                                rrtm_sw_asmaer, & !< sw aerosol asymmetry parameter
853                                                rrtm_sw_ecaer     !< sw aerosol optical detph at 0.55 microns (rrtm_iaer = 6 only)
854
855#endif
856!
857!-- Parameters of urban and land surface models
858    INTEGER(iwp)                                   ::  nzu                                !< number of layers of urban surface (will be calculated)
859    INTEGER(iwp)                                   ::  nzp                                !< number of layers of plant canopy (will be calculated)
860    INTEGER(iwp)                                   ::  nzub,nzut                          !< bottom and top layer of urban surface (will be calculated)
861    INTEGER(iwp)                                   ::  nzpt                               !< top layer of plant canopy (will be calculated)
862!-- parameters of urban and land surface models
863    INTEGER(iwp), PARAMETER                        ::  nzut_free = 3                      !< number of free layers above top of of topography
864    INTEGER(iwp), PARAMETER                        ::  ndsvf = 2                          !< number of dimensions of real values in SVF
865    INTEGER(iwp), PARAMETER                        ::  idsvf = 2                          !< number of dimensions of integer values in SVF
866    INTEGER(iwp), PARAMETER                        ::  ndcsf = 1                          !< number of dimensions of real values in CSF
867    INTEGER(iwp), PARAMETER                        ::  idcsf = 2                          !< number of dimensions of integer values in CSF
868    INTEGER(iwp), PARAMETER                        ::  kdcsf = 4                          !< number of dimensions of integer values in CSF calculation array
869    INTEGER(iwp), PARAMETER                        ::  id = 1                             !< position of d-index in surfl and surf
870    INTEGER(iwp), PARAMETER                        ::  iz = 2                             !< position of k-index in surfl and surf
871    INTEGER(iwp), PARAMETER                        ::  iy = 3                             !< position of j-index in surfl and surf
872    INTEGER(iwp), PARAMETER                        ::  ix = 4                             !< position of i-index in surfl and surf
873
874    INTEGER(iwp), PARAMETER                        ::  nsurf_type = 10                    !< number of surf types incl. phys.(land+urban) & (atm.,sky,boundary) surfaces - 1
875
876    INTEGER(iwp), PARAMETER                        ::  iup_u    = 0                       !< 0 - index of urban upward surface (ground or roof)
877    INTEGER(iwp), PARAMETER                        ::  idown_u  = 1                       !< 1 - index of urban downward surface (overhanging)
878    INTEGER(iwp), PARAMETER                        ::  inorth_u = 2                       !< 2 - index of urban northward facing wall
879    INTEGER(iwp), PARAMETER                        ::  isouth_u = 3                       !< 3 - index of urban southward facing wall
880    INTEGER(iwp), PARAMETER                        ::  ieast_u  = 4                       !< 4 - index of urban eastward facing wall
881    INTEGER(iwp), PARAMETER                        ::  iwest_u  = 5                       !< 5 - index of urban westward facing wall
882
883    INTEGER(iwp), PARAMETER                        ::  iup_l    = 6                       !< 6 - index of land upward surface (ground or roof)
884    INTEGER(iwp), PARAMETER                        ::  inorth_l = 7                       !< 7 - index of land northward facing wall
885    INTEGER(iwp), PARAMETER                        ::  isouth_l = 8                       !< 8 - index of land southward facing wall
886    INTEGER(iwp), PARAMETER                        ::  ieast_l  = 9                       !< 9 - index of land eastward facing wall
887    INTEGER(iwp), PARAMETER                        ::  iwest_l  = 10                      !< 10- index of land westward facing wall
888
889    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  idir = (/0, 0,0, 0,1,-1,0,0, 0,1,-1/)   !< surface normal direction x indices
890    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  jdir = (/0, 0,1,-1,0, 0,0,1,-1,0, 0/)   !< surface normal direction y indices
891    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  kdir = (/1,-1,0, 0,0, 0,1,0, 0,0, 0/)   !< surface normal direction z indices
892    REAL(wp),     DIMENSION(0:nsurf_type)          :: facearea                            !< area of single face in respective
893                                                                                          !< direction (will be calc'd)
894
895
896!-- indices and sizes of urban and land surface models
897    INTEGER(iwp)                                   ::  startland        !< start index of block of land and roof surfaces
898    INTEGER(iwp)                                   ::  endland          !< end index of block of land and roof surfaces
899    INTEGER(iwp)                                   ::  nlands           !< number of land and roof surfaces in local processor
900    INTEGER(iwp)                                   ::  startwall        !< start index of block of wall surfaces
901    INTEGER(iwp)                                   ::  endwall          !< end index of block of wall surfaces
902    INTEGER(iwp)                                   ::  nwalls           !< number of wall surfaces in local processor
903
904!-- indices needed for RTM netcdf output subroutines
905    INTEGER(iwp), PARAMETER                        :: nd = 5
906    CHARACTER(LEN=6), DIMENSION(0:nd-1), PARAMETER :: dirname = (/ '_roof ', '_south', '_north', '_west ', '_east ' /)
907    INTEGER(iwp), DIMENSION(0:nd-1), PARAMETER     :: dirint_u = (/ iup_u, isouth_u, inorth_u, iwest_u, ieast_u /)
908    INTEGER(iwp), DIMENSION(0:nd-1), PARAMETER     :: dirint_l = (/ iup_l, isouth_l, inorth_l, iwest_l, ieast_l /)
909    INTEGER(iwp), DIMENSION(0:nd-1)                :: dirstart
910    INTEGER(iwp), DIMENSION(0:nd-1)                :: dirend
911
912!-- indices and sizes of urban and land surface models
913    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surfl_l          !< coordinates of i-th local surface in local grid - surfl[:,k] = [d, z, y, x]
914    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surf_l           !< coordinates of i-th surface in grid - surf[:,k] = [d, z, y, x]
915    INTEGER(iwp), DIMENSION(:,:), POINTER          ::  surfl            !< coordinates of i-th local surface in local grid - surfl[:,k] = [d, z, y, x]
916    INTEGER(iwp), DIMENSION(:,:), POINTER          ::  surf             !< coordinates of i-th surface in grid - surf[:,k] = [d, z, y, x]
917    INTEGER(iwp)                                   ::  nsurfl           !< number of all surfaces in local processor
918    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  nsurfs           !< array of number of all surfaces in individual processors
919    INTEGER(iwp)                                   ::  nsurf            !< global number of surfaces in index array of surfaces (nsurf = proc nsurfs)
920    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surfstart        !< starts of blocks of surfaces for individual processors in array surf (indexed from 1)
921                                                                        !< respective block for particular processor is surfstart[iproc+1]+1 : surfstart[iproc+1]+nsurfs[iproc+1]
922
923!-- block variables needed for calculation of the plant canopy model inside the urban surface model
924    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pct              !< top layer of the plant canopy
925    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pch              !< heights of the plant canopy
926    INTEGER(iwp)                                   ::  npcbl = 0        !< number of the plant canopy gridboxes in local processor
927    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pcbl             !< k,j,i coordinates of l-th local plant canopy box pcbl[:,l] = [k, j, i]
928    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinsw          !< array of absorbed sw radiation for local plant canopy box
929    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdir       !< array of absorbed direct sw radiation for local plant canopy box
930    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdif       !< array of absorbed diffusion sw radiation for local plant canopy box
931    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinlw          !< array of absorbed lw radiation for local plant canopy box
932
933!-- configuration parameters (they can be setup in PALM config)
934    LOGICAL                                        ::  raytrace_mpi_rma = .TRUE.          !< use MPI RMA to access LAD and gridsurf from remote processes during raytracing
935    LOGICAL                                        ::  rad_angular_discretization = .TRUE.!< whether to use fixed resolution discretization of view factors for
936                                                                                          !< reflected radiation (as opposed to all mutually visible pairs)
937    LOGICAL                                        ::  plant_lw_interact = .TRUE.         !< whether plant canopy interacts with LW radiation (in addition to SW)
938    INTEGER(iwp)                                   ::  mrt_nlevels = 0                    !< number of vertical boxes above surface for which to calculate MRT
939    LOGICAL                                        ::  mrt_skip_roof = .TRUE.             !< do not calculate MRT above roof surfaces
940    LOGICAL                                        ::  mrt_include_sw = .TRUE.            !< should MRT calculation include SW radiation as well?
941    LOGICAL                                        ::  mrt_geom_human = .TRUE.            !< MRT direction weights simulate human body instead of a sphere
942    INTEGER(iwp)                                   ::  nrefsteps = 3                      !< number of reflection steps to perform
943    REAL(wp), PARAMETER                            ::  ext_coef = 0.6_wp                  !< extinction coefficient (a.k.a. alpha)
944    INTEGER(iwp), PARAMETER                        ::  rad_version_len = 10               !< length of identification string of rad version
945    CHARACTER(rad_version_len), PARAMETER          ::  rad_version = 'RAD v. 3.0'         !< identification of version of binary svf and restart files
946    INTEGER(iwp)                                   ::  raytrace_discrete_elevs = 40       !< number of discretization steps for elevation (nadir to zenith)
947    INTEGER(iwp)                                   ::  raytrace_discrete_azims = 80       !< number of discretization steps for azimuth (out of 360 degrees)
948    REAL(wp)                                       ::  max_raytracing_dist = -999.0_wp    !< maximum distance for raytracing (in metres)
949    REAL(wp)                                       ::  min_irrf_value = 1e-6_wp           !< minimum potential irradiance factor value for raytracing
950    REAL(wp), DIMENSION(1:30)                      ::  svfnorm_report_thresh = 1e21_wp    !< thresholds of SVF normalization values to report
951    INTEGER(iwp)                                   ::  svfnorm_report_num                 !< number of SVF normalization thresholds to report
952
953!-- radiation related arrays to be used in radiation_interaction routine
954    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_sw_in_dir    !< direct sw radiation
955    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_sw_in_diff   !< diffusion sw radiation
956    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_lw_in_diff   !< diffusion lw radiation
957
958!-- parameters required for RRTMG lower boundary condition
959    REAL(wp)                   :: albedo_urb      !< albedo value retuned to RRTMG boundary cond.
960    REAL(wp)                   :: emissivity_urb  !< emissivity value retuned to RRTMG boundary cond.
961    REAL(wp)                   :: t_rad_urb       !< temperature value retuned to RRTMG boundary cond.
962
963!-- type for calculation of svf
964    TYPE t_svf
965        INTEGER(iwp)                               :: isurflt           !<
966        INTEGER(iwp)                               :: isurfs            !<
967        REAL(wp)                                   :: rsvf              !<
968        REAL(wp)                                   :: rtransp           !<
969    END TYPE
970
971!-- type for calculation of csf
972    TYPE t_csf
973        INTEGER(iwp)                               :: ip                !<
974        INTEGER(iwp)                               :: itx               !<
975        INTEGER(iwp)                               :: ity               !<
976        INTEGER(iwp)                               :: itz               !<
977        INTEGER(iwp)                               :: isurfs            !< Idx of source face / -1 for sky
978        REAL(wp)                                   :: rcvf              !< Canopy view factor for faces /
979                                                                        !< canopy sink factor for sky (-1)
980    END TYPE
981
982!-- arrays storing the values of USM
983    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  svfsurf          !< svfsurf[:,isvf] = index of target and source surface for svf[isvf]
984    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  svf              !< array of shape view factors+direct irradiation factors for local surfaces
985    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfins          !< array of sw radiation falling to local surface after i-th reflection
986    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinl          !< array of lw radiation for local surface after i-th reflection
987
988    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  skyvf            !< array of sky view factor for each local surface
989    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  skyvft           !< array of sky view factor including transparency for each local surface
990    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsitrans         !< dsidir[isvfl,i] = path transmittance of i-th
991                                                                        !< direction of direct solar irradiance per target surface
992    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsitransc        !< dtto per plant canopy box
993    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsidir           !< dsidir[:,i] = unit vector of i-th
994                                                                        !< direction of direct solar irradiance
995    INTEGER(iwp)                                   ::  ndsidir          !< number of apparent solar directions used
996    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  dsidir_rev       !< dsidir_rev[ielev,iazim] = i for dsidir or -1 if not present
997
998    INTEGER(iwp)                                   ::  nmrtbl           !< No. of local grid boxes for which MRT is calculated
999    INTEGER(iwp)                                   ::  nmrtf            !< number of MRT factors for local processor
1000    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  mrtbl            !< coordinates of i-th local MRT box - surfl[:,i] = [z, y, x]
1001    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  mrtfsurf         !< mrtfsurf[:,imrtf] = index of target MRT box and source surface for mrtf[imrtf]
1002    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtf             !< array of MRT factors for each local MRT box
1003    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtft            !< array of MRT factors including transparency for each local MRT box
1004    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtsky           !< array of sky view factor for each local MRT box
1005    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtskyt          !< array of sky view factor including transparency for each local MRT box
1006    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  mrtdsit          !< array of direct solar transparencies for each local MRT box
1007    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinsw          !< mean SW radiant flux for each MRT box
1008    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinlw          !< mean LW radiant flux for each MRT box
1009    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrt              !< mean radiant temperature for each MRT box
1010    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinsw_av       !< time average mean SW radiant flux for each MRT box
1011    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinlw_av       !< time average mean LW radiant flux for each MRT box
1012    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrt_av           !< time average mean radiant temperature for each MRT box
1013
1014    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinsw         !< array of sw radiation falling to local surface including radiation from reflections
1015    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlw         !< array of lw radiation falling to local surface including radiation from reflections
1016    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdir      !< array of direct sw radiation falling to local surface
1017    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdif      !< array of diffuse sw radiation from sky and model boundary falling to local surface
1018    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwdif      !< array of diffuse lw radiation from sky and model boundary falling to local surface
1019   
1020                                                                        !< Outward radiation is only valid for nonvirtual surfaces
1021    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsl        !< array of reflected sw radiation for local surface in i-th reflection
1022    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutll        !< array of reflected + emitted lw radiation for local surface in i-th reflection
1023    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfouts         !< array of reflected sw radiation for all surfaces in i-th reflection
1024    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutl         !< array of reflected + emitted lw radiation for all surfaces in i-th reflection
1025    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlg         !< global array of incoming lw radiation from plant canopy
1026    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsw        !< array of total sw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1027    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutlw        !< array of total lw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1028    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfemitlwl      !< array of emitted lw radiation for local surface used to calculate effective surface temperature for radiation model
1029
1030!-- block variables needed for calculation of the plant canopy model inside the urban surface model
1031    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  csfsurf          !< csfsurf[:,icsf] = index of target surface and csf grid index for csf[icsf]
1032    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  csf              !< array of plant canopy sink fators + direct irradiation factors (transparency)
1033    REAL(wp), DIMENSION(:,:,:), POINTER            ::  sub_lad          !< subset of lad_s within urban surface, transformed to plain Z coordinate
1034    REAL(wp), DIMENSION(:), POINTER                ::  sub_lad_g        !< sub_lad globalized (used to avoid MPI RMA calls in raytracing)
1035    REAL(wp)                                       ::  prototype_lad    !< prototype leaf area density for computing effective optical depth
1036    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  nzterr, plantt   !< temporary global arrays for raytracing
1037    INTEGER(iwp)                                   ::  plantt_max
1038
1039!-- arrays and variables for calculation of svf and csf
1040    TYPE(t_svf), DIMENSION(:), POINTER             ::  asvf             !< pointer to growing svc array
1041    TYPE(t_csf), DIMENSION(:), POINTER             ::  acsf             !< pointer to growing csf array
1042    TYPE(t_svf), DIMENSION(:), POINTER             ::  amrtf            !< pointer to growing mrtf array
1043    TYPE(t_svf), DIMENSION(:), ALLOCATABLE, TARGET ::  asvf1, asvf2     !< realizations of svf array
1044    TYPE(t_csf), DIMENSION(:), ALLOCATABLE, TARGET ::  acsf1, acsf2     !< realizations of csf array
1045    TYPE(t_svf), DIMENSION(:), ALLOCATABLE, TARGET ::  amrtf1, amrtf2   !< realizations of mftf array
1046    INTEGER(iwp)                                   ::  nsvfla           !< dimmension of array allocated for storage of svf in local processor
1047    INTEGER(iwp)                                   ::  ncsfla           !< dimmension of array allocated for storage of csf in local processor
1048    INTEGER(iwp)                                   ::  nmrtfa           !< dimmension of array allocated for storage of mrt
1049    INTEGER(iwp)                                   ::  msvf, mcsf, mmrtf!< mod for swapping the growing array
1050    INTEGER(iwp), PARAMETER                        ::  gasize = 100000  !< initial size of growing arrays
1051    REAL(wp), PARAMETER                            ::  grow_factor = 1.4_wp !< growth factor of growing arrays
1052    INTEGER(iwp)                                   ::  nsvfl            !< number of svf for local processor
1053    INTEGER(iwp)                                   ::  ncsfl            !< no. of csf in local processor
1054                                                                        !< needed only during calc_svf but must be here because it is
1055                                                                        !< shared between subroutines calc_svf and raytrace
1056    INTEGER(iwp), DIMENSION(:,:,:,:), POINTER      ::  gridsurf         !< reverse index of local surfl[d,k,j,i] (for case rad_angular_discretization)
1057    INTEGER(iwp), DIMENSION(:,:,:), ALLOCATABLE    ::  gridpcbl         !< reverse index of local pcbl[k,j,i]
1058    INTEGER(iwp), PARAMETER                        ::  nsurf_type_u = 6 !< number of urban surf types (used in gridsurf)
1059
1060!-- temporary arrays for calculation of csf in raytracing
1061    INTEGER(iwp)                                   ::  maxboxesg        !< max number of boxes ray can cross in the domain
1062    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  boxes            !< coordinates of gridboxes being crossed by ray
1063    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  crlens           !< array of crossing lengths of ray for particular grid boxes
1064    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  lad_ip           !< array of numbers of process where lad is stored
1065#if defined( __parallel )
1066    INTEGER(kind=MPI_ADDRESS_KIND), &
1067                  DIMENSION(:), ALLOCATABLE        ::  lad_disp         !< array of displaycements of lad in local array of proc lad_ip
1068    INTEGER(iwp)                                   ::  win_lad          !< MPI RMA window for leaf area density
1069    INTEGER(iwp)                                   ::  win_gridsurf     !< MPI RMA window for reverse grid surface index
1070#endif
1071    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  lad_s_ray        !< array of received lad_s for appropriate gridboxes crossed by ray
1072    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  target_surfl
1073    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  rt2_track
1074    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rt2_track_lad
1075    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  rt2_track_dist
1076    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  rt2_dist
1077
1078!-- arrays for time averages
1079    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfradnet_av    !< average of net radiation to local surface including radiation from reflections
1080    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinsw_av      !< average of sw radiation falling to local surface including radiation from reflections
1081    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlw_av      !< average of lw radiation falling to local surface including radiation from reflections
1082    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdir_av   !< average of direct sw radiation falling to local surface
1083    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdif_av   !< average of diffuse sw radiation from sky and model boundary falling to local surface
1084    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwdif_av   !< average of diffuse lw radiation from sky and model boundary falling to local surface
1085    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswref_av   !< average of sw radiation falling to surface from reflections
1086    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwref_av   !< average of lw radiation falling to surface from reflections
1087    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsw_av     !< average of total sw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1088    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutlw_av     !< average of total lw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1089    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfins_av       !< average of array of residua of sw radiation absorbed in surface after last reflection
1090    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinl_av       !< average of array of residua of lw radiation absorbed in surface after last reflection
1091    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinlw_av       !< Average of pcbinlw
1092    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinsw_av       !< Average of pcbinsw
1093    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdir_av    !< Average of pcbinswdir
1094    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdif_av    !< Average of pcbinswdif
1095    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswref_av    !< Average of pcbinswref
1096
1097
1098!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1099!-- Energy balance variables
1100!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1101!-- parameters of the land, roof and wall surfaces
1102    REAL(wp), DIMENSION(:), ALLOCATABLE            :: albedo_surf        !< albedo of the surface
1103    REAL(wp), DIMENSION(:), ALLOCATABLE            :: emiss_surf         !< emissivity of the wall surface
1104
1105
1106    INTERFACE radiation_check_data_output
1107       MODULE PROCEDURE radiation_check_data_output
1108    END INTERFACE radiation_check_data_output
1109
1110    INTERFACE radiation_check_data_output_pr
1111       MODULE PROCEDURE radiation_check_data_output_pr
1112    END INTERFACE radiation_check_data_output_pr
1113 
1114    INTERFACE radiation_check_parameters
1115       MODULE PROCEDURE radiation_check_parameters
1116    END INTERFACE radiation_check_parameters
1117 
1118    INTERFACE radiation_clearsky
1119       MODULE PROCEDURE radiation_clearsky
1120    END INTERFACE radiation_clearsky
1121 
1122    INTERFACE radiation_constant
1123       MODULE PROCEDURE radiation_constant
1124    END INTERFACE radiation_constant
1125 
1126    INTERFACE radiation_control
1127       MODULE PROCEDURE radiation_control
1128    END INTERFACE radiation_control
1129
1130    INTERFACE radiation_3d_data_averaging
1131       MODULE PROCEDURE radiation_3d_data_averaging
1132    END INTERFACE radiation_3d_data_averaging
1133
1134    INTERFACE radiation_data_output_2d
1135       MODULE PROCEDURE radiation_data_output_2d
1136    END INTERFACE radiation_data_output_2d
1137
1138    INTERFACE radiation_data_output_3d
1139       MODULE PROCEDURE radiation_data_output_3d
1140    END INTERFACE radiation_data_output_3d
1141
1142    INTERFACE radiation_data_output_mask
1143       MODULE PROCEDURE radiation_data_output_mask
1144    END INTERFACE radiation_data_output_mask
1145
1146    INTERFACE radiation_define_netcdf_grid
1147       MODULE PROCEDURE radiation_define_netcdf_grid
1148    END INTERFACE radiation_define_netcdf_grid
1149
1150    INTERFACE radiation_header
1151       MODULE PROCEDURE radiation_header
1152    END INTERFACE radiation_header 
1153 
1154    INTERFACE radiation_init
1155       MODULE PROCEDURE radiation_init
1156    END INTERFACE radiation_init
1157
1158    INTERFACE radiation_parin
1159       MODULE PROCEDURE radiation_parin
1160    END INTERFACE radiation_parin
1161   
1162    INTERFACE radiation_rrtmg
1163       MODULE PROCEDURE radiation_rrtmg
1164    END INTERFACE radiation_rrtmg
1165
1166    INTERFACE radiation_tendency
1167       MODULE PROCEDURE radiation_tendency
1168       MODULE PROCEDURE radiation_tendency_ij
1169    END INTERFACE radiation_tendency
1170
1171    INTERFACE radiation_rrd_local
1172       MODULE PROCEDURE radiation_rrd_local
1173    END INTERFACE radiation_rrd_local
1174
1175    INTERFACE radiation_wrd_local
1176       MODULE PROCEDURE radiation_wrd_local
1177    END INTERFACE radiation_wrd_local
1178
1179    INTERFACE radiation_interaction
1180       MODULE PROCEDURE radiation_interaction
1181    END INTERFACE radiation_interaction
1182
1183    INTERFACE radiation_interaction_init
1184       MODULE PROCEDURE radiation_interaction_init
1185    END INTERFACE radiation_interaction_init
1186 
1187    INTERFACE radiation_presimulate_solar_pos
1188       MODULE PROCEDURE radiation_presimulate_solar_pos
1189    END INTERFACE radiation_presimulate_solar_pos
1190
1191    INTERFACE radiation_radflux_gridbox
1192       MODULE PROCEDURE radiation_radflux_gridbox
1193    END INTERFACE radiation_radflux_gridbox
1194
1195    INTERFACE radiation_calc_svf
1196       MODULE PROCEDURE radiation_calc_svf
1197    END INTERFACE radiation_calc_svf
1198
1199    INTERFACE radiation_write_svf
1200       MODULE PROCEDURE radiation_write_svf
1201    END INTERFACE radiation_write_svf
1202
1203    INTERFACE radiation_read_svf
1204       MODULE PROCEDURE radiation_read_svf
1205    END INTERFACE radiation_read_svf
1206
1207
1208    SAVE
1209
1210    PRIVATE
1211
1212!
1213!-- Public functions / NEEDS SORTING
1214    PUBLIC radiation_check_data_output, radiation_check_data_output_pr,        &
1215           radiation_check_parameters, radiation_control,                      &
1216           radiation_header, radiation_init, radiation_parin,                  &
1217           radiation_3d_data_averaging, radiation_tendency,                    &
1218           radiation_data_output_2d, radiation_data_output_3d,                 &
1219           radiation_define_netcdf_grid, radiation_wrd_local,                  &
1220           radiation_rrd_local, radiation_data_output_mask,                    &
1221           radiation_radflux_gridbox, radiation_calc_svf, radiation_write_svf, &
1222           radiation_interaction, radiation_interaction_init,                  &
1223           radiation_read_svf, radiation_presimulate_solar_pos
1224           
1225
1226   
1227!
1228!-- Public variables and constants / NEEDS SORTING
1229    PUBLIC albedo, albedo_type, decl_1, decl_2, decl_3, dots_rad, dt_radiation,&
1230           emissivity, force_radiation_call, lat, lon, mrt_geom_human,         &
1231           mrt_include_sw, mrt_nlevels, mrtbl, mrtinsw, mrtinlw, nmrtbl,       &
1232           rad_net_av, radiation, radiation_scheme, rad_lw_in,                 &
1233           rad_lw_in_av, rad_lw_out, rad_lw_out_av,                            &
1234           rad_lw_cs_hr, rad_lw_cs_hr_av, rad_lw_hr, rad_lw_hr_av, rad_sw_in,  &
1235           rad_sw_in_av, rad_sw_out, rad_sw_out_av, rad_sw_cs_hr,              &
1236           rad_sw_cs_hr_av, rad_sw_hr, rad_sw_hr_av, sigma_sb, solar_constant, &
1237           skip_time_do_radiation, time_radiation, unscheduled_radiation_calls,&
1238           zenith, calc_zenith, sun_direction, sun_dir_lat, sun_dir_lon,       &
1239           idir, jdir, kdir, id, iz, iy, ix,                                   &
1240           iup_u, inorth_u, isouth_u, ieast_u, iwest_u,                        &
1241           iup_l, inorth_l, isouth_l, ieast_l, iwest_l,                        &
1242           nsurf_type, nzub, nzut, nzu, pch, nsurf,                            &
1243           idsvf, ndsvf, idcsf, ndcsf, kdcsf, pct,                             &
1244           radiation_interactions, startwall, startland, endland, endwall,     &
1245           skyvf, skyvft, radiation_interactions_on, average_radiation
1246
1247
1248#if defined ( __rrtmg )
1249    PUBLIC rrtm_aldif, rrtm_aldir, rrtm_asdif, rrtm_asdir
1250#endif
1251
1252 CONTAINS
1253
1254
1255!------------------------------------------------------------------------------!
1256! Description:
1257! ------------
1258!> This subroutine controls the calls of the radiation schemes
1259!------------------------------------------------------------------------------!
1260    SUBROUTINE radiation_control
1261 
1262 
1263       IMPLICIT NONE
1264
1265
1266       SELECT CASE ( TRIM( radiation_scheme ) )
1267
1268          CASE ( 'constant' )
1269             CALL radiation_constant
1270         
1271          CASE ( 'clear-sky' ) 
1272             CALL radiation_clearsky
1273       
1274          CASE ( 'rrtmg' )
1275             CALL radiation_rrtmg
1276
1277          CASE DEFAULT
1278
1279       END SELECT
1280
1281
1282    END SUBROUTINE radiation_control
1283
1284!------------------------------------------------------------------------------!
1285! Description:
1286! ------------
1287!> Check data output for radiation model
1288!------------------------------------------------------------------------------!
1289    SUBROUTINE radiation_check_data_output( variable, unit, i, ilen, k )
1290 
1291 
1292       USE control_parameters,                                                 &
1293           ONLY: data_output, message_string
1294
1295       IMPLICIT NONE
1296
1297       CHARACTER (LEN=*) ::  unit          !<
1298       CHARACTER (LEN=*) ::  variable      !<
1299
1300       INTEGER(iwp) :: i, j, k, l
1301       INTEGER(iwp) :: ilen
1302       CHARACTER(LEN=varnamelength) :: var          !< TRIM(variable)
1303
1304       var = TRIM(variable)
1305
1306!--    first process diractional variables
1307       IF ( var(1:12) == 'rtm_rad_net_'  .OR.  var(1:13) == 'rtm_rad_insw_'  .OR.        &
1308            var(1:13) == 'rtm_rad_inlw_'  .OR.  var(1:16) == 'rtm_rad_inswdir_'  .OR.    &
1309            var(1:16) == 'rtm_rad_inswdif_'  .OR.  var(1:16) == 'rtm_rad_inswref_'  .OR. &
1310            var(1:16) == 'rtm_rad_inlwdif_'  .OR.  var(1:16) == 'rtm_rad_inlwref_'  .OR. &
1311            var(1:14) == 'rtm_rad_outsw_'  .OR.  var(1:14) == 'rtm_rad_outlw_'  .OR.     &
1312            var(1:14) == 'rtm_rad_ressw_'  .OR.  var(1:14) == 'rtm_rad_reslw_'  ) THEN
1313          IF ( .NOT.  radiation ) THEN
1314                message_string = 'output of "' // TRIM( var ) // '" require'&
1315                                 // 's radiation = .TRUE.'
1316                CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1317          ENDIF
1318          unit = 'W/m2'
1319       ELSE IF ( var(1:7) == 'rtm_svf'  .OR.  var(1:7) == 'rtm_dif'  .OR.                &
1320                 var(1:9) == 'rtm_skyvf' .OR. var(1:9) == 'rtm_skyvft' )  THEN
1321          IF ( .NOT.  radiation ) THEN
1322                message_string = 'output of "' // TRIM( var ) // '" require'&
1323                                 // 's radiation = .TRUE.'
1324                CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1325          ENDIF
1326          unit = '1'
1327       ELSE
1328!--       non-directional variables
1329          SELECT CASE ( TRIM( var ) )
1330             CASE ( 'rad_lw_cs_hr', 'rad_lw_hr', 'rad_lw_in', 'rad_lw_out', &
1331                    'rad_sw_cs_hr', 'rad_sw_hr', 'rad_sw_in', 'rad_sw_out'  )
1332                IF (  .NOT.  radiation  .OR.  radiation_scheme /= 'rrtmg' )  THEN
1333                   message_string = '"output of "' // TRIM( var ) // '" requi' // &
1334                                    'res radiation = .TRUE. and ' //              &
1335                                    'radiation_scheme = "rrtmg"'
1336                   CALL message( 'check_parameters', 'PA0406', 1, 2, 0, 6, 0 )
1337                ENDIF
1338                unit = 'K/h'
1339
1340             CASE ( 'rad_net*', 'rrtm_aldif*', 'rrtm_aldir*', 'rrtm_asdif*',      &
1341                    'rrtm_asdir*', 'rad_lw_in*', 'rad_lw_out*', 'rad_sw_in*',     &
1342                    'rad_sw_out*')
1343                IF ( i == 0 .AND. ilen == 0 .AND. k == 0)  THEN
1344                   ! Workaround for masked output (calls with i=ilen=k=0)
1345                   unit = 'illegal'
1346                   RETURN
1347                ENDIF
1348                IF ( k == 0  .OR.  data_output(i)(ilen-2:ilen) /= '_xy' )  THEN
1349                   message_string = 'illegal value for data_output: "' //         &
1350                                    TRIM( var ) // '" & only 2d-horizontal ' //   &
1351                                    'cross sections are allowed for this value'
1352                   CALL message( 'check_parameters', 'PA0111', 1, 2, 0, 6, 0 )
1353                ENDIF
1354                IF (  .NOT.  radiation  .OR.  radiation_scheme /= "rrtmg" )  THEN
1355                   IF ( TRIM( var ) == 'rrtm_aldif*'  .OR.                        &
1356                        TRIM( var ) == 'rrtm_aldir*'  .OR.                        &
1357                        TRIM( var ) == 'rrtm_asdif*'  .OR.                        &
1358                        TRIM( var ) == 'rrtm_asdir*'      )                       &
1359                   THEN
1360                      message_string = 'output of "' // TRIM( var ) // '" require'&
1361                                       // 's radiation = .TRUE. and radiation_sch'&
1362                                       // 'eme = "rrtmg"'
1363                      CALL message( 'check_parameters', 'PA0409', 1, 2, 0, 6, 0 )
1364                   ENDIF
1365                ENDIF
1366
1367                IF ( TRIM( var ) == 'rad_net*'      ) unit = 'W/m2'
1368                IF ( TRIM( var ) == 'rad_lw_in*'    ) unit = 'W/m2'
1369                IF ( TRIM( var ) == 'rad_lw_out*'   ) unit = 'W/m2'
1370                IF ( TRIM( var ) == 'rad_sw_in*'    ) unit = 'W/m2'
1371                IF ( TRIM( var ) == 'rad_sw_out*'   ) unit = 'W/m2'
1372                IF ( TRIM( var ) == 'rad_sw_in'     ) unit = 'W/m2'
1373                IF ( TRIM( var ) == 'rrtm_aldif*'   ) unit = ''
1374                IF ( TRIM( var ) == 'rrtm_aldir*'   ) unit = ''
1375                IF ( TRIM( var ) == 'rrtm_asdif*'   ) unit = ''
1376                IF ( TRIM( var ) == 'rrtm_asdir*'   ) unit = ''
1377
1378             CASE ( 'rtm_rad_pc_inlw', 'rtm_rad_pc_insw', 'rtm_rad_pc_inswdir', &
1379                    'rtm_rad_pc_inswdif', 'rtm_rad_pc_inswref')
1380                IF ( .NOT.  radiation ) THEN
1381                   message_string = 'output of "' // TRIM( var ) // '" require'&
1382                                    // 's radiation = .TRUE.'
1383                   CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1384                ENDIF
1385                unit = 'W'
1386
1387             CASE ( 'rtm_mrt', 'rtm_mrt_sw', 'rtm_mrt_lw'  )
1388                IF ( i == 0 .AND. ilen == 0 .AND. k == 0)  THEN
1389                   ! Workaround for masked output (calls with i=ilen=k=0)
1390                   unit = 'illegal'
1391                   RETURN
1392                ENDIF
1393
1394                IF ( .NOT.  radiation ) THEN
1395                   message_string = 'output of "' // TRIM( var ) // '" require'&
1396                                    // 's radiation = .TRUE.'
1397                   CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1398                ENDIF
1399                IF ( mrt_nlevels == 0 ) THEN
1400                   message_string = 'output of "' // TRIM( var ) // '" require'&
1401                                    // 's mrt_nlevels > 0'
1402                   CALL message( 'check_parameters', 'PA0510', 1, 2, 0, 6, 0 )
1403                ENDIF
1404                IF ( TRIM( var ) == 'rtm_mrt_sw'  .AND.  .NOT. mrt_include_sw ) THEN
1405                   message_string = 'output of "' // TRIM( var ) // '" require'&
1406                                    // 's rtm_mrt_sw = .TRUE.'
1407                   CALL message( 'check_parameters', 'PA0511', 1, 2, 0, 6, 0 )
1408                ENDIF
1409                IF ( TRIM( var ) == 'rtm_mrt' ) THEN
1410                   unit = 'K'
1411                ELSE
1412                   unit = 'W m-2'
1413                ENDIF
1414
1415             CASE DEFAULT
1416                unit = 'illegal'
1417
1418          END SELECT
1419       ENDIF
1420
1421    END SUBROUTINE radiation_check_data_output
1422
1423!------------------------------------------------------------------------------!
1424! Description:
1425! ------------
1426!> Check data output of profiles for radiation model
1427!------------------------------------------------------------------------------! 
1428    SUBROUTINE radiation_check_data_output_pr( variable, var_count, unit,      &
1429               dopr_unit )
1430 
1431       USE arrays_3d,                                                          &
1432           ONLY: zu
1433
1434       USE control_parameters,                                                 &
1435           ONLY: data_output_pr, message_string
1436
1437       USE indices
1438
1439       USE profil_parameter
1440
1441       USE statistics
1442
1443       IMPLICIT NONE
1444   
1445       CHARACTER (LEN=*) ::  unit      !<
1446       CHARACTER (LEN=*) ::  variable  !<
1447       CHARACTER (LEN=*) ::  dopr_unit !< local value of dopr_unit
1448 
1449       INTEGER(iwp) ::  var_count     !<
1450
1451       SELECT CASE ( TRIM( variable ) )
1452       
1453         CASE ( 'rad_net' )
1454             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme == 'constant' )&
1455             THEN
1456                message_string = 'data_output_pr = ' //                        &
1457                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1458                                 'not available for radiation = .FALSE. or ' //&
1459                                 'radiation_scheme = "constant"'
1460                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1461             ELSE
1462                dopr_index(var_count) = 99
1463                dopr_unit  = 'W/m2'
1464                hom(:,2,99,:)  = SPREAD( zw, 2, statistic_regions+1 )
1465                unit = dopr_unit
1466             ENDIF
1467
1468          CASE ( 'rad_lw_in' )
1469             IF ( (  .NOT.  radiation)  .OR.  radiation_scheme == 'constant' ) &
1470             THEN
1471                message_string = 'data_output_pr = ' //                        &
1472                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1473                                 'not available for radiation = .FALSE. or ' //&
1474                                 'radiation_scheme = "constant"'
1475                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1476             ELSE
1477                dopr_index(var_count) = 100
1478                dopr_unit  = 'W/m2'
1479                hom(:,2,100,:)  = SPREAD( zw, 2, statistic_regions+1 )
1480                unit = dopr_unit 
1481             ENDIF
1482
1483          CASE ( 'rad_lw_out' )
1484             IF ( (  .NOT. radiation )  .OR.  radiation_scheme == 'constant' ) &
1485             THEN
1486                message_string = 'data_output_pr = ' //                        &
1487                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1488                                 'not available for radiation = .FALSE. or ' //&
1489                                 'radiation_scheme = "constant"'
1490                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1491             ELSE
1492                dopr_index(var_count) = 101
1493                dopr_unit  = 'W/m2'
1494                hom(:,2,101,:)  = SPREAD( zw, 2, statistic_regions+1 )
1495                unit = dopr_unit   
1496             ENDIF
1497
1498          CASE ( 'rad_sw_in' )
1499             IF ( (  .NOT. radiation )  .OR.  radiation_scheme == 'constant' ) &
1500             THEN
1501                message_string = 'data_output_pr = ' //                        &
1502                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1503                                 'not available for radiation = .FALSE. or ' //&
1504                                 'radiation_scheme = "constant"'
1505                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1506             ELSE
1507                dopr_index(var_count) = 102
1508                dopr_unit  = 'W/m2'
1509                hom(:,2,102,:)  = SPREAD( zw, 2, statistic_regions+1 )
1510                unit = dopr_unit
1511             ENDIF
1512
1513          CASE ( 'rad_sw_out')
1514             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme == 'constant' )&
1515             THEN
1516                message_string = 'data_output_pr = ' //                        &
1517                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1518                                 'not available for radiation = .FALSE. or ' //&
1519                                 'radiation_scheme = "constant"'
1520                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1521             ELSE
1522                dopr_index(var_count) = 103
1523                dopr_unit  = 'W/m2'
1524                hom(:,2,103,:)  = SPREAD( zw, 2, statistic_regions+1 )
1525                unit = dopr_unit
1526             ENDIF
1527
1528          CASE ( 'rad_lw_cs_hr' )
1529             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
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 /= "rrtmg"'
1535                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1536             ELSE
1537                dopr_index(var_count) = 104
1538                dopr_unit  = 'K/h'
1539                hom(:,2,104,:)  = SPREAD( zu, 2, statistic_regions+1 )
1540                unit = dopr_unit
1541             ENDIF
1542
1543          CASE ( 'rad_lw_hr' )
1544             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
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 /= "rrtmg"'
1550                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1551             ELSE
1552                dopr_index(var_count) = 105
1553                dopr_unit  = 'K/h'
1554                hom(:,2,105,:)  = SPREAD( zu, 2, statistic_regions+1 )
1555                unit = dopr_unit
1556             ENDIF
1557
1558          CASE ( 'rad_sw_cs_hr' )
1559             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
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 /= "rrtmg"'
1565                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1566             ELSE
1567                dopr_index(var_count) = 106
1568                dopr_unit  = 'K/h'
1569                hom(:,2,106,:)  = SPREAD( zu, 2, statistic_regions+1 )
1570                unit = dopr_unit
1571             ENDIF
1572
1573          CASE ( 'rad_sw_hr' )
1574             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
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 /= "rrtmg"'
1580                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1581             ELSE
1582                dopr_index(var_count) = 107
1583                dopr_unit  = 'K/h'
1584                hom(:,2,107,:)  = SPREAD( zu, 2, statistic_regions+1 )
1585                unit = dopr_unit
1586             ENDIF
1587
1588
1589          CASE DEFAULT
1590             unit = 'illegal'
1591
1592       END SELECT
1593
1594
1595    END SUBROUTINE radiation_check_data_output_pr
1596 
1597 
1598!------------------------------------------------------------------------------!
1599! Description:
1600! ------------
1601!> Check parameters routine for radiation model
1602!------------------------------------------------------------------------------!
1603    SUBROUTINE radiation_check_parameters
1604
1605       USE control_parameters,                                                 &
1606           ONLY: land_surface, message_string, urban_surface
1607
1608       USE netcdf_data_input_mod,                                              &
1609           ONLY:  input_pids_static                 
1610   
1611       IMPLICIT NONE
1612       
1613!
1614!--    In case no urban-surface or land-surface model is applied, usage of
1615!--    a radiation model make no sense.         
1616       IF ( .NOT. land_surface  .AND.  .NOT. urban_surface )  THEN
1617          message_string = 'Usage of radiation module is only allowed if ' //  &
1618                           'land-surface and/or urban-surface model is applied.'
1619          CALL message( 'check_parameters', 'PA0486', 1, 2, 0, 6, 0 )
1620       ENDIF
1621
1622       IF ( radiation_scheme /= 'constant'   .AND.                             &
1623            radiation_scheme /= 'clear-sky'  .AND.                             &
1624            radiation_scheme /= 'rrtmg' )  THEN
1625          message_string = 'unknown radiation_scheme = '//                     &
1626                           TRIM( radiation_scheme )
1627          CALL message( 'check_parameters', 'PA0405', 1, 2, 0, 6, 0 )
1628       ELSEIF ( radiation_scheme == 'rrtmg' )  THEN
1629#if ! defined ( __rrtmg )
1630          message_string = 'radiation_scheme = "rrtmg" requires ' //           & 
1631                           'compilation of PALM with pre-processor ' //        &
1632                           'directive -D__rrtmg'
1633          CALL message( 'check_parameters', 'PA0407', 1, 2, 0, 6, 0 )
1634#endif
1635#if defined ( __rrtmg ) && ! defined( __netcdf )
1636          message_string = 'radiation_scheme = "rrtmg" requires ' //           & 
1637                           'the use of NetCDF (preprocessor directive ' //     &
1638                           '-D__netcdf'
1639          CALL message( 'check_parameters', 'PA0412', 1, 2, 0, 6, 0 )
1640#endif
1641
1642       ENDIF
1643!
1644!--    Checks performed only if data is given via namelist only.
1645       IF ( .NOT. input_pids_static )  THEN
1646          IF ( albedo_type == 0  .AND.  albedo == 9999999.9_wp  .AND.          &
1647               radiation_scheme == 'clear-sky')  THEN
1648             message_string = 'radiation_scheme = "clear-sky" in combination'//& 
1649                              'with albedo_type = 0 requires setting of'//     &
1650                              'albedo /= 9999999.9'
1651             CALL message( 'check_parameters', 'PA0410', 1, 2, 0, 6, 0 )
1652          ENDIF
1653
1654          IF ( albedo_type == 0  .AND.  radiation_scheme == 'rrtmg'  .AND.     &
1655             ( albedo_lw_dif == 9999999.9_wp .OR. albedo_lw_dir == 9999999.9_wp&
1656          .OR. albedo_sw_dif == 9999999.9_wp .OR. albedo_sw_dir == 9999999.9_wp& 
1657             ) ) THEN
1658             message_string = 'radiation_scheme = "rrtmg" in combination' //   & 
1659                              'with albedo_type = 0 requires setting of ' //   &
1660                              'albedo_lw_dif /= 9999999.9' //                  &
1661                              'albedo_lw_dir /= 9999999.9' //                  &
1662                              'albedo_sw_dif /= 9999999.9 and' //              &
1663                              'albedo_sw_dir /= 9999999.9'
1664             CALL message( 'check_parameters', 'PA0411', 1, 2, 0, 6, 0 )
1665          ENDIF
1666       ENDIF
1667!
1668!--    Parallel rad_angular_discretization without raytrace_mpi_rma is not implemented
1669#if defined( __parallel )     
1670       IF ( rad_angular_discretization  .AND.  .NOT. raytrace_mpi_rma )  THEN
1671          message_string = 'rad_angular_discretization can only be used ' //  &
1672                           'together with raytrace_mpi_rma or when ' //  &
1673                           'no parallelization is applied.'
1674          CALL message( 'check_parameters', 'PA0486', 1, 2, 0, 6, 0 )
1675       ENDIF
1676#endif
1677
1678       IF ( cloud_droplets  .AND.   radiation_scheme == 'rrtmg'  .AND.         &
1679            average_radiation ) THEN
1680          message_string = 'average_radiation = .T. with radiation_scheme'//   & 
1681                           '= "rrtmg" in combination cloud_droplets = .T.'//   &
1682                           'is not implementd'
1683          CALL message( 'check_parameters', 'PA0560', 1, 2, 0, 6, 0 )
1684       ENDIF
1685
1686!
1687!--    Incialize svf normalization reporting histogram
1688       svfnorm_report_num = 1
1689       DO WHILE ( svfnorm_report_thresh(svfnorm_report_num) < 1e20_wp          &
1690                   .AND. svfnorm_report_num <= 30 )
1691          svfnorm_report_num = svfnorm_report_num + 1
1692       ENDDO
1693       svfnorm_report_num = svfnorm_report_num - 1
1694
1695
1696 
1697    END SUBROUTINE radiation_check_parameters 
1698 
1699 
1700!------------------------------------------------------------------------------!
1701! Description:
1702! ------------
1703!> Initialization of the radiation model
1704!------------------------------------------------------------------------------!
1705    SUBROUTINE radiation_init
1706   
1707       IMPLICIT NONE
1708
1709       INTEGER(iwp) ::  i         !< running index x-direction
1710       INTEGER(iwp) ::  ioff      !< offset in x between surface element reference grid point in atmosphere and actual surface
1711       INTEGER(iwp) ::  j         !< running index y-direction
1712       INTEGER(iwp) ::  joff      !< offset in y between surface element reference grid point in atmosphere and actual surface
1713       INTEGER(iwp) ::  l         !< running index for orientation of vertical surfaces
1714       INTEGER(iwp) ::  m         !< running index for surface elements
1715#if defined( __rrtmg )
1716       INTEGER(iwp) ::  ind_type  !< running index for subgrid-surface tiles
1717#endif
1718
1719!
1720!--    Allocate array for storing the surface net radiation
1721       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_net )  .AND.                      &
1722                  surf_lsm_h%ns > 0  )   THEN
1723          ALLOCATE( surf_lsm_h%rad_net(1:surf_lsm_h%ns) )
1724          surf_lsm_h%rad_net = 0.0_wp 
1725       ENDIF
1726       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_net )  .AND.                      &
1727                  surf_usm_h%ns > 0  )  THEN
1728          ALLOCATE( surf_usm_h%rad_net(1:surf_usm_h%ns) )
1729          surf_usm_h%rad_net = 0.0_wp 
1730       ENDIF
1731       DO  l = 0, 3
1732          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_net )  .AND.                &
1733                     surf_lsm_v(l)%ns > 0  )  THEN
1734             ALLOCATE( surf_lsm_v(l)%rad_net(1:surf_lsm_v(l)%ns) )
1735             surf_lsm_v(l)%rad_net = 0.0_wp 
1736          ENDIF
1737          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_net )  .AND.                &
1738                     surf_usm_v(l)%ns > 0  )  THEN
1739             ALLOCATE( surf_usm_v(l)%rad_net(1:surf_usm_v(l)%ns) )
1740             surf_usm_v(l)%rad_net = 0.0_wp 
1741          ENDIF
1742       ENDDO
1743
1744
1745!
1746!--    Allocate array for storing the surface longwave (out) radiation change
1747       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_lw_out_change_0 )  .AND.          &
1748                  surf_lsm_h%ns > 0  )   THEN
1749          ALLOCATE( surf_lsm_h%rad_lw_out_change_0(1:surf_lsm_h%ns) )
1750          surf_lsm_h%rad_lw_out_change_0 = 0.0_wp 
1751       ENDIF
1752       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_lw_out_change_0 )  .AND.          &
1753                  surf_usm_h%ns > 0  )  THEN
1754          ALLOCATE( surf_usm_h%rad_lw_out_change_0(1:surf_usm_h%ns) )
1755          surf_usm_h%rad_lw_out_change_0 = 0.0_wp 
1756       ENDIF
1757       DO  l = 0, 3
1758          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_lw_out_change_0 )  .AND.    &
1759                     surf_lsm_v(l)%ns > 0  )  THEN
1760             ALLOCATE( surf_lsm_v(l)%rad_lw_out_change_0(1:surf_lsm_v(l)%ns) )
1761             surf_lsm_v(l)%rad_lw_out_change_0 = 0.0_wp 
1762          ENDIF
1763          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_lw_out_change_0 )  .AND.    &
1764                     surf_usm_v(l)%ns > 0  )  THEN
1765             ALLOCATE( surf_usm_v(l)%rad_lw_out_change_0(1:surf_usm_v(l)%ns) )
1766             surf_usm_v(l)%rad_lw_out_change_0 = 0.0_wp 
1767          ENDIF
1768       ENDDO
1769
1770!
1771!--    Allocate surface arrays for incoming/outgoing short/longwave radiation
1772       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_sw_in )  .AND.                    &
1773                  surf_lsm_h%ns > 0  )   THEN
1774          ALLOCATE( surf_lsm_h%rad_sw_in(1:surf_lsm_h%ns)  )
1775          ALLOCATE( surf_lsm_h%rad_sw_out(1:surf_lsm_h%ns) )
1776          ALLOCATE( surf_lsm_h%rad_sw_dir(1:surf_lsm_h%ns) )
1777          ALLOCATE( surf_lsm_h%rad_sw_dif(1:surf_lsm_h%ns) )
1778          ALLOCATE( surf_lsm_h%rad_sw_ref(1:surf_lsm_h%ns) )
1779          ALLOCATE( surf_lsm_h%rad_sw_res(1:surf_lsm_h%ns) )
1780          ALLOCATE( surf_lsm_h%rad_lw_in(1:surf_lsm_h%ns)  )
1781          ALLOCATE( surf_lsm_h%rad_lw_out(1:surf_lsm_h%ns) )
1782          ALLOCATE( surf_lsm_h%rad_lw_dif(1:surf_lsm_h%ns) )
1783          ALLOCATE( surf_lsm_h%rad_lw_ref(1:surf_lsm_h%ns) )
1784          ALLOCATE( surf_lsm_h%rad_lw_res(1:surf_lsm_h%ns) )
1785          surf_lsm_h%rad_sw_in  = 0.0_wp 
1786          surf_lsm_h%rad_sw_out = 0.0_wp 
1787          surf_lsm_h%rad_sw_dir = 0.0_wp 
1788          surf_lsm_h%rad_sw_dif = 0.0_wp 
1789          surf_lsm_h%rad_sw_ref = 0.0_wp 
1790          surf_lsm_h%rad_sw_res = 0.0_wp 
1791          surf_lsm_h%rad_lw_in  = 0.0_wp 
1792          surf_lsm_h%rad_lw_out = 0.0_wp 
1793          surf_lsm_h%rad_lw_dif = 0.0_wp 
1794          surf_lsm_h%rad_lw_ref = 0.0_wp 
1795          surf_lsm_h%rad_lw_res = 0.0_wp 
1796       ENDIF
1797       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_sw_in )  .AND.                    &
1798                  surf_usm_h%ns > 0  )  THEN
1799          ALLOCATE( surf_usm_h%rad_sw_in(1:surf_usm_h%ns)  )
1800          ALLOCATE( surf_usm_h%rad_sw_out(1:surf_usm_h%ns) )
1801          ALLOCATE( surf_usm_h%rad_sw_dir(1:surf_usm_h%ns) )
1802          ALLOCATE( surf_usm_h%rad_sw_dif(1:surf_usm_h%ns) )
1803          ALLOCATE( surf_usm_h%rad_sw_ref(1:surf_usm_h%ns) )
1804          ALLOCATE( surf_usm_h%rad_sw_res(1:surf_usm_h%ns) )
1805          ALLOCATE( surf_usm_h%rad_lw_in(1:surf_usm_h%ns)  )
1806          ALLOCATE( surf_usm_h%rad_lw_out(1:surf_usm_h%ns) )
1807          ALLOCATE( surf_usm_h%rad_lw_dif(1:surf_usm_h%ns) )
1808          ALLOCATE( surf_usm_h%rad_lw_ref(1:surf_usm_h%ns) )
1809          ALLOCATE( surf_usm_h%rad_lw_res(1:surf_usm_h%ns) )
1810          surf_usm_h%rad_sw_in  = 0.0_wp 
1811          surf_usm_h%rad_sw_out = 0.0_wp 
1812          surf_usm_h%rad_sw_dir = 0.0_wp 
1813          surf_usm_h%rad_sw_dif = 0.0_wp 
1814          surf_usm_h%rad_sw_ref = 0.0_wp 
1815          surf_usm_h%rad_sw_res = 0.0_wp 
1816          surf_usm_h%rad_lw_in  = 0.0_wp 
1817          surf_usm_h%rad_lw_out = 0.0_wp 
1818          surf_usm_h%rad_lw_dif = 0.0_wp 
1819          surf_usm_h%rad_lw_ref = 0.0_wp 
1820          surf_usm_h%rad_lw_res = 0.0_wp 
1821       ENDIF
1822       DO  l = 0, 3
1823          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_sw_in )  .AND.              &
1824                     surf_lsm_v(l)%ns > 0  )  THEN
1825             ALLOCATE( surf_lsm_v(l)%rad_sw_in(1:surf_lsm_v(l)%ns)  )
1826             ALLOCATE( surf_lsm_v(l)%rad_sw_out(1:surf_lsm_v(l)%ns) )
1827             ALLOCATE( surf_lsm_v(l)%rad_sw_dir(1:surf_lsm_v(l)%ns) )
1828             ALLOCATE( surf_lsm_v(l)%rad_sw_dif(1:surf_lsm_v(l)%ns) )
1829             ALLOCATE( surf_lsm_v(l)%rad_sw_ref(1:surf_lsm_v(l)%ns) )
1830             ALLOCATE( surf_lsm_v(l)%rad_sw_res(1:surf_lsm_v(l)%ns) )
1831
1832             ALLOCATE( surf_lsm_v(l)%rad_lw_in(1:surf_lsm_v(l)%ns)  )
1833             ALLOCATE( surf_lsm_v(l)%rad_lw_out(1:surf_lsm_v(l)%ns) )
1834             ALLOCATE( surf_lsm_v(l)%rad_lw_dif(1:surf_lsm_v(l)%ns) )
1835             ALLOCATE( surf_lsm_v(l)%rad_lw_ref(1:surf_lsm_v(l)%ns) )
1836             ALLOCATE( surf_lsm_v(l)%rad_lw_res(1:surf_lsm_v(l)%ns) )
1837
1838             surf_lsm_v(l)%rad_sw_in  = 0.0_wp 
1839             surf_lsm_v(l)%rad_sw_out = 0.0_wp
1840             surf_lsm_v(l)%rad_sw_dir = 0.0_wp
1841             surf_lsm_v(l)%rad_sw_dif = 0.0_wp
1842             surf_lsm_v(l)%rad_sw_ref = 0.0_wp
1843             surf_lsm_v(l)%rad_sw_res = 0.0_wp
1844
1845             surf_lsm_v(l)%rad_lw_in  = 0.0_wp 
1846             surf_lsm_v(l)%rad_lw_out = 0.0_wp 
1847             surf_lsm_v(l)%rad_lw_dif = 0.0_wp 
1848             surf_lsm_v(l)%rad_lw_ref = 0.0_wp 
1849             surf_lsm_v(l)%rad_lw_res = 0.0_wp 
1850          ENDIF
1851          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_sw_in )  .AND.              &
1852                     surf_usm_v(l)%ns > 0  )  THEN
1853             ALLOCATE( surf_usm_v(l)%rad_sw_in(1:surf_usm_v(l)%ns)  )
1854             ALLOCATE( surf_usm_v(l)%rad_sw_out(1:surf_usm_v(l)%ns) )
1855             ALLOCATE( surf_usm_v(l)%rad_sw_dir(1:surf_usm_v(l)%ns) )
1856             ALLOCATE( surf_usm_v(l)%rad_sw_dif(1:surf_usm_v(l)%ns) )
1857             ALLOCATE( surf_usm_v(l)%rad_sw_ref(1:surf_usm_v(l)%ns) )
1858             ALLOCATE( surf_usm_v(l)%rad_sw_res(1:surf_usm_v(l)%ns) )
1859             ALLOCATE( surf_usm_v(l)%rad_lw_in(1:surf_usm_v(l)%ns)  )
1860             ALLOCATE( surf_usm_v(l)%rad_lw_out(1:surf_usm_v(l)%ns) )
1861             ALLOCATE( surf_usm_v(l)%rad_lw_dif(1:surf_usm_v(l)%ns) )
1862             ALLOCATE( surf_usm_v(l)%rad_lw_ref(1:surf_usm_v(l)%ns) )
1863             ALLOCATE( surf_usm_v(l)%rad_lw_res(1:surf_usm_v(l)%ns) )
1864             surf_usm_v(l)%rad_sw_in  = 0.0_wp 
1865             surf_usm_v(l)%rad_sw_out = 0.0_wp
1866             surf_usm_v(l)%rad_sw_dir = 0.0_wp
1867             surf_usm_v(l)%rad_sw_dif = 0.0_wp
1868             surf_usm_v(l)%rad_sw_ref = 0.0_wp
1869             surf_usm_v(l)%rad_sw_res = 0.0_wp
1870             surf_usm_v(l)%rad_lw_in  = 0.0_wp 
1871             surf_usm_v(l)%rad_lw_out = 0.0_wp 
1872             surf_usm_v(l)%rad_lw_dif = 0.0_wp 
1873             surf_usm_v(l)%rad_lw_ref = 0.0_wp 
1874             surf_usm_v(l)%rad_lw_res = 0.0_wp 
1875          ENDIF
1876       ENDDO
1877!
1878!--    Fix net radiation in case of radiation_scheme = 'constant'
1879       IF ( radiation_scheme == 'constant' )  THEN
1880          IF ( ALLOCATED( surf_lsm_h%rad_net ) )                               &
1881             surf_lsm_h%rad_net    = net_radiation
1882          IF ( ALLOCATED( surf_usm_h%rad_net ) )                               &
1883             surf_usm_h%rad_net    = net_radiation
1884!
1885!--       Todo: weight with inclination angle
1886          DO  l = 0, 3
1887             IF ( ALLOCATED( surf_lsm_v(l)%rad_net ) )                         &
1888                surf_lsm_v(l)%rad_net = net_radiation
1889             IF ( ALLOCATED( surf_usm_v(l)%rad_net ) )                         &
1890                surf_usm_v(l)%rad_net = net_radiation
1891          ENDDO
1892!          radiation = .FALSE.
1893!
1894!--    Calculate orbital constants
1895       ELSE
1896          decl_1 = SIN(23.45_wp * pi / 180.0_wp)
1897          decl_2 = 2.0_wp * pi / 365.0_wp
1898          decl_3 = decl_2 * 81.0_wp
1899          lat    = latitude * pi / 180.0_wp
1900          lon    = longitude * pi / 180.0_wp
1901       ENDIF
1902
1903       IF ( radiation_scheme == 'clear-sky'  .OR.                              &
1904            radiation_scheme == 'constant')  THEN
1905
1906
1907!
1908!--       Allocate arrays for incoming/outgoing short/longwave radiation
1909          IF ( .NOT. ALLOCATED ( rad_sw_in ) )  THEN
1910             ALLOCATE ( rad_sw_in(0:0,nysg:nyng,nxlg:nxrg) )
1911          ENDIF
1912          IF ( .NOT. ALLOCATED ( rad_sw_out ) )  THEN
1913             ALLOCATE ( rad_sw_out(0:0,nysg:nyng,nxlg:nxrg) )
1914          ENDIF
1915
1916          IF ( .NOT. ALLOCATED ( rad_lw_in ) )  THEN
1917             ALLOCATE ( rad_lw_in(0:0,nysg:nyng,nxlg:nxrg) )
1918          ENDIF
1919          IF ( .NOT. ALLOCATED ( rad_lw_out ) )  THEN
1920             ALLOCATE ( rad_lw_out(0:0,nysg:nyng,nxlg:nxrg) )
1921          ENDIF
1922
1923!
1924!--       Allocate average arrays for incoming/outgoing short/longwave radiation
1925          IF ( .NOT. ALLOCATED ( rad_sw_in_av ) )  THEN
1926             ALLOCATE ( rad_sw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
1927          ENDIF
1928          IF ( .NOT. ALLOCATED ( rad_sw_out_av ) )  THEN
1929             ALLOCATE ( rad_sw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
1930          ENDIF
1931
1932          IF ( .NOT. ALLOCATED ( rad_lw_in_av ) )  THEN
1933             ALLOCATE ( rad_lw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
1934          ENDIF
1935          IF ( .NOT. ALLOCATED ( rad_lw_out_av ) )  THEN
1936             ALLOCATE ( rad_lw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
1937          ENDIF
1938!
1939!--       Allocate arrays for broadband albedo, and level 1 initialization
1940!--       via namelist paramter, unless not already allocated.
1941          IF ( .NOT. ALLOCATED(surf_lsm_h%albedo) )  THEN
1942             ALLOCATE( surf_lsm_h%albedo(0:2,1:surf_lsm_h%ns)     )
1943             surf_lsm_h%albedo    = albedo
1944          ENDIF
1945          IF ( .NOT. ALLOCATED(surf_usm_h%albedo) )  THEN
1946             ALLOCATE( surf_usm_h%albedo(0:2,1:surf_usm_h%ns)     )
1947             surf_usm_h%albedo    = albedo
1948          ENDIF
1949
1950          DO  l = 0, 3
1951             IF ( .NOT. ALLOCATED( surf_lsm_v(l)%albedo ) )  THEN
1952                ALLOCATE( surf_lsm_v(l)%albedo(0:2,1:surf_lsm_v(l)%ns) )
1953                surf_lsm_v(l)%albedo = albedo
1954             ENDIF
1955             IF ( .NOT. ALLOCATED( surf_usm_v(l)%albedo ) )  THEN
1956                ALLOCATE( surf_usm_v(l)%albedo(0:2,1:surf_usm_v(l)%ns) )
1957                surf_usm_v(l)%albedo = albedo
1958             ENDIF
1959          ENDDO
1960!
1961!--       Level 2 initialization of broadband albedo via given albedo_type.
1962!--       Only if albedo_type is non-zero. In case of urban surface and
1963!--       input data is read from ASCII file, albedo_type will be zero, so that
1964!--       albedo won't be overwritten.
1965          DO  m = 1, surf_lsm_h%ns
1966             IF ( surf_lsm_h%albedo_type(ind_veg_wall,m) /= 0 )                &
1967                surf_lsm_h%albedo(ind_veg_wall,m) =                            &
1968                           albedo_pars(2,surf_lsm_h%albedo_type(ind_veg_wall,m))
1969             IF ( surf_lsm_h%albedo_type(ind_pav_green,m) /= 0 )               &
1970                surf_lsm_h%albedo(ind_pav_green,m) =                           &
1971                           albedo_pars(2,surf_lsm_h%albedo_type(ind_pav_green,m))
1972             IF ( surf_lsm_h%albedo_type(ind_wat_win,m) /= 0 )                 &
1973                surf_lsm_h%albedo(ind_wat_win,m) =                             &
1974                           albedo_pars(2,surf_lsm_h%albedo_type(ind_wat_win,m))
1975          ENDDO
1976          DO  m = 1, surf_usm_h%ns
1977             IF ( surf_usm_h%albedo_type(ind_veg_wall,m) /= 0 )                &
1978                surf_usm_h%albedo(ind_veg_wall,m) =                            &
1979                           albedo_pars(2,surf_usm_h%albedo_type(ind_veg_wall,m))
1980             IF ( surf_usm_h%albedo_type(ind_pav_green,m) /= 0 )               &
1981                surf_usm_h%albedo(ind_pav_green,m) =                           &
1982                           albedo_pars(2,surf_usm_h%albedo_type(ind_pav_green,m))
1983             IF ( surf_usm_h%albedo_type(ind_wat_win,m) /= 0 )                 &
1984                surf_usm_h%albedo(ind_wat_win,m) =                             &
1985                           albedo_pars(2,surf_usm_h%albedo_type(ind_wat_win,m))
1986          ENDDO
1987
1988          DO  l = 0, 3
1989             DO  m = 1, surf_lsm_v(l)%ns
1990                IF ( surf_lsm_v(l)%albedo_type(ind_veg_wall,m) /= 0 )          &
1991                   surf_lsm_v(l)%albedo(ind_veg_wall,m) =                      &
1992                        albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_veg_wall,m))
1993                IF ( surf_lsm_v(l)%albedo_type(ind_pav_green,m) /= 0 )         &
1994                   surf_lsm_v(l)%albedo(ind_pav_green,m) =                     &
1995                        albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_pav_green,m))
1996                IF ( surf_lsm_v(l)%albedo_type(ind_wat_win,m) /= 0 )           &
1997                   surf_lsm_v(l)%albedo(ind_wat_win,m) =                       &
1998                        albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_wat_win,m))
1999             ENDDO
2000             DO  m = 1, surf_usm_v(l)%ns
2001                IF ( surf_usm_v(l)%albedo_type(ind_veg_wall,m) /= 0 )          &
2002                   surf_usm_v(l)%albedo(ind_veg_wall,m) =                      &
2003                        albedo_pars(2,surf_usm_v(l)%albedo_type(ind_veg_wall,m))
2004                IF ( surf_usm_v(l)%albedo_type(ind_pav_green,m) /= 0 )         &
2005                   surf_usm_v(l)%albedo(ind_pav_green,m) =                     &
2006                        albedo_pars(2,surf_usm_v(l)%albedo_type(ind_pav_green,m))
2007                IF ( surf_usm_v(l)%albedo_type(ind_wat_win,m) /= 0 )           &
2008                   surf_usm_v(l)%albedo(ind_wat_win,m) =                       &
2009                        albedo_pars(2,surf_usm_v(l)%albedo_type(ind_wat_win,m))
2010             ENDDO
2011          ENDDO
2012
2013!
2014!--       Level 3 initialization at grid points where albedo type is zero.
2015!--       This case, albedo is taken from file. In case of constant radiation
2016!--       or clear sky, only broadband albedo is given.
2017          IF ( albedo_pars_f%from_file )  THEN
2018!
2019!--          Horizontal surfaces
2020             DO  m = 1, surf_lsm_h%ns
2021                i = surf_lsm_h%i(m)
2022                j = surf_lsm_h%j(m)
2023                IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2024                   IF ( surf_lsm_h%albedo_type(ind_veg_wall,m) == 0 )          &
2025                      surf_lsm_h%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2026                   IF ( surf_lsm_h%albedo_type(ind_pav_green,m) == 0 )         &
2027                      surf_lsm_h%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2028                   IF ( surf_lsm_h%albedo_type(ind_wat_win,m) == 0 )           &
2029                      surf_lsm_h%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2030                ENDIF
2031             ENDDO
2032             DO  m = 1, surf_usm_h%ns
2033                i = surf_usm_h%i(m)
2034                j = surf_usm_h%j(m)
2035                IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2036                   IF ( surf_usm_h%albedo_type(ind_veg_wall,m) == 0 )          &
2037                      surf_usm_h%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2038                   IF ( surf_usm_h%albedo_type(ind_pav_green,m) == 0 )         &
2039                      surf_usm_h%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2040                   IF ( surf_usm_h%albedo_type(ind_wat_win,m) == 0 )           &
2041                      surf_usm_h%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2042                ENDIF
2043             ENDDO 
2044!
2045!--          Vertical surfaces           
2046             DO  l = 0, 3
2047
2048                ioff = surf_lsm_v(l)%ioff
2049                joff = surf_lsm_v(l)%joff
2050                DO  m = 1, surf_lsm_v(l)%ns
2051                   i = surf_lsm_v(l)%i(m) + ioff
2052                   j = surf_lsm_v(l)%j(m) + joff
2053                   IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2054                      IF ( surf_lsm_v(l)%albedo_type(ind_veg_wall,m) == 0 )    &
2055                         surf_lsm_v(l)%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2056                      IF ( surf_lsm_v(l)%albedo_type(ind_pav_green,m) == 0 )   &
2057                         surf_lsm_v(l)%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2058                      IF ( surf_lsm_v(l)%albedo_type(ind_wat_win,m) == 0 )     &
2059                         surf_lsm_v(l)%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2060                   ENDIF
2061                ENDDO
2062
2063                ioff = surf_usm_v(l)%ioff
2064                joff = surf_usm_v(l)%joff
2065                DO  m = 1, surf_usm_h%ns
2066                   i = surf_usm_h%i(m) + joff
2067                   j = surf_usm_h%j(m) + joff
2068                   IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2069                      IF ( surf_usm_v(l)%albedo_type(ind_veg_wall,m) == 0 )    &
2070                         surf_usm_v(l)%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2071                      IF ( surf_usm_v(l)%albedo_type(ind_pav_green,m) == 0 )   &
2072                         surf_usm_v(l)%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2073                      IF ( surf_usm_v(l)%albedo_type(ind_wat_win,m) == 0 )     &
2074                         surf_lsm_v(l)%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2075                   ENDIF
2076                ENDDO
2077             ENDDO
2078
2079          ENDIF 
2080!
2081!--    Initialization actions for RRTMG
2082       ELSEIF ( radiation_scheme == 'rrtmg' )  THEN
2083#if defined ( __rrtmg )
2084!
2085!--       Allocate albedos for short/longwave radiation, horizontal surfaces
2086!--       for wall/green/window (USM) or vegetation/pavement/water surfaces
2087!--       (LSM).
2088          ALLOCATE ( surf_lsm_h%aldif(0:2,1:surf_lsm_h%ns)       )
2089          ALLOCATE ( surf_lsm_h%aldir(0:2,1:surf_lsm_h%ns)       )
2090          ALLOCATE ( surf_lsm_h%asdif(0:2,1:surf_lsm_h%ns)       )
2091          ALLOCATE ( surf_lsm_h%asdir(0:2,1:surf_lsm_h%ns)       )
2092          ALLOCATE ( surf_lsm_h%rrtm_aldif(0:2,1:surf_lsm_h%ns)  )
2093          ALLOCATE ( surf_lsm_h%rrtm_aldir(0:2,1:surf_lsm_h%ns)  )
2094          ALLOCATE ( surf_lsm_h%rrtm_asdif(0:2,1:surf_lsm_h%ns)  )
2095          ALLOCATE ( surf_lsm_h%rrtm_asdir(0:2,1:surf_lsm_h%ns)  )
2096
2097          ALLOCATE ( surf_usm_h%aldif(0:2,1:surf_usm_h%ns)       )
2098          ALLOCATE ( surf_usm_h%aldir(0:2,1:surf_usm_h%ns)       )
2099          ALLOCATE ( surf_usm_h%asdif(0:2,1:surf_usm_h%ns)       )
2100          ALLOCATE ( surf_usm_h%asdir(0:2,1:surf_usm_h%ns)       )
2101          ALLOCATE ( surf_usm_h%rrtm_aldif(0:2,1:surf_usm_h%ns)  )
2102          ALLOCATE ( surf_usm_h%rrtm_aldir(0:2,1:surf_usm_h%ns)  )
2103          ALLOCATE ( surf_usm_h%rrtm_asdif(0:2,1:surf_usm_h%ns)  )
2104          ALLOCATE ( surf_usm_h%rrtm_asdir(0:2,1:surf_usm_h%ns)  )
2105
2106!
2107!--       Allocate broadband albedo (temporary for the current radiation
2108!--       implementations)
2109          IF ( .NOT. ALLOCATED(surf_lsm_h%albedo) )                            &
2110             ALLOCATE( surf_lsm_h%albedo(0:2,1:surf_lsm_h%ns)     )
2111          IF ( .NOT. ALLOCATED(surf_usm_h%albedo) )                            &
2112             ALLOCATE( surf_usm_h%albedo(0:2,1:surf_usm_h%ns)     )
2113
2114!
2115!--       Allocate albedos for short/longwave radiation, vertical surfaces
2116          DO  l = 0, 3
2117
2118             ALLOCATE ( surf_lsm_v(l)%aldif(0:2,1:surf_lsm_v(l)%ns)      )
2119             ALLOCATE ( surf_lsm_v(l)%aldir(0:2,1:surf_lsm_v(l)%ns)      )
2120             ALLOCATE ( surf_lsm_v(l)%asdif(0:2,1:surf_lsm_v(l)%ns)      )
2121             ALLOCATE ( surf_lsm_v(l)%asdir(0:2,1:surf_lsm_v(l)%ns)      )
2122
2123             ALLOCATE ( surf_lsm_v(l)%rrtm_aldif(0:2,1:surf_lsm_v(l)%ns) )
2124             ALLOCATE ( surf_lsm_v(l)%rrtm_aldir(0:2,1:surf_lsm_v(l)%ns) )
2125             ALLOCATE ( surf_lsm_v(l)%rrtm_asdif(0:2,1:surf_lsm_v(l)%ns) )
2126             ALLOCATE ( surf_lsm_v(l)%rrtm_asdir(0:2,1:surf_lsm_v(l)%ns) )
2127
2128             ALLOCATE ( surf_usm_v(l)%aldif(0:2,1:surf_usm_v(l)%ns)      )
2129             ALLOCATE ( surf_usm_v(l)%aldir(0:2,1:surf_usm_v(l)%ns)      )
2130             ALLOCATE ( surf_usm_v(l)%asdif(0:2,1:surf_usm_v(l)%ns)      )
2131             ALLOCATE ( surf_usm_v(l)%asdir(0:2,1:surf_usm_v(l)%ns)      )
2132
2133             ALLOCATE ( surf_usm_v(l)%rrtm_aldif(0:2,1:surf_usm_v(l)%ns) )
2134             ALLOCATE ( surf_usm_v(l)%rrtm_aldir(0:2,1:surf_usm_v(l)%ns) )
2135             ALLOCATE ( surf_usm_v(l)%rrtm_asdif(0:2,1:surf_usm_v(l)%ns) )
2136             ALLOCATE ( surf_usm_v(l)%rrtm_asdir(0:2,1:surf_usm_v(l)%ns) )
2137!
2138!--          Allocate broadband albedo (temporary for the current radiation
2139!--          implementations)
2140             IF ( .NOT. ALLOCATED( surf_lsm_v(l)%albedo ) )                    &
2141                ALLOCATE( surf_lsm_v(l)%albedo(0:2,1:surf_lsm_v(l)%ns) )
2142             IF ( .NOT. ALLOCATED( surf_usm_v(l)%albedo ) )                    &
2143                ALLOCATE( surf_usm_v(l)%albedo(0:2,1:surf_usm_v(l)%ns) )
2144
2145          ENDDO
2146!
2147!--       Level 1 initialization of spectral albedos via namelist
2148!--       paramters. Please note, this case all surface tiles are initialized
2149!--       the same.
2150          IF ( surf_lsm_h%ns > 0 )  THEN
2151             surf_lsm_h%aldif  = albedo_lw_dif
2152             surf_lsm_h%aldir  = albedo_lw_dir
2153             surf_lsm_h%asdif  = albedo_sw_dif
2154             surf_lsm_h%asdir  = albedo_sw_dir
2155             surf_lsm_h%albedo = albedo_sw_dif
2156          ENDIF
2157          IF ( surf_usm_h%ns > 0 )  THEN
2158             IF ( surf_usm_h%albedo_from_ascii )  THEN
2159                surf_usm_h%aldif  = surf_usm_h%albedo
2160                surf_usm_h%aldir  = surf_usm_h%albedo
2161                surf_usm_h%asdif  = surf_usm_h%albedo
2162                surf_usm_h%asdir  = surf_usm_h%albedo
2163             ELSE
2164                surf_usm_h%aldif  = albedo_lw_dif
2165                surf_usm_h%aldir  = albedo_lw_dir
2166                surf_usm_h%asdif  = albedo_sw_dif
2167                surf_usm_h%asdir  = albedo_sw_dir
2168                surf_usm_h%albedo = albedo_sw_dif
2169             ENDIF
2170          ENDIF
2171
2172          DO  l = 0, 3
2173
2174             IF ( surf_lsm_v(l)%ns > 0 )  THEN
2175                surf_lsm_v(l)%aldif  = albedo_lw_dif
2176                surf_lsm_v(l)%aldir  = albedo_lw_dir
2177                surf_lsm_v(l)%asdif  = albedo_sw_dif
2178                surf_lsm_v(l)%asdir  = albedo_sw_dir
2179                surf_lsm_v(l)%albedo = albedo_sw_dif
2180             ENDIF
2181
2182             IF ( surf_usm_v(l)%ns > 0 )  THEN
2183                IF ( surf_usm_v(l)%albedo_from_ascii )  THEN
2184                   surf_usm_v(l)%aldif  = surf_usm_v(l)%albedo
2185                   surf_usm_v(l)%aldir  = surf_usm_v(l)%albedo
2186                   surf_usm_v(l)%asdif  = surf_usm_v(l)%albedo
2187                   surf_usm_v(l)%asdir  = surf_usm_v(l)%albedo
2188                ELSE
2189                   surf_usm_v(l)%aldif  = albedo_lw_dif
2190                   surf_usm_v(l)%aldir  = albedo_lw_dir
2191                   surf_usm_v(l)%asdif  = albedo_sw_dif
2192                   surf_usm_v(l)%asdir  = albedo_sw_dir
2193                ENDIF
2194             ENDIF
2195          ENDDO
2196
2197!
2198!--       Level 2 initialization of spectral albedos via albedo_type.
2199!--       Please note, for natural- and urban-type surfaces, a tile approach
2200!--       is applied so that the resulting albedo is calculated via the weighted
2201!--       average of respective surface fractions.
2202          DO  m = 1, surf_lsm_h%ns
2203!
2204!--          Spectral albedos for vegetation/pavement/water surfaces
2205             DO  ind_type = 0, 2
2206                IF ( surf_lsm_h%albedo_type(ind_type,m) /= 0 )  THEN
2207                   surf_lsm_h%aldif(ind_type,m) =                              &
2208                               albedo_pars(0,surf_lsm_h%albedo_type(ind_type,m))
2209                   surf_lsm_h%asdif(ind_type,m) =                              &
2210                               albedo_pars(1,surf_lsm_h%albedo_type(ind_type,m))
2211                   surf_lsm_h%aldir(ind_type,m) =                              &
2212                               albedo_pars(0,surf_lsm_h%albedo_type(ind_type,m))
2213                   surf_lsm_h%asdir(ind_type,m) =                              &
2214                               albedo_pars(1,surf_lsm_h%albedo_type(ind_type,m))
2215                   surf_lsm_h%albedo(ind_type,m) =                             &
2216                               albedo_pars(2,surf_lsm_h%albedo_type(ind_type,m))
2217                ENDIF
2218             ENDDO
2219
2220          ENDDO
2221!
2222!--       For urban surface only if albedo has not been already initialized
2223!--       in the urban-surface model via the ASCII file.
2224          IF ( .NOT. surf_usm_h%albedo_from_ascii )  THEN
2225             DO  m = 1, surf_usm_h%ns
2226!
2227!--             Spectral albedos for wall/green/window surfaces
2228                DO  ind_type = 0, 2
2229                   IF ( surf_usm_h%albedo_type(ind_type,m) /= 0 )  THEN
2230                      surf_usm_h%aldif(ind_type,m) =                           &
2231                               albedo_pars(0,surf_usm_h%albedo_type(ind_type,m))
2232                      surf_usm_h%asdif(ind_type,m) =                           &
2233                               albedo_pars(1,surf_usm_h%albedo_type(ind_type,m))
2234                      surf_usm_h%aldir(ind_type,m) =                           &
2235                               albedo_pars(0,surf_usm_h%albedo_type(ind_type,m))
2236                      surf_usm_h%asdir(ind_type,m) =                           &
2237                               albedo_pars(1,surf_usm_h%albedo_type(ind_type,m))
2238                      surf_usm_h%albedo(ind_type,m) =                          &
2239                               albedo_pars(2,surf_usm_h%albedo_type(ind_type,m))
2240                   ENDIF
2241                ENDDO
2242
2243             ENDDO
2244          ENDIF
2245
2246          DO l = 0, 3
2247
2248             DO  m = 1, surf_lsm_v(l)%ns
2249!
2250!--             Spectral albedos for vegetation/pavement/water surfaces
2251                DO  ind_type = 0, 2
2252                   IF ( surf_lsm_v(l)%albedo_type(ind_type,m) /= 0 )  THEN
2253                      surf_lsm_v(l)%aldif(ind_type,m) =                        &
2254                            albedo_pars(0,surf_lsm_v(l)%albedo_type(ind_type,m))
2255                      surf_lsm_v(l)%asdif(ind_type,m) =                        &
2256                            albedo_pars(1,surf_lsm_v(l)%albedo_type(ind_type,m))
2257                      surf_lsm_v(l)%aldir(ind_type,m) =                        &
2258                            albedo_pars(0,surf_lsm_v(l)%albedo_type(ind_type,m))
2259                      surf_lsm_v(l)%asdir(ind_type,m) =                        &
2260                            albedo_pars(1,surf_lsm_v(l)%albedo_type(ind_type,m))
2261                      surf_lsm_v(l)%albedo(ind_type,m) =                       &
2262                            albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_type,m))
2263                   ENDIF
2264                ENDDO
2265             ENDDO
2266!
2267!--          For urban surface only if albedo has not been already initialized
2268!--          in the urban-surface model via the ASCII file.
2269             IF ( .NOT. surf_usm_v(l)%albedo_from_ascii )  THEN
2270                DO  m = 1, surf_usm_v(l)%ns
2271!
2272!--                Spectral albedos for wall/green/window surfaces
2273                   DO  ind_type = 0, 2
2274                      IF ( surf_usm_v(l)%albedo_type(ind_type,m) /= 0 )  THEN
2275                         surf_usm_v(l)%aldif(ind_type,m) =                     &
2276                            albedo_pars(0,surf_usm_v(l)%albedo_type(ind_type,m))
2277                         surf_usm_v(l)%asdif(ind_type,m) =                     &
2278                            albedo_pars(1,surf_usm_v(l)%albedo_type(ind_type,m))
2279                         surf_usm_v(l)%aldir(ind_type,m) =                     &
2280                            albedo_pars(0,surf_usm_v(l)%albedo_type(ind_type,m))
2281                         surf_usm_v(l)%asdir(ind_type,m) =                     &
2282                            albedo_pars(1,surf_usm_v(l)%albedo_type(ind_type,m))
2283                         surf_usm_v(l)%albedo(ind_type,m) =                    &
2284                            albedo_pars(2,surf_usm_v(l)%albedo_type(ind_type,m))
2285                      ENDIF
2286                   ENDDO
2287
2288                ENDDO
2289             ENDIF
2290          ENDDO
2291!
2292!--       Level 3 initialization at grid points where albedo type is zero.
2293!--       This case, spectral albedos are taken from file if available
2294          IF ( albedo_pars_f%from_file )  THEN
2295!
2296!--          Horizontal
2297             DO  m = 1, surf_lsm_h%ns
2298                i = surf_lsm_h%i(m)
2299                j = surf_lsm_h%j(m)
2300!
2301!--             Spectral albedos for vegetation/pavement/water surfaces
2302                DO  ind_type = 0, 2
2303                   IF ( surf_lsm_h%albedo_type(ind_type,m) == 0 )  THEN
2304                      IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2305                         surf_lsm_h%albedo(ind_type,m) =                       &
2306                                                albedo_pars_f%pars_xy(1,j,i)
2307                      IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2308                         surf_lsm_h%aldir(ind_type,m) =                        &
2309                                                albedo_pars_f%pars_xy(1,j,i)
2310                      IF ( albedo_pars_f%pars_xy(2,j,i) /= albedo_pars_f%fill )&
2311                         surf_lsm_h%aldif(ind_type,m) =                        &
2312                                                albedo_pars_f%pars_xy(2,j,i)
2313                      IF ( albedo_pars_f%pars_xy(3,j,i) /= albedo_pars_f%fill )&
2314                         surf_lsm_h%asdir(ind_type,m) =                        &
2315                                                albedo_pars_f%pars_xy(3,j,i)
2316                      IF ( albedo_pars_f%pars_xy(4,j,i) /= albedo_pars_f%fill )&
2317                         surf_lsm_h%asdif(ind_type,m) =                        &
2318                                                albedo_pars_f%pars_xy(4,j,i)
2319                   ENDIF
2320                ENDDO
2321             ENDDO
2322!
2323!--          For urban surface only if albedo has not been already initialized
2324!--          in the urban-surface model via the ASCII file.
2325             IF ( .NOT. surf_usm_h%albedo_from_ascii )  THEN
2326                DO  m = 1, surf_usm_h%ns
2327                   i = surf_usm_h%i(m)
2328                   j = surf_usm_h%j(m)
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                         IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2334                            surf_usm_h%albedo(ind_type,m) =                       &
2335                                                albedo_pars_f%pars_xy(1,j,i)
2336                         IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2337                            surf_usm_h%aldir(ind_type,m) =                        &
2338                                                albedo_pars_f%pars_xy(1,j,i)
2339                         IF ( albedo_pars_f%pars_xy(2,j,i) /= albedo_pars_f%fill )&
2340                            surf_usm_h%aldif(ind_type,m) =                        &
2341                                                albedo_pars_f%pars_xy(2,j,i)
2342                         IF ( albedo_pars_f%pars_xy(3,j,i) /= albedo_pars_f%fill )&
2343                            surf_usm_h%asdir(ind_type,m) =                        &
2344                                                albedo_pars_f%pars_xy(3,j,i)
2345                         IF ( albedo_pars_f%pars_xy(4,j,i) /= albedo_pars_f%fill )&
2346                            surf_usm_h%asdif(ind_type,m) =                        &
2347                                                albedo_pars_f%pars_xy(4,j,i)
2348                      ENDIF
2349                   ENDDO
2350
2351                ENDDO
2352             ENDIF
2353!
2354!--          Vertical
2355             DO  l = 0, 3
2356                ioff = surf_lsm_v(l)%ioff
2357                joff = surf_lsm_v(l)%joff
2358
2359                DO  m = 1, surf_lsm_v(l)%ns
2360                   i = surf_lsm_v(l)%i(m)
2361                   j = surf_lsm_v(l)%j(m)
2362!
2363!--                Spectral albedos for vegetation/pavement/water surfaces
2364                   DO  ind_type = 0, 2
2365                      IF ( surf_lsm_v(l)%albedo_type(ind_type,m) == 0 )  THEN
2366                         IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2367                              albedo_pars_f%fill )                             &
2368                            surf_lsm_v(l)%albedo(ind_type,m) =                 &
2369                                          albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2370                         IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2371                              albedo_pars_f%fill )                             &
2372                            surf_lsm_v(l)%aldir(ind_type,m) =                  &
2373                                          albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2374                         IF ( albedo_pars_f%pars_xy(2,j+joff,i+ioff) /=        &
2375                              albedo_pars_f%fill )                             &
2376                            surf_lsm_v(l)%aldif(ind_type,m) =                  &
2377                                          albedo_pars_f%pars_xy(2,j+joff,i+ioff)
2378                         IF ( albedo_pars_f%pars_xy(3,j+joff,i+ioff) /=        &
2379                              albedo_pars_f%fill )                             &
2380                            surf_lsm_v(l)%asdir(ind_type,m) =                  &
2381                                          albedo_pars_f%pars_xy(3,j+joff,i+ioff)
2382                         IF ( albedo_pars_f%pars_xy(4,j+joff,i+ioff) /=        &
2383                              albedo_pars_f%fill )                             &
2384                            surf_lsm_v(l)%asdif(ind_type,m) =                  &
2385                                          albedo_pars_f%pars_xy(4,j+joff,i+ioff)
2386                      ENDIF
2387                   ENDDO
2388                ENDDO
2389!
2390!--             For urban surface only if albedo has not been already initialized
2391!--             in the urban-surface model via the ASCII file.
2392                IF ( .NOT. surf_usm_v(l)%albedo_from_ascii )  THEN
2393                   ioff = surf_usm_v(l)%ioff
2394                   joff = surf_usm_v(l)%joff
2395
2396                   DO  m = 1, surf_usm_v(l)%ns
2397                      i = surf_usm_v(l)%i(m)
2398                      j = surf_usm_v(l)%j(m)
2399!
2400!--                   Spectral albedos for wall/green/window surfaces
2401                      DO  ind_type = 0, 2
2402                         IF ( surf_usm_v(l)%albedo_type(ind_type,m) == 0 )  THEN
2403                            IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2404                                 albedo_pars_f%fill )                             &
2405                               surf_usm_v(l)%albedo(ind_type,m) =                 &
2406                                             albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2407                            IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2408                                 albedo_pars_f%fill )                             &
2409                               surf_usm_v(l)%aldir(ind_type,m) =                  &
2410                                             albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2411                            IF ( albedo_pars_f%pars_xy(2,j+joff,i+ioff) /=        &
2412                                 albedo_pars_f%fill )                             &
2413                               surf_usm_v(l)%aldif(ind_type,m) =                  &
2414                                             albedo_pars_f%pars_xy(2,j+joff,i+ioff)
2415                            IF ( albedo_pars_f%pars_xy(3,j+joff,i+ioff) /=        &
2416                                 albedo_pars_f%fill )                             &
2417                               surf_usm_v(l)%asdir(ind_type,m) =                  &
2418                                             albedo_pars_f%pars_xy(3,j+joff,i+ioff)
2419                            IF ( albedo_pars_f%pars_xy(4,j+joff,i+ioff) /=        &
2420                                 albedo_pars_f%fill )                             &
2421                               surf_usm_v(l)%asdif(ind_type,m) =                  &
2422                                             albedo_pars_f%pars_xy(4,j+joff,i+ioff)
2423                         ENDIF
2424                      ENDDO
2425
2426                   ENDDO
2427                ENDIF
2428             ENDDO
2429
2430          ENDIF
2431
2432!
2433!--       Calculate initial values of current (cosine of) the zenith angle and
2434!--       whether the sun is up
2435          CALL calc_zenith     
2436!
2437!--       Calculate initial surface albedo for different surfaces
2438          IF ( .NOT. constant_albedo )  THEN
2439#if defined( __netcdf )
2440!
2441!--          Horizontally aligned natural and urban surfaces
2442             CALL calc_albedo( surf_lsm_h    )
2443             CALL calc_albedo( surf_usm_h    )
2444!
2445!--          Vertically aligned natural and urban surfaces
2446             DO  l = 0, 3
2447                CALL calc_albedo( surf_lsm_v(l) )
2448                CALL calc_albedo( surf_usm_v(l) )
2449             ENDDO
2450#endif
2451          ELSE
2452!
2453!--          Initialize sun-inclination independent spectral albedos
2454!--          Horizontal surfaces
2455             IF ( surf_lsm_h%ns > 0 )  THEN
2456                surf_lsm_h%rrtm_aldir = surf_lsm_h%aldir
2457                surf_lsm_h%rrtm_asdir = surf_lsm_h%asdir
2458                surf_lsm_h%rrtm_aldif = surf_lsm_h%aldif
2459                surf_lsm_h%rrtm_asdif = surf_lsm_h%asdif
2460             ENDIF
2461             IF ( surf_usm_h%ns > 0 )  THEN
2462                surf_usm_h%rrtm_aldir = surf_usm_h%aldir
2463                surf_usm_h%rrtm_asdir = surf_usm_h%asdir
2464                surf_usm_h%rrtm_aldif = surf_usm_h%aldif
2465                surf_usm_h%rrtm_asdif = surf_usm_h%asdif
2466             ENDIF
2467!
2468!--          Vertical surfaces
2469             DO  l = 0, 3
2470                IF ( surf_lsm_v(l)%ns > 0 )  THEN
2471                   surf_lsm_v(l)%rrtm_aldir = surf_lsm_v(l)%aldir
2472                   surf_lsm_v(l)%rrtm_asdir = surf_lsm_v(l)%asdir
2473                   surf_lsm_v(l)%rrtm_aldif = surf_lsm_v(l)%aldif
2474                   surf_lsm_v(l)%rrtm_asdif = surf_lsm_v(l)%asdif
2475                ENDIF
2476                IF ( surf_usm_v(l)%ns > 0 )  THEN
2477                   surf_usm_v(l)%rrtm_aldir = surf_usm_v(l)%aldir
2478                   surf_usm_v(l)%rrtm_asdir = surf_usm_v(l)%asdir
2479                   surf_usm_v(l)%rrtm_aldif = surf_usm_v(l)%aldif
2480                   surf_usm_v(l)%rrtm_asdif = surf_usm_v(l)%asdif
2481                ENDIF
2482             ENDDO
2483
2484          ENDIF
2485
2486!
2487!--       Allocate 3d arrays of radiative fluxes and heating rates
2488          IF ( .NOT. ALLOCATED ( rad_sw_in ) )  THEN
2489             ALLOCATE ( rad_sw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2490             rad_sw_in = 0.0_wp
2491          ENDIF
2492
2493          IF ( .NOT. ALLOCATED ( rad_sw_in_av ) )  THEN
2494             ALLOCATE ( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2495          ENDIF
2496
2497          IF ( .NOT. ALLOCATED ( rad_sw_out ) )  THEN
2498             ALLOCATE ( rad_sw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2499             rad_sw_out = 0.0_wp
2500          ENDIF
2501
2502          IF ( .NOT. ALLOCATED ( rad_sw_out_av ) )  THEN
2503             ALLOCATE ( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2504          ENDIF
2505
2506          IF ( .NOT. ALLOCATED ( rad_sw_hr ) )  THEN
2507             ALLOCATE ( rad_sw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2508             rad_sw_hr = 0.0_wp
2509          ENDIF
2510
2511          IF ( .NOT. ALLOCATED ( rad_sw_hr_av ) )  THEN
2512             ALLOCATE ( rad_sw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2513             rad_sw_hr_av = 0.0_wp
2514          ENDIF
2515
2516          IF ( .NOT. ALLOCATED ( rad_sw_cs_hr ) )  THEN
2517             ALLOCATE ( rad_sw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2518             rad_sw_cs_hr = 0.0_wp
2519          ENDIF
2520
2521          IF ( .NOT. ALLOCATED ( rad_sw_cs_hr_av ) )  THEN
2522             ALLOCATE ( rad_sw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2523             rad_sw_cs_hr_av = 0.0_wp
2524          ENDIF
2525
2526          IF ( .NOT. ALLOCATED ( rad_lw_in ) )  THEN
2527             ALLOCATE ( rad_lw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2528             rad_lw_in     = 0.0_wp
2529          ENDIF
2530
2531          IF ( .NOT. ALLOCATED ( rad_lw_in_av ) )  THEN
2532             ALLOCATE ( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2533          ENDIF
2534
2535          IF ( .NOT. ALLOCATED ( rad_lw_out ) )  THEN
2536             ALLOCATE ( rad_lw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2537            rad_lw_out    = 0.0_wp
2538          ENDIF
2539
2540          IF ( .NOT. ALLOCATED ( rad_lw_out_av ) )  THEN
2541             ALLOCATE ( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2542          ENDIF
2543
2544          IF ( .NOT. ALLOCATED ( rad_lw_hr ) )  THEN
2545             ALLOCATE ( rad_lw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2546             rad_lw_hr = 0.0_wp
2547          ENDIF
2548
2549          IF ( .NOT. ALLOCATED ( rad_lw_hr_av ) )  THEN
2550             ALLOCATE ( rad_lw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2551             rad_lw_hr_av = 0.0_wp
2552          ENDIF
2553
2554          IF ( .NOT. ALLOCATED ( rad_lw_cs_hr ) )  THEN
2555             ALLOCATE ( rad_lw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2556             rad_lw_cs_hr = 0.0_wp
2557          ENDIF
2558
2559          IF ( .NOT. ALLOCATED ( rad_lw_cs_hr_av ) )  THEN
2560             ALLOCATE ( rad_lw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2561             rad_lw_cs_hr_av = 0.0_wp
2562          ENDIF
2563
2564          ALLOCATE ( rad_sw_cs_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2565          ALLOCATE ( rad_sw_cs_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2566          rad_sw_cs_in  = 0.0_wp
2567          rad_sw_cs_out = 0.0_wp
2568
2569          ALLOCATE ( rad_lw_cs_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2570          ALLOCATE ( rad_lw_cs_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2571          rad_lw_cs_in  = 0.0_wp
2572          rad_lw_cs_out = 0.0_wp
2573
2574!
2575!--       Allocate 1-element array for surface temperature
2576!--       (RRTMG anticipates an array as passed argument).
2577          ALLOCATE ( rrtm_tsfc(1) )
2578!
2579!--       Allocate surface emissivity.
2580!--       Values will be given directly before calling rrtm_lw.
2581          ALLOCATE ( rrtm_emis(0:0,1:nbndlw+1) )
2582
2583!
2584!--       Initialize RRTMG
2585          IF ( lw_radiation )  CALL rrtmg_lw_ini ( c_p )
2586          IF ( sw_radiation )  CALL rrtmg_sw_ini ( c_p )
2587
2588!
2589!--       Set input files for RRTMG
2590          INQUIRE(FILE="RAD_SND_DATA", EXIST=snd_exists) 
2591          IF ( .NOT. snd_exists )  THEN
2592             rrtm_input_file = "rrtmg_lw.nc"
2593          ENDIF
2594
2595!
2596!--       Read vertical layers for RRTMG from sounding data
2597!--       The routine provides nzt_rad, hyp_snd(1:nzt_rad),
2598!--       t_snd(nzt+2:nzt_rad), rrtm_play(1:nzt_rad), rrtm_plev(1_nzt_rad+1),
2599!--       rrtm_tlay(nzt+2:nzt_rad), rrtm_tlev(nzt+2:nzt_rad+1)
2600          CALL read_sounding_data
2601
2602!
2603!--       Read trace gas profiles from file. This routine provides
2604!--       the rrtm_ arrays (1:nzt_rad+1)
2605          CALL read_trace_gas_data
2606#endif
2607       ENDIF
2608
2609!
2610!--    Perform user actions if required
2611       CALL user_init_radiation
2612
2613!
2614!--    Calculate radiative fluxes at model start
2615       SELECT CASE ( TRIM( radiation_scheme ) )
2616
2617          CASE ( 'rrtmg' )
2618             CALL radiation_rrtmg
2619
2620          CASE ( 'clear-sky' )
2621             CALL radiation_clearsky
2622
2623          CASE ( 'constant' )
2624             CALL radiation_constant
2625
2626          CASE DEFAULT
2627
2628       END SELECT
2629
2630       RETURN
2631
2632    END SUBROUTINE radiation_init
2633
2634
2635!------------------------------------------------------------------------------!
2636! Description:
2637! ------------
2638!> A simple clear sky radiation model
2639!------------------------------------------------------------------------------!
2640    SUBROUTINE radiation_clearsky
2641
2642
2643       IMPLICIT NONE
2644
2645       INTEGER(iwp) ::  l         !< running index for surface orientation
2646       REAL(wp)     ::  pt1       !< potential temperature at first grid level or mean value at urban layer top
2647       REAL(wp)     ::  pt1_l     !< potential temperature at first grid level or mean value at urban layer top at local subdomain
2648       REAL(wp)     ::  ql1       !< liquid water mixing ratio at first grid level or mean value at urban layer top
2649       REAL(wp)     ::  ql1_l     !< liquid water mixing ratio at first grid level or mean value at urban layer top at local subdomain
2650
2651       TYPE(surf_type), POINTER ::  surf !< pointer on respective surface type, used to generalize routine   
2652
2653!
2654!--    Calculate current zenith angle
2655       CALL calc_zenith
2656
2657!
2658!--    Calculate sky transmissivity
2659       sky_trans = 0.6_wp + 0.2_wp * zenith(0)
2660
2661!
2662!--    Calculate value of the Exner function at model surface
2663!
2664!--    In case averaged radiation is used, calculate mean temperature and
2665!--    liquid water mixing ratio at the urban-layer top.
2666       IF ( average_radiation ) THEN
2667          pt1   = 0.0_wp
2668          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1   = 0.0_wp
2669
2670          pt1_l = SUM( pt(nzut,nys:nyn,nxl:nxr) )
2671          IF ( bulk_cloud_model  .OR.  cloud_droplets  )  ql1_l = SUM( ql(nzut,nys:nyn,nxl:nxr) )
2672
2673#if defined( __parallel )     
2674          IF ( collective_wait )  CALL MPI_BARRIER( comm2d, ierr )
2675          CALL MPI_ALLREDUCE( pt1_l, pt1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
2676          IF ( ierr /= 0 ) THEN
2677              WRITE(9,*) 'Error MPI_AllReduce1:', ierr, pt1_l, pt1
2678              FLUSH(9)
2679          ENDIF
2680
2681          IF ( bulk_cloud_model  .OR.  cloud_droplets ) THEN
2682              CALL MPI_ALLREDUCE( ql1_l, ql1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
2683              IF ( ierr /= 0 ) THEN
2684                  WRITE(9,*) 'Error MPI_AllReduce2:', ierr, ql1_l, ql1
2685                  FLUSH(9)
2686              ENDIF
2687          ENDIF
2688#else
2689          pt1 = pt1_l 
2690          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1 = ql1_l
2691#endif
2692
2693          IF ( bulk_cloud_model  .OR.  cloud_droplets  )  pt1 = pt1 + lv_d_cp / exner(nzut) * ql1
2694!
2695!--       Finally, divide by number of grid points
2696          pt1 = pt1 / REAL( ( nx + 1 ) * ( ny + 1 ), KIND=wp )
2697       ENDIF
2698!
2699!--    Call clear-sky calculation for each surface orientation.
2700!--    First, horizontal surfaces
2701       surf => surf_lsm_h
2702       CALL radiation_clearsky_surf
2703       surf => surf_usm_h
2704       CALL radiation_clearsky_surf
2705!
2706!--    Vertical surfaces
2707       DO  l = 0, 3
2708          surf => surf_lsm_v(l)
2709          CALL radiation_clearsky_surf
2710          surf => surf_usm_v(l)
2711          CALL radiation_clearsky_surf
2712       ENDDO
2713
2714       CONTAINS
2715
2716          SUBROUTINE radiation_clearsky_surf
2717
2718             IMPLICIT NONE
2719
2720             INTEGER(iwp) ::  i         !< index x-direction
2721             INTEGER(iwp) ::  j         !< index y-direction
2722             INTEGER(iwp) ::  k         !< index z-direction
2723             INTEGER(iwp) ::  m         !< running index for surface elements
2724
2725             IF ( surf%ns < 1 )  RETURN
2726
2727!
2728!--          Calculate radiation fluxes and net radiation (rad_net) assuming
2729!--          homogeneous urban radiation conditions.
2730             IF ( average_radiation ) THEN       
2731
2732                k = nzut
2733
2734                surf%rad_sw_in  = solar_constant * sky_trans * zenith(0)
2735                surf%rad_sw_out = albedo_urb * surf%rad_sw_in
2736               
2737                surf%rad_lw_in  = 0.8_wp * sigma_sb * (pt1 * exner(k+1))**4
2738
2739                surf%rad_lw_out = emissivity_urb * sigma_sb * (t_rad_urb)**4   &
2740                                    + (1.0_wp - emissivity_urb) * surf%rad_lw_in
2741
2742                surf%rad_net = surf%rad_sw_in - surf%rad_sw_out                &
2743                             + surf%rad_lw_in - surf%rad_lw_out
2744
2745                surf%rad_lw_out_change_0 = 3.0_wp * emissivity_urb * sigma_sb  &
2746                                           * (t_rad_urb)**3
2747
2748!
2749!--          Calculate radiation fluxes and net radiation (rad_net) for each surface
2750!--          element.
2751             ELSE
2752
2753                DO  m = 1, surf%ns
2754                   i = surf%i(m)
2755                   j = surf%j(m)
2756                   k = surf%k(m)
2757
2758                   surf%rad_sw_in(m) = solar_constant * sky_trans * zenith(0)
2759
2760!
2761!--                Weighted average according to surface fraction.
2762!--                ATTENTION: when radiation interactions are switched on the
2763!--                calculated fluxes below are not actually used as they are
2764!--                overwritten in radiation_interaction.
2765                   surf%rad_sw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
2766                                          surf%albedo(ind_veg_wall,m)          &
2767                                        + surf%frac(ind_pav_green,m) *         &
2768                                          surf%albedo(ind_pav_green,m)         &
2769                                        + surf%frac(ind_wat_win,m)   *         &
2770                                          surf%albedo(ind_wat_win,m) )         &
2771                                        * surf%rad_sw_in(m)
2772
2773                   surf%rad_lw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
2774                                          surf%emissivity(ind_veg_wall,m)      &
2775                                        + surf%frac(ind_pav_green,m) *         &
2776                                          surf%emissivity(ind_pav_green,m)     &
2777                                        + surf%frac(ind_wat_win,m)   *         &
2778                                          surf%emissivity(ind_wat_win,m)       &
2779                                        )                                      &
2780                                        * sigma_sb                             &
2781                                        * ( surf%pt_surface(m) * exner(nzb) )**4
2782
2783                   surf%rad_lw_out_change_0(m) =                               &
2784                                      ( surf%frac(ind_veg_wall,m)  *           &
2785                                        surf%emissivity(ind_veg_wall,m)        &
2786                                      + surf%frac(ind_pav_green,m) *           &
2787                                        surf%emissivity(ind_pav_green,m)       &
2788                                      + surf%frac(ind_wat_win,m)   *           &
2789                                        surf%emissivity(ind_wat_win,m)         &
2790                                      ) * 3.0_wp * sigma_sb                    &
2791                                      * ( surf%pt_surface(m) * exner(nzb) )** 3
2792
2793
2794                   IF ( bulk_cloud_model  .OR.  cloud_droplets  )  THEN
2795                      pt1 = pt(k,j,i) + lv_d_cp / exner(k) * ql(k,j,i)
2796                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb * (pt1 * exner(k))**4
2797                   ELSE
2798                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb * (pt(k,j,i) * exner(k))**4
2799                   ENDIF
2800
2801                   surf%rad_net(m) = surf%rad_sw_in(m) - surf%rad_sw_out(m)    &
2802                                   + surf%rad_lw_in(m) - surf%rad_lw_out(m)
2803
2804                ENDDO
2805
2806             ENDIF
2807
2808!
2809!--          Fill out values in radiation arrays
2810             DO  m = 1, surf%ns
2811                i = surf%i(m)
2812                j = surf%j(m)
2813                rad_sw_in(0,j,i) = surf%rad_sw_in(m)
2814                rad_sw_out(0,j,i) = surf%rad_sw_out(m)
2815                rad_lw_in(0,j,i) = surf%rad_lw_in(m)
2816                rad_lw_out(0,j,i) = surf%rad_lw_out(m)
2817             ENDDO
2818 
2819          END SUBROUTINE radiation_clearsky_surf
2820
2821    END SUBROUTINE radiation_clearsky
2822
2823
2824!------------------------------------------------------------------------------!
2825! Description:
2826! ------------
2827!> This scheme keeps the prescribed net radiation constant during the run
2828!------------------------------------------------------------------------------!
2829    SUBROUTINE radiation_constant
2830
2831
2832       IMPLICIT NONE
2833
2834       INTEGER(iwp) ::  l         !< running index for surface orientation
2835
2836       REAL(wp)     ::  pt1       !< potential temperature at first grid level or mean value at urban layer top
2837       REAL(wp)     ::  pt1_l     !< potential temperature at first grid level or mean value at urban layer top at local subdomain
2838       REAL(wp)     ::  ql1       !< liquid water mixing ratio at first grid level or mean value at urban layer top
2839       REAL(wp)     ::  ql1_l     !< liquid water mixing ratio at first grid level or mean value at urban layer top at local subdomain
2840
2841       TYPE(surf_type), POINTER ::  surf !< pointer on respective surface type, used to generalize routine
2842
2843!
2844!--    In case averaged radiation is used, calculate mean temperature and
2845!--    liquid water mixing ratio at the urban-layer top.
2846       IF ( average_radiation ) THEN   
2847          pt1   = 0.0_wp
2848          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1   = 0.0_wp
2849
2850          pt1_l = SUM( pt(nzut,nys:nyn,nxl:nxr) )
2851          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1_l = SUM( ql(nzut,nys:nyn,nxl:nxr) )
2852
2853#if defined( __parallel )     
2854          IF ( collective_wait )  CALL MPI_BARRIER( comm2d, ierr )
2855          CALL MPI_ALLREDUCE( pt1_l, pt1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
2856          IF ( ierr /= 0 ) THEN
2857              WRITE(9,*) 'Error MPI_AllReduce3:', ierr, pt1_l, pt1
2858              FLUSH(9)
2859          ENDIF
2860          IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
2861             CALL MPI_ALLREDUCE( ql1_l, ql1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
2862             IF ( ierr /= 0 ) THEN
2863                 WRITE(9,*) 'Error MPI_AllReduce4:', ierr, ql1_l, ql1
2864                 FLUSH(9)
2865             ENDIF
2866          ENDIF
2867#else
2868          pt1 = pt1_l
2869          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1 = ql1_l
2870#endif
2871          IF ( bulk_cloud_model  .OR.  cloud_droplets )  pt1 = pt1 + lv_d_cp / exner(nzut+1) * ql1
2872!
2873!--       Finally, divide by number of grid points
2874          pt1 = pt1 / REAL( ( nx + 1 ) * ( ny + 1 ), KIND=wp )
2875       ENDIF
2876
2877!
2878!--    First, horizontal surfaces
2879       surf => surf_lsm_h
2880       CALL radiation_constant_surf
2881       surf => surf_usm_h
2882       CALL radiation_constant_surf
2883!
2884!--    Vertical surfaces
2885       DO  l = 0, 3
2886          surf => surf_lsm_v(l)
2887          CALL radiation_constant_surf
2888          surf => surf_usm_v(l)
2889          CALL radiation_constant_surf
2890       ENDDO
2891
2892       CONTAINS
2893
2894          SUBROUTINE radiation_constant_surf
2895
2896             IMPLICIT NONE
2897
2898             INTEGER(iwp) ::  i         !< index x-direction
2899             INTEGER(iwp) ::  ioff      !< offset between surface element and adjacent grid point along x
2900             INTEGER(iwp) ::  j         !< index y-direction
2901             INTEGER(iwp) ::  joff      !< offset between surface element and adjacent grid point along y
2902             INTEGER(iwp) ::  k         !< index z-direction
2903             INTEGER(iwp) ::  koff      !< offset between surface element and adjacent grid point along z
2904             INTEGER(iwp) ::  m         !< running index for surface elements
2905
2906             IF ( surf%ns < 1 )  RETURN
2907
2908!--          Calculate homogenoeus urban radiation fluxes
2909             IF ( average_radiation ) THEN
2910
2911                surf%rad_net = net_radiation
2912
2913                surf%rad_lw_in  = 0.8_wp * sigma_sb * (pt1 * exner(nzut+1))**4
2914
2915                surf%rad_lw_out = emissivity_urb * sigma_sb * (t_rad_urb)**4   &
2916                                    + ( 1.0_wp - emissivity_urb )             & ! shouldn't be this a bulk value -- emissivity_urb?
2917                                    * surf%rad_lw_in
2918
2919                surf%rad_lw_out_change_0 = 3.0_wp * emissivity_urb * sigma_sb  &
2920                                           * t_rad_urb**3
2921
2922                surf%rad_sw_in = ( surf%rad_net - surf%rad_lw_in               &
2923                                     + surf%rad_lw_out )                       &
2924                                     / ( 1.0_wp - albedo_urb )
2925
2926                surf%rad_sw_out =  albedo_urb * surf%rad_sw_in
2927
2928!
2929!--          Calculate radiation fluxes for each surface element
2930             ELSE
2931!
2932!--             Determine index offset between surface element and adjacent
2933!--             atmospheric grid point
2934                ioff = surf%ioff
2935                joff = surf%joff
2936                koff = surf%koff
2937
2938!
2939!--             Prescribe net radiation and estimate the remaining radiative fluxes
2940                DO  m = 1, surf%ns
2941                   i = surf%i(m)
2942                   j = surf%j(m)
2943                   k = surf%k(m)
2944
2945                   surf%rad_net(m) = net_radiation
2946
2947                   IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
2948                      pt1 = pt(k,j,i) + lv_d_cp / exner(k) * ql(k,j,i)
2949                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb * (pt1 * exner(k))**4
2950                   ELSE
2951                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb *                 &
2952                                             ( pt(k,j,i) * exner(k) )**4
2953                   ENDIF
2954
2955!
2956!--                Weighted average according to surface fraction.
2957                   surf%rad_lw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
2958                                          surf%emissivity(ind_veg_wall,m)      &
2959                                        + surf%frac(ind_pav_green,m) *         &
2960                                          surf%emissivity(ind_pav_green,m)     &
2961                                        + surf%frac(ind_wat_win,m)   *         &
2962                                          surf%emissivity(ind_wat_win,m)       &
2963                                        )                                      &
2964                                      * sigma_sb                               &
2965                                      * ( surf%pt_surface(m) * exner(nzb) )**4
2966
2967                   surf%rad_sw_in(m) = ( surf%rad_net(m) - surf%rad_lw_in(m)   &
2968                                       + surf%rad_lw_out(m) )                  &
2969                                       / ( 1.0_wp -                            &
2970                                          ( surf%frac(ind_veg_wall,m)  *       &
2971                                            surf%albedo(ind_veg_wall,m)        &
2972                                         +  surf%frac(ind_pav_green,m) *       &
2973                                            surf%albedo(ind_pav_green,m)       &
2974                                         +  surf%frac(ind_wat_win,m)   *       &
2975                                            surf%albedo(ind_wat_win,m) )       &
2976                                         )
2977
2978                   surf%rad_sw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
2979                                          surf%albedo(ind_veg_wall,m)          &
2980                                        + surf%frac(ind_pav_green,m) *         &
2981                                          surf%albedo(ind_pav_green,m)         &
2982                                        + surf%frac(ind_wat_win,m)   *         &
2983                                          surf%albedo(ind_wat_win,m) )         &
2984                                      * surf%rad_sw_in(m)
2985
2986                ENDDO
2987
2988             ENDIF
2989
2990!
2991!--          Fill out values in radiation arrays
2992             DO  m = 1, surf%ns
2993                i = surf%i(m)
2994                j = surf%j(m)
2995                rad_sw_in(0,j,i) = surf%rad_sw_in(m)
2996                rad_sw_out(0,j,i) = surf%rad_sw_out(m)
2997                rad_lw_in(0,j,i) = surf%rad_lw_in(m)
2998                rad_lw_out(0,j,i) = surf%rad_lw_out(m)
2999             ENDDO
3000
3001          END SUBROUTINE radiation_constant_surf
3002         
3003
3004    END SUBROUTINE radiation_constant
3005
3006!------------------------------------------------------------------------------!
3007! Description:
3008! ------------
3009!> Header output for radiation model
3010!------------------------------------------------------------------------------!
3011    SUBROUTINE radiation_header ( io )
3012
3013
3014       IMPLICIT NONE
3015 
3016       INTEGER(iwp), INTENT(IN) ::  io            !< Unit of the output file
3017   
3018
3019       
3020!
3021!--    Write radiation model header
3022       WRITE( io, 3 )
3023
3024       IF ( radiation_scheme == "constant" )  THEN
3025          WRITE( io, 4 ) net_radiation
3026       ELSEIF ( radiation_scheme == "clear-sky" )  THEN
3027          WRITE( io, 5 )
3028       ELSEIF ( radiation_scheme == "rrtmg" )  THEN
3029          WRITE( io, 6 )
3030          IF ( .NOT. lw_radiation )  WRITE( io, 10 )
3031          IF ( .NOT. sw_radiation )  WRITE( io, 11 )
3032       ENDIF
3033
3034       IF ( albedo_type_f%from_file  .OR.  vegetation_type_f%from_file  .OR.   &
3035            pavement_type_f%from_file  .OR.  water_type_f%from_file  .OR.      &
3036            building_type_f%from_file )  THEN
3037             WRITE( io, 13 )
3038       ELSE 
3039          IF ( albedo_type == 0 )  THEN
3040             WRITE( io, 7 ) albedo
3041          ELSE
3042             WRITE( io, 8 ) TRIM( albedo_type_name(albedo_type) )
3043          ENDIF
3044       ENDIF
3045       IF ( constant_albedo )  THEN
3046          WRITE( io, 9 )
3047       ENDIF
3048       
3049       WRITE( io, 12 ) dt_radiation
3050 
3051
3052 3 FORMAT (//' Radiation model information:'/                                  &
3053              ' ----------------------------'/)
3054 4 FORMAT ('    --> Using constant net radiation: net_radiation = ', F6.2,     &
3055           // 'W/m**2')
3056 5 FORMAT ('    --> Simple radiation scheme for clear sky is used (no clouds,',&
3057                   ' default)')
3058 6 FORMAT ('    --> RRTMG scheme is used')
3059 7 FORMAT (/'    User-specific surface albedo: albedo =', F6.3)
3060 8 FORMAT (/'    Albedo is set for land surface type: ', A)
3061 9 FORMAT (/'    --> Albedo is fixed during the run')
306210 FORMAT (/'    --> Longwave radiation is disabled')
306311 FORMAT (/'    --> Shortwave radiation is disabled.')
306412 FORMAT  ('    Timestep: dt_radiation = ', F6.2, '  s')
306513 FORMAT (/'    Albedo is set individually for each xy-location, according ', &
3066                 'to given surface type.')
3067
3068
3069    END SUBROUTINE radiation_header
3070   
3071
3072!------------------------------------------------------------------------------!
3073! Description:
3074! ------------
3075!> Parin for &radiation_parameters for radiation model
3076!------------------------------------------------------------------------------!
3077    SUBROUTINE radiation_parin
3078
3079
3080       IMPLICIT NONE
3081
3082       CHARACTER (LEN=80) ::  line  !< dummy string that contains the current line of the parameter file
3083       
3084       NAMELIST /radiation_par/   albedo, albedo_lw_dif, albedo_lw_dir,         &
3085                                  albedo_sw_dif, albedo_sw_dir, albedo_type,    &
3086                                  constant_albedo, dt_radiation, emissivity,    &
3087                                  lw_radiation, max_raytracing_dist,            &
3088                                  min_irrf_value, mrt_geom_human,               &
3089                                  mrt_include_sw, mrt_nlevels,                  &
3090                                  mrt_skip_roof, net_radiation, nrefsteps,      &
3091                                  plant_lw_interact, rad_angular_discretization,&
3092                                  radiation_interactions_on, radiation_scheme,  &
3093                                  raytrace_discrete_azims,                      &
3094                                  raytrace_discrete_elevs, raytrace_mpi_rma,    &
3095                                  skip_time_do_radiation, surface_reflections,  &
3096                                  svfnorm_report_thresh, sw_radiation,          &
3097                                  unscheduled_radiation_calls
3098
3099   
3100       NAMELIST /radiation_parameters/ albedo, albedo_lw_dif, albedo_lw_dir,    &
3101                                  albedo_sw_dif, albedo_sw_dir, albedo_type,    &
3102                                  constant_albedo, dt_radiation, emissivity,    &
3103                                  lw_radiation, max_raytracing_dist,            &
3104                                  min_irrf_value, mrt_geom_human,               &
3105                                  mrt_include_sw, mrt_nlevels,                  &
3106                                  mrt_skip_roof, net_radiation, nrefsteps,      &
3107                                  plant_lw_interact, rad_angular_discretization,&
3108                                  radiation_interactions_on, radiation_scheme,  &
3109                                  raytrace_discrete_azims,                      &
3110                                  raytrace_discrete_elevs, raytrace_mpi_rma,    &
3111                                  skip_time_do_radiation, surface_reflections,  &
3112                                  svfnorm_report_thresh, sw_radiation,          &
3113                                  unscheduled_radiation_calls
3114   
3115       line = ' '
3116       
3117!
3118!--    Try to find radiation model namelist
3119       REWIND ( 11 )
3120       line = ' '
3121       DO WHILE ( INDEX( line, '&radiation_parameters' ) == 0 )
3122          READ ( 11, '(A)', END=12 )  line
3123       ENDDO
3124       BACKSPACE ( 11 )
3125
3126!
3127!--    Read user-defined namelist
3128       READ ( 11, radiation_parameters, ERR = 10 )
3129
3130!
3131!--    Set flag that indicates that the radiation model is switched on
3132       radiation = .TRUE.
3133
3134       GOTO 14
3135
3136 10    BACKSPACE( 11 )
3137       READ( 11 , '(A)') line
3138       CALL parin_fail_message( 'radiation_parameters', line )
3139!
3140!--    Try to find old namelist
3141 12    REWIND ( 11 )
3142       line = ' '
3143       DO WHILE ( INDEX( line, '&radiation_par' ) == 0 )
3144          READ ( 11, '(A)', END=14 )  line
3145       ENDDO
3146       BACKSPACE ( 11 )
3147
3148!
3149!--    Read user-defined namelist
3150       READ ( 11, radiation_par, ERR = 13, END = 14 )
3151
3152       message_string = 'namelist radiation_par is deprecated and will be ' // &
3153                     'removed in near future. Please use namelist ' //         &
3154                     'radiation_parameters instead'
3155       CALL message( 'radiation_parin', 'PA0487', 0, 1, 0, 6, 0 )
3156
3157!
3158!--    Set flag that indicates that the radiation model is switched on
3159       radiation = .TRUE.
3160
3161       IF ( .NOT.  radiation_interactions_on  .AND.  surface_reflections )  THEN
3162          message_string = 'surface_reflections is allowed only when '      // &
3163               'radiation_interactions_on is set to TRUE'
3164          CALL message( 'radiation_parin', 'PA0293',1, 2, 0, 6, 0 )
3165       ENDIF
3166
3167       GOTO 14
3168
3169 13    BACKSPACE( 11 )
3170       READ( 11 , '(A)') line
3171       CALL parin_fail_message( 'radiation_par', line )
3172
3173 14    CONTINUE
3174       
3175    END SUBROUTINE radiation_parin
3176
3177
3178!------------------------------------------------------------------------------!
3179! Description:
3180! ------------
3181!> Implementation of the RRTMG radiation_scheme
3182!------------------------------------------------------------------------------!
3183    SUBROUTINE radiation_rrtmg
3184
3185#if defined ( __rrtmg )
3186       USE indices,                                                            &
3187           ONLY:  nbgp
3188
3189       USE particle_attributes,                                                &
3190           ONLY:  grid_particles, number_of_particles, particles,              &
3191                  particle_advection_start, prt_count
3192
3193       IMPLICIT NONE
3194
3195
3196       INTEGER(iwp) ::  i, j, k, l, m, n !< loop indices
3197       INTEGER(iwp) ::  k_topo     !< topography top index
3198
3199       REAL(wp)     ::  nc_rad, &    !< number concentration of cloud droplets
3200                        s_r2,   &    !< weighted sum over all droplets with r^2
3201                        s_r3         !< weighted sum over all droplets with r^3
3202
3203       REAL(wp), DIMENSION(0:nzt+1) :: pt_av, q_av, ql_av
3204!
3205!--    Just dummy arguments
3206       REAL(wp), DIMENSION(:,:,:), ALLOCATABLE :: rrtm_lw_taucld_dum,          &
3207                                                  rrtm_lw_tauaer_dum,          &
3208                                                  rrtm_sw_taucld_dum,          &
3209                                                  rrtm_sw_ssacld_dum,          &
3210                                                  rrtm_sw_asmcld_dum,          &
3211                                                  rrtm_sw_fsfcld_dum,          &
3212                                                  rrtm_sw_tauaer_dum,          &
3213                                                  rrtm_sw_ssaaer_dum,          &
3214                                                  rrtm_sw_asmaer_dum,          &
3215                                                  rrtm_sw_ecaer_dum
3216
3217!
3218!--    Calculate current (cosine of) zenith angle and whether the sun is up
3219       CALL calc_zenith     
3220!
3221!--    Calculate surface albedo. In case average radiation is applied,
3222!--    this is not required.
3223#if defined( __netcdf )
3224       IF ( .NOT. constant_albedo )  THEN
3225!
3226!--       Horizontally aligned default, natural and urban surfaces
3227          CALL calc_albedo( surf_lsm_h    )
3228          CALL calc_albedo( surf_usm_h    )
3229!
3230!--       Vertically aligned default, natural and urban surfaces
3231          DO  l = 0, 3
3232             CALL calc_albedo( surf_lsm_v(l) )
3233             CALL calc_albedo( surf_usm_v(l) )
3234          ENDDO
3235       ENDIF
3236#endif
3237
3238!
3239!--    Prepare input data for RRTMG
3240
3241!
3242!--    In case of large scale forcing with surface data, calculate new pressure
3243!--    profile. nzt_rad might be modified by these calls and all required arrays
3244!--    will then be re-allocated
3245       IF ( large_scale_forcing  .AND.  lsf_surf )  THEN
3246          CALL read_sounding_data
3247          CALL read_trace_gas_data
3248       ENDIF
3249
3250
3251       IF ( average_radiation ) THEN
3252
3253          rrtm_asdir(1)  = albedo_urb
3254          rrtm_asdif(1)  = albedo_urb
3255          rrtm_aldir(1)  = albedo_urb
3256          rrtm_aldif(1)  = albedo_urb
3257
3258          rrtm_emis = emissivity_urb
3259!
3260!--       Calculate mean pt profile. Actually, only one height level is required.
3261          CALL calc_mean_profile( pt, 4 )
3262          pt_av = hom(:, 1, 4, 0)
3263         
3264          IF ( humidity )  THEN
3265             CALL calc_mean_profile( q, 41 )
3266             q_av  = hom(:, 1, 41, 0)
3267          ENDIF
3268!
3269!--       Prepare profiles of temperature and H2O volume mixing ratio
3270          rrtm_tlev(0,nzb+1) = t_rad_urb
3271
3272          IF ( bulk_cloud_model )  THEN
3273
3274             CALL calc_mean_profile( ql, 54 )
3275             ! average ql is now in hom(:, 1, 54, 0)
3276             ql_av = hom(:, 1, 54, 0)
3277             
3278             DO k = nzb+1, nzt+1
3279                rrtm_tlay(0,k) = pt_av(k) * ( (hyp(k) ) / 100000._wp       &
3280                                 )**.286_wp + lv_d_cp * ql_av(k)
3281                rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * (q_av(k) - ql_av(k))
3282             ENDDO
3283          ELSE
3284             DO k = nzb+1, nzt+1
3285                rrtm_tlay(0,k) = pt_av(k) * ( (hyp(k) ) / 100000._wp       &
3286                                 )**.286_wp
3287             ENDDO
3288
3289             IF ( humidity )  THEN
3290                DO k = nzb+1, nzt+1
3291                   rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * q_av(k)
3292                ENDDO
3293             ELSE
3294                rrtm_h2ovmr(0,nzb+1:nzt+1) = 0.0_wp
3295             ENDIF
3296          ENDIF
3297
3298!
3299!--       Avoid temperature/humidity jumps at the top of the LES domain by
3300!--       linear interpolation from nzt+2 to nzt+7
3301          DO k = nzt+2, nzt+7
3302             rrtm_tlay(0,k) = rrtm_tlay(0,nzt+1)                            &
3303                           + ( rrtm_tlay(0,nzt+8) - rrtm_tlay(0,nzt+1) )    &
3304                           / ( rrtm_play(0,nzt+8) - rrtm_play(0,nzt+1) )    &
3305                           * ( rrtm_play(0,k) - rrtm_play(0,nzt+1) )
3306
3307             rrtm_h2ovmr(0,k) = rrtm_h2ovmr(0,nzt+1)                        &
3308                           + ( rrtm_h2ovmr(0,nzt+8) - rrtm_h2ovmr(0,nzt+1) )&
3309                           / ( rrtm_play(0,nzt+8)   - rrtm_play(0,nzt+1)   )&
3310                           * ( rrtm_play(0,k) - rrtm_play(0,nzt+1) )
3311
3312          ENDDO
3313
3314!--       Linear interpolate to zw grid
3315          DO k = nzb+2, nzt+8
3316             rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k) -        &
3317                                rrtm_tlay(0,k-1))                           &
3318                                / ( rrtm_play(0,k) - rrtm_play(0,k-1) )     &
3319                                * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
3320          ENDDO
3321
3322
3323!
3324!--       Calculate liquid water path and cloud fraction for each column.
3325!--       Note that LWP is required in g/m2 instead of kg/kg m.
3326          rrtm_cldfr  = 0.0_wp
3327          rrtm_reliq  = 0.0_wp
3328          rrtm_cliqwp = 0.0_wp
3329          rrtm_icld   = 0
3330
3331          IF ( bulk_cloud_model )  THEN
3332             DO k = nzb+1, nzt+1
3333                rrtm_cliqwp(0,k) =  ql_av(k) * 1000._wp *                   &
3334                                    (rrtm_plev(0,k) - rrtm_plev(0,k+1))     &
3335                                    * 100._wp / g 
3336
3337                IF ( rrtm_cliqwp(0,k) > 0._wp )  THEN
3338                   rrtm_cldfr(0,k) = 1._wp
3339                   IF ( rrtm_icld == 0 )  rrtm_icld = 1
3340
3341!
3342!--                Calculate cloud droplet effective radius
3343                   rrtm_reliq(0,k) = 1.0E6_wp * ( 3.0_wp * ql_av(k)         &
3344                                     * rho_surface                          &
3345                                     / ( 4.0_wp * pi * nc_const * rho_l )   &
3346                                     )**0.33333333333333_wp                 &
3347                                     * EXP( LOG( sigma_gc )**2 )
3348!
3349!--                Limit effective radius
3350                   IF ( rrtm_reliq(0,k) > 0.0_wp )  THEN
3351                      rrtm_reliq(0,k) = MAX(rrtm_reliq(0,k),2.5_wp)
3352                      rrtm_reliq(0,k) = MIN(rrtm_reliq(0,k),60.0_wp)
3353                   ENDIF
3354                ENDIF
3355             ENDDO
3356          ENDIF
3357
3358!
3359!--       Set surface temperature
3360          rrtm_tsfc = t_rad_urb
3361         
3362          IF ( lw_radiation )  THEN       
3363         
3364             CALL rrtmg_lw( 1, nzt_rad      , rrtm_icld    , rrtm_idrv      ,&
3365             rrtm_play       , rrtm_plev    , rrtm_tlay    , rrtm_tlev      ,&
3366             rrtm_tsfc       , rrtm_h2ovmr  , rrtm_o3vmr   , rrtm_co2vmr    ,&
3367             rrtm_ch4vmr     , rrtm_n2ovmr  , rrtm_o2vmr   , rrtm_cfc11vmr  ,&
3368             rrtm_cfc12vmr   , rrtm_cfc22vmr, rrtm_ccl4vmr , rrtm_emis      ,&
3369             rrtm_inflglw    , rrtm_iceflglw, rrtm_liqflglw, rrtm_cldfr     ,&
3370             rrtm_lw_taucld  , rrtm_cicewp  , rrtm_cliqwp  , rrtm_reice     ,& 
3371             rrtm_reliq      , rrtm_lw_tauaer,                               &
3372             rrtm_lwuflx     , rrtm_lwdflx  , rrtm_lwhr  ,                   &
3373             rrtm_lwuflxc    , rrtm_lwdflxc , rrtm_lwhrc ,                   &
3374             rrtm_lwuflx_dt  ,  rrtm_lwuflxc_dt )
3375
3376!
3377!--          Save fluxes
3378             DO k = nzb, nzt+1
3379                rad_lw_in(k,:,:)  = rrtm_lwdflx(0,k)
3380                rad_lw_out(k,:,:) = rrtm_lwuflx(0,k)
3381             ENDDO
3382             rad_lw_in_diff(:,:) = rad_lw_in(0,:,:)
3383!
3384!--          Save heating rates (convert from K/d to K/h).
3385!--          Further, even though an aggregated radiation is computed, map
3386!--          signle-column profiles on top of any topography, in order to
3387!--          obtain correct near surface radiation heating/cooling rates.
3388             DO  i = nxl, nxr
3389                DO  j = nys, nyn
3390                   k_topo = get_topography_top_index_ji( j, i, 's' )
3391                   DO k = k_topo+1, nzt+1
3392                      rad_lw_hr(k,j,i)     = rrtm_lwhr(0,k-k_topo)  * d_hours_day
3393                      rad_lw_cs_hr(k,j,i)  = rrtm_lwhrc(0,k-k_topo) * d_hours_day
3394                   ENDDO
3395                ENDDO
3396             ENDDO
3397
3398          ENDIF
3399
3400          IF ( sw_radiation .AND. sun_up )  THEN
3401             CALL rrtmg_sw( 1, nzt_rad      , rrtm_icld     , rrtm_iaer      ,&
3402             rrtm_play      , rrtm_plev     , rrtm_tlay     , rrtm_tlev      ,&
3403             rrtm_tsfc      , rrtm_h2ovmr   , rrtm_o3vmr    , rrtm_co2vmr    ,&
3404             rrtm_ch4vmr    , rrtm_n2ovmr   , rrtm_o2vmr    , rrtm_asdir     ,&
3405             rrtm_asdif     , rrtm_aldir    , rrtm_aldif    , zenith         ,&
3406             0.0_wp         , day_of_year   , solar_constant, rrtm_inflgsw   ,&
3407             rrtm_iceflgsw  , rrtm_liqflgsw , rrtm_cldfr    , rrtm_sw_taucld ,&
3408             rrtm_sw_ssacld , rrtm_sw_asmcld, rrtm_sw_fsfcld, rrtm_cicewp    ,&
3409             rrtm_cliqwp    , rrtm_reice    , rrtm_reliq    , rrtm_sw_tauaer ,&
3410             rrtm_sw_ssaaer , rrtm_sw_asmaer, rrtm_sw_ecaer , rrtm_swuflx    ,&
3411             rrtm_swdflx    , rrtm_swhr     , rrtm_swuflxc  , rrtm_swdflxc   ,&
3412             rrtm_swhrc     , rrtm_dirdflux , rrtm_difdflux )
3413 
3414!
3415!--          Save fluxes:
3416!--          - whole domain
3417             DO k = nzb, nzt+1
3418                rad_sw_in(k,:,:)  = rrtm_swdflx(0,k)
3419                rad_sw_out(k,:,:) = rrtm_swuflx(0,k)
3420             ENDDO
3421!--          - direct and diffuse SW at urban-surface-layer (required by RTM)
3422             rad_sw_in_dir(:,:) = rrtm_dirdflux(0,nzb)
3423             rad_sw_in_diff(:,:) = rrtm_difdflux(0,nzb)
3424
3425!
3426!--          Save heating rates (convert from K/d to K/s)
3427             DO k = nzb+1, nzt+1
3428                rad_sw_hr(k,:,:)     = rrtm_swhr(0,k)  * d_hours_day
3429                rad_sw_cs_hr(k,:,:)  = rrtm_swhrc(0,k) * d_hours_day
3430             ENDDO
3431!
3432!--       Solar radiation is zero during night
3433          ELSE
3434             rad_sw_in  = 0.0_wp
3435             rad_sw_out = 0.0_wp
3436             rad_sw_in_dir(:,:) = 0.0_wp
3437             rad_sw_in_diff(:,:) = 0.0_wp
3438          ENDIF
3439!
3440!--    RRTMG is called for each (j,i) grid point separately, starting at the
3441!--    highest topography level. Here no RTM is used since average_radiation is false
3442       ELSE
3443!
3444!--       Loop over all grid points
3445          DO i = nxl, nxr
3446             DO j = nys, nyn
3447
3448!
3449!--             Prepare profiles of temperature and H2O volume mixing ratio
3450                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
3451                   rrtm_tlev(0,nzb+1) = surf_lsm_h%pt_surface(m) * exner(nzb)
3452                ENDDO
3453                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
3454                   rrtm_tlev(0,nzb+1) = surf_usm_h%pt_surface(m) * exner(nzb)
3455                ENDDO
3456
3457
3458                IF ( bulk_cloud_model )  THEN
3459                   DO k = nzb+1, nzt+1
3460                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)                    &
3461                                        + lv_d_cp * ql(k,j,i)
3462                      rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * (q(k,j,i) - ql(k,j,i))
3463                   ENDDO
3464                ELSEIF ( cloud_droplets )  THEN
3465                   DO k = nzb+1, nzt+1
3466                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)                     &
3467                                        + lv_d_cp * ql(k,j,i)
3468                      rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * q(k,j,i) 
3469                   ENDDO
3470                ELSE
3471                   DO k = nzb+1, nzt+1
3472                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)
3473                   ENDDO
3474
3475                   IF ( humidity )  THEN
3476                      DO k = nzb+1, nzt+1
3477                         rrtm_h2ovmr(0,k) =  mol_mass_air_d_wv * q(k,j,i)
3478                      ENDDO   
3479                   ELSE
3480                      rrtm_h2ovmr(0,nzb+1:nzt+1) = 0.0_wp
3481                   ENDIF
3482                ENDIF
3483
3484!
3485!--             Avoid temperature/humidity jumps at the top of the LES domain by
3486!--             linear interpolation from nzt+2 to nzt+7
3487                DO k = nzt+2, nzt+7
3488                   rrtm_tlay(0,k) = rrtm_tlay(0,nzt+1)                         &
3489                                 + ( rrtm_tlay(0,nzt+8) - rrtm_tlay(0,nzt+1) ) &
3490                                 / ( rrtm_play(0,nzt+8) - rrtm_play(0,nzt+1) ) &
3491                                 * ( rrtm_play(0,k)     - rrtm_play(0,nzt+1) )
3492
3493                   rrtm_h2ovmr(0,k) = rrtm_h2ovmr(0,nzt+1)                     &
3494                              + ( rrtm_h2ovmr(0,nzt+8) - rrtm_h2ovmr(0,nzt+1) )&
3495                              / ( rrtm_play(0,nzt+8)   - rrtm_play(0,nzt+1)   )&
3496                              * ( rrtm_play(0,k)       - rrtm_play(0,nzt+1) )
3497
3498                ENDDO
3499
3500!--             Linear interpolate to zw grid
3501                DO k = nzb+2, nzt+8
3502                   rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k) -     &
3503                                      rrtm_tlay(0,k-1))                        &
3504                                      / ( rrtm_play(0,k) - rrtm_play(0,k-1) )  &
3505                                      * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
3506                ENDDO
3507
3508
3509!
3510!--             Calculate liquid water path and cloud fraction for each column.
3511!--             Note that LWP is required in g/m2 instead of kg/kg m.
3512                rrtm_cldfr  = 0.0_wp
3513                rrtm_reliq  = 0.0_wp
3514                rrtm_cliqwp = 0.0_wp
3515                rrtm_icld   = 0
3516
3517                IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
3518                   DO k = nzb+1, nzt+1
3519                      rrtm_cliqwp(0,k) =  ql(k,j,i) * 1000.0_wp *              &
3520                                          (rrtm_plev(0,k) - rrtm_plev(0,k+1))  &
3521                                          * 100.0_wp / g 
3522
3523                      IF ( rrtm_cliqwp(0,k) > 0.0_wp )  THEN
3524                         rrtm_cldfr(0,k) = 1.0_wp
3525                         IF ( rrtm_icld == 0 )  rrtm_icld = 1
3526
3527!
3528!--                      Calculate cloud droplet effective radius
3529                         IF ( bulk_cloud_model )  THEN
3530!
3531!--                         Calculete effective droplet radius. In case of using
3532!--                         cloud_scheme = 'morrison' and a non reasonable number
3533!--                         of cloud droplets the inital aerosol number 
3534!--                         concentration is considered.
3535                            IF ( microphysics_morrison )  THEN
3536                               IF ( nc(k,j,i) > 1.0E-20_wp )  THEN
3537                                  nc_rad = nc(k,j,i)
3538                               ELSE
3539                                  nc_rad = na_init
3540                               ENDIF
3541                            ELSE
3542                               nc_rad = nc_const
3543                            ENDIF 
3544
3545                            rrtm_reliq(0,k) = 1.0E6_wp * ( 3.0_wp * ql(k,j,i)     &
3546                                              * rho_surface                       &
3547                                              / ( 4.0_wp * pi * nc_rad * rho_l )  &
3548                                              )**0.33333333333333_wp              &
3549                                              * EXP( LOG( sigma_gc )**2 )
3550
3551                         ELSEIF ( cloud_droplets )  THEN
3552                            number_of_particles = prt_count(k,j,i)
3553
3554                            IF (number_of_particles <= 0)  CYCLE
3555                            particles => grid_particles(k,j,i)%particles(1:number_of_particles)
3556                            s_r2 = 0.0_wp
3557                            s_r3 = 0.0_wp
3558
3559                            DO  n = 1, number_of_particles
3560                               IF ( particles(n)%particle_mask )  THEN
3561                                  s_r2 = s_r2 + particles(n)%radius**2 *       &
3562                                         particles(n)%weight_factor
3563                                  s_r3 = s_r3 + particles(n)%radius**3 *       &
3564                                         particles(n)%weight_factor
3565                               ENDIF
3566                            ENDDO
3567
3568                            IF ( s_r2 > 0.0_wp )  rrtm_reliq(0,k) = s_r3 / s_r2
3569
3570                         ENDIF
3571
3572!
3573!--                      Limit effective radius
3574                         IF ( rrtm_reliq(0,k) > 0.0_wp )  THEN
3575                            rrtm_reliq(0,k) = MAX(rrtm_reliq(0,k),2.5_wp)
3576                            rrtm_reliq(0,k) = MIN(rrtm_reliq(0,k),60.0_wp)
3577                        ENDIF
3578                      ENDIF
3579                   ENDDO
3580                ENDIF
3581
3582!
3583!--             Write surface emissivity and surface temperature at current
3584!--             surface element on RRTMG-shaped array.
3585!--             Please note, as RRTMG is a single column model, surface attributes
3586!--             are only obtained from horizontally aligned surfaces (for
3587!--             simplicity). Taking surface attributes from horizontal and
3588!--             vertical walls would lead to multiple solutions. 
3589!--             Moreover, for natural- and urban-type surfaces, several surface
3590!--             classes can exist at a surface element next to each other.
3591!--             To obtain bulk parameters, apply a weighted average for these
3592!--             surfaces.
3593                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
3594                   rrtm_emis = surf_lsm_h%frac(ind_veg_wall,m)  *              &
3595                               surf_lsm_h%emissivity(ind_veg_wall,m)  +        &
3596                               surf_lsm_h%frac(ind_pav_green,m) *              &
3597                               surf_lsm_h%emissivity(ind_pav_green,m) +        & 
3598                               surf_lsm_h%frac(ind_wat_win,m)   *              &
3599                               surf_lsm_h%emissivity(ind_wat_win,m)
3600                   rrtm_tsfc = surf_lsm_h%pt_surface(m) * exner(nzb)
3601                ENDDO             
3602                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
3603                   rrtm_emis = surf_usm_h%frac(ind_veg_wall,m)  *              &
3604                               surf_usm_h%emissivity(ind_veg_wall,m)  +        &
3605                               surf_usm_h%frac(ind_pav_green,m) *              &
3606                               surf_usm_h%emissivity(ind_pav_green,m) +        & 
3607                               surf_usm_h%frac(ind_wat_win,m)   *              &
3608                               surf_usm_h%emissivity(ind_wat_win,m)
3609                   rrtm_tsfc = surf_usm_h%pt_surface(m) * exner(nzb)
3610                ENDDO
3611!
3612!--             Obtain topography top index (lower bound of RRTMG)
3613                k_topo = get_topography_top_index_ji( j, i, 's' )
3614
3615                IF ( lw_radiation )  THEN
3616!
3617!--                Due to technical reasons, copy optical depth to dummy arguments
3618!--                which are allocated on the exact size as the rrtmg_lw is called.
3619!--                As one dimesion is allocated with zero size, compiler complains
3620!--                that rank of the array does not match that of the
3621!--                assumed-shaped arguments in the RRTMG library. In order to
3622!--                avoid this, write to dummy arguments and give pass the entire
3623!--                dummy array. Seems to be the only existing work-around. 
3624                   ALLOCATE( rrtm_lw_taucld_dum(1:nbndlw+1,0:0,k_topo+1:nzt_rad+1) )
3625                   ALLOCATE( rrtm_lw_tauaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndlw+1) )
3626
3627                   rrtm_lw_taucld_dum =                                        &
3628                               rrtm_lw_taucld(1:nbndlw+1,0:0,k_topo+1:nzt_rad+1)
3629                   rrtm_lw_tauaer_dum =                                        &
3630                               rrtm_lw_tauaer(0:0,k_topo+1:nzt_rad+1,1:nbndlw+1)
3631
3632                   CALL rrtmg_lw( 1,                                           &                                       
3633                                  nzt_rad-k_topo,                              &
3634                                  rrtm_icld,                                   &
3635                                  rrtm_idrv,                                   &
3636                                  rrtm_play(:,k_topo+1:nzt_rad+1),             &
3637                                  rrtm_plev(:,k_topo+1:nzt_rad+2),             &
3638                                  rrtm_tlay(:,k_topo+1:nzt_rad+1),             &
3639                                  rrtm_tlev(:,k_topo+1:nzt_rad+2),             &
3640                                  rrtm_tsfc,                                   &
3641                                  rrtm_h2ovmr(:,k_topo+1:nzt_rad+1),           &
3642                                  rrtm_o3vmr(:,k_topo+1:nzt_rad+1),            &
3643                                  rrtm_co2vmr(:,k_topo+1:nzt_rad+1),           &
3644                                  rrtm_ch4vmr(:,k_topo+1:nzt_rad+1),           &
3645                                  rrtm_n2ovmr(:,k_topo+1:nzt_rad+1),           &
3646                                  rrtm_o2vmr(:,k_topo+1:nzt_rad+1),            &
3647                                  rrtm_cfc11vmr(:,k_topo+1:nzt_rad+1),         &
3648                                  rrtm_cfc12vmr(:,k_topo+1:nzt_rad+1),         &
3649                                  rrtm_cfc22vmr(:,k_topo+1:nzt_rad+1),         &
3650                                  rrtm_ccl4vmr(:,k_topo+1:nzt_rad+1),          &
3651                                  rrtm_emis,                                   &
3652                                  rrtm_inflglw,                                &
3653                                  rrtm_iceflglw,                               &
3654                                  rrtm_liqflglw,                               &
3655                                  rrtm_cldfr(:,k_topo+1:nzt_rad+1),            &
3656                                  rrtm_lw_taucld_dum,                          &
3657                                  rrtm_cicewp(:,k_topo+1:nzt_rad+1),           &
3658                                  rrtm_cliqwp(:,k_topo+1:nzt_rad+1),           &
3659                                  rrtm_reice(:,k_topo+1:nzt_rad+1),            & 
3660                                  rrtm_reliq(:,k_topo+1:nzt_rad+1),            &
3661                                  rrtm_lw_tauaer_dum,                          &
3662                                  rrtm_lwuflx(:,k_topo:nzt_rad+1),             &
3663                                  rrtm_lwdflx(:,k_topo:nzt_rad+1),             &
3664                                  rrtm_lwhr(:,k_topo+1:nzt_rad+1),             &
3665                                  rrtm_lwuflxc(:,k_topo:nzt_rad+1),            &
3666                                  rrtm_lwdflxc(:,k_topo:nzt_rad+1),            &
3667                                  rrtm_lwhrc(:,k_topo+1:nzt_rad+1),            &
3668                                  rrtm_lwuflx_dt(:,k_topo:nzt_rad+1),          &
3669                                  rrtm_lwuflxc_dt(:,k_topo:nzt_rad+1) )
3670
3671                   DEALLOCATE ( rrtm_lw_taucld_dum )
3672                   DEALLOCATE ( rrtm_lw_tauaer_dum )
3673!
3674!--                Save fluxes
3675                   DO k = k_topo, nzt+1
3676                      rad_lw_in(k,j,i)  = rrtm_lwdflx(0,k)
3677                      rad_lw_out(k,j,i) = rrtm_lwuflx(0,k)
3678                   ENDDO
3679
3680!
3681!--                Save heating rates (convert from K/d to K/h)
3682                   DO k = k_topo+1, nzt+1
3683                      rad_lw_hr(k,j,i)     = rrtm_lwhr(0,k-k_topo)  * d_hours_day
3684                      rad_lw_cs_hr(k,j,i)  = rrtm_lwhrc(0,k-k_topo) * d_hours_day
3685                   ENDDO
3686
3687!
3688!--                Save surface radiative fluxes and change in LW heating rate
3689!--                onto respective surface elements
3690!--                Horizontal surfaces
3691                   DO  m = surf_lsm_h%start_index(j,i),                        &
3692                           surf_lsm_h%end_index(j,i)
3693                      surf_lsm_h%rad_lw_in(m)           = rrtm_lwdflx(0,k_topo)
3694                      surf_lsm_h%rad_lw_out(m)          = rrtm_lwuflx(0,k_topo)
3695                      surf_lsm_h%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k_topo)
3696                   ENDDO             
3697                   DO  m = surf_usm_h%start_index(j,i),                        &
3698                           surf_usm_h%end_index(j,i)
3699                      surf_usm_h%rad_lw_in(m)           = rrtm_lwdflx(0,k_topo)
3700                      surf_usm_h%rad_lw_out(m)          = rrtm_lwuflx(0,k_topo)
3701                      surf_usm_h%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k_topo)
3702                   ENDDO 
3703!
3704!--                Vertical surfaces. Fluxes are obtain at vertical level of the
3705!--                respective surface element
3706                   DO  l = 0, 3
3707                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
3708                              surf_lsm_v(l)%end_index(j,i)
3709                         k                                    = surf_lsm_v(l)%k(m)
3710                         surf_lsm_v(l)%rad_lw_in(m)           = rrtm_lwdflx(0,k)
3711                         surf_lsm_v(l)%rad_lw_out(m)          = rrtm_lwuflx(0,k)
3712                         surf_lsm_v(l)%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k)
3713                      ENDDO             
3714                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
3715                              surf_usm_v(l)%end_index(j,i)
3716                         k                                    = surf_usm_v(l)%k(m)
3717                         surf_usm_v(l)%rad_lw_in(m)           = rrtm_lwdflx(0,k)
3718                         surf_usm_v(l)%rad_lw_out(m)          = rrtm_lwuflx(0,k)
3719                         surf_usm_v(l)%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k)
3720                      ENDDO 
3721                   ENDDO
3722
3723                ENDIF
3724
3725                IF ( sw_radiation .AND. sun_up )  THEN
3726!
3727!--                Get albedo for direct/diffusive long/shortwave radiation at
3728!--                current (y,x)-location from surface variables.
3729!--                Only obtain it from horizontal surfaces, as RRTMG is a single
3730!--                column model
3731!--                (Please note, only one loop will entered, controlled by
3732!--                start-end index.)
3733                   DO  m = surf_lsm_h%start_index(j,i),                        &
3734                           surf_lsm_h%end_index(j,i)
3735                      rrtm_asdir(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3736                                            surf_lsm_h%rrtm_asdir(:,m) )
3737                      rrtm_asdif(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3738                                            surf_lsm_h%rrtm_asdif(:,m) )
3739                      rrtm_aldir(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3740                                            surf_lsm_h%rrtm_aldir(:,m) )
3741                      rrtm_aldif(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3742                                            surf_lsm_h%rrtm_aldif(:,m) )
3743                   ENDDO             
3744                   DO  m = surf_usm_h%start_index(j,i),                        &
3745                           surf_usm_h%end_index(j,i)
3746                      rrtm_asdir(1)  = SUM( surf_usm_h%frac(:,m) *             &
3747                                            surf_usm_h%rrtm_asdir(:,m) )
3748                      rrtm_asdif(1)  = SUM( surf_usm_h%frac(:,m) *             &
3749                                            surf_usm_h%rrtm_asdif(:,m) )
3750                      rrtm_aldir(1)  = SUM( surf_usm_h%frac(:,m) *             &
3751                                            surf_usm_h%rrtm_aldir(:,m) )
3752                      rrtm_aldif(1)  = SUM( surf_usm_h%frac(:,m) *             &
3753                                            surf_usm_h%rrtm_aldif(:,m) )
3754                   ENDDO
3755!
3756!--                Due to technical reasons, copy optical depths and other
3757!--                to dummy arguments which are allocated on the exact size as the
3758!--                rrtmg_sw is called.
3759!--                As one dimesion is allocated with zero size, compiler complains
3760!--                that rank of the array does not match that of the
3761!--                assumed-shaped arguments in the RRTMG library. In order to
3762!--                avoid this, write to dummy arguments and give pass the entire
3763!--                dummy array. Seems to be the only existing work-around. 
3764                   ALLOCATE( rrtm_sw_taucld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3765                   ALLOCATE( rrtm_sw_ssacld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3766                   ALLOCATE( rrtm_sw_asmcld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3767                   ALLOCATE( rrtm_sw_fsfcld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3768                   ALLOCATE( rrtm_sw_tauaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3769                   ALLOCATE( rrtm_sw_ssaaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3770                   ALLOCATE( rrtm_sw_asmaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3771                   ALLOCATE( rrtm_sw_ecaer_dum(0:0,k_topo+1:nzt_rad+1,1:naerec+1)  )
3772     
3773                   rrtm_sw_taucld_dum = rrtm_sw_taucld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3774                   rrtm_sw_ssacld_dum = rrtm_sw_ssacld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3775                   rrtm_sw_asmcld_dum = rrtm_sw_asmcld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3776                   rrtm_sw_fsfcld_dum = rrtm_sw_fsfcld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3777                   rrtm_sw_tauaer_dum = rrtm_sw_tauaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3778                   rrtm_sw_ssaaer_dum = rrtm_sw_ssaaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3779                   rrtm_sw_asmaer_dum = rrtm_sw_asmaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3780                   rrtm_sw_ecaer_dum  = rrtm_sw_ecaer(0:0,k_topo+1:nzt_rad+1,1:naerec+1)
3781
3782                   CALL rrtmg_sw( 1,                                           &
3783                                  nzt_rad-k_topo,                              &
3784                                  rrtm_icld,                                   &
3785                                  rrtm_iaer,                                   &
3786                                  rrtm_play(:,k_topo+1:nzt_rad+1),             &
3787                                  rrtm_plev(:,k_topo+1:nzt_rad+2),             &
3788                                  rrtm_tlay(:,k_topo+1:nzt_rad+1),             &
3789                                  rrtm_tlev(:,k_topo+1:nzt_rad+2),             &
3790                                  rrtm_tsfc,                                   &
3791                                  rrtm_h2ovmr(:,k_topo+1:nzt_rad+1),           &                               
3792                                  rrtm_o3vmr(:,k_topo+1:nzt_rad+1),            &       
3793                                  rrtm_co2vmr(:,k_topo+1:nzt_rad+1),           &
3794                                  rrtm_ch4vmr(:,k_topo+1:nzt_rad+1),           &
3795                                  rrtm_n2ovmr(:,k_topo+1:nzt_rad+1),           &
3796                                  rrtm_o2vmr(:,k_topo+1:nzt_rad+1),            &
3797                                  rrtm_asdir,                                  & 
3798                                  rrtm_asdif,                                  &
3799                                  rrtm_aldir,                                  &
3800                                  rrtm_aldif,                                  &
3801                                  zenith,                                      &
3802                                  0.0_wp,                                      &
3803                                  day_of_year,                                 &
3804                                  solar_constant,                              &
3805                                  rrtm_inflgsw,                                &
3806                                  rrtm_iceflgsw,                               &
3807                                  rrtm_liqflgsw,                               &
3808                                  rrtm_cldfr(:,k_topo+1:nzt_rad+1),            &
3809                                  rrtm_sw_taucld_dum,                          &
3810                                  rrtm_sw_ssacld_dum,                          &
3811                                  rrtm_sw_asmcld_dum,                          &
3812                                  rrtm_sw_fsfcld_dum,                          &
3813                                  rrtm_cicewp(:,k_topo+1:nzt_rad+1),           &
3814                                  rrtm_cliqwp(:,k_topo+1:nzt_rad+1),           &
3815                                  rrtm_reice(:,k_topo+1:nzt_rad+1),            &
3816                                  rrtm_reliq(:,k_topo+1:nzt_rad+1),            &
3817                                  rrtm_sw_tauaer_dum,                          &
3818                                  rrtm_sw_ssaaer_dum,                          &
3819                                  rrtm_sw_asmaer_dum,                          &
3820                                  rrtm_sw_ecaer_dum,                           &
3821                                  rrtm_swuflx(:,k_topo:nzt_rad+1),             & 
3822                                  rrtm_swdflx(:,k_topo:nzt_rad+1),             & 
3823                                  rrtm_swhr(:,k_topo+1:nzt_rad+1),             & 
3824                                  rrtm_swuflxc(:,k_topo:nzt_rad+1),            & 
3825                                  rrtm_swdflxc(:,k_topo:nzt_rad+1),            &
3826                                  rrtm_swhrc(:,k_topo+1:nzt_rad+1),            &
3827                                  rrtm_dirdflux(:,k_topo:nzt_rad+1),           &
3828                                  rrtm_difdflux(:,k_topo:nzt_rad+1) )
3829
3830                   DEALLOCATE( rrtm_sw_taucld_dum )
3831                   DEALLOCATE( rrtm_sw_ssacld_dum )
3832                   DEALLOCATE( rrtm_sw_asmcld_dum )
3833                   DEALLOCATE( rrtm_sw_fsfcld_dum )
3834                   DEALLOCATE( rrtm_sw_tauaer_dum )
3835                   DEALLOCATE( rrtm_sw_ssaaer_dum )
3836                   DEALLOCATE( rrtm_sw_asmaer_dum )
3837                   DEALLOCATE( rrtm_sw_ecaer_dum )
3838!
3839!--                Save fluxes
3840                   DO k = nzb, nzt+1
3841                      rad_sw_in(k,j,i)  = rrtm_swdflx(0,k)
3842                      rad_sw_out(k,j,i) = rrtm_swuflx(0,k)
3843                   ENDDO
3844!
3845!--                Save heating rates (convert from K/d to K/s)
3846                   DO k = nzb+1, nzt+1
3847                      rad_sw_hr(k,j,i)     = rrtm_swhr(0,k)  * d_hours_day
3848                      rad_sw_cs_hr(k,j,i)  = rrtm_swhrc(0,k) * d_hours_day
3849                   ENDDO
3850
3851!
3852!--                Save surface radiative fluxes onto respective surface elements
3853!--                Horizontal surfaces
3854                   DO  m = surf_lsm_h%start_index(j,i),                        &
3855                           surf_lsm_h%end_index(j,i)
3856                      surf_lsm_h%rad_sw_in(m)     = rrtm_swdflx(0,k_topo)
3857                      surf_lsm_h%rad_sw_out(m)    = rrtm_swuflx(0,k_topo)
3858                   ENDDO             
3859                   DO  m = surf_usm_h%start_index(j,i),                        &
3860                           surf_usm_h%end_index(j,i)
3861                      surf_usm_h%rad_sw_in(m)     = rrtm_swdflx(0,k_topo)
3862                      surf_usm_h%rad_sw_out(m)    = rrtm_swuflx(0,k_topo)
3863                   ENDDO 
3864!
3865!--                Vertical surfaces. Fluxes are obtain at respective vertical
3866!--                level of the 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_sw_in(m)  = rrtm_swdflx(0,k)
3872                         surf_lsm_v(l)%rad_sw_out(m) = rrtm_swuflx(0,k)
3873                      ENDDO             
3874                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
3875                              surf_usm_v(l)%end_index(j,i)
3876                         k                           = surf_usm_v(l)%k(m)
3877                         surf_usm_v(l)%rad_sw_in(m)  = rrtm_swdflx(0,k)
3878                         surf_usm_v(l)%rad_sw_out(m) = rrtm_swuflx(0,k)
3879                      ENDDO 
3880                   ENDDO
3881!
3882!--             Solar radiation is zero during night
3883                ELSE
3884                   rad_sw_in  = 0.0_wp
3885                   rad_sw_out = 0.0_wp
3886!--             !!!!!!!! ATTENSION !!!!!!!!!!!!!!!
3887!--             Surface radiative fluxes should be also set to zero here                 
3888!--                Save surface radiative fluxes onto respective surface elements
3889!--                Horizontal surfaces
3890                   DO  m = surf_lsm_h%start_index(j,i),                        &
3891                           surf_lsm_h%end_index(j,i)
3892                      surf_lsm_h%rad_sw_in(m)     = 0.0_wp
3893                      surf_lsm_h%rad_sw_out(m)    = 0.0_wp
3894                   ENDDO             
3895                   DO  m = surf_usm_h%start_index(j,i),                        &
3896                           surf_usm_h%end_index(j,i)
3897                      surf_usm_h%rad_sw_in(m)     = 0.0_wp
3898                      surf_usm_h%rad_sw_out(m)    = 0.0_wp
3899                   ENDDO 
3900!
3901!--                Vertical surfaces. Fluxes are obtain at respective vertical
3902!--                level of the surface element
3903                   DO  l = 0, 3
3904                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
3905                              surf_lsm_v(l)%end_index(j,i)
3906                         k                           = surf_lsm_v(l)%k(m)
3907                         surf_lsm_v(l)%rad_sw_in(m)  = 0.0_wp
3908                         surf_lsm_v(l)%rad_sw_out(m) = 0.0_wp
3909                      ENDDO             
3910                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
3911                              surf_usm_v(l)%end_index(j,i)
3912                         k                           = surf_usm_v(l)%k(m)
3913                         surf_usm_v(l)%rad_sw_in(m)  = 0.0_wp
3914                         surf_usm_v(l)%rad_sw_out(m) = 0.0_wp
3915                      ENDDO 
3916                   ENDDO
3917                ENDIF
3918
3919             ENDDO
3920          ENDDO
3921
3922       ENDIF
3923!
3924!--    Finally, calculate surface net radiation for surface elements.
3925       IF (  .NOT.  radiation_interactions  ) THEN
3926!--       First, for horizontal surfaces   
3927          DO  m = 1, surf_lsm_h%ns
3928             surf_lsm_h%rad_net(m) = surf_lsm_h%rad_sw_in(m)                   &
3929                                   - surf_lsm_h%rad_sw_out(m)                  &
3930                                   + surf_lsm_h%rad_lw_in(m)                   &
3931                                   - surf_lsm_h%rad_lw_out(m)
3932          ENDDO
3933          DO  m = 1, surf_usm_h%ns
3934             surf_usm_h%rad_net(m) = surf_usm_h%rad_sw_in(m)                   &
3935                                   - surf_usm_h%rad_sw_out(m)                  &
3936                                   + surf_usm_h%rad_lw_in(m)                   &
3937                                   - surf_usm_h%rad_lw_out(m)
3938          ENDDO
3939!
3940!--       Vertical surfaces.
3941!--       Todo: weight with azimuth and zenith angle according to their orientation!
3942          DO  l = 0, 3     
3943             DO  m = 1, surf_lsm_v(l)%ns
3944                surf_lsm_v(l)%rad_net(m) = surf_lsm_v(l)%rad_sw_in(m)          &
3945                                         - surf_lsm_v(l)%rad_sw_out(m)         &
3946                                         + surf_lsm_v(l)%rad_lw_in(m)          &
3947                                         - surf_lsm_v(l)%rad_lw_out(m)
3948             ENDDO
3949             DO  m = 1, surf_usm_v(l)%ns
3950                surf_usm_v(l)%rad_net(m) = surf_usm_v(l)%rad_sw_in(m)          &
3951                                         - surf_usm_v(l)%rad_sw_out(m)         &
3952                                         + surf_usm_v(l)%rad_lw_in(m)          &
3953                                         - surf_usm_v(l)%rad_lw_out(m)
3954             ENDDO
3955          ENDDO
3956       ENDIF
3957
3958
3959       CALL exchange_horiz( rad_lw_in,  nbgp )
3960       CALL exchange_horiz( rad_lw_out, nbgp )
3961       CALL exchange_horiz( rad_lw_hr,    nbgp )
3962       CALL exchange_horiz( rad_lw_cs_hr, nbgp )
3963
3964       CALL exchange_horiz( rad_sw_in,  nbgp )
3965       CALL exchange_horiz( rad_sw_out, nbgp ) 
3966       CALL exchange_horiz( rad_sw_hr,    nbgp )
3967       CALL exchange_horiz( rad_sw_cs_hr, nbgp )
3968
3969#endif
3970
3971    END SUBROUTINE radiation_rrtmg
3972
3973
3974!------------------------------------------------------------------------------!
3975! Description:
3976! ------------
3977!> Calculate the cosine of the zenith angle (variable is called zenith)
3978!------------------------------------------------------------------------------!
3979    SUBROUTINE calc_zenith
3980
3981       IMPLICIT NONE
3982
3983       REAL(wp) ::  declination,  & !< solar declination angle
3984                    hour_angle      !< solar hour angle
3985!
3986!--    Calculate current day and time based on the initial values and simulation
3987!--    time
3988       CALL calc_date_and_time
3989
3990!
3991!--    Calculate solar declination and hour angle   
3992       declination = ASIN( decl_1 * SIN(decl_2 * REAL(day_of_year, KIND=wp) - decl_3) )
3993       hour_angle  = 2.0_wp * pi * (time_utc / 86400.0_wp) + lon - pi
3994
3995!
3996!--    Calculate cosine of solar zenith angle
3997       zenith(0) = SIN(lat) * SIN(declination) + COS(lat) * COS(declination)   &
3998                                            * COS(hour_angle)
3999       zenith(0) = MAX(0.0_wp,zenith(0))
4000
4001!
4002!--    Calculate solar directional vector
4003       IF ( sun_direction )  THEN
4004
4005!
4006!--       Direction in longitudes equals to sin(solar_azimuth) * sin(zenith)
4007          sun_dir_lon(0) = -SIN(hour_angle) * COS(declination)
4008
4009!
4010!--       Direction in latitues equals to cos(solar_azimuth) * sin(zenith)
4011          sun_dir_lat(0) = SIN(declination) * COS(lat) - COS(hour_angle) &
4012                              * COS(declination) * SIN(lat)
4013       ENDIF
4014
4015!
4016!--    Check if the sun is up (otheriwse shortwave calculations can be skipped)
4017       IF ( zenith(0) > 0.0_wp )  THEN
4018          sun_up = .TRUE.
4019       ELSE
4020          sun_up = .FALSE.
4021       END IF
4022
4023    END SUBROUTINE calc_zenith
4024
4025#if defined ( __rrtmg ) && defined ( __netcdf )
4026!------------------------------------------------------------------------------!
4027! Description:
4028! ------------
4029!> Calculates surface albedo components based on Briegleb (1992) and
4030!> Briegleb et al. (1986)
4031!------------------------------------------------------------------------------!
4032    SUBROUTINE calc_albedo( surf )
4033
4034        IMPLICIT NONE
4035
4036        INTEGER(iwp)    ::  ind_type !< running index surface tiles
4037        INTEGER(iwp)    ::  m        !< running index surface elements
4038
4039        TYPE(surf_type) ::  surf !< treated surfaces
4040
4041        IF ( sun_up  .AND.  .NOT. average_radiation )  THEN
4042
4043           DO  m = 1, surf%ns
4044!
4045!--           Loop over surface elements
4046              DO  ind_type = 0, SIZE( surf%albedo_type, 1 ) - 1
4047           
4048!
4049!--              Ocean
4050                 IF ( surf%albedo_type(ind_type,m) == 1 )  THEN
4051                    surf%rrtm_aldir(ind_type,m) = 0.026_wp /                    &
4052                                                ( zenith(0)**1.7_wp + 0.065_wp )&
4053                                     + 0.15_wp * ( zenith(0) - 0.1_wp )         &
4054                                               * ( zenith(0) - 0.5_wp )         &
4055                                               * ( zenith(0) - 1.0_wp )
4056                    surf%rrtm_asdir(ind_type,m) = surf%rrtm_aldir(ind_type,m)
4057!
4058!--              Snow
4059                 ELSEIF ( surf%albedo_type(ind_type,m) == 16 )  THEN
4060                    IF ( zenith(0) < 0.5_wp )  THEN
4061                       surf%rrtm_aldir(ind_type,m) =                           &
4062                                 0.5_wp * ( 1.0_wp - surf%aldif(ind_type,m) )  &
4063                                        * ( 3.0_wp / ( 1.0_wp + 4.0_wp         &
4064                                        * zenith(0) ) ) - 1.0_wp
4065                       surf%rrtm_asdir(ind_type,m) =                           &
4066                                 0.5_wp * ( 1.0_wp - surf%asdif(ind_type,m) )  &
4067                                        * ( 3.0_wp / ( 1.0_wp + 4.0_wp         &
4068                                        * zenith(0) ) ) - 1.0_wp
4069
4070                       surf%rrtm_aldir(ind_type,m) =                           &
4071                                       MIN(0.98_wp, surf%rrtm_aldir(ind_type,m))
4072                       surf%rrtm_asdir(ind_type,m) =                           &
4073                                       MIN(0.98_wp, surf%rrtm_asdir(ind_type,m))
4074                    ELSE
4075                       surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4076                       surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4077                    ENDIF
4078!
4079!--              Sea ice
4080                 ELSEIF ( surf%albedo_type(ind_type,m) == 15 )  THEN
4081                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4082                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4083
4084!
4085!--              Asphalt
4086                 ELSEIF ( surf%albedo_type(ind_type,m) == 17 )  THEN
4087                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4088                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4089
4090
4091!
4092!--              Bare soil
4093                 ELSEIF ( surf%albedo_type(ind_type,m) == 18 )  THEN
4094                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4095                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4096
4097!
4098!--              Land surfaces
4099                 ELSE
4100                    SELECT CASE ( surf%albedo_type(ind_type,m) )
4101
4102!
4103!--                    Surface types with strong zenith dependence
4104                       CASE ( 1, 2, 3, 4, 11, 12, 13 )
4105                          surf%rrtm_aldir(ind_type,m) =                        &
4106                                surf%aldif(ind_type,m) * 1.4_wp /              &
4107                                           ( 1.0_wp + 0.8_wp * zenith(0) )
4108                          surf%rrtm_asdir(ind_type,m) =                        &
4109                                surf%asdif(ind_type,m) * 1.4_wp /              &
4110                                           ( 1.0_wp + 0.8_wp * zenith(0) )
4111!
4112!--                    Surface types with weak zenith dependence
4113                       CASE ( 5, 6, 7, 8, 9, 10, 14 )
4114                          surf%rrtm_aldir(ind_type,m) =                        &
4115                                surf%aldif(ind_type,m) * 1.1_wp /              &
4116                                           ( 1.0_wp + 0.2_wp * zenith(0) )
4117                          surf%rrtm_asdir(ind_type,m) =                        &
4118                                surf%asdif(ind_type,m) * 1.1_wp /              &
4119                                           ( 1.0_wp + 0.2_wp * zenith(0) )
4120
4121                       CASE DEFAULT
4122
4123                    END SELECT
4124                 ENDIF
4125!
4126!--              Diffusive albedo is taken from Table 2
4127                 surf%rrtm_aldif(ind_type,m) = surf%aldif(ind_type,m)
4128                 surf%rrtm_asdif(ind_type,m) = surf%asdif(ind_type,m)
4129              ENDDO
4130           ENDDO
4131!
4132!--     Set albedo in case of average radiation
4133        ELSEIF ( sun_up  .AND.  average_radiation )  THEN
4134           surf%rrtm_asdir = albedo_urb
4135           surf%rrtm_asdif = albedo_urb
4136           surf%rrtm_aldir = albedo_urb
4137           surf%rrtm_aldif = albedo_urb 
4138!
4139!--     Darkness
4140        ELSE
4141           surf%rrtm_aldir = 0.0_wp
4142           surf%rrtm_asdir = 0.0_wp
4143           surf%rrtm_aldif = 0.0_wp
4144           surf%rrtm_asdif = 0.0_wp
4145        ENDIF
4146
4147    END SUBROUTINE calc_albedo
4148
4149!------------------------------------------------------------------------------!
4150! Description:
4151! ------------
4152!> Read sounding data (pressure and temperature) from RADIATION_DATA.
4153!------------------------------------------------------------------------------!
4154    SUBROUTINE read_sounding_data
4155
4156       IMPLICIT NONE
4157
4158       INTEGER(iwp) :: id,           & !< NetCDF id of input file
4159                       id_dim_zrad,  & !< pressure level id in the NetCDF file
4160                       id_var,       & !< NetCDF variable id
4161                       k,            & !< loop index
4162                       nz_snd,       & !< number of vertical levels in the sounding data
4163                       nz_snd_start, & !< start vertical index for sounding data to be used
4164                       nz_snd_end      !< end vertical index for souding data to be used
4165
4166       REAL(wp) :: t_surface           !< actual surface temperature
4167
4168       REAL(wp), DIMENSION(:), ALLOCATABLE ::  hyp_snd_tmp, & !< temporary hydrostatic pressure profile (sounding)
4169                                               t_snd_tmp      !< temporary temperature profile (sounding)
4170
4171!
4172!--    In case of updates, deallocate arrays first (sufficient to check one
4173!--    array as the others are automatically allocated). This is required
4174!--    because nzt_rad might change during the update
4175       IF ( ALLOCATED ( hyp_snd ) )  THEN
4176          DEALLOCATE( hyp_snd )
4177          DEALLOCATE( t_snd )
4178          DEALLOCATE ( rrtm_play )
4179          DEALLOCATE ( rrtm_plev )
4180          DEALLOCATE ( rrtm_tlay )
4181          DEALLOCATE ( rrtm_tlev )
4182
4183          DEALLOCATE ( rrtm_cicewp )
4184          DEALLOCATE ( rrtm_cldfr )
4185          DEALLOCATE ( rrtm_cliqwp )
4186          DEALLOCATE ( rrtm_reice )
4187          DEALLOCATE ( rrtm_reliq )
4188          DEALLOCATE ( rrtm_lw_taucld )
4189          DEALLOCATE ( rrtm_lw_tauaer )
4190
4191          DEALLOCATE ( rrtm_lwdflx  )
4192          DEALLOCATE ( rrtm_lwdflxc )
4193          DEALLOCATE ( rrtm_lwuflx  )
4194          DEALLOCATE ( rrtm_lwuflxc )
4195          DEALLOCATE ( rrtm_lwuflx_dt )
4196          DEALLOCATE ( rrtm_lwuflxc_dt )
4197          DEALLOCATE ( rrtm_lwhr  )
4198          DEALLOCATE ( rrtm_lwhrc )
4199
4200          DEALLOCATE ( rrtm_sw_taucld )
4201          DEALLOCATE ( rrtm_sw_ssacld )
4202          DEALLOCATE ( rrtm_sw_asmcld )
4203          DEALLOCATE ( rrtm_sw_fsfcld )
4204          DEALLOCATE ( rrtm_sw_tauaer )
4205          DEALLOCATE ( rrtm_sw_ssaaer )
4206          DEALLOCATE ( rrtm_sw_asmaer ) 
4207          DEALLOCATE ( rrtm_sw_ecaer )   
4208 
4209          DEALLOCATE ( rrtm_swdflx  )
4210          DEALLOCATE ( rrtm_swdflxc )
4211          DEALLOCATE ( rrtm_swuflx  )
4212          DEALLOCATE ( rrtm_swuflxc )
4213          DEALLOCATE ( rrtm_swhr  )
4214          DEALLOCATE ( rrtm_swhrc )
4215          DEALLOCATE ( rrtm_dirdflux )
4216          DEALLOCATE ( rrtm_difdflux )
4217
4218       ENDIF
4219
4220!
4221!--    Open file for reading
4222       nc_stat = NF90_OPEN( rrtm_input_file, NF90_NOWRITE, id )
4223       CALL netcdf_handle_error_rad( 'read_sounding_data', 549 )
4224
4225!
4226!--    Inquire dimension of z axis and save in nz_snd
4227       nc_stat = NF90_INQ_DIMID( id, "Pressure", id_dim_zrad )
4228       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim_zrad, len = nz_snd )
4229       CALL netcdf_handle_error_rad( 'read_sounding_data', 551 )
4230
4231!
4232! !--    Allocate temporary array for storing pressure data
4233       ALLOCATE( hyp_snd_tmp(1:nz_snd) )
4234       hyp_snd_tmp = 0.0_wp
4235
4236
4237!--    Read pressure from file
4238       nc_stat = NF90_INQ_VARID( id, "Pressure", id_var )
4239       nc_stat = NF90_GET_VAR( id, id_var, hyp_snd_tmp(:), start = (/1/),      &
4240                               count = (/nz_snd/) )
4241       CALL netcdf_handle_error_rad( 'read_sounding_data', 552 )
4242
4243!
4244!--    Allocate temporary array for storing temperature data
4245       ALLOCATE( t_snd_tmp(1:nz_snd) )
4246       t_snd_tmp = 0.0_wp
4247
4248!
4249!--    Read temperature from file
4250       nc_stat = NF90_INQ_VARID( id, "ReferenceTemperature", id_var )
4251       nc_stat = NF90_GET_VAR( id, id_var, t_snd_tmp(:), start = (/1/),        &
4252                               count = (/nz_snd/) )
4253       CALL netcdf_handle_error_rad( 'read_sounding_data', 553 )
4254
4255!
4256!--    Calculate start of sounding data
4257       nz_snd_start = nz_snd + 1
4258       nz_snd_end   = nz_snd + 1
4259
4260!
4261!--    Start filling vertical dimension at 10hPa above the model domain (hyp is
4262!--    in Pa, hyp_snd in hPa).
4263       DO  k = 1, nz_snd
4264          IF ( hyp_snd_tmp(k) < ( hyp(nzt+1) - 1000.0_wp) * 0.01_wp )  THEN
4265             nz_snd_start = k
4266             EXIT
4267          END IF
4268       END DO
4269
4270       IF ( nz_snd_start <= nz_snd )  THEN
4271          nz_snd_end = nz_snd
4272       END IF
4273
4274
4275!
4276!--    Calculate of total grid points for RRTMG calculations
4277       nzt_rad = nzt + nz_snd_end - nz_snd_start + 1
4278
4279!
4280!--    Save data above LES domain in hyp_snd, t_snd
4281       ALLOCATE( hyp_snd(nzb+1:nzt_rad) )
4282       ALLOCATE( t_snd(nzb+1:nzt_rad)   )
4283       hyp_snd = 0.0_wp
4284       t_snd = 0.0_wp
4285
4286       hyp_snd(nzt+2:nzt_rad) = hyp_snd_tmp(nz_snd_start+1:nz_snd_end)
4287       t_snd(nzt+2:nzt_rad)   = t_snd_tmp(nz_snd_start+1:nz_snd_end)
4288
4289       nc_stat = NF90_CLOSE( id )
4290
4291!
4292!--    Calculate pressure levels on zu and zw grid. Sounding data is added at
4293!--    top of the LES domain. This routine does not consider horizontal or
4294!--    vertical variability of pressure and temperature
4295       ALLOCATE ( rrtm_play(0:0,nzb+1:nzt_rad+1)   )
4296       ALLOCATE ( rrtm_plev(0:0,nzb+1:nzt_rad+2)   )
4297
4298       t_surface = pt_surface * exner(nzb)
4299       DO k = nzb+1, nzt+1
4300          rrtm_play(0,k) = hyp(k) * 0.01_wp
4301          rrtm_plev(0,k) = barometric_formula(zw(k-1),                         &
4302                              pt_surface * exner(nzb), &
4303                              surface_pressure )
4304       ENDDO
4305
4306       DO k = nzt+2, nzt_rad
4307          rrtm_play(0,k) = hyp_snd(k)
4308          rrtm_plev(0,k) = 0.5_wp * ( rrtm_play(0,k) + rrtm_play(0,k-1) )
4309       ENDDO
4310       rrtm_plev(0,nzt_rad+1) = MAX( 0.5 * hyp_snd(nzt_rad),                   &
4311                                   1.5 * hyp_snd(nzt_rad)                      &
4312                                 - 0.5 * hyp_snd(nzt_rad-1) )
4313       rrtm_plev(0,nzt_rad+2)  = MIN( 1.0E-4_wp,                               &
4314                                      0.25_wp * rrtm_plev(0,nzt_rad+1) )
4315
4316       rrtm_play(0,nzt_rad+1) = 0.5 * rrtm_plev(0,nzt_rad+1)
4317
4318!
4319!--    Calculate temperature/humidity levels at top of the LES domain.
4320!--    Currently, the temperature is taken from sounding data (might lead to a
4321!--    temperature jump at interface. To do: Humidity is currently not
4322!--    calculated above the LES domain.
4323       ALLOCATE ( rrtm_tlay(0:0,nzb+1:nzt_rad+1)   )
4324       ALLOCATE ( rrtm_tlev(0:0,nzb+1:nzt_rad+2)   )
4325
4326       DO k = nzt+8, nzt_rad
4327          rrtm_tlay(0,k)   = t_snd(k)
4328       ENDDO
4329       rrtm_tlay(0,nzt_rad+1) = 2.0_wp * rrtm_tlay(0,nzt_rad)                  &
4330                                - rrtm_tlay(0,nzt_rad-1)
4331       DO k = nzt+9, nzt_rad+1
4332          rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k)                &
4333                             - rrtm_tlay(0,k-1))                               &
4334                             / ( rrtm_play(0,k) - rrtm_play(0,k-1) )           &
4335                             * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
4336       ENDDO
4337
4338       rrtm_tlev(0,nzt_rad+2)   = 2.0_wp * rrtm_tlay(0,nzt_rad+1)              &
4339                                  - rrtm_tlev(0,nzt_rad)
4340!
4341!--    Allocate remaining RRTMG arrays
4342       ALLOCATE ( rrtm_cicewp(0:0,nzb+1:nzt_rad+1) )
4343       ALLOCATE ( rrtm_cldfr(0:0,nzb+1:nzt_rad+1) )
4344       ALLOCATE ( rrtm_cliqwp(0:0,nzb+1:nzt_rad+1) )
4345       ALLOCATE ( rrtm_reice(0:0,nzb+1:nzt_rad+1) )
4346       ALLOCATE ( rrtm_reliq(0:0,nzb+1:nzt_rad+1) )
4347       ALLOCATE ( rrtm_lw_taucld(1:nbndlw+1,0:0,nzb+1:nzt_rad+1) )
4348       ALLOCATE ( rrtm_lw_tauaer(0:0,nzb+1:nzt_rad+1,1:nbndlw+1) )
4349       ALLOCATE ( rrtm_sw_taucld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4350       ALLOCATE ( rrtm_sw_ssacld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4351       ALLOCATE ( rrtm_sw_asmcld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4352       ALLOCATE ( rrtm_sw_fsfcld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4353       ALLOCATE ( rrtm_sw_tauaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) )
4354       ALLOCATE ( rrtm_sw_ssaaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) )
4355       ALLOCATE ( rrtm_sw_asmaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) ) 
4356       ALLOCATE ( rrtm_sw_ecaer(0:0,nzb+1:nzt_rad+1,1:naerec+1) )   
4357
4358!
4359!--    The ice phase is currently not considered in PALM
4360       rrtm_cicewp = 0.0_wp
4361       rrtm_reice  = 0.0_wp
4362
4363!
4364!--    Set other parameters (move to NAMELIST parameters in the future)
4365       rrtm_lw_tauaer = 0.0_wp
4366       rrtm_lw_taucld = 0.0_wp
4367       rrtm_sw_taucld = 0.0_wp
4368       rrtm_sw_ssacld = 0.0_wp
4369       rrtm_sw_asmcld = 0.0_wp
4370       rrtm_sw_fsfcld = 0.0_wp
4371       rrtm_sw_tauaer = 0.0_wp
4372       rrtm_sw_ssaaer = 0.0_wp
4373       rrtm_sw_asmaer = 0.0_wp
4374       rrtm_sw_ecaer  = 0.0_wp
4375
4376
4377       ALLOCATE ( rrtm_swdflx(0:0,nzb:nzt_rad+1)  )
4378       ALLOCATE ( rrtm_swuflx(0:0,nzb:nzt_rad+1)  )
4379       ALLOCATE ( rrtm_swhr(0:0,nzb+1:nzt_rad+1)  )
4380       ALLOCATE ( rrtm_swuflxc(0:0,nzb:nzt_rad+1) )
4381       ALLOCATE ( rrtm_swdflxc(0:0,nzb:nzt_rad+1) )
4382       ALLOCATE ( rrtm_swhrc(0:0,nzb+1:nzt_rad+1) )
4383       ALLOCATE ( rrtm_dirdflux(0:0,nzb:nzt_rad+1) )
4384       ALLOCATE ( rrtm_difdflux(0:0,nzb:nzt_rad+1) )
4385
4386       rrtm_swdflx  = 0.0_wp
4387       rrtm_swuflx  = 0.0_wp
4388       rrtm_swhr    = 0.0_wp 
4389       rrtm_swuflxc = 0.0_wp
4390       rrtm_swdflxc = 0.0_wp
4391       rrtm_swhrc   = 0.0_wp
4392       rrtm_dirdflux = 0.0_wp
4393       rrtm_difdflux = 0.0_wp
4394
4395       ALLOCATE ( rrtm_lwdflx(0:0,nzb:nzt_rad+1)  )
4396       ALLOCATE ( rrtm_lwuflx(0:0,nzb:nzt_rad+1)  )
4397       ALLOCATE ( rrtm_lwhr(0:0,nzb+1:nzt_rad+1)  )
4398       ALLOCATE ( rrtm_lwuflxc(0:0,nzb:nzt_rad+1) )
4399       ALLOCATE ( rrtm_lwdflxc(0:0,nzb:nzt_rad+1) )
4400       ALLOCATE ( rrtm_lwhrc(0:0,nzb+1:nzt_rad+1) )
4401
4402       rrtm_lwdflx  = 0.0_wp
4403       rrtm_lwuflx  = 0.0_wp
4404       rrtm_lwhr    = 0.0_wp 
4405       rrtm_lwuflxc = 0.0_wp
4406       rrtm_lwdflxc = 0.0_wp
4407       rrtm_lwhrc   = 0.0_wp
4408
4409       ALLOCATE ( rrtm_lwuflx_dt(0:0,nzb:nzt_rad+1) )
4410       ALLOCATE ( rrtm_lwuflxc_dt(0:0,nzb:nzt_rad+1) )
4411
4412       rrtm_lwuflx_dt = 0.0_wp
4413       rrtm_lwuflxc_dt = 0.0_wp
4414
4415    END SUBROUTINE read_sounding_data
4416
4417
4418!------------------------------------------------------------------------------!
4419! Description:
4420! ------------
4421!> Read trace gas data from file
4422!------------------------------------------------------------------------------!
4423    SUBROUTINE read_trace_gas_data
4424
4425       USE rrsw_ncpar
4426
4427       IMPLICIT NONE
4428
4429       INTEGER(iwp), PARAMETER :: num_trace_gases = 10 !< number of trace gases (absorbers)
4430
4431       CHARACTER(LEN=5), DIMENSION(num_trace_gases), PARAMETER ::              & !< trace gas names
4432           trace_names = (/'O3   ', 'CO2  ', 'CH4  ', 'N2O  ', 'O2   ',        &
4433                           'CFC11', 'CFC12', 'CFC22', 'CCL4 ', 'H2O  '/)
4434
4435       INTEGER(iwp) :: id,     & !< NetCDF id
4436                       k,      & !< loop index
4437                       m,      & !< loop index
4438                       n,      & !< loop index
4439                       nabs,   & !< number of absorbers
4440                       np,     & !< number of pressure levels
4441                       id_abs, & !< NetCDF id of the respective absorber
4442                       id_dim, & !< NetCDF id of asborber's dimension
4443                       id_var    !< NetCDf id ot the absorber
4444
4445       REAL(wp) :: p_mls_l, p_mls_u, p_wgt_l, p_wgt_u, p_mls_m
4446
4447
4448       REAL(wp), DIMENSION(:), ALLOCATABLE   ::  p_mls,          & !< pressure levels for the absorbers
4449                                                 rrtm_play_tmp,  & !< temporary array for pressure zu-levels
4450                                                 rrtm_plev_tmp,  & !< temporary array for pressure zw-levels
4451                                                 trace_path_tmp    !< temporary array for storing trace gas path data
4452
4453       REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  trace_mls,      & !< array for storing the absorber amounts
4454                                                 trace_mls_path, & !< array for storing trace gas path data
4455                                                 trace_mls_tmp     !< temporary array for storing trace gas data
4456
4457
4458!
4459!--    In case of updates, deallocate arrays first (sufficient to check one
4460!--    array as the others are automatically allocated)
4461       IF ( ALLOCATED ( rrtm_o3vmr ) )  THEN
4462          DEALLOCATE ( rrtm_o3vmr  )
4463          DEALLOCATE ( rrtm_co2vmr )
4464          DEALLOCATE ( rrtm_ch4vmr )
4465          DEALLOCATE ( rrtm_n2ovmr )
4466          DEALLOCATE ( rrtm_o2vmr  )
4467          DEALLOCATE ( rrtm_cfc11vmr )
4468          DEALLOCATE ( rrtm_cfc12vmr )
4469          DEALLOCATE ( rrtm_cfc22vmr )
4470          DEALLOCATE ( rrtm_ccl4vmr  )
4471          DEALLOCATE ( rrtm_h2ovmr  )     
4472       ENDIF
4473
4474!
4475!--    Allocate trace gas profiles
4476       ALLOCATE ( rrtm_o3vmr(0:0,1:nzt_rad+1)  )
4477       ALLOCATE ( rrtm_co2vmr(0:0,1:nzt_rad+1) )
4478       ALLOCATE ( rrtm_ch4vmr(0:0,1:nzt_rad+1) )
4479       ALLOCATE ( rrtm_n2ovmr(0:0,1:nzt_rad+1) )
4480       ALLOCATE ( rrtm_o2vmr(0:0,1:nzt_rad+1)  )
4481       ALLOCATE ( rrtm_cfc11vmr(0:0,1:nzt_rad+1) )
4482       ALLOCATE ( rrtm_cfc12vmr(0:0,1:nzt_rad+1) )
4483       ALLOCATE ( rrtm_cfc22vmr(0:0,1:nzt_rad+1) )
4484       ALLOCATE ( rrtm_ccl4vmr(0:0,1:nzt_rad+1)  )
4485       ALLOCATE ( rrtm_h2ovmr(0:0,1:nzt_rad+1)  )
4486
4487!
4488!--    Open file for reading
4489       nc_stat = NF90_OPEN( rrtm_input_file, NF90_NOWRITE, id )
4490       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 549 )
4491!
4492!--    Inquire dimension ids and dimensions
4493       nc_stat = NF90_INQ_DIMID( id, "Pressure", id_dim )
4494       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4495       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim, len = np) 
4496       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4497
4498       nc_stat = NF90_INQ_DIMID( id, "Absorber", id_dim )
4499       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4500       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim, len = nabs ) 
4501       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4502   
4503
4504!
4505!--    Allocate pressure, and trace gas arrays     
4506       ALLOCATE( p_mls(1:np) )
4507       ALLOCATE( trace_mls(1:num_trace_gases,1:np) ) 
4508       ALLOCATE( trace_mls_tmp(1:nabs,1:np) ) 
4509
4510
4511       nc_stat = NF90_INQ_VARID( id, "Pressure", id_var )
4512       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4513       nc_stat = NF90_GET_VAR( id, id_var, p_mls )
4514       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4515
4516       nc_stat = NF90_INQ_VARID( id, "AbsorberAmountMLS", id_var )
4517       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4518       nc_stat = NF90_GET_VAR( id, id_var, trace_mls_tmp )
4519       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4520
4521
4522!
4523!--    Write absorber amounts (mls) to trace_mls
4524       DO n = 1, num_trace_gases
4525          CALL getAbsorberIndex( TRIM( trace_names(n) ), id_abs )
4526
4527          trace_mls(n,1:np) = trace_mls_tmp(id_abs,1:np)
4528
4529!
4530!--       Replace missing values by zero
4531          WHERE ( trace_mls(n,:) > 2.0_wp ) 
4532             trace_mls(n,:) = 0.0_wp
4533          END WHERE
4534       END DO
4535
4536       DEALLOCATE ( trace_mls_tmp )
4537
4538       nc_stat = NF90_CLOSE( id )
4539       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 551 )
4540
4541!
4542!--    Add extra pressure level for calculations of the trace gas paths
4543       ALLOCATE ( rrtm_play_tmp(1:nzt_rad+1) )
4544       ALLOCATE ( rrtm_plev_tmp(1:nzt_rad+2) )
4545
4546       rrtm_play_tmp(1:nzt_rad)   = rrtm_play(0,1:nzt_rad) 
4547       rrtm_plev_tmp(1:nzt_rad+1) = rrtm_plev(0,1:nzt_rad+1)
4548       rrtm_play_tmp(nzt_rad+1)   = rrtm_plev(0,nzt_rad+1) * 0.5_wp
4549       rrtm_plev_tmp(nzt_rad+2)   = MIN( 1.0E-4_wp, 0.25_wp                    &
4550                                         * rrtm_plev(0,nzt_rad+1) )
4551 
4552!
4553!--    Calculate trace gas path (zero at surface) with interpolation to the
4554!--    sounding levels
4555       ALLOCATE ( trace_mls_path(1:nzt_rad+2,1:num_trace_gases) )
4556
4557       trace_mls_path(nzb+1,:) = 0.0_wp
4558       
4559       DO k = nzb+2, nzt_rad+2
4560          DO m = 1, num_trace_gases
4561             trace_mls_path(k,m) = trace_mls_path(k-1,m)
4562
4563!
4564!--          When the pressure level is higher than the trace gas pressure
4565!--          level, assume that
4566             IF ( rrtm_plev_tmp(k-1) > p_mls(1) )  THEN             
4567               
4568                trace_mls_path(k,m) = trace_mls_path(k,m) + trace_mls(m,1)     &
4569                                      * ( rrtm_plev_tmp(k-1)                   &
4570                                          - MAX( p_mls(1), rrtm_plev_tmp(k) )  &
4571                                        ) / g
4572             ENDIF
4573
4574!
4575!--          Integrate for each sounding level from the contributing p_mls
4576!--          levels
4577             DO n = 2, np
4578!
4579!--             Limit p_mls so that it is within the model level
4580                p_mls_u = MIN( rrtm_plev_tmp(k-1),                             &
4581                          MAX( rrtm_plev_tmp(k), p_mls(n) ) )
4582                p_mls_l = MIN( rrtm_plev_tmp(k-1),                             &
4583                          MAX( rrtm_plev_tmp(k), p_mls(n-1) ) )
4584
4585                IF ( p_mls_l > p_mls_u )  THEN
4586
4587!
4588!--                Calculate weights for interpolation
4589                   p_mls_m = 0.5_wp * (p_mls_l + p_mls_u)
4590                   p_wgt_u = (p_mls(n-1) - p_mls_m) / (p_mls(n-1) - p_mls(n))
4591                   p_wgt_l = (p_mls_m - p_mls(n))   / (p_mls(n-1) - p_mls(n))
4592
4593!
4594!--                Add level to trace gas path
4595                   trace_mls_path(k,m) = trace_mls_path(k,m)                   &
4596                                         +  ( p_wgt_u * trace_mls(m,n)         &
4597                                            + p_wgt_l * trace_mls(m,n-1) )     &
4598                                         * (p_mls_l - p_mls_u) / g
4599                ENDIF
4600             ENDDO
4601
4602             IF ( rrtm_plev_tmp(k) < p_mls(np) )  THEN
4603                trace_mls_path(k,m) = trace_mls_path(k,m) + trace_mls(m,np)    &
4604                                      * ( MIN( rrtm_plev_tmp(k-1), p_mls(np) ) &
4605                                          - rrtm_plev_tmp(k)                   &
4606                                        ) / g 
4607             ENDIF 
4608          ENDDO
4609       ENDDO
4610
4611
4612!
4613!--    Prepare trace gas path profiles
4614       ALLOCATE ( trace_path_tmp(1:nzt_rad+1) )
4615
4616       DO m = 1, num_trace_gases
4617
4618          trace_path_tmp(1:nzt_rad+1) = ( trace_mls_path(2:nzt_rad+2,m)        &
4619                                       - trace_mls_path(1:nzt_rad+1,m) ) * g   &
4620                                       / ( rrtm_plev_tmp(1:nzt_rad+1)          &
4621                                       - rrtm_plev_tmp(2:nzt_rad+2) )
4622
4623!
4624!--       Save trace gas paths to the respective arrays
4625          SELECT CASE ( TRIM( trace_names(m) ) )
4626
4627             CASE ( 'O3' )
4628
4629                rrtm_o3vmr(0,:) = trace_path_tmp(:)
4630
4631             CASE ( 'CO2' )
4632
4633                rrtm_co2vmr(0,:) = trace_path_tmp(:)
4634
4635             CASE ( 'CH4' )
4636
4637                rrtm_ch4vmr(0,:) = trace_path_tmp(:)
4638
4639             CASE ( 'N2O' )
4640
4641                rrtm_n2ovmr(0,:) = trace_path_tmp(:)
4642
4643             CASE ( 'O2' )
4644
4645                rrtm_o2vmr(0,:) = trace_path_tmp(:)
4646
4647             CASE ( 'CFC11' )
4648
4649                rrtm_cfc11vmr(0,:) = trace_path_tmp(:)
4650
4651             CASE ( 'CFC12' )
4652
4653                rrtm_cfc12vmr(0,:) = trace_path_tmp(:)
4654
4655             CASE ( 'CFC22' )
4656
4657                rrtm_cfc22vmr(0,:) = trace_path_tmp(:)
4658
4659             CASE ( 'CCL4' )
4660
4661                rrtm_ccl4vmr(0,:) = trace_path_tmp(:)
4662
4663             CASE ( 'H2O' )
4664
4665                rrtm_h2ovmr(0,:) = trace_path_tmp(:)
4666               
4667             CASE DEFAULT
4668
4669          END SELECT
4670
4671       ENDDO
4672
4673       DEALLOCATE ( trace_path_tmp )
4674       DEALLOCATE ( trace_mls_path )
4675       DEALLOCATE ( rrtm_play_tmp )
4676       DEALLOCATE ( rrtm_plev_tmp )
4677       DEALLOCATE ( trace_mls )
4678       DEALLOCATE ( p_mls )
4679
4680    END SUBROUTINE read_trace_gas_data
4681
4682
4683    SUBROUTINE netcdf_handle_error_rad( routine_name, errno )
4684
4685       USE control_parameters,                                                 &
4686           ONLY:  message_string
4687
4688       USE NETCDF
4689
4690       USE pegrid
4691
4692       IMPLICIT NONE
4693
4694       CHARACTER(LEN=6) ::  message_identifier
4695       CHARACTER(LEN=*) ::  routine_name
4696
4697       INTEGER(iwp) ::  errno
4698
4699       IF ( nc_stat /= NF90_NOERR )  THEN
4700
4701          WRITE( message_identifier, '(''NC'',I4.4)' )  errno
4702          message_string = TRIM( NF90_STRERROR( nc_stat ) )
4703
4704          CALL message( routine_name, message_identifier, 2, 2, 0, 6, 1 )
4705
4706       ENDIF
4707
4708    END SUBROUTINE netcdf_handle_error_rad
4709#endif
4710
4711
4712!------------------------------------------------------------------------------!
4713! Description:
4714! ------------
4715!> Calculate temperature tendency due to radiative cooling/heating.
4716!> Cache-optimized version.
4717!------------------------------------------------------------------------------!
4718 SUBROUTINE radiation_tendency_ij ( i, j, tend )
4719
4720    IMPLICIT NONE
4721
4722    INTEGER(iwp) :: i, j, k !< loop indices
4723
4724    REAL(wp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg) :: tend !< pt tendency term
4725
4726    IF ( radiation_scheme == 'rrtmg' )  THEN
4727#if defined  ( __rrtmg )
4728!
4729!--    Calculate tendency based on heating rate
4730       DO k = nzb+1, nzt+1
4731          tend(k,j,i) = tend(k,j,i) + (rad_lw_hr(k,j,i) + rad_sw_hr(k,j,i))    &
4732                                         * d_exner(k) * d_seconds_hour
4733       ENDDO
4734#endif
4735    ENDIF
4736
4737    END SUBROUTINE radiation_tendency_ij
4738
4739
4740!------------------------------------------------------------------------------!
4741! Description:
4742! ------------
4743!> Calculate temperature tendency due to radiative cooling/heating.
4744!> Vector-optimized version
4745!------------------------------------------------------------------------------!
4746 SUBROUTINE radiation_tendency ( tend )
4747
4748    USE indices,                                                               &
4749        ONLY:  nxl, nxr, nyn, nys
4750
4751    IMPLICIT NONE
4752
4753    INTEGER(iwp) :: i, j, k !< loop indices
4754
4755    REAL(wp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg) :: tend !< pt tendency term
4756
4757    IF ( radiation_scheme == 'rrtmg' )  THEN
4758#if defined  ( __rrtmg )
4759!
4760!--    Calculate tendency based on heating rate
4761       DO  i = nxl, nxr
4762          DO  j = nys, nyn
4763             DO k = nzb+1, nzt+1
4764                tend(k,j,i) = tend(k,j,i) + ( rad_lw_hr(k,j,i)                 &
4765                                          +  rad_sw_hr(k,j,i) ) * d_exner(k)   &
4766                                          * d_seconds_hour
4767             ENDDO
4768          ENDDO
4769       ENDDO
4770#endif
4771    ENDIF
4772
4773
4774 END SUBROUTINE radiation_tendency
4775
4776!------------------------------------------------------------------------------!
4777! Description:
4778! ------------
4779!> This subroutine calculates interaction of the solar radiation
4780!> with urban and land surfaces and updates all surface heatfluxes.
4781!> It calculates also the required parameters for RRTMG lower BC.
4782!>
4783!> For more info. see Resler et al. 2017
4784!>
4785!> The new version 2.0 was radically rewriten, the discretization scheme
4786!> has been changed. This new version significantly improves effectivity
4787!> of the paralelization and the scalability of the model.
4788!------------------------------------------------------------------------------!
4789
4790 SUBROUTINE radiation_interaction
4791
4792     IMPLICIT NONE
4793
4794     INTEGER(iwp)                      :: i, j, k, kk, is, js, d, ku, refstep, m, mm, l, ll
4795     INTEGER(iwp)                      :: isurf, isurfsrc, isvf, icsf, ipcgb
4796     INTEGER(iwp)                      :: imrt, imrtf
4797     INTEGER(iwp)                      :: isd                !< solar direction number
4798     INTEGER(iwp)                      :: pc_box_dimshift    !< transform for best accuracy
4799     INTEGER(iwp), DIMENSION(0:3)      :: reorder = (/ 1, 0, 3, 2 /)
4800     
4801     REAL(wp), DIMENSION(3,3)          :: mrot               !< grid rotation matrix (zyx)
4802     REAL(wp), DIMENSION(3,0:nsurf_type):: vnorm             !< face direction normal vectors (zyx)
4803     REAL(wp), DIMENSION(3)            :: sunorig            !< grid rotated solar direction unit vector (zyx)
4804     REAL(wp), DIMENSION(3)            :: sunorig_grid       !< grid squashed solar direction unit vector (zyx)
4805     REAL(wp), DIMENSION(0:nsurf_type) :: costheta           !< direct irradiance factor of solar angle
4806     REAL(wp), DIMENSION(nzub:nzut)    :: pchf_prep          !< precalculated factor for canopy temperature tendency
4807     REAL(wp), PARAMETER               :: alpha = 0._wp      !< grid rotation (TODO: add to namelist or remove)
4808     REAL(wp)                          :: pc_box_area, pc_abs_frac, pc_abs_eff
4809     REAL(wp)                          :: asrc               !< area of source face
4810     REAL(wp)                          :: pcrad              !< irradiance from plant canopy
4811     REAL(wp)                          :: pabsswl  = 0.0_wp  !< total absorbed SW radiation energy in local processor (W)
4812     REAL(wp)                          :: pabssw   = 0.0_wp  !< total absorbed SW radiation energy in all processors (W)
4813     REAL(wp)                          :: pabslwl  = 0.0_wp  !< total absorbed LW radiation energy in local processor (W)
4814     REAL(wp)                          :: pabslw   = 0.0_wp  !< total absorbed LW radiation energy in all processors (W)
4815     REAL(wp)                          :: pemitlwl = 0.0_wp  !< total emitted LW radiation energy in all processors (W)
4816     REAL(wp)                          :: pemitlw  = 0.0_wp  !< total emitted LW radiation energy in all processors (W)
4817     REAL(wp)                          :: pinswl   = 0.0_wp  !< total received SW radiation energy in local processor (W)
4818     REAL(wp)                          :: pinsw    = 0.0_wp  !< total received SW radiation energy in all processor (W)
4819     REAL(wp)                          :: pinlwl   = 0.0_wp  !< total received LW radiation energy in local processor (W)
4820     REAL(wp)                          :: pinlw    = 0.0_wp  !< total received LW radiation energy in all processor (W)
4821     REAL(wp)                          :: emiss_sum_surfl    !< sum of emissisivity of surfaces in local processor
4822     REAL(wp)                          :: emiss_sum_surf     !< sum of emissisivity of surfaces in all processor
4823     REAL(wp)                          :: area_surfl         !< total area of surfaces in local processor
4824     REAL(wp)                          :: area_surf          !< total area of surfaces in all processor
4825     REAL(wp)                          :: area_hor           !< total horizontal area of domain in all processor
4826
4827#if ! defined( __nopointer )
4828     IF ( plant_canopy )  THEN
4829         pchf_prep(:) = r_d * exner(nzub:nzut)                                 &
4830                     / (c_p * hyp(nzub:nzut) * dx*dy*dz(1)) !< equals to 1 / (rho * c_p * Vbox * T)
4831     ENDIF
4832#endif
4833     sun_direction = .TRUE.
4834     CALL calc_zenith  !< required also for diffusion radiation
4835
4836!--     prepare rotated normal vectors and irradiance factor
4837     vnorm(1,:) = kdir(:)
4838     vnorm(2,:) = jdir(:)
4839     vnorm(3,:) = idir(:)
4840     mrot(1, :) = (/ 1._wp,  0._wp,      0._wp      /)
4841     mrot(2, :) = (/ 0._wp,  COS(alpha), SIN(alpha) /)
4842     mrot(3, :) = (/ 0._wp, -SIN(alpha), COS(alpha) /)
4843     sunorig = (/ zenith(0), sun_dir_lat, sun_dir_lon /)
4844     sunorig = MATMUL(mrot, sunorig)
4845     DO d = 0, nsurf_type
4846         costheta(d) = DOT_PRODUCT(sunorig, vnorm(:,d))
4847     ENDDO
4848
4849     IF ( zenith(0) > 0 )  THEN
4850!--      now we will "squash" the sunorig vector by grid box size in
4851!--      each dimension, so that this new direction vector will allow us
4852!--      to traverse the ray path within grid coordinates directly
4853         sunorig_grid = (/ sunorig(1)/dz(1), sunorig(2)/dy, sunorig(3)/dx /)
4854!--      sunorig_grid = sunorig_grid / norm2(sunorig_grid)
4855         sunorig_grid = sunorig_grid / SQRT(SUM(sunorig_grid**2))
4856
4857         IF ( npcbl > 0 )  THEN
4858!--         precompute effective box depth with prototype Leaf Area Density
4859            pc_box_dimshift = MAXLOC(ABS(sunorig), 1) - 1
4860            CALL box_absorb(CSHIFT((/dz(1),dy,dx/), pc_box_dimshift),       &
4861                                60, prototype_lad,                          &
4862                                CSHIFT(ABS(sunorig), pc_box_dimshift),      &
4863                                pc_box_area, pc_abs_frac)
4864            pc_box_area = pc_box_area * ABS(sunorig(pc_box_dimshift+1)      &
4865                          / sunorig(1))
4866            pc_abs_eff = LOG(1._wp - pc_abs_frac) / prototype_lad
4867         ENDIF
4868     ENDIF
4869
4870!--  if radiation scheme is not RRTMG, split diffusion and direct part of the solar downward radiation
4871!--  comming from radiation model and store it in 2D arrays
4872     IF (  radiation_scheme /= 'rrtmg'  )  CALL calc_diffusion_radiation
4873
4874!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4875!--     First pass: direct + diffuse irradiance + thermal
4876!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4877     surfinswdir   = 0._wp !nsurfl
4878     surfins       = 0._wp !nsurfl
4879     surfinl       = 0._wp !nsurfl
4880     surfoutsl(:)  = 0.0_wp !start-end
4881     surfoutll(:)  = 0.0_wp !start-end
4882     IF ( nmrtbl > 0 )  THEN
4883        mrtinsw(:) = 0._wp
4884        mrtinlw(:) = 0._wp
4885     ENDIF
4886     surfinlg(:)  = 0._wp !global
4887
4888
4889!--  Set up thermal radiation from surfaces
4890!--  emiss_surf is defined only for surfaces for which energy balance is calculated
4891!--  Workaround: reorder surface data type back on 1D array including all surfaces,
4892!--  which implies to reorder horizontal and vertical surfaces
4893!
4894!--  Horizontal walls
4895     mm = 1
4896     DO  i = nxl, nxr
4897        DO  j = nys, nyn
4898!--           urban
4899           DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
4900              surfoutll(mm) = SUM ( surf_usm_h%frac(:,m) *                  &
4901                                    surf_usm_h%emissivity(:,m) )            &
4902                                  * sigma_sb                                &
4903                                  * surf_usm_h%pt_surface(m)**4
4904              albedo_surf(mm) = SUM ( surf_usm_h%frac(:,m) *                &
4905                                      surf_usm_h%albedo(:,m) )
4906              emiss_surf(mm)  = SUM ( surf_usm_h%frac(:,m) *                &
4907                                      surf_usm_h%emissivity(:,m) )
4908              mm = mm + 1
4909           ENDDO
4910!--           land
4911           DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
4912              surfoutll(mm) = SUM ( surf_lsm_h%frac(:,m) *                  &
4913                                    surf_lsm_h%emissivity(:,m) )            &
4914                                  * sigma_sb                                &
4915                                  * surf_lsm_h%pt_surface(m)**4
4916              albedo_surf(mm) = SUM ( surf_lsm_h%frac(:,m) *                &
4917                                      surf_lsm_h%albedo(:,m) )
4918              emiss_surf(mm)  = SUM ( surf_lsm_h%frac(:,m) *                &
4919                                      surf_lsm_h%emissivity(:,m) )
4920              mm = mm + 1
4921           ENDDO
4922        ENDDO
4923     ENDDO
4924!
4925!--     Vertical walls
4926     DO  i = nxl, nxr
4927        DO  j = nys, nyn
4928           DO  ll = 0, 3
4929              l = reorder(ll)
4930!--              urban
4931              DO  m = surf_usm_v(l)%start_index(j,i),                       &
4932                      surf_usm_v(l)%end_index(j,i)
4933                 surfoutll(mm) = SUM ( surf_usm_v(l)%frac(:,m) *            &
4934                                       surf_usm_v(l)%emissivity(:,m) )      &
4935                                  * sigma_sb                                &
4936                                  * surf_usm_v(l)%pt_surface(m)**4
4937                 albedo_surf(mm) = SUM ( surf_usm_v(l)%frac(:,m) *          &
4938                                         surf_usm_v(l)%albedo(:,m) )
4939                 emiss_surf(mm)  = SUM ( surf_usm_v(l)%frac(:,m) *          &
4940                                         surf_usm_v(l)%emissivity(:,m) )
4941                 mm = mm + 1
4942              ENDDO
4943!--              land
4944              DO  m = surf_lsm_v(l)%start_index(j,i),                       &
4945                      surf_lsm_v(l)%end_index(j,i)
4946                 surfoutll(mm) = SUM ( surf_lsm_v(l)%frac(:,m) *            &
4947                                       surf_lsm_v(l)%emissivity(:,m) )      &
4948                                  * sigma_sb                                &
4949                                  * surf_lsm_v(l)%pt_surface(m)**4
4950                 albedo_surf(mm) = SUM ( surf_lsm_v(l)%frac(:,m) *          &
4951                                         surf_lsm_v(l)%albedo(:,m) )
4952                 emiss_surf(mm)  = SUM ( surf_lsm_v(l)%frac(:,m) *          &
4953                                         surf_lsm_v(l)%emissivity(:,m) )
4954                 mm = mm + 1
4955              ENDDO
4956           ENDDO
4957        ENDDO
4958     ENDDO
4959
4960#if defined( __parallel )
4961!--     might be optimized and gather only values relevant for current processor
4962     CALL MPI_AllGatherv(surfoutll, nsurfl, MPI_REAL, &
4963                         surfoutl, nsurfs, surfstart, MPI_REAL, comm2d, ierr) !nsurf global
4964     IF ( ierr /= 0 ) THEN
4965         WRITE(9,*) 'Error MPI_AllGatherv1:', ierr, SIZE(surfoutll), nsurfl, &
4966                     SIZE(surfoutl), nsurfs, surfstart
4967         FLUSH(9)
4968     ENDIF
4969#else
4970     surfoutl(:) = surfoutll(:) !nsurf global
4971#endif
4972
4973     IF ( surface_reflections)  THEN
4974        DO  isvf = 1, nsvfl
4975           isurf = svfsurf(1, isvf)
4976           k     = surfl(iz, isurf)
4977           j     = surfl(iy, isurf)
4978           i     = surfl(ix, isurf)
4979           isurfsrc = svfsurf(2, isvf)
4980!
4981!--        For surface-to-surface factors we calculate thermal radiation in 1st pass
4982           IF ( plant_lw_interact )  THEN
4983              surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * svf(2,isvf) * surfoutl(isurfsrc)
4984           ELSE
4985              surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * surfoutl(isurfsrc)
4986           ENDIF
4987        ENDDO
4988     ENDIF
4989!
4990!--  diffuse radiation using sky view factor
4991     DO isurf = 1, nsurfl
4992        j = surfl(iy, isurf)
4993        i = surfl(ix, isurf)
4994        surfinswdif(isurf) = rad_sw_in_diff(j,i) * skyvft(isurf)
4995        IF ( plant_lw_interact )  THEN
4996           surfinlwdif(isurf) = rad_lw_in_diff(j,i) * skyvft(isurf)
4997        ELSE
4998           surfinlwdif(isurf) = rad_lw_in_diff(j,i) * skyvf(isurf)
4999        ENDIF
5000     ENDDO
5001!
5002!--  MRT diffuse irradiance
5003     DO  imrt = 1, nmrtbl
5004        j = mrtbl(iy, imrt)
5005        i = mrtbl(ix, imrt)
5006        mrtinsw(imrt) = mrtskyt(imrt) * rad_sw_in_diff(j,i)
5007        mrtinlw(imrt) = mrtsky(imrt) * rad_lw_in_diff(j,i)
5008     ENDDO
5009
5010     !-- direct radiation
5011     IF ( zenith(0) > 0 )  THEN
5012        !--Identify solar direction vector (discretized number) 1)
5013        !--
5014        j = FLOOR(ACOS(zenith(0)) / pi * raytrace_discrete_elevs)
5015        i = MODULO(NINT(ATAN2(sun_dir_lon(0), sun_dir_lat(0))               &
5016                        / (2._wp*pi) * raytrace_discrete_azims-.5_wp, iwp), &
5017                   raytrace_discrete_azims)
5018        isd = dsidir_rev(j, i)
5019!-- TODO: check if isd = -1 to report that this solar position is not precalculated
5020        DO isurf = 1, nsurfl
5021           j = surfl(iy, isurf)
5022           i = surfl(ix, isurf)
5023           surfinswdir(isurf) = rad_sw_in_dir(j,i) *                        &
5024                costheta(surfl(id, isurf)) * dsitrans(isurf, isd) / zenith(0)
5025        ENDDO
5026!
5027!--     MRT direct irradiance
5028        DO  imrt = 1, nmrtbl
5029           j = mrtbl(iy, imrt)
5030           i = mrtbl(ix, imrt)
5031           mrtinsw(imrt) = mrtinsw(imrt) + mrtdsit(imrt, isd) * rad_sw_in_dir(j,i) &
5032                                     / zenith(0) / 4._wp ! normal to sphere
5033        ENDDO
5034     ENDIF
5035!
5036!--  MRT first pass thermal
5037     DO  imrtf = 1, nmrtf
5038        imrt = mrtfsurf(1, imrtf)
5039        isurfsrc = mrtfsurf(2, imrtf)
5040        mrtinlw(imrt) = mrtinlw(imrt) + mrtf(imrtf) * surfoutl(isurfsrc)
5041     ENDDO
5042
5043     IF ( npcbl > 0 )  THEN
5044
5045         pcbinswdir(:) = 0._wp
5046         pcbinswdif(:) = 0._wp
5047         pcbinlw(:) = 0._wp
5048!
5049!--      pcsf first pass
5050         DO icsf = 1, ncsfl
5051             ipcgb = csfsurf(1, icsf)
5052             i = pcbl(ix,ipcgb)
5053             j = pcbl(iy,ipcgb)
5054             k = pcbl(iz,ipcgb)
5055             isurfsrc = csfsurf(2, icsf)
5056
5057             IF ( isurfsrc == -1 )  THEN
5058!
5059!--             Diffuse rad from sky.
5060                pcbinswdif(ipcgb) = csf(1,icsf) * rad_sw_in_diff(j,i)
5061!
5062!--             Absorbed diffuse LW from sky minus emitted to sky
5063                IF ( plant_lw_interact )  THEN
5064                   pcbinlw(ipcgb) = csf(1,icsf)                                  &
5065                                       * (rad_lw_in_diff(j, i)                   &
5066                                          - sigma_sb * (pt(k,j,i)*exner(k))**4)
5067                ENDIF
5068!
5069!--             Direct rad
5070                IF ( zenith(0) > 0 )  THEN
5071!--                Estimate directed box absorption
5072                   pc_abs_frac = 1._wp - exp(pc_abs_eff * lad_s(k,j,i))
5073!
5074!--                isd has already been established, see 1)
5075                   pcbinswdir(ipcgb) = rad_sw_in_dir(j, i) * pc_box_area &
5076                                       * pc_abs_frac * dsitransc(ipcgb, isd)
5077                ENDIF
5078             ELSE
5079                IF ( plant_lw_interact )  THEN
5080!
5081!--                Thermal emission from plan canopy towards respective face
5082                   pcrad = sigma_sb * (pt(k,j,i) * exner(k))**4 * csf(1,icsf)
5083                   surfinlg(isurfsrc) = surfinlg(isurfsrc) + pcrad
5084!
5085!--                Remove the flux above + absorb LW from first pass from surfaces
5086                   asrc = facearea(surf(id, isurfsrc))
5087                   pcbinlw(ipcgb) = pcbinlw(ipcgb)                      &
5088                                    + (csf(1,icsf) * surfoutl(isurfsrc) & ! Absorb from first pass surf emit
5089                                       - pcrad)                         & ! Remove emitted heatflux
5090                                    * asrc
5091                ENDIF
5092             ENDIF
5093         ENDDO
5094
5095         pcbinsw(:) = pcbinswdir(:) + pcbinswdif(:)
5096     ENDIF
5097
5098     IF ( plant_lw_interact )  THEN
5099!
5100!--     Exchange incoming lw radiation from plant canopy
5101#if defined( __parallel )
5102        CALL MPI_Allreduce(MPI_IN_PLACE, surfinlg, nsurf, MPI_REAL, MPI_SUM, comm2d, ierr)
5103        IF ( ierr /= 0 )  THEN
5104           WRITE (9,*) 'Error MPI_Allreduce:', ierr
5105           FLUSH(9)
5106        ENDIF
5107        surfinl(:) = surfinl(:) + surfinlg(surfstart(myid)+1:surfstart(myid+1))
5108#else
5109        surfinl(:) = surfinl(:) + surfinlg(:)
5110#endif
5111     ENDIF
5112
5113     surfins = surfinswdir + surfinswdif
5114     surfinl = surfinl + surfinlwdif
5115     surfinsw = surfins
5116     surfinlw = surfinl
5117     surfoutsw = 0.0_wp
5118     surfoutlw = surfoutll
5119     surfemitlwl = surfoutll
5120
5121     IF ( .NOT.  surface_reflections )  THEN
5122!
5123!--     Set nrefsteps to 0 to disable reflections       
5124        nrefsteps = 0
5125        surfoutsl = albedo_surf * surfins
5126        surfoutll = (1._wp - emiss_surf) * surfinl
5127        surfoutsw = surfoutsw + surfoutsl
5128        surfoutlw = surfoutlw + surfoutll
5129     ENDIF
5130
5131!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5132!--     Next passes - reflections
5133!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5134     DO refstep = 1, nrefsteps
5135
5136         surfoutsl = albedo_surf * surfins
5137!--         for non-transparent surfaces, longwave albedo is 1 - emissivity
5138         surfoutll = (1._wp - emiss_surf) * surfinl
5139
5140#if defined( __parallel )
5141         CALL MPI_AllGatherv(surfoutsl, nsurfl, MPI_REAL, &
5142             surfouts, nsurfs, surfstart, MPI_REAL, comm2d, ierr)
5143         IF ( ierr /= 0 ) THEN
5144             WRITE(9,*) 'Error MPI_AllGatherv2:', ierr, SIZE(surfoutsl), nsurfl, &
5145                        SIZE(surfouts), nsurfs, surfstart
5146             FLUSH(9)
5147         ENDIF
5148
5149         CALL MPI_AllGatherv(surfoutll, nsurfl, MPI_REAL, &
5150             surfoutl, nsurfs, surfstart, MPI_REAL, comm2d, ierr)
5151         IF ( ierr /= 0 ) THEN
5152             WRITE(9,*) 'Error MPI_AllGatherv3:', ierr, SIZE(surfoutll), nsurfl, &
5153                        SIZE(surfoutl), nsurfs, surfstart
5154             FLUSH(9)
5155         ENDIF
5156
5157#else
5158         surfouts = surfoutsl
5159         surfoutl = surfoutll
5160#endif
5161
5162!--         reset for next pass input
5163         surfins = 0._wp
5164         surfinl = 0._wp
5165
5166!--         reflected radiation
5167         DO isvf = 1, nsvfl
5168             isurf = svfsurf(1, isvf)
5169             isurfsrc = svfsurf(2, isvf)
5170             surfins(isurf) = surfins(isurf) + svf(1,isvf) * svf(2,isvf) * surfouts(isurfsrc)
5171             IF ( plant_lw_interact )  THEN
5172                surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * svf(2,isvf) * surfoutl(isurfsrc)
5173             ELSE
5174                surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * surfoutl(isurfsrc)
5175             ENDIF
5176         ENDDO
5177!
5178!--      NOTE: PC absorbtion and MRT from reflected can both be done at once
5179!--      after all reflections if we do one more MPI_ALLGATHERV on surfout.
5180!--      Advantage: less local computation. Disadvantage: one more collective
5181!--      MPI call.
5182!
5183!--      Radiation absorbed by plant canopy
5184         DO  icsf = 1, ncsfl
5185             ipcgb = csfsurf(1, icsf)
5186             isurfsrc = csfsurf(2, icsf)
5187             IF ( isurfsrc == -1 )  CYCLE ! sky->face only in 1st pass, not here
5188!
5189!--          Calculate source surface area. If the `surf' array is removed
5190!--          before timestepping starts (future version), then asrc must be
5191!--          stored within `csf'
5192             asrc = facearea(surf(id, isurfsrc))
5193             pcbinsw(ipcgb) = pcbinsw(ipcgb) + csf(1,icsf) * surfouts(isurfsrc) * asrc
5194             IF ( plant_lw_interact )  THEN
5195                pcbinlw(ipcgb) = pcbinlw(ipcgb) + csf(1,icsf) * surfoutl(isurfsrc) * asrc
5196             ENDIF
5197         ENDDO
5198!
5199!--      MRT reflected
5200         DO  imrtf = 1, nmrtf
5201            imrt = mrtfsurf(1, imrtf)
5202            isurfsrc = mrtfsurf(2, imrtf)
5203            mrtinsw(imrt) = mrtinsw(imrt) + mrtft(imrtf) * surfouts(isurfsrc)
5204            mrtinlw(imrt) = mrtinlw(imrt) + mrtf(imrtf) * surfoutl(isurfsrc)
5205         ENDDO
5206
5207         surfinsw = surfinsw  + surfins
5208         surfinlw = surfinlw  + surfinl
5209         surfoutsw = surfoutsw + surfoutsl
5210         surfoutlw = surfoutlw + surfoutll
5211
5212     ENDDO ! refstep
5213
5214!--  push heat flux absorbed by plant canopy to respective 3D arrays
5215     IF ( npcbl > 0 )  THEN
5216         pc_heating_rate(:,:,:) = 0.0_wp
5217         DO ipcgb = 1, npcbl
5218             j = pcbl(iy, ipcgb)
5219             i = pcbl(ix, ipcgb)
5220             k = pcbl(iz, ipcgb)
5221!
5222!--          Following expression equals former kk = k - nzb_s_inner(j,i)
5223             kk = k - get_topography_top_index_ji( j, i, 's' )  !- lad arrays are defined flat
5224             pc_heating_rate(kk, j, i) = (pcbinsw(ipcgb) + pcbinlw(ipcgb)) &
5225                 * pchf_prep(k) * pt(k, j, i) !-- = dT/dt
5226         ENDDO
5227
5228         IF ( humidity .AND. plant_canopy_transpiration ) THEN
5229!--          Calculation of plant canopy transpiration rate and correspondidng latent heat rate
5230             pc_transpiration_rate(:,:,:) = 0.0_wp
5231             pc_latent_rate(:,:,:) = 0.0_wp
5232             DO ipcgb = 1, npcbl
5233                 i = pcbl(ix, ipcgb)
5234                 j = pcbl(iy, ipcgb)
5235                 k = pcbl(iz, ipcgb)
5236                 kk = k - get_topography_top_index_ji( j, i, 's' )  !- lad arrays are defined flat
5237                 CALL pcm_calc_transpiration_rate( i, j, k, kk, pcbinsw(ipcgb), pcbinlw(ipcgb), &
5238                                                   pc_transpiration_rate(kk,j,i), pc_latent_rate(kk,j,i) )
5239              ENDDO
5240         ENDIF
5241     ENDIF
5242!
5243!--  Calculate black body MRT (after all reflections)
5244     IF ( nmrtbl > 0 )  THEN
5245        IF ( mrt_include_sw )  THEN
5246           mrt(:) = ((mrtinsw(:) + mrtinlw(:)) / sigma_sb) ** .25_wp
5247        ELSE
5248           mrt(:) = (mrtinlw(:) / sigma_sb) ** .25_wp
5249        ENDIF
5250     ENDIF
5251!
5252!--     Transfer radiation arrays required for energy balance to the respective data types
5253     DO  i = 1, nsurfl
5254        m  = surfl(5,i)
5255!
5256!--     (1) Urban surfaces
5257!--     upward-facing
5258        IF ( surfl(1,i) == iup_u )  THEN
5259           surf_usm_h%rad_sw_in(m)  = surfinsw(i)
5260           surf_usm_h%rad_sw_out(m) = surfoutsw(i)
5261           surf_usm_h%rad_sw_dir(m) = surfinswdir(i)
5262           surf_usm_h%rad_sw_dif(m) = surfinswdif(i)
5263           surf_usm_h%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -        &
5264                                      surfinswdif(i)
5265           surf_usm_h%rad_sw_res(m) = surfins(i)
5266           surf_usm_h%rad_lw_in(m)  = surfinlw(i)
5267           surf_usm_h%rad_lw_out(m) = surfoutlw(i)
5268           surf_usm_h%rad_net(m)    = surfinsw(i) - surfoutsw(i) +          &
5269                                      surfinlw(i) - surfoutlw(i)
5270           surf_usm_h%rad_net_l(m)  = surf_usm_h%rad_net(m)
5271           surf_usm_h%rad_lw_dif(m) = surfinlwdif(i)
5272           surf_usm_h%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5273           surf_usm_h%rad_lw_res(m) = surfinl(i)
5274!
5275!--     northward-facding
5276        ELSEIF ( surfl(1,i) == inorth_u )  THEN
5277           surf_usm_v(0)%rad_sw_in(m)  = surfinsw(i)
5278           surf_usm_v(0)%rad_sw_out(m) = surfoutsw(i)
5279           surf_usm_v(0)%rad_sw_dir(m) = surfinswdir(i)
5280           surf_usm_v(0)%rad_sw_dif(m) = surfinswdif(i)
5281           surf_usm_v(0)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5282                                         surfinswdif(i)
5283           surf_usm_v(0)%rad_sw_res(m) = surfins(i)
5284           surf_usm_v(0)%rad_lw_in(m)  = surfinlw(i)
5285           surf_usm_v(0)%rad_lw_out(m) = surfoutlw(i)
5286           surf_usm_v(0)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5287                                         surfinlw(i) - surfoutlw(i)
5288           surf_usm_v(0)%rad_net_l(m)  = surf_usm_v(0)%rad_net(m)
5289           surf_usm_v(0)%rad_lw_dif(m) = surfinlwdif(i)
5290           surf_usm_v(0)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5291           surf_usm_v(0)%rad_lw_res(m) = surfinl(i)
5292!
5293!--     southward-facding
5294        ELSEIF ( surfl(1,i) == isouth_u )  THEN
5295           surf_usm_v(1)%rad_sw_in(m)  = surfinsw(i)
5296           surf_usm_v(1)%rad_sw_out(m) = surfoutsw(i)
5297           surf_usm_v(1)%rad_sw_dir(m) = surfinswdir(i)
5298           surf_usm_v(1)%rad_sw_dif(m) = surfinswdif(i)
5299           surf_usm_v(1)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5300                                         surfinswdif(i)
5301           surf_usm_v(1)%rad_sw_res(m) = surfins(i)
5302           surf_usm_v(1)%rad_lw_in(m)  = surfinlw(i)
5303           surf_usm_v(1)%rad_lw_out(m) = surfoutlw(i)
5304           surf_usm_v(1)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5305                                         surfinlw(i) - surfoutlw(i)
5306           surf_usm_v(1)%rad_net_l(m)  = surf_usm_v(1)%rad_net(m)
5307           surf_usm_v(1)%rad_lw_dif(m) = surfinlwdif(i)
5308           surf_usm_v(1)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5309           surf_usm_v(1)%rad_lw_res(m) = surfinl(i)
5310!
5311!--     eastward-facing
5312        ELSEIF ( surfl(1,i) == ieast_u )  THEN
5313           surf_usm_v(2)%rad_sw_in(m)  = surfinsw(i)
5314           surf_usm_v(2)%rad_sw_out(m) = surfoutsw(i)
5315           surf_usm_v(2)%rad_sw_dir(m) = surfinswdir(i)
5316           surf_usm_v(2)%rad_sw_dif(m) = surfinswdif(i)
5317           surf_usm_v(2)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5318                                         surfinswdif(i)
5319           surf_usm_v(2)%rad_sw_res(m) = surfins(i)
5320           surf_usm_v(2)%rad_lw_in(m)  = surfinlw(i)
5321           surf_usm_v(2)%rad_lw_out(m) = surfoutlw(i)
5322           surf_usm_v(2)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5323                                         surfinlw(i) - surfoutlw(i)
5324           surf_usm_v(2)%rad_net_l(m)  = surf_usm_v(2)%rad_net(m)
5325           surf_usm_v(2)%rad_lw_dif(m) = surfinlwdif(i)
5326           surf_usm_v(2)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5327           surf_usm_v(2)%rad_lw_res(m) = surfinl(i)
5328!
5329!--     westward-facding
5330        ELSEIF ( surfl(1,i) == iwest_u )  THEN
5331           surf_usm_v(3)%rad_sw_in(m)  = surfinsw(i)
5332           surf_usm_v(3)%rad_sw_out(m) = surfoutsw(i)
5333           surf_usm_v(3)%rad_sw_dir(m) = surfinswdir(i)
5334           surf_usm_v(3)%rad_sw_dif(m) = surfinswdif(i)
5335           surf_usm_v(3)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5336                                         surfinswdif(i)
5337           surf_usm_v(3)%rad_sw_res(m) = surfins(i)
5338           surf_usm_v(3)%rad_lw_in(m)  = surfinlw(i)
5339           surf_usm_v(3)%rad_lw_out(m) = surfoutlw(i)
5340           surf_usm_v(3)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5341                                         surfinlw(i) - surfoutlw(i)
5342           surf_usm_v(3)%rad_net_l(m)  = surf_usm_v(3)%rad_net(m)
5343           surf_usm_v(3)%rad_lw_dif(m) = surfinlwdif(i)
5344           surf_usm_v(3)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5345           surf_usm_v(3)%rad_lw_res(m) = surfinl(i)
5346!
5347!--     (2) land surfaces
5348!--     upward-facing
5349        ELSEIF ( surfl(1,i) == iup_l )  THEN
5350           surf_lsm_h%rad_sw_in(m)  = surfinsw(i)
5351           surf_lsm_h%rad_sw_out(m) = surfoutsw(i)
5352           surf_lsm_h%rad_sw_dir(m) = surfinswdir(i)
5353           surf_lsm_h%rad_sw_dif(m) = surfinswdif(i)
5354           surf_lsm_h%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -        &
5355                                         surfinswdif(i)
5356           surf_lsm_h%rad_sw_res(m) = surfins(i)
5357           surf_lsm_h%rad_lw_in(m)  = surfinlw(i)
5358           surf_lsm_h%rad_lw_out(m) = surfoutlw(i)
5359           surf_lsm_h%rad_net(m)    = surfinsw(i) - surfoutsw(i) +          &
5360                                      surfinlw(i) - surfoutlw(i)
5361           surf_lsm_h%rad_lw_dif(m) = surfinlwdif(i)
5362           surf_lsm_h%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5363           surf_lsm_h%rad_lw_res(m) = surfinl(i)
5364!
5365!--     northward-facding
5366        ELSEIF ( surfl(1,i) == inorth_l )  THEN
5367           surf_lsm_v(0)%rad_sw_in(m)  = surfinsw(i)
5368           surf_lsm_v(0)%rad_sw_out(m) = surfoutsw(i)
5369           surf_lsm_v(0)%rad_sw_dir(m) = surfinswdir(i)
5370           surf_lsm_v(0)%rad_sw_dif(m) = surfinswdif(i)
5371           surf_lsm_v(0)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5372                                         surfinswdif(i)
5373           surf_lsm_v(0)%rad_sw_res(m) = surfins(i)
5374           surf_lsm_v(0)%rad_lw_in(m)  = surfinlw(i)
5375           surf_lsm_v(0)%rad_lw_out(m) = surfoutlw(i)
5376           surf_lsm_v(0)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5377                                         surfinlw(i) - surfoutlw(i)
5378           surf_lsm_v(0)%rad_lw_dif(m) = surfinlwdif(i)
5379           surf_lsm_v(0)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5380           surf_lsm_v(0)%rad_lw_res(m) = surfinl(i)
5381!
5382!--     southward-facding
5383        ELSEIF ( surfl(1,i) == isouth_l )  THEN
5384           surf_lsm_v(1)%rad_sw_in(m)  = surfinsw(i)
5385           surf_lsm_v(1)%rad_sw_out(m) = surfoutsw(i)
5386           surf_lsm_v(1)%rad_sw_dir(m) = surfinswdir(i)
5387           surf_lsm_v(1)%rad_sw_dif(m) = surfinswdif(i)
5388           surf_lsm_v(1)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5389                                         surfinswdif(i)
5390           surf_lsm_v(1)%rad_sw_res(m) = surfins(i)
5391           surf_lsm_v(1)%rad_lw_in(m)  = surfinlw(i)
5392           surf_lsm_v(1)%rad_lw_out(m) = surfoutlw(i)
5393           surf_lsm_v(1)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5394                                         surfinlw(i) - surfoutlw(i)
5395           surf_lsm_v(1)%rad_lw_dif(m) = surfinlwdif(i)
5396           surf_lsm_v(1)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5397           surf_lsm_v(1)%rad_lw_res(m) = surfinl(i)
5398!
5399!--     eastward-facing
5400        ELSEIF ( surfl(1,i) == ieast_l )  THEN
5401           surf_lsm_v(2)%rad_sw_in(m)  = surfinsw(i)
5402           surf_lsm_v(2)%rad_sw_out(m) = surfoutsw(i)
5403           surf_lsm_v(2)%rad_sw_dir(m) = surfinswdir(i)
5404           surf_lsm_v(2)%rad_sw_dif(m) = surfinswdif(i)
5405           surf_lsm_v(2)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5406                                         surfinswdif(i)
5407           surf_lsm_v(2)%rad_sw_res(m) = surfins(i)
5408           surf_lsm_v(2)%rad_lw_in(m)  = surfinlw(i)
5409           surf_lsm_v(2)%rad_lw_out(m) = surfoutlw(i)
5410           surf_lsm_v(2)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5411                                         surfinlw(i) - surfoutlw(i)
5412           surf_lsm_v(2)%rad_lw_dif(m) = surfinlwdif(i)
5413           surf_lsm_v(2)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5414           surf_lsm_v(2)%rad_lw_res(m) = surfinl(i)
5415!
5416!--     westward-facing
5417        ELSEIF ( surfl(1,i) == iwest_l )  THEN
5418           surf_lsm_v(3)%rad_sw_in(m)  = surfinsw(i)
5419           surf_lsm_v(3)%rad_sw_out(m) = surfoutsw(i)
5420           surf_lsm_v(3)%rad_sw_dir(m) = surfinswdir(i)
5421           surf_lsm_v(3)%rad_sw_dif(m) = surfinswdif(i)
5422           surf_lsm_v(3)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5423                                         surfinswdif(i)
5424           surf_lsm_v(3)%rad_sw_res(m) = surfins(i)
5425           surf_lsm_v(3)%rad_lw_in(m)  = surfinlw(i)
5426           surf_lsm_v(3)%rad_lw_out(m) = surfoutlw(i)
5427           surf_lsm_v(3)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5428                                         surfinlw(i) - surfoutlw(i)
5429           surf_lsm_v(3)%rad_lw_dif(m) = surfinlwdif(i)
5430           surf_lsm_v(3)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5431           surf_lsm_v(3)%rad_lw_res(m) = surfinl(i)
5432        ENDIF
5433
5434     ENDDO
5435
5436     DO  m = 1, surf_usm_h%ns
5437        surf_usm_h%surfhf(m) = surf_usm_h%rad_sw_in(m)  +                   &
5438                               surf_usm_h%rad_lw_in(m)  -                   &
5439                               surf_usm_h%rad_sw_out(m) -                   &
5440                               surf_usm_h%rad_lw_out(m)
5441     ENDDO
5442     DO  m = 1, surf_lsm_h%ns
5443        surf_lsm_h%surfhf(m) = surf_lsm_h%rad_sw_in(m)  +                   &
5444                               surf_lsm_h%rad_lw_in(m)  -                   &
5445                               surf_lsm_h%rad_sw_out(m) -                   &
5446                               surf_lsm_h%rad_lw_out(m)
5447     ENDDO
5448
5449     DO  l = 0, 3
5450!--     urban
5451        DO  m = 1, surf_usm_v(l)%ns
5452           surf_usm_v(l)%surfhf(m) = surf_usm_v(l)%rad_sw_in(m)  +          &
5453                                     surf_usm_v(l)%rad_lw_in(m)  -          &
5454                                     surf_usm_v(l)%rad_sw_out(m) -          &
5455                                     surf_usm_v(l)%rad_lw_out(m)
5456        ENDDO
5457!--     land
5458        DO  m = 1, surf_lsm_v(l)%ns
5459           surf_lsm_v(l)%surfhf(m) = surf_lsm_v(l)%rad_sw_in(m)  +          &
5460                                     surf_lsm_v(l)%rad_lw_in(m)  -          &
5461                                     surf_lsm_v(l)%rad_sw_out(m) -          &
5462                                     surf_lsm_v(l)%rad_lw_out(m)
5463
5464        ENDDO
5465     ENDDO
5466!
5467!--  Calculate the average temperature, albedo, and emissivity for urban/land
5468!--  domain when using average_radiation in the respective radiation model
5469
5470!--  calculate horizontal area
5471! !!! ATTENTION!!! uniform grid is assumed here
5472     area_hor = (nx+1) * (ny+1) * dx * dy
5473!
5474!--  absorbed/received SW & LW and emitted LW energy of all physical
5475!--  surfaces (land and urban) in local processor
5476     pinswl = 0._wp
5477     pinlwl = 0._wp
5478     pabsswl = 0._wp
5479     pabslwl = 0._wp
5480     pemitlwl = 0._wp
5481     emiss_sum_surfl = 0._wp
5482     area_surfl = 0._wp
5483     DO  i = 1, nsurfl
5484        d = surfl(id, i)
5485!--  received SW & LW
5486        pinswl = pinswl + (surfinswdir(i) + surfinswdif(i)) * facearea(d)
5487        pinlwl = pinlwl + surfinlwdif(i) * facearea(d)
5488!--   absorbed SW & LW
5489        pabsswl = pabsswl + (1._wp - albedo_surf(i)) *                   &
5490                                                surfinsw(i) * facearea(d)
5491        pabslwl = pabslwl + emiss_surf(i) * surfinlw(i) * facearea(d)
5492!--   emitted LW
5493        pemitlwl = pemitlwl + surfemitlwl(i) * facearea(d)
5494!--   emissivity and area sum
5495        emiss_sum_surfl = emiss_sum_surfl + emiss_surf(i) * facearea(d)
5496        area_surfl = area_surfl + facearea(d)
5497     END DO
5498!
5499!--  add the absorbed SW energy by plant canopy
5500     IF ( npcbl > 0 )  THEN
5501        pabsswl = pabsswl + SUM(pcbinsw)
5502        pabslwl = pabslwl + SUM(pcbinlw)
5503        pinswl = pinswl + SUM(pcbinswdir) + SUM(pcbinswdif)
5504     ENDIF
5505!
5506!--  gather all rad flux energy in all processors
5507#if defined( __parallel )
5508     CALL MPI_ALLREDUCE( pinswl, pinsw, 1, MPI_REAL, MPI_SUM, comm2d, ierr)
5509     IF ( ierr /= 0 ) THEN
5510         WRITE(9,*) 'Error MPI_AllReduce5:', ierr, pinswl, pinsw
5511         FLUSH(9)
5512     ENDIF
5513     CALL MPI_ALLREDUCE( pinlwl, pinlw, 1, MPI_REAL, MPI_SUM, comm2d, ierr)
5514     IF ( ierr /= 0 ) THEN
5515         WRITE(9,*) 'Error MPI_AllReduce6:', ierr, pinlwl, pinlw
5516         FLUSH(9)
5517     ENDIF
5518     CALL MPI_ALLREDUCE( pabsswl, pabssw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5519     IF ( ierr /= 0 ) THEN
5520         WRITE(9,*) 'Error MPI_AllReduce7:', ierr, pabsswl, pabssw
5521         FLUSH(9)
5522     ENDIF
5523     CALL MPI_ALLREDUCE( pabslwl, pabslw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5524     IF ( ierr /= 0 ) THEN
5525         WRITE(9,*) 'Error MPI_AllReduce8:', ierr, pabslwl, pabslw
5526         FLUSH(9)
5527     ENDIF
5528     CALL MPI_ALLREDUCE( pemitlwl, pemitlw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5529     IF ( ierr /= 0 ) THEN
5530         WRITE(9,*) 'Error MPI_AllReduce8:', ierr, pemitlwl, pemitlw
5531         FLUSH(9)
5532     ENDIF
5533     CALL MPI_ALLREDUCE( emiss_sum_surfl, emiss_sum_surf, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5534     IF ( ierr /= 0 ) THEN
5535         WRITE(9,*) 'Error MPI_AllReduce9:', ierr, emiss_sum_surfl, emiss_sum_surf
5536         FLUSH(9)
5537     ENDIF
5538     CALL MPI_ALLREDUCE( area_surfl, area_surf, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5539     IF ( ierr /= 0 ) THEN
5540         WRITE(9,*) 'Error MPI_AllReduce10:', ierr, area_surfl, area_surf
5541         FLUSH(9)
5542     ENDIF
5543#else
5544     pinsw = pinswl
5545     pinlw = pinlwl
5546     pabssw = pabsswl
5547     pabslw = pabslwl
5548     pemitlw = pemitlwl
5549     emiss_sum_surf = emiss_sum_surfl
5550     area_surf = area_surfl
5551#endif
5552
5553!--  (1) albedo
5554     IF ( pinsw /= 0.0_wp )  &
5555          albedo_urb = (pinsw - pabssw) / pinsw
5556!--  (2) average emmsivity
5557     IF ( area_surf /= 0.0_wp ) &
5558          emissivity_urb = emiss_sum_surf / area_surf
5559!
5560!--  Temporally comment out calculation of effective radiative temperature.
5561!--  See below for more explanation.
5562!--  (3) temperature
5563!--   first we calculate an effective horizontal area to account for
5564!--   the effect of vertical surfaces (which contributes to LW emission)
5565!--   We simply use the ratio of the total LW to the incoming LW flux
5566      area_hor = pinlw/rad_lw_in_diff(nyn,nxl)
5567      t_rad_urb = ( (pemitlw - pabslw + emissivity_urb*pinlw) / &
5568           (emissivity_urb*sigma_sb * area_hor) )**0.25_wp
5569
5570    CONTAINS
5571
5572!------------------------------------------------------------------------------!
5573!> Calculates radiation absorbed by box with given size and LAD.
5574!>
5575!> Simulates resol**2 rays (by equally spacing a bounding horizontal square
5576!> conatining all possible rays that would cross the box) and calculates
5577!> average transparency per ray. Returns fraction of absorbed radiation flux
5578!> and area for which this fraction is effective.
5579!------------------------------------------------------------------------------!
5580    PURE SUBROUTINE box_absorb(boxsize, resol, dens, uvec, area, absorb)
5581       IMPLICIT NONE
5582
5583       REAL(wp), DIMENSION(3), INTENT(in) :: &
5584            boxsize, &      !< z, y, x size of box in m
5585            uvec            !< z, y, x unit vector of incoming flux
5586       INTEGER(iwp), INTENT(in) :: &
5587            resol           !< No. of rays in x and y dimensions
5588       REAL(wp), INTENT(in) :: &
5589            dens            !< box density (e.g. Leaf Area Density)
5590       REAL(wp), INTENT(out) :: &
5591            area, &         !< horizontal area for flux absorbtion
5592            absorb          !< fraction of absorbed flux
5593       REAL(wp) :: &
5594            xshift, yshift, &
5595            xmin, xmax, ymin, ymax, &
5596            xorig, yorig, &
5597            dx1, dy1, dz1, dx2, dy2, dz2, &
5598            crdist, &
5599            transp
5600       INTEGER(iwp) :: &
5601            i, j
5602
5603       xshift = uvec(3) / uvec(1) * boxsize(1)
5604       xmin = min(0._wp, -xshift)
5605       xmax = boxsize(3) + max(0._wp, -xshift)
5606       yshift = uvec(2) / uvec(1) * boxsize(1)
5607       ymin = min(0._wp, -yshift)
5608       ymax = boxsize(2) + max(0._wp, -yshift)
5609
5610       transp = 0._wp
5611       DO i = 1, resol
5612          xorig = xmin + (xmax-xmin) * (i-.5_wp) / resol
5613          DO j = 1, resol
5614             yorig = ymin + (ymax-ymin) * (j-.5_wp) / resol
5615
5616             dz1 = 0._wp
5617             dz2 = boxsize(1)/uvec(1)
5618
5619             IF ( uvec(2) > 0._wp )  THEN
5620                dy1 = -yorig             / uvec(2) !< crossing with y=0
5621                dy2 = (boxsize(2)-yorig) / uvec(2) !< crossing with y=boxsize(2)
5622             ELSE !uvec(2)==0
5623                dy1 = -huge(1._wp)
5624                dy2 = huge(1._wp)
5625             ENDIF
5626
5627             IF ( uvec(3) > 0._wp )  THEN
5628                dx1 = -xorig             / uvec(3) !< crossing with x=0
5629                dx2 = (boxsize(3)-xorig) / uvec(3) !< crossing with x=boxsize(3)
5630             ELSE !uvec(3)==0
5631                dx1 = -huge(1._wp)
5632                dx2 = huge(1._wp)
5633             ENDIF
5634
5635             crdist = max(0._wp, (min(dz2, dy2, dx2) - max(dz1, dy1, dx1)))
5636             transp = transp + exp(-ext_coef * dens * crdist)
5637          ENDDO
5638       ENDDO
5639       transp = transp / resol**2
5640       area = (boxsize(3)+xshift)*(boxsize(2)+yshift)
5641       absorb = 1._wp - transp
5642
5643    END SUBROUTINE box_absorb
5644
5645!------------------------------------------------------------------------------!
5646! Description:
5647! ------------
5648!> This subroutine splits direct and diffusion dw radiation
5649!> It sould not be called in case the radiation model already does it
5650!> It follows <CITATION>
5651!------------------------------------------------------------------------------!
5652    SUBROUTINE calc_diffusion_radiation 
5653   
5654        REAL(wp), PARAMETER                          :: lowest_solarUp = 0.1_wp  !< limit the sun elevation to protect stability of the calculation
5655        INTEGER(iwp)                                 :: i, j
5656        REAL(wp)                                     ::  year_angle              !< angle
5657        REAL(wp)                                     ::  etr                     !< extraterestrial radiation
5658        REAL(wp)                                     ::  corrected_solarUp       !< corrected solar up radiation
5659        REAL(wp)                                     ::  horizontalETR           !< horizontal extraterestrial radiation
5660        REAL(wp)                                     ::  clearnessIndex          !< clearness index
5661        REAL(wp)                                     ::  diff_frac               !< diffusion fraction of the radiation
5662
5663       
5664!--     Calculate current day and time based on the initial values and simulation time
5665        year_angle = ( (day_of_year_init * 86400) + time_utc_init              &
5666                        + time_since_reference_point )  * d_seconds_year       &
5667                        * 2.0_wp * pi
5668       
5669        etr = solar_constant * (1.00011_wp +                                   &
5670                          0.034221_wp * cos(year_angle) +                      &
5671                          0.001280_wp * sin(year_angle) +                      &
5672                          0.000719_wp * cos(2.0_wp * year_angle) +             &
5673                          0.000077_wp * sin(2.0_wp * year_angle))
5674       
5675!--   
5676!--     Under a very low angle, we keep extraterestrial radiation at
5677!--     the last small value, therefore the clearness index will be pushed
5678!--     towards 0 while keeping full continuity.
5679!--   
5680        IF ( zenith(0) <= lowest_solarUp )  THEN
5681            corrected_solarUp = lowest_solarUp
5682        ELSE
5683            corrected_solarUp = zenith(0)
5684        ENDIF
5685       
5686        horizontalETR = etr * corrected_solarUp
5687       
5688        DO i = nxl, nxr
5689            DO j = nys, nyn
5690                clearnessIndex = rad_sw_in(0,j,i) / horizontalETR
5691                diff_frac = 1.0_wp / (1.0_wp + exp(-5.0033_wp + 8.6025_wp * clearnessIndex))
5692                rad_sw_in_diff(j,i) = rad_sw_in(0,j,i) * diff_frac
5693                rad_sw_in_dir(j,i)  = rad_sw_in(0,j,i) * (1.0_wp - diff_frac)
5694                rad_lw_in_diff(j,i) = rad_lw_in(0,j,i)
5695            ENDDO
5696        ENDDO
5697       
5698    END SUBROUTINE calc_diffusion_radiation
5699
5700
5701 END SUBROUTINE radiation_interaction
5702   
5703!------------------------------------------------------------------------------!
5704! Description:
5705! ------------
5706!> This subroutine initializes structures needed for radiative transfer
5707!> model. This model calculates transformation processes of the
5708!> radiation inside urban and land canopy layer. The module includes also
5709!> the interaction of the radiation with the resolved plant canopy.
5710!>
5711!> For more info. see Resler et al. 2017
5712!>
5713!> The new version 2.0 was radically rewriten, the discretization scheme
5714!> has been changed. This new version significantly improves effectivity
5715!> of the paralelization and the scalability of the model.
5716!>
5717!------------------------------------------------------------------------------!
5718    SUBROUTINE radiation_interaction_init
5719
5720       USE control_parameters,                                                 &
5721           ONLY:  dz_stretch_level_start
5722           
5723       USE netcdf_data_input_mod,                                              &
5724           ONLY:  leaf_area_density_f
5725
5726       USE plant_canopy_model_mod,                                             &
5727           ONLY:  pch_index, lad_s
5728
5729       IMPLICIT NONE
5730
5731       INTEGER(iwp) :: i, j, k, l, m, d
5732       INTEGER(iwp) :: k_topo     !< vertical index indicating topography top for given (j,i)
5733       INTEGER(iwp) :: nzptl, nzubl, nzutl, isurf, ipcgb, imrt
5734       REAL(wp)     :: mrl
5735#if defined( __parallel )
5736       INTEGER(iwp), DIMENSION(:), POINTER       ::  gridsurf_rma   !< fortran pointer, but lower bounds are 1
5737       TYPE(c_ptr)                               ::  gridsurf_rma_p !< allocated c pointer
5738       INTEGER(iwp)                              ::  minfo          !< MPI RMA window info handle
5739#endif
5740
5741!
5742!--     precalculate face areas for different face directions using normal vector
5743        DO d = 0, nsurf_type
5744            facearea(d) = 1._wp
5745            IF ( idir(d) == 0 ) facearea(d) = facearea(d) * dx
5746            IF ( jdir(d) == 0 ) facearea(d) = facearea(d) * dy
5747            IF ( kdir(d) == 0 ) facearea(d) = facearea(d) * dz(1)
5748        ENDDO
5749!
5750!--    Find nzub, nzut, nzu via wall_flag_0 array (nzb_s_inner will be
5751!--    removed later). The following contruct finds the lowest / largest index
5752!--    for any upward-facing wall (see bit 12).
5753       nzubl = MINVAL( get_topography_top_index( 's' ) )
5754       nzutl = MAXVAL( get_topography_top_index( 's' ) )
5755
5756       nzubl = MAX( nzubl, nzb )
5757
5758       IF ( plant_canopy )  THEN
5759!--        allocate needed arrays
5760           ALLOCATE( pct(nys:nyn,nxl:nxr) )
5761           ALLOCATE( pch(nys:nyn,nxl:nxr) )
5762
5763!--        calculate plant canopy height
5764           npcbl = 0
5765           pct   = 0
5766           pch   = 0
5767           DO i = nxl, nxr
5768               DO j = nys, nyn
5769!
5770!--                Find topography top index
5771                   k_topo = get_topography_top_index_ji( j, i, 's' )
5772
5773                   DO k = nzt+1, 0, -1
5774                       IF ( lad_s(k,j,i) /= 0.0_wp )  THEN
5775!--                        we are at the top of the pcs
5776                           pct(j,i) = k + k_topo
5777                           pch(j,i) = k
5778                           npcbl = npcbl + pch(j,i)
5779                           EXIT
5780                       ENDIF
5781                   ENDDO
5782               ENDDO
5783           ENDDO
5784
5785           nzutl = MAX( nzutl, MAXVAL( pct ) )
5786           nzptl = MAXVAL( pct )
5787!--        code of plant canopy model uses parameter pch_index
5788!--        we need to setup it here to right value
5789!--        (pch_index, lad_s and other arrays in PCM are defined flat)
5790           pch_index = MERGE( leaf_area_density_f%nz - 1, MAXVAL( pch ),       &
5791                              leaf_area_density_f%from_file )
5792
5793           prototype_lad = MAXVAL( lad_s ) * .9_wp  !< better be *1.0 if lad is either 0 or maxval(lad) everywhere
5794           IF ( prototype_lad <= 0._wp ) prototype_lad = .3_wp
5795           !WRITE(message_string, '(a,f6.3)') 'Precomputing effective box optical ' &
5796           !    // 'depth using prototype leaf area density = ', prototype_lad
5797           !CALL message('usm_init_urban_surface', 'PA0520', 0, 0, -1, 6, 0)
5798       ENDIF
5799
5800       nzutl = MIN( nzutl + nzut_free, nzt )
5801
5802#if defined( __parallel )
5803       CALL MPI_AllReduce(nzubl, nzub, 1, MPI_INTEGER, MPI_MIN, comm2d, ierr )
5804       IF ( ierr /= 0 ) THEN
5805           WRITE(9,*) 'Error MPI_AllReduce11:', ierr, nzubl, nzub
5806           FLUSH(9)
5807       ENDIF
5808       CALL MPI_AllReduce(nzutl, nzut, 1, MPI_INTEGER, MPI_MAX, comm2d, ierr )
5809       IF ( ierr /= 0 ) THEN
5810           WRITE(9,*) 'Error MPI_AllReduce12:', ierr, nzutl, nzut
5811           FLUSH(9)
5812       ENDIF
5813       CALL MPI_AllReduce(nzptl, nzpt, 1, MPI_INTEGER, MPI_MAX, comm2d, ierr )
5814       IF ( ierr /= 0 ) THEN
5815           WRITE(9,*) 'Error MPI_AllReduce13:', ierr, nzptl, nzpt
5816           FLUSH(9)
5817       ENDIF
5818#else
5819       nzub = nzubl
5820       nzut = nzutl
5821       nzpt = nzptl
5822#endif
5823!
5824!--    Stretching (non-uniform grid spacing) is not considered in the radiation
5825!--    model. Therefore, vertical stretching has to be applied above the area
5826!--    where the parts of the radiation model which assume constant grid spacing
5827!--    are active. ABS (...) is required because the default value of
5828!--    dz_stretch_level_start is -9999999.9_wp (negative).
5829       IF ( ABS( dz_stretch_level_start(1) ) <= zw(nzut) ) THEN
5830          WRITE( message_string, * ) 'The lowest level where vertical ',       &
5831                                     'stretching is applied have to be ',      &
5832                                     'greater than ', zw(nzut)
5833          CALL message( 'radiation_interaction_init', 'PA0496', 1, 2, 0, 6, 0 )
5834       ENDIF 
5835!
5836!--    global number of urban and plant layers
5837       nzu = nzut - nzub + 1
5838       nzp = nzpt - nzub + 1
5839!
5840!--    check max_raytracing_dist relative to urban surface layer height
5841       mrl = 2.0_wp * nzu * dz(1)
5842!--    set max_raytracing_dist to double the urban surface layer height, if not set
5843       IF ( max_raytracing_dist == -999.0_wp ) THEN
5844          max_raytracing_dist = mrl
5845       ENDIF
5846!--    check if max_raytracing_dist set too low (here we only warn the user. Other
5847!      option is to correct the value again to double the urban surface layer height)
5848       IF ( max_raytracing_dist  <  mrl ) THEN
5849          WRITE(message_string, '(a,f6.1)') 'Max_raytracing_dist is set less than ', &
5850               'double the urban surface layer height, i.e. ', mrl
5851          CALL message('radiation_interaction_init', 'PA0521', 0, 0, -1, 6, 0)
5852       ENDIF
5853!        IF ( max_raytracing_dist <= mrl ) THEN
5854!           IF ( max_raytracing_dist /= -999.0_wp ) THEN
5855! !--          max_raytracing_dist too low
5856!              WRITE(message_string, '(a,f6.1)') 'Max_raytracing_dist too low, ' &
5857!                    // 'override to value ', mrl
5858!              CALL message('radiation_interaction_init', 'PA0521', 0, 0, -1, 6, 0)
5859!           ENDIF
5860!           max_raytracing_dist = mrl
5861!        ENDIF
5862!
5863!--    allocate urban surfaces grid
5864!--    calc number of surfaces in local proc
5865       CALL location_message( '    calculation of indices for surfaces', .TRUE. )
5866       nsurfl = 0
5867!
5868!--    Number of horizontal surfaces including land- and roof surfaces in both USM and LSM. Note that
5869!--    All horizontal surface elements are already counted in surface_mod.
5870       startland = 1
5871       nsurfl    = surf_usm_h%ns + surf_lsm_h%ns
5872       endland   = nsurfl
5873       nlands    = endland - startland + 1
5874
5875!
5876!--    Number of vertical surfaces in both USM and LSM. Note that all vertical surface elements are
5877!--    already counted in surface_mod.
5878       startwall = nsurfl+1
5879       DO  i = 0,3
5880          nsurfl = nsurfl + surf_usm_v(i)%ns + surf_lsm_v(i)%ns
5881       ENDDO
5882       endwall = nsurfl
5883       nwalls  = endwall - startwall + 1
5884       dirstart = (/ startland, startwall, startwall, startwall, startwall /)
5885       dirend = (/ endland, endwall, endwall, endwall, endwall /)
5886
5887!--    fill gridpcbl and pcbl
5888       IF ( npcbl > 0 )  THEN
5889           ALLOCATE( pcbl(iz:ix, 1:npcbl) )
5890           ALLOCATE( gridpcbl(nzub:nzpt,nys:nyn,nxl:nxr) )
5891           pcbl = -1
5892           gridpcbl(:,:,:) = 0
5893           ipcgb = 0
5894           DO i = nxl, nxr
5895               DO j = nys, nyn
5896!
5897!--                Find topography top index
5898                   k_topo = get_topography_top_index_ji( j, i, 's' )
5899
5900                   DO k = k_topo + 1, pct(j,i)
5901                       ipcgb = ipcgb + 1
5902                       gridpcbl(k,j,i) = ipcgb
5903                       pcbl(:,ipcgb) = (/ k, j, i /)
5904                   ENDDO
5905               ENDDO
5906           ENDDO
5907           ALLOCATE( pcbinsw( 1:npcbl ) )
5908           ALLOCATE( pcbinswdir( 1:npcbl ) )
5909           ALLOCATE( pcbinswdif( 1:npcbl ) )
5910           ALLOCATE( pcbinlw( 1:npcbl ) )
5911       ENDIF
5912
5913!--    fill surfl (the ordering of local surfaces given by the following
5914!--    cycles must not be altered, certain file input routines may depend
5915!--    on it)
5916       ALLOCATE(surfl_l(5*nsurfl))  ! is it necessary to allocate it with (5,nsurfl)?
5917       surfl(1:5,1:nsurfl) => surfl_l(1:5*nsurfl)
5918       isurf = 0
5919       IF ( rad_angular_discretization )  THEN
5920!
5921!--       Allocate and fill the reverse indexing array gridsurf
5922#if defined( __parallel )
5923!
5924!--       raytrace_mpi_rma is asserted
5925
5926          CALL MPI_Info_create(minfo, ierr)
5927          IF ( ierr /= 0 ) THEN
5928              WRITE(9,*) 'Error MPI_Info_create1:', ierr
5929              FLUSH(9)
5930          ENDIF
5931          CALL MPI_Info_set(minfo, 'accumulate_ordering', '', ierr)
5932          IF ( ierr /= 0 ) THEN
5933              WRITE(9,*) 'Error MPI_Info_set1:', ierr
5934              FLUSH(9)
5935          ENDIF
5936          CALL MPI_Info_set(minfo, 'accumulate_ops', 'same_op', ierr)
5937          IF ( ierr /= 0 ) THEN
5938              WRITE(9,*) 'Error MPI_Info_set2:', ierr
5939              FLUSH(9)
5940          ENDIF
5941          CALL MPI_Info_set(minfo, 'same_size', 'true', ierr)
5942          IF ( ierr /= 0 ) THEN
5943              WRITE(9,*) 'Error MPI_Info_set3:', ierr
5944              FLUSH(9)
5945          ENDIF
5946          CALL MPI_Info_set(minfo, 'same_disp_unit', 'true', ierr)
5947          IF ( ierr /= 0 ) THEN
5948              WRITE(9,*) 'Error MPI_Info_set4:', ierr
5949              FLUSH(9)
5950          ENDIF
5951
5952          CALL MPI_Win_allocate(INT(STORAGE_SIZE(1_iwp)/8*nsurf_type_u*nzu*nny*nnx, &
5953                                    kind=MPI_ADDRESS_KIND), STORAGE_SIZE(1_iwp)/8,  &
5954                                minfo, comm2d, gridsurf_rma_p, win_gridsurf, ierr)
5955          IF ( ierr /= 0 ) THEN
5956              WRITE(9,*) 'Error MPI_Win_allocate1:', ierr, &
5957                 INT(STORAGE_SIZE(1_iwp)/8*nsurf_type_u*nzu*nny*nnx,kind=MPI_ADDRESS_KIND), &
5958                 STORAGE_SIZE(1_iwp)/8, win_gridsurf
5959              FLUSH(9)
5960          ENDIF
5961
5962          CALL MPI_Info_free(minfo, ierr)
5963          IF ( ierr /= 0 ) THEN
5964              WRITE(9,*) 'Error MPI_Info_free1:', ierr
5965              FLUSH(9)
5966          ENDIF
5967
5968!
5969!--       On Intel compilers, calling c_f_pointer to transform a C pointer
5970!--       directly to a multi-dimensional Fotran pointer leads to strange
5971!--       errors on dimension boundaries. However, transforming to a 1D
5972!--       pointer and then redirecting a multidimensional pointer to it works
5973!--       fine.
5974          CALL c_f_pointer(gridsurf_rma_p, gridsurf_rma, (/ nsurf_type_u*nzu*nny*nnx /))
5975          gridsurf(0:nsurf_type_u-1, nzub:nzut, nys:nyn, nxl:nxr) =>                &
5976                     gridsurf_rma(1:nsurf_type_u*nzu*nny*nnx)
5977#else
5978          ALLOCATE(gridsurf(0:nsurf_type_u-1,nzub:nzut,nys:nyn,nxl:nxr) )
5979#endif
5980          gridsurf(:,:,:,:) = -999
5981       ENDIF
5982
5983!--    add horizontal surface elements (land and urban surfaces)
5984!--    TODO: add urban overhanging surfaces (idown_u)
5985       DO i = nxl, nxr
5986           DO j = nys, nyn
5987              DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
5988                 k = surf_usm_h%k(m)
5989                 isurf = isurf + 1
5990                 surfl(:,isurf) = (/iup_u,k,j,i,m/)
5991                 IF ( rad_angular_discretization ) THEN
5992                    gridsurf(iup_u,k,j,i) = isurf
5993                 ENDIF
5994              ENDDO
5995
5996              DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
5997                 k = surf_lsm_h%k(m)
5998                 isurf = isurf + 1
5999                 surfl(:,isurf) = (/iup_l,k,j,i,m/)
6000                 IF ( rad_angular_discretization ) THEN
6001                    gridsurf(iup_u,k,j,i) = isurf
6002                 ENDIF
6003              ENDDO
6004
6005           ENDDO
6006       ENDDO
6007
6008!--    add vertical surface elements (land and urban surfaces)
6009!--    TODO: remove the hard coding of l = 0 to l = idirection
6010       DO i = nxl, nxr
6011           DO j = nys, nyn
6012              l = 0
6013              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6014                 k = surf_usm_v(l)%k(m)
6015                 isurf = isurf + 1
6016                 surfl(:,isurf) = (/inorth_u,k,j,i,m/)
6017                 IF ( rad_angular_discretization ) THEN
6018                    gridsurf(inorth_u,k,j,i) = isurf
6019                 ENDIF
6020              ENDDO
6021              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6022                 k = surf_lsm_v(l)%k(m)
6023                 isurf = isurf + 1
6024                 surfl(:,isurf) = (/inorth_l,k,j,i,m/)
6025                 IF ( rad_angular_discretization ) THEN
6026                    gridsurf(inorth_u,k,j,i) = isurf
6027                 ENDIF
6028              ENDDO
6029
6030              l = 1
6031              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6032                 k = surf_usm_v(l)%k(m)
6033                 isurf = isurf + 1
6034                 surfl(:,isurf) = (/isouth_u,k,j,i,m/)
6035                 IF ( rad_angular_discretization ) THEN
6036                    gridsurf(isouth_u,k,j,i) = isurf
6037                 ENDIF
6038              ENDDO
6039              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6040                 k = surf_lsm_v(l)%k(m)
6041                 isurf = isurf + 1
6042                 surfl(:,isurf) = (/isouth_l,k,j,i,m/)
6043                 IF ( rad_angular_discretization ) THEN
6044                    gridsurf(isouth_u,k,j,i) = isurf
6045                 ENDIF
6046              ENDDO
6047
6048              l = 2
6049              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6050                 k = surf_usm_v(l)%k(m)
6051                 isurf = isurf + 1
6052                 surfl(:,isurf) = (/ieast_u,k,j,i,m/)
6053                 IF ( rad_angular_discretization ) THEN
6054                    gridsurf(ieast_u,k,j,i) = isurf
6055                 ENDIF
6056              ENDDO
6057              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6058                 k = surf_lsm_v(l)%k(m)
6059                 isurf = isurf + 1
6060                 surfl(:,isurf) = (/ieast_l,k,j,i,m/)
6061                 IF ( rad_angular_discretization ) THEN
6062                    gridsurf(ieast_u,k,j,i) = isurf
6063                 ENDIF
6064              ENDDO
6065
6066              l = 3
6067              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6068                 k = surf_usm_v(l)%k(m)
6069                 isurf = isurf + 1
6070                 surfl(:,isurf) = (/iwest_u,k,j,i,m/)
6071                 IF ( rad_angular_discretization ) THEN
6072                    gridsurf(iwest_u,k,j,i) = isurf
6073                 ENDIF
6074              ENDDO
6075              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6076                 k = surf_lsm_v(l)%k(m)
6077                 isurf = isurf + 1
6078                 surfl(:,isurf) = (/iwest_l,k,j,i,m/)
6079                 IF ( rad_angular_discretization ) THEN
6080                    gridsurf(iwest_u,k,j,i) = isurf
6081                 ENDIF
6082              ENDDO
6083           ENDDO
6084       ENDDO
6085!
6086!--    Add local MRT boxes for specified number of levels
6087       nmrtbl = 0
6088       IF ( mrt_nlevels > 0 )  THEN
6089          DO  i = nxl, nxr
6090             DO  j = nys, nyn
6091                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
6092!
6093!--                Skip roof if requested
6094                   IF ( mrt_skip_roof  .AND.  surf_usm_h%isroof_surf(m) )  CYCLE
6095!
6096!--                Cycle over specified no of levels
6097                   nmrtbl = nmrtbl + mrt_nlevels
6098                ENDDO
6099!
6100!--             Dtto for LSM
6101                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6102                   nmrtbl = nmrtbl + mrt_nlevels
6103                ENDDO
6104             ENDDO
6105          ENDDO
6106
6107          ALLOCATE( mrtbl(iz:ix,nmrtbl), mrtsky(nmrtbl), mrtskyt(nmrtbl), &
6108                    mrtinsw(nmrtbl), mrtinlw(nmrtbl), mrt(nmrtbl) )
6109
6110          imrt = 0
6111          DO  i = nxl, nxr
6112             DO  j = nys, nyn
6113                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
6114!
6115!--                Skip roof if requested
6116                   IF ( mrt_skip_roof  .AND.  surf_usm_h%isroof_surf(m) )  CYCLE
6117!
6118!--                Cycle over specified no of levels
6119                   l = surf_usm_h%k(m)
6120                   DO  k = l, l + mrt_nlevels - 1
6121                      imrt = imrt + 1
6122                      mrtbl(:,imrt) = (/k,j,i/)
6123                   ENDDO
6124                ENDDO
6125!
6126!--             Dtto for LSM
6127                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6128                   l = surf_lsm_h%k(m)
6129                   DO  k = l, l + mrt_nlevels - 1
6130                      imrt = imrt + 1
6131                      mrtbl(:,imrt) = (/k,j,i/)
6132                   ENDDO
6133                ENDDO
6134             ENDDO
6135          ENDDO
6136       ENDIF
6137
6138!
6139!--    broadband albedo of the land, roof and wall surface
6140!--    for domain border and sky set artifically to 1.0
6141!--    what allows us to calculate heat flux leaving over
6142!--    side and top borders of the domain
6143       ALLOCATE ( albedo_surf(nsurfl) )
6144       albedo_surf = 1.0_wp
6145!
6146!--    Also allocate further array for emissivity with identical order of
6147!--    surface elements as radiation arrays.
6148       ALLOCATE ( emiss_surf(nsurfl)  )
6149
6150
6151!
6152!--    global array surf of indices of surfaces and displacement index array surfstart
6153       ALLOCATE(nsurfs(0:numprocs-1))
6154
6155#if defined( __parallel )
6156       CALL MPI_Allgather(nsurfl,1,MPI_INTEGER,nsurfs,1,MPI_INTEGER,comm2d,ierr)
6157       IF ( ierr /= 0 ) THEN
6158         WRITE(9,*) 'Error MPI_AllGather1:', ierr, nsurfl, nsurfs
6159         FLUSH(9)
6160     ENDIF
6161
6162#else
6163       nsurfs(0) = nsurfl
6164#endif
6165       ALLOCATE(surfstart(0:numprocs))
6166       k = 0
6167       DO i=0,numprocs-1
6168           surfstart(i) = k
6169           k = k+nsurfs(i)
6170       ENDDO
6171       surfstart(numprocs) = k
6172       nsurf = k
6173       ALLOCATE(surf_l(5*nsurf))
6174       surf(1:5,1:nsurf) => surf_l(1:5*nsurf)
6175
6176#if defined( __parallel )
6177       CALL MPI_AllGatherv(surfl_l, nsurfl*5, MPI_INTEGER, surf_l, nsurfs*5, &
6178           surfstart(0:numprocs-1)*5, MPI_INTEGER, comm2d, ierr)
6179       IF ( ierr /= 0 ) THEN
6180           WRITE(9,*) 'Error MPI_AllGatherv4:', ierr, SIZE(surfl_l), nsurfl*5, &
6181                      SIZE(surf_l), nsurfs*5, surfstart(0:numprocs-1)*5
6182           FLUSH(9)
6183       ENDIF
6184#else
6185       surf = surfl
6186#endif
6187
6188!--
6189!--    allocation of the arrays for direct and diffusion radiation
6190       CALL location_message( '    allocation of radiation arrays', .TRUE. )
6191!--    rad_sw_in, rad_lw_in are computed in radiation model,
6192!--    splitting of direct and diffusion part is done
6193!--    in calc_diffusion_radiation for now
6194
6195       ALLOCATE( rad_sw_in_dir(nysg:nyng,nxlg:nxrg) )
6196       ALLOCATE( rad_sw_in_diff(nysg:nyng,nxlg:nxrg) )
6197       ALLOCATE( rad_lw_in_diff(nysg:nyng,nxlg:nxrg) )
6198       rad_sw_in_dir  = 0.0_wp
6199       rad_sw_in_diff = 0.0_wp
6200       rad_lw_in_diff = 0.0_wp
6201
6202!--    allocate radiation arrays
6203       ALLOCATE( surfins(nsurfl) )
6204       ALLOCATE( surfinl(nsurfl) )
6205       ALLOCATE( surfinsw(nsurfl) )
6206       ALLOCATE( surfinlw(nsurfl) )
6207       ALLOCATE( surfinswdir(nsurfl) )
6208       ALLOCATE( surfinswdif(nsurfl) )
6209       ALLOCATE( surfinlwdif(nsurfl) )
6210       ALLOCATE( surfoutsl(nsurfl) )
6211       ALLOCATE( surfoutll(nsurfl) )
6212       ALLOCATE( surfoutsw(nsurfl) )
6213       ALLOCATE( surfoutlw(nsurfl) )
6214       ALLOCATE( surfouts(nsurf) )
6215       ALLOCATE( surfoutl(nsurf) )
6216       ALLOCATE( surfinlg(nsurf) )
6217       ALLOCATE( skyvf(nsurfl) )
6218       ALLOCATE( skyvft(nsurfl) )
6219       ALLOCATE( surfemitlwl(nsurfl) )
6220
6221!
6222!--    In case of average_radiation, aggregated surface albedo and emissivity,
6223!--    also set initial value for t_rad_urb.
6224!--    For now set an arbitrary initial value.
6225       IF ( average_radiation )  THEN
6226          albedo_urb = 0.1_wp
6227          emissivity_urb = 0.9_wp
6228          t_rad_urb = pt_surface
6229       ENDIF
6230
6231    END SUBROUTINE radiation_interaction_init
6232
6233!------------------------------------------------------------------------------!
6234! Description:
6235! ------------
6236!> Calculates shape view factors (SVF), plant sink canopy factors (PCSF),
6237!> sky-view factors, discretized path for direct solar radiation, MRT factors
6238!> and other preprocessed data needed for radiation_interaction.
6239!------------------------------------------------------------------------------!
6240    SUBROUTINE radiation_calc_svf
6241   
6242        IMPLICIT NONE
6243       
6244        INTEGER(iwp)                                  :: i, j, k, d, ip, jp
6245        INTEGER(iwp)                                  :: isvf, ksvf, icsf, kcsf, npcsfl, isvf_surflt, imrt, imrtf, ipcgb
6246        INTEGER(iwp)                                  :: sd, td
6247        INTEGER(iwp)                                  :: iaz, izn      !< azimuth, zenith counters
6248        INTEGER(iwp)                                  :: naz, nzn      !< azimuth, zenith num of steps
6249        REAL(wp)                                      :: az0, zn0      !< starting azimuth/zenith
6250        REAL(wp)                                      :: azs, zns      !< azimuth/zenith cycle step
6251        REAL(wp)                                      :: az1, az2      !< relative azimuth of section borders
6252        REAL(wp)                                      :: azmid         !< ray (center) azimuth
6253        REAL(wp)                                      :: yxlen         !< |yxdir|
6254        REAL(wp), DIMENSION(2)                        :: yxdir         !< y,x *unit* vector of ray direction (in grid units)
6255        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zdirs         !< directions in z (tangent of elevation)
6256        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zcent         !< zenith angle centers
6257        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zbdry         !< zenith angle boundaries
6258        REAL(wp), DIMENSION(:), ALLOCATABLE           :: vffrac        !< view factor fractions for individual rays
6259        REAL(wp), DIMENSION(:), ALLOCATABLE           :: vffrac0       !< dtto (original values)
6260        REAL(wp), DIMENSION(:), ALLOCATABLE           :: ztransp       !< array of transparency in z steps
6261        INTEGER(iwp)                                  :: lowest_free_ray !< index into zdirs
6262        INTEGER(iwp), DIMENSION(:), ALLOCATABLE       :: itarget       !< face indices of detected obstacles
6263        INTEGER(iwp)                                  :: itarg0, itarg1
6264
6265        INTEGER(iwp)                                  :: udim
6266        INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET:: nzterrl_l
6267        INTEGER(iwp), DIMENSION(:,:), POINTER         :: nzterrl
6268        REAL(wp),     DIMENSION(:), ALLOCATABLE,TARGET:: csflt_l, pcsflt_l
6269        REAL(wp),     DIMENSION(:,:), POINTER         :: csflt, pcsflt
6270        INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET:: kcsflt_l,kpcsflt_l
6271        INTEGER(iwp), DIMENSION(:,:), POINTER         :: kcsflt,kpcsflt
6272        INTEGER(iwp), DIMENSION(:), ALLOCATABLE       :: icsflt,dcsflt,ipcsflt,dpcsflt
6273        REAL(wp), DIMENSION(3)                        :: uv
6274        LOGICAL                                       :: visible
6275        REAL(wp), DIMENSION(3)                        :: sa, ta          !< real coordinates z,y,x of source and target
6276        REAL(wp)                                      :: difvf           !< differential view factor
6277        REAL(wp)                                      :: transparency, rirrf, sqdist, svfsum
6278        INTEGER(iwp)                                  :: isurflt, isurfs, isurflt_prev
6279        INTEGER(idp)                                  :: ray_skip_maxdist, ray_skip_minval !< skipped raytracing counts
6280        INTEGER(iwp)                                  :: max_track_len !< maximum 2d track length
6281        INTEGER(iwp)                                  :: minfo
6282        REAL(wp), DIMENSION(:), POINTER               :: lad_s_rma       !< fortran 1D pointer
6283        TYPE(c_ptr)                                   :: lad_s_rma_p     !< allocated c pointer
6284#if defined( __parallel )
6285        INTEGER(kind=MPI_ADDRESS_KIND)                :: size_lad_rma
6286#endif
6287!   
6288        INTEGER(iwp), DIMENSION(0:svfnorm_report_num) :: svfnorm_counts
6289        CHARACTER(200)                                :: msg
6290
6291!--     calculation of the SVF
6292        CALL location_message( '    calculation of SVF and CSF', .TRUE. )
6293        CALL radiation_write_debug_log('Start calculation of SVF and CSF')
6294
6295!--     initialize variables and temporary arrays for calculation of svf and csf
6296        nsvfl  = 0
6297        ncsfl  = 0
6298        nsvfla = gasize
6299        msvf   = 1
6300        ALLOCATE( asvf1(nsvfla) )
6301        asvf => asvf1
6302        IF ( plant_canopy )  THEN
6303            ncsfla = gasize
6304            mcsf   = 1
6305            ALLOCATE( acsf1(ncsfla) )
6306            acsf => acsf1
6307        ENDIF
6308        nmrtf = 0
6309        IF ( mrt_nlevels > 0 )  THEN
6310           nmrtfa = gasize
6311           mmrtf = 1
6312           ALLOCATE ( amrtf1(nmrtfa) )
6313           amrtf => amrtf1
6314        ENDIF
6315        ray_skip_maxdist = 0
6316        ray_skip_minval = 0
6317       
6318!--     initialize temporary terrain and plant canopy height arrays (global 2D array!)
6319        ALLOCATE( nzterr(0:(nx+1)*(ny+1)-1) )
6320#if defined( __parallel )
6321        !ALLOCATE( nzterrl(nys:nyn,nxl:nxr) )
6322        ALLOCATE( nzterrl_l((nyn-nys+1)*(nxr-nxl+1)) )
6323        nzterrl(nys:nyn,nxl:nxr) => nzterrl_l(1:(nyn-nys+1)*(nxr-nxl+1))
6324        nzterrl = get_topography_top_index( 's' )
6325        CALL MPI_AllGather( nzterrl_l, nnx*nny, MPI_INTEGER, &
6326                            nzterr, nnx*nny, MPI_INTEGER, comm2d, ierr )
6327        IF ( ierr /= 0 ) THEN
6328            WRITE(9,*) 'Error MPI_AllGather1:', ierr, SIZE(nzterrl_l), nnx*nny, &
6329                       SIZE(nzterr), nnx*nny
6330            FLUSH(9)
6331        ENDIF
6332        DEALLOCATE(nzterrl_l)
6333#else
6334        nzterr = RESHAPE( get_topography_top_index( 's' ), (/(nx+1)*(ny+1)/) )
6335#endif
6336        IF ( plant_canopy )  THEN
6337            ALLOCATE( plantt(0:(nx+1)*(ny+1)-1) )
6338            maxboxesg = nx + ny + nzp + 1
6339            max_track_len = nx + ny + 1
6340!--         temporary arrays storing values for csf calculation during raytracing
6341            ALLOCATE( boxes(3, maxboxesg) )
6342            ALLOCATE( crlens(maxboxesg) )
6343
6344#if defined( __parallel )
6345            CALL MPI_AllGather( pct, nnx*nny, MPI_INTEGER, &
6346                                plantt, nnx*nny, MPI_INTEGER, comm2d, ierr )
6347            IF ( ierr /= 0 ) THEN
6348                WRITE(9,*) 'Error MPI_AllGather2:', ierr, SIZE(pct), nnx*nny, &
6349                           SIZE(plantt), nnx*nny
6350                FLUSH(9)
6351            ENDIF
6352
6353!--         temporary arrays storing values for csf calculation during raytracing
6354            ALLOCATE( lad_ip(maxboxesg) )
6355            ALLOCATE( lad_disp(maxboxesg) )
6356
6357            IF ( raytrace_mpi_rma )  THEN
6358                ALLOCATE( lad_s_ray(maxboxesg) )
6359               
6360                ! set conditions for RMA communication
6361                CALL MPI_Info_create(minfo, ierr)
6362                IF ( ierr /= 0 ) THEN
6363                    WRITE(9,*) 'Error MPI_Info_create2:', ierr
6364                    FLUSH(9)
6365                ENDIF
6366                CALL MPI_Info_set(minfo, 'accumulate_ordering', '', ierr)
6367                IF ( ierr /= 0 ) THEN
6368                    WRITE(9,*) 'Error MPI_Info_set5:', ierr
6369                    FLUSH(9)
6370                ENDIF
6371                CALL MPI_Info_set(minfo, 'accumulate_ops', 'same_op', ierr)
6372                IF ( ierr /= 0 ) THEN
6373                    WRITE(9,*) 'Error MPI_Info_set6:', ierr
6374                    FLUSH(9)
6375                ENDIF
6376                CALL MPI_Info_set(minfo, 'same_size', 'true', ierr)
6377                IF ( ierr /= 0 ) THEN
6378                    WRITE(9,*) 'Error MPI_Info_set7:', ierr
6379                    FLUSH(9)
6380                ENDIF
6381                CALL MPI_Info_set(minfo, 'same_disp_unit', 'true', ierr)
6382                IF ( ierr /= 0 ) THEN
6383                    WRITE(9,*) 'Error MPI_Info_set8:', ierr
6384                    FLUSH(9)
6385                ENDIF
6386
6387!--             Allocate and initialize the MPI RMA window
6388!--             must be in accordance with allocation of lad_s in plant_canopy_model
6389!--             optimization of memory should be done
6390!--             Argument X of function STORAGE_SIZE(X) needs arbitrary REAL(wp) value, set to 1.0_wp for now
6391                size_lad_rma = STORAGE_SIZE(1.0_wp)/8*nnx*nny*nzp
6392                CALL MPI_Win_allocate(size_lad_rma, STORAGE_SIZE(1.0_wp)/8, minfo, comm2d, &
6393                                        lad_s_rma_p, win_lad, ierr)
6394                IF ( ierr /= 0 ) THEN
6395                    WRITE(9,*) 'Error MPI_Win_allocate2:', ierr, size_lad_rma, &
6396                                STORAGE_SIZE(1.0_wp)/8, win_lad
6397                    FLUSH(9)
6398                ENDIF
6399                CALL c_f_pointer(lad_s_rma_p, lad_s_rma, (/ nzp*nny*nnx /))
6400                sub_lad(nzub:nzpt, nys:nyn, nxl:nxr) => lad_s_rma(1:nzp*nny*nnx)
6401            ELSE
6402                ALLOCATE(sub_lad(nzub:nzpt, nys:nyn, nxl:nxr))
6403            ENDIF
6404#else
6405            plantt = RESHAPE( pct(nys:nyn,nxl:nxr), (/(nx+1)*(ny+1)/) )
6406            ALLOCATE(sub_lad(nzub:nzpt, nys:nyn, nxl:nxr))
6407#endif
6408            plantt_max = MAXVAL(plantt)
6409            ALLOCATE( rt2_track(2, max_track_len), rt2_track_lad(nzub:plantt_max, max_track_len), &
6410                      rt2_track_dist(0:max_track_len), rt2_dist(plantt_max-nzub+2) )
6411
6412            sub_lad(:,:,:) = 0._wp
6413            DO i = nxl, nxr
6414                DO j = nys, nyn
6415                    k = get_topography_top_index_ji( j, i, 's' )
6416
6417                    sub_lad(k:nzpt, j, i) = lad_s(0:nzpt-k, j, i)
6418                ENDDO
6419            ENDDO
6420
6421#if defined( __parallel )
6422            IF ( raytrace_mpi_rma )  THEN
6423                CALL MPI_Info_free(minfo, ierr)
6424                IF ( ierr /= 0 ) THEN
6425                    WRITE(9,*) 'Error MPI_Info_free2:', ierr
6426                    FLUSH(9)
6427                ENDIF
6428                CALL MPI_Win_lock_all(0, win_lad, ierr)
6429                IF ( ierr /= 0 ) THEN
6430                    WRITE(9,*) 'Error MPI_Win_lock_all1:', ierr, win_lad
6431                    FLUSH(9)
6432                ENDIF
6433               
6434            ELSE
6435                ALLOCATE( sub_lad_g(0:(nx+1)*(ny+1)*nzp-1) )
6436                CALL MPI_AllGather( sub_lad, nnx*nny*nzp, MPI_REAL, &
6437                                    sub_lad_g, nnx*nny*nzp, MPI_REAL, comm2d, ierr )
6438                IF ( ierr /= 0 ) THEN
6439                    WRITE(9,*) 'Error MPI_AllGather3:', ierr, SIZE(sub_lad), &
6440                                nnx*nny*nzp, SIZE(sub_lad_g), nnx*nny*nzp
6441                    FLUSH(9)
6442                ENDIF
6443            ENDIF
6444#endif
6445        ENDIF
6446
6447!--     prepare the MPI_Win for collecting the surface indices
6448!--     from the reverse index arrays gridsurf from processors of target surfaces
6449#if defined( __parallel )
6450        IF ( rad_angular_discretization )  THEN
6451!
6452!--         raytrace_mpi_rma is asserted
6453            CALL MPI_Win_lock_all(0, win_gridsurf, ierr)
6454            IF ( ierr /= 0 ) THEN
6455                WRITE(9,*) 'Error MPI_Win_lock_all2:', ierr, win_gridsurf
6456                FLUSH(9)
6457            ENDIF
6458        ENDIF
6459#endif
6460
6461
6462        !--Directions opposite to face normals are not even calculated,
6463        !--they must be preset to 0
6464        !--
6465        dsitrans(:,:) = 0._wp
6466       
6467        DO isurflt = 1, nsurfl
6468!--         determine face centers
6469            td = surfl(id, isurflt)
6470            ta = (/ REAL(surfl(iz, isurflt), wp) - 0.5_wp * kdir(td),  &
6471                      REAL(surfl(iy, isurflt), wp) - 0.5_wp * jdir(td),  &
6472                      REAL(surfl(ix, isurflt), wp) - 0.5_wp * idir(td)  /)
6473
6474            !--Calculate sky view factor and raytrace DSI paths
6475            skyvf(isurflt) = 0._wp
6476            skyvft(isurflt) = 0._wp
6477
6478            !--Select a proper half-sphere for 2D raytracing
6479            SELECT CASE ( td )
6480               CASE ( iup_u, iup_l )
6481                  az0 = 0._wp
6482                  naz = raytrace_discrete_azims
6483                  azs = 2._wp * pi / REAL(naz, wp)
6484                  zn0 = 0._wp
6485                  nzn = raytrace_discrete_elevs / 2
6486                  zns = pi / 2._wp / REAL(nzn, wp)
6487               CASE ( isouth_u, isouth_l )
6488                  az0 = pi / 2._wp
6489                  naz = raytrace_discrete_azims / 2
6490                  azs = pi / REAL(naz, wp)
6491                  zn0 = 0._wp
6492                  nzn = raytrace_discrete_elevs
6493                  zns = pi / REAL(nzn, wp)
6494               CASE ( inorth_u, inorth_l )
6495                  az0 = - pi / 2._wp
6496                  naz = raytrace_discrete_azims / 2
6497                  azs = pi / REAL(naz, wp)
6498                  zn0 = 0._wp
6499                  nzn = raytrace_discrete_elevs
6500                  zns = pi / REAL(nzn, wp)
6501               CASE ( iwest_u, iwest_l )
6502                  az0 = pi
6503                  naz = raytrace_discrete_azims / 2
6504                  azs = pi / REAL(naz, wp)
6505                  zn0 = 0._wp
6506                  nzn = raytrace_discrete_elevs
6507                  zns = pi / REAL(nzn, wp)
6508               CASE ( ieast_u, ieast_l )
6509                  az0 = 0._wp
6510                  naz = raytrace_discrete_azims / 2
6511                  azs = pi / REAL(naz, wp)
6512                  zn0 = 0._wp
6513                  nzn = raytrace_discrete_elevs
6514                  zns = pi / REAL(nzn, wp)
6515               CASE DEFAULT
6516                  WRITE(message_string, *) 'ERROR: the surface type ', td,     &
6517                                           ' is not supported for calculating',&
6518                                           ' SVF'
6519                  CALL message( 'radiation_calc_svf', 'PA0488', 1, 2, 0, 6, 0 )
6520            END SELECT
6521
6522            ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), zbdry(0:nzn), vffrac(1:nzn*naz), &
6523                       ztransp(1:nzn*naz), itarget(1:nzn*naz) )   !FIXME allocate itarget only
6524                                                                  !in case of rad_angular_discretization
6525
6526            itarg0 = 1
6527            itarg1 = nzn
6528            zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
6529            zbdry(:) = (/( zn0+REAL(izn,wp)*zns, izn=0, nzn )/)
6530            IF ( td == iup_u  .OR.  td == iup_l )  THEN
6531               vffrac(1:nzn) = (COS(2 * zbdry(0:nzn-1)) - COS(2 * zbdry(1:nzn))) / 2._wp / REAL(naz, wp)
6532!
6533!--            For horizontal target, vf fractions are constant per azimuth
6534               DO iaz = 1, naz-1
6535                  vffrac(iaz*nzn+1:(iaz+1)*nzn) = vffrac(1:nzn)
6536               ENDDO
6537!--            sum of whole vffrac equals 1, verified
6538            ENDIF
6539!
6540!--         Calculate sky-view factor and direct solar visibility using 2D raytracing
6541            DO iaz = 1, naz
6542               azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
6543               IF ( td /= iup_u  .AND.  td /= iup_l )  THEN
6544                  az2 = REAL(iaz, wp) * azs - pi/2._wp
6545                  az1 = az2 - azs
6546                  !TODO precalculate after 1st line
6547                  vffrac(itarg0:itarg1) = (SIN(az2) - SIN(az1))               &
6548                              * (zbdry(1:nzn) - zbdry(0:nzn-1)                &
6549                                 + SIN(zbdry(0:nzn-1))*COS(zbdry(0:nzn-1))    &
6550                                 - SIN(zbdry(1:nzn))*COS(zbdry(1:nzn)))       &
6551                              / (2._wp * pi)
6552!--               sum of whole vffrac equals 1, verified
6553               ENDIF
6554               yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
6555               yxlen = SQRT(SUM(yxdir(:)**2))
6556               zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
6557               yxdir(:) = yxdir(:) / yxlen
6558
6559               CALL raytrace_2d(ta, yxdir, nzn, zdirs,                        &
6560                                    surfstart(myid) + isurflt, facearea(td),  &
6561                                    vffrac(itarg0:itarg1), .TRUE., .TRUE.,    &
6562                                    .FALSE., lowest_free_ray,                 &
6563                                    ztransp(itarg0:itarg1),                   &
6564                                    itarget(itarg0:itarg1))
6565
6566               skyvf(isurflt) = skyvf(isurflt) + &
6567                                SUM(vffrac(itarg0:itarg0+lowest_free_ray-1))
6568               skyvft(isurflt) = skyvft(isurflt) + &
6569                                 SUM(ztransp(itarg0:itarg0+lowest_free_ray-1) &
6570                                             * vffrac(itarg0:itarg0+lowest_free_ray-1))
6571 
6572!--            Save direct solar transparency
6573               j = MODULO(NINT(azmid/                                          &
6574                               (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
6575                          raytrace_discrete_azims)
6576
6577               DO k = 1, raytrace_discrete_elevs/2
6578                  i = dsidir_rev(k-1, j)
6579                  IF ( i /= -1  .AND.  k <= lowest_free_ray )  &
6580                     dsitrans(isurflt, i) = ztransp(itarg0+k-1)
6581               ENDDO
6582
6583!
6584!--            Advance itarget indices
6585               itarg0 = itarg1 + 1
6586               itarg1 = itarg1 + nzn
6587            ENDDO
6588
6589            IF ( rad_angular_discretization )  THEN
6590!--            sort itarget by face id
6591               CALL quicksort_itarget(itarget,vffrac,ztransp,1,nzn*naz)
6592!
6593!--            find the first valid position
6594               itarg0 = 1
6595               DO WHILE ( itarg0 <= nzn*naz )
6596                  IF ( itarget(itarg0) /= -1 )  EXIT
6597                  itarg0 = itarg0 + 1
6598               ENDDO
6599
6600               DO  i = itarg0, nzn*naz
6601!
6602!--               For duplicate values, only sum up vf fraction value
6603                  IF ( i < nzn*naz )  THEN
6604                     IF ( itarget(i+1) == itarget(i) )  THEN
6605                        vffrac(i+1) = vffrac(i+1) + vffrac(i)
6606                        CYCLE
6607                     ENDIF
6608                  ENDIF
6609!
6610!--               write to the svf array
6611                  nsvfl = nsvfl + 1
6612!--               check dimmension of asvf array and enlarge it if needed
6613                  IF ( nsvfla < nsvfl )  THEN
6614                     k = CEILING(REAL(nsvfla, kind=wp) * grow_factor)
6615                     IF ( msvf == 0 )  THEN
6616                        msvf = 1
6617                        ALLOCATE( asvf1(k) )
6618                        asvf => asvf1
6619                        asvf1(1:nsvfla) = asvf2
6620                        DEALLOCATE( asvf2 )
6621                     ELSE
6622                        msvf = 0
6623                        ALLOCATE( asvf2(k) )
6624                        asvf => asvf2
6625                        asvf2(1:nsvfla) = asvf1
6626                        DEALLOCATE( asvf1 )
6627                     ENDIF
6628
6629                     WRITE (msg,'(A,3I12)') 'Grow asvf:',nsvfl,nsvfla,k
6630                     CALL radiation_write_debug_log( msg )
6631                     
6632                     nsvfla = k
6633                  ENDIF
6634!--               write svf values into the array
6635                  asvf(nsvfl)%isurflt = isurflt
6636                  asvf(nsvfl)%isurfs = itarget(i)
6637                  asvf(nsvfl)%rsvf = vffrac(i)
6638                  asvf(nsvfl)%rtransp = ztransp(i)
6639               END DO
6640
6641            ENDIF ! rad_angular_discretization
6642
6643            DEALLOCATE ( zdirs, zcent, zbdry, vffrac, ztransp, itarget ) !FIXME itarget shall be allocated only
6644                                                                  !in case of rad_angular_discretization
6645!
6646!--         Following calculations only required for surface_reflections
6647            IF ( surface_reflections  .AND.  .NOT. rad_angular_discretization )  THEN
6648
6649               DO  isurfs = 1, nsurf
6650                  IF ( .NOT.  surface_facing(surfl(ix, isurflt), surfl(iy, isurflt), &
6651                     surfl(iz, isurflt), surfl(id, isurflt), &
6652                     surf(ix, isurfs), surf(iy, isurfs), &
6653                     surf(iz, isurfs), surf(id, isurfs)) )  THEN
6654                     CYCLE
6655                  ENDIF
6656                 
6657                  sd = surf(id, isurfs)
6658                  sa = (/ REAL(surf(iz, isurfs), wp) - 0.5_wp * kdir(sd),  &
6659                          REAL(surf(iy, isurfs), wp) - 0.5_wp * jdir(sd),  &
6660                          REAL(surf(ix, isurfs), wp) - 0.5_wp * idir(sd)  /)
6661
6662!--               unit vector source -> target
6663                  uv = (/ (ta(1)-sa(1))*dz(1), (ta(2)-sa(2))*dy, (ta(3)-sa(3))*dx /)
6664                  sqdist = SUM(uv(:)**2)
6665                  uv = uv / SQRT(sqdist)
6666
6667!--               reject raytracing above max distance
6668                  IF ( SQRT(sqdist) > max_raytracing_dist ) THEN
6669                     ray_skip_maxdist = ray_skip_maxdist + 1
6670                     CYCLE
6671                  ENDIF
6672                 
6673                  difvf = dot_product((/ kdir(sd), jdir(sd), idir(sd) /), uv) & ! cosine of source normal and direction
6674                      * dot_product((/ kdir(td), jdir(td), idir(td) /), -uv) &  ! cosine of target normal and reverse direction
6675                      / (pi * sqdist) ! square of distance between centers
6676!
6677!--               irradiance factor (our unshaded shape view factor) = view factor per differential target area * source area
6678                  rirrf = difvf * facearea(sd)
6679
6680!--               reject raytracing for potentially too small view factor values
6681                  IF ( rirrf < min_irrf_value ) THEN
6682                      ray_skip_minval = ray_skip_minval + 1
6683                      CYCLE
6684                  ENDIF
6685
6686!--               raytrace + process plant canopy sinks within
6687                  CALL raytrace(sa, ta, isurfs, difvf, facearea(td), .TRUE., &
6688                                visible, transparency)
6689
6690                  IF ( .NOT.  visible ) CYCLE
6691                 ! rsvf = rirrf * transparency
6692
6693!--               write to the svf array
6694                  nsvfl = nsvfl + 1
6695!--               check dimmension of asvf array and enlarge it if needed
6696                  IF ( nsvfla < nsvfl )  THEN
6697                     k = CEILING(REAL(nsvfla, kind=wp) * grow_factor)
6698                     IF ( msvf == 0 )  THEN
6699                        msvf = 1
6700                        ALLOCATE( asvf1(k) )
6701                        asvf => asvf1
6702                        asvf1(1:nsvfla) = asvf2
6703                        DEALLOCATE( asvf2 )
6704                     ELSE
6705                        msvf = 0
6706                        ALLOCATE( asvf2(k) )
6707                        asvf => asvf2
6708                        asvf2(1:nsvfla) = asvf1
6709                        DEALLOCATE( asvf1 )
6710                     ENDIF
6711
6712                     WRITE(msg,'(A,3I12)') 'Grow asvf:',nsvfl,nsvfla,k
6713                     CALL radiation_write_debug_log( msg )
6714                     
6715                     nsvfla = k
6716                  ENDIF
6717!--               write svf values into the array
6718                  asvf(nsvfl)%isurflt = isurflt
6719                  asvf(nsvfl)%isurfs = isurfs
6720                  asvf(nsvfl)%rsvf = rirrf !we postopne multiplication by transparency
6721                  asvf(nsvfl)%rtransp = transparency !a.k.a. Direct Irradiance Factor
6722               ENDDO
6723            ENDIF
6724        ENDDO
6725
6726!--
6727!--     Raytrace to canopy boxes to fill dsitransc TODO optimize
6728        dsitransc(:,:) = 0._wp
6729        az0 = 0._wp
6730        naz = raytrace_discrete_azims
6731        azs = 2._wp * pi / REAL(naz, wp)
6732        zn0 = 0._wp
6733        nzn = raytrace_discrete_elevs / 2
6734        zns = pi / 2._wp / REAL(nzn, wp)
6735        ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), vffrac(1:nzn), ztransp(1:nzn), &
6736               itarget(1:nzn) )
6737        zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
6738        vffrac(:) = 0._wp
6739
6740        DO  ipcgb = 1, npcbl
6741           ta = (/ REAL(pcbl(iz, ipcgb), wp),  &
6742                   REAL(pcbl(iy, ipcgb), wp),  &
6743                   REAL(pcbl(ix, ipcgb), wp) /)
6744!--        Calculate direct solar visibility using 2D raytracing
6745           DO  iaz = 1, naz
6746              azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
6747              yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
6748              yxlen = SQRT(SUM(yxdir(:)**2))
6749              zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
6750              yxdir(:) = yxdir(:) / yxlen
6751              CALL raytrace_2d(ta, yxdir, nzn, zdirs,                                &
6752                                   -999, -999._wp, vffrac, .FALSE., .FALSE., .TRUE., &
6753                                   lowest_free_ray, ztransp, itarget)
6754
6755!--           Save direct solar transparency
6756              j = MODULO(NINT(azmid/                                         &
6757                             (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
6758                         raytrace_discrete_azims)
6759              DO  k = 1, raytrace_discrete_elevs/2
6760                 i = dsidir_rev(k-1, j)
6761                 IF ( i /= -1  .AND.  k <= lowest_free_ray ) &
6762                    dsitransc(ipcgb, i) = ztransp(k)
6763              ENDDO
6764           ENDDO
6765        ENDDO
6766        DEALLOCATE ( zdirs, zcent, vffrac, ztransp, itarget )
6767!--
6768!--     Raytrace to MRT boxes
6769        IF ( nmrtbl > 0 )  THEN
6770           mrtdsit(:,:) = 0._wp
6771           mrtsky(:) = 0._wp
6772           mrtskyt(:) = 0._wp
6773           az0 = 0._wp
6774           naz = raytrace_discrete_azims
6775           azs = 2._wp * pi / REAL(naz, wp)
6776           zn0 = 0._wp
6777           nzn = raytrace_discrete_elevs
6778           zns = pi / REAL(nzn, wp)
6779           ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), zbdry(0:nzn), vffrac(1:nzn*naz), vffrac0(1:nzn), &
6780                      ztransp(1:nzn*naz), itarget(1:nzn*naz) )   !FIXME allocate itarget only
6781                                                                 !in case of rad_angular_discretization
6782
6783           zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
6784           zbdry(:) = (/( zn0+REAL(izn,wp)*zns, izn=0, nzn )/)
6785           vffrac0(:) = (COS(zbdry(0:nzn-1)) - COS(zbdry(1:nzn))) / 2._wp / REAL(naz, wp)
6786           !
6787           !--Modify direction weights to simulate human body (lower weight for top-down)
6788           IF ( mrt_geom_human )  THEN
6789              vffrac0(:) = vffrac0(:) * MAX(0._wp, SIN(zcent(:))*0.88_wp + COS(zcent(:))*0.12_wp)
6790              vffrac0(:) = vffrac0(:) / (SUM(vffrac0) * REAL(naz, wp))
6791           ENDIF
6792
6793           DO  imrt = 1, nmrtbl
6794              ta = (/ REAL(mrtbl(iz, imrt), wp),  &
6795                      REAL(mrtbl(iy, imrt), wp),  &
6796                      REAL(mrtbl(ix, imrt), wp) /)
6797!
6798!--           vf fractions are constant per azimuth
6799              DO iaz = 0, naz-1
6800                 vffrac(iaz*nzn+1:(iaz+1)*nzn) = vffrac0(:)
6801              ENDDO
6802!--           sum of whole vffrac equals 1, verified
6803              itarg0 = 1
6804              itarg1 = nzn
6805!
6806!--           Calculate sky-view factor and direct solar visibility using 2D raytracing
6807              DO  iaz = 1, naz
6808                 azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
6809                 yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
6810                 yxlen = SQRT(SUM(yxdir(:)**2))
6811                 zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
6812                 yxdir(:) = yxdir(:) / yxlen
6813
6814                 CALL raytrace_2d(ta, yxdir, nzn, zdirs,                         &
6815                                  -999, -999._wp, vffrac(itarg0:itarg1), .TRUE., &
6816                                  .FALSE., .TRUE., lowest_free_ray,              &
6817                                  ztransp(itarg0:itarg1),                        &
6818                                  itarget(itarg0:itarg1))
6819
6820!--              Sky view factors for MRT
6821                 mrtsky(imrt) = mrtsky(imrt) + &
6822                                  SUM(vffrac(itarg0:itarg0+lowest_free_ray-1))
6823                 mrtskyt(imrt) = mrtskyt(imrt) + &
6824                                   SUM(ztransp(itarg0:itarg0+lowest_free_ray-1) &
6825                                               * vffrac(itarg0:itarg0+lowest_free_ray-1))
6826!--              Direct solar transparency for MRT
6827                 j = MODULO(NINT(azmid/                                         &
6828                                (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
6829                            raytrace_discrete_azims)
6830                 DO  k = 1, raytrace_discrete_elevs/2
6831                    i = dsidir_rev(k-1, j)
6832                    IF ( i /= -1  .AND.  k <= lowest_free_ray ) &
6833                       mrtdsit(imrt, i) = ztransp(itarg0+k-1)
6834                 ENDDO
6835!
6836!--              Advance itarget indices
6837                 itarg0 = itarg1 + 1
6838                 itarg1 = itarg1 + nzn
6839              ENDDO
6840
6841!--           sort itarget by face id
6842              CALL quicksort_itarget(itarget,vffrac,ztransp,1,nzn*naz)
6843!
6844!--           find the first valid position
6845              itarg0 = 1
6846              DO WHILE ( itarg0 <= nzn*naz )
6847                 IF ( itarget(itarg0) /= -1 )  EXIT
6848                 itarg0 = itarg0 + 1
6849              ENDDO
6850
6851              DO  i = itarg0, nzn*naz
6852!
6853!--              For duplicate values, only sum up vf fraction value
6854                 IF ( i < nzn*naz )  THEN
6855                    IF ( itarget(i+1) == itarget(i) )  THEN
6856                       vffrac(i+1) = vffrac(i+1) + vffrac(i)
6857                       CYCLE
6858                    ENDIF
6859                 ENDIF
6860!
6861!--              write to the mrtf array
6862                 nmrtf = nmrtf + 1
6863!--              check dimmension of mrtf array and enlarge it if needed
6864                 IF ( nmrtfa < nmrtf )  THEN
6865                    k = CEILING(REAL(nmrtfa, kind=wp) * grow_factor)
6866                    IF ( mmrtf == 0 )  THEN
6867                       mmrtf = 1
6868                       ALLOCATE( amrtf1(k) )
6869                       amrtf => amrtf1
6870                       amrtf1(1:nmrtfa) = amrtf2
6871                       DEALLOCATE( amrtf2 )
6872                    ELSE
6873                       mmrtf = 0
6874                       ALLOCATE( amrtf2(k) )
6875                       amrtf => amrtf2
6876                       amrtf2(1:nmrtfa) = amrtf1
6877                       DEALLOCATE( amrtf1 )
6878                    ENDIF
6879
6880                    WRITE (msg,'(A,3I12)') 'Grow amrtf:', nmrtf, nmrtfa, k
6881                    CALL radiation_write_debug_log( msg )
6882
6883                    nmrtfa = k
6884                 ENDIF
6885!--              write mrtf values into the array
6886                 amrtf(nmrtf)%isurflt = imrt
6887                 amrtf(nmrtf)%isurfs = itarget(i)
6888                 amrtf(nmrtf)%rsvf = vffrac(i)
6889                 amrtf(nmrtf)%rtransp = ztransp(i)
6890              ENDDO ! itarg
6891
6892           ENDDO ! imrt
6893           DEALLOCATE ( zdirs, zcent, zbdry, vffrac, vffrac0, ztransp, itarget )
6894!
6895!--        Move MRT factors to final arrays
6896           ALLOCATE ( mrtf(nmrtf), mrtft(nmrtf), mrtfsurf(2,nmrtf) )
6897           DO  imrtf = 1, nmrtf
6898              mrtf(imrtf) = amrtf(imrtf)%rsvf
6899              mrtft(imrtf) = amrtf(imrtf)%rsvf * amrtf(imrtf)%rtransp
6900              mrtfsurf(:,imrtf) = (/amrtf(imrtf)%isurflt, amrtf(imrtf)%isurfs /)
6901           ENDDO
6902           IF ( ALLOCATED(amrtf1) )  DEALLOCATE( amrtf1 )
6903           IF ( ALLOCATED(amrtf2) )  DEALLOCATE( amrtf2 )
6904        ENDIF ! nmrtbl > 0
6905
6906        IF ( rad_angular_discretization )  THEN
6907#if defined( __parallel )
6908!--        finalize MPI_RMA communication established to get global index of the surface from grid indices
6909!--        flush all MPI window pending requests
6910           CALL MPI_Win_flush_all(win_gridsurf, ierr)
6911           IF ( ierr /= 0 ) THEN
6912               WRITE(9,*) 'Error MPI_Win_flush_all1:', ierr, win_gridsurf
6913               FLUSH(9)
6914           ENDIF
6915!--        unlock MPI window
6916           CALL MPI_Win_unlock_all(win_gridsurf, ierr)
6917           IF ( ierr /= 0 ) THEN
6918               WRITE(9,*) 'Error MPI_Win_unlock_all1:', ierr, win_gridsurf
6919               FLUSH(9)
6920           ENDIF
6921!--        free MPI window
6922           CALL MPI_Win_free(win_gridsurf, ierr)
6923           IF ( ierr /= 0 ) THEN
6924               WRITE(9,*) 'Error MPI_Win_free1:', ierr, win_gridsurf
6925               FLUSH(9)
6926           ENDIF
6927#else
6928           DEALLOCATE ( gridsurf )
6929#endif
6930        ENDIF
6931
6932        CALL radiation_write_debug_log( 'End of calculation SVF' )
6933        WRITE(msg, *) 'Raytracing skipped for maximum distance of ', &
6934           max_raytracing_dist, ' m on ', ray_skip_maxdist, ' pairs.'
6935        CALL radiation_write_debug_log( msg )
6936        WRITE(msg, *) 'Raytracing skipped for minimum potential value of ', &
6937           min_irrf_value , ' on ', ray_skip_minval, ' pairs.'
6938        CALL radiation_write_debug_log( msg )
6939
6940        CALL location_message( '    waiting for completion of SVF and CSF calculation in all processes', .TRUE. )
6941!--     deallocate temporary global arrays
6942        DEALLOCATE(nzterr)
6943       
6944        IF ( plant_canopy )  THEN
6945!--         finalize mpi_rma communication and deallocate temporary arrays
6946#if defined( __parallel )
6947            IF ( raytrace_mpi_rma )  THEN
6948                CALL MPI_Win_flush_all(win_lad, ierr)
6949                IF ( ierr /= 0 ) THEN
6950                    WRITE(9,*) 'Error MPI_Win_flush_all2:', ierr, win_lad
6951                    FLUSH(9)
6952                ENDIF
6953!--             unlock MPI window
6954                CALL MPI_Win_unlock_all(win_lad, ierr)
6955                IF ( ierr /= 0 ) THEN
6956                    WRITE(9,*) 'Error MPI_Win_unlock_all2:', ierr, win_lad
6957                    FLUSH(9)
6958                ENDIF
6959!--             free MPI window
6960                CALL MPI_Win_free(win_lad, ierr)
6961                IF ( ierr /= 0 ) THEN
6962                    WRITE(9,*) 'Error MPI_Win_free2:', ierr, win_lad
6963                    FLUSH(9)
6964                ENDIF
6965!--             deallocate temporary arrays storing values for csf calculation during raytracing
6966                DEALLOCATE( lad_s_ray )
6967!--             sub_lad is the pointer to lad_s_rma in case of raytrace_mpi_rma
6968!--             and must not be deallocated here
6969            ELSE
6970                DEALLOCATE(sub_lad)
6971                DEALLOCATE(sub_lad_g)
6972            ENDIF
6973#else
6974            DEALLOCATE(sub_lad)
6975#endif
6976            DEALLOCATE( boxes )
6977            DEALLOCATE( crlens )
6978            DEALLOCATE( plantt )
6979            DEALLOCATE( rt2_track, rt2_track_lad, rt2_track_dist, rt2_dist )
6980        ENDIF
6981
6982        CALL location_message( '    calculation of the complete SVF array', .TRUE. )
6983
6984        IF ( rad_angular_discretization )  THEN
6985           CALL radiation_write_debug_log( 'Load svf from the structure array to plain arrays' )
6986           ALLOCATE( svf(ndsvf,nsvfl) )
6987           ALLOCATE( svfsurf(idsvf,nsvfl) )
6988
6989           DO isvf = 1, nsvfl
6990               svf(:, isvf) = (/ asvf(isvf)%rsvf, asvf(isvf)%rtransp /)
6991               svfsurf(:, isvf) = (/ asvf(isvf)%isurflt, asvf(isvf)%isurfs /)
6992           ENDDO
6993        ELSE
6994           CALL radiation_write_debug_log( 'Start SVF sort' )
6995!--        sort svf ( a version of quicksort )
6996           CALL quicksort_svf(asvf,1,nsvfl)
6997
6998           !< load svf from the structure array to plain arrays
6999           CALL radiation_write_debug_log( 'Load svf from the structure array to plain arrays' )
7000           ALLOCATE( svf(ndsvf,nsvfl) )
7001           ALLOCATE( svfsurf(idsvf,nsvfl) )
7002           svfnorm_counts(:) = 0._wp
7003           isurflt_prev = -1
7004           ksvf = 1
7005           svfsum = 0._wp
7006           DO isvf = 1, nsvfl
7007!--            normalize svf per target face
7008               IF ( asvf(ksvf)%isurflt /= isurflt_prev )  THEN
7009                   IF ( isurflt_prev /= -1  .AND.  svfsum /= 0._wp )  THEN
7010                       !< update histogram of logged svf normalization values
7011                       i = searchsorted(svfnorm_report_thresh, svfsum / (1._wp-skyvf(isurflt_prev)))
7012                       svfnorm_counts(i) = svfnorm_counts(i) + 1
7013
7014                       svf(1, isvf_surflt:isvf-1) = svf(1, isvf_surflt:isvf-1) / svfsum * (1._wp-skyvf(isurflt_prev))
7015                   ENDIF
7016                   isurflt_prev = asvf(ksvf)%isurflt
7017                   isvf_surflt = isvf
7018                   svfsum = asvf(ksvf)%rsvf !?? / asvf(ksvf)%rtransp
7019               ELSE
7020                   svfsum = svfsum + asvf(ksvf)%rsvf !?? / asvf(ksvf)%rtransp
7021               ENDIF
7022
7023               svf(:, isvf) = (/ asvf(ksvf)%rsvf, asvf(ksvf)%rtransp /)
7024               svfsurf(:, isvf) = (/ asvf(ksvf)%isurflt, asvf(ksvf)%isurfs /)
7025
7026!--            next element
7027               ksvf = ksvf + 1
7028           ENDDO
7029
7030           IF ( isurflt_prev /= -1  .AND.  svfsum /= 0._wp )  THEN
7031               i = searchsorted(svfnorm_report_thresh, svfsum / (1._wp-skyvf(isurflt_prev)))
7032               svfnorm_counts(i) = svfnorm_counts(i) + 1
7033
7034               svf(1, isvf_surflt:nsvfl) = svf(1, isvf_surflt:nsvfl) / svfsum * (1._wp-skyvf(isurflt_prev))
7035           ENDIF
7036           WRITE(9, *) 'SVF normalization histogram:', svfnorm_counts,  &
7037                       'on thresholds:', svfnorm_report_thresh(1:svfnorm_report_num), '(val < thresh <= val)'
7038           !TODO we should be able to deallocate skyvf, from now on we only need skyvft
7039        ENDIF ! rad_angular_discretization
7040
7041!--     deallocate temporary asvf array
7042!--     DEALLOCATE(asvf) - ifort has a problem with deallocation of allocatable target
7043!--     via pointing pointer - we need to test original targets
7044        IF ( ALLOCATED(asvf1) )  THEN
7045            DEALLOCATE(asvf1)
7046        ENDIF
7047        IF ( ALLOCATED(asvf2) )  THEN
7048            DEALLOCATE(asvf2)
7049        ENDIF
7050
7051        npcsfl = 0
7052        IF ( plant_canopy )  THEN
7053
7054            CALL location_message( '    calculation of the complete CSF array', .TRUE. )
7055            CALL radiation_write_debug_log( 'Calculation of the complete CSF array' )
7056!--         sort and merge csf for the last time, keeping the array size to minimum
7057            CALL merge_and_grow_csf(-1)
7058           
7059!--         aggregate csb among processors
7060!--         allocate necessary arrays
7061            udim = max(ncsfl,1)
7062            ALLOCATE( csflt_l(ndcsf*udim) )
7063            csflt(1:ndcsf,1:udim) => csflt_l(1:ndcsf*udim)
7064            ALLOCATE( kcsflt_l(kdcsf*udim) )
7065            kcsflt(1:kdcsf,1:udim) => kcsflt_l(1:kdcsf*udim)
7066            ALLOCATE( icsflt(0:numprocs-1) )
7067            ALLOCATE( dcsflt(0:numprocs-1) )
7068            ALLOCATE( ipcsflt(0:numprocs-1) )
7069            ALLOCATE( dpcsflt(0:numprocs-1) )
7070           
7071!--         fill out arrays of csf values and
7072!--         arrays of number of elements and displacements
7073!--         for particular precessors
7074            icsflt = 0
7075            dcsflt = 0
7076            ip = -1
7077            j = -1
7078            d = 0
7079            DO kcsf = 1, ncsfl
7080                j = j+1
7081                IF ( acsf(kcsf)%ip /= ip )  THEN
7082!--                 new block of the processor
7083!--                 number of elements of previous block
7084                    IF ( ip>=0) icsflt(ip) = j
7085                    d = d+j
7086!--                 blank blocks
7087                    DO jp = ip+1, acsf(kcsf)%ip-1
7088!--                     number of elements is zero, displacement is equal to previous
7089                        icsflt(jp) = 0
7090                        dcsflt(jp) = d
7091                    ENDDO
7092!--                 the actual block
7093                    ip = acsf(kcsf)%ip
7094                    dcsflt(ip) = d
7095                    j = 0
7096                ENDIF
7097                csflt(1,kcsf) = acsf(kcsf)%rcvf
7098!--             fill out integer values of itz,ity,itx,isurfs
7099                kcsflt(1,kcsf) = acsf(kcsf)%itz
7100                kcsflt(2,kcsf) = acsf(kcsf)%ity
7101                kcsflt(3,kcsf) = acsf(kcsf)%itx
7102                kcsflt(4,kcsf) = acsf(kcsf)%isurfs
7103            ENDDO
7104!--         last blank blocks at the end of array
7105            j = j+1
7106            IF ( ip>=0 ) icsflt(ip) = j
7107            d = d+j
7108            DO jp = ip+1, numprocs-1
7109!--             number of elements is zero, displacement is equal to previous
7110                icsflt(jp) = 0
7111                dcsflt(jp) = d
7112            ENDDO
7113           
7114!--         deallocate temporary acsf array
7115!--         DEALLOCATE(acsf) - ifort has a problem with deallocation of allocatable target
7116!--         via pointing pointer - we need to test original targets
7117            IF ( ALLOCATED(acsf1) )  THEN
7118                DEALLOCATE(acsf1)
7119            ENDIF
7120            IF ( ALLOCATED(acsf2) )  THEN
7121                DEALLOCATE(acsf2)
7122            ENDIF
7123                   
7124#if defined( __parallel )
7125!--         scatter and gather the number of elements to and from all processor
7126!--         and calculate displacements
7127            CALL radiation_write_debug_log( 'Scatter and gather the number of elements to and from all processor' )
7128            CALL MPI_AlltoAll(icsflt,1,MPI_INTEGER,ipcsflt,1,MPI_INTEGER,comm2d, ierr)
7129            IF ( ierr /= 0 ) THEN
7130                WRITE(9,*) 'Error MPI_AlltoAll1:', ierr, SIZE(icsflt), SIZE(ipcsflt)
7131                FLUSH(9)
7132            ENDIF
7133
7134            npcsfl = SUM(ipcsflt)
7135            d = 0
7136            DO i = 0, numprocs-1
7137                dpcsflt(i) = d
7138                d = d + ipcsflt(i)
7139            ENDDO
7140
7141!--         exchange csf fields between processors
7142            CALL radiation_write_debug_log( 'Exchange csf fields between processors' )
7143            udim = max(npcsfl,1)
7144            ALLOCATE( pcsflt_l(ndcsf*udim) )
7145            pcsflt(1:ndcsf,1:udim) => pcsflt_l(1:ndcsf*udim)
7146            ALLOCATE( kpcsflt_l(kdcsf*udim) )
7147            kpcsflt(1:kdcsf,1:udim) => kpcsflt_l(1:kdcsf*udim)
7148            CALL MPI_AlltoAllv(csflt_l, ndcsf*icsflt, ndcsf*dcsflt, MPI_REAL, &
7149                pcsflt_l, ndcsf*ipcsflt, ndcsf*dpcsflt, MPI_REAL, comm2d, ierr)
7150            IF ( ierr /= 0 ) THEN
7151                WRITE(9,*) 'Error MPI_AlltoAllv1:', ierr, SIZE(ipcsflt), ndcsf*icsflt, &
7152                            ndcsf*dcsflt, SIZE(pcsflt_l),ndcsf*ipcsflt, ndcsf*dpcsflt
7153                FLUSH(9)
7154            ENDIF
7155
7156            CALL MPI_AlltoAllv(kcsflt_l, kdcsf*icsflt, kdcsf*dcsflt, MPI_INTEGER, &
7157                kpcsflt_l, kdcsf*ipcsflt, kdcsf*dpcsflt, MPI_INTEGER, comm2d, ierr)
7158            IF ( ierr /= 0 ) THEN
7159                WRITE(9,*) 'Error MPI_AlltoAllv2:', ierr, SIZE(kcsflt_l),kdcsf*icsflt, &
7160                           kdcsf*dcsflt, SIZE(kpcsflt_l), kdcsf*ipcsflt, kdcsf*dpcsflt
7161                FLUSH(9)
7162            ENDIF
7163           
7164#else
7165            npcsfl = ncsfl
7166            ALLOCATE( pcsflt(ndcsf,max(npcsfl,ndcsf)) )
7167            ALLOCATE( kpcsflt(kdcsf,max(npcsfl,kdcsf)) )
7168            pcsflt = csflt
7169            kpcsflt = kcsflt
7170#endif
7171
7172!--         deallocate temporary arrays
7173            DEALLOCATE( csflt_l )
7174            DEALLOCATE( kcsflt_l )
7175            DEALLOCATE( icsflt )
7176            DEALLOCATE( dcsflt )
7177            DEALLOCATE( ipcsflt )
7178            DEALLOCATE( dpcsflt )
7179
7180!--         sort csf ( a version of quicksort )
7181            CALL radiation_write_debug_log( 'Sort csf' )
7182            CALL quicksort_csf2(kpcsflt, pcsflt, 1, npcsfl)
7183
7184!--         aggregate canopy sink factor records with identical box & source
7185!--         againg across all values from all processors
7186            CALL radiation_write_debug_log( 'Aggregate canopy sink factor records with identical box' )
7187
7188            IF ( npcsfl > 0 )  THEN
7189                icsf = 1 !< reading index
7190                kcsf = 1 !< writing index
7191                DO while (icsf < npcsfl)
7192!--                 here kpcsf(kcsf) already has values from kpcsf(icsf)
7193                    IF ( kpcsflt(3,icsf) == kpcsflt(3,icsf+1)  .AND.  &
7194                         kpcsflt(2,icsf) == kpcsflt(2,icsf+1)  .AND.  &
7195                         kpcsflt(1,icsf) == kpcsflt(1,icsf+1)  .AND.  &
7196                         kpcsflt(4,icsf) == kpcsflt(4,icsf+1) )  THEN
7197
7198                        pcsflt(1,kcsf) = pcsflt(1,kcsf) + pcsflt(1,icsf+1)
7199
7200!--                     advance reading index, keep writing index
7201                        icsf = icsf + 1
7202                    ELSE
7203!--                     not identical, just advance and copy
7204                        icsf = icsf + 1
7205                        kcsf = kcsf + 1
7206                        kpcsflt(:,kcsf) = kpcsflt(:,icsf)
7207                        pcsflt(:,kcsf) = pcsflt(:,icsf)
7208                    ENDIF
7209                ENDDO
7210!--             last written item is now also the last item in valid part of array
7211                npcsfl = kcsf
7212            ENDIF
7213
7214            ncsfl = npcsfl
7215            IF ( ncsfl > 0 )  THEN
7216                ALLOCATE( csf(ndcsf,ncsfl) )
7217                ALLOCATE( csfsurf(idcsf,ncsfl) )
7218                DO icsf = 1, ncsfl
7219                    csf(:,icsf) = pcsflt(:,icsf)
7220                    csfsurf(1,icsf) =  gridpcbl(kpcsflt(1,icsf),kpcsflt(2,icsf),kpcsflt(3,icsf))
7221                    csfsurf(2,icsf) =  kpcsflt(4,icsf)
7222                ENDDO
7223            ENDIF
7224           
7225!--         deallocation of temporary arrays
7226            IF ( npcbl > 0 )  DEALLOCATE( gridpcbl )
7227            DEALLOCATE( pcsflt_l )
7228            DEALLOCATE( kpcsflt_l )
7229            CALL radiation_write_debug_log( 'End of aggregate csf' )
7230           
7231        ENDIF
7232
7233#if defined( __parallel )
7234        CALL MPI_BARRIER( comm2d, ierr )
7235#endif
7236        CALL radiation_write_debug_log( 'End of radiation_calc_svf (after mpi_barrier)' )
7237
7238        RETURN
7239       
7240!        WRITE( message_string, * )  &
7241!            'I/O error when processing shape view factors / ',  &
7242!            'plant canopy sink factors / direct irradiance factors.'
7243!        CALL message( 'init_urban_surface', 'PA0502', 2, 2, 0, 6, 0 )
7244       
7245    END SUBROUTINE radiation_calc_svf
7246
7247   
7248!------------------------------------------------------------------------------!
7249! Description:
7250! ------------
7251!> Raytracing for detecting obstacles and calculating compound canopy sink
7252!> factors. (A simple obstacle detection would only need to process faces in
7253!> 3 dimensions without any ordering.)
7254!> Assumtions:
7255!> -----------
7256!> 1. The ray always originates from a face midpoint (only one coordinate equals
7257!>    *.5, i.e. wall) and doesn't travel parallel to the surface (that would mean
7258!>    shape factor=0). Therefore, the ray may never travel exactly along a face
7259!>    or an edge.
7260!> 2. From grid bottom to urban surface top the grid has to be *equidistant*
7261!>    within each of the dimensions, including vertical (but the resolution
7262!>    doesn't need to be the same in all three dimensions).
7263!------------------------------------------------------------------------------!
7264    SUBROUTINE raytrace(src, targ, isrc, difvf, atarg, create_csf, visible, transparency)
7265        IMPLICIT NONE
7266
7267        REAL(wp), DIMENSION(3), INTENT(in)     :: src, targ    !< real coordinates z,y,x
7268        INTEGER(iwp), INTENT(in)               :: isrc         !< index of source face for csf
7269        REAL(wp), INTENT(in)                   :: difvf        !< differential view factor for csf
7270        REAL(wp), INTENT(in)                   :: atarg        !< target surface area for csf
7271        LOGICAL, INTENT(in)                    :: create_csf   !< whether to generate new CSFs during raytracing
7272        LOGICAL, INTENT(out)                   :: visible
7273        REAL(wp), INTENT(out)                  :: transparency !< along whole path
7274        INTEGER(iwp)                           :: i, k, d
7275        INTEGER(iwp)                           :: seldim       !< dimension to be incremented
7276        INTEGER(iwp)                           :: ncsb         !< no of written plant canopy sinkboxes
7277        INTEGER(iwp)                           :: maxboxes     !< max no of gridboxes visited
7278        REAL(wp)                               :: distance     !< euclidean along path
7279        REAL(wp)                               :: crlen        !< length of gridbox crossing
7280        REAL(wp)                               :: lastdist     !< beginning of current crossing
7281        REAL(wp)                               :: nextdist     !< end of current crossing
7282        REAL(wp)                               :: realdist     !< distance in meters per unit distance
7283        REAL(wp)                               :: crmid        !< midpoint of crossing
7284        REAL(wp)                               :: cursink      !< sink factor for current canopy box
7285        REAL(wp), DIMENSION(3)                 :: delta        !< path vector
7286        REAL(wp), DIMENSION(3)                 :: uvect        !< unit vector
7287        REAL(wp), DIMENSION(3)                 :: dimnextdist  !< distance for each dimension increments
7288        INTEGER(iwp), DIMENSION(3)             :: box          !< gridbox being crossed
7289        INTEGER(iwp), DIMENSION(3)             :: dimnext      !< next dimension increments along path
7290        INTEGER(iwp), DIMENSION(3)             :: dimdelta     !< dimension direction = +- 1
7291        INTEGER(iwp)                           :: px, py       !< number of processors in x and y dir before
7292                                                               !< the processor in the question
7293        INTEGER(iwp)                           :: ip           !< number of processor where gridbox reside
7294        INTEGER(iwp)                           :: ig           !< 1D index of gridbox in global 2D array
7295       
7296        REAL(wp)                               :: eps = 1E-10_wp !< epsilon for value comparison
7297        REAL(wp)                               :: lad_s_target   !< recieved lad_s of particular grid box
7298
7299!
7300!--     Maximum number of gridboxes visited equals to maximum number of boundaries crossed in each dimension plus one. That's also
7301!--     the maximum number of plant canopy boxes written. We grow the acsf array accordingly using exponential factor.
7302        maxboxes = SUM(ABS(NINT(targ, iwp) - NINT(src, iwp))) + 1
7303        IF ( plant_canopy  .AND.  ncsfl + maxboxes > ncsfla )  THEN
7304!--         use this code for growing by fixed exponential increments (equivalent to case where ncsfl always increases by 1)
7305!--         k = CEILING(grow_factor ** real(CEILING(log(real(ncsfl + maxboxes, kind=wp)) &
7306!--                                                / log(grow_factor)), kind=wp))
7307!--         or use this code to simply always keep some extra space after growing
7308            k = CEILING(REAL(ncsfl + maxboxes, kind=wp) * grow_factor)
7309
7310            CALL merge_and_grow_csf(k)
7311        ENDIF
7312       
7313        transparency = 1._wp
7314        ncsb = 0
7315
7316        delta(:) = targ(:) - src(:)
7317        distance = SQRT(SUM(delta(:)**2))
7318        IF ( distance == 0._wp )  THEN
7319            visible = .TRUE.
7320            RETURN
7321        ENDIF
7322        uvect(:) = delta(:) / distance
7323        realdist = SQRT(SUM( (uvect(:)*(/dz(1),dy,dx/))**2 ))
7324
7325        lastdist = 0._wp
7326
7327!--     Since all face coordinates have values *.5 and we'd like to use
7328!--     integers, all these have .5 added
7329        DO d = 1, 3
7330            IF ( uvect(d) == 0._wp )  THEN
7331                dimnext(d) = 999999999
7332                dimdelta(d) = 999999999
7333                dimnextdist(d) = 1.0E20_wp
7334            ELSE IF ( uvect(d) > 0._wp )  THEN
7335                dimnext(d) = CEILING(src(d) + .5_wp)
7336                dimdelta(d) = 1
7337                dimnextdist(d) = (dimnext(d) - .5_wp - src(d)) / uvect(d)
7338            ELSE
7339                dimnext(d) = FLOOR(src(d) + .5_wp)
7340                dimdelta(d) = -1
7341                dimnextdist(d) = (dimnext(d) - .5_wp - src(d)) / uvect(d)
7342            ENDIF
7343        ENDDO
7344
7345        DO
7346!--         along what dimension will the next wall crossing be?
7347            seldim = minloc(dimnextdist, 1)
7348            nextdist = dimnextdist(seldim)
7349            IF ( nextdist > distance ) nextdist = distance
7350
7351            crlen = nextdist - lastdist
7352            IF ( crlen > .001_wp )  THEN
7353                crmid = (lastdist + nextdist) * .5_wp
7354                box = NINT(src(:) + uvect(:) * crmid, iwp)
7355
7356!--             calculate index of the grid with global indices (box(2),box(3))
7357!--             in the array nzterr and plantt and id of the coresponding processor
7358                px = box(3)/nnx
7359                py = box(2)/nny
7360                ip = px*pdims(2)+py
7361                ig = ip*nnx*nny + (box(3)-px*nnx)*nny + box(2)-py*nny
7362                IF ( box(1) <= nzterr(ig) )  THEN
7363                    visible = .FALSE.
7364                    RETURN
7365                ENDIF
7366
7367                IF ( plant_canopy )  THEN
7368                    IF ( box(1) <= plantt(ig) )  THEN
7369                        ncsb = ncsb + 1
7370                        boxes(:,ncsb) = box
7371                        crlens(ncsb) = crlen
7372#if defined( __parallel )
7373                        lad_ip(ncsb) = ip
7374                        lad_disp(ncsb) = (box(3)-px*nnx)*(nny*nzp) + (box(2)-py*nny)*nzp + box(1)-nzub
7375#endif
7376                    ENDIF
7377                ENDIF
7378            ENDIF
7379
7380            IF ( ABS(distance - nextdist) < eps )  EXIT
7381            lastdist = nextdist
7382            dimnext(seldim) = dimnext(seldim) + dimdelta(seldim)
7383            dimnextdist(seldim) = (dimnext(seldim) - .5_wp - src(seldim)) / uvect(seldim)
7384        ENDDO
7385       
7386        IF ( plant_canopy )  THEN
7387#if defined( __parallel )
7388            IF ( raytrace_mpi_rma )  THEN
7389!--             send requests for lad_s to appropriate processor
7390                CALL cpu_log( log_point_s(77), 'rad_rma_lad', 'start' )
7391                DO i = 1, ncsb
7392                    CALL MPI_Get(lad_s_ray(i), 1, MPI_REAL, lad_ip(i), lad_disp(i), &
7393                                 1, MPI_REAL, win_lad, ierr)
7394                    IF ( ierr /= 0 )  THEN
7395                        WRITE(9,*) 'Error MPI_Get1:', ierr, lad_s_ray(i), &
7396                                   lad_ip(i), lad_disp(i), win_lad
7397                        FLUSH(9)
7398                    ENDIF
7399                ENDDO
7400               
7401!--             wait for all pending local requests complete
7402                CALL MPI_Win_flush_local_all(win_lad, ierr)
7403                IF ( ierr /= 0 )  THEN
7404                    WRITE(9,*) 'Error MPI_Win_flush_local_all1:', ierr, win_lad
7405                    FLUSH(9)
7406                ENDIF
7407                CALL cpu_log( log_point_s(77), 'rad_rma_lad', 'stop' )
7408               
7409            ENDIF
7410#endif
7411
7412!--         calculate csf and transparency
7413            DO i = 1, ncsb
7414#if defined( __parallel )
7415                IF ( raytrace_mpi_rma )  THEN
7416                    lad_s_target = lad_s_ray(i)
7417                ELSE
7418                    lad_s_target = sub_lad_g(lad_ip(i)*nnx*nny*nzp + lad_disp(i))
7419                ENDIF
7420#else
7421                lad_s_target = sub_lad(boxes(1,i),boxes(2,i),boxes(3,i))
7422#endif
7423                cursink = 1._wp - exp(-ext_coef * lad_s_target * crlens(i)*realdist)
7424
7425                IF ( create_csf )  THEN
7426!--                 write svf values into the array
7427                    ncsfl = ncsfl + 1
7428                    acsf(ncsfl)%ip = lad_ip(i)
7429                    acsf(ncsfl)%itx = boxes(3,i)
7430                    acsf(ncsfl)%ity = boxes(2,i)
7431                    acsf(ncsfl)%itz = boxes(1,i)
7432                    acsf(ncsfl)%isurfs = isrc
7433                    acsf(ncsfl)%rcvf = cursink*transparency*difvf*atarg
7434                ENDIF  !< create_csf
7435
7436                transparency = transparency * (1._wp - cursink)
7437               
7438            ENDDO
7439        ENDIF
7440       
7441        visible = .TRUE.
7442
7443    END SUBROUTINE raytrace
7444   
7445 
7446!------------------------------------------------------------------------------!
7447! Description:
7448! ------------
7449!> A new, more efficient version of ray tracing algorithm that processes a whole
7450!> arc instead of a single ray.
7451!>
7452!> In all comments, horizon means tangent of horizon angle, i.e.
7453!> vertical_delta / horizontal_distance
7454!------------------------------------------------------------------------------!
7455   SUBROUTINE raytrace_2d(origin, yxdir, nrays, zdirs, iorig, aorig, vffrac,  &
7456                              calc_svf, create_csf, skip_1st_pcb,             &
7457                              lowest_free_ray, transparency, itarget)
7458      IMPLICIT NONE
7459
7460      REAL(wp), DIMENSION(3), INTENT(IN)     ::  origin        !< z,y,x coordinates of ray origin
7461      REAL(wp), DIMENSION(2), INTENT(IN)     ::  yxdir         !< y,x *unit* vector of ray direction (in grid units)
7462      INTEGER(iwp)                           ::  nrays         !< number of rays (z directions) to raytrace
7463      REAL(wp), DIMENSION(nrays), INTENT(IN) ::  zdirs         !< list of z directions to raytrace (z/hdist, grid, zenith->nadir)
7464      INTEGER(iwp), INTENT(in)               ::  iorig         !< index of origin face for csf
7465      REAL(wp), INTENT(in)                   ::  aorig         !< origin face area for csf
7466      REAL(wp), DIMENSION(nrays), INTENT(in) ::  vffrac        !< view factor fractions of each ray for csf
7467      LOGICAL, INTENT(in)                    ::  calc_svf      !< whether to calculate SFV (identify obstacle surfaces)
7468      LOGICAL, INTENT(in)                    ::  create_csf    !< whether to create canopy sink factors
7469      LOGICAL, INTENT(in)                    ::  skip_1st_pcb  !< whether to skip first plant canopy box during raytracing
7470      INTEGER(iwp), INTENT(out)              ::  lowest_free_ray !< index into zdirs
7471      REAL(wp), DIMENSION(nrays), INTENT(OUT) ::  transparency !< transparencies of zdirs paths
7472      INTEGER(iwp), DIMENSION(nrays), INTENT(OUT) ::  itarget  !< global indices of target faces for zdirs
7473
7474      INTEGER(iwp), DIMENSION(nrays)         ::  target_procs
7475      REAL(wp)                               ::  horizon       !< highest horizon found after raytracing (z/hdist)
7476      INTEGER(iwp)                           ::  i, k, l, d
7477      INTEGER(iwp)                           ::  seldim       !< dimension to be incremented
7478      REAL(wp), DIMENSION(2)                 ::  yxorigin     !< horizontal copy of origin (y,x)
7479      REAL(wp)                               ::  distance     !< euclidean along path
7480      REAL(wp)                               ::  lastdist     !< beginning of current crossing
7481      REAL(wp)                               ::  nextdist     !< end of current crossing
7482      REAL(wp)                               ::  crmid        !< midpoint of crossing
7483      REAL(wp)                               ::  horz_entry   !< horizon at entry to column
7484      REAL(wp)                               ::  horz_exit    !< horizon at exit from column
7485      REAL(wp)                               ::  bdydim       !< boundary for current dimension
7486      REAL(wp), DIMENSION(2)                 ::  crossdist    !< distances to boundary for dimensions
7487      REAL(wp), DIMENSION(2)                 ::  dimnextdist  !< distance for each dimension increments
7488      INTEGER(iwp), DIMENSION(2)             ::  column       !< grid column being crossed
7489      INTEGER(iwp), DIMENSION(2)             ::  dimnext      !< next dimension increments along path
7490      INTEGER(iwp), DIMENSION(2)             ::  dimdelta     !< dimension direction = +- 1
7491      INTEGER(iwp)                           ::  px, py       !< number of processors in x and y dir before
7492                                                              !< the processor in the question
7493      INTEGER(iwp)                           ::  ip           !< number of processor where gridbox reside
7494      INTEGER(iwp)                           ::  ig           !< 1D index of gridbox in global 2D array
7495      INTEGER(iwp)                           ::  wcount       !< RMA window item count
7496      INTEGER(iwp)                           ::  maxboxes     !< max no of CSF created
7497      INTEGER(iwp)                           ::  nly          !< maximum  plant canopy height
7498      INTEGER(iwp)                           ::  ntrack
7499     
7500      INTEGER(iwp)                           ::  zb0
7501      INTEGER(iwp)                           ::  zb1
7502      INTEGER(iwp)                           ::  nz
7503      INTEGER(iwp)                           ::  iz
7504      INTEGER(iwp)                           ::  zsgn
7505      INTEGER(iwp)                           ::  lowest_lad   !< lowest column cell for which we need LAD
7506      INTEGER(iwp)                           ::  lastdir      !< wall direction before hitting this column
7507      INTEGER(iwp), DIMENSION(2)             ::  lastcolumn
7508
7509#if defined( __parallel )
7510      INTEGER(MPI_ADDRESS_KIND)              ::  wdisp        !< RMA window displacement
7511#endif
7512     
7513      REAL(wp)                               ::  eps = 1E-10_wp !< epsilon for value comparison
7514      REAL(wp)                               ::  zbottom, ztop !< urban surface boundary in real numbers
7515      REAL(wp)                               ::  zorig         !< z coordinate of ray column entry
7516      REAL(wp)                               ::  zexit         !< z coordinate of ray column exit
7517      REAL(wp)                               ::  qdist         !< ratio of real distance to z coord difference
7518      REAL(wp)                               ::  dxxyy         !< square of real horizontal distance
7519      REAL(wp)                               ::  curtrans      !< transparency of current PC box crossing
7520     
7521
7522     
7523      yxorigin(:) = origin(2:3)
7524      transparency(:) = 1._wp !-- Pre-set the all rays to transparent before reducing
7525      horizon = -HUGE(1._wp)
7526      lowest_free_ray = nrays
7527      IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7528         ALLOCATE(target_surfl(nrays))
7529         target_surfl(:) = -1
7530         lastdir = -999
7531         lastcolumn(:) = -999
7532      ENDIF
7533
7534!--   Determine distance to boundary (in 2D xy)
7535      IF ( yxdir(1) > 0._wp )  THEN
7536         bdydim = ny + .5_wp !< north global boundary
7537         crossdist(1) = (bdydim - yxorigin(1)) / yxdir(1)
7538      ELSEIF ( yxdir(1) == 0._wp )  THEN
7539         crossdist(1) = HUGE(1._wp)
7540      ELSE
7541          bdydim = -.5_wp !< south global boundary
7542          crossdist(1) = (bdydim - yxorigin(1)) / yxdir(1)
7543      ENDIF
7544
7545      IF ( yxdir(2) >= 0._wp )  THEN
7546          bdydim = nx + .5_wp !< east global boundary
7547          crossdist(2) = (bdydim - yxorigin(2)) / yxdir(2)
7548      ELSEIF ( yxdir(2) == 0._wp )  THEN
7549         crossdist(2) = HUGE(1._wp)
7550      ELSE
7551          bdydim = -.5_wp !< west global boundary
7552          crossdist(2) = (bdydim - yxorigin(2)) / yxdir(2)
7553      ENDIF
7554      distance = minval(crossdist, 1)
7555
7556      IF ( plant_canopy )  THEN
7557         rt2_track_dist(0) = 0._wp
7558         rt2_track_lad(:,:) = 0._wp
7559         nly = plantt_max - nzub + 1
7560      ENDIF
7561
7562      lastdist = 0._wp
7563
7564!--   Since all face coordinates have values *.5 and we'd like to use
7565!--   integers, all these have .5 added
7566      DO  d = 1, 2
7567          IF ( yxdir(d) == 0._wp )  THEN
7568              dimnext(d) = HUGE(1_iwp)
7569              dimdelta(d) = HUGE(1_iwp)
7570              dimnextdist(d) = HUGE(1._wp)
7571          ELSE IF ( yxdir(d) > 0._wp )  THEN
7572              dimnext(d) = FLOOR(yxorigin(d) + .5_wp) + 1
7573              dimdelta(d) = 1
7574              dimnextdist(d) = (dimnext(d) - .5_wp - yxorigin(d)) / yxdir(d)
7575          ELSE
7576              dimnext(d) = CEILING(yxorigin(d) + .5_wp) - 1
7577              dimdelta(d) = -1
7578              dimnextdist(d) = (dimnext(d) - .5_wp - yxorigin(d)) / yxdir(d)
7579          ENDIF
7580      ENDDO
7581
7582      ntrack = 0
7583      DO
7584!--      along what dimension will the next wall crossing be?
7585         seldim = minloc(dimnextdist, 1)
7586         nextdist = dimnextdist(seldim)
7587         IF ( nextdist > distance )  nextdist = distance
7588
7589         IF ( nextdist > lastdist )  THEN
7590            ntrack = ntrack + 1
7591            crmid = (lastdist + nextdist) * .5_wp
7592            column = NINT(yxorigin(:) + yxdir(:) * crmid, iwp)
7593
7594!--         calculate index of the grid with global indices (column(1),column(2))
7595!--         in the array nzterr and plantt and id of the coresponding processor
7596            px = column(2)/nnx
7597            py = column(1)/nny
7598            ip = px*pdims(2)+py
7599            ig = ip*nnx*nny + (column(2)-px*nnx)*nny + column(1)-py*nny
7600
7601            IF ( lastdist == 0._wp )  THEN
7602               horz_entry = -HUGE(1._wp)
7603            ELSE
7604               horz_entry = (REAL(nzterr(ig), wp) + .5_wp - origin(1)) / lastdist
7605            ENDIF
7606            horz_exit = (REAL(nzterr(ig), wp) + .5_wp - origin(1)) / nextdist
7607
7608            IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7609!
7610!--            Identify vertical obstacles hit by rays in current column
7611               DO WHILE ( lowest_free_ray > 0 )
7612                  IF ( zdirs(lowest_free_ray) > horz_entry )  EXIT
7613!
7614!--               This may only happen after 1st column, so lastdir and lastcolumn are valid
7615                  CALL request_itarget(lastdir,                                         &
7616                        CEILING(-0.5_wp + origin(1) + zdirs(lowest_free_ray)*lastdist), &
7617                        lastcolumn(1), lastcolumn(2),                                   &
7618                        target_surfl(lowest_free_ray), target_procs(lowest_free_ray))
7619                  lowest_free_ray = lowest_free_ray - 1
7620               ENDDO
7621!
7622!--            Identify horizontal obstacles hit by rays in current column
7623               DO WHILE ( lowest_free_ray > 0 )
7624                  IF ( zdirs(lowest_free_ray) > horz_exit )  EXIT
7625                  CALL request_itarget(iup_u, nzterr(ig)+1, column(1), column(2), &
7626                                       target_surfl(lowest_free_ray),           &
7627                                       target_procs(lowest_free_ray))
7628                  lowest_free_ray = lowest_free_ray - 1
7629               ENDDO
7630            ENDIF
7631
7632            horizon = MAX(horizon, horz_entry, horz_exit)
7633
7634            IF ( plant_canopy )  THEN
7635               rt2_track(:, ntrack) = column(:)
7636               rt2_track_dist(ntrack) = nextdist
7637            ENDIF
7638         ENDIF
7639
7640         IF ( ABS(distance - nextdist) < eps )  EXIT
7641
7642         IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7643!
7644!--         Save wall direction of coming building column (= this air column)
7645            IF ( seldim == 1 )  THEN
7646               IF ( dimdelta(seldim) == 1 )  THEN
7647                  lastdir = isouth_u
7648               ELSE
7649                  lastdir = inorth_u
7650               ENDIF
7651            ELSE
7652               IF ( dimdelta(seldim) == 1 )  THEN
7653                  lastdir = iwest_u
7654               ELSE
7655                  lastdir = ieast_u
7656               ENDIF
7657            ENDIF
7658            lastcolumn = column
7659         ENDIF
7660         lastdist = nextdist
7661         dimnext(seldim) = dimnext(seldim) + dimdelta(seldim)
7662         dimnextdist(seldim) = (dimnext(seldim) - .5_wp - yxorigin(seldim)) / yxdir(seldim)
7663      ENDDO
7664
7665      IF ( plant_canopy )  THEN
7666!--      Request LAD WHERE applicable
7667!--     
7668#if defined( __parallel )
7669         IF ( raytrace_mpi_rma )  THEN
7670!--         send requests for lad_s to appropriate processor
7671            !CALL cpu_log( log_point_s(77), 'usm_init_rma', 'start' )
7672            DO  i = 1, ntrack
7673               px = rt2_track(2,i)/nnx
7674               py = rt2_track(1,i)/nny
7675               ip = px*pdims(2)+py
7676               ig = ip*nnx*nny + (rt2_track(2,i)-px*nnx)*nny + rt2_track(1,i)-py*nny
7677
7678               IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7679!
7680!--               For fixed view resolution, we need plant canopy even for rays
7681!--               to opposing surfaces
7682                  lowest_lad = nzterr(ig) + 1
7683               ELSE
7684!
7685!--               We only need LAD for rays directed above horizon (to sky)
7686                  lowest_lad = CEILING( -0.5_wp + origin(1) +            &
7687                                    MIN( horizon * rt2_track_dist(i-1),  & ! entry
7688                                         horizon * rt2_track_dist(i)   ) ) ! exit
7689               ENDIF
7690!
7691!--            Skip asking for LAD where all plant canopy is under requested level
7692               IF ( plantt(ig) < lowest_lad )  CYCLE
7693
7694               wdisp = (rt2_track(2,i)-px*nnx)*(nny*nzp) + (rt2_track(1,i)-py*nny)*nzp + lowest_lad-nzub
7695               wcount = plantt(ig)-lowest_lad+1
7696               ! TODO send request ASAP - even during raytracing
7697               CALL MPI_Get(rt2_track_lad(lowest_lad:plantt(ig), i), wcount, MPI_REAL, ip,    &
7698                            wdisp, wcount, MPI_REAL, win_lad, ierr)
7699               IF ( ierr /= 0 )  THEN
7700                  WRITE(9,*) 'Error MPI_Get2:', ierr, rt2_track_lad(lowest_lad:plantt(ig), i), &
7701                             wcount, ip, wdisp, win_lad
7702                  FLUSH(9)
7703               ENDIF
7704            ENDDO
7705
7706!--         wait for all pending local requests complete
7707            ! TODO WAIT selectively for each column later when needed
7708            CALL MPI_Win_flush_local_all(win_lad, ierr)
7709            IF ( ierr /= 0 )  THEN
7710               WRITE(9,*) 'Error MPI_Win_flush_local_all2:', ierr, win_lad
7711               FLUSH(9)
7712            ENDIF
7713            !CALL cpu_log( log_point_s(77), 'usm_init_rma', 'stop' )
7714
7715         ELSE ! raytrace_mpi_rma = .F.
7716            DO  i = 1, ntrack
7717               px = rt2_track(2,i)/nnx
7718               py = rt2_track(1,i)/nny
7719               ip = px*pdims(2)+py
7720               ig = ip*nnx*nny*nzp + (rt2_track(2,i)-px*nnx)*(nny*nzp) + (rt2_track(1,i)-py*nny)*nzp
7721               rt2_track_lad(nzub:plantt_max, i) = sub_lad_g(ig:ig+nly-1)
7722            ENDDO
7723         ENDIF
7724#else
7725         DO  i = 1, ntrack
7726            rt2_track_lad(nzub:plantt_max, i) = sub_lad(rt2_track(1,i), rt2_track(2,i), nzub:plantt_max)
7727         ENDDO
7728#endif
7729      ENDIF ! plant_canopy
7730
7731      IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7732#if defined( __parallel )
7733!--      wait for all gridsurf requests to complete
7734         CALL MPI_Win_flush_local_all(win_gridsurf, ierr)
7735         IF ( ierr /= 0 )  THEN
7736            WRITE(9,*) 'Error MPI_Win_flush_local_all3:', ierr, win_gridsurf
7737            FLUSH(9)
7738         ENDIF
7739#endif
7740!
7741!--      recalculate local surf indices into global ones
7742         DO i = 1, nrays
7743            IF ( target_surfl(i) == -1 )  THEN
7744               itarget(i) = -1
7745            ELSE
7746               itarget(i) = target_surfl(i) + surfstart(target_procs(i))
7747            ENDIF
7748         ENDDO
7749         
7750         DEALLOCATE( target_surfl )
7751         
7752      ELSE
7753         itarget(:) = -1
7754      ENDIF ! rad_angular_discretization
7755
7756      IF ( plant_canopy )  THEN
7757!--      Skip the PCB around origin if requested (for MRT, the PCB might not be there)
7758!--     
7759         IF ( skip_1st_pcb  .AND.  NINT(origin(1)) <= plantt_max )  THEN
7760            rt2_track_lad(NINT(origin(1), iwp), 1) = 0._wp
7761         ENDIF
7762
7763!--      Assert that we have space allocated for CSFs
7764!--     
7765         maxboxes = (ntrack + MAX(CEILING(origin(1)-.5_wp) - nzub,          &
7766                                  nzut - CEILING(origin(1)-.5_wp))) * nrays
7767         IF ( ncsfl + maxboxes > ncsfla )  THEN
7768!--         use this code for growing by fixed exponential increments (equivalent to case where ncsfl always increases by 1)
7769!--         k = CEILING(grow_factor ** real(CEILING(log(real(ncsfl + maxboxes, kind=wp)) &
7770!--                                                / log(grow_factor)), kind=wp))
7771!--         or use this code to simply always keep some extra space after growing
7772            k = CEILING(REAL(ncsfl + maxboxes, kind=wp) * grow_factor)
7773            CALL merge_and_grow_csf(k)
7774         ENDIF
7775
7776!--      Calculate transparencies and store new CSFs
7777!--     
7778         zbottom = REAL(nzub, wp) - .5_wp
7779         ztop = REAL(plantt_max, wp) + .5_wp
7780
7781!--      Reverse direction of radiation (face->sky), only when calc_svf
7782!--     
7783         IF ( calc_svf )  THEN
7784            DO  i = 1, ntrack ! for each column
7785               dxxyy = ((dy*yxdir(1))**2 + (dx*yxdir(2))**2) * (rt2_track_dist(i)-rt2_track_dist(i-1))**2
7786               px = rt2_track(2,i)/nnx
7787               py = rt2_track(1,i)/nny
7788               ip = px*pdims(2)+py
7789
7790               DO  k = 1, nrays ! for each ray
7791!
7792!--               NOTE 6778:
7793!--               With traditional svf discretization, CSFs under the horizon
7794!--               (i.e. for surface to surface radiation)  are created in
7795!--               raytrace(). With rad_angular_discretization, we must create
7796!--               CSFs under horizon only for one direction, otherwise we would
7797!--               have duplicate amount of energy. Although we could choose
7798!--               either of the two directions (they differ only by
7799!--               discretization error with no bias), we choose the the backward
7800!--               direction, because it tends to cumulate high canopy sink
7801!--               factors closer to raytrace origin, i.e. it should potentially
7802!--               cause less moiree.
7803                  IF ( .NOT. rad_angular_discretization )  THEN
7804                     IF ( zdirs(k) <= horizon )  CYCLE
7805                  ENDIF
7806
7807                  zorig = origin(1) + zdirs(k) * rt2_track_dist(i-1)
7808                  IF ( zorig <= zbottom  .OR.  zorig >= ztop )  CYCLE
7809
7810                  zsgn = INT(SIGN(1._wp, zdirs(k)), iwp)
7811                  rt2_dist(1) = 0._wp
7812                  IF ( zdirs(k) == 0._wp )  THEN ! ray is exactly horizontal
7813                     nz = 2
7814                     rt2_dist(nz) = SQRT(dxxyy)
7815                     iz = CEILING(-.5_wp + zorig, iwp)
7816                  ELSE
7817                     zexit = MIN(MAX(origin(1) + zdirs(k) * rt2_track_dist(i), zbottom), ztop)
7818
7819                     zb0 = FLOOR(  zorig * zsgn - .5_wp) + 1  ! because it must be greater than orig
7820                     zb1 = CEILING(zexit * zsgn - .5_wp) - 1  ! because it must be smaller than exit
7821                     nz = MAX(zb1 - zb0 + 3, 2)
7822                     rt2_dist(nz) = SQRT(((zexit-zorig)*dz(1))**2 + dxxyy)
7823                     qdist = rt2_dist(nz) / (zexit-zorig)
7824                     rt2_dist(2:nz-1) = (/( ((REAL(l, wp) + .5_wp) * zsgn - zorig) * qdist , l = zb0, zb1 )/)
7825                     iz = zb0 * zsgn
7826                  ENDIF
7827
7828                  DO  l = 2, nz
7829                     IF ( rt2_track_lad(iz, i) > 0._wp )  THEN
7830                        curtrans = exp(-ext_coef * rt2_track_lad(iz, i) * (rt2_dist(l)-rt2_dist(l-1)))
7831
7832                        IF ( create_csf )  THEN
7833                           ncsfl = ncsfl + 1
7834                           acsf(ncsfl)%ip = ip
7835                           acsf(ncsfl)%itx = rt2_track(2,i)
7836                           acsf(ncsfl)%ity = rt2_track(1,i)
7837                           acsf(ncsfl)%itz = iz
7838                           acsf(ncsfl)%isurfs = iorig
7839                           acsf(ncsfl)%rcvf = (1._wp - curtrans)*transparency(k)*vffrac(k)
7840                        ENDIF
7841
7842                        transparency(k) = transparency(k) * curtrans
7843                     ENDIF
7844                     iz = iz + zsgn
7845                  ENDDO ! l = 1, nz - 1
7846               ENDDO ! k = 1, nrays
7847            ENDDO ! i = 1, ntrack
7848
7849            transparency(1:lowest_free_ray) = 1._wp !-- Reset rays above horizon to transparent (see NOTE 6778)
7850         ENDIF
7851
7852!--      Forward direction of radiation (sky->face), always
7853!--     
7854         DO  i = ntrack, 1, -1 ! for each column backwards
7855            dxxyy = ((dy*yxdir(1))**2 + (dx*yxdir(2))**2) * (rt2_track_dist(i)-rt2_track_dist(i-1))**2
7856            px = rt2_track(2,i)/nnx
7857            py = rt2_track(1,i)/nny
7858            ip = px*pdims(2)+py
7859
7860            DO  k = 1, nrays ! for each ray
7861!
7862!--            See NOTE 6778 above
7863               IF ( zdirs(k) <= horizon )  CYCLE
7864
7865               zexit = origin(1) + zdirs(k) * rt2_track_dist(i-1)
7866               IF ( zexit <= zbottom  .OR.  zexit >= ztop )  CYCLE
7867
7868               zsgn = -INT(SIGN(1._wp, zdirs(k)), iwp)
7869               rt2_dist(1) = 0._wp
7870               IF ( zdirs(k) == 0._wp )  THEN ! ray is exactly horizontal
7871                  nz = 2
7872                  rt2_dist(nz) = SQRT(dxxyy)
7873                  iz = NINT(zexit, iwp)
7874               ELSE
7875                  zorig = MIN(MAX(origin(1) + zdirs(k) * rt2_track_dist(i), zbottom), ztop)
7876
7877                  zb0 = FLOOR(  zorig * zsgn - .5_wp) + 1  ! because it must be greater than orig
7878                  zb1 = CEILING(zexit * zsgn - .5_wp) - 1  ! because it must be smaller than exit
7879                  nz = MAX(zb1 - zb0 + 3, 2)
7880                  rt2_dist(nz) = SQRT(((zexit-zorig)*dz(1))**2 + dxxyy)
7881                  qdist = rt2_dist(nz) / (zexit-zorig)
7882                  rt2_dist(2:nz-1) = (/( ((REAL(l, wp) + .5_wp) * zsgn - zorig) * qdist , l = zb0, zb1 )/)
7883                  iz = zb0 * zsgn
7884               ENDIF
7885
7886               DO  l = 2, nz
7887                  IF ( rt2_track_lad(iz, i) > 0._wp )  THEN
7888                     curtrans = exp(-ext_coef * rt2_track_lad(iz, i) * (rt2_dist(l)-rt2_dist(l-1)))
7889
7890                     IF ( create_csf )  THEN
7891                        ncsfl = ncsfl + 1
7892                        acsf(ncsfl)%ip = ip
7893                        acsf(ncsfl)%itx = rt2_track(2,i)
7894                        acsf(ncsfl)%ity = rt2_track(1,i)
7895                        acsf(ncsfl)%itz = iz
7896                        IF ( itarget(k) /= -1 )  ERROR STOP !FIXME remove after test
7897                        acsf(ncsfl)%isurfs = -1
7898                        acsf(ncsfl)%rcvf = (1._wp - curtrans)*transparency(k)*aorig*vffrac(k)
7899                     ENDIF  ! create_csf
7900
7901                     transparency(k) = transparency(k) * curtrans
7902                  ENDIF
7903                  iz = iz + zsgn
7904               ENDDO ! l = 1, nz - 1
7905            ENDDO ! k = 1, nrays
7906         ENDDO ! i = 1, ntrack
7907      ENDIF ! plant_canopy
7908
7909      IF ( .NOT. (rad_angular_discretization  .AND.  calc_svf) )  THEN
7910!
7911!--      Just update lowest_free_ray according to horizon
7912         DO WHILE ( lowest_free_ray > 0 )
7913            IF ( zdirs(lowest_free_ray) > horizon )  EXIT
7914            lowest_free_ray = lowest_free_ray - 1
7915         ENDDO
7916      ENDIF
7917
7918   CONTAINS
7919
7920      SUBROUTINE request_itarget( d, z, y, x, isurfl, iproc )
7921
7922         INTEGER(iwp), INTENT(in)            ::  d, z, y, x
7923         INTEGER(iwp), TARGET, INTENT(out)   ::  isurfl
7924         INTEGER(iwp), INTENT(out)           ::  iproc
7925#if defined( __parallel )
7926#else
7927         INTEGER(iwp)                        ::  target_displ  !< index of the grid in the local gridsurf array
7928#endif
7929         INTEGER(iwp)                        ::  px, py        !< number of processors in x and y direction
7930                                                               !< before the processor in the question
7931#if defined( __parallel )
7932         INTEGER(KIND=MPI_ADDRESS_KIND)      ::  target_displ  !< index of the grid in the local gridsurf array
7933
7934!
7935!--      Calculate target processor and index in the remote local target gridsurf array
7936         px = x / nnx
7937         py = y / nny
7938         iproc = px * pdims(2) + py
7939         target_displ = ((x-px*nnx) * nny + y - py*nny ) * nzu * nsurf_type_u +&
7940                        ( z-nzub ) * nsurf_type_u + d
7941!
7942!--      Send MPI_Get request to obtain index target_surfl(i)
7943         CALL MPI_GET( isurfl, 1, MPI_INTEGER, iproc, target_displ,            &
7944                       1, MPI_INTEGER, win_gridsurf, ierr)
7945         IF ( ierr /= 0 )  THEN
7946            WRITE( 9,* ) 'Error MPI_Get3:', ierr, isurfl, iproc, target_displ, &
7947                         win_gridsurf
7948            FLUSH( 9 )
7949         ENDIF
7950#else
7951!--      set index target_surfl(i)
7952         isurfl = gridsurf(d,z,y,x)
7953#endif
7954
7955      END SUBROUTINE request_itarget
7956
7957   END SUBROUTINE raytrace_2d
7958 
7959
7960!------------------------------------------------------------------------------!
7961!
7962! Description:
7963! ------------
7964!> Calculates apparent solar positions for all timesteps and stores discretized
7965!> positions.
7966!------------------------------------------------------------------------------!
7967   SUBROUTINE radiation_presimulate_solar_pos
7968      IMPLICIT NONE
7969
7970      INTEGER(iwp)                              ::  it, i, j
7971      REAL(wp)                                  ::  tsrp_prev
7972      REAL(wp)                                  ::  simulated_time_prev
7973      REAL(wp), DIMENSION(:,:), ALLOCATABLE     ::  dsidir_tmp       !< dsidir_tmp[:,i] = unit vector of i-th
7974                                                                     !< appreant solar direction
7975
7976      ALLOCATE ( dsidir_rev(0:raytrace_discrete_elevs/2-1,                 &
7977                            0:raytrace_discrete_azims-1) )
7978      dsidir_rev(:,:) = -1
7979      ALLOCATE ( dsidir_tmp(3,                                             &
7980                     raytrace_discrete_elevs/2*raytrace_discrete_azims) )
7981      ndsidir = 0
7982
7983!
7984!--   We will artificialy update time_since_reference_point and return to
7985!--   true value later
7986      tsrp_prev = time_since_reference_point
7987      simulated_time_prev = simulated_time
7988      sun_direction = .TRUE.
7989
7990!
7991!--   Process spinup time if configured
7992      IF ( spinup_time > 0._wp )  THEN
7993         DO  it = 0, CEILING(spinup_time / dt_spinup)
7994            time_since_reference_point = -spinup_time + REAL(it, wp) * dt_spinup
7995            simulated_time = simulated_time + dt_spinup
7996            CALL simulate_pos
7997         ENDDO
7998      ENDIF
7999!
8000!--   Process simulation time
8001      DO  it = 0, CEILING(( end_time - spinup_time ) / dt_radiation)
8002         time_since_reference_point = REAL(it, wp) * dt_radiation
8003         simulated_time = simulated_time + dt_spinup
8004         CALL simulate_pos
8005      ENDDO
8006
8007      time_since_reference_point = tsrp_prev
8008      simulated_time = simulated_time_prev
8009
8010!--   Allocate global vars which depend on ndsidir
8011      ALLOCATE ( dsidir ( 3, ndsidir ) )
8012      dsidir(:,:) = dsidir_tmp(:, 1:ndsidir)
8013      DEALLOCATE ( dsidir_tmp )
8014
8015      ALLOCATE ( dsitrans(nsurfl, ndsidir) )
8016      ALLOCATE ( dsitransc(npcbl, ndsidir) )
8017      IF ( nmrtbl > 0 )  ALLOCATE ( mrtdsit(nmrtbl, ndsidir) )
8018
8019      WRITE ( message_string, * ) 'Precalculated', ndsidir, ' solar positions', &
8020                                  'from', it, ' timesteps.'
8021      CALL message( 'radiation_presimulate_solar_pos', 'UI0013', 0, 0, 0, 6, 0 )
8022
8023      CONTAINS
8024
8025      !------------------------------------------------------------------------!
8026      ! Description:
8027      ! ------------
8028      !> Simuates a single position
8029      !------------------------------------------------------------------------!
8030      SUBROUTINE simulate_pos
8031         IMPLICIT NONE
8032!
8033!--      Update apparent solar position based on modified t_s_r_p
8034         CALL calc_zenith
8035         IF ( zenith(0) > 0 )  THEN
8036!--         
8037!--         Identify solar direction vector (discretized number) 1)
8038            i = MODULO(NINT(ATAN2(sun_dir_lon(0), sun_dir_lat(0))               &
8039                            / (2._wp*pi) * raytrace_discrete_azims-.5_wp, iwp), &
8040                       raytrace_discrete_azims)
8041            j = FLOOR(ACOS(zenith(0)) / pi * raytrace_discrete_elevs)
8042            IF ( dsidir_rev(j, i) == -1 )  THEN
8043               ndsidir = ndsidir + 1
8044               dsidir_tmp(:, ndsidir) =                                              &
8045                     (/ COS((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs), &
8046                        SIN((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs)  &
8047                      * COS((REAL(i,wp)+.5_wp) * 2_wp*pi / raytrace_discrete_azims), &
8048                        SIN((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs)  &
8049                      * SIN((REAL(i,wp)+.5_wp) * 2_wp*pi / raytrace_discrete_azims) /)
8050               dsidir_rev(j, i) = ndsidir
8051            ENDIF
8052         ENDIF
8053      END SUBROUTINE simulate_pos
8054
8055   END SUBROUTINE radiation_presimulate_solar_pos
8056
8057
8058
8059!------------------------------------------------------------------------------!
8060! Description:
8061! ------------
8062!> Determines whether two faces are oriented towards each other. Since the
8063!> surfaces follow the gird box surfaces, it checks first whether the two surfaces
8064!> are directed in the same direction, then it checks if the two surfaces are
8065!> located in confronted direction but facing away from each other, e.g. <--| |-->
8066!------------------------------------------------------------------------------!
8067    PURE LOGICAL FUNCTION surface_facing(x, y, z, d, x2, y2, z2, d2)
8068        IMPLICIT NONE
8069        INTEGER(iwp),   INTENT(in)  :: x, y, z, d, x2, y2, z2, d2
8070     
8071        surface_facing = .FALSE.
8072
8073!-- first check: are the two surfaces directed in the same direction
8074        IF ( (d==iup_u  .OR.  d==iup_l )                             &
8075             .AND. (d2==iup_u  .OR. d2==iup_l) ) RETURN
8076        IF ( (d==isouth_u  .OR.  d==isouth_l ) &
8077             .AND.  (d2==isouth_u  .OR.  d2==isouth_l) ) RETURN
8078        IF ( (d==inorth_u  .OR.  d==inorth_l ) &
8079             .AND.  (d2==inorth_u  .OR.  d2==inorth_l) ) RETURN
8080        IF ( (d==iwest_u  .OR.  d==iwest_l )     &
8081             .AND.  (d2==iwest_u  .OR.  d2==iwest_l ) ) RETURN
8082        IF ( (d==ieast_u  .OR.  d==ieast_l )     &
8083             .AND.  (d2==ieast_u  .OR.  d2==ieast_l ) ) RETURN
8084
8085!-- second check: are surfaces facing away from each other
8086        SELECT CASE (d)
8087            CASE (iup_u, iup_l)                     !< upward facing surfaces
8088                IF ( z2 < z ) RETURN
8089            CASE (isouth_u, isouth_l)               !< southward facing surfaces
8090                IF ( y2 > y ) RETURN
8091            CASE (inorth_u, inorth_l)               !< northward facing surfaces
8092                IF ( y2 < y ) RETURN
8093            CASE (iwest_u, iwest_l)                 !< westward facing surfaces
8094                IF ( x2 > x ) RETURN
8095            CASE (ieast_u, ieast_l)                 !< eastward facing surfaces
8096                IF ( x2 < x ) RETURN
8097        END SELECT
8098
8099        SELECT CASE (d2)
8100            CASE (iup_u)                            !< ground, roof
8101                IF ( z < z2 ) RETURN
8102            CASE (isouth_u, isouth_l)               !< south facing
8103                IF ( y > y2 ) RETURN
8104            CASE (inorth_u, inorth_l)               !< north facing
8105                IF ( y < y2 ) RETURN
8106            CASE (iwest_u, iwest_l)                 !< west facing
8107                IF ( x > x2 ) RETURN
8108            CASE (ieast_u, ieast_l)                 !< east facing
8109                IF ( x < x2 ) RETURN
8110            CASE (-1)
8111                CONTINUE
8112        END SELECT
8113
8114        surface_facing = .TRUE.
8115       
8116    END FUNCTION surface_facing
8117
8118
8119!------------------------------------------------------------------------------!
8120!
8121! Description:
8122! ------------
8123!> Soubroutine reads svf and svfsurf data from saved file
8124!> SVF means sky view factors and CSF means canopy sink factors
8125!------------------------------------------------------------------------------!
8126    SUBROUTINE radiation_read_svf
8127
8128       IMPLICIT NONE
8129       
8130       CHARACTER(rad_version_len)   :: rad_version_field
8131       
8132       INTEGER(iwp)                 :: i
8133       INTEGER(iwp)                 :: ndsidir_from_file = 0
8134       INTEGER(iwp)                 :: npcbl_from_file = 0
8135       INTEGER(iwp)                 :: nsurfl_from_file = 0
8136       
8137       DO  i = 0, io_blocks-1
8138          IF ( i == io_group )  THEN
8139
8140!
8141!--          numprocs_previous_run is only known in case of reading restart
8142!--          data. If a new initial run which reads svf data is started the
8143!--          following query will be skipped
8144             IF ( initializing_actions == 'read_restart_data' ) THEN
8145
8146                IF ( numprocs_previous_run /= numprocs ) THEN
8147                   WRITE( message_string, * ) 'A different number of ',        &
8148                                              'processors between the run ',   &
8149                                              'that has written the svf data ',&
8150                                              'and the one that will read it ',&
8151                                              'is not allowed' 
8152                   CALL message( 'check_open', 'PA0491', 1, 2, 0, 6, 0 )
8153                ENDIF
8154
8155             ENDIF
8156             
8157!
8158!--          Open binary file
8159             CALL check_open( 88 )
8160
8161!
8162!--          read and check version
8163             READ ( 88 ) rad_version_field
8164             IF ( TRIM(rad_version_field) /= TRIM(rad_version) )  THEN
8165                 WRITE( message_string, * ) 'Version of binary SVF file "',    &
8166                             TRIM(rad_version_field), '" does not match ',     &
8167                             'the version of model "', TRIM(rad_version), '"'
8168                 CALL message( 'radiation_read_svf', 'PA0482', 1, 2, 0, 6, 0 )
8169             ENDIF
8170             
8171!
8172!--          read nsvfl, ncsfl, nsurfl
8173             READ ( 88 ) nsvfl, ncsfl, nsurfl_from_file, npcbl_from_file,      &
8174                         ndsidir_from_file
8175             
8176             IF ( nsvfl < 0  .OR.  ncsfl < 0 )  THEN
8177                 WRITE( message_string, * ) 'Wrong number of SVF or CSF'
8178                 CALL message( 'radiation_read_svf', 'PA0483', 1, 2, 0, 6, 0 )
8179             ELSE
8180                 WRITE(message_string,*) '    Number of SVF, CSF, and nsurfl ',&
8181                                         'to read', nsvfl, ncsfl,              &
8182                                         nsurfl_from_file
8183                 CALL location_message( message_string, .TRUE. )
8184             ENDIF
8185             
8186             IF ( nsurfl_from_file /= nsurfl )  THEN
8187                 WRITE( message_string, * ) 'nsurfl from SVF file does not ',  &
8188                                            'match calculated nsurfl from ',   &
8189                                            'radiation_interaction_init'
8190                 CALL message( 'radiation_read_svf', 'PA0490', 1, 2, 0, 6, 0 )
8191             ENDIF
8192             
8193             IF ( npcbl_from_file /= npcbl )  THEN
8194                 WRITE( message_string, * ) 'npcbl from SVF file does not ',   &
8195                                            'match calculated npcbl from ',    &
8196                                            'radiation_interaction_init'
8197                 CALL message( 'radiation_read_svf', 'PA0493', 1, 2, 0, 6, 0 )
8198             ENDIF
8199             
8200             IF ( ndsidir_from_file /= ndsidir )  THEN
8201                 WRITE( message_string, * ) 'ndsidir from SVF file does not ', &
8202                                            'match calculated ndsidir from ',  &
8203                                            'radiation_presimulate_solar_pos'
8204                 CALL message( 'radiation_read_svf', 'PA0494', 1, 2, 0, 6, 0 )
8205             ENDIF
8206             
8207!
8208!--          Arrays skyvf, skyvft, dsitrans and dsitransc are allready
8209!--          allocated in radiation_interaction_init and
8210!--          radiation_presimulate_solar_pos
8211             IF ( nsurfl > 0 )  THEN
8212                READ(88) skyvf
8213                READ(88) skyvft
8214                READ(88) dsitrans 
8215             ENDIF
8216             
8217             IF ( plant_canopy  .AND.  npcbl > 0 ) THEN
8218                READ ( 88 )  dsitransc
8219             ENDIF
8220             
8221!
8222!--          The allocation of svf, svfsurf, csf and csfsurf happens in routine
8223!--          radiation_calc_svf which is not called if the program enters
8224!--          radiation_read_svf. Therefore these arrays has to allocate in the
8225!--          following
8226             IF ( nsvfl > 0 )  THEN
8227                ALLOCATE( svf(ndsvf,nsvfl) )
8228                ALLOCATE( svfsurf(idsvf,nsvfl) )
8229                READ(88) svf
8230                READ(88) svfsurf
8231             ENDIF
8232
8233             IF ( plant_canopy  .AND.  ncsfl > 0 )  THEN
8234                ALLOCATE( csf(ndcsf,ncsfl) )
8235                ALLOCATE( csfsurf(idcsf,ncsfl) )
8236                READ(88) csf
8237                READ(88) csfsurf
8238             ENDIF
8239             
8240!
8241!--          Close binary file                 
8242             CALL close_file( 88 )
8243               
8244          ENDIF
8245#if defined( __parallel )
8246          CALL MPI_BARRIER( comm2d, ierr )
8247#endif
8248       ENDDO
8249
8250    END SUBROUTINE radiation_read_svf
8251
8252
8253!------------------------------------------------------------------------------!
8254!
8255! Description:
8256! ------------
8257!> Subroutine stores svf, svfsurf, csf and csfsurf data to a file.
8258!------------------------------------------------------------------------------!
8259    SUBROUTINE radiation_write_svf
8260
8261       IMPLICIT NONE
8262       
8263       INTEGER(iwp)        :: i
8264
8265       DO  i = 0, io_blocks-1
8266          IF ( i == io_group )  THEN
8267!
8268!--          Open binary file
8269             CALL check_open( 89 )
8270
8271             WRITE ( 89 )  rad_version
8272             WRITE ( 89 )  nsvfl, ncsfl, nsurfl, npcbl, ndsidir
8273             IF ( nsurfl > 0 ) THEN
8274                WRITE ( 89 )  skyvf
8275                WRITE ( 89 )  skyvft
8276                WRITE ( 89 )  dsitrans
8277             ENDIF
8278             IF ( npcbl > 0 ) THEN
8279                WRITE ( 89 )  dsitransc
8280             ENDIF
8281             IF ( nsvfl > 0 ) THEN
8282                WRITE ( 89 )  svf
8283                WRITE ( 89 )  svfsurf
8284             ENDIF
8285             IF ( plant_canopy  .AND.  ncsfl > 0 )  THEN
8286                 WRITE ( 89 )  csf
8287                 WRITE ( 89 )  csfsurf
8288             ENDIF
8289
8290!
8291!--          Close binary file                 
8292             CALL close_file( 89 )
8293
8294          ENDIF
8295#if defined( __parallel )
8296          CALL MPI_BARRIER( comm2d, ierr )
8297#endif
8298       ENDDO
8299    END SUBROUTINE radiation_write_svf
8300
8301!------------------------------------------------------------------------------!
8302!
8303! Description:
8304! ------------
8305!> Block of auxiliary subroutines:
8306!> 1. quicksort and corresponding comparison
8307!> 2. merge_and_grow_csf for implementation of "dynamical growing"
8308!>    array for csf
8309!------------------------------------------------------------------------------!
8310!-- quicksort.f -*-f90-*-
8311!-- Author: t-nissie, adaptation J.Resler
8312!-- License: GPLv3
8313!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8314    RECURSIVE SUBROUTINE quicksort_itarget(itarget, vffrac, ztransp, first, last)
8315        IMPLICIT NONE
8316        INTEGER(iwp), DIMENSION(:), INTENT(INOUT)   :: itarget
8317        REAL(wp), DIMENSION(:), INTENT(INOUT)       :: vffrac, ztransp
8318        INTEGER(iwp), INTENT(IN)                    :: first, last
8319        INTEGER(iwp)                                :: x, t
8320        INTEGER(iwp)                                :: i, j
8321        REAL(wp)                                    :: tr
8322
8323        IF ( first>=last ) RETURN
8324        x = itarget((first+last)/2)
8325        i = first
8326        j = last
8327        DO
8328            DO WHILE ( itarget(i) < x )
8329               i=i+1
8330            ENDDO
8331            DO WHILE ( x < itarget(j) )
8332                j=j-1
8333            ENDDO
8334            IF ( i >= j ) EXIT
8335            t = itarget(i);  itarget(i) = itarget(j);  itarget(j) = t
8336            tr = vffrac(i);  vffrac(i) = vffrac(j);  vffrac(j) = tr
8337            tr = ztransp(i);  ztransp(i) = ztransp(j);  ztransp(j) = tr
8338            i=i+1
8339            j=j-1
8340        ENDDO
8341        IF ( first < i-1 ) CALL quicksort_itarget(itarget, vffrac, ztransp, first, i-1)
8342        IF ( j+1 < last )  CALL quicksort_itarget(itarget, vffrac, ztransp, j+1, last)
8343    END SUBROUTINE quicksort_itarget
8344
8345    PURE FUNCTION svf_lt(svf1,svf2) result (res)
8346      TYPE (t_svf), INTENT(in) :: svf1,svf2
8347      LOGICAL                  :: res
8348      IF ( svf1%isurflt < svf2%isurflt  .OR.    &
8349          (svf1%isurflt == svf2%isurflt  .AND.  svf1%isurfs < svf2%isurfs) )  THEN
8350          res = .TRUE.
8351      ELSE
8352          res = .FALSE.
8353      ENDIF
8354    END FUNCTION svf_lt
8355
8356
8357!-- quicksort.f -*-f90-*-
8358!-- Author: t-nissie, adaptation J.Resler
8359!-- License: GPLv3
8360!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8361    RECURSIVE SUBROUTINE quicksort_svf(svfl, first, last)
8362        IMPLICIT NONE
8363        TYPE(t_svf), DIMENSION(:), INTENT(INOUT)  :: svfl
8364        INTEGER(iwp), INTENT(IN)                  :: first, last
8365        TYPE(t_svf)                               :: x, t
8366        INTEGER(iwp)                              :: i, j
8367
8368        IF ( first>=last ) RETURN
8369        x = svfl( (first+last) / 2 )
8370        i = first
8371        j = last
8372        DO
8373            DO while ( svf_lt(svfl(i),x) )
8374               i=i+1
8375            ENDDO
8376            DO while ( svf_lt(x,svfl(j)) )
8377                j=j-1
8378            ENDDO
8379            IF ( i >= j ) EXIT
8380            t = svfl(i);  svfl(i) = svfl(j);  svfl(j) = t
8381            i=i+1
8382            j=j-1
8383        ENDDO
8384        IF ( first < i-1 ) CALL quicksort_svf(svfl, first, i-1)
8385        IF ( j+1 < last )  CALL quicksort_svf(svfl, j+1, last)
8386    END SUBROUTINE quicksort_svf
8387
8388    PURE FUNCTION csf_lt(csf1,csf2) result (res)
8389      TYPE (t_csf), INTENT(in) :: csf1,csf2
8390      LOGICAL                  :: res
8391      IF ( csf1%ip < csf2%ip  .OR.    &
8392           (csf1%ip == csf2%ip  .AND.  csf1%itx < csf2%itx)  .OR.  &
8393           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity < csf2%ity)  .OR.  &
8394           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity == csf2%ity  .AND.   &
8395            csf1%itz < csf2%itz)  .OR.  &
8396           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity == csf2%ity  .AND.   &
8397            csf1%itz == csf2%itz  .AND.  csf1%isurfs < csf2%isurfs) )  THEN
8398          res = .TRUE.
8399      ELSE
8400          res = .FALSE.
8401      ENDIF
8402    END FUNCTION csf_lt
8403
8404
8405!-- quicksort.f -*-f90-*-
8406!-- Author: t-nissie, adaptation J.Resler
8407!-- License: GPLv3
8408!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8409    RECURSIVE SUBROUTINE quicksort_csf(csfl, first, last)
8410        IMPLICIT NONE
8411        TYPE(t_csf), DIMENSION(:), INTENT(INOUT)  :: csfl
8412        INTEGER(iwp), INTENT(IN)                  :: first, last
8413        TYPE(t_csf)                               :: x, t
8414        INTEGER(iwp)                              :: i, j
8415
8416        IF ( first>=last ) RETURN
8417        x = csfl( (first+last)/2 )
8418        i = first
8419        j = last
8420        DO
8421            DO while ( csf_lt(csfl(i),x) )
8422                i=i+1
8423            ENDDO
8424            DO while ( csf_lt(x,csfl(j)) )
8425                j=j-1
8426            ENDDO
8427            IF ( i >= j ) EXIT
8428            t = csfl(i);  csfl(i) = csfl(j);  csfl(j) = t
8429            i=i+1
8430            j=j-1
8431        ENDDO
8432        IF ( first < i-1 ) CALL quicksort_csf(csfl, first, i-1)
8433        IF ( j+1 < last )  CALL quicksort_csf(csfl, j+1, last)
8434    END SUBROUTINE quicksort_csf
8435
8436   
8437    SUBROUTINE merge_and_grow_csf(newsize)
8438        INTEGER(iwp), INTENT(in)                :: newsize  !< new array size after grow, must be >= ncsfl
8439                                                            !< or -1 to shrink to minimum
8440        INTEGER(iwp)                            :: iread, iwrite
8441        TYPE(t_csf), DIMENSION(:), POINTER      :: acsfnew
8442        CHARACTER(100)                          :: msg
8443
8444        IF ( newsize == -1 )  THEN
8445!--         merge in-place
8446            acsfnew => acsf
8447        ELSE
8448!--         allocate new array
8449            IF ( mcsf == 0 )  THEN
8450                ALLOCATE( acsf1(newsize) )
8451                acsfnew => acsf1
8452            ELSE
8453                ALLOCATE( acsf2(newsize) )
8454                acsfnew => acsf2
8455            ENDIF
8456        ENDIF
8457
8458        IF ( ncsfl >= 1 )  THEN
8459!--         sort csf in place (quicksort)
8460            CALL quicksort_csf(acsf,1,ncsfl)
8461
8462!--         while moving to a new array, aggregate canopy sink factor records with identical box & source
8463            acsfnew(1) = acsf(1)
8464            iwrite = 1
8465            DO iread = 2, ncsfl
8466!--             here acsf(kcsf) already has values from acsf(icsf)
8467                IF ( acsfnew(iwrite)%itx == acsf(iread)%itx &
8468                         .AND.  acsfnew(iwrite)%ity == acsf(iread)%ity &
8469                         .AND.  acsfnew(iwrite)%itz == acsf(iread)%itz &
8470                         .AND.  acsfnew(iwrite)%isurfs == acsf(iread)%isurfs )  THEN
8471
8472                    acsfnew(iwrite)%rcvf = acsfnew(iwrite)%rcvf + acsf(iread)%rcvf
8473!--                 advance reading index, keep writing index
8474                ELSE
8475!--                 not identical, just advance and copy
8476                    iwrite = iwrite + 1
8477                    acsfnew(iwrite) = acsf(iread)
8478                ENDIF
8479            ENDDO
8480            ncsfl = iwrite
8481        ENDIF
8482
8483        IF ( newsize == -1 )  THEN
8484!--         allocate new array and copy shrinked data
8485            IF ( mcsf == 0 )  THEN
8486                ALLOCATE( acsf1(ncsfl) )
8487                acsf1(1:ncsfl) = acsf2(1:ncsfl)
8488            ELSE
8489                ALLOCATE( acsf2(ncsfl) )
8490                acsf2(1:ncsfl) = acsf1(1:ncsfl)
8491            ENDIF
8492        ENDIF
8493
8494!--     deallocate old array
8495        IF ( mcsf == 0 )  THEN
8496            mcsf = 1
8497            acsf => acsf1
8498            DEALLOCATE( acsf2 )
8499        ELSE
8500            mcsf = 0
8501            acsf => acsf2
8502            DEALLOCATE( acsf1 )
8503        ENDIF
8504        ncsfla = newsize
8505
8506        WRITE(msg,'(A,2I12)') 'Grow acsf2:',ncsfl,ncsfla
8507        CALL radiation_write_debug_log( msg )
8508
8509    END SUBROUTINE merge_and_grow_csf
8510
8511   
8512!-- quicksort.f -*-f90-*-
8513!-- Author: t-nissie, adaptation J.Resler
8514!-- License: GPLv3
8515!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8516    RECURSIVE SUBROUTINE quicksort_csf2(kpcsflt, pcsflt, first, last)
8517        IMPLICIT NONE
8518        INTEGER(iwp), DIMENSION(:,:), INTENT(INOUT)  :: kpcsflt
8519        REAL(wp), DIMENSION(:,:), INTENT(INOUT)      :: pcsflt
8520        INTEGER(iwp), INTENT(IN)                     :: first, last
8521        REAL(wp), DIMENSION(ndcsf)                   :: t2
8522        INTEGER(iwp), DIMENSION(kdcsf)               :: x, t1
8523        INTEGER(iwp)                                 :: i, j
8524
8525        IF ( first>=last ) RETURN
8526        x = kpcsflt(:, (first+last)/2 )
8527        i = first
8528        j = last
8529        DO
8530            DO while ( csf_lt2(kpcsflt(:,i),x) )
8531                i=i+1
8532            ENDDO
8533            DO while ( csf_lt2(x,kpcsflt(:,j)) )
8534                j=j-1
8535            ENDDO
8536            IF ( i >= j ) EXIT
8537            t1 = kpcsflt(:,i);  kpcsflt(:,i) = kpcsflt(:,j);  kpcsflt(:,j) = t1
8538            t2 = pcsflt(:,i);  pcsflt(:,i) = pcsflt(:,j);  pcsflt(:,j) = t2
8539            i=i+1
8540            j=j-1
8541        ENDDO
8542        IF ( first < i-1 ) CALL quicksort_csf2(kpcsflt, pcsflt, first, i-1)
8543        IF ( j+1 < last )  CALL quicksort_csf2(kpcsflt, pcsflt, j+1, last)
8544    END SUBROUTINE quicksort_csf2
8545   
8546
8547    PURE FUNCTION csf_lt2(item1, item2) result(res)
8548        INTEGER(iwp), DIMENSION(kdcsf), INTENT(in)  :: item1, item2
8549        LOGICAL                                     :: res
8550        res = ( (item1(3) < item2(3))                                                        &
8551             .OR.  (item1(3) == item2(3)  .AND.  item1(2) < item2(2))                            &
8552             .OR.  (item1(3) == item2(3)  .AND.  item1(2) == item2(2)  .AND.  item1(1) < item2(1)) &
8553             .OR.  (item1(3) == item2(3)  .AND.  item1(2) == item2(2)  .AND.  item1(1) == item2(1) &
8554                 .AND.  item1(4) < item2(4)) )
8555    END FUNCTION csf_lt2
8556
8557    PURE FUNCTION searchsorted(athresh, val) result(ind)
8558        REAL(wp), DIMENSION(:), INTENT(IN)  :: athresh
8559        REAL(wp), INTENT(IN)                :: val
8560        INTEGER(iwp)                        :: ind
8561        INTEGER(iwp)                        :: i
8562
8563        DO i = LBOUND(athresh, 1), UBOUND(athresh, 1)
8564            IF ( val < athresh(i) ) THEN
8565                ind = i - 1
8566                RETURN
8567            ENDIF
8568        ENDDO
8569        ind = UBOUND(athresh, 1)
8570    END FUNCTION searchsorted
8571
8572!------------------------------------------------------------------------------!
8573! Description:
8574! ------------
8575!
8576!> radiation_radflux_gridbox subroutine gives the sw and lw radiation fluxes at the
8577!> faces of a gridbox defined at i,j,k and located in the urban layer.
8578!> The total sw and the diffuse sw radiation as well as the lw radiation fluxes at
8579!> the gridbox 6 faces are stored in sw_gridbox, swd_gridbox, and lw_gridbox arrays,
8580!> respectively, in the following order:
8581!>  up_face, down_face, north_face, south_face, east_face, west_face
8582!>
8583!> The subroutine reports also how successful was the search process via the parameter
8584!> i_feedback as follow:
8585!> - i_feedback =  1 : successful
8586!> - i_feedback = -1 : unsuccessful; the requisted point is outside the urban domain
8587!> - i_feedback =  0 : uncomplete; some gridbox faces fluxes are missing
8588!>
8589!>
8590!> It is called outside from usm_urban_surface_mod whenever the radiation fluxes
8591!> are needed.
8592!>
8593!> This routine is not used so far. However, it may serve as an interface for radiation
8594!> fluxes of urban and land surfaces
8595!>
8596!> TODO:
8597!>    - Compare performance when using some combination of the Fortran intrinsic
8598!>      functions, e.g. MINLOC, MAXLOC, ALL, ANY and COUNT functions, which search
8599!>      surfl array for elements meeting user-specified criterion, i.e. i,j,k
8600!>    - Report non-found or incomplete radiation fluxes arrays , if any, at the
8601!>      gridbox faces in an error message form
8602!>
8603!------------------------------------------------------------------------------!
8604    SUBROUTINE radiation_radflux_gridbox(i,j,k,sw_gridbox,swd_gridbox,lw_gridbox,i_feedback)
8605       
8606        IMPLICIT NONE
8607
8608        INTEGER(iwp),                 INTENT(in)  :: i,j,k                 !< gridbox indices at which fluxes are required
8609        INTEGER(iwp)                              :: ii,jj,kk,d            !< surface indices and type
8610        INTEGER(iwp)                              :: l                     !< surface id
8611        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
8612        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
8613        INTEGER(iwp),                 INTENT(out) :: i_feedback            !< feedback to report how the search was successful
8614
8615
8616!-- initialize variables
8617        i_feedback  = -999999
8618        sw_gridbox  = -999999.9_wp
8619        lw_gridbox  = -999999.9_wp
8620        swd_gridbox = -999999.9_wp
8621       
8622!-- check the requisted grid indices
8623        IF ( k < nzb   .OR.  k > nzut  .OR.   &
8624             j < nysg  .OR.  j > nyng  .OR.   &
8625             i < nxlg  .OR.  i > nxrg         &
8626             ) THEN
8627           i_feedback = -1
8628           RETURN
8629        ENDIF
8630
8631!-- search for the required grid and formulate the fluxes at the 6 gridbox faces
8632        DO l = 1, nsurfl
8633            ii = surfl(ix,l)
8634            jj = surfl(iy,l)
8635            kk = surfl(iz,l)
8636
8637            IF ( ii == i  .AND.  jj == j  .AND.  kk == k ) THEN
8638               d = surfl(id,l)
8639
8640               SELECT CASE ( d )
8641
8642               CASE (iup_u,iup_l)                          !- gridbox up_facing face
8643                  sw_gridbox(1) = surfinsw(l)
8644                  lw_gridbox(1) = surfinlw(l)
8645                  swd_gridbox(1) = surfinswdif(l)
8646
8647               CASE (inorth_u,inorth_l)                    !- gridbox north_facing face
8648                  sw_gridbox(3) = surfinsw(l)
8649                  lw_gridbox(3) = surfinlw(l)
8650                  swd_gridbox(3) = surfinswdif(l)
8651
8652               CASE (isouth_u,isouth_l)                    !- gridbox south_facing face
8653                  sw_gridbox(4) = surfinsw(l)
8654                  lw_gridbox(4) = surfinlw(l)
8655                  swd_gridbox(4) = surfinswdif(l)
8656
8657               CASE (ieast_u,ieast_l)                      !- gridbox east_facing face
8658                  sw_gridbox(5) = surfinsw(l)
8659                  lw_gridbox(5) = surfinlw(l)
8660                  swd_gridbox(5) = surfinswdif(l)
8661
8662               CASE (iwest_u,iwest_l)                      !- gridbox west_facing face
8663                  sw_gridbox(6) = surfinsw(l)
8664                  lw_gridbox(6) = surfinlw(l)
8665                  swd_gridbox(6) = surfinswdif(l)
8666
8667               END SELECT
8668
8669            ENDIF
8670
8671        IF ( ALL( sw_gridbox(:)  /= -999999.9_wp )  ) EXIT
8672        ENDDO
8673
8674!-- check the completeness of the fluxes at all gidbox faces       
8675!-- TODO: report non-found or incomplete rad fluxes arrays in an error message form
8676        IF ( ANY( sw_gridbox(:)  <= -999999.9_wp )  .OR.   &
8677             ANY( swd_gridbox(:) <= -999999.9_wp )  .OR.   &
8678             ANY( lw_gridbox(:)  <= -999999.9_wp ) ) THEN
8679           i_feedback = 0
8680        ELSE
8681           i_feedback = 1
8682        ENDIF
8683       
8684        RETURN
8685       
8686    END SUBROUTINE radiation_radflux_gridbox
8687
8688!------------------------------------------------------------------------------!
8689!
8690! Description:
8691! ------------
8692!> Subroutine for averaging 3D data
8693!------------------------------------------------------------------------------!
8694SUBROUTINE radiation_3d_data_averaging( mode, variable )
8695 
8696
8697    USE control_parameters
8698
8699    USE indices
8700
8701    USE kinds
8702
8703    IMPLICIT NONE
8704
8705    CHARACTER (LEN=*) ::  mode    !<
8706    CHARACTER (LEN=*) :: variable !<
8707
8708    LOGICAL      ::  match_lsm !< flag indicating natural-type surface
8709    LOGICAL      ::  match_usm !< flag indicating urban-type surface
8710   
8711    INTEGER(iwp) ::  i !<
8712    INTEGER(iwp) ::  j !<
8713    INTEGER(iwp) ::  k !<
8714    INTEGER(iwp) ::  l, m !< index of current surface element
8715
8716    INTEGER(iwp)                                       :: ids, idsint_u, idsint_l, isurf
8717    CHARACTER(LEN=varnamelength)                       :: var
8718
8719!-- find the real name of the variable
8720    ids = -1
8721    l = -1
8722    var = TRIM(variable)
8723    DO i = 0, nd-1
8724        k = len(TRIM(var))
8725        j = len(TRIM(dirname(i)))
8726        IF ( TRIM(var(k-j+1:k)) == TRIM(dirname(i)) )  THEN
8727            ids = i
8728            idsint_u = dirint_u(ids)
8729            idsint_l = dirint_l(ids)
8730            var = var(:k-j)
8731            EXIT
8732        ENDIF
8733    ENDDO
8734    IF ( ids == -1 )  THEN
8735        var = TRIM(variable)
8736    ENDIF
8737
8738    IF ( mode == 'allocate' )  THEN
8739
8740       SELECT CASE ( TRIM( var ) )
8741!--          block of large scale (e.g. RRTMG) radiation output variables
8742             CASE ( 'rad_net*' )
8743                IF ( .NOT. ALLOCATED( rad_net_av ) )  THEN
8744                   ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
8745                ENDIF
8746                rad_net_av = 0.0_wp
8747             
8748             CASE ( 'rad_lw_in*' )
8749                IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) )  THEN
8750                   ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
8751                ENDIF
8752                rad_lw_in_xy_av = 0.0_wp
8753               
8754             CASE ( 'rad_lw_out*' )
8755                IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) )  THEN
8756                   ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
8757                ENDIF
8758                rad_lw_out_xy_av = 0.0_wp
8759               
8760             CASE ( 'rad_sw_in*' )
8761                IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) )  THEN
8762                   ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
8763                ENDIF
8764                rad_sw_in_xy_av = 0.0_wp
8765               
8766             CASE ( 'rad_sw_out*' )
8767                IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) )  THEN
8768                   ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
8769                ENDIF
8770                rad_sw_out_xy_av = 0.0_wp               
8771
8772             CASE ( 'rad_lw_in' )
8773                IF ( .NOT. ALLOCATED( rad_lw_in_av ) )  THEN
8774                   ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8775                ENDIF
8776                rad_lw_in_av = 0.0_wp
8777
8778             CASE ( 'rad_lw_out' )
8779                IF ( .NOT. ALLOCATED( rad_lw_out_av ) )  THEN
8780                   ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8781                ENDIF
8782                rad_lw_out_av = 0.0_wp
8783
8784             CASE ( 'rad_lw_cs_hr' )
8785                IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) )  THEN
8786                   ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8787                ENDIF
8788                rad_lw_cs_hr_av = 0.0_wp
8789
8790             CASE ( 'rad_lw_hr' )
8791                IF ( .NOT. ALLOCATED( rad_lw_hr_av ) )  THEN
8792                   ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8793                ENDIF
8794                rad_lw_hr_av = 0.0_wp
8795
8796             CASE ( 'rad_sw_in' )
8797                IF ( .NOT. ALLOCATED( rad_sw_in_av ) )  THEN
8798                   ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8799                ENDIF
8800                rad_sw_in_av = 0.0_wp
8801
8802             CASE ( 'rad_sw_out' )
8803                IF ( .NOT. ALLOCATED( rad_sw_out_av ) )  THEN
8804                   ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8805                ENDIF
8806                rad_sw_out_av = 0.0_wp
8807
8808             CASE ( 'rad_sw_cs_hr' )
8809                IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) )  THEN
8810                   ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8811                ENDIF
8812                rad_sw_cs_hr_av = 0.0_wp
8813
8814             CASE ( 'rad_sw_hr' )
8815                IF ( .NOT. ALLOCATED( rad_sw_hr_av ) )  THEN
8816                   ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8817                ENDIF
8818                rad_sw_hr_av = 0.0_wp
8819
8820!--          block of RTM output variables
8821             CASE ( 'rtm_rad_net' )
8822!--              array of complete radiation balance
8823                 IF ( .NOT.  ALLOCATED(surfradnet_av) )  THEN
8824                     ALLOCATE( surfradnet_av(nsurfl) )
8825                     surfradnet_av = 0.0_wp
8826                 ENDIF
8827
8828             CASE ( 'rtm_rad_insw' )
8829!--                 array of sw radiation falling to surface after i-th reflection
8830                 IF ( .NOT.  ALLOCATED(surfinsw_av) )  THEN
8831                     ALLOCATE( surfinsw_av(nsurfl) )
8832                     surfinsw_av = 0.0_wp
8833                 ENDIF
8834
8835             CASE ( 'rtm_rad_inlw' )
8836!--                 array of lw radiation falling to surface after i-th reflection
8837                 IF ( .NOT.  ALLOCATED(surfinlw_av) )  THEN
8838                     ALLOCATE( surfinlw_av(nsurfl) )
8839                     surfinlw_av = 0.0_wp
8840                 ENDIF
8841
8842             CASE ( 'rtm_rad_inswdir' )
8843!--                 array of direct sw radiation falling to surface from sun
8844                 IF ( .NOT.  ALLOCATED(surfinswdir_av) )  THEN
8845                     ALLOCATE( surfinswdir_av(nsurfl) )
8846                     surfinswdir_av = 0.0_wp
8847                 ENDIF
8848
8849             CASE ( 'rtm_rad_inswdif' )
8850!--                 array of difusion sw radiation falling to surface from sky and borders of the domain
8851                 IF ( .NOT.  ALLOCATED(surfinswdif_av) )  THEN
8852                     ALLOCATE( surfinswdif_av(nsurfl) )
8853                     surfinswdif_av = 0.0_wp
8854                 ENDIF
8855
8856             CASE ( 'rtm_rad_inswref' )
8857!--                 array of sw radiation falling to surface from reflections
8858                 IF ( .NOT.  ALLOCATED(surfinswref_av) )  THEN
8859                     ALLOCATE( surfinswref_av(nsurfl) )
8860                     surfinswref_av = 0.0_wp
8861                 ENDIF
8862
8863             CASE ( 'rtm_rad_inlwdif' )
8864!--                 array of sw radiation falling to surface after i-th reflection
8865                IF ( .NOT.  ALLOCATED(surfinlwdif_av) )  THEN
8866                     ALLOCATE( surfinlwdif_av(nsurfl) )
8867                     surfinlwdif_av = 0.0_wp
8868                 ENDIF
8869
8870             CASE ( 'rtm_rad_inlwref' )
8871!--                 array of lw radiation falling to surface from reflections
8872                 IF ( .NOT.  ALLOCATED(surfinlwref_av) )  THEN
8873                     ALLOCATE( surfinlwref_av(nsurfl) )
8874                     surfinlwref_av = 0.0_wp
8875                 ENDIF
8876
8877             CASE ( 'rtm_rad_outsw' )
8878!--                 array of sw radiation emitted from surface after i-th reflection
8879                 IF ( .NOT.  ALLOCATED(surfoutsw_av) )  THEN
8880                     ALLOCATE( surfoutsw_av(nsurfl) )
8881                     surfoutsw_av = 0.0_wp
8882                 ENDIF
8883
8884             CASE ( 'rtm_rad_outlw' )
8885!--                 array of lw radiation emitted from surface after i-th reflection
8886                 IF ( .NOT.  ALLOCATED(surfoutlw_av) )  THEN
8887                     ALLOCATE( surfoutlw_av(nsurfl) )
8888                     surfoutlw_av = 0.0_wp
8889                 ENDIF
8890             CASE ( 'rtm_rad_ressw' )
8891!--                 array of residua of sw radiation absorbed in surface after last reflection
8892                 IF ( .NOT.  ALLOCATED(surfins_av) )  THEN
8893                     ALLOCATE( surfins_av(nsurfl) )
8894                     surfins_av = 0.0_wp
8895                 ENDIF
8896
8897             CASE ( 'rtm_rad_reslw' )
8898!--                 array of residua of lw radiation absorbed in surface after last reflection
8899                 IF ( .NOT.  ALLOCATED(surfinl_av) )  THEN
8900                     ALLOCATE( surfinl_av(nsurfl) )
8901                     surfinl_av = 0.0_wp
8902                 ENDIF
8903
8904             CASE ( 'rtm_rad_pc_inlw' )
8905!--                 array of of lw radiation absorbed in plant canopy
8906                 IF ( .NOT.  ALLOCATED(pcbinlw_av) )  THEN
8907                     ALLOCATE( pcbinlw_av(1:npcbl) )
8908                     pcbinlw_av = 0.0_wp
8909                 ENDIF
8910
8911             CASE ( 'rtm_rad_pc_insw' )
8912!--                 array of of sw radiation absorbed in plant canopy
8913                 IF ( .NOT.  ALLOCATED(pcbinsw_av) )  THEN
8914                     ALLOCATE( pcbinsw_av(1:npcbl) )
8915                     pcbinsw_av = 0.0_wp
8916                 ENDIF
8917
8918             CASE ( 'rtm_rad_pc_inswdir' )
8919!--                 array of of direct sw radiation absorbed in plant canopy
8920                 IF ( .NOT.  ALLOCATED(pcbinswdir_av) )  THEN
8921                     ALLOCATE( pcbinswdir_av(1:npcbl) )
8922                     pcbinswdir_av = 0.0_wp
8923                 ENDIF
8924
8925             CASE ( 'rtm_rad_pc_inswdif' )
8926!--                 array of of diffuse sw radiation absorbed in plant canopy
8927                 IF ( .NOT.  ALLOCATED(pcbinswdif_av) )  THEN
8928                     ALLOCATE( pcbinswdif_av(1:npcbl) )
8929                     pcbinswdif_av = 0.0_wp
8930                 ENDIF
8931
8932             CASE ( 'rtm_rad_pc_inswref' )
8933!--                 array of of reflected sw radiation absorbed in plant canopy
8934                 IF ( .NOT.  ALLOCATED(pcbinswref_av) )  THEN
8935                     ALLOCATE( pcbinswref_av(1:npcbl) )
8936                     pcbinswref_av = 0.0_wp
8937                 ENDIF
8938
8939             CASE ( 'rtm_mrt_sw' )
8940                IF ( .NOT. ALLOCATED( mrtinsw_av ) )  THEN
8941                   ALLOCATE( mrtinsw_av(nmrtbl) )
8942                ENDIF
8943                mrtinsw_av = 0.0_wp
8944
8945             CASE ( 'rtm_mrt_lw' )
8946                IF ( .NOT. ALLOCATED( mrtinlw_av ) )  THEN
8947                   ALLOCATE( mrtinlw_av(nmrtbl) )
8948                ENDIF
8949                mrtinlw_av = 0.0_wp
8950
8951             CASE ( 'rtm_mrt' )
8952                IF ( .NOT. ALLOCATED( mrt_av ) )  THEN
8953                   ALLOCATE( mrt_av(nmrtbl) )
8954                ENDIF
8955                mrt_av = 0.0_wp
8956
8957          CASE DEFAULT
8958             CONTINUE
8959
8960       END SELECT
8961
8962    ELSEIF ( mode == 'sum' )  THEN
8963
8964       SELECT CASE ( TRIM( var ) )
8965!--       block of large scale (e.g. RRTMG) radiation output variables
8966          CASE ( 'rad_net*' )
8967             IF ( ALLOCATED( rad_net_av ) ) THEN
8968                DO  i = nxl, nxr
8969                   DO  j = nys, nyn
8970                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
8971                                  surf_lsm_h%end_index(j,i)
8972                      match_usm = surf_usm_h%start_index(j,i) <=               &
8973                                  surf_usm_h%end_index(j,i)
8974
8975                     IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
8976                         m = surf_lsm_h%end_index(j,i)
8977                         rad_net_av(j,i) = rad_net_av(j,i) +                   &
8978                                         surf_lsm_h%rad_net(m)
8979                      ELSEIF ( match_usm )  THEN
8980                         m = surf_usm_h%end_index(j,i)
8981                         rad_net_av(j,i) = rad_net_av(j,i) +                   &
8982                                         surf_usm_h%rad_net(m)
8983                      ENDIF
8984                   ENDDO
8985                ENDDO
8986             ENDIF
8987
8988          CASE ( 'rad_lw_in*' )
8989             IF ( ALLOCATED( rad_lw_in_xy_av ) ) THEN
8990                DO  i = nxl, nxr
8991                   DO  j = nys, nyn
8992                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
8993                                  surf_lsm_h%end_index(j,i)
8994                      match_usm = surf_usm_h%start_index(j,i) <=               &
8995                                  surf_usm_h%end_index(j,i)
8996
8997                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
8998                         m = surf_lsm_h%end_index(j,i)
8999                         rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i) +         &
9000                                         surf_lsm_h%rad_lw_in(m)
9001                      ELSEIF ( match_usm )  THEN
9002                         m = surf_usm_h%end_index(j,i)
9003                         rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i) +         &
9004                                         surf_usm_h%rad_lw_in(m)
9005                      ENDIF
9006                   ENDDO
9007                ENDDO
9008             ENDIF
9009             
9010          CASE ( 'rad_lw_out*' )
9011             IF ( ALLOCATED( rad_lw_out_xy_av ) ) THEN
9012                DO  i = nxl, nxr
9013                   DO  j = nys, nyn
9014                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9015                                  surf_lsm_h%end_index(j,i)
9016                      match_usm = surf_usm_h%start_index(j,i) <=               &
9017                                  surf_usm_h%end_index(j,i)
9018
9019                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9020                         m = surf_lsm_h%end_index(j,i)
9021                         rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i) +       &
9022                                                 surf_lsm_h%rad_lw_out(m)
9023                      ELSEIF ( match_usm )  THEN
9024                         m = surf_usm_h%end_index(j,i)
9025                         rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i) +       &
9026                                                 surf_usm_h%rad_lw_out(m)
9027                      ENDIF
9028                   ENDDO
9029                ENDDO
9030             ENDIF
9031             
9032          CASE ( 'rad_sw_in*' )
9033             IF ( ALLOCATED( rad_sw_in_xy_av ) ) THEN
9034                DO  i = nxl, nxr
9035                   DO  j = nys, nyn
9036                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9037                                  surf_lsm_h%end_index(j,i)
9038                      match_usm = surf_usm_h%start_index(j,i) <=               &
9039                                  surf_usm_h%end_index(j,i)
9040
9041                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9042                         m = surf_lsm_h%end_index(j,i)
9043                         rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i) +         &
9044                                                surf_lsm_h%rad_sw_in(m)
9045                      ELSEIF ( match_usm )  THEN
9046                         m = surf_usm_h%end_index(j,i)
9047                         rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i) +         &
9048                                                surf_usm_h%rad_sw_in(m)
9049                      ENDIF
9050                   ENDDO
9051                ENDDO
9052             ENDIF
9053             
9054          CASE ( 'rad_sw_out*' )
9055             IF ( ALLOCATED( rad_sw_out_xy_av ) ) THEN
9056                DO  i = nxl, nxr
9057                   DO  j = nys, nyn
9058                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9059                                  surf_lsm_h%end_index(j,i)
9060                      match_usm = surf_usm_h%start_index(j,i) <=               &
9061                                  surf_usm_h%end_index(j,i)
9062
9063                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9064                         m = surf_lsm_h%end_index(j,i)
9065                         rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i) +       &
9066                                                 surf_lsm_h%rad_sw_out(m)
9067                      ELSEIF ( match_usm )  THEN
9068                         m = surf_usm_h%end_index(j,i)
9069                         rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i) +       &
9070                                                 surf_usm_h%rad_sw_out(m)
9071                      ENDIF
9072                   ENDDO
9073                ENDDO
9074             ENDIF
9075             
9076          CASE ( 'rad_lw_in' )
9077             IF ( ALLOCATED( rad_lw_in_av ) ) THEN
9078                DO  i = nxlg, nxrg
9079                   DO  j = nysg, nyng
9080                      DO  k = nzb, nzt+1
9081                         rad_lw_in_av(k,j,i) = rad_lw_in_av(k,j,i)             &
9082                                               + rad_lw_in(k,j,i)
9083                      ENDDO
9084                   ENDDO
9085                ENDDO
9086             ENDIF
9087
9088          CASE ( 'rad_lw_out' )
9089             IF ( ALLOCATED( rad_lw_out_av ) ) THEN
9090                DO  i = nxlg, nxrg
9091                   DO  j = nysg, nyng
9092                      DO  k = nzb, nzt+1
9093                         rad_lw_out_av(k,j,i) = rad_lw_out_av(k,j,i)           &
9094                                                + rad_lw_out(k,j,i)
9095                      ENDDO
9096                   ENDDO
9097                ENDDO
9098             ENDIF
9099
9100          CASE ( 'rad_lw_cs_hr' )
9101             IF ( ALLOCATED( rad_lw_cs_hr_av ) ) THEN
9102                DO  i = nxlg, nxrg
9103                   DO  j = nysg, nyng
9104                      DO  k = nzb, nzt+1
9105                         rad_lw_cs_hr_av(k,j,i) = rad_lw_cs_hr_av(k,j,i)       &
9106                                                  + rad_lw_cs_hr(k,j,i)
9107                      ENDDO
9108                   ENDDO
9109                ENDDO
9110             ENDIF
9111
9112          CASE ( 'rad_lw_hr' )
9113             IF ( ALLOCATED( rad_lw_hr_av ) ) THEN
9114                DO  i = nxlg, nxrg
9115                   DO  j = nysg, nyng
9116                      DO  k = nzb, nzt+1
9117                         rad_lw_hr_av(k,j,i) = rad_lw_hr_av(k,j,i)             &
9118                                               + rad_lw_hr(k,j,i)
9119                      ENDDO
9120                   ENDDO
9121                ENDDO
9122             ENDIF
9123
9124          CASE ( 'rad_sw_in' )
9125             IF ( ALLOCATED( rad_sw_in_av ) ) THEN
9126                DO  i = nxlg, nxrg
9127                   DO  j = nysg, nyng
9128                      DO  k = nzb, nzt+1
9129                         rad_sw_in_av(k,j,i) = rad_sw_in_av(k,j,i)             &
9130                                               + rad_sw_in(k,j,i)
9131                      ENDDO
9132                   ENDDO
9133                ENDDO
9134             ENDIF
9135
9136          CASE ( 'rad_sw_out' )
9137             IF ( ALLOCATED( rad_sw_out_av ) ) THEN
9138                DO  i = nxlg, nxrg
9139                   DO  j = nysg, nyng
9140                      DO  k = nzb, nzt+1
9141                         rad_sw_out_av(k,j,i) = rad_sw_out_av(k,j,i)           &
9142                                                + rad_sw_out(k,j,i)
9143                      ENDDO
9144                   ENDDO
9145                ENDDO
9146             ENDIF
9147
9148          CASE ( 'rad_sw_cs_hr' )
9149             IF ( ALLOCATED( rad_sw_cs_hr_av ) ) THEN
9150                DO  i = nxlg, nxrg
9151                   DO  j = nysg, nyng
9152                      DO  k = nzb, nzt+1
9153                         rad_sw_cs_hr_av(k,j,i) = rad_sw_cs_hr_av(k,j,i)       &
9154                                                  + rad_sw_cs_hr(k,j,i)
9155                      ENDDO
9156                   ENDDO
9157                ENDDO
9158             ENDIF
9159
9160          CASE ( 'rad_sw_hr' )
9161             IF ( ALLOCATED( rad_sw_hr_av ) ) THEN
9162                DO  i = nxlg, nxrg
9163                   DO  j = nysg, nyng
9164                      DO  k = nzb, nzt+1
9165                         rad_sw_hr_av(k,j,i) = rad_sw_hr_av(k,j,i)             &
9166                                               + rad_sw_hr(k,j,i)
9167                      ENDDO
9168                   ENDDO
9169                ENDDO
9170             ENDIF
9171
9172!--       block of RTM output variables
9173          CASE ( 'rtm_rad_net' )
9174!--           array of complete radiation balance
9175              DO isurf = dirstart(ids), dirend(ids)
9176                 IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9177                    surfradnet_av(isurf) = surfinsw(isurf) - surfoutsw(isurf) +  surfinlw(isurf) - surfoutlw(isurf)
9178                 ENDIF
9179              ENDDO
9180
9181          CASE ( 'rtm_rad_insw' )
9182!--           array of sw radiation falling to surface after i-th reflection
9183              DO isurf = dirstart(ids), dirend(ids)
9184                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9185                      surfinsw_av(isurf) = surfinsw_av(isurf) + surfinsw(isurf)
9186                  ENDIF
9187              ENDDO
9188
9189          CASE ( 'rtm_rad_inlw' )
9190!--           array of lw radiation falling to surface after i-th reflection
9191              DO isurf = dirstart(ids), dirend(ids)
9192                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9193                      surfinlw_av(isurf) = surfinlw_av(isurf) + surfinlw(isurf)
9194                  ENDIF
9195              ENDDO
9196
9197          CASE ( 'rtm_rad_inswdir' )
9198!--           array of direct sw radiation falling to surface from sun
9199              DO isurf = dirstart(ids), dirend(ids)
9200                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9201                      surfinswdir_av(isurf) = surfinswdir_av(isurf) + surfinswdir(isurf)
9202                  ENDIF
9203              ENDDO
9204
9205          CASE ( 'rtm_rad_inswdif' )
9206!--           array of difusion sw radiation falling to surface from sky and borders of the domain
9207              DO isurf = dirstart(ids), dirend(ids)
9208                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9209                      surfinswdif_av(isurf) = surfinswdif_av(isurf) + surfinswdif(isurf)
9210                  ENDIF
9211              ENDDO
9212
9213          CASE ( 'rtm_rad_inswref' )
9214!--           array of sw radiation falling to surface from reflections
9215              DO isurf = dirstart(ids), dirend(ids)
9216                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9217                      surfinswref_av(isurf) = surfinswref_av(isurf) + surfinsw(isurf) - &
9218                                          surfinswdir(isurf) - surfinswdif(isurf)
9219                  ENDIF
9220              ENDDO
9221
9222
9223          CASE ( 'rtm_rad_inlwdif' )
9224!--           array of sw radiation falling to surface after i-th reflection
9225              DO isurf = dirstart(ids), dirend(ids)
9226                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9227                      surfinlwdif_av(isurf) = surfinlwdif_av(isurf) + surfinlwdif(isurf)
9228                  ENDIF
9229              ENDDO
9230!
9231          CASE ( 'rtm_rad_inlwref' )
9232!--           array of lw radiation falling to surface from reflections
9233              DO isurf = dirstart(ids), dirend(ids)
9234                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9235                      surfinlwref_av(isurf) = surfinlwref_av(isurf) + &
9236                                          surfinlw(isurf) - surfinlwdif(isurf)
9237                  ENDIF
9238              ENDDO
9239
9240          CASE ( 'rtm_rad_outsw' )
9241!--           array of sw radiation emitted from surface after i-th reflection
9242              DO isurf = dirstart(ids), dirend(ids)
9243                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9244                      surfoutsw_av(isurf) = surfoutsw_av(isurf) + surfoutsw(isurf)
9245                  ENDIF
9246              ENDDO
9247
9248          CASE ( 'rtm_rad_outlw' )
9249!--           array of lw radiation emitted from surface after i-th reflection
9250              DO isurf = dirstart(ids), dirend(ids)
9251                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9252                      surfoutlw_av(isurf) = surfoutlw_av(isurf) + surfoutlw(isurf)
9253                  ENDIF
9254              ENDDO
9255
9256          CASE ( 'rtm_rad_ressw' )
9257!--           array of residua of sw radiation absorbed in surface after last reflection
9258              DO isurf = dirstart(ids), dirend(ids)
9259                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9260                      surfins_av(isurf) = surfins_av(isurf) + surfins(isurf)
9261                  ENDIF
9262              ENDDO
9263
9264          CASE ( 'rtm_rad_reslw' )
9265!--           array of residua of lw radiation absorbed in surface after last reflection
9266              DO isurf = dirstart(ids), dirend(ids)
9267                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9268                      surfinl_av(isurf) = surfinl_av(isurf) + surfinl(isurf)
9269                  ENDIF
9270              ENDDO
9271
9272          CASE ( 'rtm_rad_pc_inlw' )
9273              DO l = 1, npcbl
9274                 pcbinlw_av(l) = pcbinlw_av(l) + pcbinlw(l)
9275              ENDDO
9276
9277          CASE ( 'rtm_rad_pc_insw' )
9278              DO l = 1, npcbl
9279                 pcbinsw_av(l) = pcbinsw_av(l) + pcbinsw(l)
9280              ENDDO
9281
9282          CASE ( 'rtm_rad_pc_inswdir' )
9283              DO l = 1, npcbl
9284                 pcbinswdir_av(l) = pcbinswdir_av(l) + pcbinswdir(l)
9285              ENDDO
9286
9287          CASE ( 'rtm_rad_pc_inswdif' )
9288              DO l = 1, npcbl
9289                 pcbinswdif_av(l) = pcbinswdif_av(l) + pcbinswdif(l)
9290              ENDDO
9291
9292          CASE ( 'rtm_rad_pc_inswref' )
9293              DO l = 1, npcbl
9294                 pcbinswref_av(l) = pcbinswref_av(l) + pcbinsw(l) - pcbinswdir(l) - pcbinswdif(l)
9295              ENDDO
9296
9297          CASE ( 'rad_mrt_sw' )
9298             IF ( ALLOCATED( mrtinsw_av ) )  THEN
9299                mrtinsw_av(:) = mrtinsw_av(:) + mrtinsw(:)
9300             ENDIF
9301
9302          CASE ( 'rad_mrt_lw' )
9303             IF ( ALLOCATED( mrtinlw_av ) )  THEN
9304                mrtinlw_av(:) = mrtinlw_av(:) + mrtinlw(:)
9305             ENDIF
9306
9307          CASE ( 'rad_mrt' )
9308             IF ( ALLOCATED( mrt_av ) )  THEN
9309                mrt_av(:) = mrt_av(:) + mrt(:)
9310             ENDIF
9311
9312          CASE DEFAULT
9313             CONTINUE
9314
9315       END SELECT
9316
9317    ELSEIF ( mode == 'average' )  THEN
9318
9319       SELECT CASE ( TRIM( var ) )
9320!--       block of large scale (e.g. RRTMG) radiation output variables
9321          CASE ( 'rad_net*' )
9322             IF ( ALLOCATED( rad_net_av ) ) THEN
9323                DO  i = nxlg, nxrg
9324                   DO  j = nysg, nyng
9325                      rad_net_av(j,i) = rad_net_av(j,i)                        &
9326                                        / REAL( average_count_3d, KIND=wp )
9327                   ENDDO
9328                ENDDO
9329             ENDIF
9330             
9331          CASE ( 'rad_lw_in*' )
9332             IF ( ALLOCATED( rad_lw_in_xy_av ) ) THEN
9333                DO  i = nxlg, nxrg
9334                   DO  j = nysg, nyng
9335                      rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i)              &
9336                                        / REAL( average_count_3d, KIND=wp )
9337                   ENDDO
9338                ENDDO
9339             ENDIF
9340             
9341          CASE ( 'rad_lw_out*' )
9342             IF ( ALLOCATED( rad_lw_out_xy_av ) ) THEN
9343                DO  i = nxlg, nxrg
9344                   DO  j = nysg, nyng
9345                      rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i)            &
9346                                        / REAL( average_count_3d, KIND=wp )
9347                   ENDDO
9348                ENDDO
9349             ENDIF
9350             
9351          CASE ( 'rad_sw_in*' )
9352             IF ( ALLOCATED( rad_sw_in_xy_av ) ) THEN
9353                DO  i = nxlg, nxrg
9354                   DO  j = nysg, nyng
9355                      rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i)              &
9356                                        / REAL( average_count_3d, KIND=wp )
9357                   ENDDO
9358                ENDDO
9359             ENDIF
9360             
9361          CASE ( 'rad_sw_out*' )
9362             IF ( ALLOCATED( rad_sw_out_xy_av ) ) THEN
9363                DO  i = nxlg, nxrg
9364                   DO  j = nysg, nyng
9365                      rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i)             &
9366                                        / REAL( average_count_3d, KIND=wp )
9367                   ENDDO
9368                ENDDO
9369             ENDIF
9370
9371          CASE ( 'rad_lw_in' )
9372             IF ( ALLOCATED( rad_lw_in_av ) ) THEN
9373                DO  i = nxlg, nxrg
9374                   DO  j = nysg, nyng
9375                      DO  k = nzb, nzt+1
9376                         rad_lw_in_av(k,j,i) = rad_lw_in_av(k,j,i)             &
9377                                               / REAL( average_count_3d, KIND=wp )
9378                      ENDDO
9379                   ENDDO
9380                ENDDO
9381             ENDIF
9382
9383          CASE ( 'rad_lw_out' )
9384             IF ( ALLOCATED( rad_lw_out_av ) ) THEN
9385                DO  i = nxlg, nxrg
9386                   DO  j = nysg, nyng
9387                      DO  k = nzb, nzt+1
9388                         rad_lw_out_av(k,j,i) = rad_lw_out_av(k,j,i)           &
9389                                                / REAL( average_count_3d, KIND=wp )
9390                      ENDDO
9391                   ENDDO
9392                ENDDO
9393             ENDIF
9394
9395          CASE ( 'rad_lw_cs_hr' )
9396             IF ( ALLOCATED( rad_lw_cs_hr_av ) ) THEN
9397                DO  i = nxlg, nxrg
9398                   DO  j = nysg, nyng
9399                      DO  k = nzb, nzt+1
9400                         rad_lw_cs_hr_av(k,j,i) = rad_lw_cs_hr_av(k,j,i)       &
9401                                                / REAL( average_count_3d, KIND=wp )
9402                      ENDDO
9403                   ENDDO
9404                ENDDO
9405             ENDIF
9406
9407          CASE ( 'rad_lw_hr' )
9408             IF ( ALLOCATED( rad_lw_hr_av ) ) THEN
9409                DO  i = nxlg, nxrg
9410                   DO  j = nysg, nyng
9411                      DO  k = nzb, nzt+1
9412                         rad_lw_hr_av(k,j,i) = rad_lw_hr_av(k,j,i)             &
9413                                               / REAL( average_count_3d, KIND=wp )
9414                      ENDDO
9415                   ENDDO
9416                ENDDO
9417             ENDIF
9418
9419          CASE ( 'rad_sw_in' )
9420             IF ( ALLOCATED( rad_sw_in_av ) ) THEN
9421                DO  i = nxlg, nxrg
9422                   DO  j = nysg, nyng
9423                      DO  k = nzb, nzt+1
9424                         rad_sw_in_av(k,j,i) = rad_sw_in_av(k,j,i)             &
9425                                               / REAL( average_count_3d, KIND=wp )
9426                      ENDDO
9427                   ENDDO
9428                ENDDO
9429             ENDIF
9430
9431          CASE ( 'rad_sw_out' )
9432             IF ( ALLOCATED( rad_sw_out_av ) ) THEN
9433                DO  i = nxlg, nxrg
9434                   DO  j = nysg, nyng
9435                      DO  k = nzb, nzt+1
9436                         rad_sw_out_av(k,j,i) = rad_sw_out_av(k,j,i)           &
9437                                                / REAL( average_count_3d, KIND=wp )
9438                      ENDDO
9439                   ENDDO
9440                ENDDO
9441             ENDIF
9442
9443          CASE ( 'rad_sw_cs_hr' )
9444             IF ( ALLOCATED( rad_sw_cs_hr_av ) ) THEN
9445                DO  i = nxlg, nxrg
9446                   DO  j = nysg, nyng
9447                      DO  k = nzb, nzt+1
9448                         rad_sw_cs_hr_av(k,j,i) = rad_sw_cs_hr_av(k,j,i)       &
9449                                                / REAL( average_count_3d, KIND=wp )
9450                      ENDDO
9451                   ENDDO
9452                ENDDO
9453             ENDIF
9454
9455          CASE ( 'rad_sw_hr' )
9456             IF ( ALLOCATED( rad_sw_hr_av ) ) THEN
9457                DO  i = nxlg, nxrg
9458                   DO  j = nysg, nyng
9459                      DO  k = nzb, nzt+1
9460                         rad_sw_hr_av(k,j,i) = rad_sw_hr_av(k,j,i)             &
9461                                               / REAL( average_count_3d, KIND=wp )
9462                      ENDDO
9463                   ENDDO
9464                ENDDO
9465             ENDIF
9466
9467!--       block of RTM output variables
9468          CASE ( 'rtm_rad_net' )
9469!--           array of complete radiation balance
9470              DO isurf = dirstart(ids), dirend(ids)
9471                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9472                      surfradnet_av(isurf) = surfinsw_av(isurf) / REAL( average_count_3d, kind=wp )
9473                  ENDIF
9474              ENDDO
9475
9476          CASE ( 'rtm_rad_insw' )
9477!--           array of sw radiation falling to surface after i-th reflection
9478              DO isurf = dirstart(ids), dirend(ids)
9479                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9480                      surfinsw_av(isurf) = surfinsw_av(isurf) / REAL( average_count_3d, kind=wp )
9481                  ENDIF
9482              ENDDO
9483
9484          CASE ( 'rtm_rad_inlw' )
9485!--           array of lw radiation falling to surface after i-th reflection
9486              DO isurf = dirstart(ids), dirend(ids)
9487                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9488                      surfinlw_av(isurf) = surfinlw_av(isurf) / REAL( average_count_3d, kind=wp )
9489                  ENDIF
9490              ENDDO
9491
9492          CASE ( 'rtm_rad_inswdir' )
9493!--           array of direct sw radiation falling to surface from sun
9494              DO isurf = dirstart(ids), dirend(ids)
9495                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9496                      surfinswdir_av(isurf) = surfinswdir_av(isurf) / REAL( average_count_3d, kind=wp )
9497                  ENDIF
9498              ENDDO
9499
9500          CASE ( 'rtm_rad_inswdif' )
9501!--           array of difusion sw radiation falling to surface from sky and borders of the domain
9502              DO isurf = dirstart(ids), dirend(ids)
9503                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9504                      surfinswdif_av(isurf) = surfinswdif_av(isurf) / REAL( average_count_3d, kind=wp )
9505                  ENDIF
9506              ENDDO
9507
9508          CASE ( 'rtm_rad_inswref' )
9509!--           array of sw radiation falling to surface from reflections
9510              DO isurf = dirstart(ids), dirend(ids)
9511                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9512                      surfinswref_av(isurf) = surfinswref_av(isurf) / REAL( average_count_3d, kind=wp )
9513                  ENDIF
9514              ENDDO
9515
9516          CASE ( 'rtm_rad_inlwdif' )
9517!--           array of sw radiation falling to surface after i-th reflection
9518              DO isurf = dirstart(ids), dirend(ids)
9519                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9520                      surfinlwdif_av(isurf) = surfinlwdif_av(isurf) / REAL( average_count_3d, kind=wp )
9521                  ENDIF
9522              ENDDO
9523
9524          CASE ( 'rtm_rad_inlwref' )
9525!--           array of lw radiation falling to surface from reflections
9526              DO isurf = dirstart(ids), dirend(ids)
9527                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9528                      surfinlwref_av(isurf) = surfinlwref_av(isurf) / REAL( average_count_3d, kind=wp )
9529                  ENDIF
9530              ENDDO
9531
9532          CASE ( 'rtm_rad_outsw' )
9533!--           array of sw radiation emitted from surface after i-th reflection
9534              DO isurf = dirstart(ids), dirend(ids)
9535                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9536                      surfoutsw_av(isurf) = surfoutsw_av(isurf) / REAL( average_count_3d, kind=wp )
9537                  ENDIF
9538              ENDDO
9539
9540          CASE ( 'rtm_rad_outlw' )
9541!--           array of lw radiation emitted from surface after i-th reflection
9542              DO isurf = dirstart(ids), dirend(ids)
9543                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9544                      surfoutlw_av(isurf) = surfoutlw_av(isurf) / REAL( average_count_3d, kind=wp )
9545                  ENDIF
9546              ENDDO
9547
9548          CASE ( 'rtm_rad_ressw' )
9549!--           array of residua of sw radiation absorbed in surface after last reflection
9550              DO isurf = dirstart(ids), dirend(ids)
9551                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9552                      surfins_av(isurf) = surfins_av(isurf) / REAL( average_count_3d, kind=wp )
9553                  ENDIF
9554              ENDDO
9555
9556          CASE ( 'rtm_rad_reslw' )
9557!--           array of residua of lw radiation absorbed in surface after last reflection
9558              DO isurf = dirstart(ids), dirend(ids)
9559                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9560                      surfinl_av(isurf) = surfinl_av(isurf) / REAL( average_count_3d, kind=wp )
9561                  ENDIF
9562              ENDDO
9563
9564          CASE ( 'rtm_rad_pc_inlw' )
9565              DO l = 1, npcbl
9566                 pcbinlw_av(:) = pcbinlw_av(:) / REAL( average_count_3d, kind=wp )
9567              ENDDO
9568
9569          CASE ( 'rtm_rad_pc_insw' )
9570              DO l = 1, npcbl
9571                 pcbinsw_av(:) = pcbinsw_av(:) / REAL( average_count_3d, kind=wp )
9572              ENDDO
9573
9574          CASE ( 'rtm_rad_pc_inswdir' )
9575              DO l = 1, npcbl
9576                 pcbinswdir_av(:) = pcbinswdir_av(:) / REAL( average_count_3d, kind=wp )
9577              ENDDO
9578
9579          CASE ( 'rtm_rad_pc_inswdif' )
9580              DO l = 1, npcbl
9581                 pcbinswdif_av(:) = pcbinswdif_av(:) / REAL( average_count_3d, kind=wp )
9582              ENDDO
9583
9584          CASE ( 'rtm_rad_pc_inswref' )
9585              DO l = 1, npcbl
9586                 pcbinswref_av(:) = pcbinswref_av(:) / REAL( average_count_3d, kind=wp )
9587              ENDDO
9588
9589          CASE ( 'rad_mrt_lw' )
9590             IF ( ALLOCATED( mrtinlw_av ) )  THEN
9591                mrtinlw_av(:) = mrtinlw_av(:) / REAL( average_count_3d, KIND=wp )
9592             ENDIF
9593
9594          CASE ( 'rad_mrt' )
9595             IF ( ALLOCATED( mrt_av ) )  THEN
9596                mrt_av(:) = mrt_av(:) / REAL( average_count_3d, KIND=wp )
9597             ENDIF
9598
9599       END SELECT
9600
9601    ENDIF
9602
9603END SUBROUTINE radiation_3d_data_averaging
9604
9605
9606!------------------------------------------------------------------------------!
9607!
9608! Description:
9609! ------------
9610!> Subroutine defining appropriate grid for netcdf variables.
9611!> It is called out from subroutine netcdf.
9612!------------------------------------------------------------------------------!
9613SUBROUTINE radiation_define_netcdf_grid( variable, found, grid_x, grid_y, grid_z )
9614   
9615    IMPLICIT NONE
9616
9617    CHARACTER (LEN=*), INTENT(IN)  ::  variable    !<
9618    LOGICAL, INTENT(OUT)           ::  found       !<
9619    CHARACTER (LEN=*), INTENT(OUT) ::  grid_x      !<
9620    CHARACTER (LEN=*), INTENT(OUT) ::  grid_y      !<
9621    CHARACTER (LEN=*), INTENT(OUT) ::  grid_z      !<
9622
9623    CHARACTER (len=varnamelength)  :: var
9624
9625    found  = .TRUE.
9626
9627!
9628!-- Check for the grid
9629    var = TRIM(variable)
9630!-- RTM directional variables
9631    IF ( var(1:12) == 'rtm_rad_net_'  .OR.  var(1:13) == 'rtm_rad_insw_'  .OR.          &
9632         var(1:13) == 'rtm_rad_inlw_'  .OR.  var(1:16) == 'rtm_rad_inswdir_'  .OR.      &
9633         var(1:16) == 'rtm_rad_inswdif_'  .OR.  var(1:16) == 'rtm_rad_inswref_'  .OR.   &
9634         var(1:16) == 'rtm_rad_inlwdif_'  .OR.  var(1:16) == 'rtm_rad_inlwref_'  .OR.   &
9635         var(1:14) == 'rtm_rad_outsw_'  .OR.  var(1:14) == 'rtm_rad_outlw_'  .OR.       &
9636         var(1:14) == 'rtm_rad_ressw_'  .OR.  var(1:14) == 'rtm_rad_reslw_'  .OR.       &
9637         var == 'rtm_rad_pc_inlw'  .OR.                                                 &
9638         var == 'rtm_rad_pc_insw'  .OR.  var == 'rtm_rad_pc_inswdir'  .OR.              &
9639         var == 'rtm_rad_pc_inswdif'  .OR.  var == 'rtm_rad_pc_inswref'  .OR.           &
9640         var(1:7) == 'rtm_svf'  .OR.  var(1:7) == 'rtm_dif'  .OR.                       &
9641         var(1:9) == 'rtm_skyvf' .OR. var(1:10) == 'rtm_skyvft'  .OR.                   &
9642         var == 'rtm_mrt'  .OR.  var ==  'rtm_mrt_sw'  .OR.  var == 'rtm_mrt_lw' )  THEN
9643
9644         found = .TRUE.
9645         grid_x = 'x'
9646         grid_y = 'y'
9647         grid_z = 'zu'
9648    ELSE
9649
9650       SELECT CASE ( TRIM( var ) )
9651
9652          CASE ( 'rad_lw_cs_hr', 'rad_lw_hr', 'rad_sw_cs_hr', 'rad_sw_hr',        &
9653                 'rad_lw_cs_hr_xy', 'rad_lw_hr_xy', 'rad_sw_cs_hr_xy',            &
9654                 'rad_sw_hr_xy', 'rad_lw_cs_hr_xz', 'rad_lw_hr_xz',               &
9655                 'rad_sw_cs_hr_xz', 'rad_sw_hr_xz', 'rad_lw_cs_hr_yz',            &
9656                 'rad_lw_hr_yz', 'rad_sw_cs_hr_yz', 'rad_sw_hr_yz',               &
9657                 'rad_mrt', 'rad_mrt_sw', 'rad_mrt_lw' )
9658             grid_x = 'x'
9659             grid_y = 'y'
9660             grid_z = 'zu'
9661
9662          CASE ( 'rad_lw_in', 'rad_lw_out', 'rad_sw_in', 'rad_sw_out',            &
9663                 'rad_lw_in_xy', 'rad_lw_out_xy', 'rad_sw_in_xy','rad_sw_out_xy', &
9664                 'rad_lw_in_xz', 'rad_lw_out_xz', 'rad_sw_in_xz','rad_sw_out_xz', &
9665                 'rad_lw_in_yz', 'rad_lw_out_yz', 'rad_sw_in_yz','rad_sw_out_yz' )
9666             grid_x = 'x'
9667             grid_y = 'y'
9668             grid_z = 'zw'
9669
9670
9671          CASE DEFAULT
9672             found  = .FALSE.
9673             grid_x = 'none'
9674             grid_y = 'none'
9675             grid_z = 'none'
9676
9677           END SELECT
9678       ENDIF
9679
9680    END SUBROUTINE radiation_define_netcdf_grid
9681
9682!------------------------------------------------------------------------------!
9683!
9684! Description:
9685! ------------
9686!> Subroutine defining 2D output variables
9687!------------------------------------------------------------------------------!
9688 SUBROUTINE radiation_data_output_2d( av, variable, found, grid, mode,         &
9689                                      local_pf, two_d, nzb_do, nzt_do )
9690 
9691    USE indices
9692
9693    USE kinds
9694
9695
9696    IMPLICIT NONE
9697
9698    CHARACTER (LEN=*) ::  grid     !<
9699    CHARACTER (LEN=*) ::  mode     !<
9700    CHARACTER (LEN=*) ::  variable !<
9701
9702    INTEGER(iwp) ::  av !<
9703    INTEGER(iwp) ::  i  !<
9704    INTEGER(iwp) ::  j  !<
9705    INTEGER(iwp) ::  k  !<
9706    INTEGER(iwp) ::  m  !< index of surface element at grid point (j,i)
9707    INTEGER(iwp) ::  nzb_do   !<
9708    INTEGER(iwp) ::  nzt_do   !<
9709
9710    LOGICAL      ::  found !<
9711    LOGICAL      ::  two_d !< flag parameter that indicates 2D variables (horizontal cross sections)
9712
9713    REAL(wp) ::  fill_value = -999.0_wp    !< value for the _FillValue attribute
9714
9715    REAL(wp), DIMENSION(nxl:nxr,nys:nyn,nzb_do:nzt_do) ::  local_pf !<
9716
9717    found = .TRUE.
9718
9719    SELECT CASE ( TRIM( variable ) )
9720
9721       CASE ( 'rad_net*_xy' )        ! 2d-array
9722          IF ( av == 0 ) THEN
9723             DO  i = nxl, nxr
9724                DO  j = nys, nyn
9725!
9726!--                Obtain rad_net from its respective surface type
9727!--                Natural-type surfaces
9728                   DO  m = surf_lsm_h%start_index(j,i),                        &
9729                           surf_lsm_h%end_index(j,i) 
9730                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_net(m)
9731                   ENDDO
9732!
9733!--                Urban-type surfaces
9734                   DO  m = surf_usm_h%start_index(j,i),                        &
9735                           surf_usm_h%end_index(j,i) 
9736                      local_pf(i,j,nzb+1) = surf_usm_h%rad_net(m)
9737                   ENDDO
9738                ENDDO
9739             ENDDO
9740          ELSE
9741             IF ( .NOT. ALLOCATED( rad_net_av ) ) THEN
9742                ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
9743                rad_net_av = REAL( fill_value, KIND = wp )
9744             ENDIF
9745             DO  i = nxl, nxr
9746                DO  j = nys, nyn 
9747                   local_pf(i,j,nzb+1) = rad_net_av(j,i)
9748                ENDDO
9749             ENDDO
9750          ENDIF
9751          two_d = .TRUE.
9752          grid = 'zu1'
9753         
9754       CASE ( 'rad_lw_in*_xy' )        ! 2d-array
9755          IF ( av == 0 ) THEN
9756             DO  i = nxl, nxr
9757                DO  j = nys, nyn
9758!
9759!--                Obtain rad_net from its respective surface type
9760!--                Natural-type surfaces
9761                   DO  m = surf_lsm_h%start_index(j,i),                        &
9762                           surf_lsm_h%end_index(j,i) 
9763                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_lw_in(m)
9764                   ENDDO
9765!
9766!--                Urban-type surfaces
9767                   DO  m = surf_usm_h%start_index(j,i),                        &
9768                           surf_usm_h%end_index(j,i) 
9769                      local_pf(i,j,nzb+1) = surf_usm_h%rad_lw_in(m)
9770                   ENDDO
9771                ENDDO
9772             ENDDO
9773          ELSE
9774             IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) ) THEN
9775                ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
9776                rad_lw_in_xy_av = REAL( fill_value, KIND = wp )
9777             ENDIF
9778             DO  i = nxl, nxr
9779                DO  j = nys, nyn 
9780                   local_pf(i,j,nzb+1) = rad_lw_in_xy_av(j,i)
9781                ENDDO
9782             ENDDO
9783          ENDIF
9784          two_d = .TRUE.
9785          grid = 'zu1'
9786         
9787       CASE ( 'rad_lw_out*_xy' )        ! 2d-array
9788          IF ( av == 0 ) THEN
9789             DO  i = nxl, nxr
9790                DO  j = nys, nyn
9791!
9792!--                Obtain rad_net from its respective surface type
9793!--                Natural-type surfaces
9794                   DO  m = surf_lsm_h%start_index(j,i),                        &
9795                           surf_lsm_h%end_index(j,i) 
9796                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_lw_out(m)
9797                   ENDDO
9798!
9799!--                Urban-type surfaces
9800                   DO  m = surf_usm_h%start_index(j,i),                        &
9801                           surf_usm_h%end_index(j,i) 
9802                      local_pf(i,j,nzb+1) = surf_usm_h%rad_lw_out(m)
9803                   ENDDO
9804                ENDDO
9805             ENDDO
9806          ELSE
9807             IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) ) THEN
9808                ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
9809                rad_lw_out_xy_av = REAL( fill_value, KIND = wp )
9810             ENDIF
9811             DO  i = nxl, nxr
9812                DO  j = nys, nyn 
9813                   local_pf(i,j,nzb+1) = rad_lw_out_xy_av(j,i)
9814                ENDDO
9815             ENDDO
9816          ENDIF
9817          two_d = .TRUE.
9818          grid = 'zu1'
9819         
9820       CASE ( 'rad_sw_in*_xy' )        ! 2d-array
9821          IF ( av == 0 ) THEN
9822             DO  i = nxl, nxr
9823                DO  j = nys, nyn
9824!
9825!--                Obtain rad_net from its respective surface type
9826!--                Natural-type surfaces
9827                   DO  m = surf_lsm_h%start_index(j,i),                        &
9828                           surf_lsm_h%end_index(j,i) 
9829                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_sw_in(m)
9830                   ENDDO
9831!
9832!--                Urban-type surfaces
9833                   DO  m = surf_usm_h%start_index(j,i),                        &
9834                           surf_usm_h%end_index(j,i) 
9835                      local_pf(i,j,nzb+1) = surf_usm_h%rad_sw_in(m)
9836                   ENDDO
9837                ENDDO
9838             ENDDO
9839          ELSE
9840             IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) ) THEN
9841                ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
9842                rad_sw_in_xy_av = REAL( fill_value, KIND = wp )
9843             ENDIF
9844             DO  i = nxl, nxr
9845                DO  j = nys, nyn 
9846                   local_pf(i,j,nzb+1) = rad_sw_in_xy_av(j,i)
9847                ENDDO
9848             ENDDO
9849          ENDIF
9850          two_d = .TRUE.
9851          grid = 'zu1'
9852         
9853       CASE ( 'rad_sw_out*_xy' )        ! 2d-array
9854          IF ( av == 0 ) THEN
9855             DO  i = nxl, nxr
9856                DO  j = nys, nyn
9857!
9858!--                Obtain rad_net from its respective surface type
9859!--                Natural-type surfaces
9860                   DO  m = surf_lsm_h%start_index(j,i),                        &
9861                           surf_lsm_h%end_index(j,i) 
9862                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_sw_out(m)
9863                   ENDDO
9864!
9865!--                Urban-type surfaces
9866                   DO  m = surf_usm_h%start_index(j,i),                        &
9867                           surf_usm_h%end_index(j,i) 
9868                      local_pf(i,j,nzb+1) = surf_usm_h%rad_sw_out(m)
9869                   ENDDO
9870                ENDDO
9871             ENDDO
9872          ELSE
9873             IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) ) THEN
9874                ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
9875                rad_sw_out_xy_av = REAL( fill_value, KIND = wp )
9876             ENDIF
9877             DO  i = nxl, nxr
9878                DO  j = nys, nyn 
9879                   local_pf(i,j,nzb+1) = rad_sw_out_xy_av(j,i)
9880                ENDDO
9881             ENDDO
9882          ENDIF
9883          two_d = .TRUE.
9884          grid = 'zu1'         
9885         
9886       CASE ( 'rad_lw_in_xy', 'rad_lw_in_xz', 'rad_lw_in_yz' )
9887          IF ( av == 0 ) THEN
9888             DO  i = nxl, nxr
9889                DO  j = nys, nyn
9890                   DO  k = nzb_do, nzt_do
9891                      local_pf(i,j,k) = rad_lw_in(k,j,i)
9892                   ENDDO
9893                ENDDO
9894             ENDDO
9895          ELSE
9896            IF ( .NOT. ALLOCATED( rad_lw_in_av ) ) THEN
9897               ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9898               rad_lw_in_av = REAL( fill_value, KIND = wp )
9899            ENDIF
9900             DO  i = nxl, nxr
9901                DO  j = nys, nyn 
9902                   DO  k = nzb_do, nzt_do
9903                      local_pf(i,j,k) = rad_lw_in_av(k,j,i)
9904                   ENDDO
9905                ENDDO
9906             ENDDO
9907          ENDIF
9908          IF ( mode == 'xy' )  grid = 'zu'
9909
9910       CASE ( 'rad_lw_out_xy', 'rad_lw_out_xz', 'rad_lw_out_yz' )
9911          IF ( av == 0 ) THEN
9912             DO  i = nxl, nxr
9913                DO  j = nys, nyn
9914                   DO  k = nzb_do, nzt_do
9915                      local_pf(i,j,k) = rad_lw_out(k,j,i)
9916                   ENDDO
9917                ENDDO
9918             ENDDO
9919          ELSE
9920            IF ( .NOT. ALLOCATED( rad_lw_out_av ) ) THEN
9921               ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9922               rad_lw_out_av = REAL( fill_value, KIND = wp )
9923            ENDIF
9924             DO  i = nxl, nxr
9925                DO  j = nys, nyn 
9926                   DO  k = nzb_do, nzt_do
9927                      local_pf(i,j,k) = rad_lw_out_av(k,j,i)
9928                   ENDDO
9929                ENDDO
9930             ENDDO
9931          ENDIF   
9932          IF ( mode == 'xy' )  grid = 'zu'
9933
9934       CASE ( 'rad_lw_cs_hr_xy', 'rad_lw_cs_hr_xz', 'rad_lw_cs_hr_yz' )
9935          IF ( av == 0 ) THEN
9936             DO  i = nxl, nxr
9937                DO  j = nys, nyn
9938                   DO  k = nzb_do, nzt_do
9939                      local_pf(i,j,k) = rad_lw_cs_hr(k,j,i)
9940                   ENDDO
9941                ENDDO
9942             ENDDO
9943          ELSE
9944            IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) ) THEN
9945               ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9946               rad_lw_cs_hr_av = REAL( fill_value, KIND = wp )
9947            ENDIF
9948             DO  i = nxl, nxr
9949                DO  j = nys, nyn 
9950                   DO  k = nzb_do, nzt_do
9951                      local_pf(i,j,k) = rad_lw_cs_hr_av(k,j,i)
9952                   ENDDO
9953                ENDDO
9954             ENDDO
9955          ENDIF
9956          IF ( mode == 'xy' )  grid = 'zw'
9957
9958       CASE ( 'rad_lw_hr_xy', 'rad_lw_hr_xz', 'rad_lw_hr_yz' )
9959          IF ( av == 0 ) THEN
9960             DO  i = nxl, nxr
9961                DO  j = nys, nyn
9962                   DO  k = nzb_do, nzt_do
9963                      local_pf(i,j,k) = rad_lw_hr(k,j,i)
9964                   ENDDO
9965                ENDDO
9966             ENDDO
9967          ELSE
9968            IF ( .NOT. ALLOCATED( rad_lw_hr_av ) ) THEN
9969               ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9970               rad_lw_hr_av= REAL( fill_value, KIND = wp )
9971            ENDIF
9972             DO  i = nxl, nxr
9973                DO  j = nys, nyn 
9974                   DO  k = nzb_do, nzt_do
9975                      local_pf(i,j,k) = rad_lw_hr_av(k,j,i)
9976                   ENDDO
9977                ENDDO
9978             ENDDO
9979          ENDIF
9980          IF ( mode == 'xy' )  grid = 'zw'
9981
9982       CASE ( 'rad_sw_in_xy', 'rad_sw_in_xz', 'rad_sw_in_yz' )
9983          IF ( av == 0 ) THEN
9984             DO  i = nxl, nxr
9985                DO  j = nys, nyn
9986                   DO  k = nzb_do, nzt_do
9987                      local_pf(i,j,k) = rad_sw_in(k,j,i)
9988                   ENDDO
9989                ENDDO
9990             ENDDO
9991          ELSE
9992            IF ( .NOT. ALLOCATED( rad_sw_in_av ) ) THEN
9993               ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9994               rad_sw_in_av = REAL( fill_value, KIND = wp )
9995            ENDIF
9996             DO  i = nxl, nxr
9997                DO  j = nys, nyn 
9998                   DO  k = nzb_do, nzt_do
9999                      local_pf(i,j,k) = rad_sw_in_av(k,j,i)
10000                   ENDDO
10001                ENDDO
10002             ENDDO
10003          ENDIF
10004          IF ( mode == 'xy' )  grid = 'zu'
10005
10006       CASE ( 'rad_sw_out_xy', 'rad_sw_out_xz', 'rad_sw_out_yz' )
10007          IF ( av == 0 ) THEN
10008             DO  i = nxl, nxr
10009                DO  j = nys, nyn
10010                   DO  k = nzb_do, nzt_do
10011                      local_pf(i,j,k) = rad_sw_out(k,j,i)
10012                   ENDDO
10013                ENDDO
10014             ENDDO
10015          ELSE
10016            IF ( .NOT. ALLOCATED( rad_sw_out_av ) ) THEN
10017               ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10018               rad_sw_out_av = REAL( fill_value, KIND = wp )
10019            ENDIF
10020             DO  i = nxl, nxr
10021                DO  j = nys, nyn 
10022                   DO  k = nzb, nzt+1
10023                      local_pf(i,j,k) = rad_sw_out_av(k,j,i)
10024                   ENDDO
10025                ENDDO
10026             ENDDO
10027          ENDIF
10028          IF ( mode == 'xy' )  grid = 'zu'
10029
10030       CASE ( 'rad_sw_cs_hr_xy', 'rad_sw_cs_hr_xz', 'rad_sw_cs_hr_yz' )
10031          IF ( av == 0 ) THEN
10032             DO  i = nxl, nxr
10033                DO  j = nys, nyn
10034                   DO  k = nzb_do, nzt_do
10035                      local_pf(i,j,k) = rad_sw_cs_hr(k,j,i)
10036                   ENDDO
10037                ENDDO
10038             ENDDO
10039          ELSE
10040            IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) ) THEN
10041               ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10042               rad_sw_cs_hr_av = REAL( fill_value, KIND = wp )
10043            ENDIF
10044             DO  i = nxl, nxr
10045                DO  j = nys, nyn 
10046                   DO  k = nzb_do, nzt_do
10047                      local_pf(i,j,k) = rad_sw_cs_hr_av(k,j,i)
10048                   ENDDO
10049                ENDDO
10050             ENDDO
10051          ENDIF
10052          IF ( mode == 'xy' )  grid = 'zw'
10053
10054       CASE ( 'rad_sw_hr_xy', 'rad_sw_hr_xz', 'rad_sw_hr_yz' )
10055          IF ( av == 0 ) THEN
10056             DO  i = nxl, nxr
10057                DO  j = nys, nyn
10058                   DO  k = nzb_do, nzt_do
10059                      local_pf(i,j,k) = rad_sw_hr(k,j,i)
10060                   ENDDO
10061                ENDDO
10062             ENDDO
10063          ELSE
10064            IF ( .NOT. ALLOCATED( rad_sw_hr_av ) ) THEN
10065               ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10066               rad_sw_hr_av = REAL( fill_value, KIND = wp )
10067            ENDIF
10068             DO  i = nxl, nxr
10069                DO  j = nys, nyn 
10070                   DO  k = nzb_do, nzt_do
10071                      local_pf(i,j,k) = rad_sw_hr_av(k,j,i)
10072                   ENDDO
10073                ENDDO
10074             ENDDO
10075          ENDIF
10076          IF ( mode == 'xy' )  grid = 'zw'
10077
10078       CASE DEFAULT
10079          found = .FALSE.
10080          grid  = 'none'
10081
10082    END SELECT
10083 
10084 END SUBROUTINE radiation_data_output_2d
10085
10086
10087!------------------------------------------------------------------------------!
10088!
10089! Description:
10090! ------------
10091!> Subroutine defining 3D output variables
10092!------------------------------------------------------------------------------!
10093 SUBROUTINE radiation_data_output_3d( av, variable, found, local_pf, nzb_do, nzt_do )
10094 
10095
10096    USE indices
10097
10098    USE kinds
10099
10100
10101    IMPLICIT NONE
10102
10103    CHARACTER (LEN=*) ::  variable !<
10104
10105    INTEGER(iwp) ::  av          !<
10106    INTEGER(iwp) ::  i, j, k, l  !<
10107    INTEGER(iwp) ::  nzb_do      !<
10108    INTEGER(iwp) ::  nzt_do      !<
10109
10110    LOGICAL      ::  found       !<
10111
10112    REAL(wp)     ::  fill_value = -999.0_wp    !< value for the _FillValue attribute
10113
10114    REAL(sp), DIMENSION(nxl:nxr,nys:nyn,nzb_do:nzt_do) ::  local_pf !<
10115
10116    CHARACTER (len=varnamelength)                   :: var, surfid
10117    INTEGER(iwp)                                    :: ids,idsint_u,idsint_l,isurf,isvf,isurfs,isurflt,ipcgb
10118    INTEGER(iwp)                                    :: is, js, ks, istat
10119
10120    found = .TRUE.
10121
10122    ids = -1
10123    var = TRIM(variable)
10124    DO i = 0, nd-1
10125        k = len(TRIM(var))
10126        j = len(TRIM(dirname(i)))
10127        IF ( TRIM(var(k-j+1:k)) == TRIM(dirname(i)) )  THEN
10128            ids = i
10129            idsint_u = dirint_u(ids)
10130            idsint_l = dirint_l(ids)
10131            var = var(:k-j)
10132            EXIT
10133        ENDIF
10134    ENDDO
10135    IF ( ids == -1 )  THEN
10136        var = TRIM(variable)
10137    ENDIF
10138
10139    IF ( (var(1:8) == 'rtm_svf_'  .OR.  var(1:8) == 'rtm_dif_')  .AND.  len(TRIM(var)) >= 13 )  THEN
10140!--     svf values to particular surface
10141        surfid = var(9:)
10142        i = index(surfid,'_')
10143        j = index(surfid(i+1:),'_')
10144        READ(surfid(1:i-1),*, iostat=istat ) is
10145        IF ( istat == 0 )  THEN
10146            READ(surfid(i+1:i+j-1),*, iostat=istat ) js
10147        ENDIF
10148        IF ( istat == 0 )  THEN
10149            READ(surfid(i+j+1:),*, iostat=istat ) ks
10150        ENDIF
10151        IF ( istat == 0 )  THEN
10152            var = var(1:7)
10153        ENDIF
10154    ENDIF
10155
10156    local_pf = fill_value
10157
10158    SELECT CASE ( TRIM( var ) )
10159!--   block of large scale radiation model (e.g. RRTMG) output variables
10160      CASE ( 'rad_sw_in' )
10161         IF ( av == 0 )  THEN
10162            DO  i = nxl, nxr
10163               DO  j = nys, nyn
10164                  DO  k = nzb_do, nzt_do
10165                     local_pf(i,j,k) = rad_sw_in(k,j,i)
10166                  ENDDO
10167               ENDDO
10168            ENDDO
10169         ELSE
10170            IF ( .NOT. ALLOCATED( rad_sw_in_av ) ) THEN
10171               ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10172               rad_sw_in_av = REAL( fill_value, KIND = wp )
10173            ENDIF
10174            DO  i = nxl, nxr
10175               DO  j = nys, nyn
10176                  DO  k = nzb_do, nzt_do
10177                     local_pf(i,j,k) = rad_sw_in_av(k,j,i)
10178                  ENDDO
10179               ENDDO
10180            ENDDO
10181         ENDIF
10182
10183      CASE ( 'rad_sw_out' )
10184         IF ( av == 0 )  THEN
10185            DO  i = nxl, nxr
10186               DO  j = nys, nyn
10187                  DO  k = nzb_do, nzt_do
10188                     local_pf(i,j,k) = rad_sw_out(k,j,i)
10189                  ENDDO
10190               ENDDO
10191            ENDDO
10192         ELSE
10193            IF ( .NOT. ALLOCATED( rad_sw_out_av ) ) THEN
10194               ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10195               rad_sw_out_av = REAL( fill_value, KIND = wp )
10196            ENDIF
10197            DO  i = nxl, nxr
10198               DO  j = nys, nyn
10199                  DO  k = nzb_do, nzt_do
10200                     local_pf(i,j,k) = rad_sw_out_av(k,j,i)
10201                  ENDDO
10202               ENDDO
10203            ENDDO
10204         ENDIF
10205
10206      CASE ( 'rad_sw_cs_hr' )
10207         IF ( av == 0 )  THEN
10208            DO  i = nxl, nxr
10209               DO  j = nys, nyn
10210                  DO  k = nzb_do, nzt_do
10211                     local_pf(i,j,k) = rad_sw_cs_hr(k,j,i)
10212                  ENDDO
10213               ENDDO
10214            ENDDO
10215         ELSE
10216            IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) ) THEN
10217               ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10218               rad_sw_cs_hr_av = REAL( fill_value, KIND = wp )
10219            ENDIF
10220            DO  i = nxl, nxr
10221               DO  j = nys, nyn
10222                  DO  k = nzb_do, nzt_do
10223                     local_pf(i,j,k) = rad_sw_cs_hr_av(k,j,i)
10224                  ENDDO
10225               ENDDO
10226            ENDDO
10227         ENDIF
10228
10229      CASE ( 'rad_sw_hr' )
10230         IF ( av == 0 )  THEN
10231            DO  i = nxl, nxr
10232               DO  j = nys, nyn
10233                  DO  k = nzb_do, nzt_do
10234                     local_pf(i,j,k) = rad_sw_hr(k,j,i)
10235                  ENDDO
10236               ENDDO
10237            ENDDO
10238         ELSE
10239            IF ( .NOT. ALLOCATED( rad_sw_hr_av ) ) THEN
10240               ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10241               rad_sw_hr_av = REAL( fill_value, KIND = wp )
10242            ENDIF
10243            DO  i = nxl, nxr
10244               DO  j = nys, nyn
10245                  DO  k = nzb_do, nzt_do
10246                     local_pf(i,j,k) = rad_sw_hr_av(k,j,i)
10247                  ENDDO
10248               ENDDO
10249            ENDDO
10250         ENDIF
10251
10252      CASE ( 'rad_lw_in' )
10253         IF ( av == 0 )  THEN
10254            DO  i = nxl, nxr
10255               DO  j = nys, nyn
10256                  DO  k = nzb_do, nzt_do
10257                     local_pf(i,j,k) = rad_lw_in(k,j,i)
10258                  ENDDO
10259               ENDDO
10260            ENDDO
10261         ELSE
10262            IF ( .NOT. ALLOCATED( rad_lw_in_av ) ) THEN
10263               ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10264               rad_lw_in_av = REAL( fill_value, KIND = wp )
10265            ENDIF
10266            DO  i = nxl, nxr
10267               DO  j = nys, nyn
10268                  DO  k = nzb_do, nzt_do
10269                     local_pf(i,j,k) = rad_lw_in_av(k,j,i)
10270                  ENDDO
10271               ENDDO
10272            ENDDO
10273         ENDIF
10274
10275      CASE ( 'rad_lw_out' )
10276         IF ( av == 0 )  THEN
10277            DO  i = nxl, nxr
10278               DO  j = nys, nyn
10279                  DO  k = nzb_do, nzt_do
10280                     local_pf(i,j,k) = rad_lw_out(k,j,i)
10281                  ENDDO
10282               ENDDO
10283            ENDDO
10284         ELSE
10285            IF ( .NOT. ALLOCATED( rad_lw_out_av ) ) THEN
10286               ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10287               rad_lw_out_av = REAL( fill_value, KIND = wp )
10288            ENDIF
10289            DO  i = nxl, nxr
10290               DO  j = nys, nyn
10291                  DO  k = nzb_do, nzt_do
10292                     local_pf(i,j,k) = rad_lw_out_av(k,j,i)
10293                  ENDDO
10294               ENDDO
10295            ENDDO
10296         ENDIF
10297
10298      CASE ( 'rad_lw_cs_hr' )
10299         IF ( av == 0 )  THEN
10300            DO  i = nxl, nxr
10301               DO  j = nys, nyn
10302                  DO  k = nzb_do, nzt_do
10303                     local_pf(i,j,k) = rad_lw_cs_hr(k,j,i)
10304                  ENDDO
10305               ENDDO
10306            ENDDO
10307         ELSE
10308            IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) ) THEN
10309               ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10310               rad_lw_cs_hr_av = REAL( fill_value, KIND = wp )
10311            ENDIF
10312            DO  i = nxl, nxr
10313               DO  j = nys, nyn
10314                  DO  k = nzb_do, nzt_do
10315                     local_pf(i,j,k) = rad_lw_cs_hr_av(k,j,i)
10316                  ENDDO
10317               ENDDO
10318            ENDDO
10319         ENDIF
10320
10321      CASE ( 'rad_lw_hr' )
10322         IF ( av == 0 )  THEN
10323            DO  i = nxl, nxr
10324               DO  j = nys, nyn
10325                  DO  k = nzb_do, nzt_do
10326                     local_pf(i,j,k) = rad_lw_hr(k,j,i)
10327                  ENDDO
10328               ENDDO
10329            ENDDO
10330         ELSE
10331            IF ( .NOT. ALLOCATED( rad_lw_hr_av ) ) THEN
10332               ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10333              rad_lw_hr_av = REAL( fill_value, KIND = wp )
10334            ENDIF
10335            DO  i = nxl, nxr
10336               DO  j = nys, nyn
10337                  DO  k = nzb_do, nzt_do
10338                     local_pf(i,j,k) = rad_lw_hr_av(k,j,i)
10339                  ENDDO
10340               ENDDO
10341            ENDDO
10342         ENDIF
10343
10344!--   block of RTM output variables
10345!--   variables are intended mainly for debugging and detailed analyse purposes
10346      CASE ( 'rtm_skyvf' )
10347!--        sky view factor
10348         DO isurf = dirstart(ids), dirend(ids)
10349            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10350               local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = skyvf(isurf)
10351            ENDIF
10352         ENDDO
10353
10354      CASE ( 'rtm_skyvft' )
10355!--      sky view factor
10356         DO isurf = dirstart(ids), dirend(ids)
10357            IF ( surfl(id,isurf) == ids )  THEN
10358               local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = skyvft(isurf)
10359            ENDIF
10360         ENDDO
10361
10362      CASE ( 'rtm_svf', 'rtm_dif' )
10363!--      shape view factors or iradiance factors to selected surface
10364         IF ( TRIM(var)=='rtm_svf' )  THEN
10365             k = 1
10366         ELSE
10367             k = 2
10368         ENDIF
10369         DO isvf = 1, nsvfl
10370            isurflt = svfsurf(1, isvf)
10371            isurfs = svfsurf(2, isvf)
10372
10373            IF ( surf(ix,isurfs) == is  .AND.  surf(iy,isurfs) == js  .AND. surf(iz,isurfs) == ks  .AND. &
10374                 (surf(id,isurfs) == idsint_u .OR. surfl(id,isurf) == idsint_l ) ) THEN
10375!--            correct source surface
10376               local_pf(surfl(ix,isurflt),surfl(iy,isurflt),surfl(iz,isurflt)) = svf(k,isvf)
10377            ENDIF
10378         ENDDO
10379
10380      CASE ( 'rtm_rad_net' )
10381!--     array of complete radiation balance
10382         DO isurf = dirstart(ids), dirend(ids)
10383            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10384               IF ( av == 0 )  THEN
10385                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = &
10386                         surfinsw(isurf) - surfoutsw(isurf) +  surfinlw(isurf) - surfoutlw(isurf)
10387               ELSE
10388                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfradnet_av(isurf)
10389               ENDIF
10390            ENDIF
10391         ENDDO
10392
10393      CASE ( 'rtm_rad_insw' )
10394!--      array of sw radiation falling to surface after i-th reflection
10395         DO isurf = dirstart(ids), dirend(ids)
10396            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10397               IF ( av == 0 )  THEN
10398                 local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinsw(isurf)
10399               ELSE
10400                 local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinsw_av(isurf)
10401               ENDIF
10402            ENDIF
10403         ENDDO
10404
10405      CASE ( 'rtm_rad_inlw' )
10406!--      array of lw radiation falling to surface after i-th reflection
10407         DO isurf = dirstart(ids), dirend(ids)
10408            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10409               IF ( av == 0 )  THEN
10410                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlw(isurf)
10411               ELSE
10412                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlw_av(isurf)
10413               ENDIF
10414             ENDIF
10415         ENDDO
10416
10417      CASE ( 'rtm_rad_inswdir' )
10418!--      array of direct sw radiation falling to surface from sun
10419         DO isurf = dirstart(ids), dirend(ids)
10420            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10421               IF ( av == 0 )  THEN
10422                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdir(isurf)
10423               ELSE
10424                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdir_av(isurf)
10425               ENDIF
10426            ENDIF
10427         ENDDO
10428
10429      CASE ( 'rtm_rad_inswdif' )
10430!--      array of difusion sw radiation falling to surface from sky and borders of the domain
10431         DO isurf = dirstart(ids), dirend(ids)
10432            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10433               IF ( av == 0 )  THEN
10434                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdif(isurf)
10435               ELSE
10436                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdif_av(isurf)
10437               ENDIF
10438            ENDIF
10439         ENDDO
10440
10441      CASE ( 'rtm_rad_inswref' )
10442!--      array of sw radiation falling to surface from reflections
10443         DO isurf = dirstart(ids), dirend(ids)
10444            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10445               IF ( av == 0 )  THEN
10446                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = &
10447                    surfinsw(isurf) - surfinswdir(isurf) - surfinswdif(isurf)
10448               ELSE
10449                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswref_av(isurf)
10450               ENDIF
10451            ENDIF
10452         ENDDO
10453
10454      CASE ( 'rtm_rad_inlwdif' )
10455!--      array of difusion lw radiation falling to surface from sky and borders of the domain
10456         DO isurf = dirstart(ids), dirend(ids)
10457            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10458               IF ( av == 0 )  THEN
10459                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlwdif(isurf)
10460               ELSE
10461                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlwdif_av(isurf)
10462               ENDIF
10463            ENDIF
10464         ENDDO
10465
10466      CASE ( 'rtm_rad_inlwref' )
10467!--      array of lw radiation falling to surface from reflections
10468         DO isurf = dirstart(ids), dirend(ids)
10469            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10470               IF ( av == 0 )  THEN
10471                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlw(isurf) - surfinlwdif(isurf)
10472               ELSE
10473                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlwref_av(isurf)
10474               ENDIF
10475            ENDIF
10476         ENDDO
10477
10478      CASE ( 'rtm_rad_outsw' )
10479!--      array of sw radiation emitted from surface after i-th reflection
10480         DO isurf = dirstart(ids), dirend(ids)
10481            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10482               IF ( av == 0 )  THEN
10483                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutsw(isurf)
10484               ELSE
10485                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutsw_av(isurf)
10486               ENDIF
10487            ENDIF
10488         ENDDO
10489
10490      CASE ( 'rtm_rad_outlw' )
10491!--      array of lw radiation emitted from surface after i-th reflection
10492         DO isurf = dirstart(ids), dirend(ids)
10493            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10494               IF ( av == 0 )  THEN
10495                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutlw(isurf)
10496               ELSE
10497                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutlw_av(isurf)
10498               ENDIF
10499            ENDIF
10500         ENDDO
10501
10502      CASE ( 'rtm_rad_ressw' )
10503!--      average of array of residua of sw radiation absorbed in surface after last reflection
10504         DO isurf = dirstart(ids), dirend(ids)
10505            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10506               IF ( av == 0 )  THEN
10507                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfins(isurf)
10508               ELSE
10509                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfins_av(isurf)
10510               ENDIF
10511            ENDIF
10512         ENDDO
10513
10514      CASE ( 'rtm_rad_reslw' )
10515!--      average of array of residua of lw radiation absorbed in surface after last reflection
10516         DO isurf = dirstart(ids), dirend(ids)
10517            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10518               IF ( av == 0 )  THEN
10519                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinl(isurf)
10520               ELSE
10521                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinl_av(isurf)
10522               ENDIF
10523            ENDIF
10524         ENDDO
10525
10526      CASE ( 'rtm_rad_pc_inlw' )
10527!--      array of lw radiation absorbed by plant canopy
10528         DO ipcgb = 1, npcbl
10529            IF ( av == 0 )  THEN
10530               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinlw(ipcgb)
10531            ELSE
10532               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinlw_av(ipcgb)
10533            ENDIF
10534         ENDDO
10535
10536      CASE ( 'rtm_rad_pc_insw' )
10537!--      array of sw radiation absorbed by plant canopy
10538         DO ipcgb = 1, npcbl
10539            IF ( av == 0 )  THEN
10540              local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinsw(ipcgb)
10541            ELSE
10542              local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinsw_av(ipcgb)
10543            ENDIF
10544         ENDDO
10545
10546      CASE ( 'rtm_rad_pc_inswdir' )
10547!--      array of direct sw radiation absorbed by plant canopy
10548         DO ipcgb = 1, npcbl
10549            IF ( av == 0 )  THEN
10550               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdir(ipcgb)
10551            ELSE
10552               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdir_av(ipcgb)
10553            ENDIF
10554         ENDDO
10555
10556      CASE ( 'rtm_rad_pc_inswdif' )
10557!--      array of diffuse sw radiation absorbed by plant canopy
10558         DO ipcgb = 1, npcbl
10559            IF ( av == 0 )  THEN
10560               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdif(ipcgb)
10561            ELSE
10562               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdif_av(ipcgb)
10563            ENDIF
10564         ENDDO
10565
10566      CASE ( 'rtm_rad_pc_inswref' )
10567!--      array of reflected sw radiation absorbed by plant canopy
10568         DO ipcgb = 1, npcbl
10569            IF ( av == 0 )  THEN
10570               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = &
10571                                    pcbinsw(ipcgb) - pcbinswdir(ipcgb) - pcbinswdif(ipcgb)
10572            ELSE
10573               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswref_av(ipcgb)
10574            ENDIF
10575         ENDDO
10576
10577      CASE ( 'rtm_mrt_sw' )
10578         local_pf = REAL( fill_value, KIND = wp )
10579         IF ( av == 0 )  THEN
10580            DO  l = 1, nmrtbl
10581               local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinsw(l)
10582            ENDDO
10583         ELSE
10584            IF ( ALLOCATED( mrtinsw_av ) ) THEN
10585               DO  l = 1, nmrtbl
10586                  local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinsw_av(l)
10587               ENDDO
10588            ENDIF
10589         ENDIF
10590
10591      CASE ( 'rtm_mrt_lw' )
10592         local_pf = REAL( fill_value, KIND = wp )
10593         IF ( av == 0 )  THEN
10594            DO  l = 1, nmrtbl
10595               local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinlw(l)
10596            ENDDO
10597         ELSE
10598            IF ( ALLOCATED( mrtinlw_av ) ) THEN
10599               DO  l = 1, nmrtbl
10600                  local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinlw_av(l)
10601               ENDDO
10602            ENDIF
10603         ENDIF
10604
10605      CASE ( 'rtm_mrt' )
10606         local_pf = REAL( fill_value, KIND = wp )
10607         IF ( av == 0 )  THEN
10608            DO  l = 1, nmrtbl
10609               local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrt(l)
10610            ENDDO
10611         ELSE
10612            IF ( ALLOCATED( mrt_av ) ) THEN
10613               DO  l = 1, nmrtbl
10614                  local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrt_av(l)
10615               ENDDO
10616            ENDIF
10617         ENDIF
10618
10619       CASE DEFAULT
10620          found = .FALSE.
10621
10622    END SELECT
10623
10624
10625 END SUBROUTINE radiation_data_output_3d
10626
10627!------------------------------------------------------------------------------!
10628!
10629! Description:
10630! ------------
10631!> Subroutine defining masked data output
10632!------------------------------------------------------------------------------!
10633 SUBROUTINE radiation_data_output_mask( av, variable, found, local_pf )
10634 
10635    USE control_parameters
10636       
10637    USE indices
10638   
10639    USE kinds
10640   
10641
10642    IMPLICIT NONE
10643
10644    CHARACTER (LEN=*) ::  variable   !<
10645
10646    CHARACTER(LEN=5) ::  grid        !< flag to distinquish between staggered grids
10647
10648    INTEGER(iwp) ::  av              !<
10649    INTEGER(iwp) ::  i               !<
10650    INTEGER(iwp) ::  j               !<
10651    INTEGER(iwp) ::  k               !<
10652    INTEGER(iwp) ::  topo_top_ind    !< k index of highest horizontal surface
10653
10654    LOGICAL ::  found                !< true if output array was found
10655    LOGICAL ::  resorted             !< true if array is resorted
10656
10657
10658    REAL(wp),                                                                  &
10659       DIMENSION(mask_size_l(mid,1),mask_size_l(mid,2),mask_size_l(mid,3)) ::  &
10660          local_pf   !<
10661
10662    REAL(wp), DIMENSION(:,:,:), POINTER ::  to_be_resorted  !< points to array which needs to be resorted for output
10663
10664
10665    found    = .TRUE.
10666    grid     = 's'
10667    resorted = .FALSE.
10668
10669    SELECT CASE ( TRIM( variable ) )
10670
10671
10672       CASE ( 'rad_lw_in' )
10673          IF ( av == 0 )  THEN
10674             to_be_resorted => rad_lw_in
10675          ELSE
10676             to_be_resorted => rad_lw_in_av
10677          ENDIF
10678
10679       CASE ( 'rad_lw_out' )
10680          IF ( av == 0 )  THEN
10681             to_be_resorted => rad_lw_out
10682          ELSE
10683             to_be_resorted => rad_lw_out_av
10684          ENDIF
10685
10686       CASE ( 'rad_lw_cs_hr' )
10687          IF ( av == 0 )  THEN
10688             to_be_resorted => rad_lw_cs_hr
10689          ELSE
10690             to_be_resorted => rad_lw_cs_hr_av
10691          ENDIF
10692
10693       CASE ( 'rad_lw_hr' )
10694          IF ( av == 0 )  THEN
10695             to_be_resorted => rad_lw_hr
10696          ELSE
10697             to_be_resorted => rad_lw_hr_av
10698          ENDIF
10699
10700       CASE ( 'rad_sw_in' )
10701          IF ( av == 0 )  THEN
10702             to_be_resorted => rad_sw_in
10703          ELSE
10704             to_be_resorted => rad_sw_in_av
10705          ENDIF
10706
10707       CASE ( 'rad_sw_out' )
10708          IF ( av == 0 )  THEN
10709             to_be_resorted => rad_sw_out
10710          ELSE
10711             to_be_resorted => rad_sw_out_av
10712          ENDIF
10713
10714       CASE ( 'rad_sw_cs_hr' )
10715          IF ( av == 0 )  THEN
10716             to_be_resorted => rad_sw_cs_hr
10717          ELSE
10718             to_be_resorted => rad_sw_cs_hr_av
10719          ENDIF
10720
10721       CASE ( 'rad_sw_hr' )
10722          IF ( av == 0 )  THEN
10723             to_be_resorted => rad_sw_hr
10724          ELSE
10725             to_be_resorted => rad_sw_hr_av
10726          ENDIF
10727
10728       CASE DEFAULT
10729          found = .FALSE.
10730
10731    END SELECT
10732
10733!
10734!-- Resort the array to be output, if not done above
10735    IF ( .NOT. resorted )  THEN
10736       IF ( .NOT. mask_surface(mid) )  THEN
10737!
10738!--       Default masked output
10739          DO  i = 1, mask_size_l(mid,1)
10740             DO  j = 1, mask_size_l(mid,2)
10741                DO  k = 1, mask_size_l(mid,3)
10742                   local_pf(i,j,k) =  to_be_resorted(mask_k(mid,k), &
10743                                      mask_j(mid,j),mask_i(mid,i))
10744                ENDDO
10745             ENDDO
10746          ENDDO
10747
10748       ELSE
10749!
10750!--       Terrain-following masked output
10751          DO  i = 1, mask_size_l(mid,1)
10752             DO  j = 1, mask_size_l(mid,2)
10753!
10754!--             Get k index of highest horizontal surface
10755                topo_top_ind = get_topography_top_index_ji( mask_j(mid,j), &
10756                                                            mask_i(mid,i), &
10757                                                            grid )
10758!
10759!--             Save output array
10760                DO  k = 1, mask_size_l(mid,3)
10761                   local_pf(i,j,k) = to_be_resorted(                       &
10762                                          MIN( topo_top_ind+mask_k(mid,k), &
10763                                               nzt+1 ),                    &
10764                                          mask_j(mid,j),                   &
10765                                          mask_i(mid,i)                     )
10766                ENDDO
10767             ENDDO
10768          ENDDO
10769
10770       ENDIF
10771    ENDIF
10772
10773
10774
10775 END SUBROUTINE radiation_data_output_mask
10776
10777
10778!------------------------------------------------------------------------------!
10779! Description:
10780! ------------
10781!> Subroutine writes local (subdomain) restart data
10782!------------------------------------------------------------------------------!
10783 SUBROUTINE radiation_wrd_local
10784
10785
10786    IMPLICIT NONE
10787
10788
10789    IF ( ALLOCATED( rad_net_av ) )  THEN
10790       CALL wrd_write_string( 'rad_net_av' )
10791       WRITE ( 14 )  rad_net_av
10792    ENDIF
10793   
10794    IF ( ALLOCATED( rad_lw_in_xy_av ) )  THEN
10795       CALL wrd_write_string( 'rad_lw_in_xy_av' )
10796       WRITE ( 14 )  rad_lw_in_xy_av
10797    ENDIF
10798   
10799    IF ( ALLOCATED( rad_lw_out_xy_av ) )  THEN
10800       CALL wrd_write_string( 'rad_lw_out_xy_av' )
10801       WRITE ( 14 )  rad_lw_out_xy_av
10802    ENDIF
10803   
10804    IF ( ALLOCATED( rad_sw_in_xy_av ) )  THEN
10805       CALL wrd_write_string( 'rad_sw_in_xy_av' )
10806       WRITE ( 14 )  rad_sw_in_xy_av
10807    ENDIF
10808   
10809    IF ( ALLOCATED( rad_sw_out_xy_av ) )  THEN
10810       CALL wrd_write_string( 'rad_sw_out_xy_av' )
10811       WRITE ( 14 )  rad_sw_out_xy_av
10812    ENDIF
10813
10814    IF ( ALLOCATED( rad_lw_in ) )  THEN
10815       CALL wrd_write_string( 'rad_lw_in' )
10816       WRITE ( 14 )  rad_lw_in
10817    ENDIF
10818
10819    IF ( ALLOCATED( rad_lw_in_av ) )  THEN
10820       CALL wrd_write_string( 'rad_lw_in_av' )
10821       WRITE ( 14 )  rad_lw_in_av
10822    ENDIF
10823
10824    IF ( ALLOCATED( rad_lw_out ) )  THEN
10825       CALL wrd_write_string( 'rad_lw_out' )
10826       WRITE ( 14 )  rad_lw_out
10827    ENDIF
10828
10829    IF ( ALLOCATED( rad_lw_out_av) )  THEN
10830       CALL wrd_write_string( 'rad_lw_out_av' )
10831       WRITE ( 14 )  rad_lw_out_av
10832    ENDIF
10833
10834    IF ( ALLOCATED( rad_lw_cs_hr) )  THEN
10835       CALL wrd_write_string( 'rad_lw_cs_hr' )
10836       WRITE ( 14 )  rad_lw_cs_hr
10837    ENDIF
10838
10839    IF ( ALLOCATED( rad_lw_cs_hr_av) )  THEN
10840       CALL wrd_write_string( 'rad_lw_cs_hr_av' )
10841       WRITE ( 14 )  rad_lw_cs_hr_av
10842    ENDIF
10843
10844    IF ( ALLOCATED( rad_lw_hr) )  THEN
10845       CALL wrd_write_string( 'rad_lw_hr' )
10846       WRITE ( 14 )  rad_lw_hr
10847    ENDIF
10848
10849    IF ( ALLOCATED( rad_lw_hr_av) )  THEN
10850       CALL wrd_write_string( 'rad_lw_hr_av' )
10851       WRITE ( 14 )  rad_lw_hr_av
10852    ENDIF
10853
10854    IF ( ALLOCATED( rad_sw_in) )  THEN
10855       CALL wrd_write_string( 'rad_sw_in' )
10856       WRITE ( 14 )  rad_sw_in
10857    ENDIF
10858
10859    IF ( ALLOCATED( rad_sw_in_av) )  THEN
10860       CALL wrd_write_string( 'rad_sw_in_av' )
10861       WRITE ( 14 )  rad_sw_in_av
10862    ENDIF
10863
10864    IF ( ALLOCATED( rad_sw_out) )  THEN
10865       CALL wrd_write_string( 'rad_sw_out' )
10866       WRITE ( 14 )  rad_sw_out
10867    ENDIF
10868
10869    IF ( ALLOCATED( rad_sw_out_av) )  THEN
10870       CALL wrd_write_string( 'rad_sw_out_av' )
10871       WRITE ( 14 )  rad_sw_out_av
10872    ENDIF
10873
10874    IF ( ALLOCATED( rad_sw_cs_hr) )  THEN
10875       CALL wrd_write_string( 'rad_sw_cs_hr' )
10876       WRITE ( 14 )  rad_sw_cs_hr
10877    ENDIF
10878
10879    IF ( ALLOCATED( rad_sw_cs_hr_av) )  THEN
10880       CALL wrd_write_string( 'rad_sw_cs_hr_av' )
10881       WRITE ( 14 )  rad_sw_cs_hr_av
10882    ENDIF
10883
10884    IF ( ALLOCATED( rad_sw_hr) )  THEN
10885       CALL wrd_write_string( 'rad_sw_hr' )
10886       WRITE ( 14 )  rad_sw_hr
10887    ENDIF
10888
10889    IF ( ALLOCATED( rad_sw_hr_av) )  THEN
10890       CALL wrd_write_string( 'rad_sw_hr_av' )
10891       WRITE ( 14 )  rad_sw_hr_av
10892    ENDIF
10893
10894
10895 END SUBROUTINE radiation_wrd_local
10896
10897!------------------------------------------------------------------------------!
10898! Description:
10899! ------------
10900!> Subroutine reads local (subdomain) restart data
10901!------------------------------------------------------------------------------!
10902 SUBROUTINE radiation_rrd_local( i, k, nxlf, nxlc, nxl_on_file, nxrf, nxrc,    &
10903                                nxr_on_file, nynf, nync, nyn_on_file, nysf,    &
10904                                nysc, nys_on_file, tmp_2d, tmp_3d, found )
10905 
10906
10907    USE control_parameters
10908       
10909    USE indices
10910   
10911    USE kinds
10912   
10913    USE pegrid
10914
10915
10916    IMPLICIT NONE
10917
10918    INTEGER(iwp) ::  i               !<
10919    INTEGER(iwp) ::  k               !<
10920    INTEGER(iwp) ::  nxlc            !<
10921    INTEGER(iwp) ::  nxlf            !<
10922    INTEGER(iwp) ::  nxl_on_file     !<
10923    INTEGER(iwp) ::  nxrc            !<
10924    INTEGER(iwp) ::  nxrf            !<
10925    INTEGER(iwp) ::  nxr_on_file     !<
10926    INTEGER(iwp) ::  nync            !<
10927    INTEGER(iwp) ::  nynf            !<
10928    INTEGER(iwp) ::  nyn_on_file     !<
10929    INTEGER(iwp) ::  nysc            !<
10930    INTEGER(iwp) ::  nysf            !<
10931    INTEGER(iwp) ::  nys_on_file     !<
10932
10933    LOGICAL, INTENT(OUT)  :: found
10934
10935    REAL(wp), DIMENSION(nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_2d   !<
10936
10937    REAL(wp), DIMENSION(nzb:nzt+1,nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_3d   !<
10938
10939    REAL(wp), DIMENSION(0:0,nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_3d2   !<
10940
10941
10942    found = .TRUE.
10943
10944
10945    SELECT CASE ( restart_string(1:length) )
10946
10947       CASE ( 'rad_net_av' )
10948          IF ( .NOT. ALLOCATED( rad_net_av ) )  THEN
10949             ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
10950          ENDIF 
10951          IF ( k == 1 )  READ ( 13 )  tmp_2d
10952          rad_net_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =           &
10953                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10954                       
10955       CASE ( 'rad_lw_in_xy_av' )
10956          IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) )  THEN
10957             ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
10958          ENDIF 
10959          IF ( k == 1 )  READ ( 13 )  tmp_2d
10960          rad_lw_in_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =      &
10961                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10962                       
10963       CASE ( 'rad_lw_out_xy_av' )
10964          IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) )  THEN
10965             ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
10966          ENDIF 
10967          IF ( k == 1 )  READ ( 13 )  tmp_2d
10968          rad_lw_out_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =     &
10969                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10970                       
10971       CASE ( 'rad_sw_in_xy_av' )
10972          IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) )  THEN
10973             ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
10974          ENDIF 
10975          IF ( k == 1 )  READ ( 13 )  tmp_2d
10976          rad_sw_in_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =      &
10977                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10978                       
10979       CASE ( 'rad_sw_out_xy_av' )
10980          IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) )  THEN
10981             ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
10982          ENDIF 
10983          IF ( k == 1 )  READ ( 13 )  tmp_2d
10984          rad_sw_out_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =     &
10985                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10986                       
10987       CASE ( 'rad_lw_in' )
10988          IF ( .NOT. ALLOCATED( rad_lw_in ) )  THEN
10989             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
10990                  radiation_scheme == 'constant')  THEN
10991                ALLOCATE( rad_lw_in(0:0,nysg:nyng,nxlg:nxrg) )
10992             ELSE
10993                ALLOCATE( rad_lw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10994             ENDIF
10995          ENDIF 
10996          IF ( k == 1 )  THEN
10997             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
10998                  radiation_scheme == 'constant')  THEN
10999                READ ( 13 )  tmp_3d2
11000                rad_lw_in(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =   &
11001                   tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11002             ELSE
11003                READ ( 13 )  tmp_3d
11004                rad_lw_in(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11005                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11006             ENDIF
11007          ENDIF
11008
11009       CASE ( 'rad_lw_in_av' )
11010          IF ( .NOT. ALLOCATED( rad_lw_in_av ) )  THEN
11011             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11012                  radiation_scheme == 'constant')  THEN
11013                ALLOCATE( rad_lw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
11014             ELSE
11015                ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11016             ENDIF
11017          ENDIF 
11018          IF ( k == 1 )  THEN
11019             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11020                  radiation_scheme == 'constant')  THEN
11021                READ ( 13 )  tmp_3d2
11022                rad_lw_in_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =&
11023                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11024             ELSE
11025                READ ( 13 )  tmp_3d
11026                rad_lw_in_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11027                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11028             ENDIF
11029          ENDIF
11030
11031       CASE ( 'rad_lw_out' )
11032          IF ( .NOT. ALLOCATED( rad_lw_out ) )  THEN
11033             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11034                  radiation_scheme == 'constant')  THEN
11035                ALLOCATE( rad_lw_out(0:0,nysg:nyng,nxlg:nxrg) )
11036             ELSE
11037                ALLOCATE( rad_lw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11038             ENDIF
11039          ENDIF 
11040          IF ( k == 1 )  THEN
11041             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11042                  radiation_scheme == 'constant')  THEN
11043                READ ( 13 )  tmp_3d2
11044                rad_lw_out(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11045                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11046             ELSE
11047                READ ( 13 )  tmp_3d
11048                rad_lw_out(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =    &
11049                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11050             ENDIF
11051          ENDIF
11052
11053       CASE ( 'rad_lw_out_av' )
11054          IF ( .NOT. ALLOCATED( rad_lw_out_av ) )  THEN
11055             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11056                  radiation_scheme == 'constant')  THEN
11057                ALLOCATE( rad_lw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
11058             ELSE
11059                ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11060             ENDIF
11061          ENDIF 
11062          IF ( k == 1 )  THEN
11063             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11064                  radiation_scheme == 'constant')  THEN
11065                READ ( 13 )  tmp_3d2
11066                rad_lw_out_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) &
11067                   = tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11068             ELSE
11069                READ ( 13 )  tmp_3d
11070                rad_lw_out_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &
11071                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11072             ENDIF
11073          ENDIF
11074
11075       CASE ( 'rad_lw_cs_hr' )
11076          IF ( .NOT. ALLOCATED( rad_lw_cs_hr ) )  THEN
11077             ALLOCATE( rad_lw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11078          ENDIF
11079          IF ( k == 1 )  READ ( 13 )  tmp_3d
11080          rad_lw_cs_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11081                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11082
11083       CASE ( 'rad_lw_cs_hr_av' )
11084          IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) )  THEN
11085             ALLOCATE( rad_lw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11086          ENDIF
11087          IF ( k == 1 )  READ ( 13 )  tmp_3d
11088          rad_lw_cs_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11089                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11090
11091       CASE ( 'rad_lw_hr' )
11092          IF ( .NOT. ALLOCATED( rad_lw_hr ) )  THEN
11093             ALLOCATE( rad_lw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11094          ENDIF
11095          IF ( k == 1 )  READ ( 13 )  tmp_3d
11096          rad_lw_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =           &
11097                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11098
11099       CASE ( 'rad_lw_hr_av' )
11100          IF ( .NOT. ALLOCATED( rad_lw_hr_av ) )  THEN
11101             ALLOCATE( rad_lw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11102          ENDIF
11103          IF ( k == 1 )  READ ( 13 )  tmp_3d
11104          rad_lw_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11105                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11106
11107       CASE ( 'rad_sw_in' )
11108          IF ( .NOT. ALLOCATED( rad_sw_in ) )  THEN
11109             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11110                  radiation_scheme == 'constant')  THEN
11111                ALLOCATE( rad_sw_in(0:0,nysg:nyng,nxlg:nxrg) )
11112             ELSE
11113                ALLOCATE( rad_sw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11114             ENDIF
11115          ENDIF 
11116          IF ( k == 1 )  THEN
11117             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11118                  radiation_scheme == 'constant')  THEN
11119                READ ( 13 )  tmp_3d2
11120                rad_sw_in(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =   &
11121                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11122             ELSE
11123                READ ( 13 )  tmp_3d
11124                rad_sw_in(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11125                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11126             ENDIF
11127          ENDIF
11128
11129       CASE ( 'rad_sw_in_av' )
11130          IF ( .NOT. ALLOCATED( rad_sw_in_av ) )  THEN
11131             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11132                  radiation_scheme == 'constant')  THEN
11133                ALLOCATE( rad_sw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
11134             ELSE
11135                ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11136             ENDIF
11137          ENDIF 
11138          IF ( k == 1 )  THEN
11139             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11140                  radiation_scheme == 'constant')  THEN
11141                READ ( 13 )  tmp_3d2
11142                rad_sw_in_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =&
11143                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11144             ELSE
11145                READ ( 13 )  tmp_3d
11146                rad_sw_in_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11147                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11148             ENDIF
11149          ENDIF
11150
11151       CASE ( 'rad_sw_out' )
11152          IF ( .NOT. ALLOCATED( rad_sw_out ) )  THEN
11153             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11154                  radiation_scheme == 'constant')  THEN
11155                ALLOCATE( rad_sw_out(0:0,nysg:nyng,nxlg:nxrg) )
11156             ELSE
11157                ALLOCATE( rad_sw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11158             ENDIF
11159          ENDIF 
11160          IF ( k == 1 )  THEN
11161             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11162                  radiation_scheme == 'constant')  THEN
11163                READ ( 13 )  tmp_3d2
11164                rad_sw_out(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11165                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11166             ELSE
11167                READ ( 13 )  tmp_3d
11168                rad_sw_out(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =    &
11169                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11170             ENDIF
11171          ENDIF
11172
11173       CASE ( 'rad_sw_out_av' )
11174          IF ( .NOT. ALLOCATED( rad_sw_out_av ) )  THEN
11175             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11176                  radiation_scheme == 'constant')  THEN
11177                ALLOCATE( rad_sw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
11178             ELSE
11179                ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11180             ENDIF
11181          ENDIF 
11182          IF ( k == 1 )  THEN
11183             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11184                  radiation_scheme == 'constant')  THEN
11185                READ ( 13 )  tmp_3d2
11186                rad_sw_out_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) &
11187                   = tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11188             ELSE
11189                READ ( 13 )  tmp_3d
11190                rad_sw_out_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &
11191                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11192             ENDIF
11193          ENDIF
11194
11195       CASE ( 'rad_sw_cs_hr' )
11196          IF ( .NOT. ALLOCATED( rad_sw_cs_hr ) )  THEN
11197             ALLOCATE( rad_sw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11198          ENDIF
11199          IF ( k == 1 )  READ ( 13 )  tmp_3d
11200          rad_sw_cs_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11201                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11202
11203       CASE ( 'rad_sw_cs_hr_av' )
11204          IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) )  THEN
11205             ALLOCATE( rad_sw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11206          ENDIF
11207          IF ( k == 1 )  READ ( 13 )  tmp_3d
11208          rad_sw_cs_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11209                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11210
11211       CASE ( 'rad_sw_hr' )
11212          IF ( .NOT. ALLOCATED( rad_sw_hr ) )  THEN
11213             ALLOCATE( rad_sw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11214          ENDIF
11215          IF ( k == 1 )  READ ( 13 )  tmp_3d
11216          rad_sw_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =           &
11217                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11218
11219       CASE ( 'rad_sw_hr_av' )
11220          IF ( .NOT. ALLOCATED( rad_sw_hr_av ) )  THEN
11221             ALLOCATE( rad_sw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11222          ENDIF
11223          IF ( k == 1 )  READ ( 13 )  tmp_3d
11224          rad_lw_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11225                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11226
11227       CASE DEFAULT
11228
11229          found = .FALSE.
11230
11231    END SELECT
11232
11233 END SUBROUTINE radiation_rrd_local
11234
11235!------------------------------------------------------------------------------!
11236! Description:
11237! ------------
11238!> Subroutine writes debug information
11239!------------------------------------------------------------------------------!
11240 SUBROUTINE radiation_write_debug_log ( message )
11241    !> it writes debug log with time stamp
11242    CHARACTER(*)  :: message
11243    CHARACTER(15) :: dtc
11244    CHARACTER(8)  :: date
11245    CHARACTER(10) :: time
11246    CHARACTER(5)  :: zone
11247    CALL date_and_time(date, time, zone)
11248    dtc = date(7:8)//','//time(1:2)//':'//time(3:4)//':'//time(5:10)
11249    WRITE(9,'(2A)') dtc, TRIM(message)
11250    FLUSH(9)
11251 END SUBROUTINE radiation_write_debug_log
11252
11253 END MODULE radiation_model_mod
Note: See TracBrowser for help on using the repository browser.