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

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

Bugfix in initialization of surfaces in cyclic-fill case + bugfix in radiation output

  • 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.5 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 3608 2018-12-07 12:59:57Z suehring $
30! Bugfix radiation output
31!
32! 3607 2018-12-07 11:56:58Z suehring
33! Output of radiation-related quantities migrated to radiation_model_mod.
34!
35! 3589 2018-11-30 15:09:51Z suehring
36! Remove erroneous UTF encoding
37!
38! 3572 2018-11-28 11:40:28Z suehring
39! Add filling the short- and longwave radiation flux arrays (e.g. diffuse,
40! direct, reflected, resedual) for all surfaces. This is required to surface
41! outputs in suface_output_mod. (M. Salim)
42!
43! 3571 2018-11-28 09:24:03Z moh.hefny
44! Add an epsilon value to compare values in if statement to fix possible
45! precsion related errors in raytrace routines.
46!
47! 3524 2018-11-14 13:36:44Z raasch
48! missing cpp-directives added
49!
50! 3495 2018-11-06 15:22:17Z kanani
51! Resort control_parameters ONLY list,
52! From branch radiation@3491 moh.hefny:
53! bugfix in calculating the apparent solar positions by updating
54! the simulated time so that the actual time is correct.
55!
56! 3464 2018-10-30 18:08:55Z kanani
57! From branch resler@3462, pavelkrc:
58! add MRT shaping function for human
59!
60! 3449 2018-10-29 19:36:56Z suehring
61! New RTM version 3.0: (Pavel Krc, Jaroslav Resler, ICS, Prague)
62!   - Interaction of plant canopy with LW radiation
63!   - Transpiration from resolved plant canopy dependent on radiation
64!     called from RTM
65!
66!
67! 3435 2018-10-26 18:25:44Z gronemeier
68! - workaround: return unit=illegal in check_data_output for certain variables
69!   when check called from init_masks
70! - Use pointer in masked output to reduce code redundancies
71! - Add terrain-following masked output
72!
73! 3424 2018-10-25 07:29:10Z gronemeier
74! bugfix: add rad_lw_in, rad_lw_out, rad_sw_out to radiation_check_data_output
75!
76! 3378 2018-10-19 12:34:59Z kanani
77! merge from radiation branch (r3362) into trunk
78! (moh.hefny):
79! - removed read/write_svf_on_init and read_dist_max_svf (not used anymore)
80! - bugfix nzut > nzpt in calculating maxboxes
81!
82! 3372 2018-10-18 14:03:19Z raasch
83! bugfix: kind type of 2nd argument of mpi_win_allocate changed, misplaced
84!         __parallel directive
85!
86! 3351 2018-10-15 18:40:42Z suehring
87! Do not overwrite values of spectral and broadband albedo during initialization
88! if they are already initialized in the urban-surface model via ASCII input.
89!
90! 3337 2018-10-12 15:17:09Z kanani
91! - New RTM version 2.9: (Pavel Krc, Jaroslav Resler, ICS, Prague)
92!   added calculation of the MRT inside the RTM module
93!   MRT fluxes are consequently used in the new biometeorology module
94!   for calculation of biological indices (MRT, PET)
95!   Fixes of v. 2.5 and SVN trunk:
96!    - proper initialization of rad_net_l
97!    - make arrays nsurfs and surfstart TARGET to prevent some MPI problems
98!    - initialization of arrays used in MPI one-sided operation as 1-D arrays
99!      to prevent problems with some MPI/compiler combinations
100!    - fix indexing of target displacement in subroutine request_itarget to
101!      consider nzub
102!    - fix LAD dimmension range in PCB calculation
103!    - check ierr in all MPI calls
104!    - use proper per-gridbox sky and diffuse irradiance
105!    - fix shading for reflected irradiance
106!    - clear away the residuals of "atmospheric surfaces" implementation
107!    - fix rounding bug in raytrace_2d introduced in SVN trunk
108! - New RTM version 2.5: (Pavel Krc, Jaroslav Resler, ICS, Prague)
109!   can use angular discretization for all SVF
110!   (i.e. reflected and emitted radiation in addition to direct and diffuse),
111!   allowing for much better scaling wih high resoltion and/or complex terrain
112! - Unite array grow factors
113! - Fix slightly shifted terrain height in raytrace_2d
114! - Use more efficient MPI_Win_allocate for reverse gridsurf index
115! - Fix random MPI RMA bugs on Intel compilers
116! - Fix approx. double plant canopy sink values for reflected radiation
117! - Fix mostly missing plant canopy sinks for direct radiation
118! - Fix discretization errors for plant canopy sink in diffuse radiation
119! - Fix rounding errors in raytrace_2d
120!
121! 3274 2018-09-24 15:42:55Z knoop
122! Modularization of all bulk cloud physics code components
123!
124! 3272 2018-09-24 10:16:32Z suehring
125! - split direct and diffusion shortwave radiation using RRTMG rather than using
126!   calc_diffusion_radiation, in case of RRTMG
127! - removed the namelist variable split_diffusion_radiation. Now splitting depends
128!   on the choise of radiation radiation scheme
129! - removed calculating the rdiation flux for surfaces at the radiation scheme
130!   in case of using RTM since it will be calculated anyway in the radiation
131!   interaction routine.
132! - set SW radiation flux for surfaces to zero at night in case of no RTM is used
133! - precalculate the unit vector yxdir of ray direction to avoid the temporarly
134!   array allocation during the subroutine call
135! - fixed a bug in calculating the max number of boxes ray can cross in the domain
136!
137! 3264 2018-09-20 13:54:11Z moh.hefny
138! Bugfix in raytrace_2d calls
139!
140! 3248 2018-09-14 09:42:06Z sward
141! Minor formating changes
142!
143! 3246 2018-09-13 15:14:50Z sward
144! Added error handling for input namelist via parin_fail_message
145!
146! 3241 2018-09-12 15:02:00Z raasch
147! unused variables removed or commented
148!
149! 3233 2018-09-07 13:21:24Z schwenkel
150! Adapted for the use of cloud_droplets
151!
152! 3230 2018-09-05 09:29:05Z schwenkel
153! Bugfix in radiation_constant_surf: changed (10.0 - emissivity_urb) to
154! (1.0 - emissivity_urb)
155!
156! 3226 2018-08-31 12:27:09Z suehring
157! Bugfixes in calculation of sky-view factors and canopy-sink factors.
158!
159! 3186 2018-07-30 17:07:14Z suehring
160! Remove print statement
161!
162! 3180 2018-07-27 11:00:56Z suehring
163! Revise concept for calculation of effective radiative temperature and mapping
164! of radiative heating
165!
166! 3175 2018-07-26 14:07:38Z suehring
167! Bugfix for commit 3172
168!
169! 3173 2018-07-26 12:55:23Z suehring
170! Revise output of surface radiation quantities in case of overhanging
171! structures
172!
173! 3172 2018-07-26 12:06:06Z suehring
174! Bugfixes:
175!  - temporal work-around for calculation of effective radiative surface
176!    temperature
177!  - prevent positive solar radiation during nighttime
178!
179! 3170 2018-07-25 15:19:37Z suehring
180! Bugfix, map signle-column radiation forcing profiles on top of any topography
181!
182! 3156 2018-07-19 16:30:54Z knoop
183! Bugfix: replaced usage of the pt array with the surf%pt_surface array
184!
185! 3137 2018-07-17 06:44:21Z maronga
186! String length for trace_names fixed
187!
188! 3127 2018-07-15 08:01:25Z maronga
189! A few pavement parameters updated.
190!
191! 3123 2018-07-12 16:21:53Z suehring
192! Correct working precision for INTEGER number
193!
194! 3122 2018-07-11 21:46:41Z maronga
195! Bugfix: maximum distance for raytracing was set to  -999 m by default,
196! effectively switching off all surface reflections when max_raytracing_dist
197! was not explicitly set in namelist
198!
199! 3117 2018-07-11 09:59:11Z maronga
200! Bugfix: water vapor was not transfered to RRTMG when bulk_cloud_model = .F.
201! Bugfix: changed the calculation of RRTMG boundary conditions (Mohamed Salim)
202! Bugfix: dry residual atmosphere is replaced by standard RRTMG atmosphere
203!
204! 3116 2018-07-10 14:31:58Z suehring
205! Output of long/shortwave radiation at surface
206!
207! 3107 2018-07-06 15:55:51Z suehring
208! Bugfix, missing index for dz
209!
210! 3066 2018-06-12 08:55:55Z Giersch
211! Error message revised
212!
213! 3065 2018-06-12 07:03:02Z Giersch
214! dz was replaced by dz(1), error message concerning vertical stretching was
215! added 
216!
217! 3049 2018-05-29 13:52:36Z Giersch
218! Error messages revised
219!
220! 3045 2018-05-28 07:55:41Z Giersch
221! Error message revised
222!
223! 3026 2018-05-22 10:30:53Z schwenkel
224! Changed the name specific humidity to mixing ratio, since we are computing
225! mixing ratios.
226!
227! 3016 2018-05-09 10:53:37Z Giersch
228! Revised structure of reading svf data according to PALM coding standard:
229! svf_code_field/len and fsvf removed, error messages PA0493 and PA0494 added,
230! allocation status of output arrays checked.
231!
232! 3014 2018-05-09 08:42:38Z maronga
233! Introduced plant canopy height similar to urban canopy height to limit
234! the memory requirement to allocate lad.
235! Deactivated automatic setting of minimum raytracing distance.
236!
237! 3004 2018-04-27 12:33:25Z Giersch
238! Further allocation checks implemented (averaged data will be assigned to fill
239! values if no allocation happened so far)
240!
241! 2995 2018-04-19 12:13:16Z Giersch
242! IF-statement in radiation_init removed so that the calculation of radiative
243! fluxes at model start is done in any case, bugfix in
244! radiation_presimulate_solar_pos (end_time is the sum of end_time and the
245! spinup_time specified in the p3d_file ), list of variables/fields that have
246! to be written out or read in case of restarts has been extended
247!
248! 2977 2018-04-17 10:27:57Z kanani
249! Implement changes from branch radiation (r2948-2971) with minor modifications,
250! plus some formatting.
251! (moh.hefny):
252! - replaced plant_canopy by npcbl to check tree existence to avoid weird
253!   allocation of related arrays (after domain decomposition some domains
254!   contains no trees although plant_canopy (global parameter) is still TRUE).
255! - added a namelist parameter to force RTM settings
256! - enabled the option to switch radiation reflections off
257! - renamed surf_reflections to surface_reflections
258! - removed average_radiation flag from the namelist (now it is implicitly set
259!   in init_3d_model according to RTM)
260! - edited read and write sky view factors and CSF routines to account for
261!   the sub-domains which may not contain any of them
262!
263! 2967 2018-04-13 11:22:08Z raasch
264! bugfix: missing parallel cpp-directives added
265!
266! 2964 2018-04-12 16:04:03Z Giersch
267! Error message PA0491 has been introduced which could be previously found in
268! check_open. The variable numprocs_previous_run is only known in case of
269! initializing_actions == read_restart_data
270!
271! 2963 2018-04-12 14:47:44Z suehring
272! - Introduce index for vegetation/wall, pavement/green-wall and water/window
273!   surfaces, for clearer access of surface fraction, albedo, emissivity, etc. .
274! - Minor bugfix in initialization of albedo for window surfaces
275!
276! 2944 2018-04-03 16:20:18Z suehring
277! Fixed bad commit
278!
279! 2943 2018-04-03 16:17:10Z suehring
280! No read of nsurfl from SVF file since it is calculated in
281! radiation_interaction_init,
282! allocation of arrays in radiation_read_svf only if not yet allocated,
283! update of 2920 revision comment.
284!
285! 2932 2018-03-26 09:39:22Z maronga
286! renamed radiation_par to radiation_parameters
287!
288! 2930 2018-03-23 16:30:46Z suehring
289! Remove default surfaces from radiation model, does not make much sense to
290! apply radiation model without energy-balance solvers; Further, add check for
291! this.
292!
293! 2920 2018-03-22 11:22:01Z kanani
294! - Bugfix: Initialize pcbl array (=-1)
295! RTM version 2.0 (Jaroslav Resler, Pavel Krc, Mohamed Salim):
296! - new major version of radiation interactions
297! - substantially enhanced performance and scalability
298! - processing of direct and diffuse solar radiation separated from reflected
299!   radiation, removed virtual surfaces
300! - new type of sky discretization by azimuth and elevation angles
301! - diffuse radiation processed cumulatively using sky view factor
302! - used precalculated apparent solar positions for direct irradiance
303! - added new 2D raytracing process for processing whole vertical column at once
304!   to increase memory efficiency and decrease number of MPI RMA operations
305! - enabled limiting the number of view factors between surfaces by the distance
306!   and value
307! - fixing issues induced by transferring radiation interactions from
308!   urban_surface_mod to radiation_mod
309! - bugfixes and other minor enhancements
310!
311! 2906 2018-03-19 08:56:40Z Giersch
312! NAMELIST paramter read/write_svf_on_init have been removed, functions
313! check_open and close_file are used now for opening/closing files related to
314! svf data, adjusted unit number and error numbers
315!
316! 2894 2018-03-15 09:17:58Z Giersch
317! Calculations of the index range of the subdomain on file which overlaps with
318! the current subdomain are already done in read_restart_data_mod
319! radiation_read_restart_data was renamed to radiation_rrd_local and
320! radiation_last_actions was renamed to radiation_wrd_local, variable named
321! found has been introduced for checking if restart data was found, reading
322! of restart strings has been moved completely to read_restart_data_mod,
323! radiation_rrd_local is already inside the overlap loop programmed in
324! read_restart_data_mod, the marker *** end rad *** is not necessary anymore,
325! strings and their respective lengths are written out and read now in case of
326! restart runs to get rid of prescribed character lengths (Giersch)
327!
328! 2809 2018-02-15 09:55:58Z suehring
329! Bugfix for gfortran: Replace the function C_SIZEOF with STORAGE_SIZE
330!
331! 2753 2018-01-16 14:16:49Z suehring
332! Tile approach for spectral albedo implemented.
333!
334! 2746 2018-01-15 12:06:04Z suehring
335! Move flag plant canopy to modules
336!
337! 2724 2018-01-05 12:12:38Z maronga
338! Set default of average_radiation to .FALSE.
339!
340! 2723 2018-01-05 09:27:03Z maronga
341! Bugfix in calculation of rad_lw_out (clear-sky). First grid level was used
342! instead of the surface value
343!
344! 2718 2018-01-02 08:49:38Z maronga
345! Corrected "Former revisions" section
346!
347! 2707 2017-12-18 18:34:46Z suehring
348! Changes from last commit documented
349!
350! 2706 2017-12-18 18:33:49Z suehring
351! Bugfix, in average radiation case calculate exner function before using it.
352!
353! 2701 2017-12-15 15:40:50Z suehring
354! Changes from last commit documented
355!
356! 2698 2017-12-14 18:46:24Z suehring
357! Bugfix in get_topography_top_index
358!
359! 2696 2017-12-14 17:12:51Z kanani
360! - Change in file header (GPL part)
361! - Improved reading/writing of SVF from/to file (BM)
362! - Bugfixes concerning RRTMG as well as average_radiation options (M. Salim)
363! - Revised initialization of surface albedo and some minor bugfixes (MS)
364! - Update net radiation after running radiation interaction routine (MS)
365! - Revisions from M Salim included
366! - Adjustment to topography and surface structure (MS)
367! - Initialization of albedo and surface emissivity via input file (MS)
368! - albedo_pars extended (MS)
369!
370! 2604 2017-11-06 13:29:00Z schwenkel
371! bugfix for calculation of effective radius using morrison microphysics
372!
373! 2601 2017-11-02 16:22:46Z scharf
374! added emissivity to namelist
375!
376! 2575 2017-10-24 09:57:58Z maronga
377! Bugfix: calculation of shortwave and longwave albedos for RRTMG swapped
378!
379! 2547 2017-10-16 12:41:56Z schwenkel
380! extended by cloud_droplets option, minor bugfix and correct calculation of
381! cloud droplet number concentration
382!
383! 2544 2017-10-13 18:09:32Z maronga
384! Moved date and time quantitis to separate module date_and_time_mod
385!
386! 2512 2017-10-04 08:26:59Z raasch
387! upper bounds of cross section and 3d output changed from nx+1,ny+1 to nx,ny
388! no output of ghost layer data
389!
390! 2504 2017-09-27 10:36:13Z maronga
391! Updates pavement types and albedo parameters
392!
393! 2328 2017-08-03 12:34:22Z maronga
394! Emissivity can now be set individually for each pixel.
395! Albedo type can be inferred from land surface model.
396! Added default albedo type for bare soil
397!
398! 2318 2017-07-20 17:27:44Z suehring
399! Get topography top index via Function call
400!
401! 2317 2017-07-20 17:27:19Z suehring
402! Improved syntax layout
403!
404! 2298 2017-06-29 09:28:18Z raasch
405! type of write_binary changed from CHARACTER to LOGICAL
406!
407! 2296 2017-06-28 07:53:56Z maronga
408! Added output of rad_sw_out for radiation_scheme = 'constant'
409!
410! 2270 2017-06-09 12:18:47Z maronga
411! Numbering changed (2 timeseries removed)
412!
413! 2249 2017-06-06 13:58:01Z sward
414! Allow for RRTMG runs without humidity/cloud physics
415!
416! 2248 2017-06-06 13:52:54Z sward
417! Error no changed
418!
419! 2233 2017-05-30 18:08:54Z suehring
420!
421! 2232 2017-05-30 17:47:52Z suehring
422! Adjustments to new topography concept
423! Bugfix in read restart
424!
425! 2200 2017-04-11 11:37:51Z suehring
426! Bugfix in call of exchange_horiz_2d and read restart data
427!
428! 2163 2017-03-01 13:23:15Z schwenkel
429! Bugfix in radiation_check_data_output
430!
431! 2157 2017-02-22 15:10:35Z suehring
432! Bugfix in read_restart data
433!
434! 2011 2016-09-19 17:29:57Z kanani
435! Removed CALL of auxiliary SUBROUTINE get_usm_info,
436! flag urban_surface is now defined in module control_parameters.
437!
438! 2007 2016-08-24 15:47:17Z kanani
439! Added calculation of solar directional vector for new urban surface
440! model,
441! accounted for urban_surface model in radiation_check_parameters,
442! correction of comments for zenith angle.
443!
444! 2000 2016-08-20 18:09:15Z knoop
445! Forced header and separation lines into 80 columns
446!
447! 1976 2016-07-27 13:28:04Z maronga
448! Output of 2D/3D/masked data is now directly done within this module. The
449! radiation schemes have been simplified for better usability so that
450! rad_lw_in, rad_lw_out, rad_sw_in, and rad_sw_out are available independent of
451! the radiation code used.
452!
453! 1856 2016-04-13 12:56:17Z maronga
454! Bugfix: allocation of rad_lw_out for radiation_scheme = 'clear-sky'
455!
456! 1853 2016-04-11 09:00:35Z maronga
457! Added routine for radiation_scheme = constant.
458
459! 1849 2016-04-08 11:33:18Z hoffmann
460! Adapted for modularization of microphysics
461!
462! 1826 2016-04-07 12:01:39Z maronga
463! Further modularization.
464!
465! 1788 2016-03-10 11:01:04Z maronga
466! Added new albedo class for pavements / roads.
467!
468! 1783 2016-03-06 18:36:17Z raasch
469! palm-netcdf-module removed in order to avoid a circular module dependency,
470! netcdf-variables moved to netcdf-module, new routine netcdf_handle_error_rad
471! added
472!
473! 1757 2016-02-22 15:49:32Z maronga
474! Added parameter unscheduled_radiation_calls. Bugfix: interpolation of sounding
475! profiles for pressure and temperature above the LES domain.
476!
477! 1709 2015-11-04 14:47:01Z maronga
478! Bugfix: set initial value for rrtm_lwuflx_dt to zero, small formatting
479! corrections
480!
481! 1701 2015-11-02 07:43:04Z maronga
482! Bugfixes: wrong index for output of timeseries, setting of nz_snd_end
483!
484! 1691 2015-10-26 16:17:44Z maronga
485! Added option for spin-up runs without radiation (skip_time_do_radiation). Bugfix
486! in calculation of pressure profiles. Bugfix in calculation of trace gas profiles.
487! Added output of radiative heating rates.
488!
489! 1682 2015-10-07 23:56:08Z knoop
490! Code annotations made doxygen readable
491!
492! 1606 2015-06-29 10:43:37Z maronga
493! Added preprocessor directive __netcdf to allow for compiling without netCDF.
494! Note, however, that RRTMG cannot be used without netCDF.
495!
496! 1590 2015-05-08 13:56:27Z maronga
497! Bugfix: definition of character strings requires same length for all elements
498!
499! 1587 2015-05-04 14:19:01Z maronga
500! Added albedo class for snow
501!
502! 1585 2015-04-30 07:05:52Z maronga
503! Added support for RRTMG
504!
505! 1571 2015-03-12 16:12:49Z maronga
506! Added missing KIND attribute. Removed upper-case variable names
507!
508! 1551 2015-03-03 14:18:16Z maronga
509! Added support for data output. Various variables have been renamed. Added
510! interface for different radiation schemes (currently: clear-sky, constant, and
511! RRTM (not yet implemented).
512!
513! 1496 2014-12-02 17:25:50Z maronga
514! Initial revision
515!
516!
517! Description:
518! ------------
519!> Radiation models and interfaces
520!> @todo Replace dz(1) appropriatly to account for grid stretching
521!> @todo move variable definitions used in radiation_init only to the subroutine
522!>       as they are no longer required after initialization.
523!> @todo Output of full column vertical profiles used in RRTMG
524!> @todo Output of other rrtm arrays (such as volume mixing ratios)
525!> @todo Check for mis-used NINT() calls in raytrace_2d
526!>       RESULT: Original was correct (carefully verified formula), the change
527!>               to INT broke raytracing      -- P. Krc
528!> @todo Optimize radiation_tendency routines
529!>
530!> @note Many variables have a leading dummy dimension (0:0) in order to
531!>       match the assume-size shape expected by the RRTMG model.
532!------------------------------------------------------------------------------!
533 MODULE radiation_model_mod
534 
535    USE arrays_3d,                                                             &
536        ONLY:  dzw, hyp, nc, pt, p, q, ql, u, v, w, zu, zw, exner, d_exner
537
538    USE basic_constants_and_equations_mod,                                     &
539        ONLY:  c_p, g, lv_d_cp, l_v, pi, r_d, rho_l, solar_constant,      &
540               barometric_formula
541
542    USE calc_mean_profile_mod,                                                 &
543        ONLY:  calc_mean_profile
544
545    USE control_parameters,                                                    &
546        ONLY:  cloud_droplets, coupling_char, dz, dt_spinup, end_time,         &
547               humidity,                                                       &
548               initializing_actions, io_blocks, io_group,                      &
549               land_surface, large_scale_forcing,                              &
550               latitude, longitude, lsf_surf,                                  &
551               message_string, plant_canopy, pt_surface,                       &
552               rho_surface, simulated_time, spinup_time, surface_pressure,     &
553               time_since_reference_point, urban_surface, varnamelength
554
555    USE cpulog,                                                                &
556        ONLY:  cpu_log, log_point, log_point_s
557
558    USE grid_variables,                                                        &
559         ONLY:  ddx, ddy, dx, dy 
560
561    USE date_and_time_mod,                                                     &
562        ONLY:  calc_date_and_time, d_hours_day, d_seconds_hour, day_of_year,   &
563               d_seconds_year, day_of_year_init, time_utc_init, time_utc
564
565    USE indices,                                                               &
566        ONLY:  nnx, nny, nx, nxl, nxlg, nxr, nxrg, ny, nyn, nyng, nys, nysg,   &
567               nzb, nzt
568
569    USE, INTRINSIC :: iso_c_binding
570
571    USE kinds
572
573    USE bulk_cloud_model_mod,                                                  &
574        ONLY:  bulk_cloud_model, microphysics_morrison, na_init, nc_const, sigma_gc
575
576#if defined ( __netcdf )
577    USE NETCDF
578#endif
579
580    USE netcdf_data_input_mod,                                                 &
581        ONLY:  albedo_type_f, albedo_pars_f, building_type_f, pavement_type_f, &
582               vegetation_type_f, water_type_f
583
584    USE plant_canopy_model_mod,                                                &
585        ONLY:  lad_s, pc_heating_rate, pc_transpiration_rate, pc_latent_rate,  &
586               plant_canopy_transpiration, pcm_calc_transpiration_rate
587
588    USE pegrid
589
590#if defined ( __rrtmg )
591    USE parrrsw,                                                               &
592        ONLY:  naerec, nbndsw
593
594    USE parrrtm,                                                               &
595        ONLY:  nbndlw
596
597    USE rrtmg_lw_init,                                                         &
598        ONLY:  rrtmg_lw_ini
599
600    USE rrtmg_sw_init,                                                         &
601        ONLY:  rrtmg_sw_ini
602
603    USE rrtmg_lw_rad,                                                          &
604        ONLY:  rrtmg_lw
605
606    USE rrtmg_sw_rad,                                                          &
607        ONLY:  rrtmg_sw
608#endif
609    USE statistics,                                                            &
610        ONLY:  hom
611
612    USE surface_mod,                                                           &
613        ONLY:  get_topography_top_index, get_topography_top_index_ji,          &
614               ind_pav_green, ind_veg_wall, ind_wat_win,                       &
615               surf_lsm_h, surf_lsm_v, surf_type, surf_usm_h, surf_usm_v
616
617    IMPLICIT NONE
618
619    CHARACTER(10) :: radiation_scheme = 'clear-sky' ! 'constant', 'clear-sky', or 'rrtmg'
620
621!
622!-- Predefined Land surface classes (albedo_type) after Briegleb (1992)
623    CHARACTER(37), DIMENSION(0:33), PARAMETER :: albedo_type_name = (/      &
624                                   'user defined                         ', & !  0
625                                   'ocean                                ', & !  1
626                                   'mixed farming, tall grassland        ', & !  2
627                                   'tall/medium grassland                ', & !  3
628                                   'evergreen shrubland                  ', & !  4
629                                   'short grassland/meadow/shrubland     ', & !  5
630                                   'evergreen needleleaf forest          ', & !  6
631                                   'mixed deciduous evergreen forest     ', & !  7
632                                   'deciduous forest                     ', & !  8
633                                   'tropical evergreen broadleaved forest', & !  9
634                                   'medium/tall grassland/woodland       ', & ! 10
635                                   'desert, sandy                        ', & ! 11
636                                   'desert, rocky                        ', & ! 12
637                                   'tundra                               ', & ! 13
638                                   'land ice                             ', & ! 14
639                                   'sea ice                              ', & ! 15
640                                   'snow                                 ', & ! 16
641                                   'bare soil                            ', & ! 17
642                                   'asphalt/concrete mix                 ', & ! 18
643                                   'asphalt (asphalt concrete)           ', & ! 19
644                                   'concrete (Portland concrete)         ', & ! 20
645                                   'sett                                 ', & ! 21
646                                   'paving stones                        ', & ! 22
647                                   'cobblestone                          ', & ! 23
648                                   'metal                                ', & ! 24
649                                   'wood                                 ', & ! 25
650                                   'gravel                               ', & ! 26
651                                   'fine gravel                          ', & ! 27
652                                   'pebblestone                          ', & ! 28
653                                   'woodchips                            ', & ! 29
654                                   'tartan (sports)                      ', & ! 30
655                                   'artifical turf (sports)              ', & ! 31
656                                   'clay (sports)                        ', & ! 32
657                                   'building (dummy)                     '  & ! 33
658                                                         /)
659
660    REAL(wp), PARAMETER :: sigma_sb       = 5.67037321E-8_wp !< Stefan-Boltzmann constant
661
662    INTEGER(iwp) :: albedo_type  = 9999999, & !< Albedo surface type
663                    dots_rad     = 0          !< starting index for timeseries output
664
665    LOGICAL ::  unscheduled_radiation_calls = .TRUE., & !< flag parameter indicating whether additional calls of the radiation code are allowed
666                constant_albedo = .FALSE.,            & !< flag parameter indicating whether the albedo may change depending on zenith
667                force_radiation_call = .FALSE.,       & !< flag parameter for unscheduled radiation calls
668                lw_radiation = .TRUE.,                & !< flag parameter indicating whether longwave radiation shall be calculated
669                radiation = .FALSE.,                  & !< flag parameter indicating whether the radiation model is used
670                sun_up    = .TRUE.,                   & !< flag parameter indicating whether the sun is up or down
671                sw_radiation = .TRUE.,                & !< flag parameter indicating whether shortwave radiation shall be calculated
672                sun_direction = .FALSE.,              & !< flag parameter indicating whether solar direction shall be calculated
673                average_radiation = .FALSE.,          & !< flag to set the calculation of radiation averaging for the domain
674                radiation_interactions = .FALSE.,     & !< flag to activiate RTM (TRUE only if vertical urban/land surface and trees exist)
675                surface_reflections = .TRUE.,         & !< flag to switch the calculation of radiation interaction between surfaces.
676                                                        !< When it switched off, only the effect of buildings and trees shadow
677                                                        !< will be considered. However fewer SVFs are expected.
678                radiation_interactions_on = .TRUE.      !< namelist flag to force RTM activiation regardless to vertical urban/land surface and trees
679
680    REAL(wp) :: albedo = 9999999.9_wp,           & !< NAMELIST alpha
681                albedo_lw_dif = 9999999.9_wp,    & !< NAMELIST aldif
682                albedo_lw_dir = 9999999.9_wp,    & !< NAMELIST aldir
683                albedo_sw_dif = 9999999.9_wp,    & !< NAMELIST asdif
684                albedo_sw_dir = 9999999.9_wp,    & !< NAMELIST asdir
685                decl_1,                          & !< declination coef. 1
686                decl_2,                          & !< declination coef. 2
687                decl_3,                          & !< declination coef. 3
688                dt_radiation = 0.0_wp,           & !< radiation model timestep
689                emissivity = 9999999.9_wp,       & !< NAMELIST surface emissivity
690                lon = 0.0_wp,                    & !< longitude in radians
691                lat = 0.0_wp,                    & !< latitude in radians
692                net_radiation = 0.0_wp,          & !< net radiation at surface
693                skip_time_do_radiation = 0.0_wp, & !< Radiation model is not called before this time
694                sky_trans,                       & !< sky transmissivity
695                time_radiation = 0.0_wp            !< time since last call of radiation code
696
697
698    REAL(wp), DIMENSION(0:0) ::  zenith,         & !< cosine of solar zenith angle
699                                 sun_dir_lat,    & !< solar directional vector in latitudes
700                                 sun_dir_lon       !< solar directional vector in longitudes
701
702    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_net_av       !< average of net radiation (rad_net) at surface
703    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_lw_in_xy_av  !< average of incoming longwave radiation at surface
704    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_lw_out_xy_av !< average of outgoing longwave radiation at surface
705    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_sw_in_xy_av  !< average of incoming shortwave radiation at surface
706    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_sw_out_xy_av !< average of outgoing shortwave radiation at surface
707!
708!-- Land surface albedos for solar zenith angle of 60degree after Briegleb (1992)     
709!-- (shortwave, longwave, broadband):   sw,      lw,      bb,
710    REAL(wp), DIMENSION(0:2,1:33), PARAMETER :: albedo_pars = RESHAPE( (/& 
711                                   0.06_wp, 0.06_wp, 0.06_wp,            & !  1
712                                   0.09_wp, 0.28_wp, 0.19_wp,            & !  2
713                                   0.11_wp, 0.33_wp, 0.23_wp,            & !  3
714                                   0.11_wp, 0.33_wp, 0.23_wp,            & !  4
715                                   0.14_wp, 0.34_wp, 0.25_wp,            & !  5
716                                   0.06_wp, 0.22_wp, 0.14_wp,            & !  6
717                                   0.06_wp, 0.27_wp, 0.17_wp,            & !  7
718                                   0.06_wp, 0.31_wp, 0.19_wp,            & !  8
719                                   0.06_wp, 0.22_wp, 0.14_wp,            & !  9
720                                   0.06_wp, 0.28_wp, 0.18_wp,            & ! 10
721                                   0.35_wp, 0.51_wp, 0.43_wp,            & ! 11
722                                   0.24_wp, 0.40_wp, 0.32_wp,            & ! 12
723                                   0.10_wp, 0.27_wp, 0.19_wp,            & ! 13
724                                   0.90_wp, 0.65_wp, 0.77_wp,            & ! 14
725                                   0.90_wp, 0.65_wp, 0.77_wp,            & ! 15
726                                   0.95_wp, 0.70_wp, 0.82_wp,            & ! 16
727                                   0.08_wp, 0.08_wp, 0.08_wp,            & ! 17
728                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 18
729                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 19
730                                   0.30_wp, 0.30_wp, 0.30_wp,            & ! 20
731                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 21
732                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 22
733                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 23
734                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 24
735                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 25
736                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 26
737                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 27
738                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 28
739                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 29
740                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 30
741                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 31
742                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 32
743                                   0.17_wp, 0.17_wp, 0.17_wp             & ! 33
744                                 /), (/ 3, 33 /) )
745
746    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE, TARGET :: &
747                        rad_lw_cs_hr,                  & !< longwave clear sky radiation heating rate (K/s)
748                        rad_lw_cs_hr_av,               & !< average of rad_lw_cs_hr
749                        rad_lw_hr,                     & !< longwave radiation heating rate (K/s)
750                        rad_lw_hr_av,                  & !< average of rad_sw_hr
751                        rad_lw_in,                     & !< incoming longwave radiation (W/m2)
752                        rad_lw_in_av,                  & !< average of rad_lw_in
753                        rad_lw_out,                    & !< outgoing longwave radiation (W/m2)
754                        rad_lw_out_av,                 & !< average of rad_lw_out
755                        rad_sw_cs_hr,                  & !< shortwave clear sky radiation heating rate (K/s)
756                        rad_sw_cs_hr_av,               & !< average of rad_sw_cs_hr
757                        rad_sw_hr,                     & !< shortwave radiation heating rate (K/s)
758                        rad_sw_hr_av,                  & !< average of rad_sw_hr
759                        rad_sw_in,                     & !< incoming shortwave radiation (W/m2)
760                        rad_sw_in_av,                  & !< average of rad_sw_in
761                        rad_sw_out,                    & !< outgoing shortwave radiation (W/m2)
762                        rad_sw_out_av                    !< average of rad_sw_out
763
764
765!
766!-- Variables and parameters used in RRTMG only
767#if defined ( __rrtmg )
768    CHARACTER(LEN=12) :: rrtm_input_file = "RAD_SND_DATA" !< name of the NetCDF input file (sounding data)
769
770
771!
772!-- Flag parameters for RRTMGS (should not be changed)
773    INTEGER(iwp), PARAMETER :: rrtm_idrv     = 1, & !< flag for longwave upward flux calculation option (0,1)
774                               rrtm_inflglw  = 2, & !< flag for lw cloud optical properties (0,1,2)
775                               rrtm_iceflglw = 0, & !< flag for lw ice particle specifications (0,1,2,3)
776                               rrtm_liqflglw = 1, & !< flag for lw liquid droplet specifications
777                               rrtm_inflgsw  = 2, & !< flag for sw cloud optical properties (0,1,2)
778                               rrtm_iceflgsw = 0, & !< flag for sw ice particle specifications (0,1,2,3)
779                               rrtm_liqflgsw = 1    !< flag for sw liquid droplet specifications
780
781!
782!-- The following variables should be only changed with care, as this will
783!-- require further setting of some variables, which is currently not
784!-- implemented (aerosols, ice phase).
785    INTEGER(iwp) :: nzt_rad,           & !< upper vertical limit for radiation calculations
786                    rrtm_icld = 0,     & !< cloud flag (0: clear sky column, 1: cloudy column)
787                    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)
788
789    INTEGER(iwp) :: nc_stat !< local variable for storin the result of netCDF calls for error message handling
790
791    LOGICAL :: snd_exists = .FALSE.      !< flag parameter to check whether a user-defined input files exists
792
793    REAL(wp), PARAMETER :: mol_mass_air_d_wv = 1.607793_wp !< molecular weight dry air / water vapor
794
795    REAL(wp), DIMENSION(:), ALLOCATABLE :: hyp_snd,     & !< hypostatic pressure from sounding data (hPa)
796                                           rrtm_tsfc,   & !< dummy array for storing surface temperature
797                                           t_snd          !< actual temperature from sounding data (hPa)
798
799    REAL(wp), DIMENSION(:,:), ALLOCATABLE :: rrtm_ccl4vmr,   & !< CCL4 volume mixing ratio (g/mol)
800                                             rrtm_cfc11vmr,  & !< CFC11 volume mixing ratio (g/mol)
801                                             rrtm_cfc12vmr,  & !< CFC12 volume mixing ratio (g/mol)
802                                             rrtm_cfc22vmr,  & !< CFC22 volume mixing ratio (g/mol)
803                                             rrtm_ch4vmr,    & !< CH4 volume mixing ratio
804                                             rrtm_cicewp,    & !< in-cloud ice water path (g/m2)
805                                             rrtm_cldfr,     & !< cloud fraction (0,1)
806                                             rrtm_cliqwp,    & !< in-cloud liquid water path (g/m2)
807                                             rrtm_co2vmr,    & !< CO2 volume mixing ratio (g/mol)
808                                             rrtm_emis,      & !< surface emissivity (0-1) 
809                                             rrtm_h2ovmr,    & !< H2O volume mixing ratio
810                                             rrtm_n2ovmr,    & !< N2O volume mixing ratio
811                                             rrtm_o2vmr,     & !< O2 volume mixing ratio
812                                             rrtm_o3vmr,     & !< O3 volume mixing ratio
813                                             rrtm_play,      & !< pressure layers (hPa, zu-grid)
814                                             rrtm_plev,      & !< pressure layers (hPa, zw-grid)
815                                             rrtm_reice,     & !< cloud ice effective radius (microns)
816                                             rrtm_reliq,     & !< cloud water drop effective radius (microns)
817                                             rrtm_tlay,      & !< actual temperature (K, zu-grid)
818                                             rrtm_tlev,      & !< actual temperature (K, zw-grid)
819                                             rrtm_lwdflx,    & !< RRTM output of incoming longwave radiation flux (W/m2)
820                                             rrtm_lwdflxc,   & !< RRTM output of outgoing clear sky longwave radiation flux (W/m2)
821                                             rrtm_lwuflx,    & !< RRTM output of outgoing longwave radiation flux (W/m2)
822                                             rrtm_lwuflxc,   & !< RRTM output of incoming clear sky longwave radiation flux (W/m2)
823                                             rrtm_lwuflx_dt, & !< RRTM output of incoming clear sky longwave radiation flux (W/m2)
824                                             rrtm_lwuflxc_dt,& !< RRTM output of outgoing clear sky longwave radiation flux (W/m2)
825                                             rrtm_lwhr,      & !< RRTM output of longwave radiation heating rate (K/d)
826                                             rrtm_lwhrc,     & !< RRTM output of incoming longwave clear sky radiation heating rate (K/d)
827                                             rrtm_swdflx,    & !< RRTM output of incoming shortwave radiation flux (W/m2)
828                                             rrtm_swdflxc,   & !< RRTM output of outgoing clear sky shortwave radiation flux (W/m2)
829                                             rrtm_swuflx,    & !< RRTM output of outgoing shortwave radiation flux (W/m2)
830                                             rrtm_swuflxc,   & !< RRTM output of incoming clear sky shortwave radiation flux (W/m2)
831                                             rrtm_swhr,      & !< RRTM output of shortwave radiation heating rate (K/d)
832                                             rrtm_swhrc,     & !< RRTM output of incoming shortwave clear sky radiation heating rate (K/d)
833                                             rrtm_dirdflux,  & !< RRTM output of incoming direct shortwave (W/m2)
834                                             rrtm_difdflux     !< RRTM output of incoming diffuse shortwave (W/m2)
835
836    REAL(wp), DIMENSION(1) ::                rrtm_aldif,     & !< surface albedo for longwave diffuse radiation
837                                             rrtm_aldir,     & !< surface albedo for longwave direct radiation
838                                             rrtm_asdif,     & !< surface albedo for shortwave diffuse radiation
839                                             rrtm_asdir        !< surface albedo for shortwave direct radiation
840
841!
842!-- Definition of arrays that are currently not used for calling RRTMG (due to setting of flag parameters)
843    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::  rad_lw_cs_in,   & !< incoming clear sky longwave radiation (W/m2) (not used)
844                                                rad_lw_cs_out,  & !< outgoing clear sky longwave radiation (W/m2) (not used)
845                                                rad_sw_cs_in,   & !< incoming clear sky shortwave radiation (W/m2) (not used)
846                                                rad_sw_cs_out,  & !< outgoing clear sky shortwave radiation (W/m2) (not used)
847                                                rrtm_lw_tauaer, & !< lw aerosol optical depth
848                                                rrtm_lw_taucld, & !< lw in-cloud optical depth
849                                                rrtm_sw_taucld, & !< sw in-cloud optical depth
850                                                rrtm_sw_ssacld, & !< sw in-cloud single scattering albedo
851                                                rrtm_sw_asmcld, & !< sw in-cloud asymmetry parameter
852                                                rrtm_sw_fsfcld, & !< sw in-cloud forward scattering fraction
853                                                rrtm_sw_tauaer, & !< sw aerosol optical depth
854                                                rrtm_sw_ssaaer, & !< sw aerosol single scattering albedo
855                                                rrtm_sw_asmaer, & !< sw aerosol asymmetry parameter
856                                                rrtm_sw_ecaer     !< sw aerosol optical detph at 0.55 microns (rrtm_iaer = 6 only)
857
858#endif
859!
860!-- Parameters of urban and land surface models
861    INTEGER(iwp)                                   ::  nzu                                !< number of layers of urban surface (will be calculated)
862    INTEGER(iwp)                                   ::  nzp                                !< number of layers of plant canopy (will be calculated)
863    INTEGER(iwp)                                   ::  nzub,nzut                          !< bottom and top layer of urban surface (will be calculated)
864    INTEGER(iwp)                                   ::  nzpt                               !< top layer of plant canopy (will be calculated)
865!-- parameters of urban and land surface models
866    INTEGER(iwp), PARAMETER                        ::  nzut_free = 3                      !< number of free layers above top of of topography
867    INTEGER(iwp), PARAMETER                        ::  ndsvf = 2                          !< number of dimensions of real values in SVF
868    INTEGER(iwp), PARAMETER                        ::  idsvf = 2                          !< number of dimensions of integer values in SVF
869    INTEGER(iwp), PARAMETER                        ::  ndcsf = 1                          !< number of dimensions of real values in CSF
870    INTEGER(iwp), PARAMETER                        ::  idcsf = 2                          !< number of dimensions of integer values in CSF
871    INTEGER(iwp), PARAMETER                        ::  kdcsf = 4                          !< number of dimensions of integer values in CSF calculation array
872    INTEGER(iwp), PARAMETER                        ::  id = 1                             !< position of d-index in surfl and surf
873    INTEGER(iwp), PARAMETER                        ::  iz = 2                             !< position of k-index in surfl and surf
874    INTEGER(iwp), PARAMETER                        ::  iy = 3                             !< position of j-index in surfl and surf
875    INTEGER(iwp), PARAMETER                        ::  ix = 4                             !< position of i-index in surfl and surf
876
877    INTEGER(iwp), PARAMETER                        ::  nsurf_type = 10                    !< number of surf types incl. phys.(land+urban) & (atm.,sky,boundary) surfaces - 1
878
879    INTEGER(iwp), PARAMETER                        ::  iup_u    = 0                       !< 0 - index of urban upward surface (ground or roof)
880    INTEGER(iwp), PARAMETER                        ::  idown_u  = 1                       !< 1 - index of urban downward surface (overhanging)
881    INTEGER(iwp), PARAMETER                        ::  inorth_u = 2                       !< 2 - index of urban northward facing wall
882    INTEGER(iwp), PARAMETER                        ::  isouth_u = 3                       !< 3 - index of urban southward facing wall
883    INTEGER(iwp), PARAMETER                        ::  ieast_u  = 4                       !< 4 - index of urban eastward facing wall
884    INTEGER(iwp), PARAMETER                        ::  iwest_u  = 5                       !< 5 - index of urban westward facing wall
885
886    INTEGER(iwp), PARAMETER                        ::  iup_l    = 6                       !< 6 - index of land upward surface (ground or roof)
887    INTEGER(iwp), PARAMETER                        ::  inorth_l = 7                       !< 7 - index of land northward facing wall
888    INTEGER(iwp), PARAMETER                        ::  isouth_l = 8                       !< 8 - index of land southward facing wall
889    INTEGER(iwp), PARAMETER                        ::  ieast_l  = 9                       !< 9 - index of land eastward facing wall
890    INTEGER(iwp), PARAMETER                        ::  iwest_l  = 10                      !< 10- index of land westward facing wall
891
892    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  idir = (/0, 0,0, 0,1,-1,0,0, 0,1,-1/)   !< surface normal direction x indices
893    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  jdir = (/0, 0,1,-1,0, 0,0,1,-1,0, 0/)   !< surface normal direction y indices
894    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  kdir = (/1,-1,0, 0,0, 0,1,0, 0,0, 0/)   !< surface normal direction z indices
895    REAL(wp),     DIMENSION(0:nsurf_type)          :: facearea                            !< area of single face in respective
896                                                                                          !< direction (will be calc'd)
897
898
899!-- indices and sizes of urban and land surface models
900    INTEGER(iwp)                                   ::  startland        !< start index of block of land and roof surfaces
901    INTEGER(iwp)                                   ::  endland          !< end index of block of land and roof surfaces
902    INTEGER(iwp)                                   ::  nlands           !< number of land and roof surfaces in local processor
903    INTEGER(iwp)                                   ::  startwall        !< start index of block of wall surfaces
904    INTEGER(iwp)                                   ::  endwall          !< end index of block of wall surfaces
905    INTEGER(iwp)                                   ::  nwalls           !< number of wall surfaces in local processor
906
907!-- indices needed for RTM netcdf output subroutines
908    INTEGER(iwp), PARAMETER                        :: nd = 5
909    CHARACTER(LEN=6), DIMENSION(0:nd-1), PARAMETER :: dirname = (/ '_roof ', '_south', '_north', '_west ', '_east ' /)
910    INTEGER(iwp), DIMENSION(0:nd-1), PARAMETER     :: dirint_u = (/ iup_u, isouth_u, inorth_u, iwest_u, ieast_u /)
911    INTEGER(iwp), DIMENSION(0:nd-1), PARAMETER     :: dirint_l = (/ iup_l, isouth_l, inorth_l, iwest_l, ieast_l /)
912    INTEGER(iwp), DIMENSION(0:nd-1)                :: dirstart
913    INTEGER(iwp), DIMENSION(0:nd-1)                :: dirend
914
915!-- indices and sizes of urban and land surface models
916    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surfl_l          !< coordinates of i-th local surface in local grid - surfl[:,k] = [d, z, y, x]
917    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surf_l           !< coordinates of i-th surface in grid - surf[:,k] = [d, z, y, x]
918    INTEGER(iwp), DIMENSION(:,:), POINTER          ::  surfl            !< coordinates of i-th local surface in local grid - surfl[:,k] = [d, z, y, x]
919    INTEGER(iwp), DIMENSION(:,:), POINTER          ::  surf             !< coordinates of i-th surface in grid - surf[:,k] = [d, z, y, x]
920    INTEGER(iwp)                                   ::  nsurfl           !< number of all surfaces in local processor
921    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  nsurfs           !< array of number of all surfaces in individual processors
922    INTEGER(iwp)                                   ::  nsurf            !< global number of surfaces in index array of surfaces (nsurf = proc nsurfs)
923    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surfstart        !< starts of blocks of surfaces for individual processors in array surf (indexed from 1)
924                                                                        !< respective block for particular processor is surfstart[iproc+1]+1 : surfstart[iproc+1]+nsurfs[iproc+1]
925
926!-- block variables needed for calculation of the plant canopy model inside the urban surface model
927    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pct              !< top layer of the plant canopy
928    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pch              !< heights of the plant canopy
929    INTEGER(iwp)                                   ::  npcbl = 0        !< number of the plant canopy gridboxes in local processor
930    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pcbl             !< k,j,i coordinates of l-th local plant canopy box pcbl[:,l] = [k, j, i]
931    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinsw          !< array of absorbed sw radiation for local plant canopy box
932    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdir       !< array of absorbed direct sw radiation for local plant canopy box
933    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdif       !< array of absorbed diffusion sw radiation for local plant canopy box
934    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinlw          !< array of absorbed lw radiation for local plant canopy box
935
936!-- configuration parameters (they can be setup in PALM config)
937    LOGICAL                                        ::  raytrace_mpi_rma = .TRUE.          !< use MPI RMA to access LAD and gridsurf from remote processes during raytracing
938    LOGICAL                                        ::  rad_angular_discretization = .TRUE.!< whether to use fixed resolution discretization of view factors for
939                                                                                          !< reflected radiation (as opposed to all mutually visible pairs)
940    LOGICAL                                        ::  plant_lw_interact = .TRUE.         !< whether plant canopy interacts with LW radiation (in addition to SW)
941    INTEGER(iwp)                                   ::  mrt_nlevels = 0                    !< number of vertical boxes above surface for which to calculate MRT
942    LOGICAL                                        ::  mrt_skip_roof = .TRUE.             !< do not calculate MRT above roof surfaces
943    LOGICAL                                        ::  mrt_include_sw = .TRUE.            !< should MRT calculation include SW radiation as well?
944    LOGICAL                                        ::  mrt_geom_human = .TRUE.            !< MRT direction weights simulate human body instead of a sphere
945    INTEGER(iwp)                                   ::  nrefsteps = 3                      !< number of reflection steps to perform
946    REAL(wp), PARAMETER                            ::  ext_coef = 0.6_wp                  !< extinction coefficient (a.k.a. alpha)
947    INTEGER(iwp), PARAMETER                        ::  rad_version_len = 10               !< length of identification string of rad version
948    CHARACTER(rad_version_len), PARAMETER          ::  rad_version = 'RAD v. 3.0'         !< identification of version of binary svf and restart files
949    INTEGER(iwp)                                   ::  raytrace_discrete_elevs = 40       !< number of discretization steps for elevation (nadir to zenith)
950    INTEGER(iwp)                                   ::  raytrace_discrete_azims = 80       !< number of discretization steps for azimuth (out of 360 degrees)
951    REAL(wp)                                       ::  max_raytracing_dist = -999.0_wp    !< maximum distance for raytracing (in metres)
952    REAL(wp)                                       ::  min_irrf_value = 1e-6_wp           !< minimum potential irradiance factor value for raytracing
953    REAL(wp), DIMENSION(1:30)                      ::  svfnorm_report_thresh = 1e21_wp    !< thresholds of SVF normalization values to report
954    INTEGER(iwp)                                   ::  svfnorm_report_num                 !< number of SVF normalization thresholds to report
955
956!-- radiation related arrays to be used in radiation_interaction routine
957    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_sw_in_dir    !< direct sw radiation
958    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_sw_in_diff   !< diffusion sw radiation
959    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_lw_in_diff   !< diffusion lw radiation
960
961!-- parameters required for RRTMG lower boundary condition
962    REAL(wp)                   :: albedo_urb      !< albedo value retuned to RRTMG boundary cond.
963    REAL(wp)                   :: emissivity_urb  !< emissivity value retuned to RRTMG boundary cond.
964    REAL(wp)                   :: t_rad_urb       !< temperature value retuned to RRTMG boundary cond.
965
966!-- type for calculation of svf
967    TYPE t_svf
968        INTEGER(iwp)                               :: isurflt           !<
969        INTEGER(iwp)                               :: isurfs            !<
970        REAL(wp)                                   :: rsvf              !<
971        REAL(wp)                                   :: rtransp           !<
972    END TYPE
973
974!-- type for calculation of csf
975    TYPE t_csf
976        INTEGER(iwp)                               :: ip                !<
977        INTEGER(iwp)                               :: itx               !<
978        INTEGER(iwp)                               :: ity               !<
979        INTEGER(iwp)                               :: itz               !<
980        INTEGER(iwp)                               :: isurfs            !< Idx of source face / -1 for sky
981        REAL(wp)                                   :: rcvf              !< Canopy view factor for faces /
982                                                                        !< canopy sink factor for sky (-1)
983    END TYPE
984
985!-- arrays storing the values of USM
986    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  svfsurf          !< svfsurf[:,isvf] = index of target and source surface for svf[isvf]
987    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  svf              !< array of shape view factors+direct irradiation factors for local surfaces
988    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfins          !< array of sw radiation falling to local surface after i-th reflection
989    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinl          !< array of lw radiation for local surface after i-th reflection
990
991    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  skyvf            !< array of sky view factor for each local surface
992    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  skyvft           !< array of sky view factor including transparency for each local surface
993    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsitrans         !< dsidir[isvfl,i] = path transmittance of i-th
994                                                                        !< direction of direct solar irradiance per target surface
995    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsitransc        !< dtto per plant canopy box
996    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsidir           !< dsidir[:,i] = unit vector of i-th
997                                                                        !< direction of direct solar irradiance
998    INTEGER(iwp)                                   ::  ndsidir          !< number of apparent solar directions used
999    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  dsidir_rev       !< dsidir_rev[ielev,iazim] = i for dsidir or -1 if not present
1000
1001    INTEGER(iwp)                                   ::  nmrtbl           !< No. of local grid boxes for which MRT is calculated
1002    INTEGER(iwp)                                   ::  nmrtf            !< number of MRT factors for local processor
1003    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  mrtbl            !< coordinates of i-th local MRT box - surfl[:,i] = [z, y, x]
1004    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  mrtfsurf         !< mrtfsurf[:,imrtf] = index of target MRT box and source surface for mrtf[imrtf]
1005    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtf             !< array of MRT factors for each local MRT box
1006    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtft            !< array of MRT factors including transparency for each local MRT box
1007    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtsky           !< array of sky view factor for each local MRT box
1008    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtskyt          !< array of sky view factor including transparency for each local MRT box
1009    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  mrtdsit          !< array of direct solar transparencies for each local MRT box
1010    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinsw          !< mean SW radiant flux for each MRT box
1011    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinlw          !< mean LW radiant flux for each MRT box
1012    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrt              !< mean radiant temperature for each MRT box
1013    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinsw_av       !< time average mean SW radiant flux for each MRT box
1014    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinlw_av       !< time average mean LW radiant flux for each MRT box
1015    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrt_av           !< time average mean radiant temperature for each MRT box
1016
1017    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinsw         !< array of sw radiation falling to local surface including radiation from reflections
1018    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlw         !< array of lw radiation falling to local surface including radiation from reflections
1019    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdir      !< array of direct sw radiation falling to local surface
1020    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdif      !< array of diffuse sw radiation from sky and model boundary falling to local surface
1021    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwdif      !< array of diffuse lw radiation from sky and model boundary falling to local surface
1022   
1023                                                                        !< Outward radiation is only valid for nonvirtual surfaces
1024    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsl        !< array of reflected sw radiation for local surface in i-th reflection
1025    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutll        !< array of reflected + emitted lw radiation for local surface in i-th reflection
1026    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfouts         !< array of reflected sw radiation for all surfaces in i-th reflection
1027    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutl         !< array of reflected + emitted lw radiation for all surfaces in i-th reflection
1028    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlg         !< global array of incoming lw radiation from plant canopy
1029    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsw        !< array of total sw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1030    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutlw        !< array of total lw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1031    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfemitlwl      !< array of emitted lw radiation for local surface used to calculate effective surface temperature for radiation model
1032
1033!-- block variables needed for calculation of the plant canopy model inside the urban surface model
1034    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  csfsurf          !< csfsurf[:,icsf] = index of target surface and csf grid index for csf[icsf]
1035    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  csf              !< array of plant canopy sink fators + direct irradiation factors (transparency)
1036    REAL(wp), DIMENSION(:,:,:), POINTER            ::  sub_lad          !< subset of lad_s within urban surface, transformed to plain Z coordinate
1037    REAL(wp), DIMENSION(:), POINTER                ::  sub_lad_g        !< sub_lad globalized (used to avoid MPI RMA calls in raytracing)
1038    REAL(wp)                                       ::  prototype_lad    !< prototype leaf area density for computing effective optical depth
1039    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  nzterr, plantt   !< temporary global arrays for raytracing
1040    INTEGER(iwp)                                   ::  plantt_max
1041
1042!-- arrays and variables for calculation of svf and csf
1043    TYPE(t_svf), DIMENSION(:), POINTER             ::  asvf             !< pointer to growing svc array
1044    TYPE(t_csf), DIMENSION(:), POINTER             ::  acsf             !< pointer to growing csf array
1045    TYPE(t_svf), DIMENSION(:), POINTER             ::  amrtf            !< pointer to growing mrtf array
1046    TYPE(t_svf), DIMENSION(:), ALLOCATABLE, TARGET ::  asvf1, asvf2     !< realizations of svf array
1047    TYPE(t_csf), DIMENSION(:), ALLOCATABLE, TARGET ::  acsf1, acsf2     !< realizations of csf array
1048    TYPE(t_svf), DIMENSION(:), ALLOCATABLE, TARGET ::  amrtf1, amrtf2   !< realizations of mftf array
1049    INTEGER(iwp)                                   ::  nsvfla           !< dimmension of array allocated for storage of svf in local processor
1050    INTEGER(iwp)                                   ::  ncsfla           !< dimmension of array allocated for storage of csf in local processor
1051    INTEGER(iwp)                                   ::  nmrtfa           !< dimmension of array allocated for storage of mrt
1052    INTEGER(iwp)                                   ::  msvf, mcsf, mmrtf!< mod for swapping the growing array
1053    INTEGER(iwp), PARAMETER                        ::  gasize = 100000  !< initial size of growing arrays
1054    REAL(wp), PARAMETER                            ::  grow_factor = 1.4_wp !< growth factor of growing arrays
1055    INTEGER(iwp)                                   ::  nsvfl            !< number of svf for local processor
1056    INTEGER(iwp)                                   ::  ncsfl            !< no. of csf in local processor
1057                                                                        !< needed only during calc_svf but must be here because it is
1058                                                                        !< shared between subroutines calc_svf and raytrace
1059    INTEGER(iwp), DIMENSION(:,:,:,:), POINTER      ::  gridsurf         !< reverse index of local surfl[d,k,j,i] (for case rad_angular_discretization)
1060    INTEGER(iwp), DIMENSION(:,:,:), ALLOCATABLE    ::  gridpcbl         !< reverse index of local pcbl[k,j,i]
1061    INTEGER(iwp), PARAMETER                        ::  nsurf_type_u = 6 !< number of urban surf types (used in gridsurf)
1062
1063!-- temporary arrays for calculation of csf in raytracing
1064    INTEGER(iwp)                                   ::  maxboxesg        !< max number of boxes ray can cross in the domain
1065    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  boxes            !< coordinates of gridboxes being crossed by ray
1066    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  crlens           !< array of crossing lengths of ray for particular grid boxes
1067    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  lad_ip           !< array of numbers of process where lad is stored
1068#if defined( __parallel )
1069    INTEGER(kind=MPI_ADDRESS_KIND), &
1070                  DIMENSION(:), ALLOCATABLE        ::  lad_disp         !< array of displaycements of lad in local array of proc lad_ip
1071    INTEGER(iwp)                                   ::  win_lad          !< MPI RMA window for leaf area density
1072    INTEGER(iwp)                                   ::  win_gridsurf     !< MPI RMA window for reverse grid surface index
1073#endif
1074    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  lad_s_ray        !< array of received lad_s for appropriate gridboxes crossed by ray
1075    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  target_surfl
1076    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  rt2_track
1077    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rt2_track_lad
1078    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  rt2_track_dist
1079    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  rt2_dist
1080
1081!-- arrays for time averages
1082    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfradnet_av    !< average of net radiation to local surface including radiation from reflections
1083    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinsw_av      !< average of sw radiation falling to local surface including radiation from reflections
1084    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlw_av      !< average of lw radiation falling to local surface including radiation from reflections
1085    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdir_av   !< average of direct sw radiation falling to local surface
1086    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdif_av   !< average of diffuse sw radiation from sky and model boundary falling to local surface
1087    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwdif_av   !< average of diffuse lw radiation from sky and model boundary falling to local surface
1088    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswref_av   !< average of sw radiation falling to surface from reflections
1089    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwref_av   !< average of lw radiation falling to surface from reflections
1090    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsw_av     !< average of total sw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1091    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutlw_av     !< average of total lw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1092    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfins_av       !< average of array of residua of sw radiation absorbed in surface after last reflection
1093    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinl_av       !< average of array of residua of lw radiation absorbed in surface after last reflection
1094    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinlw_av       !< Average of pcbinlw
1095    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinsw_av       !< Average of pcbinsw
1096    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdir_av    !< Average of pcbinswdir
1097    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdif_av    !< Average of pcbinswdif
1098    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswref_av    !< Average of pcbinswref
1099
1100
1101!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1102!-- Energy balance variables
1103!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1104!-- parameters of the land, roof and wall surfaces
1105    REAL(wp), DIMENSION(:), ALLOCATABLE            :: albedo_surf        !< albedo of the surface
1106    REAL(wp), DIMENSION(:), ALLOCATABLE            :: emiss_surf         !< emissivity of the wall surface
1107
1108
1109    INTERFACE radiation_check_data_output
1110       MODULE PROCEDURE radiation_check_data_output
1111    END INTERFACE radiation_check_data_output
1112
1113    INTERFACE radiation_check_data_output_pr
1114       MODULE PROCEDURE radiation_check_data_output_pr
1115    END INTERFACE radiation_check_data_output_pr
1116 
1117    INTERFACE radiation_check_parameters
1118       MODULE PROCEDURE radiation_check_parameters
1119    END INTERFACE radiation_check_parameters
1120 
1121    INTERFACE radiation_clearsky
1122       MODULE PROCEDURE radiation_clearsky
1123    END INTERFACE radiation_clearsky
1124 
1125    INTERFACE radiation_constant
1126       MODULE PROCEDURE radiation_constant
1127    END INTERFACE radiation_constant
1128 
1129    INTERFACE radiation_control
1130       MODULE PROCEDURE radiation_control
1131    END INTERFACE radiation_control
1132
1133    INTERFACE radiation_3d_data_averaging
1134       MODULE PROCEDURE radiation_3d_data_averaging
1135    END INTERFACE radiation_3d_data_averaging
1136
1137    INTERFACE radiation_data_output_2d
1138       MODULE PROCEDURE radiation_data_output_2d
1139    END INTERFACE radiation_data_output_2d
1140
1141    INTERFACE radiation_data_output_3d
1142       MODULE PROCEDURE radiation_data_output_3d
1143    END INTERFACE radiation_data_output_3d
1144
1145    INTERFACE radiation_data_output_mask
1146       MODULE PROCEDURE radiation_data_output_mask
1147    END INTERFACE radiation_data_output_mask
1148
1149    INTERFACE radiation_define_netcdf_grid
1150       MODULE PROCEDURE radiation_define_netcdf_grid
1151    END INTERFACE radiation_define_netcdf_grid
1152
1153    INTERFACE radiation_header
1154       MODULE PROCEDURE radiation_header
1155    END INTERFACE radiation_header 
1156 
1157    INTERFACE radiation_init
1158       MODULE PROCEDURE radiation_init
1159    END INTERFACE radiation_init
1160
1161    INTERFACE radiation_parin
1162       MODULE PROCEDURE radiation_parin
1163    END INTERFACE radiation_parin
1164   
1165    INTERFACE radiation_rrtmg
1166       MODULE PROCEDURE radiation_rrtmg
1167    END INTERFACE radiation_rrtmg
1168
1169    INTERFACE radiation_tendency
1170       MODULE PROCEDURE radiation_tendency
1171       MODULE PROCEDURE radiation_tendency_ij
1172    END INTERFACE radiation_tendency
1173
1174    INTERFACE radiation_rrd_local
1175       MODULE PROCEDURE radiation_rrd_local
1176    END INTERFACE radiation_rrd_local
1177
1178    INTERFACE radiation_wrd_local
1179       MODULE PROCEDURE radiation_wrd_local
1180    END INTERFACE radiation_wrd_local
1181
1182    INTERFACE radiation_interaction
1183       MODULE PROCEDURE radiation_interaction
1184    END INTERFACE radiation_interaction
1185
1186    INTERFACE radiation_interaction_init
1187       MODULE PROCEDURE radiation_interaction_init
1188    END INTERFACE radiation_interaction_init
1189 
1190    INTERFACE radiation_presimulate_solar_pos
1191       MODULE PROCEDURE radiation_presimulate_solar_pos
1192    END INTERFACE radiation_presimulate_solar_pos
1193
1194    INTERFACE radiation_radflux_gridbox
1195       MODULE PROCEDURE radiation_radflux_gridbox
1196    END INTERFACE radiation_radflux_gridbox
1197
1198    INTERFACE radiation_calc_svf
1199       MODULE PROCEDURE radiation_calc_svf
1200    END INTERFACE radiation_calc_svf
1201
1202    INTERFACE radiation_write_svf
1203       MODULE PROCEDURE radiation_write_svf
1204    END INTERFACE radiation_write_svf
1205
1206    INTERFACE radiation_read_svf
1207       MODULE PROCEDURE radiation_read_svf
1208    END INTERFACE radiation_read_svf
1209
1210
1211    SAVE
1212
1213    PRIVATE
1214
1215!
1216!-- Public functions / NEEDS SORTING
1217    PUBLIC radiation_check_data_output, radiation_check_data_output_pr,        &
1218           radiation_check_parameters, radiation_control,                      &
1219           radiation_header, radiation_init, radiation_parin,                  &
1220           radiation_3d_data_averaging, radiation_tendency,                    &
1221           radiation_data_output_2d, radiation_data_output_3d,                 &
1222           radiation_define_netcdf_grid, radiation_wrd_local,                  &
1223           radiation_rrd_local, radiation_data_output_mask,                    &
1224           radiation_radflux_gridbox, radiation_calc_svf, radiation_write_svf, &
1225           radiation_interaction, radiation_interaction_init,                  &
1226           radiation_read_svf, radiation_presimulate_solar_pos
1227           
1228
1229   
1230!
1231!-- Public variables and constants / NEEDS SORTING
1232    PUBLIC albedo, albedo_type, decl_1, decl_2, decl_3, dots_rad, dt_radiation,&
1233           emissivity, force_radiation_call, lat, lon, mrt_geom_human,         &
1234           mrt_include_sw, mrt_nlevels, mrtbl, mrtinsw, mrtinlw, nmrtbl,       &
1235           rad_net_av, radiation, radiation_scheme, rad_lw_in,                 &
1236           rad_lw_in_av, rad_lw_out, rad_lw_out_av,                            &
1237           rad_lw_cs_hr, rad_lw_cs_hr_av, rad_lw_hr, rad_lw_hr_av, rad_sw_in,  &
1238           rad_sw_in_av, rad_sw_out, rad_sw_out_av, rad_sw_cs_hr,              &
1239           rad_sw_cs_hr_av, rad_sw_hr, rad_sw_hr_av, sigma_sb, solar_constant, &
1240           skip_time_do_radiation, time_radiation, unscheduled_radiation_calls,&
1241           zenith, calc_zenith, sun_direction, sun_dir_lat, sun_dir_lon,       &
1242           idir, jdir, kdir, id, iz, iy, ix,                                   &
1243           iup_u, inorth_u, isouth_u, ieast_u, iwest_u,                        &
1244           iup_l, inorth_l, isouth_l, ieast_l, iwest_l,                        &
1245           nsurf_type, nzub, nzut, nzu, pch, nsurf,                            &
1246           idsvf, ndsvf, idcsf, ndcsf, kdcsf, pct,                             &
1247           radiation_interactions, startwall, startland, endland, endwall,     &
1248           skyvf, skyvft, radiation_interactions_on, average_radiation
1249
1250
1251#if defined ( __rrtmg )
1252    PUBLIC rrtm_aldif, rrtm_aldir, rrtm_asdif, rrtm_asdir
1253#endif
1254
1255 CONTAINS
1256
1257
1258!------------------------------------------------------------------------------!
1259! Description:
1260! ------------
1261!> This subroutine controls the calls of the radiation schemes
1262!------------------------------------------------------------------------------!
1263    SUBROUTINE radiation_control
1264 
1265 
1266       IMPLICIT NONE
1267
1268
1269       SELECT CASE ( TRIM( radiation_scheme ) )
1270
1271          CASE ( 'constant' )
1272             CALL radiation_constant
1273         
1274          CASE ( 'clear-sky' ) 
1275             CALL radiation_clearsky
1276       
1277          CASE ( 'rrtmg' )
1278             CALL radiation_rrtmg
1279
1280          CASE DEFAULT
1281
1282       END SELECT
1283
1284
1285    END SUBROUTINE radiation_control
1286
1287!------------------------------------------------------------------------------!
1288! Description:
1289! ------------
1290!> Check data output for radiation model
1291!------------------------------------------------------------------------------!
1292    SUBROUTINE radiation_check_data_output( variable, unit, i, ilen, k )
1293 
1294 
1295       USE control_parameters,                                                 &
1296           ONLY: data_output, message_string
1297
1298       IMPLICIT NONE
1299
1300       CHARACTER (LEN=*) ::  unit          !<
1301       CHARACTER (LEN=*) ::  variable      !<
1302
1303       INTEGER(iwp) :: i, j, k, l
1304       INTEGER(iwp) :: ilen
1305       CHARACTER(LEN=varnamelength) :: var          !< TRIM(variable)
1306
1307       var = TRIM(variable)
1308
1309!--    first process diractional variables
1310       IF ( var(1:12) == 'rtm_rad_net_'  .OR.  var(1:13) == 'rtm_rad_insw_'  .OR.        &
1311            var(1:13) == 'rtm_rad_inlw_'  .OR.  var(1:16) == 'rtm_rad_inswdir_'  .OR.    &
1312            var(1:16) == 'rtm_rad_inswdif_'  .OR.  var(1:16) == 'rtm_rad_inswref_'  .OR. &
1313            var(1:16) == 'rtm_rad_inlwdif_'  .OR.  var(1:16) == 'rtm_rad_inlwref_'  .OR. &
1314            var(1:14) == 'rtm_rad_outsw_'  .OR.  var(1:14) == 'rtm_rad_outlw_'  .OR.     &
1315            var(1:14) == 'rtm_rad_ressw_'  .OR.  var(1:14) == 'rtm_rad_reslw_'  ) THEN
1316          IF ( .NOT.  radiation ) THEN
1317                message_string = 'output of "' // TRIM( var ) // '" require'&
1318                                 // 's radiation = .TRUE.'
1319                CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1320          ENDIF
1321          unit = 'W/m2'
1322       ELSE IF ( var(1:7) == 'rtm_svf'  .OR.  var(1:7) == 'rtm_dif'  .OR.                &
1323                 var(1:9) == 'rtm_skyvf' .OR. var(1:9) == 'rtm_skyvft' )  THEN
1324          IF ( .NOT.  radiation ) THEN
1325                message_string = 'output of "' // TRIM( var ) // '" require'&
1326                                 // 's radiation = .TRUE.'
1327                CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1328          ENDIF
1329          unit = '1'
1330       ELSE
1331!--       non-directional variables
1332          SELECT CASE ( TRIM( var ) )
1333             CASE ( 'rad_lw_cs_hr', 'rad_lw_hr', 'rad_lw_in', 'rad_lw_out', &
1334                    'rad_sw_cs_hr', 'rad_sw_hr', 'rad_sw_in', 'rad_sw_out'  )
1335                IF (  .NOT.  radiation  .OR.  radiation_scheme /= 'rrtmg' )  THEN
1336                   message_string = '"output of "' // TRIM( var ) // '" requi' // &
1337                                    'res radiation = .TRUE. and ' //              &
1338                                    'radiation_scheme = "rrtmg"'
1339                   CALL message( 'check_parameters', 'PA0406', 1, 2, 0, 6, 0 )
1340                ENDIF
1341                unit = 'K/h'
1342
1343             CASE ( 'rad_net*', 'rrtm_aldif*', 'rrtm_aldir*', 'rrtm_asdif*',      &
1344                    'rrtm_asdir*', 'rad_lw_in*', 'rad_lw_out*', 'rad_sw_in*',     &
1345                    'rad_sw_out*')
1346                IF ( i == 0 .AND. ilen == 0 .AND. k == 0)  THEN
1347                   ! Workaround for masked output (calls with i=ilen=k=0)
1348                   unit = 'illegal'
1349                   RETURN
1350                ENDIF
1351                IF ( k == 0  .OR.  data_output(i)(ilen-2:ilen) /= '_xy' )  THEN
1352                   message_string = 'illegal value for data_output: "' //         &
1353                                    TRIM( var ) // '" & only 2d-horizontal ' //   &
1354                                    'cross sections are allowed for this value'
1355                   CALL message( 'check_parameters', 'PA0111', 1, 2, 0, 6, 0 )
1356                ENDIF
1357                IF (  .NOT.  radiation  .OR.  radiation_scheme /= "rrtmg" )  THEN
1358                   IF ( TRIM( var ) == 'rrtm_aldif*'  .OR.                        &
1359                        TRIM( var ) == 'rrtm_aldir*'  .OR.                        &
1360                        TRIM( var ) == 'rrtm_asdif*'  .OR.                        &
1361                        TRIM( var ) == 'rrtm_asdir*'      )                       &
1362                   THEN
1363                      message_string = 'output of "' // TRIM( var ) // '" require'&
1364                                       // 's radiation = .TRUE. and radiation_sch'&
1365                                       // 'eme = "rrtmg"'
1366                      CALL message( 'check_parameters', 'PA0409', 1, 2, 0, 6, 0 )
1367                   ENDIF
1368                ENDIF
1369
1370                IF ( TRIM( var ) == 'rad_net*'      ) unit = 'W/m2'
1371                IF ( TRIM( var ) == 'rad_lw_in*'    ) unit = 'W/m2'
1372                IF ( TRIM( var ) == 'rad_lw_out*'   ) unit = 'W/m2'
1373                IF ( TRIM( var ) == 'rad_sw_in*'    ) unit = 'W/m2'
1374                IF ( TRIM( var ) == 'rad_sw_out*'   ) unit = 'W/m2'
1375                IF ( TRIM( var ) == 'rad_sw_in'     ) unit = 'W/m2'
1376                IF ( TRIM( var ) == 'rrtm_aldif*'   ) unit = ''
1377                IF ( TRIM( var ) == 'rrtm_aldir*'   ) unit = ''
1378                IF ( TRIM( var ) == 'rrtm_asdif*'   ) unit = ''
1379                IF ( TRIM( var ) == 'rrtm_asdir*'   ) unit = ''
1380
1381             CASE ( 'rtm_rad_pc_inlw', 'rtm_rad_pc_insw', 'rtm_rad_pc_inswdir', &
1382                    'rtm_rad_pc_inswdif', 'rtm_rad_pc_inswref')
1383                IF ( .NOT.  radiation ) THEN
1384                   message_string = 'output of "' // TRIM( var ) // '" require'&
1385                                    // 's radiation = .TRUE.'
1386                   CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1387                ENDIF
1388                unit = 'W'
1389
1390             CASE ( 'rtm_mrt', 'rtm_mrt_sw', 'rtm_mrt_lw'  )
1391                IF ( i == 0 .AND. ilen == 0 .AND. k == 0)  THEN
1392                   ! Workaround for masked output (calls with i=ilen=k=0)
1393                   unit = 'illegal'
1394                   RETURN
1395                ENDIF
1396
1397                IF ( .NOT.  radiation ) THEN
1398                   message_string = 'output of "' // TRIM( var ) // '" require'&
1399                                    // 's radiation = .TRUE.'
1400                   CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1401                ENDIF
1402                IF ( mrt_nlevels == 0 ) THEN
1403                   message_string = 'output of "' // TRIM( var ) // '" require'&
1404                                    // 's mrt_nlevels > 0'
1405                   CALL message( 'check_parameters', 'PA0510', 1, 2, 0, 6, 0 )
1406                ENDIF
1407                IF ( TRIM( var ) == 'rtm_mrt_sw'  .AND.  .NOT. mrt_include_sw ) THEN
1408                   message_string = 'output of "' // TRIM( var ) // '" require'&
1409                                    // 's rtm_mrt_sw = .TRUE.'
1410                   CALL message( 'check_parameters', 'PA0511', 1, 2, 0, 6, 0 )
1411                ENDIF
1412                IF ( TRIM( var ) == 'rtm_mrt' ) THEN
1413                   unit = 'K'
1414                ELSE
1415                   unit = 'W m-2'
1416                ENDIF
1417
1418             CASE DEFAULT
1419                unit = 'illegal'
1420
1421          END SELECT
1422       ENDIF
1423
1424    END SUBROUTINE radiation_check_data_output
1425
1426!------------------------------------------------------------------------------!
1427! Description:
1428! ------------
1429!> Check data output of profiles for radiation model
1430!------------------------------------------------------------------------------! 
1431    SUBROUTINE radiation_check_data_output_pr( variable, var_count, unit,      &
1432               dopr_unit )
1433 
1434       USE arrays_3d,                                                          &
1435           ONLY: zu
1436
1437       USE control_parameters,                                                 &
1438           ONLY: data_output_pr, message_string
1439
1440       USE indices
1441
1442       USE profil_parameter
1443
1444       USE statistics
1445
1446       IMPLICIT NONE
1447   
1448       CHARACTER (LEN=*) ::  unit      !<
1449       CHARACTER (LEN=*) ::  variable  !<
1450       CHARACTER (LEN=*) ::  dopr_unit !< local value of dopr_unit
1451 
1452       INTEGER(iwp) ::  var_count     !<
1453
1454       SELECT CASE ( TRIM( variable ) )
1455       
1456         CASE ( 'rad_net' )
1457             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme == 'constant' )&
1458             THEN
1459                message_string = 'data_output_pr = ' //                        &
1460                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1461                                 'not available for radiation = .FALSE. or ' //&
1462                                 'radiation_scheme = "constant"'
1463                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1464             ELSE
1465                dopr_index(var_count) = 99
1466                dopr_unit  = 'W/m2'
1467                hom(:,2,99,:)  = SPREAD( zw, 2, statistic_regions+1 )
1468                unit = dopr_unit
1469             ENDIF
1470
1471          CASE ( 'rad_lw_in' )
1472             IF ( (  .NOT.  radiation)  .OR.  radiation_scheme == 'constant' ) &
1473             THEN
1474                message_string = 'data_output_pr = ' //                        &
1475                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1476                                 'not available for radiation = .FALSE. or ' //&
1477                                 'radiation_scheme = "constant"'
1478                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1479             ELSE
1480                dopr_index(var_count) = 100
1481                dopr_unit  = 'W/m2'
1482                hom(:,2,100,:)  = SPREAD( zw, 2, statistic_regions+1 )
1483                unit = dopr_unit 
1484             ENDIF
1485
1486          CASE ( 'rad_lw_out' )
1487             IF ( (  .NOT. radiation )  .OR.  radiation_scheme == 'constant' ) &
1488             THEN
1489                message_string = 'data_output_pr = ' //                        &
1490                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1491                                 'not available for radiation = .FALSE. or ' //&
1492                                 'radiation_scheme = "constant"'
1493                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1494             ELSE
1495                dopr_index(var_count) = 101
1496                dopr_unit  = 'W/m2'
1497                hom(:,2,101,:)  = SPREAD( zw, 2, statistic_regions+1 )
1498                unit = dopr_unit   
1499             ENDIF
1500
1501          CASE ( 'rad_sw_in' )
1502             IF ( (  .NOT. radiation )  .OR.  radiation_scheme == 'constant' ) &
1503             THEN
1504                message_string = 'data_output_pr = ' //                        &
1505                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1506                                 'not available for radiation = .FALSE. or ' //&
1507                                 'radiation_scheme = "constant"'
1508                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1509             ELSE
1510                dopr_index(var_count) = 102
1511                dopr_unit  = 'W/m2'
1512                hom(:,2,102,:)  = SPREAD( zw, 2, statistic_regions+1 )
1513                unit = dopr_unit
1514             ENDIF
1515
1516          CASE ( 'rad_sw_out')
1517             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme == 'constant' )&
1518             THEN
1519                message_string = 'data_output_pr = ' //                        &
1520                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1521                                 'not available for radiation = .FALSE. or ' //&
1522                                 'radiation_scheme = "constant"'
1523                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1524             ELSE
1525                dopr_index(var_count) = 103
1526                dopr_unit  = 'W/m2'
1527                hom(:,2,103,:)  = SPREAD( zw, 2, statistic_regions+1 )
1528                unit = dopr_unit
1529             ENDIF
1530
1531          CASE ( 'rad_lw_cs_hr' )
1532             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1533             THEN
1534                message_string = 'data_output_pr = ' //                        &
1535                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1536                                 'not available for radiation = .FALSE. or ' //&
1537                                 'radiation_scheme /= "rrtmg"'
1538                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1539             ELSE
1540                dopr_index(var_count) = 104
1541                dopr_unit  = 'K/h'
1542                hom(:,2,104,:)  = SPREAD( zu, 2, statistic_regions+1 )
1543                unit = dopr_unit
1544             ENDIF
1545
1546          CASE ( 'rad_lw_hr' )
1547             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1548             THEN
1549                message_string = 'data_output_pr = ' //                        &
1550                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1551                                 'not available for radiation = .FALSE. or ' //&
1552                                 'radiation_scheme /= "rrtmg"'
1553                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1554             ELSE
1555                dopr_index(var_count) = 105
1556                dopr_unit  = 'K/h'
1557                hom(:,2,105,:)  = SPREAD( zu, 2, statistic_regions+1 )
1558                unit = dopr_unit
1559             ENDIF
1560
1561          CASE ( 'rad_sw_cs_hr' )
1562             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1563             THEN
1564                message_string = 'data_output_pr = ' //                        &
1565                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1566                                 'not available for radiation = .FALSE. or ' //&
1567                                 'radiation_scheme /= "rrtmg"'
1568                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1569             ELSE
1570                dopr_index(var_count) = 106
1571                dopr_unit  = 'K/h'
1572                hom(:,2,106,:)  = SPREAD( zu, 2, statistic_regions+1 )
1573                unit = dopr_unit
1574             ENDIF
1575
1576          CASE ( 'rad_sw_hr' )
1577             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1578             THEN
1579                message_string = 'data_output_pr = ' //                        &
1580                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1581                                 'not available for radiation = .FALSE. or ' //&
1582                                 'radiation_scheme /= "rrtmg"'
1583                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1584             ELSE
1585                dopr_index(var_count) = 107
1586                dopr_unit  = 'K/h'
1587                hom(:,2,107,:)  = SPREAD( zu, 2, statistic_regions+1 )
1588                unit = dopr_unit
1589             ENDIF
1590
1591
1592          CASE DEFAULT
1593             unit = 'illegal'
1594
1595       END SELECT
1596
1597
1598    END SUBROUTINE radiation_check_data_output_pr
1599 
1600 
1601!------------------------------------------------------------------------------!
1602! Description:
1603! ------------
1604!> Check parameters routine for radiation model
1605!------------------------------------------------------------------------------!
1606    SUBROUTINE radiation_check_parameters
1607
1608       USE control_parameters,                                                 &
1609           ONLY: land_surface, message_string, urban_surface
1610
1611       USE netcdf_data_input_mod,                                              &
1612           ONLY:  input_pids_static                 
1613   
1614       IMPLICIT NONE
1615       
1616!
1617!--    In case no urban-surface or land-surface model is applied, usage of
1618!--    a radiation model make no sense.         
1619       IF ( .NOT. land_surface  .AND.  .NOT. urban_surface )  THEN
1620          message_string = 'Usage of radiation module is only allowed if ' //  &
1621                           'land-surface and/or urban-surface model is applied.'
1622          CALL message( 'check_parameters', 'PA0486', 1, 2, 0, 6, 0 )
1623       ENDIF
1624
1625       IF ( radiation_scheme /= 'constant'   .AND.                             &
1626            radiation_scheme /= 'clear-sky'  .AND.                             &
1627            radiation_scheme /= 'rrtmg' )  THEN
1628          message_string = 'unknown radiation_scheme = '//                     &
1629                           TRIM( radiation_scheme )
1630          CALL message( 'check_parameters', 'PA0405', 1, 2, 0, 6, 0 )
1631       ELSEIF ( radiation_scheme == 'rrtmg' )  THEN
1632#if ! defined ( __rrtmg )
1633          message_string = 'radiation_scheme = "rrtmg" requires ' //           & 
1634                           'compilation of PALM with pre-processor ' //        &
1635                           'directive -D__rrtmg'
1636          CALL message( 'check_parameters', 'PA0407', 1, 2, 0, 6, 0 )
1637#endif
1638#if defined ( __rrtmg ) && ! defined( __netcdf )
1639          message_string = 'radiation_scheme = "rrtmg" requires ' //           & 
1640                           'the use of NetCDF (preprocessor directive ' //     &
1641                           '-D__netcdf'
1642          CALL message( 'check_parameters', 'PA0412', 1, 2, 0, 6, 0 )
1643#endif
1644
1645       ENDIF
1646!
1647!--    Checks performed only if data is given via namelist only.
1648       IF ( .NOT. input_pids_static )  THEN
1649          IF ( albedo_type == 0  .AND.  albedo == 9999999.9_wp  .AND.          &
1650               radiation_scheme == 'clear-sky')  THEN
1651             message_string = 'radiation_scheme = "clear-sky" in combination'//& 
1652                              'with albedo_type = 0 requires setting of'//     &
1653                              'albedo /= 9999999.9'
1654             CALL message( 'check_parameters', 'PA0410', 1, 2, 0, 6, 0 )
1655          ENDIF
1656
1657          IF ( albedo_type == 0  .AND.  radiation_scheme == 'rrtmg'  .AND.     &
1658             ( albedo_lw_dif == 9999999.9_wp .OR. albedo_lw_dir == 9999999.9_wp&
1659          .OR. albedo_sw_dif == 9999999.9_wp .OR. albedo_sw_dir == 9999999.9_wp& 
1660             ) ) THEN
1661             message_string = 'radiation_scheme = "rrtmg" in combination' //   & 
1662                              'with albedo_type = 0 requires setting of ' //   &
1663                              'albedo_lw_dif /= 9999999.9' //                  &
1664                              'albedo_lw_dir /= 9999999.9' //                  &
1665                              'albedo_sw_dif /= 9999999.9 and' //              &
1666                              'albedo_sw_dir /= 9999999.9'
1667             CALL message( 'check_parameters', 'PA0411', 1, 2, 0, 6, 0 )
1668          ENDIF
1669       ENDIF
1670!
1671!--    Parallel rad_angular_discretization without raytrace_mpi_rma is not implemented
1672#if defined( __parallel )     
1673       IF ( rad_angular_discretization  .AND.  .NOT. raytrace_mpi_rma )  THEN
1674          message_string = 'rad_angular_discretization can only be used ' //  &
1675                           'together with raytrace_mpi_rma or when ' //  &
1676                           'no parallelization is applied.'
1677          CALL message( 'check_parameters', 'PA0486', 1, 2, 0, 6, 0 )
1678       ENDIF
1679#endif
1680
1681       IF ( cloud_droplets  .AND.   radiation_scheme == 'rrtmg'  .AND.         &
1682            average_radiation ) THEN
1683          message_string = 'average_radiation = .T. with radiation_scheme'//   & 
1684                           '= "rrtmg" in combination cloud_droplets = .T.'//   &
1685                           'is not implementd'
1686          CALL message( 'check_parameters', 'PA0560', 1, 2, 0, 6, 0 )
1687       ENDIF
1688
1689!
1690!--    Incialize svf normalization reporting histogram
1691       svfnorm_report_num = 1
1692       DO WHILE ( svfnorm_report_thresh(svfnorm_report_num) < 1e20_wp          &
1693                   .AND. svfnorm_report_num <= 30 )
1694          svfnorm_report_num = svfnorm_report_num + 1
1695       ENDDO
1696       svfnorm_report_num = svfnorm_report_num - 1
1697
1698
1699 
1700    END SUBROUTINE radiation_check_parameters 
1701 
1702 
1703!------------------------------------------------------------------------------!
1704! Description:
1705! ------------
1706!> Initialization of the radiation model
1707!------------------------------------------------------------------------------!
1708    SUBROUTINE radiation_init
1709   
1710       IMPLICIT NONE
1711
1712       INTEGER(iwp) ::  i         !< running index x-direction
1713       INTEGER(iwp) ::  ioff      !< offset in x between surface element reference grid point in atmosphere and actual surface
1714       INTEGER(iwp) ::  j         !< running index y-direction
1715       INTEGER(iwp) ::  joff      !< offset in y between surface element reference grid point in atmosphere and actual surface
1716       INTEGER(iwp) ::  l         !< running index for orientation of vertical surfaces
1717       INTEGER(iwp) ::  m         !< running index for surface elements
1718#if defined( __rrtmg )
1719       INTEGER(iwp) ::  ind_type  !< running index for subgrid-surface tiles
1720#endif
1721
1722!
1723!--    Allocate array for storing the surface net radiation
1724       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_net )  .AND.                      &
1725                  surf_lsm_h%ns > 0  )   THEN
1726          ALLOCATE( surf_lsm_h%rad_net(1:surf_lsm_h%ns) )
1727          surf_lsm_h%rad_net = 0.0_wp 
1728       ENDIF
1729       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_net )  .AND.                      &
1730                  surf_usm_h%ns > 0  )  THEN
1731          ALLOCATE( surf_usm_h%rad_net(1:surf_usm_h%ns) )
1732          surf_usm_h%rad_net = 0.0_wp 
1733       ENDIF
1734       DO  l = 0, 3
1735          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_net )  .AND.                &
1736                     surf_lsm_v(l)%ns > 0  )  THEN
1737             ALLOCATE( surf_lsm_v(l)%rad_net(1:surf_lsm_v(l)%ns) )
1738             surf_lsm_v(l)%rad_net = 0.0_wp 
1739          ENDIF
1740          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_net )  .AND.                &
1741                     surf_usm_v(l)%ns > 0  )  THEN
1742             ALLOCATE( surf_usm_v(l)%rad_net(1:surf_usm_v(l)%ns) )
1743             surf_usm_v(l)%rad_net = 0.0_wp 
1744          ENDIF
1745       ENDDO
1746
1747
1748!
1749!--    Allocate array for storing the surface longwave (out) radiation change
1750       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_lw_out_change_0 )  .AND.          &
1751                  surf_lsm_h%ns > 0  )   THEN
1752          ALLOCATE( surf_lsm_h%rad_lw_out_change_0(1:surf_lsm_h%ns) )
1753          surf_lsm_h%rad_lw_out_change_0 = 0.0_wp 
1754       ENDIF
1755       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_lw_out_change_0 )  .AND.          &
1756                  surf_usm_h%ns > 0  )  THEN
1757          ALLOCATE( surf_usm_h%rad_lw_out_change_0(1:surf_usm_h%ns) )
1758          surf_usm_h%rad_lw_out_change_0 = 0.0_wp 
1759       ENDIF
1760       DO  l = 0, 3
1761          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_lw_out_change_0 )  .AND.    &
1762                     surf_lsm_v(l)%ns > 0  )  THEN
1763             ALLOCATE( surf_lsm_v(l)%rad_lw_out_change_0(1:surf_lsm_v(l)%ns) )
1764             surf_lsm_v(l)%rad_lw_out_change_0 = 0.0_wp 
1765          ENDIF
1766          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_lw_out_change_0 )  .AND.    &
1767                     surf_usm_v(l)%ns > 0  )  THEN
1768             ALLOCATE( surf_usm_v(l)%rad_lw_out_change_0(1:surf_usm_v(l)%ns) )
1769             surf_usm_v(l)%rad_lw_out_change_0 = 0.0_wp 
1770          ENDIF
1771       ENDDO
1772
1773!
1774!--    Allocate surface arrays for incoming/outgoing short/longwave radiation
1775       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_sw_in )  .AND.                    &
1776                  surf_lsm_h%ns > 0  )   THEN
1777          ALLOCATE( surf_lsm_h%rad_sw_in(1:surf_lsm_h%ns)  )
1778          ALLOCATE( surf_lsm_h%rad_sw_out(1:surf_lsm_h%ns) )
1779          ALLOCATE( surf_lsm_h%rad_sw_dir(1:surf_lsm_h%ns) )
1780          ALLOCATE( surf_lsm_h%rad_sw_dif(1:surf_lsm_h%ns) )
1781          ALLOCATE( surf_lsm_h%rad_sw_ref(1:surf_lsm_h%ns) )
1782          ALLOCATE( surf_lsm_h%rad_sw_res(1:surf_lsm_h%ns) )
1783          ALLOCATE( surf_lsm_h%rad_lw_in(1:surf_lsm_h%ns)  )
1784          ALLOCATE( surf_lsm_h%rad_lw_out(1:surf_lsm_h%ns) )
1785          ALLOCATE( surf_lsm_h%rad_lw_dif(1:surf_lsm_h%ns) )
1786          ALLOCATE( surf_lsm_h%rad_lw_ref(1:surf_lsm_h%ns) )
1787          ALLOCATE( surf_lsm_h%rad_lw_res(1:surf_lsm_h%ns) )
1788          surf_lsm_h%rad_sw_in  = 0.0_wp 
1789          surf_lsm_h%rad_sw_out = 0.0_wp 
1790          surf_lsm_h%rad_sw_dir = 0.0_wp 
1791          surf_lsm_h%rad_sw_dif = 0.0_wp 
1792          surf_lsm_h%rad_sw_ref = 0.0_wp 
1793          surf_lsm_h%rad_sw_res = 0.0_wp 
1794          surf_lsm_h%rad_lw_in  = 0.0_wp 
1795          surf_lsm_h%rad_lw_out = 0.0_wp 
1796          surf_lsm_h%rad_lw_dif = 0.0_wp 
1797          surf_lsm_h%rad_lw_ref = 0.0_wp 
1798          surf_lsm_h%rad_lw_res = 0.0_wp 
1799       ENDIF
1800       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_sw_in )  .AND.                    &
1801                  surf_usm_h%ns > 0  )  THEN
1802          ALLOCATE( surf_usm_h%rad_sw_in(1:surf_usm_h%ns)  )
1803          ALLOCATE( surf_usm_h%rad_sw_out(1:surf_usm_h%ns) )
1804          ALLOCATE( surf_usm_h%rad_sw_dir(1:surf_usm_h%ns) )
1805          ALLOCATE( surf_usm_h%rad_sw_dif(1:surf_usm_h%ns) )
1806          ALLOCATE( surf_usm_h%rad_sw_ref(1:surf_usm_h%ns) )
1807          ALLOCATE( surf_usm_h%rad_sw_res(1:surf_usm_h%ns) )
1808          ALLOCATE( surf_usm_h%rad_lw_in(1:surf_usm_h%ns)  )
1809          ALLOCATE( surf_usm_h%rad_lw_out(1:surf_usm_h%ns) )
1810          ALLOCATE( surf_usm_h%rad_lw_dif(1:surf_usm_h%ns) )
1811          ALLOCATE( surf_usm_h%rad_lw_ref(1:surf_usm_h%ns) )
1812          ALLOCATE( surf_usm_h%rad_lw_res(1:surf_usm_h%ns) )
1813          surf_usm_h%rad_sw_in  = 0.0_wp 
1814          surf_usm_h%rad_sw_out = 0.0_wp 
1815          surf_usm_h%rad_sw_dir = 0.0_wp 
1816          surf_usm_h%rad_sw_dif = 0.0_wp 
1817          surf_usm_h%rad_sw_ref = 0.0_wp 
1818          surf_usm_h%rad_sw_res = 0.0_wp 
1819          surf_usm_h%rad_lw_in  = 0.0_wp 
1820          surf_usm_h%rad_lw_out = 0.0_wp 
1821          surf_usm_h%rad_lw_dif = 0.0_wp 
1822          surf_usm_h%rad_lw_ref = 0.0_wp 
1823          surf_usm_h%rad_lw_res = 0.0_wp 
1824       ENDIF
1825       DO  l = 0, 3
1826          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_sw_in )  .AND.              &
1827                     surf_lsm_v(l)%ns > 0  )  THEN
1828             ALLOCATE( surf_lsm_v(l)%rad_sw_in(1:surf_lsm_v(l)%ns)  )
1829             ALLOCATE( surf_lsm_v(l)%rad_sw_out(1:surf_lsm_v(l)%ns) )
1830             ALLOCATE( surf_lsm_v(l)%rad_sw_dir(1:surf_lsm_v(l)%ns) )
1831             ALLOCATE( surf_lsm_v(l)%rad_sw_dif(1:surf_lsm_v(l)%ns) )
1832             ALLOCATE( surf_lsm_v(l)%rad_sw_ref(1:surf_lsm_v(l)%ns) )
1833             ALLOCATE( surf_lsm_v(l)%rad_sw_res(1:surf_lsm_v(l)%ns) )
1834
1835             ALLOCATE( surf_lsm_v(l)%rad_lw_in(1:surf_lsm_v(l)%ns)  )
1836             ALLOCATE( surf_lsm_v(l)%rad_lw_out(1:surf_lsm_v(l)%ns) )
1837             ALLOCATE( surf_lsm_v(l)%rad_lw_dif(1:surf_lsm_v(l)%ns) )
1838             ALLOCATE( surf_lsm_v(l)%rad_lw_ref(1:surf_lsm_v(l)%ns) )
1839             ALLOCATE( surf_lsm_v(l)%rad_lw_res(1:surf_lsm_v(l)%ns) )
1840
1841             surf_lsm_v(l)%rad_sw_in  = 0.0_wp 
1842             surf_lsm_v(l)%rad_sw_out = 0.0_wp
1843             surf_lsm_v(l)%rad_sw_dir = 0.0_wp
1844             surf_lsm_v(l)%rad_sw_dif = 0.0_wp
1845             surf_lsm_v(l)%rad_sw_ref = 0.0_wp
1846             surf_lsm_v(l)%rad_sw_res = 0.0_wp
1847
1848             surf_lsm_v(l)%rad_lw_in  = 0.0_wp 
1849             surf_lsm_v(l)%rad_lw_out = 0.0_wp 
1850             surf_lsm_v(l)%rad_lw_dif = 0.0_wp 
1851             surf_lsm_v(l)%rad_lw_ref = 0.0_wp 
1852             surf_lsm_v(l)%rad_lw_res = 0.0_wp 
1853          ENDIF
1854          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_sw_in )  .AND.              &
1855                     surf_usm_v(l)%ns > 0  )  THEN
1856             ALLOCATE( surf_usm_v(l)%rad_sw_in(1:surf_usm_v(l)%ns)  )
1857             ALLOCATE( surf_usm_v(l)%rad_sw_out(1:surf_usm_v(l)%ns) )
1858             ALLOCATE( surf_usm_v(l)%rad_sw_dir(1:surf_usm_v(l)%ns) )
1859             ALLOCATE( surf_usm_v(l)%rad_sw_dif(1:surf_usm_v(l)%ns) )
1860             ALLOCATE( surf_usm_v(l)%rad_sw_ref(1:surf_usm_v(l)%ns) )
1861             ALLOCATE( surf_usm_v(l)%rad_sw_res(1:surf_usm_v(l)%ns) )
1862             ALLOCATE( surf_usm_v(l)%rad_lw_in(1:surf_usm_v(l)%ns)  )
1863             ALLOCATE( surf_usm_v(l)%rad_lw_out(1:surf_usm_v(l)%ns) )
1864             ALLOCATE( surf_usm_v(l)%rad_lw_dif(1:surf_usm_v(l)%ns) )
1865             ALLOCATE( surf_usm_v(l)%rad_lw_ref(1:surf_usm_v(l)%ns) )
1866             ALLOCATE( surf_usm_v(l)%rad_lw_res(1:surf_usm_v(l)%ns) )
1867             surf_usm_v(l)%rad_sw_in  = 0.0_wp 
1868             surf_usm_v(l)%rad_sw_out = 0.0_wp
1869             surf_usm_v(l)%rad_sw_dir = 0.0_wp
1870             surf_usm_v(l)%rad_sw_dif = 0.0_wp
1871             surf_usm_v(l)%rad_sw_ref = 0.0_wp
1872             surf_usm_v(l)%rad_sw_res = 0.0_wp
1873             surf_usm_v(l)%rad_lw_in  = 0.0_wp 
1874             surf_usm_v(l)%rad_lw_out = 0.0_wp 
1875             surf_usm_v(l)%rad_lw_dif = 0.0_wp 
1876             surf_usm_v(l)%rad_lw_ref = 0.0_wp 
1877             surf_usm_v(l)%rad_lw_res = 0.0_wp 
1878          ENDIF
1879       ENDDO
1880!
1881!--    Fix net radiation in case of radiation_scheme = 'constant'
1882       IF ( radiation_scheme == 'constant' )  THEN
1883          IF ( ALLOCATED( surf_lsm_h%rad_net ) )                               &
1884             surf_lsm_h%rad_net    = net_radiation
1885          IF ( ALLOCATED( surf_usm_h%rad_net ) )                               &
1886             surf_usm_h%rad_net    = net_radiation
1887!
1888!--       Todo: weight with inclination angle
1889          DO  l = 0, 3
1890             IF ( ALLOCATED( surf_lsm_v(l)%rad_net ) )                         &
1891                surf_lsm_v(l)%rad_net = net_radiation
1892             IF ( ALLOCATED( surf_usm_v(l)%rad_net ) )                         &
1893                surf_usm_v(l)%rad_net = net_radiation
1894          ENDDO
1895!          radiation = .FALSE.
1896!
1897!--    Calculate orbital constants
1898       ELSE
1899          decl_1 = SIN(23.45_wp * pi / 180.0_wp)
1900          decl_2 = 2.0_wp * pi / 365.0_wp
1901          decl_3 = decl_2 * 81.0_wp
1902          lat    = latitude * pi / 180.0_wp
1903          lon    = longitude * pi / 180.0_wp
1904       ENDIF
1905
1906       IF ( radiation_scheme == 'clear-sky'  .OR.                              &
1907            radiation_scheme == 'constant')  THEN
1908
1909
1910!
1911!--       Allocate arrays for incoming/outgoing short/longwave radiation
1912          IF ( .NOT. ALLOCATED ( rad_sw_in ) )  THEN
1913             ALLOCATE ( rad_sw_in(0:0,nysg:nyng,nxlg:nxrg) )
1914          ENDIF
1915          IF ( .NOT. ALLOCATED ( rad_sw_out ) )  THEN
1916             ALLOCATE ( rad_sw_out(0:0,nysg:nyng,nxlg:nxrg) )
1917          ENDIF
1918
1919          IF ( .NOT. ALLOCATED ( rad_lw_in ) )  THEN
1920             ALLOCATE ( rad_lw_in(0:0,nysg:nyng,nxlg:nxrg) )
1921          ENDIF
1922          IF ( .NOT. ALLOCATED ( rad_lw_out ) )  THEN
1923             ALLOCATE ( rad_lw_out(0:0,nysg:nyng,nxlg:nxrg) )
1924          ENDIF
1925
1926!
1927!--       Allocate average arrays for incoming/outgoing short/longwave radiation
1928          IF ( .NOT. ALLOCATED ( rad_sw_in_av ) )  THEN
1929             ALLOCATE ( rad_sw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
1930          ENDIF
1931          IF ( .NOT. ALLOCATED ( rad_sw_out_av ) )  THEN
1932             ALLOCATE ( rad_sw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
1933          ENDIF
1934
1935          IF ( .NOT. ALLOCATED ( rad_lw_in_av ) )  THEN
1936             ALLOCATE ( rad_lw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
1937          ENDIF
1938          IF ( .NOT. ALLOCATED ( rad_lw_out_av ) )  THEN
1939             ALLOCATE ( rad_lw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
1940          ENDIF
1941!
1942!--       Allocate arrays for broadband albedo, and level 1 initialization
1943!--       via namelist paramter, unless not already allocated.
1944          IF ( .NOT. ALLOCATED(surf_lsm_h%albedo) )  THEN
1945             ALLOCATE( surf_lsm_h%albedo(0:2,1:surf_lsm_h%ns)     )
1946             surf_lsm_h%albedo    = albedo
1947          ENDIF
1948          IF ( .NOT. ALLOCATED(surf_usm_h%albedo) )  THEN
1949             ALLOCATE( surf_usm_h%albedo(0:2,1:surf_usm_h%ns)     )
1950             surf_usm_h%albedo    = albedo
1951          ENDIF
1952
1953          DO  l = 0, 3
1954             IF ( .NOT. ALLOCATED( surf_lsm_v(l)%albedo ) )  THEN
1955                ALLOCATE( surf_lsm_v(l)%albedo(0:2,1:surf_lsm_v(l)%ns) )
1956                surf_lsm_v(l)%albedo = albedo
1957             ENDIF
1958             IF ( .NOT. ALLOCATED( surf_usm_v(l)%albedo ) )  THEN
1959                ALLOCATE( surf_usm_v(l)%albedo(0:2,1:surf_usm_v(l)%ns) )
1960                surf_usm_v(l)%albedo = albedo
1961             ENDIF
1962          ENDDO
1963!
1964!--       Level 2 initialization of broadband albedo via given albedo_type.
1965!--       Only if albedo_type is non-zero. In case of urban surface and
1966!--       input data is read from ASCII file, albedo_type will be zero, so that
1967!--       albedo won't be overwritten.
1968          DO  m = 1, surf_lsm_h%ns
1969             IF ( surf_lsm_h%albedo_type(ind_veg_wall,m) /= 0 )                &
1970                surf_lsm_h%albedo(ind_veg_wall,m) =                            &
1971                           albedo_pars(2,surf_lsm_h%albedo_type(ind_veg_wall,m))
1972             IF ( surf_lsm_h%albedo_type(ind_pav_green,m) /= 0 )               &
1973                surf_lsm_h%albedo(ind_pav_green,m) =                           &
1974                           albedo_pars(2,surf_lsm_h%albedo_type(ind_pav_green,m))
1975             IF ( surf_lsm_h%albedo_type(ind_wat_win,m) /= 0 )                 &
1976                surf_lsm_h%albedo(ind_wat_win,m) =                             &
1977                           albedo_pars(2,surf_lsm_h%albedo_type(ind_wat_win,m))
1978          ENDDO
1979          DO  m = 1, surf_usm_h%ns
1980             IF ( surf_usm_h%albedo_type(ind_veg_wall,m) /= 0 )                &
1981                surf_usm_h%albedo(ind_veg_wall,m) =                            &
1982                           albedo_pars(2,surf_usm_h%albedo_type(ind_veg_wall,m))
1983             IF ( surf_usm_h%albedo_type(ind_pav_green,m) /= 0 )               &
1984                surf_usm_h%albedo(ind_pav_green,m) =                           &
1985                           albedo_pars(2,surf_usm_h%albedo_type(ind_pav_green,m))
1986             IF ( surf_usm_h%albedo_type(ind_wat_win,m) /= 0 )                 &
1987                surf_usm_h%albedo(ind_wat_win,m) =                             &
1988                           albedo_pars(2,surf_usm_h%albedo_type(ind_wat_win,m))
1989          ENDDO
1990
1991          DO  l = 0, 3
1992             DO  m = 1, surf_lsm_v(l)%ns
1993                IF ( surf_lsm_v(l)%albedo_type(ind_veg_wall,m) /= 0 )          &
1994                   surf_lsm_v(l)%albedo(ind_veg_wall,m) =                      &
1995                        albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_veg_wall,m))
1996                IF ( surf_lsm_v(l)%albedo_type(ind_pav_green,m) /= 0 )         &
1997                   surf_lsm_v(l)%albedo(ind_pav_green,m) =                     &
1998                        albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_pav_green,m))
1999                IF ( surf_lsm_v(l)%albedo_type(ind_wat_win,m) /= 0 )           &
2000                   surf_lsm_v(l)%albedo(ind_wat_win,m) =                       &
2001                        albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_wat_win,m))
2002             ENDDO
2003             DO  m = 1, surf_usm_v(l)%ns
2004                IF ( surf_usm_v(l)%albedo_type(ind_veg_wall,m) /= 0 )          &
2005                   surf_usm_v(l)%albedo(ind_veg_wall,m) =                      &
2006                        albedo_pars(2,surf_usm_v(l)%albedo_type(ind_veg_wall,m))
2007                IF ( surf_usm_v(l)%albedo_type(ind_pav_green,m) /= 0 )         &
2008                   surf_usm_v(l)%albedo(ind_pav_green,m) =                     &
2009                        albedo_pars(2,surf_usm_v(l)%albedo_type(ind_pav_green,m))
2010                IF ( surf_usm_v(l)%albedo_type(ind_wat_win,m) /= 0 )           &
2011                   surf_usm_v(l)%albedo(ind_wat_win,m) =                       &
2012                        albedo_pars(2,surf_usm_v(l)%albedo_type(ind_wat_win,m))
2013             ENDDO
2014          ENDDO
2015
2016!
2017!--       Level 3 initialization at grid points where albedo type is zero.
2018!--       This case, albedo is taken from file. In case of constant radiation
2019!--       or clear sky, only broadband albedo is given.
2020          IF ( albedo_pars_f%from_file )  THEN
2021!
2022!--          Horizontal surfaces
2023             DO  m = 1, surf_lsm_h%ns
2024                i = surf_lsm_h%i(m)
2025                j = surf_lsm_h%j(m)
2026                IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2027                   IF ( surf_lsm_h%albedo_type(ind_veg_wall,m) == 0 )          &
2028                      surf_lsm_h%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2029                   IF ( surf_lsm_h%albedo_type(ind_pav_green,m) == 0 )         &
2030                      surf_lsm_h%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2031                   IF ( surf_lsm_h%albedo_type(ind_wat_win,m) == 0 )           &
2032                      surf_lsm_h%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2033                ENDIF
2034             ENDDO
2035             DO  m = 1, surf_usm_h%ns
2036                i = surf_usm_h%i(m)
2037                j = surf_usm_h%j(m)
2038                IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2039                   IF ( surf_usm_h%albedo_type(ind_veg_wall,m) == 0 )          &
2040                      surf_usm_h%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2041                   IF ( surf_usm_h%albedo_type(ind_pav_green,m) == 0 )         &
2042                      surf_usm_h%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2043                   IF ( surf_usm_h%albedo_type(ind_wat_win,m) == 0 )           &
2044                      surf_usm_h%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2045                ENDIF
2046             ENDDO 
2047!
2048!--          Vertical surfaces           
2049             DO  l = 0, 3
2050
2051                ioff = surf_lsm_v(l)%ioff
2052                joff = surf_lsm_v(l)%joff
2053                DO  m = 1, surf_lsm_v(l)%ns
2054                   i = surf_lsm_v(l)%i(m) + ioff
2055                   j = surf_lsm_v(l)%j(m) + joff
2056                   IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2057                      IF ( surf_lsm_v(l)%albedo_type(ind_veg_wall,m) == 0 )    &
2058                         surf_lsm_v(l)%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2059                      IF ( surf_lsm_v(l)%albedo_type(ind_pav_green,m) == 0 )   &
2060                         surf_lsm_v(l)%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2061                      IF ( surf_lsm_v(l)%albedo_type(ind_wat_win,m) == 0 )     &
2062                         surf_lsm_v(l)%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2063                   ENDIF
2064                ENDDO
2065
2066                ioff = surf_usm_v(l)%ioff
2067                joff = surf_usm_v(l)%joff
2068                DO  m = 1, surf_usm_h%ns
2069                   i = surf_usm_h%i(m) + joff
2070                   j = surf_usm_h%j(m) + joff
2071                   IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2072                      IF ( surf_usm_v(l)%albedo_type(ind_veg_wall,m) == 0 )    &
2073                         surf_usm_v(l)%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2074                      IF ( surf_usm_v(l)%albedo_type(ind_pav_green,m) == 0 )   &
2075                         surf_usm_v(l)%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2076                      IF ( surf_usm_v(l)%albedo_type(ind_wat_win,m) == 0 )     &
2077                         surf_lsm_v(l)%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2078                   ENDIF
2079                ENDDO
2080             ENDDO
2081
2082          ENDIF 
2083!
2084!--    Initialization actions for RRTMG
2085       ELSEIF ( radiation_scheme == 'rrtmg' )  THEN
2086#if defined ( __rrtmg )
2087!
2088!--       Allocate albedos for short/longwave radiation, horizontal surfaces
2089!--       for wall/green/window (USM) or vegetation/pavement/water surfaces
2090!--       (LSM).
2091          ALLOCATE ( surf_lsm_h%aldif(0:2,1:surf_lsm_h%ns)       )
2092          ALLOCATE ( surf_lsm_h%aldir(0:2,1:surf_lsm_h%ns)       )
2093          ALLOCATE ( surf_lsm_h%asdif(0:2,1:surf_lsm_h%ns)       )
2094          ALLOCATE ( surf_lsm_h%asdir(0:2,1:surf_lsm_h%ns)       )
2095          ALLOCATE ( surf_lsm_h%rrtm_aldif(0:2,1:surf_lsm_h%ns)  )
2096          ALLOCATE ( surf_lsm_h%rrtm_aldir(0:2,1:surf_lsm_h%ns)  )
2097          ALLOCATE ( surf_lsm_h%rrtm_asdif(0:2,1:surf_lsm_h%ns)  )
2098          ALLOCATE ( surf_lsm_h%rrtm_asdir(0:2,1:surf_lsm_h%ns)  )
2099
2100          ALLOCATE ( surf_usm_h%aldif(0:2,1:surf_usm_h%ns)       )
2101          ALLOCATE ( surf_usm_h%aldir(0:2,1:surf_usm_h%ns)       )
2102          ALLOCATE ( surf_usm_h%asdif(0:2,1:surf_usm_h%ns)       )
2103          ALLOCATE ( surf_usm_h%asdir(0:2,1:surf_usm_h%ns)       )
2104          ALLOCATE ( surf_usm_h%rrtm_aldif(0:2,1:surf_usm_h%ns)  )
2105          ALLOCATE ( surf_usm_h%rrtm_aldir(0:2,1:surf_usm_h%ns)  )
2106          ALLOCATE ( surf_usm_h%rrtm_asdif(0:2,1:surf_usm_h%ns)  )
2107          ALLOCATE ( surf_usm_h%rrtm_asdir(0:2,1:surf_usm_h%ns)  )
2108
2109!
2110!--       Allocate broadband albedo (temporary for the current radiation
2111!--       implementations)
2112          IF ( .NOT. ALLOCATED(surf_lsm_h%albedo) )                            &
2113             ALLOCATE( surf_lsm_h%albedo(0:2,1:surf_lsm_h%ns)     )
2114          IF ( .NOT. ALLOCATED(surf_usm_h%albedo) )                            &
2115             ALLOCATE( surf_usm_h%albedo(0:2,1:surf_usm_h%ns)     )
2116
2117!
2118!--       Allocate albedos for short/longwave radiation, vertical surfaces
2119          DO  l = 0, 3
2120
2121             ALLOCATE ( surf_lsm_v(l)%aldif(0:2,1:surf_lsm_v(l)%ns)      )
2122             ALLOCATE ( surf_lsm_v(l)%aldir(0:2,1:surf_lsm_v(l)%ns)      )
2123             ALLOCATE ( surf_lsm_v(l)%asdif(0:2,1:surf_lsm_v(l)%ns)      )
2124             ALLOCATE ( surf_lsm_v(l)%asdir(0:2,1:surf_lsm_v(l)%ns)      )
2125
2126             ALLOCATE ( surf_lsm_v(l)%rrtm_aldif(0:2,1:surf_lsm_v(l)%ns) )
2127             ALLOCATE ( surf_lsm_v(l)%rrtm_aldir(0:2,1:surf_lsm_v(l)%ns) )
2128             ALLOCATE ( surf_lsm_v(l)%rrtm_asdif(0:2,1:surf_lsm_v(l)%ns) )
2129             ALLOCATE ( surf_lsm_v(l)%rrtm_asdir(0:2,1:surf_lsm_v(l)%ns) )
2130
2131             ALLOCATE ( surf_usm_v(l)%aldif(0:2,1:surf_usm_v(l)%ns)      )
2132             ALLOCATE ( surf_usm_v(l)%aldir(0:2,1:surf_usm_v(l)%ns)      )
2133             ALLOCATE ( surf_usm_v(l)%asdif(0:2,1:surf_usm_v(l)%ns)      )
2134             ALLOCATE ( surf_usm_v(l)%asdir(0:2,1:surf_usm_v(l)%ns)      )
2135
2136             ALLOCATE ( surf_usm_v(l)%rrtm_aldif(0:2,1:surf_usm_v(l)%ns) )
2137             ALLOCATE ( surf_usm_v(l)%rrtm_aldir(0:2,1:surf_usm_v(l)%ns) )
2138             ALLOCATE ( surf_usm_v(l)%rrtm_asdif(0:2,1:surf_usm_v(l)%ns) )
2139             ALLOCATE ( surf_usm_v(l)%rrtm_asdir(0:2,1:surf_usm_v(l)%ns) )
2140!
2141!--          Allocate broadband albedo (temporary for the current radiation
2142!--          implementations)
2143             IF ( .NOT. ALLOCATED( surf_lsm_v(l)%albedo ) )                    &
2144                ALLOCATE( surf_lsm_v(l)%albedo(0:2,1:surf_lsm_v(l)%ns) )
2145             IF ( .NOT. ALLOCATED( surf_usm_v(l)%albedo ) )                    &
2146                ALLOCATE( surf_usm_v(l)%albedo(0:2,1:surf_usm_v(l)%ns) )
2147
2148          ENDDO
2149!
2150!--       Level 1 initialization of spectral albedos via namelist
2151!--       paramters. Please note, this case all surface tiles are initialized
2152!--       the same.
2153          IF ( surf_lsm_h%ns > 0 )  THEN
2154             surf_lsm_h%aldif  = albedo_lw_dif
2155             surf_lsm_h%aldir  = albedo_lw_dir
2156             surf_lsm_h%asdif  = albedo_sw_dif
2157             surf_lsm_h%asdir  = albedo_sw_dir
2158             surf_lsm_h%albedo = albedo_sw_dif
2159          ENDIF
2160          IF ( surf_usm_h%ns > 0 )  THEN
2161             IF ( surf_usm_h%albedo_from_ascii )  THEN
2162                surf_usm_h%aldif  = surf_usm_h%albedo
2163                surf_usm_h%aldir  = surf_usm_h%albedo
2164                surf_usm_h%asdif  = surf_usm_h%albedo
2165                surf_usm_h%asdir  = surf_usm_h%albedo
2166             ELSE
2167                surf_usm_h%aldif  = albedo_lw_dif
2168                surf_usm_h%aldir  = albedo_lw_dir
2169                surf_usm_h%asdif  = albedo_sw_dif
2170                surf_usm_h%asdir  = albedo_sw_dir
2171                surf_usm_h%albedo = albedo_sw_dif
2172             ENDIF
2173          ENDIF
2174
2175          DO  l = 0, 3
2176
2177             IF ( surf_lsm_v(l)%ns > 0 )  THEN
2178                surf_lsm_v(l)%aldif  = albedo_lw_dif
2179                surf_lsm_v(l)%aldir  = albedo_lw_dir
2180                surf_lsm_v(l)%asdif  = albedo_sw_dif
2181                surf_lsm_v(l)%asdir  = albedo_sw_dir
2182                surf_lsm_v(l)%albedo = albedo_sw_dif
2183             ENDIF
2184
2185             IF ( surf_usm_v(l)%ns > 0 )  THEN
2186                IF ( surf_usm_v(l)%albedo_from_ascii )  THEN
2187                   surf_usm_v(l)%aldif  = surf_usm_v(l)%albedo
2188                   surf_usm_v(l)%aldir  = surf_usm_v(l)%albedo
2189                   surf_usm_v(l)%asdif  = surf_usm_v(l)%albedo
2190                   surf_usm_v(l)%asdir  = surf_usm_v(l)%albedo
2191                ELSE
2192                   surf_usm_v(l)%aldif  = albedo_lw_dif
2193                   surf_usm_v(l)%aldir  = albedo_lw_dir
2194                   surf_usm_v(l)%asdif  = albedo_sw_dif
2195                   surf_usm_v(l)%asdir  = albedo_sw_dir
2196                ENDIF
2197             ENDIF
2198          ENDDO
2199
2200!
2201!--       Level 2 initialization of spectral albedos via albedo_type.
2202!--       Please note, for natural- and urban-type surfaces, a tile approach
2203!--       is applied so that the resulting albedo is calculated via the weighted
2204!--       average of respective surface fractions.
2205          DO  m = 1, surf_lsm_h%ns
2206!
2207!--          Spectral albedos for vegetation/pavement/water surfaces
2208             DO  ind_type = 0, 2
2209                IF ( surf_lsm_h%albedo_type(ind_type,m) /= 0 )  THEN
2210                   surf_lsm_h%aldif(ind_type,m) =                              &
2211                               albedo_pars(0,surf_lsm_h%albedo_type(ind_type,m))
2212                   surf_lsm_h%asdif(ind_type,m) =                              &
2213                               albedo_pars(1,surf_lsm_h%albedo_type(ind_type,m))
2214                   surf_lsm_h%aldir(ind_type,m) =                              &
2215                               albedo_pars(0,surf_lsm_h%albedo_type(ind_type,m))
2216                   surf_lsm_h%asdir(ind_type,m) =                              &
2217                               albedo_pars(1,surf_lsm_h%albedo_type(ind_type,m))
2218                   surf_lsm_h%albedo(ind_type,m) =                             &
2219                               albedo_pars(2,surf_lsm_h%albedo_type(ind_type,m))
2220                ENDIF
2221             ENDDO
2222
2223          ENDDO
2224!
2225!--       For urban surface only if albedo has not been already initialized
2226!--       in the urban-surface model via the ASCII file.
2227          IF ( .NOT. surf_usm_h%albedo_from_ascii )  THEN
2228             DO  m = 1, surf_usm_h%ns
2229!
2230!--             Spectral albedos for wall/green/window surfaces
2231                DO  ind_type = 0, 2
2232                   IF ( surf_usm_h%albedo_type(ind_type,m) /= 0 )  THEN
2233                      surf_usm_h%aldif(ind_type,m) =                           &
2234                               albedo_pars(0,surf_usm_h%albedo_type(ind_type,m))
2235                      surf_usm_h%asdif(ind_type,m) =                           &
2236                               albedo_pars(1,surf_usm_h%albedo_type(ind_type,m))
2237                      surf_usm_h%aldir(ind_type,m) =                           &
2238                               albedo_pars(0,surf_usm_h%albedo_type(ind_type,m))
2239                      surf_usm_h%asdir(ind_type,m) =                           &
2240                               albedo_pars(1,surf_usm_h%albedo_type(ind_type,m))
2241                      surf_usm_h%albedo(ind_type,m) =                          &
2242                               albedo_pars(2,surf_usm_h%albedo_type(ind_type,m))
2243                   ENDIF
2244                ENDDO
2245
2246             ENDDO
2247          ENDIF
2248
2249          DO l = 0, 3
2250
2251             DO  m = 1, surf_lsm_v(l)%ns
2252!
2253!--             Spectral albedos for vegetation/pavement/water surfaces
2254                DO  ind_type = 0, 2
2255                   IF ( surf_lsm_v(l)%albedo_type(ind_type,m) /= 0 )  THEN
2256                      surf_lsm_v(l)%aldif(ind_type,m) =                        &
2257                            albedo_pars(0,surf_lsm_v(l)%albedo_type(ind_type,m))
2258                      surf_lsm_v(l)%asdif(ind_type,m) =                        &
2259                            albedo_pars(1,surf_lsm_v(l)%albedo_type(ind_type,m))
2260                      surf_lsm_v(l)%aldir(ind_type,m) =                        &
2261                            albedo_pars(0,surf_lsm_v(l)%albedo_type(ind_type,m))
2262                      surf_lsm_v(l)%asdir(ind_type,m) =                        &
2263                            albedo_pars(1,surf_lsm_v(l)%albedo_type(ind_type,m))
2264                      surf_lsm_v(l)%albedo(ind_type,m) =                       &
2265                            albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_type,m))
2266                   ENDIF
2267                ENDDO
2268             ENDDO
2269!
2270!--          For urban surface only if albedo has not been already initialized
2271!--          in the urban-surface model via the ASCII file.
2272             IF ( .NOT. surf_usm_v(l)%albedo_from_ascii )  THEN
2273                DO  m = 1, surf_usm_v(l)%ns
2274!
2275!--                Spectral albedos for wall/green/window surfaces
2276                   DO  ind_type = 0, 2
2277                      IF ( surf_usm_v(l)%albedo_type(ind_type,m) /= 0 )  THEN
2278                         surf_usm_v(l)%aldif(ind_type,m) =                     &
2279                            albedo_pars(0,surf_usm_v(l)%albedo_type(ind_type,m))
2280                         surf_usm_v(l)%asdif(ind_type,m) =                     &
2281                            albedo_pars(1,surf_usm_v(l)%albedo_type(ind_type,m))
2282                         surf_usm_v(l)%aldir(ind_type,m) =                     &
2283                            albedo_pars(0,surf_usm_v(l)%albedo_type(ind_type,m))
2284                         surf_usm_v(l)%asdir(ind_type,m) =                     &
2285                            albedo_pars(1,surf_usm_v(l)%albedo_type(ind_type,m))
2286                         surf_usm_v(l)%albedo(ind_type,m) =                    &
2287                            albedo_pars(2,surf_usm_v(l)%albedo_type(ind_type,m))
2288                      ENDIF
2289                   ENDDO
2290
2291                ENDDO
2292             ENDIF
2293          ENDDO
2294!
2295!--       Level 3 initialization at grid points where albedo type is zero.
2296!--       This case, spectral albedos are taken from file if available
2297          IF ( albedo_pars_f%from_file )  THEN
2298!
2299!--          Horizontal
2300             DO  m = 1, surf_lsm_h%ns
2301                i = surf_lsm_h%i(m)
2302                j = surf_lsm_h%j(m)
2303!
2304!--             Spectral albedos for vegetation/pavement/water surfaces
2305                DO  ind_type = 0, 2
2306                   IF ( surf_lsm_h%albedo_type(ind_type,m) == 0 )  THEN
2307                      IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2308                         surf_lsm_h%albedo(ind_type,m) =                       &
2309                                                albedo_pars_f%pars_xy(1,j,i)
2310                      IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2311                         surf_lsm_h%aldir(ind_type,m) =                        &
2312                                                albedo_pars_f%pars_xy(1,j,i)
2313                      IF ( albedo_pars_f%pars_xy(2,j,i) /= albedo_pars_f%fill )&
2314                         surf_lsm_h%aldif(ind_type,m) =                        &
2315                                                albedo_pars_f%pars_xy(2,j,i)
2316                      IF ( albedo_pars_f%pars_xy(3,j,i) /= albedo_pars_f%fill )&
2317                         surf_lsm_h%asdir(ind_type,m) =                        &
2318                                                albedo_pars_f%pars_xy(3,j,i)
2319                      IF ( albedo_pars_f%pars_xy(4,j,i) /= albedo_pars_f%fill )&
2320                         surf_lsm_h%asdif(ind_type,m) =                        &
2321                                                albedo_pars_f%pars_xy(4,j,i)
2322                   ENDIF
2323                ENDDO
2324             ENDDO
2325!
2326!--          For urban surface only if albedo has not been already initialized
2327!--          in the urban-surface model via the ASCII file.
2328             IF ( .NOT. surf_usm_h%albedo_from_ascii )  THEN
2329                DO  m = 1, surf_usm_h%ns
2330                   i = surf_usm_h%i(m)
2331                   j = surf_usm_h%j(m)
2332!
2333!--                Spectral albedos for wall/green/window surfaces
2334                   DO  ind_type = 0, 2
2335                      IF ( surf_usm_h%albedo_type(ind_type,m) == 0 )  THEN
2336                         IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2337                            surf_usm_h%albedo(ind_type,m) =                       &
2338                                                albedo_pars_f%pars_xy(1,j,i)
2339                         IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2340                            surf_usm_h%aldir(ind_type,m) =                        &
2341                                                albedo_pars_f%pars_xy(1,j,i)
2342                         IF ( albedo_pars_f%pars_xy(2,j,i) /= albedo_pars_f%fill )&
2343                            surf_usm_h%aldif(ind_type,m) =                        &
2344                                                albedo_pars_f%pars_xy(2,j,i)
2345                         IF ( albedo_pars_f%pars_xy(3,j,i) /= albedo_pars_f%fill )&
2346                            surf_usm_h%asdir(ind_type,m) =                        &
2347                                                albedo_pars_f%pars_xy(3,j,i)
2348                         IF ( albedo_pars_f%pars_xy(4,j,i) /= albedo_pars_f%fill )&
2349                            surf_usm_h%asdif(ind_type,m) =                        &
2350                                                albedo_pars_f%pars_xy(4,j,i)
2351                      ENDIF
2352                   ENDDO
2353
2354                ENDDO
2355             ENDIF
2356!
2357!--          Vertical
2358             DO  l = 0, 3
2359                ioff = surf_lsm_v(l)%ioff
2360                joff = surf_lsm_v(l)%joff
2361
2362                DO  m = 1, surf_lsm_v(l)%ns
2363                   i = surf_lsm_v(l)%i(m)
2364                   j = surf_lsm_v(l)%j(m)
2365!
2366!--                Spectral albedos for vegetation/pavement/water surfaces
2367                   DO  ind_type = 0, 2
2368                      IF ( surf_lsm_v(l)%albedo_type(ind_type,m) == 0 )  THEN
2369                         IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2370                              albedo_pars_f%fill )                             &
2371                            surf_lsm_v(l)%albedo(ind_type,m) =                 &
2372                                          albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2373                         IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2374                              albedo_pars_f%fill )                             &
2375                            surf_lsm_v(l)%aldir(ind_type,m) =                  &
2376                                          albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2377                         IF ( albedo_pars_f%pars_xy(2,j+joff,i+ioff) /=        &
2378                              albedo_pars_f%fill )                             &
2379                            surf_lsm_v(l)%aldif(ind_type,m) =                  &
2380                                          albedo_pars_f%pars_xy(2,j+joff,i+ioff)
2381                         IF ( albedo_pars_f%pars_xy(3,j+joff,i+ioff) /=        &
2382                              albedo_pars_f%fill )                             &
2383                            surf_lsm_v(l)%asdir(ind_type,m) =                  &
2384                                          albedo_pars_f%pars_xy(3,j+joff,i+ioff)
2385                         IF ( albedo_pars_f%pars_xy(4,j+joff,i+ioff) /=        &
2386                              albedo_pars_f%fill )                             &
2387                            surf_lsm_v(l)%asdif(ind_type,m) =                  &
2388                                          albedo_pars_f%pars_xy(4,j+joff,i+ioff)
2389                      ENDIF
2390                   ENDDO
2391                ENDDO
2392!
2393!--             For urban surface only if albedo has not been already initialized
2394!--             in the urban-surface model via the ASCII file.
2395                IF ( .NOT. surf_usm_v(l)%albedo_from_ascii )  THEN
2396                   ioff = surf_usm_v(l)%ioff
2397                   joff = surf_usm_v(l)%joff
2398
2399                   DO  m = 1, surf_usm_v(l)%ns
2400                      i = surf_usm_v(l)%i(m)
2401                      j = surf_usm_v(l)%j(m)
2402!
2403!--                   Spectral albedos for wall/green/window surfaces
2404                      DO  ind_type = 0, 2
2405                         IF ( surf_usm_v(l)%albedo_type(ind_type,m) == 0 )  THEN
2406                            IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2407                                 albedo_pars_f%fill )                             &
2408                               surf_usm_v(l)%albedo(ind_type,m) =                 &
2409                                             albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2410                            IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2411                                 albedo_pars_f%fill )                             &
2412                               surf_usm_v(l)%aldir(ind_type,m) =                  &
2413                                             albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2414                            IF ( albedo_pars_f%pars_xy(2,j+joff,i+ioff) /=        &
2415                                 albedo_pars_f%fill )                             &
2416                               surf_usm_v(l)%aldif(ind_type,m) =                  &
2417                                             albedo_pars_f%pars_xy(2,j+joff,i+ioff)
2418                            IF ( albedo_pars_f%pars_xy(3,j+joff,i+ioff) /=        &
2419                                 albedo_pars_f%fill )                             &
2420                               surf_usm_v(l)%asdir(ind_type,m) =                  &
2421                                             albedo_pars_f%pars_xy(3,j+joff,i+ioff)
2422                            IF ( albedo_pars_f%pars_xy(4,j+joff,i+ioff) /=        &
2423                                 albedo_pars_f%fill )                             &
2424                               surf_usm_v(l)%asdif(ind_type,m) =                  &
2425                                             albedo_pars_f%pars_xy(4,j+joff,i+ioff)
2426                         ENDIF
2427                      ENDDO
2428
2429                   ENDDO
2430                ENDIF
2431             ENDDO
2432
2433          ENDIF
2434
2435!
2436!--       Calculate initial values of current (cosine of) the zenith angle and
2437!--       whether the sun is up
2438          CALL calc_zenith     
2439!
2440!--       Calculate initial surface albedo for different surfaces
2441          IF ( .NOT. constant_albedo )  THEN
2442#if defined( __netcdf )
2443!
2444!--          Horizontally aligned natural and urban surfaces
2445             CALL calc_albedo( surf_lsm_h    )
2446             CALL calc_albedo( surf_usm_h    )
2447!
2448!--          Vertically aligned natural and urban surfaces
2449             DO  l = 0, 3
2450                CALL calc_albedo( surf_lsm_v(l) )
2451                CALL calc_albedo( surf_usm_v(l) )
2452             ENDDO
2453#endif
2454          ELSE
2455!
2456!--          Initialize sun-inclination independent spectral albedos
2457!--          Horizontal surfaces
2458             IF ( surf_lsm_h%ns > 0 )  THEN
2459                surf_lsm_h%rrtm_aldir = surf_lsm_h%aldir
2460                surf_lsm_h%rrtm_asdir = surf_lsm_h%asdir
2461                surf_lsm_h%rrtm_aldif = surf_lsm_h%aldif
2462                surf_lsm_h%rrtm_asdif = surf_lsm_h%asdif
2463             ENDIF
2464             IF ( surf_usm_h%ns > 0 )  THEN
2465                surf_usm_h%rrtm_aldir = surf_usm_h%aldir
2466                surf_usm_h%rrtm_asdir = surf_usm_h%asdir
2467                surf_usm_h%rrtm_aldif = surf_usm_h%aldif
2468                surf_usm_h%rrtm_asdif = surf_usm_h%asdif
2469             ENDIF
2470!
2471!--          Vertical surfaces
2472             DO  l = 0, 3
2473                IF ( surf_lsm_v(l)%ns > 0 )  THEN
2474                   surf_lsm_v(l)%rrtm_aldir = surf_lsm_v(l)%aldir
2475                   surf_lsm_v(l)%rrtm_asdir = surf_lsm_v(l)%asdir
2476                   surf_lsm_v(l)%rrtm_aldif = surf_lsm_v(l)%aldif
2477                   surf_lsm_v(l)%rrtm_asdif = surf_lsm_v(l)%asdif
2478                ENDIF
2479                IF ( surf_usm_v(l)%ns > 0 )  THEN
2480                   surf_usm_v(l)%rrtm_aldir = surf_usm_v(l)%aldir
2481                   surf_usm_v(l)%rrtm_asdir = surf_usm_v(l)%asdir
2482                   surf_usm_v(l)%rrtm_aldif = surf_usm_v(l)%aldif
2483                   surf_usm_v(l)%rrtm_asdif = surf_usm_v(l)%asdif
2484                ENDIF
2485             ENDDO
2486
2487          ENDIF
2488
2489!
2490!--       Allocate 3d arrays of radiative fluxes and heating rates
2491          IF ( .NOT. ALLOCATED ( rad_sw_in ) )  THEN
2492             ALLOCATE ( rad_sw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2493             rad_sw_in = 0.0_wp
2494          ENDIF
2495
2496          IF ( .NOT. ALLOCATED ( rad_sw_in_av ) )  THEN
2497             ALLOCATE ( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2498          ENDIF
2499
2500          IF ( .NOT. ALLOCATED ( rad_sw_out ) )  THEN
2501             ALLOCATE ( rad_sw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2502             rad_sw_out = 0.0_wp
2503          ENDIF
2504
2505          IF ( .NOT. ALLOCATED ( rad_sw_out_av ) )  THEN
2506             ALLOCATE ( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2507          ENDIF
2508
2509          IF ( .NOT. ALLOCATED ( rad_sw_hr ) )  THEN
2510             ALLOCATE ( rad_sw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2511             rad_sw_hr = 0.0_wp
2512          ENDIF
2513
2514          IF ( .NOT. ALLOCATED ( rad_sw_hr_av ) )  THEN
2515             ALLOCATE ( rad_sw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2516             rad_sw_hr_av = 0.0_wp
2517          ENDIF
2518
2519          IF ( .NOT. ALLOCATED ( rad_sw_cs_hr ) )  THEN
2520             ALLOCATE ( rad_sw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2521             rad_sw_cs_hr = 0.0_wp
2522          ENDIF
2523
2524          IF ( .NOT. ALLOCATED ( rad_sw_cs_hr_av ) )  THEN
2525             ALLOCATE ( rad_sw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2526             rad_sw_cs_hr_av = 0.0_wp
2527          ENDIF
2528
2529          IF ( .NOT. ALLOCATED ( rad_lw_in ) )  THEN
2530             ALLOCATE ( rad_lw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2531             rad_lw_in     = 0.0_wp
2532          ENDIF
2533
2534          IF ( .NOT. ALLOCATED ( rad_lw_in_av ) )  THEN
2535             ALLOCATE ( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2536          ENDIF
2537
2538          IF ( .NOT. ALLOCATED ( rad_lw_out ) )  THEN
2539             ALLOCATE ( rad_lw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2540            rad_lw_out    = 0.0_wp
2541          ENDIF
2542
2543          IF ( .NOT. ALLOCATED ( rad_lw_out_av ) )  THEN
2544             ALLOCATE ( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2545          ENDIF
2546
2547          IF ( .NOT. ALLOCATED ( rad_lw_hr ) )  THEN
2548             ALLOCATE ( rad_lw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2549             rad_lw_hr = 0.0_wp
2550          ENDIF
2551
2552          IF ( .NOT. ALLOCATED ( rad_lw_hr_av ) )  THEN
2553             ALLOCATE ( rad_lw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2554             rad_lw_hr_av = 0.0_wp
2555          ENDIF
2556
2557          IF ( .NOT. ALLOCATED ( rad_lw_cs_hr ) )  THEN
2558             ALLOCATE ( rad_lw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2559             rad_lw_cs_hr = 0.0_wp
2560          ENDIF
2561
2562          IF ( .NOT. ALLOCATED ( rad_lw_cs_hr_av ) )  THEN
2563             ALLOCATE ( rad_lw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2564             rad_lw_cs_hr_av = 0.0_wp
2565          ENDIF
2566
2567          ALLOCATE ( rad_sw_cs_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2568          ALLOCATE ( rad_sw_cs_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2569          rad_sw_cs_in  = 0.0_wp
2570          rad_sw_cs_out = 0.0_wp
2571
2572          ALLOCATE ( rad_lw_cs_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2573          ALLOCATE ( rad_lw_cs_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2574          rad_lw_cs_in  = 0.0_wp
2575          rad_lw_cs_out = 0.0_wp
2576
2577!
2578!--       Allocate 1-element array for surface temperature
2579!--       (RRTMG anticipates an array as passed argument).
2580          ALLOCATE ( rrtm_tsfc(1) )
2581!
2582!--       Allocate surface emissivity.
2583!--       Values will be given directly before calling rrtm_lw.
2584          ALLOCATE ( rrtm_emis(0:0,1:nbndlw+1) )
2585
2586!
2587!--       Initialize RRTMG
2588          IF ( lw_radiation )  CALL rrtmg_lw_ini ( c_p )
2589          IF ( sw_radiation )  CALL rrtmg_sw_ini ( c_p )
2590
2591!
2592!--       Set input files for RRTMG
2593          INQUIRE(FILE="RAD_SND_DATA", EXIST=snd_exists) 
2594          IF ( .NOT. snd_exists )  THEN
2595             rrtm_input_file = "rrtmg_lw.nc"
2596          ENDIF
2597
2598!
2599!--       Read vertical layers for RRTMG from sounding data
2600!--       The routine provides nzt_rad, hyp_snd(1:nzt_rad),
2601!--       t_snd(nzt+2:nzt_rad), rrtm_play(1:nzt_rad), rrtm_plev(1_nzt_rad+1),
2602!--       rrtm_tlay(nzt+2:nzt_rad), rrtm_tlev(nzt+2:nzt_rad+1)
2603          CALL read_sounding_data
2604
2605!
2606!--       Read trace gas profiles from file. This routine provides
2607!--       the rrtm_ arrays (1:nzt_rad+1)
2608          CALL read_trace_gas_data
2609#endif
2610       ENDIF
2611
2612!
2613!--    Perform user actions if required
2614       CALL user_init_radiation
2615
2616!
2617!--    Calculate radiative fluxes at model start
2618       SELECT CASE ( TRIM( radiation_scheme ) )
2619
2620          CASE ( 'rrtmg' )
2621             CALL radiation_rrtmg
2622
2623          CASE ( 'clear-sky' )
2624             CALL radiation_clearsky
2625
2626          CASE ( 'constant' )
2627             CALL radiation_constant
2628
2629          CASE DEFAULT
2630
2631       END SELECT
2632
2633       RETURN
2634
2635    END SUBROUTINE radiation_init
2636
2637
2638!------------------------------------------------------------------------------!
2639! Description:
2640! ------------
2641!> A simple clear sky radiation model
2642!------------------------------------------------------------------------------!
2643    SUBROUTINE radiation_clearsky
2644
2645
2646       IMPLICIT NONE
2647
2648       INTEGER(iwp) ::  l         !< running index for surface orientation
2649       REAL(wp)     ::  pt1       !< potential temperature at first grid level or mean value at urban layer top
2650       REAL(wp)     ::  pt1_l     !< potential temperature at first grid level or mean value at urban layer top at local subdomain
2651       REAL(wp)     ::  ql1       !< liquid water mixing ratio at first grid level or mean value at urban layer top
2652       REAL(wp)     ::  ql1_l     !< liquid water mixing ratio at first grid level or mean value at urban layer top at local subdomain
2653
2654       TYPE(surf_type), POINTER ::  surf !< pointer on respective surface type, used to generalize routine   
2655
2656!
2657!--    Calculate current zenith angle
2658       CALL calc_zenith
2659
2660!
2661!--    Calculate sky transmissivity
2662       sky_trans = 0.6_wp + 0.2_wp * zenith(0)
2663
2664!
2665!--    Calculate value of the Exner function at model surface
2666!
2667!--    In case averaged radiation is used, calculate mean temperature and
2668!--    liquid water mixing ratio at the urban-layer top.
2669       IF ( average_radiation ) THEN
2670          pt1   = 0.0_wp
2671          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1   = 0.0_wp
2672
2673          pt1_l = SUM( pt(nzut,nys:nyn,nxl:nxr) )
2674          IF ( bulk_cloud_model  .OR.  cloud_droplets  )  ql1_l = SUM( ql(nzut,nys:nyn,nxl:nxr) )
2675
2676#if defined( __parallel )     
2677          IF ( collective_wait )  CALL MPI_BARRIER( comm2d, ierr )
2678          CALL MPI_ALLREDUCE( pt1_l, pt1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
2679          IF ( ierr /= 0 ) THEN
2680              WRITE(9,*) 'Error MPI_AllReduce1:', ierr, pt1_l, pt1
2681              FLUSH(9)
2682          ENDIF
2683
2684          IF ( bulk_cloud_model  .OR.  cloud_droplets ) THEN
2685              CALL MPI_ALLREDUCE( ql1_l, ql1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
2686              IF ( ierr /= 0 ) THEN
2687                  WRITE(9,*) 'Error MPI_AllReduce2:', ierr, ql1_l, ql1
2688                  FLUSH(9)
2689              ENDIF
2690          ENDIF
2691#else
2692          pt1 = pt1_l 
2693          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1 = ql1_l
2694#endif
2695
2696          IF ( bulk_cloud_model  .OR.  cloud_droplets  )  pt1 = pt1 + lv_d_cp / exner(nzut) * ql1
2697!
2698!--       Finally, divide by number of grid points
2699          pt1 = pt1 / REAL( ( nx + 1 ) * ( ny + 1 ), KIND=wp )
2700       ENDIF
2701!
2702!--    Call clear-sky calculation for each surface orientation.
2703!--    First, horizontal surfaces
2704       surf => surf_lsm_h
2705       CALL radiation_clearsky_surf
2706       surf => surf_usm_h
2707       CALL radiation_clearsky_surf
2708!
2709!--    Vertical surfaces
2710       DO  l = 0, 3
2711          surf => surf_lsm_v(l)
2712          CALL radiation_clearsky_surf
2713          surf => surf_usm_v(l)
2714          CALL radiation_clearsky_surf
2715       ENDDO
2716
2717       CONTAINS
2718
2719          SUBROUTINE radiation_clearsky_surf
2720
2721             IMPLICIT NONE
2722
2723             INTEGER(iwp) ::  i         !< index x-direction
2724             INTEGER(iwp) ::  j         !< index y-direction
2725             INTEGER(iwp) ::  k         !< index z-direction
2726             INTEGER(iwp) ::  m         !< running index for surface elements
2727
2728             IF ( surf%ns < 1 )  RETURN
2729
2730!
2731!--          Calculate radiation fluxes and net radiation (rad_net) assuming
2732!--          homogeneous urban radiation conditions.
2733             IF ( average_radiation ) THEN       
2734
2735                k = nzut
2736
2737                surf%rad_sw_in  = solar_constant * sky_trans * zenith(0)
2738                surf%rad_sw_out = albedo_urb * surf%rad_sw_in
2739               
2740                surf%rad_lw_in  = 0.8_wp * sigma_sb * (pt1 * exner(k+1))**4
2741
2742                surf%rad_lw_out = emissivity_urb * sigma_sb * (t_rad_urb)**4   &
2743                                    + (1.0_wp - emissivity_urb) * surf%rad_lw_in
2744
2745                surf%rad_net = surf%rad_sw_in - surf%rad_sw_out                &
2746                             + surf%rad_lw_in - surf%rad_lw_out
2747
2748                surf%rad_lw_out_change_0 = 3.0_wp * emissivity_urb * sigma_sb  &
2749                                           * (t_rad_urb)**3
2750
2751!
2752!--          Calculate radiation fluxes and net radiation (rad_net) for each surface
2753!--          element.
2754             ELSE
2755
2756                DO  m = 1, surf%ns
2757                   i = surf%i(m)
2758                   j = surf%j(m)
2759                   k = surf%k(m)
2760
2761                   surf%rad_sw_in(m) = solar_constant * sky_trans * zenith(0)
2762
2763!
2764!--                Weighted average according to surface fraction.
2765!--                ATTENTION: when radiation interactions are switched on the
2766!--                calculated fluxes below are not actually used as they are
2767!--                overwritten in radiation_interaction.
2768                   surf%rad_sw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
2769                                          surf%albedo(ind_veg_wall,m)          &
2770                                        + surf%frac(ind_pav_green,m) *         &
2771                                          surf%albedo(ind_pav_green,m)         &
2772                                        + surf%frac(ind_wat_win,m)   *         &
2773                                          surf%albedo(ind_wat_win,m) )         &
2774                                        * surf%rad_sw_in(m)
2775
2776                   surf%rad_lw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
2777                                          surf%emissivity(ind_veg_wall,m)      &
2778                                        + surf%frac(ind_pav_green,m) *         &
2779                                          surf%emissivity(ind_pav_green,m)     &
2780                                        + surf%frac(ind_wat_win,m)   *         &
2781                                          surf%emissivity(ind_wat_win,m)       &
2782                                        )                                      &
2783                                        * sigma_sb                             &
2784                                        * ( surf%pt_surface(m) * exner(nzb) )**4
2785
2786                   surf%rad_lw_out_change_0(m) =                               &
2787                                      ( surf%frac(ind_veg_wall,m)  *           &
2788                                        surf%emissivity(ind_veg_wall,m)        &
2789                                      + surf%frac(ind_pav_green,m) *           &
2790                                        surf%emissivity(ind_pav_green,m)       &
2791                                      + surf%frac(ind_wat_win,m)   *           &
2792                                        surf%emissivity(ind_wat_win,m)         &
2793                                      ) * 3.0_wp * sigma_sb                    &
2794                                      * ( surf%pt_surface(m) * exner(nzb) )** 3
2795
2796
2797                   IF ( bulk_cloud_model  .OR.  cloud_droplets  )  THEN
2798                      pt1 = pt(k,j,i) + lv_d_cp / exner(k) * ql(k,j,i)
2799                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb * (pt1 * exner(k))**4
2800                   ELSE
2801                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb * (pt(k,j,i) * exner(k))**4
2802                   ENDIF
2803
2804                   surf%rad_net(m) = surf%rad_sw_in(m) - surf%rad_sw_out(m)    &
2805                                   + surf%rad_lw_in(m) - surf%rad_lw_out(m)
2806
2807                ENDDO
2808
2809             ENDIF
2810
2811!
2812!--          Fill out values in radiation arrays
2813             DO  m = 1, surf%ns
2814                i = surf%i(m)
2815                j = surf%j(m)
2816                rad_sw_in(0,j,i) = surf%rad_sw_in(m)
2817                rad_sw_out(0,j,i) = surf%rad_sw_out(m)
2818                rad_lw_in(0,j,i) = surf%rad_lw_in(m)
2819                rad_lw_out(0,j,i) = surf%rad_lw_out(m)
2820             ENDDO
2821 
2822          END SUBROUTINE radiation_clearsky_surf
2823
2824    END SUBROUTINE radiation_clearsky
2825
2826
2827!------------------------------------------------------------------------------!
2828! Description:
2829! ------------
2830!> This scheme keeps the prescribed net radiation constant during the run
2831!------------------------------------------------------------------------------!
2832    SUBROUTINE radiation_constant
2833
2834
2835       IMPLICIT NONE
2836
2837       INTEGER(iwp) ::  l         !< running index for surface orientation
2838
2839       REAL(wp)     ::  pt1       !< potential temperature at first grid level or mean value at urban layer top
2840       REAL(wp)     ::  pt1_l     !< potential temperature at first grid level or mean value at urban layer top at local subdomain
2841       REAL(wp)     ::  ql1       !< liquid water mixing ratio at first grid level or mean value at urban layer top
2842       REAL(wp)     ::  ql1_l     !< liquid water mixing ratio at first grid level or mean value at urban layer top at local subdomain
2843
2844       TYPE(surf_type), POINTER ::  surf !< pointer on respective surface type, used to generalize routine
2845
2846!
2847!--    In case averaged radiation is used, calculate mean temperature and
2848!--    liquid water mixing ratio at the urban-layer top.
2849       IF ( average_radiation ) THEN   
2850          pt1   = 0.0_wp
2851          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1   = 0.0_wp
2852
2853          pt1_l = SUM( pt(nzut,nys:nyn,nxl:nxr) )
2854          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1_l = SUM( ql(nzut,nys:nyn,nxl:nxr) )
2855
2856#if defined( __parallel )     
2857          IF ( collective_wait )  CALL MPI_BARRIER( comm2d, ierr )
2858          CALL MPI_ALLREDUCE( pt1_l, pt1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
2859          IF ( ierr /= 0 ) THEN
2860              WRITE(9,*) 'Error MPI_AllReduce3:', ierr, pt1_l, pt1
2861              FLUSH(9)
2862          ENDIF
2863          IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
2864             CALL MPI_ALLREDUCE( ql1_l, ql1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
2865             IF ( ierr /= 0 ) THEN
2866                 WRITE(9,*) 'Error MPI_AllReduce4:', ierr, ql1_l, ql1
2867                 FLUSH(9)
2868             ENDIF
2869          ENDIF
2870#else
2871          pt1 = pt1_l
2872          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1 = ql1_l
2873#endif
2874          IF ( bulk_cloud_model  .OR.  cloud_droplets )  pt1 = pt1 + lv_d_cp / exner(nzut+1) * ql1
2875!
2876!--       Finally, divide by number of grid points
2877          pt1 = pt1 / REAL( ( nx + 1 ) * ( ny + 1 ), KIND=wp )
2878       ENDIF
2879
2880!
2881!--    First, horizontal surfaces
2882       surf => surf_lsm_h
2883       CALL radiation_constant_surf
2884       surf => surf_usm_h
2885       CALL radiation_constant_surf
2886!
2887!--    Vertical surfaces
2888       DO  l = 0, 3
2889          surf => surf_lsm_v(l)
2890          CALL radiation_constant_surf
2891          surf => surf_usm_v(l)
2892          CALL radiation_constant_surf
2893       ENDDO
2894
2895       CONTAINS
2896
2897          SUBROUTINE radiation_constant_surf
2898
2899             IMPLICIT NONE
2900
2901             INTEGER(iwp) ::  i         !< index x-direction
2902             INTEGER(iwp) ::  ioff      !< offset between surface element and adjacent grid point along x
2903             INTEGER(iwp) ::  j         !< index y-direction
2904             INTEGER(iwp) ::  joff      !< offset between surface element and adjacent grid point along y
2905             INTEGER(iwp) ::  k         !< index z-direction
2906             INTEGER(iwp) ::  koff      !< offset between surface element and adjacent grid point along z
2907             INTEGER(iwp) ::  m         !< running index for surface elements
2908
2909             IF ( surf%ns < 1 )  RETURN
2910
2911!--          Calculate homogenoeus urban radiation fluxes
2912             IF ( average_radiation ) THEN
2913
2914                surf%rad_net = net_radiation
2915
2916                surf%rad_lw_in  = 0.8_wp * sigma_sb * (pt1 * exner(nzut+1))**4
2917
2918                surf%rad_lw_out = emissivity_urb * sigma_sb * (t_rad_urb)**4   &
2919                                    + ( 1.0_wp - emissivity_urb )             & ! shouldn't be this a bulk value -- emissivity_urb?
2920                                    * surf%rad_lw_in
2921
2922                surf%rad_lw_out_change_0 = 3.0_wp * emissivity_urb * sigma_sb  &
2923                                           * t_rad_urb**3
2924
2925                surf%rad_sw_in = ( surf%rad_net - surf%rad_lw_in               &
2926                                     + surf%rad_lw_out )                       &
2927                                     / ( 1.0_wp - albedo_urb )
2928
2929                surf%rad_sw_out =  albedo_urb * surf%rad_sw_in
2930
2931!
2932!--          Calculate radiation fluxes for each surface element
2933             ELSE
2934!
2935!--             Determine index offset between surface element and adjacent
2936!--             atmospheric grid point
2937                ioff = surf%ioff
2938                joff = surf%joff
2939                koff = surf%koff
2940
2941!
2942!--             Prescribe net radiation and estimate the remaining radiative fluxes
2943                DO  m = 1, surf%ns
2944                   i = surf%i(m)
2945                   j = surf%j(m)
2946                   k = surf%k(m)
2947
2948                   surf%rad_net(m) = net_radiation
2949
2950                   IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
2951                      pt1 = pt(k,j,i) + lv_d_cp / exner(k) * ql(k,j,i)
2952                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb * (pt1 * exner(k))**4
2953                   ELSE
2954                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb *                 &
2955                                             ( pt(k,j,i) * exner(k) )**4
2956                   ENDIF
2957
2958!
2959!--                Weighted average according to surface fraction.
2960                   surf%rad_lw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
2961                                          surf%emissivity(ind_veg_wall,m)      &
2962                                        + surf%frac(ind_pav_green,m) *         &
2963                                          surf%emissivity(ind_pav_green,m)     &
2964                                        + surf%frac(ind_wat_win,m)   *         &
2965                                          surf%emissivity(ind_wat_win,m)       &
2966                                        )                                      &
2967                                      * sigma_sb                               &
2968                                      * ( surf%pt_surface(m) * exner(nzb) )**4
2969
2970                   surf%rad_sw_in(m) = ( surf%rad_net(m) - surf%rad_lw_in(m)   &
2971                                       + surf%rad_lw_out(m) )                  &
2972                                       / ( 1.0_wp -                            &
2973                                          ( surf%frac(ind_veg_wall,m)  *       &
2974                                            surf%albedo(ind_veg_wall,m)        &
2975                                         +  surf%frac(ind_pav_green,m) *       &
2976                                            surf%albedo(ind_pav_green,m)       &
2977                                         +  surf%frac(ind_wat_win,m)   *       &
2978                                            surf%albedo(ind_wat_win,m) )       &
2979                                         )
2980
2981                   surf%rad_sw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
2982                                          surf%albedo(ind_veg_wall,m)          &
2983                                        + surf%frac(ind_pav_green,m) *         &
2984                                          surf%albedo(ind_pav_green,m)         &
2985                                        + surf%frac(ind_wat_win,m)   *         &
2986                                          surf%albedo(ind_wat_win,m) )         &
2987                                      * surf%rad_sw_in(m)
2988
2989                ENDDO
2990
2991             ENDIF
2992
2993!
2994!--          Fill out values in radiation arrays
2995             DO  m = 1, surf%ns
2996                i = surf%i(m)
2997                j = surf%j(m)
2998                rad_sw_in(0,j,i) = surf%rad_sw_in(m)
2999                rad_sw_out(0,j,i) = surf%rad_sw_out(m)
3000                rad_lw_in(0,j,i) = surf%rad_lw_in(m)
3001                rad_lw_out(0,j,i) = surf%rad_lw_out(m)
3002             ENDDO
3003
3004          END SUBROUTINE radiation_constant_surf
3005         
3006
3007    END SUBROUTINE radiation_constant
3008
3009!------------------------------------------------------------------------------!
3010! Description:
3011! ------------
3012!> Header output for radiation model
3013!------------------------------------------------------------------------------!
3014    SUBROUTINE radiation_header ( io )
3015
3016
3017       IMPLICIT NONE
3018 
3019       INTEGER(iwp), INTENT(IN) ::  io            !< Unit of the output file
3020   
3021
3022       
3023!
3024!--    Write radiation model header
3025       WRITE( io, 3 )
3026
3027       IF ( radiation_scheme == "constant" )  THEN
3028          WRITE( io, 4 ) net_radiation
3029       ELSEIF ( radiation_scheme == "clear-sky" )  THEN
3030          WRITE( io, 5 )
3031       ELSEIF ( radiation_scheme == "rrtmg" )  THEN
3032          WRITE( io, 6 )
3033          IF ( .NOT. lw_radiation )  WRITE( io, 10 )
3034          IF ( .NOT. sw_radiation )  WRITE( io, 11 )
3035       ENDIF
3036
3037       IF ( albedo_type_f%from_file  .OR.  vegetation_type_f%from_file  .OR.   &
3038            pavement_type_f%from_file  .OR.  water_type_f%from_file  .OR.      &
3039            building_type_f%from_file )  THEN
3040             WRITE( io, 13 )
3041       ELSE 
3042          IF ( albedo_type == 0 )  THEN
3043             WRITE( io, 7 ) albedo
3044          ELSE
3045             WRITE( io, 8 ) TRIM( albedo_type_name(albedo_type) )
3046          ENDIF
3047       ENDIF
3048       IF ( constant_albedo )  THEN
3049          WRITE( io, 9 )
3050       ENDIF
3051       
3052       WRITE( io, 12 ) dt_radiation
3053 
3054
3055 3 FORMAT (//' Radiation model information:'/                                  &
3056              ' ----------------------------'/)
3057 4 FORMAT ('    --> Using constant net radiation: net_radiation = ', F6.2,     &
3058           // 'W/m**2')
3059 5 FORMAT ('    --> Simple radiation scheme for clear sky is used (no clouds,',&
3060                   ' default)')
3061 6 FORMAT ('    --> RRTMG scheme is used')
3062 7 FORMAT (/'    User-specific surface albedo: albedo =', F6.3)
3063 8 FORMAT (/'    Albedo is set for land surface type: ', A)
3064 9 FORMAT (/'    --> Albedo is fixed during the run')
306510 FORMAT (/'    --> Longwave radiation is disabled')
306611 FORMAT (/'    --> Shortwave radiation is disabled.')
306712 FORMAT  ('    Timestep: dt_radiation = ', F6.2, '  s')
306813 FORMAT (/'    Albedo is set individually for each xy-location, according ', &
3069                 'to given surface type.')
3070
3071
3072    END SUBROUTINE radiation_header
3073   
3074
3075!------------------------------------------------------------------------------!
3076! Description:
3077! ------------
3078!> Parin for &radiation_parameters for radiation model
3079!------------------------------------------------------------------------------!
3080    SUBROUTINE radiation_parin
3081
3082
3083       IMPLICIT NONE
3084
3085       CHARACTER (LEN=80) ::  line  !< dummy string that contains the current line of the parameter file
3086       
3087       NAMELIST /radiation_par/   albedo, albedo_lw_dif, albedo_lw_dir,         &
3088                                  albedo_sw_dif, albedo_sw_dir, albedo_type,    &
3089                                  constant_albedo, dt_radiation, emissivity,    &
3090                                  lw_radiation, max_raytracing_dist,            &
3091                                  min_irrf_value, mrt_geom_human,               &
3092                                  mrt_include_sw, mrt_nlevels,                  &
3093                                  mrt_skip_roof, net_radiation, nrefsteps,      &
3094                                  plant_lw_interact, rad_angular_discretization,&
3095                                  radiation_interactions_on, radiation_scheme,  &
3096                                  raytrace_discrete_azims,                      &
3097                                  raytrace_discrete_elevs, raytrace_mpi_rma,    &
3098                                  skip_time_do_radiation, surface_reflections,  &
3099                                  svfnorm_report_thresh, sw_radiation,          &
3100                                  unscheduled_radiation_calls
3101
3102   
3103       NAMELIST /radiation_parameters/ albedo, albedo_lw_dif, albedo_lw_dir,    &
3104                                  albedo_sw_dif, albedo_sw_dir, albedo_type,    &
3105                                  constant_albedo, dt_radiation, emissivity,    &
3106                                  lw_radiation, max_raytracing_dist,            &
3107                                  min_irrf_value, mrt_geom_human,               &
3108                                  mrt_include_sw, mrt_nlevels,                  &
3109                                  mrt_skip_roof, net_radiation, nrefsteps,      &
3110                                  plant_lw_interact, rad_angular_discretization,&
3111                                  radiation_interactions_on, radiation_scheme,  &
3112                                  raytrace_discrete_azims,                      &
3113                                  raytrace_discrete_elevs, raytrace_mpi_rma,    &
3114                                  skip_time_do_radiation, surface_reflections,  &
3115                                  svfnorm_report_thresh, sw_radiation,          &
3116                                  unscheduled_radiation_calls
3117   
3118       line = ' '
3119       
3120!
3121!--    Try to find radiation model namelist
3122       REWIND ( 11 )
3123       line = ' '
3124       DO WHILE ( INDEX( line, '&radiation_parameters' ) == 0 )
3125          READ ( 11, '(A)', END=12 )  line
3126       ENDDO
3127       BACKSPACE ( 11 )
3128
3129!
3130!--    Read user-defined namelist
3131       READ ( 11, radiation_parameters, ERR = 10 )
3132
3133!
3134!--    Set flag that indicates that the radiation model is switched on
3135       radiation = .TRUE.
3136
3137       GOTO 14
3138
3139 10    BACKSPACE( 11 )
3140       READ( 11 , '(A)') line
3141       CALL parin_fail_message( 'radiation_parameters', line )
3142!
3143!--    Try to find old namelist
3144 12    REWIND ( 11 )
3145       line = ' '
3146       DO WHILE ( INDEX( line, '&radiation_par' ) == 0 )
3147          READ ( 11, '(A)', END=14 )  line
3148       ENDDO
3149       BACKSPACE ( 11 )
3150
3151!
3152!--    Read user-defined namelist
3153       READ ( 11, radiation_par, ERR = 13, END = 14 )
3154
3155       message_string = 'namelist radiation_par is deprecated and will be ' // &
3156                     'removed in near future. Please use namelist ' //         &
3157                     'radiation_parameters instead'
3158       CALL message( 'radiation_parin', 'PA0487', 0, 1, 0, 6, 0 )
3159
3160!
3161!--    Set flag that indicates that the radiation model is switched on
3162       radiation = .TRUE.
3163
3164       IF ( .NOT.  radiation_interactions_on  .AND.  surface_reflections )  THEN
3165          message_string = 'surface_reflections is allowed only when '      // &
3166               'radiation_interactions_on is set to TRUE'
3167          CALL message( 'radiation_parin', 'PA0293',1, 2, 0, 6, 0 )
3168       ENDIF
3169
3170       GOTO 14
3171
3172 13    BACKSPACE( 11 )
3173       READ( 11 , '(A)') line
3174       CALL parin_fail_message( 'radiation_par', line )
3175
3176 14    CONTINUE
3177       
3178    END SUBROUTINE radiation_parin
3179
3180
3181!------------------------------------------------------------------------------!
3182! Description:
3183! ------------
3184!> Implementation of the RRTMG radiation_scheme
3185!------------------------------------------------------------------------------!
3186    SUBROUTINE radiation_rrtmg
3187
3188#if defined ( __rrtmg )
3189       USE indices,                                                            &
3190           ONLY:  nbgp
3191
3192       USE particle_attributes,                                                &
3193           ONLY:  grid_particles, number_of_particles, particles,              &
3194                  particle_advection_start, prt_count
3195
3196       IMPLICIT NONE
3197
3198
3199       INTEGER(iwp) ::  i, j, k, l, m, n !< loop indices
3200       INTEGER(iwp) ::  k_topo     !< topography top index
3201
3202       REAL(wp)     ::  nc_rad, &    !< number concentration of cloud droplets
3203                        s_r2,   &    !< weighted sum over all droplets with r^2
3204                        s_r3         !< weighted sum over all droplets with r^3
3205
3206       REAL(wp), DIMENSION(0:nzt+1) :: pt_av, q_av, ql_av
3207!
3208!--    Just dummy arguments
3209       REAL(wp), DIMENSION(:,:,:), ALLOCATABLE :: rrtm_lw_taucld_dum,          &
3210                                                  rrtm_lw_tauaer_dum,          &
3211                                                  rrtm_sw_taucld_dum,          &
3212                                                  rrtm_sw_ssacld_dum,          &
3213                                                  rrtm_sw_asmcld_dum,          &
3214                                                  rrtm_sw_fsfcld_dum,          &
3215                                                  rrtm_sw_tauaer_dum,          &
3216                                                  rrtm_sw_ssaaer_dum,          &
3217                                                  rrtm_sw_asmaer_dum,          &
3218                                                  rrtm_sw_ecaer_dum
3219
3220!
3221!--    Calculate current (cosine of) zenith angle and whether the sun is up
3222       CALL calc_zenith     
3223!
3224!--    Calculate surface albedo. In case average radiation is applied,
3225!--    this is not required.
3226#if defined( __netcdf )
3227       IF ( .NOT. constant_albedo )  THEN
3228!
3229!--       Horizontally aligned default, natural and urban surfaces
3230          CALL calc_albedo( surf_lsm_h    )
3231          CALL calc_albedo( surf_usm_h    )
3232!
3233!--       Vertically aligned default, natural and urban surfaces
3234          DO  l = 0, 3
3235             CALL calc_albedo( surf_lsm_v(l) )
3236             CALL calc_albedo( surf_usm_v(l) )
3237          ENDDO
3238       ENDIF
3239#endif
3240
3241!
3242!--    Prepare input data for RRTMG
3243
3244!
3245!--    In case of large scale forcing with surface data, calculate new pressure
3246!--    profile. nzt_rad might be modified by these calls and all required arrays
3247!--    will then be re-allocated
3248       IF ( large_scale_forcing  .AND.  lsf_surf )  THEN
3249          CALL read_sounding_data
3250          CALL read_trace_gas_data
3251       ENDIF
3252
3253
3254       IF ( average_radiation ) THEN
3255
3256          rrtm_asdir(1)  = albedo_urb
3257          rrtm_asdif(1)  = albedo_urb
3258          rrtm_aldir(1)  = albedo_urb
3259          rrtm_aldif(1)  = albedo_urb
3260
3261          rrtm_emis = emissivity_urb
3262!
3263!--       Calculate mean pt profile. Actually, only one height level is required.
3264          CALL calc_mean_profile( pt, 4 )
3265          pt_av = hom(:, 1, 4, 0)
3266         
3267          IF ( humidity )  THEN
3268             CALL calc_mean_profile( q, 41 )
3269             q_av  = hom(:, 1, 41, 0)
3270          ENDIF
3271!
3272!--       Prepare profiles of temperature and H2O volume mixing ratio
3273          rrtm_tlev(0,nzb+1) = t_rad_urb
3274
3275          IF ( bulk_cloud_model )  THEN
3276
3277             CALL calc_mean_profile( ql, 54 )
3278             ! average ql is now in hom(:, 1, 54, 0)
3279             ql_av = hom(:, 1, 54, 0)
3280             
3281             DO k = nzb+1, nzt+1
3282                rrtm_tlay(0,k) = pt_av(k) * ( (hyp(k) ) / 100000._wp       &
3283                                 )**.286_wp + lv_d_cp * ql_av(k)
3284                rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * (q_av(k) - ql_av(k))
3285             ENDDO
3286          ELSE
3287             DO k = nzb+1, nzt+1
3288                rrtm_tlay(0,k) = pt_av(k) * ( (hyp(k) ) / 100000._wp       &
3289                                 )**.286_wp
3290             ENDDO
3291
3292             IF ( humidity )  THEN
3293                DO k = nzb+1, nzt+1
3294                   rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * q_av(k)
3295                ENDDO
3296             ELSE
3297                rrtm_h2ovmr(0,nzb+1:nzt+1) = 0.0_wp
3298             ENDIF
3299          ENDIF
3300
3301!
3302!--       Avoid temperature/humidity jumps at the top of the LES domain by
3303!--       linear interpolation from nzt+2 to nzt+7
3304          DO k = nzt+2, nzt+7
3305             rrtm_tlay(0,k) = rrtm_tlay(0,nzt+1)                            &
3306                           + ( rrtm_tlay(0,nzt+8) - rrtm_tlay(0,nzt+1) )    &
3307                           / ( rrtm_play(0,nzt+8) - rrtm_play(0,nzt+1) )    &
3308                           * ( rrtm_play(0,k) - rrtm_play(0,nzt+1) )
3309
3310             rrtm_h2ovmr(0,k) = rrtm_h2ovmr(0,nzt+1)                        &
3311                           + ( rrtm_h2ovmr(0,nzt+8) - rrtm_h2ovmr(0,nzt+1) )&
3312                           / ( rrtm_play(0,nzt+8)   - rrtm_play(0,nzt+1)   )&
3313                           * ( rrtm_play(0,k) - rrtm_play(0,nzt+1) )
3314
3315          ENDDO
3316
3317!--       Linear interpolate to zw grid
3318          DO k = nzb+2, nzt+8
3319             rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k) -        &
3320                                rrtm_tlay(0,k-1))                           &
3321                                / ( rrtm_play(0,k) - rrtm_play(0,k-1) )     &
3322                                * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
3323          ENDDO
3324
3325
3326!
3327!--       Calculate liquid water path and cloud fraction for each column.
3328!--       Note that LWP is required in g/m2 instead of kg/kg m.
3329          rrtm_cldfr  = 0.0_wp
3330          rrtm_reliq  = 0.0_wp
3331          rrtm_cliqwp = 0.0_wp
3332          rrtm_icld   = 0
3333
3334          IF ( bulk_cloud_model )  THEN
3335             DO k = nzb+1, nzt+1
3336                rrtm_cliqwp(0,k) =  ql_av(k) * 1000._wp *                   &
3337                                    (rrtm_plev(0,k) - rrtm_plev(0,k+1))     &
3338                                    * 100._wp / g 
3339
3340                IF ( rrtm_cliqwp(0,k) > 0._wp )  THEN
3341                   rrtm_cldfr(0,k) = 1._wp
3342                   IF ( rrtm_icld == 0 )  rrtm_icld = 1
3343
3344!
3345!--                Calculate cloud droplet effective radius
3346                   rrtm_reliq(0,k) = 1.0E6_wp * ( 3.0_wp * ql_av(k)         &
3347                                     * rho_surface                          &
3348                                     / ( 4.0_wp * pi * nc_const * rho_l )   &
3349                                     )**0.33333333333333_wp                 &
3350                                     * EXP( LOG( sigma_gc )**2 )
3351!
3352!--                Limit effective radius
3353                   IF ( rrtm_reliq(0,k) > 0.0_wp )  THEN
3354                      rrtm_reliq(0,k) = MAX(rrtm_reliq(0,k),2.5_wp)
3355                      rrtm_reliq(0,k) = MIN(rrtm_reliq(0,k),60.0_wp)
3356                   ENDIF
3357                ENDIF
3358             ENDDO
3359          ENDIF
3360
3361!
3362!--       Set surface temperature
3363          rrtm_tsfc = t_rad_urb
3364         
3365          IF ( lw_radiation )  THEN       
3366         
3367             CALL rrtmg_lw( 1, nzt_rad      , rrtm_icld    , rrtm_idrv      ,&
3368             rrtm_play       , rrtm_plev    , rrtm_tlay    , rrtm_tlev      ,&
3369             rrtm_tsfc       , rrtm_h2ovmr  , rrtm_o3vmr   , rrtm_co2vmr    ,&
3370             rrtm_ch4vmr     , rrtm_n2ovmr  , rrtm_o2vmr   , rrtm_cfc11vmr  ,&
3371             rrtm_cfc12vmr   , rrtm_cfc22vmr, rrtm_ccl4vmr , rrtm_emis      ,&
3372             rrtm_inflglw    , rrtm_iceflglw, rrtm_liqflglw, rrtm_cldfr     ,&
3373             rrtm_lw_taucld  , rrtm_cicewp  , rrtm_cliqwp  , rrtm_reice     ,& 
3374             rrtm_reliq      , rrtm_lw_tauaer,                               &
3375             rrtm_lwuflx     , rrtm_lwdflx  , rrtm_lwhr  ,                   &
3376             rrtm_lwuflxc    , rrtm_lwdflxc , rrtm_lwhrc ,                   &
3377             rrtm_lwuflx_dt  ,  rrtm_lwuflxc_dt )
3378
3379!
3380!--          Save fluxes
3381             DO k = nzb, nzt+1
3382                rad_lw_in(k,:,:)  = rrtm_lwdflx(0,k)
3383                rad_lw_out(k,:,:) = rrtm_lwuflx(0,k)
3384             ENDDO
3385             rad_lw_in_diff(:,:) = rad_lw_in(0,:,:)
3386!
3387!--          Save heating rates (convert from K/d to K/h).
3388!--          Further, even though an aggregated radiation is computed, map
3389!--          signle-column profiles on top of any topography, in order to
3390!--          obtain correct near surface radiation heating/cooling rates.
3391             DO  i = nxl, nxr
3392                DO  j = nys, nyn
3393                   k_topo = get_topography_top_index_ji( j, i, 's' )
3394                   DO k = k_topo+1, nzt+1
3395                      rad_lw_hr(k,j,i)     = rrtm_lwhr(0,k-k_topo)  * d_hours_day
3396                      rad_lw_cs_hr(k,j,i)  = rrtm_lwhrc(0,k-k_topo) * d_hours_day
3397                   ENDDO
3398                ENDDO
3399             ENDDO
3400
3401          ENDIF
3402
3403          IF ( sw_radiation .AND. sun_up )  THEN
3404             CALL rrtmg_sw( 1, nzt_rad      , rrtm_icld     , rrtm_iaer      ,&
3405             rrtm_play      , rrtm_plev     , rrtm_tlay     , rrtm_tlev      ,&
3406             rrtm_tsfc      , rrtm_h2ovmr   , rrtm_o3vmr    , rrtm_co2vmr    ,&
3407             rrtm_ch4vmr    , rrtm_n2ovmr   , rrtm_o2vmr    , rrtm_asdir     ,&
3408             rrtm_asdif     , rrtm_aldir    , rrtm_aldif    , zenith         ,&
3409             0.0_wp         , day_of_year   , solar_constant, rrtm_inflgsw   ,&
3410             rrtm_iceflgsw  , rrtm_liqflgsw , rrtm_cldfr    , rrtm_sw_taucld ,&
3411             rrtm_sw_ssacld , rrtm_sw_asmcld, rrtm_sw_fsfcld, rrtm_cicewp    ,&
3412             rrtm_cliqwp    , rrtm_reice    , rrtm_reliq    , rrtm_sw_tauaer ,&
3413             rrtm_sw_ssaaer , rrtm_sw_asmaer, rrtm_sw_ecaer , rrtm_swuflx    ,&
3414             rrtm_swdflx    , rrtm_swhr     , rrtm_swuflxc  , rrtm_swdflxc   ,&
3415             rrtm_swhrc     , rrtm_dirdflux , rrtm_difdflux )
3416 
3417!
3418!--          Save fluxes:
3419!--          - whole domain
3420             DO k = nzb, nzt+1
3421                rad_sw_in(k,:,:)  = rrtm_swdflx(0,k)
3422                rad_sw_out(k,:,:) = rrtm_swuflx(0,k)
3423             ENDDO
3424!--          - direct and diffuse SW at urban-surface-layer (required by RTM)
3425             rad_sw_in_dir(:,:) = rrtm_dirdflux(0,nzb)
3426             rad_sw_in_diff(:,:) = rrtm_difdflux(0,nzb)
3427
3428!
3429!--          Save heating rates (convert from K/d to K/s)
3430             DO k = nzb+1, nzt+1
3431                rad_sw_hr(k,:,:)     = rrtm_swhr(0,k)  * d_hours_day
3432                rad_sw_cs_hr(k,:,:)  = rrtm_swhrc(0,k) * d_hours_day
3433             ENDDO
3434!
3435!--       Solar radiation is zero during night
3436          ELSE
3437             rad_sw_in  = 0.0_wp
3438             rad_sw_out = 0.0_wp
3439             rad_sw_in_dir(:,:) = 0.0_wp
3440             rad_sw_in_diff(:,:) = 0.0_wp
3441          ENDIF
3442!
3443!--    RRTMG is called for each (j,i) grid point separately, starting at the
3444!--    highest topography level. Here no RTM is used since average_radiation is false
3445       ELSE
3446!
3447!--       Loop over all grid points
3448          DO i = nxl, nxr
3449             DO j = nys, nyn
3450
3451!
3452!--             Prepare profiles of temperature and H2O volume mixing ratio
3453                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
3454                   rrtm_tlev(0,nzb+1) = surf_lsm_h%pt_surface(m) * exner(nzb)
3455                ENDDO
3456                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
3457                   rrtm_tlev(0,nzb+1) = surf_usm_h%pt_surface(m) * exner(nzb)
3458                ENDDO
3459
3460
3461                IF ( bulk_cloud_model )  THEN
3462                   DO k = nzb+1, nzt+1
3463                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)                    &
3464                                        + lv_d_cp * ql(k,j,i)
3465                      rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * (q(k,j,i) - ql(k,j,i))
3466                   ENDDO
3467                ELSEIF ( cloud_droplets )  THEN
3468                   DO k = nzb+1, nzt+1
3469                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)                     &
3470                                        + lv_d_cp * ql(k,j,i)
3471                      rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * q(k,j,i) 
3472                   ENDDO
3473                ELSE
3474                   DO k = nzb+1, nzt+1
3475                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)
3476                   ENDDO
3477
3478                   IF ( humidity )  THEN
3479                      DO k = nzb+1, nzt+1
3480                         rrtm_h2ovmr(0,k) =  mol_mass_air_d_wv * q(k,j,i)
3481                      ENDDO   
3482                   ELSE
3483                      rrtm_h2ovmr(0,nzb+1:nzt+1) = 0.0_wp
3484                   ENDIF
3485                ENDIF
3486
3487!
3488!--             Avoid temperature/humidity jumps at the top of the LES domain by
3489!--             linear interpolation from nzt+2 to nzt+7
3490                DO k = nzt+2, nzt+7
3491                   rrtm_tlay(0,k) = rrtm_tlay(0,nzt+1)                         &
3492                                 + ( rrtm_tlay(0,nzt+8) - rrtm_tlay(0,nzt+1) ) &
3493                                 / ( rrtm_play(0,nzt+8) - rrtm_play(0,nzt+1) ) &
3494                                 * ( rrtm_play(0,k)     - rrtm_play(0,nzt+1) )
3495
3496                   rrtm_h2ovmr(0,k) = rrtm_h2ovmr(0,nzt+1)                     &
3497                              + ( rrtm_h2ovmr(0,nzt+8) - rrtm_h2ovmr(0,nzt+1) )&
3498                              / ( rrtm_play(0,nzt+8)   - rrtm_play(0,nzt+1)   )&
3499                              * ( rrtm_play(0,k)       - rrtm_play(0,nzt+1) )
3500
3501                ENDDO
3502
3503!--             Linear interpolate to zw grid
3504                DO k = nzb+2, nzt+8
3505                   rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k) -     &
3506                                      rrtm_tlay(0,k-1))                        &
3507                                      / ( rrtm_play(0,k) - rrtm_play(0,k-1) )  &
3508                                      * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
3509                ENDDO
3510
3511
3512!
3513!--             Calculate liquid water path and cloud fraction for each column.
3514!--             Note that LWP is required in g/m2 instead of kg/kg m.
3515                rrtm_cldfr  = 0.0_wp
3516                rrtm_reliq  = 0.0_wp
3517                rrtm_cliqwp = 0.0_wp
3518                rrtm_icld   = 0
3519
3520                IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
3521                   DO k = nzb+1, nzt+1
3522                      rrtm_cliqwp(0,k) =  ql(k,j,i) * 1000.0_wp *              &
3523                                          (rrtm_plev(0,k) - rrtm_plev(0,k+1))  &
3524                                          * 100.0_wp / g 
3525
3526                      IF ( rrtm_cliqwp(0,k) > 0.0_wp )  THEN
3527                         rrtm_cldfr(0,k) = 1.0_wp
3528                         IF ( rrtm_icld == 0 )  rrtm_icld = 1
3529
3530!
3531!--                      Calculate cloud droplet effective radius
3532                         IF ( bulk_cloud_model )  THEN
3533!
3534!--                         Calculete effective droplet radius. In case of using
3535!--                         cloud_scheme = 'morrison' and a non reasonable number
3536!--                         of cloud droplets the inital aerosol number 
3537!--                         concentration is considered.
3538                            IF ( microphysics_morrison )  THEN
3539                               IF ( nc(k,j,i) > 1.0E-20_wp )  THEN
3540                                  nc_rad = nc(k,j,i)
3541                               ELSE
3542                                  nc_rad = na_init
3543                               ENDIF
3544                            ELSE
3545                               nc_rad = nc_const
3546                            ENDIF 
3547
3548                            rrtm_reliq(0,k) = 1.0E6_wp * ( 3.0_wp * ql(k,j,i)     &
3549                                              * rho_surface                       &
3550                                              / ( 4.0_wp * pi * nc_rad * rho_l )  &
3551                                              )**0.33333333333333_wp              &
3552                                              * EXP( LOG( sigma_gc )**2 )
3553
3554                         ELSEIF ( cloud_droplets )  THEN
3555                            number_of_particles = prt_count(k,j,i)
3556
3557                            IF (number_of_particles <= 0)  CYCLE
3558                            particles => grid_particles(k,j,i)%particles(1:number_of_particles)
3559                            s_r2 = 0.0_wp
3560                            s_r3 = 0.0_wp
3561
3562                            DO  n = 1, number_of_particles
3563                               IF ( particles(n)%particle_mask )  THEN
3564                                  s_r2 = s_r2 + particles(n)%radius**2 *       &
3565                                         particles(n)%weight_factor
3566                                  s_r3 = s_r3 + particles(n)%radius**3 *       &
3567                                         particles(n)%weight_factor
3568                               ENDIF
3569                            ENDDO
3570
3571                            IF ( s_r2 > 0.0_wp )  rrtm_reliq(0,k) = s_r3 / s_r2
3572
3573                         ENDIF
3574
3575!
3576!--                      Limit effective radius
3577                         IF ( rrtm_reliq(0,k) > 0.0_wp )  THEN
3578                            rrtm_reliq(0,k) = MAX(rrtm_reliq(0,k),2.5_wp)
3579                            rrtm_reliq(0,k) = MIN(rrtm_reliq(0,k),60.0_wp)
3580                        ENDIF
3581                      ENDIF
3582                   ENDDO
3583                ENDIF
3584
3585!
3586!--             Write surface emissivity and surface temperature at current
3587!--             surface element on RRTMG-shaped array.
3588!--             Please note, as RRTMG is a single column model, surface attributes
3589!--             are only obtained from horizontally aligned surfaces (for
3590!--             simplicity). Taking surface attributes from horizontal and
3591!--             vertical walls would lead to multiple solutions. 
3592!--             Moreover, for natural- and urban-type surfaces, several surface
3593!--             classes can exist at a surface element next to each other.
3594!--             To obtain bulk parameters, apply a weighted average for these
3595!--             surfaces.
3596                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
3597                   rrtm_emis = surf_lsm_h%frac(ind_veg_wall,m)  *              &
3598                               surf_lsm_h%emissivity(ind_veg_wall,m)  +        &
3599                               surf_lsm_h%frac(ind_pav_green,m) *              &
3600                               surf_lsm_h%emissivity(ind_pav_green,m) +        & 
3601                               surf_lsm_h%frac(ind_wat_win,m)   *              &
3602                               surf_lsm_h%emissivity(ind_wat_win,m)
3603                   rrtm_tsfc = surf_lsm_h%pt_surface(m) * exner(nzb)
3604                ENDDO             
3605                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
3606                   rrtm_emis = surf_usm_h%frac(ind_veg_wall,m)  *              &
3607                               surf_usm_h%emissivity(ind_veg_wall,m)  +        &
3608                               surf_usm_h%frac(ind_pav_green,m) *              &
3609                               surf_usm_h%emissivity(ind_pav_green,m) +        & 
3610                               surf_usm_h%frac(ind_wat_win,m)   *              &
3611                               surf_usm_h%emissivity(ind_wat_win,m)
3612                   rrtm_tsfc = surf_usm_h%pt_surface(m) * exner(nzb)
3613                ENDDO
3614!
3615!--             Obtain topography top index (lower bound of RRTMG)
3616                k_topo = get_topography_top_index_ji( j, i, 's' )
3617
3618                IF ( lw_radiation )  THEN
3619!
3620!--                Due to technical reasons, copy optical depth to dummy arguments
3621!--                which are allocated on the exact size as the rrtmg_lw is called.
3622!--                As one dimesion is allocated with zero size, compiler complains
3623!--                that rank of the array does not match that of the
3624!--                assumed-shaped arguments in the RRTMG library. In order to
3625!--                avoid this, write to dummy arguments and give pass the entire
3626!--                dummy array. Seems to be the only existing work-around. 
3627                   ALLOCATE( rrtm_lw_taucld_dum(1:nbndlw+1,0:0,k_topo+1:nzt_rad+1) )
3628                   ALLOCATE( rrtm_lw_tauaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndlw+1) )
3629
3630                   rrtm_lw_taucld_dum =                                        &
3631                               rrtm_lw_taucld(1:nbndlw+1,0:0,k_topo+1:nzt_rad+1)
3632                   rrtm_lw_tauaer_dum =                                        &
3633                               rrtm_lw_tauaer(0:0,k_topo+1:nzt_rad+1,1:nbndlw+1)
3634
3635                   CALL rrtmg_lw( 1,                                           &                                       
3636                                  nzt_rad-k_topo,                              &
3637                                  rrtm_icld,                                   &
3638                                  rrtm_idrv,                                   &
3639                                  rrtm_play(:,k_topo+1:nzt_rad+1),             &
3640                                  rrtm_plev(:,k_topo+1:nzt_rad+2),             &
3641                                  rrtm_tlay(:,k_topo+1:nzt_rad+1),             &
3642                                  rrtm_tlev(:,k_topo+1:nzt_rad+2),             &
3643                                  rrtm_tsfc,                                   &
3644                                  rrtm_h2ovmr(:,k_topo+1:nzt_rad+1),           &
3645                                  rrtm_o3vmr(:,k_topo+1:nzt_rad+1),            &
3646                                  rrtm_co2vmr(:,k_topo+1:nzt_rad+1),           &
3647                                  rrtm_ch4vmr(:,k_topo+1:nzt_rad+1),           &
3648                                  rrtm_n2ovmr(:,k_topo+1:nzt_rad+1),           &
3649                                  rrtm_o2vmr(:,k_topo+1:nzt_rad+1),            &
3650                                  rrtm_cfc11vmr(:,k_topo+1:nzt_rad+1),         &
3651                                  rrtm_cfc12vmr(:,k_topo+1:nzt_rad+1),         &
3652                                  rrtm_cfc22vmr(:,k_topo+1:nzt_rad+1),         &
3653                                  rrtm_ccl4vmr(:,k_topo+1:nzt_rad+1),          &
3654                                  rrtm_emis,                                   &
3655                                  rrtm_inflglw,                                &
3656                                  rrtm_iceflglw,                               &
3657                                  rrtm_liqflglw,                               &
3658                                  rrtm_cldfr(:,k_topo+1:nzt_rad+1),            &
3659                                  rrtm_lw_taucld_dum,                          &
3660                                  rrtm_cicewp(:,k_topo+1:nzt_rad+1),           &
3661                                  rrtm_cliqwp(:,k_topo+1:nzt_rad+1),           &
3662                                  rrtm_reice(:,k_topo+1:nzt_rad+1),            & 
3663                                  rrtm_reliq(:,k_topo+1:nzt_rad+1),            &
3664                                  rrtm_lw_tauaer_dum,                          &
3665                                  rrtm_lwuflx(:,k_topo:nzt_rad+1),             &
3666                                  rrtm_lwdflx(:,k_topo:nzt_rad+1),             &
3667                                  rrtm_lwhr(:,k_topo+1:nzt_rad+1),             &
3668                                  rrtm_lwuflxc(:,k_topo:nzt_rad+1),            &
3669                                  rrtm_lwdflxc(:,k_topo:nzt_rad+1),            &
3670                                  rrtm_lwhrc(:,k_topo+1:nzt_rad+1),            &
3671                                  rrtm_lwuflx_dt(:,k_topo:nzt_rad+1),          &
3672                                  rrtm_lwuflxc_dt(:,k_topo:nzt_rad+1) )
3673
3674                   DEALLOCATE ( rrtm_lw_taucld_dum )
3675                   DEALLOCATE ( rrtm_lw_tauaer_dum )
3676!
3677!--                Save fluxes
3678                   DO k = k_topo, nzt+1
3679                      rad_lw_in(k,j,i)  = rrtm_lwdflx(0,k)
3680                      rad_lw_out(k,j,i) = rrtm_lwuflx(0,k)
3681                   ENDDO
3682
3683!
3684!--                Save heating rates (convert from K/d to K/h)
3685                   DO k = k_topo+1, nzt+1
3686                      rad_lw_hr(k,j,i)     = rrtm_lwhr(0,k-k_topo)  * d_hours_day
3687                      rad_lw_cs_hr(k,j,i)  = rrtm_lwhrc(0,k-k_topo) * d_hours_day
3688                   ENDDO
3689
3690!
3691!--                Save surface radiative fluxes and change in LW heating rate
3692!--                onto respective surface elements
3693!--                Horizontal surfaces
3694                   DO  m = surf_lsm_h%start_index(j,i),                        &
3695                           surf_lsm_h%end_index(j,i)
3696                      surf_lsm_h%rad_lw_in(m)           = rrtm_lwdflx(0,k_topo)
3697                      surf_lsm_h%rad_lw_out(m)          = rrtm_lwuflx(0,k_topo)
3698                      surf_lsm_h%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k_topo)
3699                   ENDDO             
3700                   DO  m = surf_usm_h%start_index(j,i),                        &
3701                           surf_usm_h%end_index(j,i)
3702                      surf_usm_h%rad_lw_in(m)           = rrtm_lwdflx(0,k_topo)
3703                      surf_usm_h%rad_lw_out(m)          = rrtm_lwuflx(0,k_topo)
3704                      surf_usm_h%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k_topo)
3705                   ENDDO 
3706!
3707!--                Vertical surfaces. Fluxes are obtain at vertical level of the
3708!--                respective surface element
3709                   DO  l = 0, 3
3710                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
3711                              surf_lsm_v(l)%end_index(j,i)
3712                         k                                    = surf_lsm_v(l)%k(m)
3713                         surf_lsm_v(l)%rad_lw_in(m)           = rrtm_lwdflx(0,k)
3714                         surf_lsm_v(l)%rad_lw_out(m)          = rrtm_lwuflx(0,k)
3715                         surf_lsm_v(l)%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k)
3716                      ENDDO             
3717                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
3718                              surf_usm_v(l)%end_index(j,i)
3719                         k                                    = surf_usm_v(l)%k(m)
3720                         surf_usm_v(l)%rad_lw_in(m)           = rrtm_lwdflx(0,k)
3721                         surf_usm_v(l)%rad_lw_out(m)          = rrtm_lwuflx(0,k)
3722                         surf_usm_v(l)%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k)
3723                      ENDDO 
3724                   ENDDO
3725
3726                ENDIF
3727
3728                IF ( sw_radiation .AND. sun_up )  THEN
3729!
3730!--                Get albedo for direct/diffusive long/shortwave radiation at
3731!--                current (y,x)-location from surface variables.
3732!--                Only obtain it from horizontal surfaces, as RRTMG is a single
3733!--                column model
3734!--                (Please note, only one loop will entered, controlled by
3735!--                start-end index.)
3736                   DO  m = surf_lsm_h%start_index(j,i),                        &
3737                           surf_lsm_h%end_index(j,i)
3738                      rrtm_asdir(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3739                                            surf_lsm_h%rrtm_asdir(:,m) )
3740                      rrtm_asdif(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3741                                            surf_lsm_h%rrtm_asdif(:,m) )
3742                      rrtm_aldir(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3743                                            surf_lsm_h%rrtm_aldir(:,m) )
3744                      rrtm_aldif(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3745                                            surf_lsm_h%rrtm_aldif(:,m) )
3746                   ENDDO             
3747                   DO  m = surf_usm_h%start_index(j,i),                        &
3748                           surf_usm_h%end_index(j,i)
3749                      rrtm_asdir(1)  = SUM( surf_usm_h%frac(:,m) *             &
3750                                            surf_usm_h%rrtm_asdir(:,m) )
3751                      rrtm_asdif(1)  = SUM( surf_usm_h%frac(:,m) *             &
3752                                            surf_usm_h%rrtm_asdif(:,m) )
3753                      rrtm_aldir(1)  = SUM( surf_usm_h%frac(:,m) *             &
3754                                            surf_usm_h%rrtm_aldir(:,m) )
3755                      rrtm_aldif(1)  = SUM( surf_usm_h%frac(:,m) *             &
3756                                            surf_usm_h%rrtm_aldif(:,m) )
3757                   ENDDO
3758!
3759!--                Due to technical reasons, copy optical depths and other
3760!--                to dummy arguments which are allocated on the exact size as the
3761!--                rrtmg_sw is called.
3762!--                As one dimesion is allocated with zero size, compiler complains
3763!--                that rank of the array does not match that of the
3764!--                assumed-shaped arguments in the RRTMG library. In order to
3765!--                avoid this, write to dummy arguments and give pass the entire
3766!--                dummy array. Seems to be the only existing work-around. 
3767                   ALLOCATE( rrtm_sw_taucld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3768                   ALLOCATE( rrtm_sw_ssacld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3769                   ALLOCATE( rrtm_sw_asmcld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3770                   ALLOCATE( rrtm_sw_fsfcld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3771                   ALLOCATE( rrtm_sw_tauaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3772                   ALLOCATE( rrtm_sw_ssaaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3773                   ALLOCATE( rrtm_sw_asmaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3774                   ALLOCATE( rrtm_sw_ecaer_dum(0:0,k_topo+1:nzt_rad+1,1:naerec+1)  )
3775     
3776                   rrtm_sw_taucld_dum = rrtm_sw_taucld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3777                   rrtm_sw_ssacld_dum = rrtm_sw_ssacld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3778                   rrtm_sw_asmcld_dum = rrtm_sw_asmcld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3779                   rrtm_sw_fsfcld_dum = rrtm_sw_fsfcld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3780                   rrtm_sw_tauaer_dum = rrtm_sw_tauaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3781                   rrtm_sw_ssaaer_dum = rrtm_sw_ssaaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3782                   rrtm_sw_asmaer_dum = rrtm_sw_asmaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3783                   rrtm_sw_ecaer_dum  = rrtm_sw_ecaer(0:0,k_topo+1:nzt_rad+1,1:naerec+1)
3784
3785                   CALL rrtmg_sw( 1,                                           &
3786                                  nzt_rad-k_topo,                              &
3787                                  rrtm_icld,                                   &
3788                                  rrtm_iaer,                                   &
3789                                  rrtm_play(:,k_topo+1:nzt_rad+1),             &
3790                                  rrtm_plev(:,k_topo+1:nzt_rad+2),             &
3791                                  rrtm_tlay(:,k_topo+1:nzt_rad+1),             &
3792                                  rrtm_tlev(:,k_topo+1:nzt_rad+2),             &
3793                                  rrtm_tsfc,                                   &
3794                                  rrtm_h2ovmr(:,k_topo+1:nzt_rad+1),           &                               
3795                                  rrtm_o3vmr(:,k_topo+1:nzt_rad+1),            &       
3796                                  rrtm_co2vmr(:,k_topo+1:nzt_rad+1),           &
3797                                  rrtm_ch4vmr(:,k_topo+1:nzt_rad+1),           &
3798                                  rrtm_n2ovmr(:,k_topo+1:nzt_rad+1),           &
3799                                  rrtm_o2vmr(:,k_topo+1:nzt_rad+1),            &
3800                                  rrtm_asdir,                                  & 
3801                                  rrtm_asdif,                                  &
3802                                  rrtm_aldir,                                  &
3803                                  rrtm_aldif,                                  &
3804                                  zenith,                                      &
3805                                  0.0_wp,                                      &
3806                                  day_of_year,                                 &
3807                                  solar_constant,                              &
3808                                  rrtm_inflgsw,                                &
3809                                  rrtm_iceflgsw,                               &
3810                                  rrtm_liqflgsw,                               &
3811                                  rrtm_cldfr(:,k_topo+1:nzt_rad+1),            &
3812                                  rrtm_sw_taucld_dum,                          &
3813                                  rrtm_sw_ssacld_dum,                          &
3814                                  rrtm_sw_asmcld_dum,                          &
3815                                  rrtm_sw_fsfcld_dum,                          &
3816                                  rrtm_cicewp(:,k_topo+1:nzt_rad+1),           &
3817                                  rrtm_cliqwp(:,k_topo+1:nzt_rad+1),           &
3818                                  rrtm_reice(:,k_topo+1:nzt_rad+1),            &
3819                                  rrtm_reliq(:,k_topo+1:nzt_rad+1),            &
3820                                  rrtm_sw_tauaer_dum,                          &
3821                                  rrtm_sw_ssaaer_dum,                          &
3822                                  rrtm_sw_asmaer_dum,                          &
3823                                  rrtm_sw_ecaer_dum,                           &
3824                                  rrtm_swuflx(:,k_topo:nzt_rad+1),             & 
3825                                  rrtm_swdflx(:,k_topo:nzt_rad+1),             & 
3826                                  rrtm_swhr(:,k_topo+1:nzt_rad+1),             & 
3827                                  rrtm_swuflxc(:,k_topo:nzt_rad+1),            & 
3828                                  rrtm_swdflxc(:,k_topo:nzt_rad+1),            &
3829                                  rrtm_swhrc(:,k_topo+1:nzt_rad+1),            &
3830                                  rrtm_dirdflux(:,k_topo:nzt_rad+1),           &
3831                                  rrtm_difdflux(:,k_topo:nzt_rad+1) )
3832
3833                   DEALLOCATE( rrtm_sw_taucld_dum )
3834                   DEALLOCATE( rrtm_sw_ssacld_dum )
3835                   DEALLOCATE( rrtm_sw_asmcld_dum )
3836                   DEALLOCATE( rrtm_sw_fsfcld_dum )
3837                   DEALLOCATE( rrtm_sw_tauaer_dum )
3838                   DEALLOCATE( rrtm_sw_ssaaer_dum )
3839                   DEALLOCATE( rrtm_sw_asmaer_dum )
3840                   DEALLOCATE( rrtm_sw_ecaer_dum )
3841!
3842!--                Save fluxes
3843                   DO k = nzb, nzt+1
3844                      rad_sw_in(k,j,i)  = rrtm_swdflx(0,k)
3845                      rad_sw_out(k,j,i) = rrtm_swuflx(0,k)
3846                   ENDDO
3847!
3848!--                Save heating rates (convert from K/d to K/s)
3849                   DO k = nzb+1, nzt+1
3850                      rad_sw_hr(k,j,i)     = rrtm_swhr(0,k)  * d_hours_day
3851                      rad_sw_cs_hr(k,j,i)  = rrtm_swhrc(0,k) * d_hours_day
3852                   ENDDO
3853
3854!
3855!--                Save surface radiative fluxes onto respective surface elements
3856!--                Horizontal surfaces
3857                   DO  m = surf_lsm_h%start_index(j,i),                        &
3858                           surf_lsm_h%end_index(j,i)
3859                      surf_lsm_h%rad_sw_in(m)     = rrtm_swdflx(0,k_topo)
3860                      surf_lsm_h%rad_sw_out(m)    = rrtm_swuflx(0,k_topo)
3861                   ENDDO             
3862                   DO  m = surf_usm_h%start_index(j,i),                        &
3863                           surf_usm_h%end_index(j,i)
3864                      surf_usm_h%rad_sw_in(m)     = rrtm_swdflx(0,k_topo)
3865                      surf_usm_h%rad_sw_out(m)    = rrtm_swuflx(0,k_topo)
3866                   ENDDO 
3867!
3868!--                Vertical surfaces. Fluxes are obtain at respective vertical
3869!--                level of the surface element
3870                   DO  l = 0, 3
3871                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
3872                              surf_lsm_v(l)%end_index(j,i)
3873                         k                           = surf_lsm_v(l)%k(m)
3874                         surf_lsm_v(l)%rad_sw_in(m)  = rrtm_swdflx(0,k)
3875                         surf_lsm_v(l)%rad_sw_out(m) = rrtm_swuflx(0,k)
3876                      ENDDO             
3877                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
3878                              surf_usm_v(l)%end_index(j,i)
3879                         k                           = surf_usm_v(l)%k(m)
3880                         surf_usm_v(l)%rad_sw_in(m)  = rrtm_swdflx(0,k)
3881                         surf_usm_v(l)%rad_sw_out(m) = rrtm_swuflx(0,k)
3882                      ENDDO 
3883                   ENDDO
3884!
3885!--             Solar radiation is zero during night
3886                ELSE
3887                   rad_sw_in  = 0.0_wp
3888                   rad_sw_out = 0.0_wp
3889!--             !!!!!!!! ATTENSION !!!!!!!!!!!!!!!
3890!--             Surface radiative fluxes should be also set to zero here                 
3891!--                Save surface radiative fluxes onto respective surface elements
3892!--                Horizontal surfaces
3893                   DO  m = surf_lsm_h%start_index(j,i),                        &
3894                           surf_lsm_h%end_index(j,i)
3895                      surf_lsm_h%rad_sw_in(m)     = 0.0_wp
3896                      surf_lsm_h%rad_sw_out(m)    = 0.0_wp
3897                   ENDDO             
3898                   DO  m = surf_usm_h%start_index(j,i),                        &
3899                           surf_usm_h%end_index(j,i)
3900                      surf_usm_h%rad_sw_in(m)     = 0.0_wp
3901                      surf_usm_h%rad_sw_out(m)    = 0.0_wp
3902                   ENDDO 
3903!
3904!--                Vertical surfaces. Fluxes are obtain at respective vertical
3905!--                level of the surface element
3906                   DO  l = 0, 3
3907                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
3908                              surf_lsm_v(l)%end_index(j,i)
3909                         k                           = surf_lsm_v(l)%k(m)
3910                         surf_lsm_v(l)%rad_sw_in(m)  = 0.0_wp
3911                         surf_lsm_v(l)%rad_sw_out(m) = 0.0_wp
3912                      ENDDO             
3913                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
3914                              surf_usm_v(l)%end_index(j,i)
3915                         k                           = surf_usm_v(l)%k(m)
3916                         surf_usm_v(l)%rad_sw_in(m)  = 0.0_wp
3917                         surf_usm_v(l)%rad_sw_out(m) = 0.0_wp
3918                      ENDDO 
3919                   ENDDO
3920                ENDIF
3921
3922             ENDDO
3923          ENDDO
3924
3925       ENDIF
3926!
3927!--    Finally, calculate surface net radiation for surface elements.
3928       IF (  .NOT.  radiation_interactions  ) THEN
3929!--       First, for horizontal surfaces   
3930          DO  m = 1, surf_lsm_h%ns
3931             surf_lsm_h%rad_net(m) = surf_lsm_h%rad_sw_in(m)                   &
3932                                   - surf_lsm_h%rad_sw_out(m)                  &
3933                                   + surf_lsm_h%rad_lw_in(m)                   &
3934                                   - surf_lsm_h%rad_lw_out(m)
3935          ENDDO
3936          DO  m = 1, surf_usm_h%ns
3937             surf_usm_h%rad_net(m) = surf_usm_h%rad_sw_in(m)                   &
3938                                   - surf_usm_h%rad_sw_out(m)                  &
3939                                   + surf_usm_h%rad_lw_in(m)                   &
3940                                   - surf_usm_h%rad_lw_out(m)
3941          ENDDO
3942!
3943!--       Vertical surfaces.
3944!--       Todo: weight with azimuth and zenith angle according to their orientation!
3945          DO  l = 0, 3     
3946             DO  m = 1, surf_lsm_v(l)%ns
3947                surf_lsm_v(l)%rad_net(m) = surf_lsm_v(l)%rad_sw_in(m)          &
3948                                         - surf_lsm_v(l)%rad_sw_out(m)         &
3949                                         + surf_lsm_v(l)%rad_lw_in(m)          &
3950                                         - surf_lsm_v(l)%rad_lw_out(m)
3951             ENDDO
3952             DO  m = 1, surf_usm_v(l)%ns
3953                surf_usm_v(l)%rad_net(m) = surf_usm_v(l)%rad_sw_in(m)          &
3954                                         - surf_usm_v(l)%rad_sw_out(m)         &
3955                                         + surf_usm_v(l)%rad_lw_in(m)          &
3956                                         - surf_usm_v(l)%rad_lw_out(m)
3957             ENDDO
3958          ENDDO
3959       ENDIF
3960
3961
3962       CALL exchange_horiz( rad_lw_in,  nbgp )
3963       CALL exchange_horiz( rad_lw_out, nbgp )
3964       CALL exchange_horiz( rad_lw_hr,    nbgp )
3965       CALL exchange_horiz( rad_lw_cs_hr, nbgp )
3966
3967       CALL exchange_horiz( rad_sw_in,  nbgp )
3968       CALL exchange_horiz( rad_sw_out, nbgp ) 
3969       CALL exchange_horiz( rad_sw_hr,    nbgp )
3970       CALL exchange_horiz( rad_sw_cs_hr, nbgp )
3971
3972#endif
3973
3974    END SUBROUTINE radiation_rrtmg
3975
3976
3977!------------------------------------------------------------------------------!
3978! Description:
3979! ------------
3980!> Calculate the cosine of the zenith angle (variable is called zenith)
3981!------------------------------------------------------------------------------!
3982    SUBROUTINE calc_zenith
3983
3984       IMPLICIT NONE
3985
3986       REAL(wp) ::  declination,  & !< solar declination angle
3987                    hour_angle      !< solar hour angle
3988!
3989!--    Calculate current day and time based on the initial values and simulation
3990!--    time
3991       CALL calc_date_and_time
3992
3993!
3994!--    Calculate solar declination and hour angle   
3995       declination = ASIN( decl_1 * SIN(decl_2 * REAL(day_of_year, KIND=wp) - decl_3) )
3996       hour_angle  = 2.0_wp * pi * (time_utc / 86400.0_wp) + lon - pi
3997
3998!
3999!--    Calculate cosine of solar zenith angle
4000       zenith(0) = SIN(lat) * SIN(declination) + COS(lat) * COS(declination)   &
4001                                            * COS(hour_angle)
4002       zenith(0) = MAX(0.0_wp,zenith(0))
4003
4004!
4005!--    Calculate solar directional vector
4006       IF ( sun_direction )  THEN
4007
4008!
4009!--       Direction in longitudes equals to sin(solar_azimuth) * sin(zenith)
4010          sun_dir_lon(0) = -SIN(hour_angle) * COS(declination)
4011
4012!
4013!--       Direction in latitues equals to cos(solar_azimuth) * sin(zenith)
4014          sun_dir_lat(0) = SIN(declination) * COS(lat) - COS(hour_angle) &
4015                              * COS(declination) * SIN(lat)
4016       ENDIF
4017
4018!
4019!--    Check if the sun is up (otheriwse shortwave calculations can be skipped)
4020       IF ( zenith(0) > 0.0_wp )  THEN
4021          sun_up = .TRUE.
4022       ELSE
4023          sun_up = .FALSE.
4024       END IF
4025
4026    END SUBROUTINE calc_zenith
4027
4028#if defined ( __rrtmg ) && defined ( __netcdf )
4029!------------------------------------------------------------------------------!
4030! Description:
4031! ------------
4032!> Calculates surface albedo components based on Briegleb (1992) and
4033!> Briegleb et al. (1986)
4034!------------------------------------------------------------------------------!
4035    SUBROUTINE calc_albedo( surf )
4036
4037        IMPLICIT NONE
4038
4039        INTEGER(iwp)    ::  ind_type !< running index surface tiles
4040        INTEGER(iwp)    ::  m        !< running index surface elements
4041
4042        TYPE(surf_type) ::  surf !< treated surfaces
4043
4044        IF ( sun_up  .AND.  .NOT. average_radiation )  THEN
4045
4046           DO  m = 1, surf%ns
4047!
4048!--           Loop over surface elements
4049              DO  ind_type = 0, SIZE( surf%albedo_type, 1 ) - 1
4050           
4051!
4052!--              Ocean
4053                 IF ( surf%albedo_type(ind_type,m) == 1 )  THEN
4054                    surf%rrtm_aldir(ind_type,m) = 0.026_wp /                    &
4055                                                ( zenith(0)**1.7_wp + 0.065_wp )&
4056                                     + 0.15_wp * ( zenith(0) - 0.1_wp )         &
4057                                               * ( zenith(0) - 0.5_wp )         &
4058                                               * ( zenith(0) - 1.0_wp )
4059                    surf%rrtm_asdir(ind_type,m) = surf%rrtm_aldir(ind_type,m)
4060!
4061!--              Snow
4062                 ELSEIF ( surf%albedo_type(ind_type,m) == 16 )  THEN
4063                    IF ( zenith(0) < 0.5_wp )  THEN
4064                       surf%rrtm_aldir(ind_type,m) =                           &
4065                                 0.5_wp * ( 1.0_wp - surf%aldif(ind_type,m) )  &
4066                                        * ( 3.0_wp / ( 1.0_wp + 4.0_wp         &
4067                                        * zenith(0) ) ) - 1.0_wp
4068                       surf%rrtm_asdir(ind_type,m) =                           &
4069                                 0.5_wp * ( 1.0_wp - surf%asdif(ind_type,m) )  &
4070                                        * ( 3.0_wp / ( 1.0_wp + 4.0_wp         &
4071                                        * zenith(0) ) ) - 1.0_wp
4072
4073                       surf%rrtm_aldir(ind_type,m) =                           &
4074                                       MIN(0.98_wp, surf%rrtm_aldir(ind_type,m))
4075                       surf%rrtm_asdir(ind_type,m) =                           &
4076                                       MIN(0.98_wp, surf%rrtm_asdir(ind_type,m))
4077                    ELSE
4078                       surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4079                       surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4080                    ENDIF
4081!
4082!--              Sea ice
4083                 ELSEIF ( surf%albedo_type(ind_type,m) == 15 )  THEN
4084                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4085                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4086
4087!
4088!--              Asphalt
4089                 ELSEIF ( surf%albedo_type(ind_type,m) == 17 )  THEN
4090                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4091                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4092
4093
4094!
4095!--              Bare soil
4096                 ELSEIF ( surf%albedo_type(ind_type,m) == 18 )  THEN
4097                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4098                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4099
4100!
4101!--              Land surfaces
4102                 ELSE
4103                    SELECT CASE ( surf%albedo_type(ind_type,m) )
4104
4105!
4106!--                    Surface types with strong zenith dependence
4107                       CASE ( 1, 2, 3, 4, 11, 12, 13 )
4108                          surf%rrtm_aldir(ind_type,m) =                        &
4109                                surf%aldif(ind_type,m) * 1.4_wp /              &
4110                                           ( 1.0_wp + 0.8_wp * zenith(0) )
4111                          surf%rrtm_asdir(ind_type,m) =                        &
4112                                surf%asdif(ind_type,m) * 1.4_wp /              &
4113                                           ( 1.0_wp + 0.8_wp * zenith(0) )
4114!
4115!--                    Surface types with weak zenith dependence
4116                       CASE ( 5, 6, 7, 8, 9, 10, 14 )
4117                          surf%rrtm_aldir(ind_type,m) =                        &
4118                                surf%aldif(ind_type,m) * 1.1_wp /              &
4119                                           ( 1.0_wp + 0.2_wp * zenith(0) )
4120                          surf%rrtm_asdir(ind_type,m) =                        &
4121                                surf%asdif(ind_type,m) * 1.1_wp /              &
4122                                           ( 1.0_wp + 0.2_wp * zenith(0) )
4123
4124                       CASE DEFAULT
4125
4126                    END SELECT
4127                 ENDIF
4128!
4129!--              Diffusive albedo is taken from Table 2
4130                 surf%rrtm_aldif(ind_type,m) = surf%aldif(ind_type,m)
4131                 surf%rrtm_asdif(ind_type,m) = surf%asdif(ind_type,m)
4132              ENDDO
4133           ENDDO
4134!
4135!--     Set albedo in case of average radiation
4136        ELSEIF ( sun_up  .AND.  average_radiation )  THEN
4137           surf%rrtm_asdir = albedo_urb
4138           surf%rrtm_asdif = albedo_urb
4139           surf%rrtm_aldir = albedo_urb
4140           surf%rrtm_aldif = albedo_urb 
4141!
4142!--     Darkness
4143        ELSE
4144           surf%rrtm_aldir = 0.0_wp
4145           surf%rrtm_asdir = 0.0_wp
4146           surf%rrtm_aldif = 0.0_wp
4147           surf%rrtm_asdif = 0.0_wp
4148        ENDIF
4149
4150    END SUBROUTINE calc_albedo
4151
4152!------------------------------------------------------------------------------!
4153! Description:
4154! ------------
4155!> Read sounding data (pressure and temperature) from RADIATION_DATA.
4156!------------------------------------------------------------------------------!
4157    SUBROUTINE read_sounding_data
4158
4159       IMPLICIT NONE
4160
4161       INTEGER(iwp) :: id,           & !< NetCDF id of input file
4162                       id_dim_zrad,  & !< pressure level id in the NetCDF file
4163                       id_var,       & !< NetCDF variable id
4164                       k,            & !< loop index
4165                       nz_snd,       & !< number of vertical levels in the sounding data
4166                       nz_snd_start, & !< start vertical index for sounding data to be used
4167                       nz_snd_end      !< end vertical index for souding data to be used
4168
4169       REAL(wp) :: t_surface           !< actual surface temperature
4170
4171       REAL(wp), DIMENSION(:), ALLOCATABLE ::  hyp_snd_tmp, & !< temporary hydrostatic pressure profile (sounding)
4172                                               t_snd_tmp      !< temporary temperature profile (sounding)
4173
4174!
4175!--    In case of updates, deallocate arrays first (sufficient to check one
4176!--    array as the others are automatically allocated). This is required
4177!--    because nzt_rad might change during the update
4178       IF ( ALLOCATED ( hyp_snd ) )  THEN
4179          DEALLOCATE( hyp_snd )
4180          DEALLOCATE( t_snd )
4181          DEALLOCATE ( rrtm_play )
4182          DEALLOCATE ( rrtm_plev )
4183          DEALLOCATE ( rrtm_tlay )
4184          DEALLOCATE ( rrtm_tlev )
4185
4186          DEALLOCATE ( rrtm_cicewp )
4187          DEALLOCATE ( rrtm_cldfr )
4188          DEALLOCATE ( rrtm_cliqwp )
4189          DEALLOCATE ( rrtm_reice )
4190          DEALLOCATE ( rrtm_reliq )
4191          DEALLOCATE ( rrtm_lw_taucld )
4192          DEALLOCATE ( rrtm_lw_tauaer )
4193
4194          DEALLOCATE ( rrtm_lwdflx  )
4195          DEALLOCATE ( rrtm_lwdflxc )
4196          DEALLOCATE ( rrtm_lwuflx  )
4197          DEALLOCATE ( rrtm_lwuflxc )
4198          DEALLOCATE ( rrtm_lwuflx_dt )
4199          DEALLOCATE ( rrtm_lwuflxc_dt )
4200          DEALLOCATE ( rrtm_lwhr  )
4201          DEALLOCATE ( rrtm_lwhrc )
4202
4203          DEALLOCATE ( rrtm_sw_taucld )
4204          DEALLOCATE ( rrtm_sw_ssacld )
4205          DEALLOCATE ( rrtm_sw_asmcld )
4206          DEALLOCATE ( rrtm_sw_fsfcld )
4207          DEALLOCATE ( rrtm_sw_tauaer )
4208          DEALLOCATE ( rrtm_sw_ssaaer )
4209          DEALLOCATE ( rrtm_sw_asmaer ) 
4210          DEALLOCATE ( rrtm_sw_ecaer )   
4211 
4212          DEALLOCATE ( rrtm_swdflx  )
4213          DEALLOCATE ( rrtm_swdflxc )
4214          DEALLOCATE ( rrtm_swuflx  )
4215          DEALLOCATE ( rrtm_swuflxc )
4216          DEALLOCATE ( rrtm_swhr  )
4217          DEALLOCATE ( rrtm_swhrc )
4218          DEALLOCATE ( rrtm_dirdflux )
4219          DEALLOCATE ( rrtm_difdflux )
4220
4221       ENDIF
4222
4223!
4224!--    Open file for reading
4225       nc_stat = NF90_OPEN( rrtm_input_file, NF90_NOWRITE, id )
4226       CALL netcdf_handle_error_rad( 'read_sounding_data', 549 )
4227
4228!
4229!--    Inquire dimension of z axis and save in nz_snd
4230       nc_stat = NF90_INQ_DIMID( id, "Pressure", id_dim_zrad )
4231       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim_zrad, len = nz_snd )
4232       CALL netcdf_handle_error_rad( 'read_sounding_data', 551 )
4233
4234!
4235! !--    Allocate temporary array for storing pressure data
4236       ALLOCATE( hyp_snd_tmp(1:nz_snd) )
4237       hyp_snd_tmp = 0.0_wp
4238
4239
4240!--    Read pressure from file
4241       nc_stat = NF90_INQ_VARID( id, "Pressure", id_var )
4242       nc_stat = NF90_GET_VAR( id, id_var, hyp_snd_tmp(:), start = (/1/),      &
4243                               count = (/nz_snd/) )
4244       CALL netcdf_handle_error_rad( 'read_sounding_data', 552 )
4245
4246!
4247!--    Allocate temporary array for storing temperature data
4248       ALLOCATE( t_snd_tmp(1:nz_snd) )
4249       t_snd_tmp = 0.0_wp
4250
4251!
4252!--    Read temperature from file
4253       nc_stat = NF90_INQ_VARID( id, "ReferenceTemperature", id_var )
4254       nc_stat = NF90_GET_VAR( id, id_var, t_snd_tmp(:), start = (/1/),        &
4255                               count = (/nz_snd/) )
4256       CALL netcdf_handle_error_rad( 'read_sounding_data', 553 )
4257
4258!
4259!--    Calculate start of sounding data
4260       nz_snd_start = nz_snd + 1
4261       nz_snd_end   = nz_snd + 1
4262
4263!
4264!--    Start filling vertical dimension at 10hPa above the model domain (hyp is
4265!--    in Pa, hyp_snd in hPa).
4266       DO  k = 1, nz_snd
4267          IF ( hyp_snd_tmp(k) < ( hyp(nzt+1) - 1000.0_wp) * 0.01_wp )  THEN
4268             nz_snd_start = k
4269             EXIT
4270          END IF
4271       END DO
4272
4273       IF ( nz_snd_start <= nz_snd )  THEN
4274          nz_snd_end = nz_snd
4275       END IF
4276
4277
4278!
4279!--    Calculate of total grid points for RRTMG calculations
4280       nzt_rad = nzt + nz_snd_end - nz_snd_start + 1
4281
4282!
4283!--    Save data above LES domain in hyp_snd, t_snd
4284       ALLOCATE( hyp_snd(nzb+1:nzt_rad) )
4285       ALLOCATE( t_snd(nzb+1:nzt_rad)   )
4286       hyp_snd = 0.0_wp
4287       t_snd = 0.0_wp
4288
4289       hyp_snd(nzt+2:nzt_rad) = hyp_snd_tmp(nz_snd_start+1:nz_snd_end)
4290       t_snd(nzt+2:nzt_rad)   = t_snd_tmp(nz_snd_start+1:nz_snd_end)
4291
4292       nc_stat = NF90_CLOSE( id )
4293
4294!
4295!--    Calculate pressure levels on zu and zw grid. Sounding data is added at
4296!--    top of the LES domain. This routine does not consider horizontal or
4297!--    vertical variability of pressure and temperature
4298       ALLOCATE ( rrtm_play(0:0,nzb+1:nzt_rad+1)   )
4299       ALLOCATE ( rrtm_plev(0:0,nzb+1:nzt_rad+2)   )
4300
4301       t_surface = pt_surface * exner(nzb)
4302       DO k = nzb+1, nzt+1
4303          rrtm_play(0,k) = hyp(k) * 0.01_wp
4304          rrtm_plev(0,k) = barometric_formula(zw(k-1),                         &
4305                              pt_surface * exner(nzb), &
4306                              surface_pressure )
4307       ENDDO
4308
4309       DO k = nzt+2, nzt_rad
4310          rrtm_play(0,k) = hyp_snd(k)
4311          rrtm_plev(0,k) = 0.5_wp * ( rrtm_play(0,k) + rrtm_play(0,k-1) )
4312       ENDDO
4313       rrtm_plev(0,nzt_rad+1) = MAX( 0.5 * hyp_snd(nzt_rad),                   &
4314                                   1.5 * hyp_snd(nzt_rad)                      &
4315                                 - 0.5 * hyp_snd(nzt_rad-1) )
4316       rrtm_plev(0,nzt_rad+2)  = MIN( 1.0E-4_wp,                               &
4317                                      0.25_wp * rrtm_plev(0,nzt_rad+1) )
4318
4319       rrtm_play(0,nzt_rad+1) = 0.5 * rrtm_plev(0,nzt_rad+1)
4320
4321!
4322!--    Calculate temperature/humidity levels at top of the LES domain.
4323!--    Currently, the temperature is taken from sounding data (might lead to a
4324!--    temperature jump at interface. To do: Humidity is currently not
4325!--    calculated above the LES domain.
4326       ALLOCATE ( rrtm_tlay(0:0,nzb+1:nzt_rad+1)   )
4327       ALLOCATE ( rrtm_tlev(0:0,nzb+1:nzt_rad+2)   )
4328
4329       DO k = nzt+8, nzt_rad
4330          rrtm_tlay(0,k)   = t_snd(k)
4331       ENDDO
4332       rrtm_tlay(0,nzt_rad+1) = 2.0_wp * rrtm_tlay(0,nzt_rad)                  &
4333                                - rrtm_tlay(0,nzt_rad-1)
4334       DO k = nzt+9, nzt_rad+1
4335          rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k)                &
4336                             - rrtm_tlay(0,k-1))                               &
4337                             / ( rrtm_play(0,k) - rrtm_play(0,k-1) )           &
4338                             * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
4339       ENDDO
4340
4341       rrtm_tlev(0,nzt_rad+2)   = 2.0_wp * rrtm_tlay(0,nzt_rad+1)              &
4342                                  - rrtm_tlev(0,nzt_rad)
4343!
4344!--    Allocate remaining RRTMG arrays
4345       ALLOCATE ( rrtm_cicewp(0:0,nzb+1:nzt_rad+1) )
4346       ALLOCATE ( rrtm_cldfr(0:0,nzb+1:nzt_rad+1) )
4347       ALLOCATE ( rrtm_cliqwp(0:0,nzb+1:nzt_rad+1) )
4348       ALLOCATE ( rrtm_reice(0:0,nzb+1:nzt_rad+1) )
4349       ALLOCATE ( rrtm_reliq(0:0,nzb+1:nzt_rad+1) )
4350       ALLOCATE ( rrtm_lw_taucld(1:nbndlw+1,0:0,nzb+1:nzt_rad+1) )
4351       ALLOCATE ( rrtm_lw_tauaer(0:0,nzb+1:nzt_rad+1,1:nbndlw+1) )
4352       ALLOCATE ( rrtm_sw_taucld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4353       ALLOCATE ( rrtm_sw_ssacld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4354       ALLOCATE ( rrtm_sw_asmcld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4355       ALLOCATE ( rrtm_sw_fsfcld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4356       ALLOCATE ( rrtm_sw_tauaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) )
4357       ALLOCATE ( rrtm_sw_ssaaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) )
4358       ALLOCATE ( rrtm_sw_asmaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) ) 
4359       ALLOCATE ( rrtm_sw_ecaer(0:0,nzb+1:nzt_rad+1,1:naerec+1) )   
4360
4361!
4362!--    The ice phase is currently not considered in PALM
4363       rrtm_cicewp = 0.0_wp
4364       rrtm_reice  = 0.0_wp
4365
4366!
4367!--    Set other parameters (move to NAMELIST parameters in the future)
4368       rrtm_lw_tauaer = 0.0_wp
4369       rrtm_lw_taucld = 0.0_wp
4370       rrtm_sw_taucld = 0.0_wp
4371       rrtm_sw_ssacld = 0.0_wp
4372       rrtm_sw_asmcld = 0.0_wp
4373       rrtm_sw_fsfcld = 0.0_wp
4374       rrtm_sw_tauaer = 0.0_wp
4375       rrtm_sw_ssaaer = 0.0_wp
4376       rrtm_sw_asmaer = 0.0_wp
4377       rrtm_sw_ecaer  = 0.0_wp
4378
4379
4380       ALLOCATE ( rrtm_swdflx(0:0,nzb:nzt_rad+1)  )
4381       ALLOCATE ( rrtm_swuflx(0:0,nzb:nzt_rad+1)  )
4382       ALLOCATE ( rrtm_swhr(0:0,nzb+1:nzt_rad+1)  )
4383       ALLOCATE ( rrtm_swuflxc(0:0,nzb:nzt_rad+1) )
4384       ALLOCATE ( rrtm_swdflxc(0:0,nzb:nzt_rad+1) )
4385       ALLOCATE ( rrtm_swhrc(0:0,nzb+1:nzt_rad+1) )
4386       ALLOCATE ( rrtm_dirdflux(0:0,nzb:nzt_rad+1) )
4387       ALLOCATE ( rrtm_difdflux(0:0,nzb:nzt_rad+1) )
4388
4389       rrtm_swdflx  = 0.0_wp
4390       rrtm_swuflx  = 0.0_wp
4391       rrtm_swhr    = 0.0_wp 
4392       rrtm_swuflxc = 0.0_wp
4393       rrtm_swdflxc = 0.0_wp
4394       rrtm_swhrc   = 0.0_wp
4395       rrtm_dirdflux = 0.0_wp
4396       rrtm_difdflux = 0.0_wp
4397
4398       ALLOCATE ( rrtm_lwdflx(0:0,nzb:nzt_rad+1)  )
4399       ALLOCATE ( rrtm_lwuflx(0:0,nzb:nzt_rad+1)  )
4400       ALLOCATE ( rrtm_lwhr(0:0,nzb+1:nzt_rad+1)  )
4401       ALLOCATE ( rrtm_lwuflxc(0:0,nzb:nzt_rad+1) )
4402       ALLOCATE ( rrtm_lwdflxc(0:0,nzb:nzt_rad+1) )
4403       ALLOCATE ( rrtm_lwhrc(0:0,nzb+1:nzt_rad+1) )
4404
4405       rrtm_lwdflx  = 0.0_wp
4406       rrtm_lwuflx  = 0.0_wp
4407       rrtm_lwhr    = 0.0_wp 
4408       rrtm_lwuflxc = 0.0_wp
4409       rrtm_lwdflxc = 0.0_wp
4410       rrtm_lwhrc   = 0.0_wp
4411
4412       ALLOCATE ( rrtm_lwuflx_dt(0:0,nzb:nzt_rad+1) )
4413       ALLOCATE ( rrtm_lwuflxc_dt(0:0,nzb:nzt_rad+1) )
4414
4415       rrtm_lwuflx_dt = 0.0_wp
4416       rrtm_lwuflxc_dt = 0.0_wp
4417
4418    END SUBROUTINE read_sounding_data
4419
4420
4421!------------------------------------------------------------------------------!
4422! Description:
4423! ------------
4424!> Read trace gas data from file
4425!------------------------------------------------------------------------------!
4426    SUBROUTINE read_trace_gas_data
4427
4428       USE rrsw_ncpar
4429
4430       IMPLICIT NONE
4431
4432       INTEGER(iwp), PARAMETER :: num_trace_gases = 10 !< number of trace gases (absorbers)
4433
4434       CHARACTER(LEN=5), DIMENSION(num_trace_gases), PARAMETER ::              & !< trace gas names
4435           trace_names = (/'O3   ', 'CO2  ', 'CH4  ', 'N2O  ', 'O2   ',        &
4436                           'CFC11', 'CFC12', 'CFC22', 'CCL4 ', 'H2O  '/)
4437
4438       INTEGER(iwp) :: id,     & !< NetCDF id
4439                       k,      & !< loop index
4440                       m,      & !< loop index
4441                       n,      & !< loop index
4442                       nabs,   & !< number of absorbers
4443                       np,     & !< number of pressure levels
4444                       id_abs, & !< NetCDF id of the respective absorber
4445                       id_dim, & !< NetCDF id of asborber's dimension
4446                       id_var    !< NetCDf id ot the absorber
4447
4448       REAL(wp) :: p_mls_l, p_mls_u, p_wgt_l, p_wgt_u, p_mls_m
4449
4450
4451       REAL(wp), DIMENSION(:), ALLOCATABLE   ::  p_mls,          & !< pressure levels for the absorbers
4452                                                 rrtm_play_tmp,  & !< temporary array for pressure zu-levels
4453                                                 rrtm_plev_tmp,  & !< temporary array for pressure zw-levels
4454                                                 trace_path_tmp    !< temporary array for storing trace gas path data
4455
4456       REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  trace_mls,      & !< array for storing the absorber amounts
4457                                                 trace_mls_path, & !< array for storing trace gas path data
4458                                                 trace_mls_tmp     !< temporary array for storing trace gas data
4459
4460
4461!
4462!--    In case of updates, deallocate arrays first (sufficient to check one
4463!--    array as the others are automatically allocated)
4464       IF ( ALLOCATED ( rrtm_o3vmr ) )  THEN
4465          DEALLOCATE ( rrtm_o3vmr  )
4466          DEALLOCATE ( rrtm_co2vmr )
4467          DEALLOCATE ( rrtm_ch4vmr )
4468          DEALLOCATE ( rrtm_n2ovmr )
4469          DEALLOCATE ( rrtm_o2vmr  )
4470          DEALLOCATE ( rrtm_cfc11vmr )
4471          DEALLOCATE ( rrtm_cfc12vmr )
4472          DEALLOCATE ( rrtm_cfc22vmr )
4473          DEALLOCATE ( rrtm_ccl4vmr  )
4474          DEALLOCATE ( rrtm_h2ovmr  )     
4475       ENDIF
4476
4477!
4478!--    Allocate trace gas profiles
4479       ALLOCATE ( rrtm_o3vmr(0:0,1:nzt_rad+1)  )
4480       ALLOCATE ( rrtm_co2vmr(0:0,1:nzt_rad+1) )
4481       ALLOCATE ( rrtm_ch4vmr(0:0,1:nzt_rad+1) )
4482       ALLOCATE ( rrtm_n2ovmr(0:0,1:nzt_rad+1) )
4483       ALLOCATE ( rrtm_o2vmr(0:0,1:nzt_rad+1)  )
4484       ALLOCATE ( rrtm_cfc11vmr(0:0,1:nzt_rad+1) )
4485       ALLOCATE ( rrtm_cfc12vmr(0:0,1:nzt_rad+1) )
4486       ALLOCATE ( rrtm_cfc22vmr(0:0,1:nzt_rad+1) )
4487       ALLOCATE ( rrtm_ccl4vmr(0:0,1:nzt_rad+1)  )
4488       ALLOCATE ( rrtm_h2ovmr(0:0,1:nzt_rad+1)  )
4489
4490!
4491!--    Open file for reading
4492       nc_stat = NF90_OPEN( rrtm_input_file, NF90_NOWRITE, id )
4493       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 549 )
4494!
4495!--    Inquire dimension ids and dimensions
4496       nc_stat = NF90_INQ_DIMID( id, "Pressure", id_dim )
4497       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4498       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim, len = np) 
4499       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4500
4501       nc_stat = NF90_INQ_DIMID( id, "Absorber", id_dim )
4502       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4503       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim, len = nabs ) 
4504       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4505   
4506
4507!
4508!--    Allocate pressure, and trace gas arrays     
4509       ALLOCATE( p_mls(1:np) )
4510       ALLOCATE( trace_mls(1:num_trace_gases,1:np) ) 
4511       ALLOCATE( trace_mls_tmp(1:nabs,1:np) ) 
4512
4513
4514       nc_stat = NF90_INQ_VARID( id, "Pressure", id_var )
4515       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4516       nc_stat = NF90_GET_VAR( id, id_var, p_mls )
4517       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4518
4519       nc_stat = NF90_INQ_VARID( id, "AbsorberAmountMLS", id_var )
4520       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4521       nc_stat = NF90_GET_VAR( id, id_var, trace_mls_tmp )
4522       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4523
4524
4525!
4526!--    Write absorber amounts (mls) to trace_mls
4527       DO n = 1, num_trace_gases
4528          CALL getAbsorberIndex( TRIM( trace_names(n) ), id_abs )
4529
4530          trace_mls(n,1:np) = trace_mls_tmp(id_abs,1:np)
4531
4532!
4533!--       Replace missing values by zero
4534          WHERE ( trace_mls(n,:) > 2.0_wp ) 
4535             trace_mls(n,:) = 0.0_wp
4536          END WHERE
4537       END DO
4538
4539       DEALLOCATE ( trace_mls_tmp )
4540
4541       nc_stat = NF90_CLOSE( id )
4542       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 551 )
4543
4544!
4545!--    Add extra pressure level for calculations of the trace gas paths
4546       ALLOCATE ( rrtm_play_tmp(1:nzt_rad+1) )
4547       ALLOCATE ( rrtm_plev_tmp(1:nzt_rad+2) )
4548
4549       rrtm_play_tmp(1:nzt_rad)   = rrtm_play(0,1:nzt_rad) 
4550       rrtm_plev_tmp(1:nzt_rad+1) = rrtm_plev(0,1:nzt_rad+1)
4551       rrtm_play_tmp(nzt_rad+1)   = rrtm_plev(0,nzt_rad+1) * 0.5_wp
4552       rrtm_plev_tmp(nzt_rad+2)   = MIN( 1.0E-4_wp, 0.25_wp                    &
4553                                         * rrtm_plev(0,nzt_rad+1) )
4554 
4555!
4556!--    Calculate trace gas path (zero at surface) with interpolation to the
4557!--    sounding levels
4558       ALLOCATE ( trace_mls_path(1:nzt_rad+2,1:num_trace_gases) )
4559
4560       trace_mls_path(nzb+1,:) = 0.0_wp
4561       
4562       DO k = nzb+2, nzt_rad+2
4563          DO m = 1, num_trace_gases
4564             trace_mls_path(k,m) = trace_mls_path(k-1,m)
4565
4566!
4567!--          When the pressure level is higher than the trace gas pressure
4568!--          level, assume that
4569             IF ( rrtm_plev_tmp(k-1) > p_mls(1) )  THEN             
4570               
4571                trace_mls_path(k,m) = trace_mls_path(k,m) + trace_mls(m,1)     &
4572                                      * ( rrtm_plev_tmp(k-1)                   &
4573                                          - MAX( p_mls(1), rrtm_plev_tmp(k) )  &
4574                                        ) / g
4575             ENDIF
4576
4577!
4578!--          Integrate for each sounding level from the contributing p_mls
4579!--          levels
4580             DO n = 2, np
4581!
4582!--             Limit p_mls so that it is within the model level
4583                p_mls_u = MIN( rrtm_plev_tmp(k-1),                             &
4584                          MAX( rrtm_plev_tmp(k), p_mls(n) ) )
4585                p_mls_l = MIN( rrtm_plev_tmp(k-1),                             &
4586                          MAX( rrtm_plev_tmp(k), p_mls(n-1) ) )
4587
4588                IF ( p_mls_l > p_mls_u )  THEN
4589
4590!
4591!--                Calculate weights for interpolation
4592                   p_mls_m = 0.5_wp * (p_mls_l + p_mls_u)
4593                   p_wgt_u = (p_mls(n-1) - p_mls_m) / (p_mls(n-1) - p_mls(n))
4594                   p_wgt_l = (p_mls_m - p_mls(n))   / (p_mls(n-1) - p_mls(n))
4595
4596!
4597!--                Add level to trace gas path
4598                   trace_mls_path(k,m) = trace_mls_path(k,m)                   &
4599                                         +  ( p_wgt_u * trace_mls(m,n)         &
4600                                            + p_wgt_l * trace_mls(m,n-1) )     &
4601                                         * (p_mls_l - p_mls_u) / g
4602                ENDIF
4603             ENDDO
4604
4605             IF ( rrtm_plev_tmp(k) < p_mls(np) )  THEN
4606                trace_mls_path(k,m) = trace_mls_path(k,m) + trace_mls(m,np)    &
4607                                      * ( MIN( rrtm_plev_tmp(k-1), p_mls(np) ) &
4608                                          - rrtm_plev_tmp(k)                   &
4609                                        ) / g 
4610             ENDIF 
4611          ENDDO
4612       ENDDO
4613
4614
4615!
4616!--    Prepare trace gas path profiles
4617       ALLOCATE ( trace_path_tmp(1:nzt_rad+1) )
4618
4619       DO m = 1, num_trace_gases
4620
4621          trace_path_tmp(1:nzt_rad+1) = ( trace_mls_path(2:nzt_rad+2,m)        &
4622                                       - trace_mls_path(1:nzt_rad+1,m) ) * g   &
4623                                       / ( rrtm_plev_tmp(1:nzt_rad+1)          &
4624                                       - rrtm_plev_tmp(2:nzt_rad+2) )
4625
4626!
4627!--       Save trace gas paths to the respective arrays
4628          SELECT CASE ( TRIM( trace_names(m) ) )
4629
4630             CASE ( 'O3' )
4631
4632                rrtm_o3vmr(0,:) = trace_path_tmp(:)
4633
4634             CASE ( 'CO2' )
4635
4636                rrtm_co2vmr(0,:) = trace_path_tmp(:)
4637
4638             CASE ( 'CH4' )
4639
4640                rrtm_ch4vmr(0,:) = trace_path_tmp(:)
4641
4642             CASE ( 'N2O' )
4643
4644                rrtm_n2ovmr(0,:) = trace_path_tmp(:)
4645
4646             CASE ( 'O2' )
4647
4648                rrtm_o2vmr(0,:) = trace_path_tmp(:)
4649
4650             CASE ( 'CFC11' )
4651
4652                rrtm_cfc11vmr(0,:) = trace_path_tmp(:)
4653
4654             CASE ( 'CFC12' )
4655
4656                rrtm_cfc12vmr(0,:) = trace_path_tmp(:)
4657
4658             CASE ( 'CFC22' )
4659
4660                rrtm_cfc22vmr(0,:) = trace_path_tmp(:)
4661
4662             CASE ( 'CCL4' )
4663
4664                rrtm_ccl4vmr(0,:) = trace_path_tmp(:)
4665
4666             CASE ( 'H2O' )
4667
4668                rrtm_h2ovmr(0,:) = trace_path_tmp(:)
4669               
4670             CASE DEFAULT
4671
4672          END SELECT
4673
4674       ENDDO
4675
4676       DEALLOCATE ( trace_path_tmp )
4677       DEALLOCATE ( trace_mls_path )
4678       DEALLOCATE ( rrtm_play_tmp )
4679       DEALLOCATE ( rrtm_plev_tmp )
4680       DEALLOCATE ( trace_mls )
4681       DEALLOCATE ( p_mls )
4682
4683    END SUBROUTINE read_trace_gas_data
4684
4685
4686    SUBROUTINE netcdf_handle_error_rad( routine_name, errno )
4687
4688       USE control_parameters,                                                 &
4689           ONLY:  message_string
4690
4691       USE NETCDF
4692
4693       USE pegrid
4694
4695       IMPLICIT NONE
4696
4697       CHARACTER(LEN=6) ::  message_identifier
4698       CHARACTER(LEN=*) ::  routine_name
4699
4700       INTEGER(iwp) ::  errno
4701
4702       IF ( nc_stat /= NF90_NOERR )  THEN
4703
4704          WRITE( message_identifier, '(''NC'',I4.4)' )  errno
4705          message_string = TRIM( NF90_STRERROR( nc_stat ) )
4706
4707          CALL message( routine_name, message_identifier, 2, 2, 0, 6, 1 )
4708
4709       ENDIF
4710
4711    END SUBROUTINE netcdf_handle_error_rad
4712#endif
4713
4714
4715!------------------------------------------------------------------------------!
4716! Description:
4717! ------------
4718!> Calculate temperature tendency due to radiative cooling/heating.
4719!> Cache-optimized version.
4720!------------------------------------------------------------------------------!
4721 SUBROUTINE radiation_tendency_ij ( i, j, tend )
4722
4723    IMPLICIT NONE
4724
4725    INTEGER(iwp) :: i, j, k !< loop indices
4726
4727    REAL(wp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg) :: tend !< pt tendency term
4728
4729    IF ( radiation_scheme == 'rrtmg' )  THEN
4730#if defined  ( __rrtmg )
4731!
4732!--    Calculate tendency based on heating rate
4733       DO k = nzb+1, nzt+1
4734          tend(k,j,i) = tend(k,j,i) + (rad_lw_hr(k,j,i) + rad_sw_hr(k,j,i))    &
4735                                         * d_exner(k) * d_seconds_hour
4736       ENDDO
4737#endif
4738    ENDIF
4739
4740    END SUBROUTINE radiation_tendency_ij
4741
4742
4743!------------------------------------------------------------------------------!
4744! Description:
4745! ------------
4746!> Calculate temperature tendency due to radiative cooling/heating.
4747!> Vector-optimized version
4748!------------------------------------------------------------------------------!
4749 SUBROUTINE radiation_tendency ( tend )
4750
4751    USE indices,                                                               &
4752        ONLY:  nxl, nxr, nyn, nys
4753
4754    IMPLICIT NONE
4755
4756    INTEGER(iwp) :: i, j, k !< loop indices
4757
4758    REAL(wp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg) :: tend !< pt tendency term
4759
4760    IF ( radiation_scheme == 'rrtmg' )  THEN
4761#if defined  ( __rrtmg )
4762!
4763!--    Calculate tendency based on heating rate
4764       DO  i = nxl, nxr
4765          DO  j = nys, nyn
4766             DO k = nzb+1, nzt+1
4767                tend(k,j,i) = tend(k,j,i) + ( rad_lw_hr(k,j,i)                 &
4768                                          +  rad_sw_hr(k,j,i) ) * d_exner(k)   &
4769                                          * d_seconds_hour
4770             ENDDO
4771          ENDDO
4772       ENDDO
4773#endif
4774    ENDIF
4775
4776
4777 END SUBROUTINE radiation_tendency
4778
4779!------------------------------------------------------------------------------!
4780! Description:
4781! ------------
4782!> This subroutine calculates interaction of the solar radiation
4783!> with urban and land surfaces and updates all surface heatfluxes.
4784!> It calculates also the required parameters for RRTMG lower BC.
4785!>
4786!> For more info. see Resler et al. 2017
4787!>
4788!> The new version 2.0 was radically rewriten, the discretization scheme
4789!> has been changed. This new version significantly improves effectivity
4790!> of the paralelization and the scalability of the model.
4791!------------------------------------------------------------------------------!
4792
4793 SUBROUTINE radiation_interaction
4794
4795     IMPLICIT NONE
4796
4797     INTEGER(iwp)                      :: i, j, k, kk, is, js, d, ku, refstep, m, mm, l, ll
4798     INTEGER(iwp)                      :: isurf, isurfsrc, isvf, icsf, ipcgb
4799     INTEGER(iwp)                      :: imrt, imrtf
4800     INTEGER(iwp)                      :: isd                !< solar direction number
4801     INTEGER(iwp)                      :: pc_box_dimshift    !< transform for best accuracy
4802     INTEGER(iwp), DIMENSION(0:3)      :: reorder = (/ 1, 0, 3, 2 /)
4803     
4804     REAL(wp), DIMENSION(3,3)          :: mrot               !< grid rotation matrix (zyx)
4805     REAL(wp), DIMENSION(3,0:nsurf_type):: vnorm             !< face direction normal vectors (zyx)
4806     REAL(wp), DIMENSION(3)            :: sunorig            !< grid rotated solar direction unit vector (zyx)
4807     REAL(wp), DIMENSION(3)            :: sunorig_grid       !< grid squashed solar direction unit vector (zyx)
4808     REAL(wp), DIMENSION(0:nsurf_type) :: costheta           !< direct irradiance factor of solar angle
4809     REAL(wp), DIMENSION(nzub:nzut)    :: pchf_prep          !< precalculated factor for canopy temperature tendency
4810     REAL(wp), PARAMETER               :: alpha = 0._wp      !< grid rotation (TODO: add to namelist or remove)
4811     REAL(wp)                          :: pc_box_area, pc_abs_frac, pc_abs_eff
4812     REAL(wp)                          :: asrc               !< area of source face
4813     REAL(wp)                          :: pcrad              !< irradiance from plant canopy
4814     REAL(wp)                          :: pabsswl  = 0.0_wp  !< total absorbed SW radiation energy in local processor (W)
4815     REAL(wp)                          :: pabssw   = 0.0_wp  !< total absorbed SW radiation energy in all processors (W)
4816     REAL(wp)                          :: pabslwl  = 0.0_wp  !< total absorbed LW radiation energy in local processor (W)
4817     REAL(wp)                          :: pabslw   = 0.0_wp  !< total absorbed LW radiation energy in all processors (W)
4818     REAL(wp)                          :: pemitlwl = 0.0_wp  !< total emitted LW radiation energy in all processors (W)
4819     REAL(wp)                          :: pemitlw  = 0.0_wp  !< total emitted LW radiation energy in all processors (W)
4820     REAL(wp)                          :: pinswl   = 0.0_wp  !< total received SW radiation energy in local processor (W)
4821     REAL(wp)                          :: pinsw    = 0.0_wp  !< total received SW radiation energy in all processor (W)
4822     REAL(wp)                          :: pinlwl   = 0.0_wp  !< total received LW radiation energy in local processor (W)
4823     REAL(wp)                          :: pinlw    = 0.0_wp  !< total received LW radiation energy in all processor (W)
4824     REAL(wp)                          :: emiss_sum_surfl    !< sum of emissisivity of surfaces in local processor
4825     REAL(wp)                          :: emiss_sum_surf     !< sum of emissisivity of surfaces in all processor
4826     REAL(wp)                          :: area_surfl         !< total area of surfaces in local processor
4827     REAL(wp)                          :: area_surf          !< total area of surfaces in all processor
4828     REAL(wp)                          :: area_hor           !< total horizontal area of domain in all processor
4829
4830#if ! defined( __nopointer )
4831     IF ( plant_canopy )  THEN
4832         pchf_prep(:) = r_d * exner(nzub:nzut)                                 &
4833                     / (c_p * hyp(nzub:nzut) * dx*dy*dz(1)) !< equals to 1 / (rho * c_p * Vbox * T)
4834     ENDIF
4835#endif
4836     sun_direction = .TRUE.
4837     CALL calc_zenith  !< required also for diffusion radiation
4838
4839!--     prepare rotated normal vectors and irradiance factor
4840     vnorm(1,:) = kdir(:)
4841     vnorm(2,:) = jdir(:)
4842     vnorm(3,:) = idir(:)
4843     mrot(1, :) = (/ 1._wp,  0._wp,      0._wp      /)
4844     mrot(2, :) = (/ 0._wp,  COS(alpha), SIN(alpha) /)
4845     mrot(3, :) = (/ 0._wp, -SIN(alpha), COS(alpha) /)
4846     sunorig = (/ zenith(0), sun_dir_lat, sun_dir_lon /)
4847     sunorig = MATMUL(mrot, sunorig)
4848     DO d = 0, nsurf_type
4849         costheta(d) = DOT_PRODUCT(sunorig, vnorm(:,d))
4850     ENDDO
4851
4852     IF ( zenith(0) > 0 )  THEN
4853!--      now we will "squash" the sunorig vector by grid box size in
4854!--      each dimension, so that this new direction vector will allow us
4855!--      to traverse the ray path within grid coordinates directly
4856         sunorig_grid = (/ sunorig(1)/dz(1), sunorig(2)/dy, sunorig(3)/dx /)
4857!--      sunorig_grid = sunorig_grid / norm2(sunorig_grid)
4858         sunorig_grid = sunorig_grid / SQRT(SUM(sunorig_grid**2))
4859
4860         IF ( npcbl > 0 )  THEN
4861!--         precompute effective box depth with prototype Leaf Area Density
4862            pc_box_dimshift = MAXLOC(ABS(sunorig), 1) - 1
4863            CALL box_absorb(CSHIFT((/dz(1),dy,dx/), pc_box_dimshift),       &
4864                                60, prototype_lad,                          &
4865                                CSHIFT(ABS(sunorig), pc_box_dimshift),      &
4866                                pc_box_area, pc_abs_frac)
4867            pc_box_area = pc_box_area * ABS(sunorig(pc_box_dimshift+1)      &
4868                          / sunorig(1))
4869            pc_abs_eff = LOG(1._wp - pc_abs_frac) / prototype_lad
4870         ENDIF
4871     ENDIF
4872
4873!--  if radiation scheme is not RRTMG, split diffusion and direct part of the solar downward radiation
4874!--  comming from radiation model and store it in 2D arrays
4875     IF (  radiation_scheme /= 'rrtmg'  )  CALL calc_diffusion_radiation
4876
4877!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4878!--     First pass: direct + diffuse irradiance + thermal
4879!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4880     surfinswdir   = 0._wp !nsurfl
4881     surfins       = 0._wp !nsurfl
4882     surfinl       = 0._wp !nsurfl
4883     surfoutsl(:)  = 0.0_wp !start-end
4884     surfoutll(:)  = 0.0_wp !start-end
4885     IF ( nmrtbl > 0 )  THEN
4886        mrtinsw(:) = 0._wp
4887        mrtinlw(:) = 0._wp
4888     ENDIF
4889     surfinlg(:)  = 0._wp !global
4890
4891
4892!--  Set up thermal radiation from surfaces
4893!--  emiss_surf is defined only for surfaces for which energy balance is calculated
4894!--  Workaround: reorder surface data type back on 1D array including all surfaces,
4895!--  which implies to reorder horizontal and vertical surfaces
4896!
4897!--  Horizontal walls
4898     mm = 1
4899     DO  i = nxl, nxr
4900        DO  j = nys, nyn
4901!--           urban
4902           DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
4903              surfoutll(mm) = SUM ( surf_usm_h%frac(:,m) *                  &
4904                                    surf_usm_h%emissivity(:,m) )            &
4905                                  * sigma_sb                                &
4906                                  * surf_usm_h%pt_surface(m)**4
4907              albedo_surf(mm) = SUM ( surf_usm_h%frac(:,m) *                &
4908                                      surf_usm_h%albedo(:,m) )
4909              emiss_surf(mm)  = SUM ( surf_usm_h%frac(:,m) *                &
4910                                      surf_usm_h%emissivity(:,m) )
4911              mm = mm + 1
4912           ENDDO
4913!--           land
4914           DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
4915              surfoutll(mm) = SUM ( surf_lsm_h%frac(:,m) *                  &
4916                                    surf_lsm_h%emissivity(:,m) )            &
4917                                  * sigma_sb                                &
4918                                  * surf_lsm_h%pt_surface(m)**4
4919              albedo_surf(mm) = SUM ( surf_lsm_h%frac(:,m) *                &
4920                                      surf_lsm_h%albedo(:,m) )
4921              emiss_surf(mm)  = SUM ( surf_lsm_h%frac(:,m) *                &
4922                                      surf_lsm_h%emissivity(:,m) )
4923              mm = mm + 1
4924           ENDDO
4925        ENDDO
4926     ENDDO
4927!
4928!--     Vertical walls
4929     DO  i = nxl, nxr
4930        DO  j = nys, nyn
4931           DO  ll = 0, 3
4932              l = reorder(ll)
4933!--              urban
4934              DO  m = surf_usm_v(l)%start_index(j,i),                       &
4935                      surf_usm_v(l)%end_index(j,i)
4936                 surfoutll(mm) = SUM ( surf_usm_v(l)%frac(:,m) *            &
4937                                       surf_usm_v(l)%emissivity(:,m) )      &
4938                                  * sigma_sb                                &
4939                                  * surf_usm_v(l)%pt_surface(m)**4
4940                 albedo_surf(mm) = SUM ( surf_usm_v(l)%frac(:,m) *          &
4941                                         surf_usm_v(l)%albedo(:,m) )
4942                 emiss_surf(mm)  = SUM ( surf_usm_v(l)%frac(:,m) *          &
4943                                         surf_usm_v(l)%emissivity(:,m) )
4944                 mm = mm + 1
4945              ENDDO
4946!--              land
4947              DO  m = surf_lsm_v(l)%start_index(j,i),                       &
4948                      surf_lsm_v(l)%end_index(j,i)
4949                 surfoutll(mm) = SUM ( surf_lsm_v(l)%frac(:,m) *            &
4950                                       surf_lsm_v(l)%emissivity(:,m) )      &
4951                                  * sigma_sb                                &
4952                                  * surf_lsm_v(l)%pt_surface(m)**4
4953                 albedo_surf(mm) = SUM ( surf_lsm_v(l)%frac(:,m) *          &
4954                                         surf_lsm_v(l)%albedo(:,m) )
4955                 emiss_surf(mm)  = SUM ( surf_lsm_v(l)%frac(:,m) *          &
4956                                         surf_lsm_v(l)%emissivity(:,m) )
4957                 mm = mm + 1
4958              ENDDO
4959           ENDDO
4960        ENDDO
4961     ENDDO
4962
4963#if defined( __parallel )
4964!--     might be optimized and gather only values relevant for current processor
4965     CALL MPI_AllGatherv(surfoutll, nsurfl, MPI_REAL, &
4966                         surfoutl, nsurfs, surfstart, MPI_REAL, comm2d, ierr) !nsurf global
4967     IF ( ierr /= 0 ) THEN
4968         WRITE(9,*) 'Error MPI_AllGatherv1:', ierr, SIZE(surfoutll), nsurfl, &
4969                     SIZE(surfoutl), nsurfs, surfstart
4970         FLUSH(9)
4971     ENDIF
4972#else
4973     surfoutl(:) = surfoutll(:) !nsurf global
4974#endif
4975
4976     IF ( surface_reflections)  THEN
4977        DO  isvf = 1, nsvfl
4978           isurf = svfsurf(1, isvf)
4979           k     = surfl(iz, isurf)
4980           j     = surfl(iy, isurf)
4981           i     = surfl(ix, isurf)
4982           isurfsrc = svfsurf(2, isvf)
4983!
4984!--        For surface-to-surface factors we calculate thermal radiation in 1st pass
4985           IF ( plant_lw_interact )  THEN
4986              surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * svf(2,isvf) * surfoutl(isurfsrc)
4987           ELSE
4988              surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * surfoutl(isurfsrc)
4989           ENDIF
4990        ENDDO
4991     ENDIF
4992!
4993!--  diffuse radiation using sky view factor
4994     DO isurf = 1, nsurfl
4995        j = surfl(iy, isurf)
4996        i = surfl(ix, isurf)
4997        surfinswdif(isurf) = rad_sw_in_diff(j,i) * skyvft(isurf)
4998        IF ( plant_lw_interact )  THEN
4999           surfinlwdif(isurf) = rad_lw_in_diff(j,i) * skyvft(isurf)
5000        ELSE
5001           surfinlwdif(isurf) = rad_lw_in_diff(j,i) * skyvf(isurf)
5002        ENDIF
5003     ENDDO
5004!
5005!--  MRT diffuse irradiance
5006     DO  imrt = 1, nmrtbl
5007        j = mrtbl(iy, imrt)
5008        i = mrtbl(ix, imrt)
5009        mrtinsw(imrt) = mrtskyt(imrt) * rad_sw_in_diff(j,i)
5010        mrtinlw(imrt) = mrtsky(imrt) * rad_lw_in_diff(j,i)
5011     ENDDO
5012
5013     !-- direct radiation
5014     IF ( zenith(0) > 0 )  THEN
5015        !--Identify solar direction vector (discretized number) 1)
5016        !--
5017        j = FLOOR(ACOS(zenith(0)) / pi * raytrace_discrete_elevs)
5018        i = MODULO(NINT(ATAN2(sun_dir_lon(0), sun_dir_lat(0))               &
5019                        / (2._wp*pi) * raytrace_discrete_azims-.5_wp, iwp), &
5020                   raytrace_discrete_azims)
5021        isd = dsidir_rev(j, i)
5022!-- TODO: check if isd = -1 to report that this solar position is not precalculated
5023        DO isurf = 1, nsurfl
5024           j = surfl(iy, isurf)
5025           i = surfl(ix, isurf)
5026           surfinswdir(isurf) = rad_sw_in_dir(j,i) *                        &
5027                costheta(surfl(id, isurf)) * dsitrans(isurf, isd) / zenith(0)
5028        ENDDO
5029!
5030!--     MRT direct irradiance
5031        DO  imrt = 1, nmrtbl
5032           j = mrtbl(iy, imrt)
5033           i = mrtbl(ix, imrt)
5034           mrtinsw(imrt) = mrtinsw(imrt) + mrtdsit(imrt, isd) * rad_sw_in_dir(j,i) &
5035                                     / zenith(0) / 4._wp ! normal to sphere
5036        ENDDO
5037     ENDIF
5038!
5039!--  MRT first pass thermal
5040     DO  imrtf = 1, nmrtf
5041        imrt = mrtfsurf(1, imrtf)
5042        isurfsrc = mrtfsurf(2, imrtf)
5043        mrtinlw(imrt) = mrtinlw(imrt) + mrtf(imrtf) * surfoutl(isurfsrc)
5044     ENDDO
5045
5046     IF ( npcbl > 0 )  THEN
5047
5048         pcbinswdir(:) = 0._wp
5049         pcbinswdif(:) = 0._wp
5050         pcbinlw(:) = 0._wp
5051!
5052!--      pcsf first pass
5053         DO icsf = 1, ncsfl
5054             ipcgb = csfsurf(1, icsf)
5055             i = pcbl(ix,ipcgb)
5056             j = pcbl(iy,ipcgb)
5057             k = pcbl(iz,ipcgb)
5058             isurfsrc = csfsurf(2, icsf)
5059
5060             IF ( isurfsrc == -1 )  THEN
5061!
5062!--             Diffuse rad from sky.
5063                pcbinswdif(ipcgb) = csf(1,icsf) * rad_sw_in_diff(j,i)
5064!
5065!--             Absorbed diffuse LW from sky minus emitted to sky
5066                IF ( plant_lw_interact )  THEN
5067                   pcbinlw(ipcgb) = csf(1,icsf)                                  &
5068                                       * (rad_lw_in_diff(j, i)                   &
5069                                          - sigma_sb * (pt(k,j,i)*exner(k))**4)
5070                ENDIF
5071!
5072!--             Direct rad
5073                IF ( zenith(0) > 0 )  THEN
5074!--                Estimate directed box absorption
5075                   pc_abs_frac = 1._wp - exp(pc_abs_eff * lad_s(k,j,i))
5076!
5077!--                isd has already been established, see 1)
5078                   pcbinswdir(ipcgb) = rad_sw_in_dir(j, i) * pc_box_area &
5079                                       * pc_abs_frac * dsitransc(ipcgb, isd)
5080                ENDIF
5081             ELSE
5082                IF ( plant_lw_interact )  THEN
5083!
5084!--                Thermal emission from plan canopy towards respective face
5085                   pcrad = sigma_sb * (pt(k,j,i) * exner(k))**4 * csf(1,icsf)
5086                   surfinlg(isurfsrc) = surfinlg(isurfsrc) + pcrad
5087!
5088!--                Remove the flux above + absorb LW from first pass from surfaces
5089                   asrc = facearea(surf(id, isurfsrc))
5090                   pcbinlw(ipcgb) = pcbinlw(ipcgb)                      &
5091                                    + (csf(1,icsf) * surfoutl(isurfsrc) & ! Absorb from first pass surf emit
5092                                       - pcrad)                         & ! Remove emitted heatflux
5093                                    * asrc
5094                ENDIF
5095             ENDIF
5096         ENDDO
5097
5098         pcbinsw(:) = pcbinswdir(:) + pcbinswdif(:)
5099     ENDIF
5100
5101     IF ( plant_lw_interact )  THEN
5102!
5103!--     Exchange incoming lw radiation from plant canopy
5104#if defined( __parallel )
5105        CALL MPI_Allreduce(MPI_IN_PLACE, surfinlg, nsurf, MPI_REAL, MPI_SUM, comm2d, ierr)
5106        IF ( ierr /= 0 )  THEN
5107           WRITE (9,*) 'Error MPI_Allreduce:', ierr
5108           FLUSH(9)
5109        ENDIF
5110        surfinl(:) = surfinl(:) + surfinlg(surfstart(myid)+1:surfstart(myid+1))
5111#else
5112        surfinl(:) = surfinl(:) + surfinlg(:)
5113#endif
5114     ENDIF
5115
5116     surfins = surfinswdir + surfinswdif
5117     surfinl = surfinl + surfinlwdif
5118     surfinsw = surfins
5119     surfinlw = surfinl
5120     surfoutsw = 0.0_wp
5121     surfoutlw = surfoutll
5122     surfemitlwl = surfoutll
5123
5124     IF ( .NOT.  surface_reflections )  THEN
5125!
5126!--     Set nrefsteps to 0 to disable reflections       
5127        nrefsteps = 0
5128        surfoutsl = albedo_surf * surfins
5129        surfoutll = (1._wp - emiss_surf) * surfinl
5130        surfoutsw = surfoutsw + surfoutsl
5131        surfoutlw = surfoutlw + surfoutll
5132     ENDIF
5133
5134!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5135!--     Next passes - reflections
5136!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5137     DO refstep = 1, nrefsteps
5138
5139         surfoutsl = albedo_surf * surfins
5140!--         for non-transparent surfaces, longwave albedo is 1 - emissivity
5141         surfoutll = (1._wp - emiss_surf) * surfinl
5142
5143#if defined( __parallel )
5144         CALL MPI_AllGatherv(surfoutsl, nsurfl, MPI_REAL, &
5145             surfouts, nsurfs, surfstart, MPI_REAL, comm2d, ierr)
5146         IF ( ierr /= 0 ) THEN
5147             WRITE(9,*) 'Error MPI_AllGatherv2:', ierr, SIZE(surfoutsl), nsurfl, &
5148                        SIZE(surfouts), nsurfs, surfstart
5149             FLUSH(9)
5150         ENDIF
5151
5152         CALL MPI_AllGatherv(surfoutll, nsurfl, MPI_REAL, &
5153             surfoutl, nsurfs, surfstart, MPI_REAL, comm2d, ierr)
5154         IF ( ierr /= 0 ) THEN
5155             WRITE(9,*) 'Error MPI_AllGatherv3:', ierr, SIZE(surfoutll), nsurfl, &
5156                        SIZE(surfoutl), nsurfs, surfstart
5157             FLUSH(9)
5158         ENDIF
5159
5160#else
5161         surfouts = surfoutsl
5162         surfoutl = surfoutll
5163#endif
5164
5165!--         reset for next pass input
5166         surfins = 0._wp
5167         surfinl = 0._wp
5168
5169!--         reflected radiation
5170         DO isvf = 1, nsvfl
5171             isurf = svfsurf(1, isvf)
5172             isurfsrc = svfsurf(2, isvf)
5173             surfins(isurf) = surfins(isurf) + svf(1,isvf) * svf(2,isvf) * surfouts(isurfsrc)
5174             IF ( plant_lw_interact )  THEN
5175                surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * svf(2,isvf) * surfoutl(isurfsrc)
5176             ELSE
5177                surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * surfoutl(isurfsrc)
5178             ENDIF
5179         ENDDO
5180!
5181!--      NOTE: PC absorbtion and MRT from reflected can both be done at once
5182!--      after all reflections if we do one more MPI_ALLGATHERV on surfout.
5183!--      Advantage: less local computation. Disadvantage: one more collective
5184!--      MPI call.
5185!
5186!--      Radiation absorbed by plant canopy
5187         DO  icsf = 1, ncsfl
5188             ipcgb = csfsurf(1, icsf)
5189             isurfsrc = csfsurf(2, icsf)
5190             IF ( isurfsrc == -1 )  CYCLE ! sky->face only in 1st pass, not here
5191!
5192!--          Calculate source surface area. If the `surf' array is removed
5193!--          before timestepping starts (future version), then asrc must be
5194!--          stored within `csf'
5195             asrc = facearea(surf(id, isurfsrc))
5196             pcbinsw(ipcgb) = pcbinsw(ipcgb) + csf(1,icsf) * surfouts(isurfsrc) * asrc
5197             IF ( plant_lw_interact )  THEN
5198                pcbinlw(ipcgb) = pcbinlw(ipcgb) + csf(1,icsf) * surfoutl(isurfsrc) * asrc
5199             ENDIF
5200         ENDDO
5201!
5202!--      MRT reflected
5203         DO  imrtf = 1, nmrtf
5204            imrt = mrtfsurf(1, imrtf)
5205            isurfsrc = mrtfsurf(2, imrtf)
5206            mrtinsw(imrt) = mrtinsw(imrt) + mrtft(imrtf) * surfouts(isurfsrc)
5207            mrtinlw(imrt) = mrtinlw(imrt) + mrtf(imrtf) * surfoutl(isurfsrc)
5208         ENDDO
5209
5210         surfinsw = surfinsw  + surfins
5211         surfinlw = surfinlw  + surfinl
5212         surfoutsw = surfoutsw + surfoutsl
5213         surfoutlw = surfoutlw + surfoutll
5214
5215     ENDDO ! refstep
5216
5217!--  push heat flux absorbed by plant canopy to respective 3D arrays
5218     IF ( npcbl > 0 )  THEN
5219         pc_heating_rate(:,:,:) = 0.0_wp
5220         DO ipcgb = 1, npcbl
5221             j = pcbl(iy, ipcgb)
5222             i = pcbl(ix, ipcgb)
5223             k = pcbl(iz, ipcgb)
5224!
5225!--          Following expression equals former kk = k - nzb_s_inner(j,i)
5226             kk = k - get_topography_top_index_ji( j, i, 's' )  !- lad arrays are defined flat
5227             pc_heating_rate(kk, j, i) = (pcbinsw(ipcgb) + pcbinlw(ipcgb)) &
5228                 * pchf_prep(k) * pt(k, j, i) !-- = dT/dt
5229         ENDDO
5230
5231         IF ( humidity .AND. plant_canopy_transpiration ) THEN
5232!--          Calculation of plant canopy transpiration rate and correspondidng latent heat rate
5233             pc_transpiration_rate(:,:,:) = 0.0_wp
5234             pc_latent_rate(:,:,:) = 0.0_wp
5235             DO ipcgb = 1, npcbl
5236                 i = pcbl(ix, ipcgb)
5237                 j = pcbl(iy, ipcgb)
5238                 k = pcbl(iz, ipcgb)
5239                 kk = k - get_topography_top_index_ji( j, i, 's' )  !- lad arrays are defined flat
5240                 CALL pcm_calc_transpiration_rate( i, j, k, kk, pcbinsw(ipcgb), pcbinlw(ipcgb), &
5241                                                   pc_transpiration_rate(kk,j,i), pc_latent_rate(kk,j,i) )
5242              ENDDO
5243         ENDIF
5244     ENDIF
5245!
5246!--  Calculate black body MRT (after all reflections)
5247     IF ( nmrtbl > 0 )  THEN
5248        IF ( mrt_include_sw )  THEN
5249           mrt(:) = ((mrtinsw(:) + mrtinlw(:)) / sigma_sb) ** .25_wp
5250        ELSE
5251           mrt(:) = (mrtinlw(:) / sigma_sb) ** .25_wp
5252        ENDIF
5253     ENDIF
5254!
5255!--     Transfer radiation arrays required for energy balance to the respective data types
5256     DO  i = 1, nsurfl
5257        m  = surfl(5,i)
5258!
5259!--     (1) Urban surfaces
5260!--     upward-facing
5261        IF ( surfl(1,i) == iup_u )  THEN
5262           surf_usm_h%rad_sw_in(m)  = surfinsw(i)
5263           surf_usm_h%rad_sw_out(m) = surfoutsw(i)
5264           surf_usm_h%rad_sw_dir(m) = surfinswdir(i)
5265           surf_usm_h%rad_sw_dif(m) = surfinswdif(i)
5266           surf_usm_h%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -        &
5267                                      surfinswdif(i)
5268           surf_usm_h%rad_sw_res(m) = surfins(i)
5269           surf_usm_h%rad_lw_in(m)  = surfinlw(i)
5270           surf_usm_h%rad_lw_out(m) = surfoutlw(i)
5271           surf_usm_h%rad_net(m)    = surfinsw(i) - surfoutsw(i) +          &
5272                                      surfinlw(i) - surfoutlw(i)
5273           surf_usm_h%rad_net_l(m)  = surf_usm_h%rad_net(m)
5274           surf_usm_h%rad_lw_dif(m) = surfinlwdif(i)
5275           surf_usm_h%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5276           surf_usm_h%rad_lw_res(m) = surfinl(i)
5277!
5278!--     northward-facding
5279        ELSEIF ( surfl(1,i) == inorth_u )  THEN
5280           surf_usm_v(0)%rad_sw_in(m)  = surfinsw(i)
5281           surf_usm_v(0)%rad_sw_out(m) = surfoutsw(i)
5282           surf_usm_v(0)%rad_sw_dir(m) = surfinswdir(i)
5283           surf_usm_v(0)%rad_sw_dif(m) = surfinswdif(i)
5284           surf_usm_v(0)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5285                                         surfinswdif(i)
5286           surf_usm_v(0)%rad_sw_res(m) = surfins(i)
5287           surf_usm_v(0)%rad_lw_in(m)  = surfinlw(i)
5288           surf_usm_v(0)%rad_lw_out(m) = surfoutlw(i)
5289           surf_usm_v(0)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5290                                         surfinlw(i) - surfoutlw(i)
5291           surf_usm_v(0)%rad_net_l(m)  = surf_usm_v(0)%rad_net(m)
5292           surf_usm_v(0)%rad_lw_dif(m) = surfinlwdif(i)
5293           surf_usm_v(0)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5294           surf_usm_v(0)%rad_lw_res(m) = surfinl(i)
5295!
5296!--     southward-facding
5297        ELSEIF ( surfl(1,i) == isouth_u )  THEN
5298           surf_usm_v(1)%rad_sw_in(m)  = surfinsw(i)
5299           surf_usm_v(1)%rad_sw_out(m) = surfoutsw(i)
5300           surf_usm_v(1)%rad_sw_dir(m) = surfinswdir(i)
5301           surf_usm_v(1)%rad_sw_dif(m) = surfinswdif(i)
5302           surf_usm_v(1)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5303                                         surfinswdif(i)
5304           surf_usm_v(1)%rad_sw_res(m) = surfins(i)
5305           surf_usm_v(1)%rad_lw_in(m)  = surfinlw(i)
5306           surf_usm_v(1)%rad_lw_out(m) = surfoutlw(i)
5307           surf_usm_v(1)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5308                                         surfinlw(i) - surfoutlw(i)
5309           surf_usm_v(1)%rad_net_l(m)  = surf_usm_v(1)%rad_net(m)
5310           surf_usm_v(1)%rad_lw_dif(m) = surfinlwdif(i)
5311           surf_usm_v(1)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5312           surf_usm_v(1)%rad_lw_res(m) = surfinl(i)
5313!
5314!--     eastward-facing
5315        ELSEIF ( surfl(1,i) == ieast_u )  THEN
5316           surf_usm_v(2)%rad_sw_in(m)  = surfinsw(i)
5317           surf_usm_v(2)%rad_sw_out(m) = surfoutsw(i)
5318           surf_usm_v(2)%rad_sw_dir(m) = surfinswdir(i)
5319           surf_usm_v(2)%rad_sw_dif(m) = surfinswdif(i)
5320           surf_usm_v(2)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5321                                         surfinswdif(i)
5322           surf_usm_v(2)%rad_sw_res(m) = surfins(i)
5323           surf_usm_v(2)%rad_lw_in(m)  = surfinlw(i)
5324           surf_usm_v(2)%rad_lw_out(m) = surfoutlw(i)
5325           surf_usm_v(2)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5326                                         surfinlw(i) - surfoutlw(i)
5327           surf_usm_v(2)%rad_net_l(m)  = surf_usm_v(2)%rad_net(m)
5328           surf_usm_v(2)%rad_lw_dif(m) = surfinlwdif(i)
5329           surf_usm_v(2)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5330           surf_usm_v(2)%rad_lw_res(m) = surfinl(i)
5331!
5332!--     westward-facding
5333        ELSEIF ( surfl(1,i) == iwest_u )  THEN
5334           surf_usm_v(3)%rad_sw_in(m)  = surfinsw(i)
5335           surf_usm_v(3)%rad_sw_out(m) = surfoutsw(i)
5336           surf_usm_v(3)%rad_sw_dir(m) = surfinswdir(i)
5337           surf_usm_v(3)%rad_sw_dif(m) = surfinswdif(i)
5338           surf_usm_v(3)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5339                                         surfinswdif(i)
5340           surf_usm_v(3)%rad_sw_res(m) = surfins(i)
5341           surf_usm_v(3)%rad_lw_in(m)  = surfinlw(i)
5342           surf_usm_v(3)%rad_lw_out(m) = surfoutlw(i)
5343           surf_usm_v(3)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5344                                         surfinlw(i) - surfoutlw(i)
5345           surf_usm_v(3)%rad_net_l(m)  = surf_usm_v(3)%rad_net(m)
5346           surf_usm_v(3)%rad_lw_dif(m) = surfinlwdif(i)
5347           surf_usm_v(3)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5348           surf_usm_v(3)%rad_lw_res(m) = surfinl(i)
5349!
5350!--     (2) land surfaces
5351!--     upward-facing
5352        ELSEIF ( surfl(1,i) == iup_l )  THEN
5353           surf_lsm_h%rad_sw_in(m)  = surfinsw(i)
5354           surf_lsm_h%rad_sw_out(m) = surfoutsw(i)
5355           surf_lsm_h%rad_sw_dir(m) = surfinswdir(i)
5356           surf_lsm_h%rad_sw_dif(m) = surfinswdif(i)
5357           surf_lsm_h%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -        &
5358                                         surfinswdif(i)
5359           surf_lsm_h%rad_sw_res(m) = surfins(i)
5360           surf_lsm_h%rad_lw_in(m)  = surfinlw(i)
5361           surf_lsm_h%rad_lw_out(m) = surfoutlw(i)
5362           surf_lsm_h%rad_net(m)    = surfinsw(i) - surfoutsw(i) +          &
5363                                      surfinlw(i) - surfoutlw(i)
5364           surf_lsm_h%rad_lw_dif(m) = surfinlwdif(i)
5365           surf_lsm_h%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5366           surf_lsm_h%rad_lw_res(m) = surfinl(i)
5367!
5368!--     northward-facding
5369        ELSEIF ( surfl(1,i) == inorth_l )  THEN
5370           surf_lsm_v(0)%rad_sw_in(m)  = surfinsw(i)
5371           surf_lsm_v(0)%rad_sw_out(m) = surfoutsw(i)
5372           surf_lsm_v(0)%rad_sw_dir(m) = surfinswdir(i)
5373           surf_lsm_v(0)%rad_sw_dif(m) = surfinswdif(i)
5374           surf_lsm_v(0)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5375                                         surfinswdif(i)
5376           surf_lsm_v(0)%rad_sw_res(m) = surfins(i)
5377           surf_lsm_v(0)%rad_lw_in(m)  = surfinlw(i)
5378           surf_lsm_v(0)%rad_lw_out(m) = surfoutlw(i)
5379           surf_lsm_v(0)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5380                                         surfinlw(i) - surfoutlw(i)
5381           surf_lsm_v(0)%rad_lw_dif(m) = surfinlwdif(i)
5382           surf_lsm_v(0)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5383           surf_lsm_v(0)%rad_lw_res(m) = surfinl(i)
5384!
5385!--     southward-facding
5386        ELSEIF ( surfl(1,i) == isouth_l )  THEN
5387           surf_lsm_v(1)%rad_sw_in(m)  = surfinsw(i)
5388           surf_lsm_v(1)%rad_sw_out(m) = surfoutsw(i)
5389           surf_lsm_v(1)%rad_sw_dir(m) = surfinswdir(i)
5390           surf_lsm_v(1)%rad_sw_dif(m) = surfinswdif(i)
5391           surf_lsm_v(1)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5392                                         surfinswdif(i)
5393           surf_lsm_v(1)%rad_sw_res(m) = surfins(i)
5394           surf_lsm_v(1)%rad_lw_in(m)  = surfinlw(i)
5395           surf_lsm_v(1)%rad_lw_out(m) = surfoutlw(i)
5396           surf_lsm_v(1)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5397                                         surfinlw(i) - surfoutlw(i)
5398           surf_lsm_v(1)%rad_lw_dif(m) = surfinlwdif(i)
5399           surf_lsm_v(1)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5400           surf_lsm_v(1)%rad_lw_res(m) = surfinl(i)
5401!
5402!--     eastward-facing
5403        ELSEIF ( surfl(1,i) == ieast_l )  THEN
5404           surf_lsm_v(2)%rad_sw_in(m)  = surfinsw(i)
5405           surf_lsm_v(2)%rad_sw_out(m) = surfoutsw(i)
5406           surf_lsm_v(2)%rad_sw_dir(m) = surfinswdir(i)
5407           surf_lsm_v(2)%rad_sw_dif(m) = surfinswdif(i)
5408           surf_lsm_v(2)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5409                                         surfinswdif(i)
5410           surf_lsm_v(2)%rad_sw_res(m) = surfins(i)
5411           surf_lsm_v(2)%rad_lw_in(m)  = surfinlw(i)
5412           surf_lsm_v(2)%rad_lw_out(m) = surfoutlw(i)
5413           surf_lsm_v(2)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5414                                         surfinlw(i) - surfoutlw(i)
5415           surf_lsm_v(2)%rad_lw_dif(m) = surfinlwdif(i)
5416           surf_lsm_v(2)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5417           surf_lsm_v(2)%rad_lw_res(m) = surfinl(i)
5418!
5419!--     westward-facing
5420        ELSEIF ( surfl(1,i) == iwest_l )  THEN
5421           surf_lsm_v(3)%rad_sw_in(m)  = surfinsw(i)
5422           surf_lsm_v(3)%rad_sw_out(m) = surfoutsw(i)
5423           surf_lsm_v(3)%rad_sw_dir(m) = surfinswdir(i)
5424           surf_lsm_v(3)%rad_sw_dif(m) = surfinswdif(i)
5425           surf_lsm_v(3)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5426                                         surfinswdif(i)
5427           surf_lsm_v(3)%rad_sw_res(m) = surfins(i)
5428           surf_lsm_v(3)%rad_lw_in(m)  = surfinlw(i)
5429           surf_lsm_v(3)%rad_lw_out(m) = surfoutlw(i)
5430           surf_lsm_v(3)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5431                                         surfinlw(i) - surfoutlw(i)
5432           surf_lsm_v(3)%rad_lw_dif(m) = surfinlwdif(i)
5433           surf_lsm_v(3)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5434           surf_lsm_v(3)%rad_lw_res(m) = surfinl(i)
5435        ENDIF
5436
5437     ENDDO
5438
5439     DO  m = 1, surf_usm_h%ns
5440        surf_usm_h%surfhf(m) = surf_usm_h%rad_sw_in(m)  +                   &
5441                               surf_usm_h%rad_lw_in(m)  -                   &
5442                               surf_usm_h%rad_sw_out(m) -                   &
5443                               surf_usm_h%rad_lw_out(m)
5444     ENDDO
5445     DO  m = 1, surf_lsm_h%ns
5446        surf_lsm_h%surfhf(m) = surf_lsm_h%rad_sw_in(m)  +                   &
5447                               surf_lsm_h%rad_lw_in(m)  -                   &
5448                               surf_lsm_h%rad_sw_out(m) -                   &
5449                               surf_lsm_h%rad_lw_out(m)
5450     ENDDO
5451
5452     DO  l = 0, 3
5453!--     urban
5454        DO  m = 1, surf_usm_v(l)%ns
5455           surf_usm_v(l)%surfhf(m) = surf_usm_v(l)%rad_sw_in(m)  +          &
5456                                     surf_usm_v(l)%rad_lw_in(m)  -          &
5457                                     surf_usm_v(l)%rad_sw_out(m) -          &
5458                                     surf_usm_v(l)%rad_lw_out(m)
5459        ENDDO
5460!--     land
5461        DO  m = 1, surf_lsm_v(l)%ns
5462           surf_lsm_v(l)%surfhf(m) = surf_lsm_v(l)%rad_sw_in(m)  +          &
5463                                     surf_lsm_v(l)%rad_lw_in(m)  -          &
5464                                     surf_lsm_v(l)%rad_sw_out(m) -          &
5465                                     surf_lsm_v(l)%rad_lw_out(m)
5466
5467        ENDDO
5468     ENDDO
5469!
5470!--  Calculate the average temperature, albedo, and emissivity for urban/land
5471!--  domain when using average_radiation in the respective radiation model
5472
5473!--  calculate horizontal area
5474! !!! ATTENTION!!! uniform grid is assumed here
5475     area_hor = (nx+1) * (ny+1) * dx * dy
5476!
5477!--  absorbed/received SW & LW and emitted LW energy of all physical
5478!--  surfaces (land and urban) in local processor
5479     pinswl = 0._wp
5480     pinlwl = 0._wp
5481     pabsswl = 0._wp
5482     pabslwl = 0._wp
5483     pemitlwl = 0._wp
5484     emiss_sum_surfl = 0._wp
5485     area_surfl = 0._wp
5486     DO  i = 1, nsurfl
5487        d = surfl(id, i)
5488!--  received SW & LW
5489        pinswl = pinswl + (surfinswdir(i) + surfinswdif(i)) * facearea(d)
5490        pinlwl = pinlwl + surfinlwdif(i) * facearea(d)
5491!--   absorbed SW & LW
5492        pabsswl = pabsswl + (1._wp - albedo_surf(i)) *                   &
5493                                                surfinsw(i) * facearea(d)
5494        pabslwl = pabslwl + emiss_surf(i) * surfinlw(i) * facearea(d)
5495!--   emitted LW
5496        pemitlwl = pemitlwl + surfemitlwl(i) * facearea(d)
5497!--   emissivity and area sum
5498        emiss_sum_surfl = emiss_sum_surfl + emiss_surf(i) * facearea(d)
5499        area_surfl = area_surfl + facearea(d)
5500     END DO
5501!
5502!--  add the absorbed SW energy by plant canopy
5503     IF ( npcbl > 0 )  THEN
5504        pabsswl = pabsswl + SUM(pcbinsw)
5505        pabslwl = pabslwl + SUM(pcbinlw)
5506        pinswl = pinswl + SUM(pcbinswdir) + SUM(pcbinswdif)
5507     ENDIF
5508!
5509!--  gather all rad flux energy in all processors
5510#if defined( __parallel )
5511     CALL MPI_ALLREDUCE( pinswl, pinsw, 1, MPI_REAL, MPI_SUM, comm2d, ierr)
5512     IF ( ierr /= 0 ) THEN
5513         WRITE(9,*) 'Error MPI_AllReduce5:', ierr, pinswl, pinsw
5514         FLUSH(9)
5515     ENDIF
5516     CALL MPI_ALLREDUCE( pinlwl, pinlw, 1, MPI_REAL, MPI_SUM, comm2d, ierr)
5517     IF ( ierr /= 0 ) THEN
5518         WRITE(9,*) 'Error MPI_AllReduce6:', ierr, pinlwl, pinlw
5519         FLUSH(9)
5520     ENDIF
5521     CALL MPI_ALLREDUCE( pabsswl, pabssw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5522     IF ( ierr /= 0 ) THEN
5523         WRITE(9,*) 'Error MPI_AllReduce7:', ierr, pabsswl, pabssw
5524         FLUSH(9)
5525     ENDIF
5526     CALL MPI_ALLREDUCE( pabslwl, pabslw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5527     IF ( ierr /= 0 ) THEN
5528         WRITE(9,*) 'Error MPI_AllReduce8:', ierr, pabslwl, pabslw
5529         FLUSH(9)
5530     ENDIF
5531     CALL MPI_ALLREDUCE( pemitlwl, pemitlw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5532     IF ( ierr /= 0 ) THEN
5533         WRITE(9,*) 'Error MPI_AllReduce8:', ierr, pemitlwl, pemitlw
5534         FLUSH(9)
5535     ENDIF
5536     CALL MPI_ALLREDUCE( emiss_sum_surfl, emiss_sum_surf, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5537     IF ( ierr /= 0 ) THEN
5538         WRITE(9,*) 'Error MPI_AllReduce9:', ierr, emiss_sum_surfl, emiss_sum_surf
5539         FLUSH(9)
5540     ENDIF
5541     CALL MPI_ALLREDUCE( area_surfl, area_surf, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5542     IF ( ierr /= 0 ) THEN
5543         WRITE(9,*) 'Error MPI_AllReduce10:', ierr, area_surfl, area_surf
5544         FLUSH(9)
5545     ENDIF
5546#else
5547     pinsw = pinswl
5548     pinlw = pinlwl
5549     pabssw = pabsswl
5550     pabslw = pabslwl
5551     pemitlw = pemitlwl
5552     emiss_sum_surf = emiss_sum_surfl
5553     area_surf = area_surfl
5554#endif
5555
5556!--  (1) albedo
5557     IF ( pinsw /= 0.0_wp )  &
5558          albedo_urb = (pinsw - pabssw) / pinsw
5559!--  (2) average emmsivity
5560     IF ( area_surf /= 0.0_wp ) &
5561          emissivity_urb = emiss_sum_surf / area_surf
5562!
5563!--  Temporally comment out calculation of effective radiative temperature.
5564!--  See below for more explanation.
5565!--  (3) temperature
5566!--   first we calculate an effective horizontal area to account for
5567!--   the effect of vertical surfaces (which contributes to LW emission)
5568!--   We simply use the ratio of the total LW to the incoming LW flux
5569      area_hor = pinlw/rad_lw_in_diff(nyn,nxl)
5570      t_rad_urb = ( (pemitlw - pabslw + emissivity_urb*pinlw) / &
5571           (emissivity_urb*sigma_sb * area_hor) )**0.25_wp
5572
5573    CONTAINS
5574
5575!------------------------------------------------------------------------------!
5576!> Calculates radiation absorbed by box with given size and LAD.
5577!>
5578!> Simulates resol**2 rays (by equally spacing a bounding horizontal square
5579!> conatining all possible rays that would cross the box) and calculates
5580!> average transparency per ray. Returns fraction of absorbed radiation flux
5581!> and area for which this fraction is effective.
5582!------------------------------------------------------------------------------!
5583    PURE SUBROUTINE box_absorb(boxsize, resol, dens, uvec, area, absorb)
5584       IMPLICIT NONE
5585
5586       REAL(wp), DIMENSION(3), INTENT(in) :: &
5587            boxsize, &      !< z, y, x size of box in m
5588            uvec            !< z, y, x unit vector of incoming flux
5589       INTEGER(iwp), INTENT(in) :: &
5590            resol           !< No. of rays in x and y dimensions
5591       REAL(wp), INTENT(in) :: &
5592            dens            !< box density (e.g. Leaf Area Density)
5593       REAL(wp), INTENT(out) :: &
5594            area, &         !< horizontal area for flux absorbtion
5595            absorb          !< fraction of absorbed flux
5596       REAL(wp) :: &
5597            xshift, yshift, &
5598            xmin, xmax, ymin, ymax, &
5599            xorig, yorig, &
5600            dx1, dy1, dz1, dx2, dy2, dz2, &
5601            crdist, &
5602            transp
5603       INTEGER(iwp) :: &
5604            i, j
5605
5606       xshift = uvec(3) / uvec(1) * boxsize(1)
5607       xmin = min(0._wp, -xshift)
5608       xmax = boxsize(3) + max(0._wp, -xshift)
5609       yshift = uvec(2) / uvec(1) * boxsize(1)
5610       ymin = min(0._wp, -yshift)
5611       ymax = boxsize(2) + max(0._wp, -yshift)
5612
5613       transp = 0._wp
5614       DO i = 1, resol
5615          xorig = xmin + (xmax-xmin) * (i-.5_wp) / resol
5616          DO j = 1, resol
5617             yorig = ymin + (ymax-ymin) * (j-.5_wp) / resol
5618
5619             dz1 = 0._wp
5620             dz2 = boxsize(1)/uvec(1)
5621
5622             IF ( uvec(2) > 0._wp )  THEN
5623                dy1 = -yorig             / uvec(2) !< crossing with y=0
5624                dy2 = (boxsize(2)-yorig) / uvec(2) !< crossing with y=boxsize(2)
5625             ELSE !uvec(2)==0
5626                dy1 = -huge(1._wp)
5627                dy2 = huge(1._wp)
5628             ENDIF
5629
5630             IF ( uvec(3) > 0._wp )  THEN
5631                dx1 = -xorig             / uvec(3) !< crossing with x=0
5632                dx2 = (boxsize(3)-xorig) / uvec(3) !< crossing with x=boxsize(3)
5633             ELSE !uvec(3)==0
5634                dx1 = -huge(1._wp)
5635                dx2 = huge(1._wp)
5636             ENDIF
5637
5638             crdist = max(0._wp, (min(dz2, dy2, dx2) - max(dz1, dy1, dx1)))
5639             transp = transp + exp(-ext_coef * dens * crdist)
5640          ENDDO
5641       ENDDO
5642       transp = transp / resol**2
5643       area = (boxsize(3)+xshift)*(boxsize(2)+yshift)
5644       absorb = 1._wp - transp
5645
5646    END SUBROUTINE box_absorb
5647
5648!------------------------------------------------------------------------------!
5649! Description:
5650! ------------
5651!> This subroutine splits direct and diffusion dw radiation
5652!> It sould not be called in case the radiation model already does it
5653!> It follows <CITATION>
5654!------------------------------------------------------------------------------!
5655    SUBROUTINE calc_diffusion_radiation 
5656   
5657        REAL(wp), PARAMETER                          :: lowest_solarUp = 0.1_wp  !< limit the sun elevation to protect stability of the calculation
5658        INTEGER(iwp)                                 :: i, j
5659        REAL(wp)                                     ::  year_angle              !< angle
5660        REAL(wp)                                     ::  etr                     !< extraterestrial radiation
5661        REAL(wp)                                     ::  corrected_solarUp       !< corrected solar up radiation
5662        REAL(wp)                                     ::  horizontalETR           !< horizontal extraterestrial radiation
5663        REAL(wp)                                     ::  clearnessIndex          !< clearness index
5664        REAL(wp)                                     ::  diff_frac               !< diffusion fraction of the radiation
5665
5666       
5667!--     Calculate current day and time based on the initial values and simulation time
5668        year_angle = ( (day_of_year_init * 86400) + time_utc_init              &
5669                        + time_since_reference_point )  * d_seconds_year       &
5670                        * 2.0_wp * pi
5671       
5672        etr = solar_constant * (1.00011_wp +                                   &
5673                          0.034221_wp * cos(year_angle) +                      &
5674                          0.001280_wp * sin(year_angle) +                      &
5675                          0.000719_wp * cos(2.0_wp * year_angle) +             &
5676                          0.000077_wp * sin(2.0_wp * year_angle))
5677       
5678!--   
5679!--     Under a very low angle, we keep extraterestrial radiation at
5680!--     the last small value, therefore the clearness index will be pushed
5681!--     towards 0 while keeping full continuity.
5682!--   
5683        IF ( zenith(0) <= lowest_solarUp )  THEN
5684            corrected_solarUp = lowest_solarUp
5685        ELSE
5686            corrected_solarUp = zenith(0)
5687        ENDIF
5688       
5689        horizontalETR = etr * corrected_solarUp
5690       
5691        DO i = nxl, nxr
5692            DO j = nys, nyn
5693                clearnessIndex = rad_sw_in(0,j,i) / horizontalETR
5694                diff_frac = 1.0_wp / (1.0_wp + exp(-5.0033_wp + 8.6025_wp * clearnessIndex))
5695                rad_sw_in_diff(j,i) = rad_sw_in(0,j,i) * diff_frac
5696                rad_sw_in_dir(j,i)  = rad_sw_in(0,j,i) * (1.0_wp - diff_frac)
5697                rad_lw_in_diff(j,i) = rad_lw_in(0,j,i)
5698            ENDDO
5699        ENDDO
5700       
5701    END SUBROUTINE calc_diffusion_radiation
5702
5703
5704 END SUBROUTINE radiation_interaction
5705   
5706!------------------------------------------------------------------------------!
5707! Description:
5708! ------------
5709!> This subroutine initializes structures needed for radiative transfer
5710!> model. This model calculates transformation processes of the
5711!> radiation inside urban and land canopy layer. The module includes also
5712!> the interaction of the radiation with the resolved plant canopy.
5713!>
5714!> For more info. see Resler et al. 2017
5715!>
5716!> The new version 2.0 was radically rewriten, the discretization scheme
5717!> has been changed. This new version significantly improves effectivity
5718!> of the paralelization and the scalability of the model.
5719!>
5720!------------------------------------------------------------------------------!
5721    SUBROUTINE radiation_interaction_init
5722
5723       USE control_parameters,                                                 &
5724           ONLY:  dz_stretch_level_start
5725           
5726       USE netcdf_data_input_mod,                                              &
5727           ONLY:  leaf_area_density_f
5728
5729       USE plant_canopy_model_mod,                                             &
5730           ONLY:  pch_index, lad_s
5731
5732       IMPLICIT NONE
5733
5734       INTEGER(iwp) :: i, j, k, l, m, d
5735       INTEGER(iwp) :: k_topo     !< vertical index indicating topography top for given (j,i)
5736       INTEGER(iwp) :: nzptl, nzubl, nzutl, isurf, ipcgb, imrt
5737       REAL(wp)     :: mrl
5738#if defined( __parallel )
5739       INTEGER(iwp), DIMENSION(:), POINTER       ::  gridsurf_rma   !< fortran pointer, but lower bounds are 1
5740       TYPE(c_ptr)                               ::  gridsurf_rma_p !< allocated c pointer
5741       INTEGER(iwp)                              ::  minfo          !< MPI RMA window info handle
5742#endif
5743
5744!
5745!--     precalculate face areas for different face directions using normal vector
5746        DO d = 0, nsurf_type
5747            facearea(d) = 1._wp
5748            IF ( idir(d) == 0 ) facearea(d) = facearea(d) * dx
5749            IF ( jdir(d) == 0 ) facearea(d) = facearea(d) * dy
5750            IF ( kdir(d) == 0 ) facearea(d) = facearea(d) * dz(1)
5751        ENDDO
5752!
5753!--    Find nzub, nzut, nzu via wall_flag_0 array (nzb_s_inner will be
5754!--    removed later). The following contruct finds the lowest / largest index
5755!--    for any upward-facing wall (see bit 12).
5756       nzubl = MINVAL( get_topography_top_index( 's' ) )
5757       nzutl = MAXVAL( get_topography_top_index( 's' ) )
5758
5759       nzubl = MAX( nzubl, nzb )
5760
5761       IF ( plant_canopy )  THEN
5762!--        allocate needed arrays
5763           ALLOCATE( pct(nys:nyn,nxl:nxr) )
5764           ALLOCATE( pch(nys:nyn,nxl:nxr) )
5765
5766!--        calculate plant canopy height
5767           npcbl = 0
5768           pct   = 0
5769           pch   = 0
5770           DO i = nxl, nxr
5771               DO j = nys, nyn
5772!
5773!--                Find topography top index
5774                   k_topo = get_topography_top_index_ji( j, i, 's' )
5775
5776                   DO k = nzt+1, 0, -1
5777                       IF ( lad_s(k,j,i) /= 0.0_wp )  THEN
5778!--                        we are at the top of the pcs
5779                           pct(j,i) = k + k_topo
5780                           pch(j,i) = k
5781                           npcbl = npcbl + pch(j,i)
5782                           EXIT
5783                       ENDIF
5784                   ENDDO
5785               ENDDO
5786           ENDDO
5787
5788           nzutl = MAX( nzutl, MAXVAL( pct ) )
5789           nzptl = MAXVAL( pct )
5790!--        code of plant canopy model uses parameter pch_index
5791!--        we need to setup it here to right value
5792!--        (pch_index, lad_s and other arrays in PCM are defined flat)
5793           pch_index = MERGE( leaf_area_density_f%nz - 1, MAXVAL( pch ),       &
5794                              leaf_area_density_f%from_file )
5795
5796           prototype_lad = MAXVAL( lad_s ) * .9_wp  !< better be *1.0 if lad is either 0 or maxval(lad) everywhere
5797           IF ( prototype_lad <= 0._wp ) prototype_lad = .3_wp
5798           !WRITE(message_string, '(a,f6.3)') 'Precomputing effective box optical ' &
5799           !    // 'depth using prototype leaf area density = ', prototype_lad
5800           !CALL message('usm_init_urban_surface', 'PA0520', 0, 0, -1, 6, 0)
5801       ENDIF
5802
5803       nzutl = MIN( nzutl + nzut_free, nzt )
5804
5805#if defined( __parallel )
5806       CALL MPI_AllReduce(nzubl, nzub, 1, MPI_INTEGER, MPI_MIN, comm2d, ierr )
5807       IF ( ierr /= 0 ) THEN
5808           WRITE(9,*) 'Error MPI_AllReduce11:', ierr, nzubl, nzub
5809           FLUSH(9)
5810       ENDIF
5811       CALL MPI_AllReduce(nzutl, nzut, 1, MPI_INTEGER, MPI_MAX, comm2d, ierr )
5812       IF ( ierr /= 0 ) THEN
5813           WRITE(9,*) 'Error MPI_AllReduce12:', ierr, nzutl, nzut
5814           FLUSH(9)
5815       ENDIF
5816       CALL MPI_AllReduce(nzptl, nzpt, 1, MPI_INTEGER, MPI_MAX, comm2d, ierr )
5817       IF ( ierr /= 0 ) THEN
5818           WRITE(9,*) 'Error MPI_AllReduce13:', ierr, nzptl, nzpt
5819           FLUSH(9)
5820       ENDIF
5821#else
5822       nzub = nzubl
5823       nzut = nzutl
5824       nzpt = nzptl
5825#endif
5826!
5827!--    Stretching (non-uniform grid spacing) is not considered in the radiation
5828!--    model. Therefore, vertical stretching has to be applied above the area
5829!--    where the parts of the radiation model which assume constant grid spacing
5830!--    are active. ABS (...) is required because the default value of
5831!--    dz_stretch_level_start is -9999999.9_wp (negative).
5832       IF ( ABS( dz_stretch_level_start(1) ) <= zw(nzut) ) THEN
5833          WRITE( message_string, * ) 'The lowest level where vertical ',       &
5834                                     'stretching is applied have to be ',      &
5835                                     'greater than ', zw(nzut)
5836          CALL message( 'radiation_interaction_init', 'PA0496', 1, 2, 0, 6, 0 )
5837       ENDIF 
5838!
5839!--    global number of urban and plant layers
5840       nzu = nzut - nzub + 1
5841       nzp = nzpt - nzub + 1
5842!
5843!--    check max_raytracing_dist relative to urban surface layer height
5844       mrl = 2.0_wp * nzu * dz(1)
5845!--    set max_raytracing_dist to double the urban surface layer height, if not set
5846       IF ( max_raytracing_dist == -999.0_wp ) THEN
5847          max_raytracing_dist = mrl
5848       ENDIF
5849!--    check if max_raytracing_dist set too low (here we only warn the user. Other
5850!      option is to correct the value again to double the urban surface layer height)
5851       IF ( max_raytracing_dist  <  mrl ) THEN
5852          WRITE(message_string, '(a,f6.1)') 'Max_raytracing_dist is set less than ', &
5853               'double the urban surface layer height, i.e. ', mrl
5854          CALL message('radiation_interaction_init', 'PA0521', 0, 0, -1, 6, 0)
5855       ENDIF
5856!        IF ( max_raytracing_dist <= mrl ) THEN
5857!           IF ( max_raytracing_dist /= -999.0_wp ) THEN
5858! !--          max_raytracing_dist too low
5859!              WRITE(message_string, '(a,f6.1)') 'Max_raytracing_dist too low, ' &
5860!                    // 'override to value ', mrl
5861!              CALL message('radiation_interaction_init', 'PA0521', 0, 0, -1, 6, 0)
5862!           ENDIF
5863!           max_raytracing_dist = mrl
5864!        ENDIF
5865!
5866!--    allocate urban surfaces grid
5867!--    calc number of surfaces in local proc
5868       CALL location_message( '    calculation of indices for surfaces', .TRUE. )
5869       nsurfl = 0
5870!
5871!--    Number of horizontal surfaces including land- and roof surfaces in both USM and LSM. Note that
5872!--    All horizontal surface elements are already counted in surface_mod.
5873       startland = 1
5874       nsurfl    = surf_usm_h%ns + surf_lsm_h%ns
5875       endland   = nsurfl
5876       nlands    = endland - startland + 1
5877
5878!
5879!--    Number of vertical surfaces in both USM and LSM. Note that all vertical surface elements are
5880!--    already counted in surface_mod.
5881       startwall = nsurfl+1
5882       DO  i = 0,3
5883          nsurfl = nsurfl + surf_usm_v(i)%ns + surf_lsm_v(i)%ns
5884       ENDDO
5885       endwall = nsurfl
5886       nwalls  = endwall - startwall + 1
5887       dirstart = (/ startland, startwall, startwall, startwall, startwall /)
5888       dirend = (/ endland, endwall, endwall, endwall, endwall /)
5889
5890!--    fill gridpcbl and pcbl
5891       IF ( npcbl > 0 )  THEN
5892           ALLOCATE( pcbl(iz:ix, 1:npcbl) )
5893           ALLOCATE( gridpcbl(nzub:nzpt,nys:nyn,nxl:nxr) )
5894           pcbl = -1
5895           gridpcbl(:,:,:) = 0
5896           ipcgb = 0
5897           DO i = nxl, nxr
5898               DO j = nys, nyn
5899!
5900!--                Find topography top index
5901                   k_topo = get_topography_top_index_ji( j, i, 's' )
5902
5903                   DO k = k_topo + 1, pct(j,i)
5904                       ipcgb = ipcgb + 1
5905                       gridpcbl(k,j,i) = ipcgb
5906                       pcbl(:,ipcgb) = (/ k, j, i /)
5907                   ENDDO
5908               ENDDO
5909           ENDDO
5910           ALLOCATE( pcbinsw( 1:npcbl ) )
5911           ALLOCATE( pcbinswdir( 1:npcbl ) )
5912           ALLOCATE( pcbinswdif( 1:npcbl ) )
5913           ALLOCATE( pcbinlw( 1:npcbl ) )
5914       ENDIF
5915
5916!--    fill surfl (the ordering of local surfaces given by the following
5917!--    cycles must not be altered, certain file input routines may depend
5918!--    on it)
5919       ALLOCATE(surfl_l(5*nsurfl))  ! is it necessary to allocate it with (5,nsurfl)?
5920       surfl(1:5,1:nsurfl) => surfl_l(1:5*nsurfl)
5921       isurf = 0
5922       IF ( rad_angular_discretization )  THEN
5923!
5924!--       Allocate and fill the reverse indexing array gridsurf
5925#if defined( __parallel )
5926!
5927!--       raytrace_mpi_rma is asserted
5928
5929          CALL MPI_Info_create(minfo, ierr)
5930          IF ( ierr /= 0 ) THEN
5931              WRITE(9,*) 'Error MPI_Info_create1:', ierr
5932              FLUSH(9)
5933          ENDIF
5934          CALL MPI_Info_set(minfo, 'accumulate_ordering', '', ierr)
5935          IF ( ierr /= 0 ) THEN
5936              WRITE(9,*) 'Error MPI_Info_set1:', ierr
5937              FLUSH(9)
5938          ENDIF
5939          CALL MPI_Info_set(minfo, 'accumulate_ops', 'same_op', ierr)
5940          IF ( ierr /= 0 ) THEN
5941              WRITE(9,*) 'Error MPI_Info_set2:', ierr
5942              FLUSH(9)
5943          ENDIF
5944          CALL MPI_Info_set(minfo, 'same_size', 'true', ierr)
5945          IF ( ierr /= 0 ) THEN
5946              WRITE(9,*) 'Error MPI_Info_set3:', ierr
5947              FLUSH(9)
5948          ENDIF
5949          CALL MPI_Info_set(minfo, 'same_disp_unit', 'true', ierr)
5950          IF ( ierr /= 0 ) THEN
5951              WRITE(9,*) 'Error MPI_Info_set4:', ierr
5952              FLUSH(9)
5953          ENDIF
5954
5955          CALL MPI_Win_allocate(INT(STORAGE_SIZE(1_iwp)/8*nsurf_type_u*nzu*nny*nnx, &
5956                                    kind=MPI_ADDRESS_KIND), STORAGE_SIZE(1_iwp)/8,  &
5957                                minfo, comm2d, gridsurf_rma_p, win_gridsurf, ierr)
5958          IF ( ierr /= 0 ) THEN
5959              WRITE(9,*) 'Error MPI_Win_allocate1:', ierr, &
5960                 INT(STORAGE_SIZE(1_iwp)/8*nsurf_type_u*nzu*nny*nnx,kind=MPI_ADDRESS_KIND), &
5961                 STORAGE_SIZE(1_iwp)/8, win_gridsurf
5962              FLUSH(9)
5963          ENDIF
5964
5965          CALL MPI_Info_free(minfo, ierr)
5966          IF ( ierr /= 0 ) THEN
5967              WRITE(9,*) 'Error MPI_Info_free1:', ierr
5968              FLUSH(9)
5969          ENDIF
5970
5971!
5972!--       On Intel compilers, calling c_f_pointer to transform a C pointer
5973!--       directly to a multi-dimensional Fotran pointer leads to strange
5974!--       errors on dimension boundaries. However, transforming to a 1D
5975!--       pointer and then redirecting a multidimensional pointer to it works
5976!--       fine.
5977          CALL c_f_pointer(gridsurf_rma_p, gridsurf_rma, (/ nsurf_type_u*nzu*nny*nnx /))
5978          gridsurf(0:nsurf_type_u-1, nzub:nzut, nys:nyn, nxl:nxr) =>                &
5979                     gridsurf_rma(1:nsurf_type_u*nzu*nny*nnx)
5980#else
5981          ALLOCATE(gridsurf(0:nsurf_type_u-1,nzub:nzut,nys:nyn,nxl:nxr) )
5982#endif
5983          gridsurf(:,:,:,:) = -999
5984       ENDIF
5985
5986!--    add horizontal surface elements (land and urban surfaces)
5987!--    TODO: add urban overhanging surfaces (idown_u)
5988       DO i = nxl, nxr
5989           DO j = nys, nyn
5990              DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
5991                 k = surf_usm_h%k(m)
5992                 isurf = isurf + 1
5993                 surfl(:,isurf) = (/iup_u,k,j,i,m/)
5994                 IF ( rad_angular_discretization ) THEN
5995                    gridsurf(iup_u,k,j,i) = isurf
5996                 ENDIF
5997              ENDDO
5998
5999              DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6000                 k = surf_lsm_h%k(m)
6001                 isurf = isurf + 1
6002                 surfl(:,isurf) = (/iup_l,k,j,i,m/)
6003                 IF ( rad_angular_discretization ) THEN
6004                    gridsurf(iup_u,k,j,i) = isurf
6005                 ENDIF
6006              ENDDO
6007
6008           ENDDO
6009       ENDDO
6010
6011!--    add vertical surface elements (land and urban surfaces)
6012!--    TODO: remove the hard coding of l = 0 to l = idirection
6013       DO i = nxl, nxr
6014           DO j = nys, nyn
6015              l = 0
6016              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6017                 k = surf_usm_v(l)%k(m)
6018                 isurf = isurf + 1
6019                 surfl(:,isurf) = (/inorth_u,k,j,i,m/)
6020                 IF ( rad_angular_discretization ) THEN
6021                    gridsurf(inorth_u,k,j,i) = isurf
6022                 ENDIF
6023              ENDDO
6024              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6025                 k = surf_lsm_v(l)%k(m)
6026                 isurf = isurf + 1
6027                 surfl(:,isurf) = (/inorth_l,k,j,i,m/)
6028                 IF ( rad_angular_discretization ) THEN
6029                    gridsurf(inorth_u,k,j,i) = isurf
6030                 ENDIF
6031              ENDDO
6032
6033              l = 1
6034              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6035                 k = surf_usm_v(l)%k(m)
6036                 isurf = isurf + 1
6037                 surfl(:,isurf) = (/isouth_u,k,j,i,m/)
6038                 IF ( rad_angular_discretization ) THEN
6039                    gridsurf(isouth_u,k,j,i) = isurf
6040                 ENDIF
6041              ENDDO
6042              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6043                 k = surf_lsm_v(l)%k(m)
6044                 isurf = isurf + 1
6045                 surfl(:,isurf) = (/isouth_l,k,j,i,m/)
6046                 IF ( rad_angular_discretization ) THEN
6047                    gridsurf(isouth_u,k,j,i) = isurf
6048                 ENDIF
6049              ENDDO
6050
6051              l = 2
6052              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6053                 k = surf_usm_v(l)%k(m)
6054                 isurf = isurf + 1
6055                 surfl(:,isurf) = (/ieast_u,k,j,i,m/)
6056                 IF ( rad_angular_discretization ) THEN
6057                    gridsurf(ieast_u,k,j,i) = isurf
6058                 ENDIF
6059              ENDDO
6060              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6061                 k = surf_lsm_v(l)%k(m)
6062                 isurf = isurf + 1
6063                 surfl(:,isurf) = (/ieast_l,k,j,i,m/)
6064                 IF ( rad_angular_discretization ) THEN
6065                    gridsurf(ieast_u,k,j,i) = isurf
6066                 ENDIF
6067              ENDDO
6068
6069              l = 3
6070              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6071                 k = surf_usm_v(l)%k(m)
6072                 isurf = isurf + 1
6073                 surfl(:,isurf) = (/iwest_u,k,j,i,m/)
6074                 IF ( rad_angular_discretization ) THEN
6075                    gridsurf(iwest_u,k,j,i) = isurf
6076                 ENDIF
6077              ENDDO
6078              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6079                 k = surf_lsm_v(l)%k(m)
6080                 isurf = isurf + 1
6081                 surfl(:,isurf) = (/iwest_l,k,j,i,m/)
6082                 IF ( rad_angular_discretization ) THEN
6083                    gridsurf(iwest_u,k,j,i) = isurf
6084                 ENDIF
6085              ENDDO
6086           ENDDO
6087       ENDDO
6088!
6089!--    Add local MRT boxes for specified number of levels
6090       nmrtbl = 0
6091       IF ( mrt_nlevels > 0 )  THEN
6092          DO  i = nxl, nxr
6093             DO  j = nys, nyn
6094                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
6095!
6096!--                Skip roof if requested
6097                   IF ( mrt_skip_roof  .AND.  surf_usm_h%isroof_surf(m) )  CYCLE
6098!
6099!--                Cycle over specified no of levels
6100                   nmrtbl = nmrtbl + mrt_nlevels
6101                ENDDO
6102!
6103!--             Dtto for LSM
6104                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6105                   nmrtbl = nmrtbl + mrt_nlevels
6106                ENDDO
6107             ENDDO
6108          ENDDO
6109
6110          ALLOCATE( mrtbl(iz:ix,nmrtbl), mrtsky(nmrtbl), mrtskyt(nmrtbl), &
6111                    mrtinsw(nmrtbl), mrtinlw(nmrtbl), mrt(nmrtbl) )
6112
6113          imrt = 0
6114          DO  i = nxl, nxr
6115             DO  j = nys, nyn
6116                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
6117!
6118!--                Skip roof if requested
6119                   IF ( mrt_skip_roof  .AND.  surf_usm_h%isroof_surf(m) )  CYCLE
6120!
6121!--                Cycle over specified no of levels
6122                   l = surf_usm_h%k(m)
6123                   DO  k = l, l + mrt_nlevels - 1
6124                      imrt = imrt + 1
6125                      mrtbl(:,imrt) = (/k,j,i/)
6126                   ENDDO
6127                ENDDO
6128!
6129!--             Dtto for LSM
6130                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6131                   l = surf_lsm_h%k(m)
6132                   DO  k = l, l + mrt_nlevels - 1
6133                      imrt = imrt + 1
6134                      mrtbl(:,imrt) = (/k,j,i/)
6135                   ENDDO
6136                ENDDO
6137             ENDDO
6138          ENDDO
6139       ENDIF
6140
6141!
6142!--    broadband albedo of the land, roof and wall surface
6143!--    for domain border and sky set artifically to 1.0
6144!--    what allows us to calculate heat flux leaving over
6145!--    side and top borders of the domain
6146       ALLOCATE ( albedo_surf(nsurfl) )
6147       albedo_surf = 1.0_wp
6148!
6149!--    Also allocate further array for emissivity with identical order of
6150!--    surface elements as radiation arrays.
6151       ALLOCATE ( emiss_surf(nsurfl)  )
6152
6153
6154!
6155!--    global array surf of indices of surfaces and displacement index array surfstart
6156       ALLOCATE(nsurfs(0:numprocs-1))
6157
6158#if defined( __parallel )
6159       CALL MPI_Allgather(nsurfl,1,MPI_INTEGER,nsurfs,1,MPI_INTEGER,comm2d,ierr)
6160       IF ( ierr /= 0 ) THEN
6161         WRITE(9,*) 'Error MPI_AllGather1:', ierr, nsurfl, nsurfs
6162         FLUSH(9)
6163     ENDIF
6164
6165#else
6166       nsurfs(0) = nsurfl
6167#endif
6168       ALLOCATE(surfstart(0:numprocs))
6169       k = 0
6170       DO i=0,numprocs-1
6171           surfstart(i) = k
6172           k = k+nsurfs(i)
6173       ENDDO
6174       surfstart(numprocs) = k
6175       nsurf = k
6176       ALLOCATE(surf_l(5*nsurf))
6177       surf(1:5,1:nsurf) => surf_l(1:5*nsurf)
6178
6179#if defined( __parallel )
6180       CALL MPI_AllGatherv(surfl_l, nsurfl*5, MPI_INTEGER, surf_l, nsurfs*5, &
6181           surfstart(0:numprocs-1)*5, MPI_INTEGER, comm2d, ierr)
6182       IF ( ierr /= 0 ) THEN
6183           WRITE(9,*) 'Error MPI_AllGatherv4:', ierr, SIZE(surfl_l), nsurfl*5, &
6184                      SIZE(surf_l), nsurfs*5, surfstart(0:numprocs-1)*5
6185           FLUSH(9)
6186       ENDIF
6187#else
6188       surf = surfl
6189#endif
6190
6191!--
6192!--    allocation of the arrays for direct and diffusion radiation
6193       CALL location_message( '    allocation of radiation arrays', .TRUE. )
6194!--    rad_sw_in, rad_lw_in are computed in radiation model,
6195!--    splitting of direct and diffusion part is done
6196!--    in calc_diffusion_radiation for now
6197
6198       ALLOCATE( rad_sw_in_dir(nysg:nyng,nxlg:nxrg) )
6199       ALLOCATE( rad_sw_in_diff(nysg:nyng,nxlg:nxrg) )
6200       ALLOCATE( rad_lw_in_diff(nysg:nyng,nxlg:nxrg) )
6201       rad_sw_in_dir  = 0.0_wp
6202       rad_sw_in_diff = 0.0_wp
6203       rad_lw_in_diff = 0.0_wp
6204
6205!--    allocate radiation arrays
6206       ALLOCATE( surfins(nsurfl) )
6207       ALLOCATE( surfinl(nsurfl) )
6208       ALLOCATE( surfinsw(nsurfl) )
6209       ALLOCATE( surfinlw(nsurfl) )
6210       ALLOCATE( surfinswdir(nsurfl) )
6211       ALLOCATE( surfinswdif(nsurfl) )
6212       ALLOCATE( surfinlwdif(nsurfl) )
6213       ALLOCATE( surfoutsl(nsurfl) )
6214       ALLOCATE( surfoutll(nsurfl) )
6215       ALLOCATE( surfoutsw(nsurfl) )
6216       ALLOCATE( surfoutlw(nsurfl) )
6217       ALLOCATE( surfouts(nsurf) )
6218       ALLOCATE( surfoutl(nsurf) )
6219       ALLOCATE( surfinlg(nsurf) )
6220       ALLOCATE( skyvf(nsurfl) )
6221       ALLOCATE( skyvft(nsurfl) )
6222       ALLOCATE( surfemitlwl(nsurfl) )
6223
6224!
6225!--    In case of average_radiation, aggregated surface albedo and emissivity,
6226!--    also set initial value for t_rad_urb.
6227!--    For now set an arbitrary initial value.
6228       IF ( average_radiation )  THEN
6229          albedo_urb = 0.1_wp
6230          emissivity_urb = 0.9_wp
6231          t_rad_urb = pt_surface
6232       ENDIF
6233
6234    END SUBROUTINE radiation_interaction_init
6235
6236!------------------------------------------------------------------------------!
6237! Description:
6238! ------------
6239!> Calculates shape view factors (SVF), plant sink canopy factors (PCSF),
6240!> sky-view factors, discretized path for direct solar radiation, MRT factors
6241!> and other preprocessed data needed for radiation_interaction.
6242!------------------------------------------------------------------------------!
6243    SUBROUTINE radiation_calc_svf
6244   
6245        IMPLICIT NONE
6246       
6247        INTEGER(iwp)                                  :: i, j, k, d, ip, jp
6248        INTEGER(iwp)                                  :: isvf, ksvf, icsf, kcsf, npcsfl, isvf_surflt, imrt, imrtf, ipcgb
6249        INTEGER(iwp)                                  :: sd, td
6250        INTEGER(iwp)                                  :: iaz, izn      !< azimuth, zenith counters
6251        INTEGER(iwp)                                  :: naz, nzn      !< azimuth, zenith num of steps
6252        REAL(wp)                                      :: az0, zn0      !< starting azimuth/zenith
6253        REAL(wp)                                      :: azs, zns      !< azimuth/zenith cycle step
6254        REAL(wp)                                      :: az1, az2      !< relative azimuth of section borders
6255        REAL(wp)                                      :: azmid         !< ray (center) azimuth
6256        REAL(wp)                                      :: yxlen         !< |yxdir|
6257        REAL(wp), DIMENSION(2)                        :: yxdir         !< y,x *unit* vector of ray direction (in grid units)
6258        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zdirs         !< directions in z (tangent of elevation)
6259        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zcent         !< zenith angle centers
6260        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zbdry         !< zenith angle boundaries
6261        REAL(wp), DIMENSION(:), ALLOCATABLE           :: vffrac        !< view factor fractions for individual rays
6262        REAL(wp), DIMENSION(:), ALLOCATABLE           :: vffrac0       !< dtto (original values)
6263        REAL(wp), DIMENSION(:), ALLOCATABLE           :: ztransp       !< array of transparency in z steps
6264        INTEGER(iwp)                                  :: lowest_free_ray !< index into zdirs
6265        INTEGER(iwp), DIMENSION(:), ALLOCATABLE       :: itarget       !< face indices of detected obstacles
6266        INTEGER(iwp)                                  :: itarg0, itarg1
6267
6268        INTEGER(iwp)                                  :: udim
6269        INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET:: nzterrl_l
6270        INTEGER(iwp), DIMENSION(:,:), POINTER         :: nzterrl
6271        REAL(wp),     DIMENSION(:), ALLOCATABLE,TARGET:: csflt_l, pcsflt_l
6272        REAL(wp),     DIMENSION(:,:), POINTER         :: csflt, pcsflt
6273        INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET:: kcsflt_l,kpcsflt_l
6274        INTEGER(iwp), DIMENSION(:,:), POINTER         :: kcsflt,kpcsflt
6275        INTEGER(iwp), DIMENSION(:), ALLOCATABLE       :: icsflt,dcsflt,ipcsflt,dpcsflt
6276        REAL(wp), DIMENSION(3)                        :: uv
6277        LOGICAL                                       :: visible
6278        REAL(wp), DIMENSION(3)                        :: sa, ta          !< real coordinates z,y,x of source and target
6279        REAL(wp)                                      :: difvf           !< differential view factor
6280        REAL(wp)                                      :: transparency, rirrf, sqdist, svfsum
6281        INTEGER(iwp)                                  :: isurflt, isurfs, isurflt_prev
6282        INTEGER(idp)                                  :: ray_skip_maxdist, ray_skip_minval !< skipped raytracing counts
6283        INTEGER(iwp)                                  :: max_track_len !< maximum 2d track length
6284        INTEGER(iwp)                                  :: minfo
6285        REAL(wp), DIMENSION(:), POINTER               :: lad_s_rma       !< fortran 1D pointer
6286        TYPE(c_ptr)                                   :: lad_s_rma_p     !< allocated c pointer
6287#if defined( __parallel )
6288        INTEGER(kind=MPI_ADDRESS_KIND)                :: size_lad_rma
6289#endif
6290!   
6291        INTEGER(iwp), DIMENSION(0:svfnorm_report_num) :: svfnorm_counts
6292        CHARACTER(200)                                :: msg
6293
6294!--     calculation of the SVF
6295        CALL location_message( '    calculation of SVF and CSF', .TRUE. )
6296        CALL radiation_write_debug_log('Start calculation of SVF and CSF')
6297
6298!--     initialize variables and temporary arrays for calculation of svf and csf
6299        nsvfl  = 0
6300        ncsfl  = 0
6301        nsvfla = gasize
6302        msvf   = 1
6303        ALLOCATE( asvf1(nsvfla) )
6304        asvf => asvf1
6305        IF ( plant_canopy )  THEN
6306            ncsfla = gasize
6307            mcsf   = 1
6308            ALLOCATE( acsf1(ncsfla) )
6309            acsf => acsf1
6310        ENDIF
6311        nmrtf = 0
6312        IF ( mrt_nlevels > 0 )  THEN
6313           nmrtfa = gasize
6314           mmrtf = 1
6315           ALLOCATE ( amrtf1(nmrtfa) )
6316           amrtf => amrtf1
6317        ENDIF
6318        ray_skip_maxdist = 0
6319        ray_skip_minval = 0
6320       
6321!--     initialize temporary terrain and plant canopy height arrays (global 2D array!)
6322        ALLOCATE( nzterr(0:(nx+1)*(ny+1)-1) )
6323#if defined( __parallel )
6324        !ALLOCATE( nzterrl(nys:nyn,nxl:nxr) )
6325        ALLOCATE( nzterrl_l((nyn-nys+1)*(nxr-nxl+1)) )
6326        nzterrl(nys:nyn,nxl:nxr) => nzterrl_l(1:(nyn-nys+1)*(nxr-nxl+1))
6327        nzterrl = get_topography_top_index( 's' )
6328        CALL MPI_AllGather( nzterrl_l, nnx*nny, MPI_INTEGER, &
6329                            nzterr, nnx*nny, MPI_INTEGER, comm2d, ierr )
6330        IF ( ierr /= 0 ) THEN
6331            WRITE(9,*) 'Error MPI_AllGather1:', ierr, SIZE(nzterrl_l), nnx*nny, &
6332                       SIZE(nzterr), nnx*nny
6333            FLUSH(9)
6334        ENDIF
6335        DEALLOCATE(nzterrl_l)
6336#else
6337        nzterr = RESHAPE( get_topography_top_index( 's' ), (/(nx+1)*(ny+1)/) )
6338#endif
6339        IF ( plant_canopy )  THEN
6340            ALLOCATE( plantt(0:(nx+1)*(ny+1)-1) )
6341            maxboxesg = nx + ny + nzp + 1
6342            max_track_len = nx + ny + 1
6343!--         temporary arrays storing values for csf calculation during raytracing
6344            ALLOCATE( boxes(3, maxboxesg) )
6345            ALLOCATE( crlens(maxboxesg) )
6346
6347#if defined( __parallel )
6348            CALL MPI_AllGather( pct, nnx*nny, MPI_INTEGER, &
6349                                plantt, nnx*nny, MPI_INTEGER, comm2d, ierr )
6350            IF ( ierr /= 0 ) THEN
6351                WRITE(9,*) 'Error MPI_AllGather2:', ierr, SIZE(pct), nnx*nny, &
6352                           SIZE(plantt), nnx*nny
6353                FLUSH(9)
6354            ENDIF
6355
6356!--         temporary arrays storing values for csf calculation during raytracing
6357            ALLOCATE( lad_ip(maxboxesg) )
6358            ALLOCATE( lad_disp(maxboxesg) )
6359
6360            IF ( raytrace_mpi_rma )  THEN
6361                ALLOCATE( lad_s_ray(maxboxesg) )
6362               
6363                ! set conditions for RMA communication
6364                CALL MPI_Info_create(minfo, ierr)
6365                IF ( ierr /= 0 ) THEN
6366                    WRITE(9,*) 'Error MPI_Info_create2:', ierr
6367                    FLUSH(9)
6368                ENDIF
6369                CALL MPI_Info_set(minfo, 'accumulate_ordering', '', ierr)
6370                IF ( ierr /= 0 ) THEN
6371                    WRITE(9,*) 'Error MPI_Info_set5:', ierr
6372                    FLUSH(9)
6373                ENDIF
6374                CALL MPI_Info_set(minfo, 'accumulate_ops', 'same_op', ierr)
6375                IF ( ierr /= 0 ) THEN
6376                    WRITE(9,*) 'Error MPI_Info_set6:', ierr
6377                    FLUSH(9)
6378                ENDIF
6379                CALL MPI_Info_set(minfo, 'same_size', 'true', ierr)
6380                IF ( ierr /= 0 ) THEN
6381                    WRITE(9,*) 'Error MPI_Info_set7:', ierr
6382                    FLUSH(9)
6383                ENDIF
6384                CALL MPI_Info_set(minfo, 'same_disp_unit', 'true', ierr)
6385                IF ( ierr /= 0 ) THEN
6386                    WRITE(9,*) 'Error MPI_Info_set8:', ierr
6387                    FLUSH(9)
6388                ENDIF
6389
6390!--             Allocate and initialize the MPI RMA window
6391!--             must be in accordance with allocation of lad_s in plant_canopy_model
6392!--             optimization of memory should be done
6393!--             Argument X of function STORAGE_SIZE(X) needs arbitrary REAL(wp) value, set to 1.0_wp for now
6394                size_lad_rma = STORAGE_SIZE(1.0_wp)/8*nnx*nny*nzp
6395                CALL MPI_Win_allocate(size_lad_rma, STORAGE_SIZE(1.0_wp)/8, minfo, comm2d, &
6396                                        lad_s_rma_p, win_lad, ierr)
6397                IF ( ierr /= 0 ) THEN
6398                    WRITE(9,*) 'Error MPI_Win_allocate2:', ierr, size_lad_rma, &
6399                                STORAGE_SIZE(1.0_wp)/8, win_lad
6400                    FLUSH(9)
6401                ENDIF
6402                CALL c_f_pointer(lad_s_rma_p, lad_s_rma, (/ nzp*nny*nnx /))
6403                sub_lad(nzub:nzpt, nys:nyn, nxl:nxr) => lad_s_rma(1:nzp*nny*nnx)
6404            ELSE
6405                ALLOCATE(sub_lad(nzub:nzpt, nys:nyn, nxl:nxr))
6406            ENDIF
6407#else
6408            plantt = RESHAPE( pct(nys:nyn,nxl:nxr), (/(nx+1)*(ny+1)/) )
6409            ALLOCATE(sub_lad(nzub:nzpt, nys:nyn, nxl:nxr))
6410#endif
6411            plantt_max = MAXVAL(plantt)
6412            ALLOCATE( rt2_track(2, max_track_len), rt2_track_lad(nzub:plantt_max, max_track_len), &
6413                      rt2_track_dist(0:max_track_len), rt2_dist(plantt_max-nzub+2) )
6414
6415            sub_lad(:,:,:) = 0._wp
6416            DO i = nxl, nxr
6417                DO j = nys, nyn
6418                    k = get_topography_top_index_ji( j, i, 's' )
6419
6420                    sub_lad(k:nzpt, j, i) = lad_s(0:nzpt-k, j, i)
6421                ENDDO
6422            ENDDO
6423
6424#if defined( __parallel )
6425            IF ( raytrace_mpi_rma )  THEN
6426                CALL MPI_Info_free(minfo, ierr)
6427                IF ( ierr /= 0 ) THEN
6428                    WRITE(9,*) 'Error MPI_Info_free2:', ierr
6429                    FLUSH(9)
6430                ENDIF
6431                CALL MPI_Win_lock_all(0, win_lad, ierr)
6432                IF ( ierr /= 0 ) THEN
6433                    WRITE(9,*) 'Error MPI_Win_lock_all1:', ierr, win_lad
6434                    FLUSH(9)
6435                ENDIF
6436               
6437            ELSE
6438                ALLOCATE( sub_lad_g(0:(nx+1)*(ny+1)*nzp-1) )
6439                CALL MPI_AllGather( sub_lad, nnx*nny*nzp, MPI_REAL, &
6440                                    sub_lad_g, nnx*nny*nzp, MPI_REAL, comm2d, ierr )
6441                IF ( ierr /= 0 ) THEN
6442                    WRITE(9,*) 'Error MPI_AllGather3:', ierr, SIZE(sub_lad), &
6443                                nnx*nny*nzp, SIZE(sub_lad_g), nnx*nny*nzp
6444                    FLUSH(9)
6445                ENDIF
6446            ENDIF
6447#endif
6448        ENDIF
6449
6450!--     prepare the MPI_Win for collecting the surface indices
6451!--     from the reverse index arrays gridsurf from processors of target surfaces
6452#if defined( __parallel )
6453        IF ( rad_angular_discretization )  THEN
6454!
6455!--         raytrace_mpi_rma is asserted
6456            CALL MPI_Win_lock_all(0, win_gridsurf, ierr)
6457            IF ( ierr /= 0 ) THEN
6458                WRITE(9,*) 'Error MPI_Win_lock_all2:', ierr, win_gridsurf
6459                FLUSH(9)
6460            ENDIF
6461        ENDIF
6462#endif
6463
6464
6465        !--Directions opposite to face normals are not even calculated,
6466        !--they must be preset to 0
6467        !--
6468        dsitrans(:,:) = 0._wp
6469       
6470        DO isurflt = 1, nsurfl
6471!--         determine face centers
6472            td = surfl(id, isurflt)
6473            ta = (/ REAL(surfl(iz, isurflt), wp) - 0.5_wp * kdir(td),  &
6474                      REAL(surfl(iy, isurflt), wp) - 0.5_wp * jdir(td),  &
6475                      REAL(surfl(ix, isurflt), wp) - 0.5_wp * idir(td)  /)
6476
6477            !--Calculate sky view factor and raytrace DSI paths
6478            skyvf(isurflt) = 0._wp
6479            skyvft(isurflt) = 0._wp
6480
6481            !--Select a proper half-sphere for 2D raytracing
6482            SELECT CASE ( td )
6483               CASE ( iup_u, iup_l )
6484                  az0 = 0._wp
6485                  naz = raytrace_discrete_azims
6486                  azs = 2._wp * pi / REAL(naz, wp)
6487                  zn0 = 0._wp
6488                  nzn = raytrace_discrete_elevs / 2
6489                  zns = pi / 2._wp / REAL(nzn, wp)
6490               CASE ( isouth_u, isouth_l )
6491                  az0 = pi / 2._wp
6492                  naz = raytrace_discrete_azims / 2
6493                  azs = pi / REAL(naz, wp)
6494                  zn0 = 0._wp
6495                  nzn = raytrace_discrete_elevs
6496                  zns = pi / REAL(nzn, wp)
6497               CASE ( inorth_u, inorth_l )
6498                  az0 = - pi / 2._wp
6499                  naz = raytrace_discrete_azims / 2
6500                  azs = pi / REAL(naz, wp)
6501                  zn0 = 0._wp
6502                  nzn = raytrace_discrete_elevs
6503                  zns = pi / REAL(nzn, wp)
6504               CASE ( iwest_u, iwest_l )
6505                  az0 = pi
6506                  naz = raytrace_discrete_azims / 2
6507                  azs = pi / REAL(naz, wp)
6508                  zn0 = 0._wp
6509                  nzn = raytrace_discrete_elevs
6510                  zns = pi / REAL(nzn, wp)
6511               CASE ( ieast_u, ieast_l )
6512                  az0 = 0._wp
6513                  naz = raytrace_discrete_azims / 2
6514                  azs = pi / REAL(naz, wp)
6515                  zn0 = 0._wp
6516                  nzn = raytrace_discrete_elevs
6517                  zns = pi / REAL(nzn, wp)
6518               CASE DEFAULT
6519                  WRITE(message_string, *) 'ERROR: the surface type ', td,     &
6520                                           ' is not supported for calculating',&
6521                                           ' SVF'
6522                  CALL message( 'radiation_calc_svf', 'PA0488', 1, 2, 0, 6, 0 )
6523            END SELECT
6524
6525            ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), zbdry(0:nzn), vffrac(1:nzn*naz), &
6526                       ztransp(1:nzn*naz), itarget(1:nzn*naz) )   !FIXME allocate itarget only
6527                                                                  !in case of rad_angular_discretization
6528
6529            itarg0 = 1
6530            itarg1 = nzn
6531            zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
6532            zbdry(:) = (/( zn0+REAL(izn,wp)*zns, izn=0, nzn )/)
6533            IF ( td == iup_u  .OR.  td == iup_l )  THEN
6534               vffrac(1:nzn) = (COS(2 * zbdry(0:nzn-1)) - COS(2 * zbdry(1:nzn))) / 2._wp / REAL(naz, wp)
6535!
6536!--            For horizontal target, vf fractions are constant per azimuth
6537               DO iaz = 1, naz-1
6538                  vffrac(iaz*nzn+1:(iaz+1)*nzn) = vffrac(1:nzn)
6539               ENDDO
6540!--            sum of whole vffrac equals 1, verified
6541            ENDIF
6542!
6543!--         Calculate sky-view factor and direct solar visibility using 2D raytracing
6544            DO iaz = 1, naz
6545               azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
6546               IF ( td /= iup_u  .AND.  td /= iup_l )  THEN
6547                  az2 = REAL(iaz, wp) * azs - pi/2._wp
6548                  az1 = az2 - azs
6549                  !TODO precalculate after 1st line
6550                  vffrac(itarg0:itarg1) = (SIN(az2) - SIN(az1))               &
6551                              * (zbdry(1:nzn) - zbdry(0:nzn-1)                &
6552                                 + SIN(zbdry(0:nzn-1))*COS(zbdry(0:nzn-1))    &
6553                                 - SIN(zbdry(1:nzn))*COS(zbdry(1:nzn)))       &
6554                              / (2._wp * pi)
6555!--               sum of whole vffrac equals 1, verified
6556               ENDIF
6557               yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
6558               yxlen = SQRT(SUM(yxdir(:)**2))
6559               zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
6560               yxdir(:) = yxdir(:) / yxlen
6561
6562               CALL raytrace_2d(ta, yxdir, nzn, zdirs,                        &
6563                                    surfstart(myid) + isurflt, facearea(td),  &
6564                                    vffrac(itarg0:itarg1), .TRUE., .TRUE.,    &
6565                                    .FALSE., lowest_free_ray,                 &
6566                                    ztransp(itarg0:itarg1),                   &
6567                                    itarget(itarg0:itarg1))
6568
6569               skyvf(isurflt) = skyvf(isurflt) + &
6570                                SUM(vffrac(itarg0:itarg0+lowest_free_ray-1))
6571               skyvft(isurflt) = skyvft(isurflt) + &
6572                                 SUM(ztransp(itarg0:itarg0+lowest_free_ray-1) &
6573                                             * vffrac(itarg0:itarg0+lowest_free_ray-1))
6574 
6575!--            Save direct solar transparency
6576               j = MODULO(NINT(azmid/                                          &
6577                               (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
6578                          raytrace_discrete_azims)
6579
6580               DO k = 1, raytrace_discrete_elevs/2
6581                  i = dsidir_rev(k-1, j)
6582                  IF ( i /= -1  .AND.  k <= lowest_free_ray )  &
6583                     dsitrans(isurflt, i) = ztransp(itarg0+k-1)
6584               ENDDO
6585
6586!
6587!--            Advance itarget indices
6588               itarg0 = itarg1 + 1
6589               itarg1 = itarg1 + nzn
6590            ENDDO
6591
6592            IF ( rad_angular_discretization )  THEN
6593!--            sort itarget by face id
6594               CALL quicksort_itarget(itarget,vffrac,ztransp,1,nzn*naz)
6595!
6596!--            find the first valid position
6597               itarg0 = 1
6598               DO WHILE ( itarg0 <= nzn*naz )
6599                  IF ( itarget(itarg0) /= -1 )  EXIT
6600                  itarg0 = itarg0 + 1
6601               ENDDO
6602
6603               DO  i = itarg0, nzn*naz
6604!
6605!--               For duplicate values, only sum up vf fraction value
6606                  IF ( i < nzn*naz )  THEN
6607                     IF ( itarget(i+1) == itarget(i) )  THEN
6608                        vffrac(i+1) = vffrac(i+1) + vffrac(i)
6609                        CYCLE
6610                     ENDIF
6611                  ENDIF
6612!
6613!--               write to the svf array
6614                  nsvfl = nsvfl + 1
6615!--               check dimmension of asvf array and enlarge it if needed
6616                  IF ( nsvfla < nsvfl )  THEN
6617                     k = CEILING(REAL(nsvfla, kind=wp) * grow_factor)
6618                     IF ( msvf == 0 )  THEN
6619                        msvf = 1
6620                        ALLOCATE( asvf1(k) )
6621                        asvf => asvf1
6622                        asvf1(1:nsvfla) = asvf2
6623                        DEALLOCATE( asvf2 )
6624                     ELSE
6625                        msvf = 0
6626                        ALLOCATE( asvf2(k) )
6627                        asvf => asvf2
6628                        asvf2(1:nsvfla) = asvf1
6629                        DEALLOCATE( asvf1 )
6630                     ENDIF
6631
6632                     WRITE (msg,'(A,3I12)') 'Grow asvf:',nsvfl,nsvfla,k
6633                     CALL radiation_write_debug_log( msg )
6634                     
6635                     nsvfla = k
6636                  ENDIF
6637!--               write svf values into the array
6638                  asvf(nsvfl)%isurflt = isurflt
6639                  asvf(nsvfl)%isurfs = itarget(i)
6640                  asvf(nsvfl)%rsvf = vffrac(i)
6641                  asvf(nsvfl)%rtransp = ztransp(i)
6642               END DO
6643
6644            ENDIF ! rad_angular_discretization
6645
6646            DEALLOCATE ( zdirs, zcent, zbdry, vffrac, ztransp, itarget ) !FIXME itarget shall be allocated only
6647                                                                  !in case of rad_angular_discretization
6648!
6649!--         Following calculations only required for surface_reflections
6650            IF ( surface_reflections  .AND.  .NOT. rad_angular_discretization )  THEN
6651
6652               DO  isurfs = 1, nsurf
6653                  IF ( .NOT.  surface_facing(surfl(ix, isurflt), surfl(iy, isurflt), &
6654                     surfl(iz, isurflt), surfl(id, isurflt), &
6655                     surf(ix, isurfs), surf(iy, isurfs), &
6656                     surf(iz, isurfs), surf(id, isurfs)) )  THEN
6657                     CYCLE
6658                  ENDIF
6659                 
6660                  sd = surf(id, isurfs)
6661                  sa = (/ REAL(surf(iz, isurfs), wp) - 0.5_wp * kdir(sd),  &
6662                          REAL(surf(iy, isurfs), wp) - 0.5_wp * jdir(sd),  &
6663                          REAL(surf(ix, isurfs), wp) - 0.5_wp * idir(sd)  /)
6664
6665!--               unit vector source -> target
6666                  uv = (/ (ta(1)-sa(1))*dz(1), (ta(2)-sa(2))*dy, (ta(3)-sa(3))*dx /)
6667                  sqdist = SUM(uv(:)**2)
6668                  uv = uv / SQRT(sqdist)
6669
6670!--               reject raytracing above max distance
6671                  IF ( SQRT(sqdist) > max_raytracing_dist ) THEN
6672                     ray_skip_maxdist = ray_skip_maxdist + 1
6673                     CYCLE
6674                  ENDIF
6675                 
6676                  difvf = dot_product((/ kdir(sd), jdir(sd), idir(sd) /), uv) & ! cosine of source normal and direction
6677                      * dot_product((/ kdir(td), jdir(td), idir(td) /), -uv) &  ! cosine of target normal and reverse direction
6678                      / (pi * sqdist) ! square of distance between centers
6679!
6680!--               irradiance factor (our unshaded shape view factor) = view factor per differential target area * source area
6681                  rirrf = difvf * facearea(sd)
6682
6683!--               reject raytracing for potentially too small view factor values
6684                  IF ( rirrf < min_irrf_value ) THEN
6685                      ray_skip_minval = ray_skip_minval + 1
6686                      CYCLE
6687                  ENDIF
6688
6689!--               raytrace + process plant canopy sinks within
6690                  CALL raytrace(sa, ta, isurfs, difvf, facearea(td), .TRUE., &
6691                                visible, transparency)
6692
6693                  IF ( .NOT.  visible ) CYCLE
6694                 ! rsvf = rirrf * transparency
6695
6696!--               write to the svf array
6697                  nsvfl = nsvfl + 1
6698!--               check dimmension of asvf array and enlarge it if needed
6699                  IF ( nsvfla < nsvfl )  THEN
6700                     k = CEILING(REAL(nsvfla, kind=wp) * grow_factor)
6701                     IF ( msvf == 0 )  THEN
6702                        msvf = 1
6703                        ALLOCATE( asvf1(k) )
6704                        asvf => asvf1
6705                        asvf1(1:nsvfla) = asvf2
6706                        DEALLOCATE( asvf2 )
6707                     ELSE
6708                        msvf = 0
6709                        ALLOCATE( asvf2(k) )
6710                        asvf => asvf2
6711                        asvf2(1:nsvfla) = asvf1
6712                        DEALLOCATE( asvf1 )
6713                     ENDIF
6714
6715                     WRITE(msg,'(A,3I12)') 'Grow asvf:',nsvfl,nsvfla,k
6716                     CALL radiation_write_debug_log( msg )
6717                     
6718                     nsvfla = k
6719                  ENDIF
6720!--               write svf values into the array
6721                  asvf(nsvfl)%isurflt = isurflt
6722                  asvf(nsvfl)%isurfs = isurfs
6723                  asvf(nsvfl)%rsvf = rirrf !we postopne multiplication by transparency
6724                  asvf(nsvfl)%rtransp = transparency !a.k.a. Direct Irradiance Factor
6725               ENDDO
6726            ENDIF
6727        ENDDO
6728
6729!--
6730!--     Raytrace to canopy boxes to fill dsitransc TODO optimize
6731        dsitransc(:,:) = 0._wp
6732        az0 = 0._wp
6733        naz = raytrace_discrete_azims
6734        azs = 2._wp * pi / REAL(naz, wp)
6735        zn0 = 0._wp
6736        nzn = raytrace_discrete_elevs / 2
6737        zns = pi / 2._wp / REAL(nzn, wp)
6738        ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), vffrac(1:nzn), ztransp(1:nzn), &
6739               itarget(1:nzn) )
6740        zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
6741        vffrac(:) = 0._wp
6742
6743        DO  ipcgb = 1, npcbl
6744           ta = (/ REAL(pcbl(iz, ipcgb), wp),  &
6745                   REAL(pcbl(iy, ipcgb), wp),  &
6746                   REAL(pcbl(ix, ipcgb), wp) /)
6747!--        Calculate direct solar visibility using 2D raytracing
6748           DO  iaz = 1, naz
6749              azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
6750              yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
6751              yxlen = SQRT(SUM(yxdir(:)**2))
6752              zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
6753              yxdir(:) = yxdir(:) / yxlen
6754              CALL raytrace_2d(ta, yxdir, nzn, zdirs,                                &
6755                                   -999, -999._wp, vffrac, .FALSE., .FALSE., .TRUE., &
6756                                   lowest_free_ray, ztransp, itarget)
6757
6758!--           Save direct solar transparency
6759              j = MODULO(NINT(azmid/                                         &
6760                             (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
6761                         raytrace_discrete_azims)
6762              DO  k = 1, raytrace_discrete_elevs/2
6763                 i = dsidir_rev(k-1, j)
6764                 IF ( i /= -1  .AND.  k <= lowest_free_ray ) &
6765                    dsitransc(ipcgb, i) = ztransp(k)
6766              ENDDO
6767           ENDDO
6768        ENDDO
6769        DEALLOCATE ( zdirs, zcent, vffrac, ztransp, itarget )
6770!--
6771!--     Raytrace to MRT boxes
6772        IF ( nmrtbl > 0 )  THEN
6773           mrtdsit(:,:) = 0._wp
6774           mrtsky(:) = 0._wp
6775           mrtskyt(:) = 0._wp
6776           az0 = 0._wp
6777           naz = raytrace_discrete_azims
6778           azs = 2._wp * pi / REAL(naz, wp)
6779           zn0 = 0._wp
6780           nzn = raytrace_discrete_elevs
6781           zns = pi / REAL(nzn, wp)
6782           ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), zbdry(0:nzn), vffrac(1:nzn*naz), vffrac0(1:nzn), &
6783                      ztransp(1:nzn*naz), itarget(1:nzn*naz) )   !FIXME allocate itarget only
6784                                                                 !in case of rad_angular_discretization
6785
6786           zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
6787           zbdry(:) = (/( zn0+REAL(izn,wp)*zns, izn=0, nzn )/)
6788           vffrac0(:) = (COS(zbdry(0:nzn-1)) - COS(zbdry(1:nzn))) / 2._wp / REAL(naz, wp)
6789           !
6790           !--Modify direction weights to simulate human body (lower weight for top-down)
6791           IF ( mrt_geom_human )  THEN
6792              vffrac0(:) = vffrac0(:) * MAX(0._wp, SIN(zcent(:))*0.88_wp + COS(zcent(:))*0.12_wp)
6793              vffrac0(:) = vffrac0(:) / (SUM(vffrac0) * REAL(naz, wp))
6794           ENDIF
6795
6796           DO  imrt = 1, nmrtbl
6797              ta = (/ REAL(mrtbl(iz, imrt), wp),  &
6798                      REAL(mrtbl(iy, imrt), wp),  &
6799                      REAL(mrtbl(ix, imrt), wp) /)
6800!
6801!--           vf fractions are constant per azimuth
6802              DO iaz = 0, naz-1
6803                 vffrac(iaz*nzn+1:(iaz+1)*nzn) = vffrac0(:)
6804              ENDDO
6805!--           sum of whole vffrac equals 1, verified
6806              itarg0 = 1
6807              itarg1 = nzn
6808!
6809!--           Calculate sky-view factor and direct solar visibility using 2D raytracing
6810              DO  iaz = 1, naz
6811                 azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
6812                 yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
6813                 yxlen = SQRT(SUM(yxdir(:)**2))
6814                 zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
6815                 yxdir(:) = yxdir(:) / yxlen
6816
6817                 CALL raytrace_2d(ta, yxdir, nzn, zdirs,                         &
6818                                  -999, -999._wp, vffrac(itarg0:itarg1), .TRUE., &
6819                                  .FALSE., .TRUE., lowest_free_ray,              &
6820                                  ztransp(itarg0:itarg1),                        &
6821                                  itarget(itarg0:itarg1))
6822
6823!--              Sky view factors for MRT
6824                 mrtsky(imrt) = mrtsky(imrt) + &
6825                                  SUM(vffrac(itarg0:itarg0+lowest_free_ray-1))
6826                 mrtskyt(imrt) = mrtskyt(imrt) + &
6827                                   SUM(ztransp(itarg0:itarg0+lowest_free_ray-1) &
6828                                               * vffrac(itarg0:itarg0+lowest_free_ray-1))
6829!--              Direct solar transparency for MRT
6830                 j = MODULO(NINT(azmid/                                         &
6831                                (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
6832                            raytrace_discrete_azims)
6833                 DO  k = 1, raytrace_discrete_elevs/2
6834                    i = dsidir_rev(k-1, j)
6835                    IF ( i /= -1  .AND.  k <= lowest_free_ray ) &
6836                       mrtdsit(imrt, i) = ztransp(itarg0+k-1)
6837                 ENDDO
6838!
6839!--              Advance itarget indices
6840                 itarg0 = itarg1 + 1
6841                 itarg1 = itarg1 + nzn
6842              ENDDO
6843
6844!--           sort itarget by face id
6845              CALL quicksort_itarget(itarget,vffrac,ztransp,1,nzn*naz)
6846!
6847!--           find the first valid position
6848              itarg0 = 1
6849              DO WHILE ( itarg0 <= nzn*naz )
6850                 IF ( itarget(itarg0) /= -1 )  EXIT
6851                 itarg0 = itarg0 + 1
6852              ENDDO
6853
6854              DO  i = itarg0, nzn*naz
6855!
6856!--              For duplicate values, only sum up vf fraction value
6857                 IF ( i < nzn*naz )  THEN
6858                    IF ( itarget(i+1) == itarget(i) )  THEN
6859                       vffrac(i+1) = vffrac(i+1) + vffrac(i)
6860                       CYCLE
6861                    ENDIF
6862                 ENDIF
6863!
6864!--              write to the mrtf array
6865                 nmrtf = nmrtf + 1
6866!--              check dimmension of mrtf array and enlarge it if needed
6867                 IF ( nmrtfa < nmrtf )  THEN
6868                    k = CEILING(REAL(nmrtfa, kind=wp) * grow_factor)
6869                    IF ( mmrtf == 0 )  THEN
6870                       mmrtf = 1
6871                       ALLOCATE( amrtf1(k) )
6872                       amrtf => amrtf1
6873                       amrtf1(1:nmrtfa) = amrtf2
6874                       DEALLOCATE( amrtf2 )
6875                    ELSE
6876                       mmrtf = 0
6877                       ALLOCATE( amrtf2(k) )
6878                       amrtf => amrtf2
6879                       amrtf2(1:nmrtfa) = amrtf1
6880                       DEALLOCATE( amrtf1 )
6881                    ENDIF
6882
6883                    WRITE (msg,'(A,3I12)') 'Grow amrtf:', nmrtf, nmrtfa, k
6884                    CALL radiation_write_debug_log( msg )
6885
6886                    nmrtfa = k
6887                 ENDIF
6888!--              write mrtf values into the array
6889                 amrtf(nmrtf)%isurflt = imrt
6890                 amrtf(nmrtf)%isurfs = itarget(i)
6891                 amrtf(nmrtf)%rsvf = vffrac(i)
6892                 amrtf(nmrtf)%rtransp = ztransp(i)
6893              ENDDO ! itarg
6894
6895           ENDDO ! imrt
6896           DEALLOCATE ( zdirs, zcent, zbdry, vffrac, vffrac0, ztransp, itarget )
6897!
6898!--        Move MRT factors to final arrays
6899           ALLOCATE ( mrtf(nmrtf), mrtft(nmrtf), mrtfsurf(2,nmrtf) )
6900           DO  imrtf = 1, nmrtf
6901              mrtf(imrtf) = amrtf(imrtf)%rsvf
6902              mrtft(imrtf) = amrtf(imrtf)%rsvf * amrtf(imrtf)%rtransp
6903              mrtfsurf(:,imrtf) = (/amrtf(imrtf)%isurflt, amrtf(imrtf)%isurfs /)
6904           ENDDO
6905           IF ( ALLOCATED(amrtf1) )  DEALLOCATE( amrtf1 )
6906           IF ( ALLOCATED(amrtf2) )  DEALLOCATE( amrtf2 )
6907        ENDIF ! nmrtbl > 0
6908
6909        IF ( rad_angular_discretization )  THEN
6910#if defined( __parallel )
6911!--        finalize MPI_RMA communication established to get global index of the surface from grid indices
6912!--        flush all MPI window pending requests
6913           CALL MPI_Win_flush_all(win_gridsurf, ierr)
6914           IF ( ierr /= 0 ) THEN
6915               WRITE(9,*) 'Error MPI_Win_flush_all1:', ierr, win_gridsurf
6916               FLUSH(9)
6917           ENDIF
6918!--        unlock MPI window
6919           CALL MPI_Win_unlock_all(win_gridsurf, ierr)
6920           IF ( ierr /= 0 ) THEN
6921               WRITE(9,*) 'Error MPI_Win_unlock_all1:', ierr, win_gridsurf
6922               FLUSH(9)
6923           ENDIF
6924!--        free MPI window
6925           CALL MPI_Win_free(win_gridsurf, ierr)
6926           IF ( ierr /= 0 ) THEN
6927               WRITE(9,*) 'Error MPI_Win_free1:', ierr, win_gridsurf
6928               FLUSH(9)
6929           ENDIF
6930#else
6931           DEALLOCATE ( gridsurf )
6932#endif
6933        ENDIF
6934
6935        CALL radiation_write_debug_log( 'End of calculation SVF' )
6936        WRITE(msg, *) 'Raytracing skipped for maximum distance of ', &
6937           max_raytracing_dist, ' m on ', ray_skip_maxdist, ' pairs.'
6938        CALL radiation_write_debug_log( msg )
6939        WRITE(msg, *) 'Raytracing skipped for minimum potential value of ', &
6940           min_irrf_value , ' on ', ray_skip_minval, ' pairs.'
6941        CALL radiation_write_debug_log( msg )
6942
6943        CALL location_message( '    waiting for completion of SVF and CSF calculation in all processes', .TRUE. )
6944!--     deallocate temporary global arrays
6945        DEALLOCATE(nzterr)
6946       
6947        IF ( plant_canopy )  THEN
6948!--         finalize mpi_rma communication and deallocate temporary arrays
6949#if defined( __parallel )
6950            IF ( raytrace_mpi_rma )  THEN
6951                CALL MPI_Win_flush_all(win_lad, ierr)
6952                IF ( ierr /= 0 ) THEN
6953                    WRITE(9,*) 'Error MPI_Win_flush_all2:', ierr, win_lad
6954                    FLUSH(9)
6955                ENDIF
6956!--             unlock MPI window
6957                CALL MPI_Win_unlock_all(win_lad, ierr)
6958                IF ( ierr /= 0 ) THEN
6959                    WRITE(9,*) 'Error MPI_Win_unlock_all2:', ierr, win_lad
6960                    FLUSH(9)
6961                ENDIF
6962!--             free MPI window
6963                CALL MPI_Win_free(win_lad, ierr)
6964                IF ( ierr /= 0 ) THEN
6965                    WRITE(9,*) 'Error MPI_Win_free2:', ierr, win_lad
6966                    FLUSH(9)
6967                ENDIF
6968!--             deallocate temporary arrays storing values for csf calculation during raytracing
6969                DEALLOCATE( lad_s_ray )
6970!--             sub_lad is the pointer to lad_s_rma in case of raytrace_mpi_rma
6971!--             and must not be deallocated here
6972            ELSE
6973                DEALLOCATE(sub_lad)
6974                DEALLOCATE(sub_lad_g)
6975            ENDIF
6976#else
6977            DEALLOCATE(sub_lad)
6978#endif
6979            DEALLOCATE( boxes )
6980            DEALLOCATE( crlens )
6981            DEALLOCATE( plantt )
6982            DEALLOCATE( rt2_track, rt2_track_lad, rt2_track_dist, rt2_dist )
6983        ENDIF
6984
6985        CALL location_message( '    calculation of the complete SVF array', .TRUE. )
6986
6987        IF ( rad_angular_discretization )  THEN
6988           CALL radiation_write_debug_log( 'Load svf from the structure array to plain arrays' )
6989           ALLOCATE( svf(ndsvf,nsvfl) )
6990           ALLOCATE( svfsurf(idsvf,nsvfl) )
6991
6992           DO isvf = 1, nsvfl
6993               svf(:, isvf) = (/ asvf(isvf)%rsvf, asvf(isvf)%rtransp /)
6994               svfsurf(:, isvf) = (/ asvf(isvf)%isurflt, asvf(isvf)%isurfs /)
6995           ENDDO
6996        ELSE
6997           CALL radiation_write_debug_log( 'Start SVF sort' )
6998!--        sort svf ( a version of quicksort )
6999           CALL quicksort_svf(asvf,1,nsvfl)
7000
7001           !< load svf from the structure array to plain arrays
7002           CALL radiation_write_debug_log( 'Load svf from the structure array to plain arrays' )
7003           ALLOCATE( svf(ndsvf,nsvfl) )
7004           ALLOCATE( svfsurf(idsvf,nsvfl) )
7005           svfnorm_counts(:) = 0._wp
7006           isurflt_prev = -1
7007           ksvf = 1
7008           svfsum = 0._wp
7009           DO isvf = 1, nsvfl
7010!--            normalize svf per target face
7011               IF ( asvf(ksvf)%isurflt /= isurflt_prev )  THEN
7012                   IF ( isurflt_prev /= -1  .AND.  svfsum /= 0._wp )  THEN
7013                       !< update histogram of logged svf normalization values
7014                       i = searchsorted(svfnorm_report_thresh, svfsum / (1._wp-skyvf(isurflt_prev)))
7015                       svfnorm_counts(i) = svfnorm_counts(i) + 1
7016
7017                       svf(1, isvf_surflt:isvf-1) = svf(1, isvf_surflt:isvf-1) / svfsum * (1._wp-skyvf(isurflt_prev))
7018                   ENDIF
7019                   isurflt_prev = asvf(ksvf)%isurflt
7020                   isvf_surflt = isvf
7021                   svfsum = asvf(ksvf)%rsvf !?? / asvf(ksvf)%rtransp
7022               ELSE
7023                   svfsum = svfsum + asvf(ksvf)%rsvf !?? / asvf(ksvf)%rtransp
7024               ENDIF
7025
7026               svf(:, isvf) = (/ asvf(ksvf)%rsvf, asvf(ksvf)%rtransp /)
7027               svfsurf(:, isvf) = (/ asvf(ksvf)%isurflt, asvf(ksvf)%isurfs /)
7028
7029!--            next element
7030               ksvf = ksvf + 1
7031           ENDDO
7032
7033           IF ( isurflt_prev /= -1  .AND.  svfsum /= 0._wp )  THEN
7034               i = searchsorted(svfnorm_report_thresh, svfsum / (1._wp-skyvf(isurflt_prev)))
7035               svfnorm_counts(i) = svfnorm_counts(i) + 1
7036
7037               svf(1, isvf_surflt:nsvfl) = svf(1, isvf_surflt:nsvfl) / svfsum * (1._wp-skyvf(isurflt_prev))
7038           ENDIF
7039           WRITE(9, *) 'SVF normalization histogram:', svfnorm_counts,  &
7040                       'on thresholds:', svfnorm_report_thresh(1:svfnorm_report_num), '(val < thresh <= val)'
7041           !TODO we should be able to deallocate skyvf, from now on we only need skyvft
7042        ENDIF ! rad_angular_discretization
7043
7044!--     deallocate temporary asvf array
7045!--     DEALLOCATE(asvf) - ifort has a problem with deallocation of allocatable target
7046!--     via pointing pointer - we need to test original targets
7047        IF ( ALLOCATED(asvf1) )  THEN
7048            DEALLOCATE(asvf1)
7049        ENDIF
7050        IF ( ALLOCATED(asvf2) )  THEN
7051            DEALLOCATE(asvf2)
7052        ENDIF
7053
7054        npcsfl = 0
7055        IF ( plant_canopy )  THEN
7056
7057            CALL location_message( '    calculation of the complete CSF array', .TRUE. )
7058            CALL radiation_write_debug_log( 'Calculation of the complete CSF array' )
7059!--         sort and merge csf for the last time, keeping the array size to minimum
7060            CALL merge_and_grow_csf(-1)
7061           
7062!--         aggregate csb among processors
7063!--         allocate necessary arrays
7064            udim = max(ncsfl,1)
7065            ALLOCATE( csflt_l(ndcsf*udim) )
7066            csflt(1:ndcsf,1:udim) => csflt_l(1:ndcsf*udim)
7067            ALLOCATE( kcsflt_l(kdcsf*udim) )
7068            kcsflt(1:kdcsf,1:udim) => kcsflt_l(1:kdcsf*udim)
7069            ALLOCATE( icsflt(0:numprocs-1) )
7070            ALLOCATE( dcsflt(0:numprocs-1) )
7071            ALLOCATE( ipcsflt(0:numprocs-1) )
7072            ALLOCATE( dpcsflt(0:numprocs-1) )
7073           
7074!--         fill out arrays of csf values and
7075!--         arrays of number of elements and displacements
7076!--         for particular precessors
7077            icsflt = 0
7078            dcsflt = 0
7079            ip = -1
7080            j = -1
7081            d = 0
7082            DO kcsf = 1, ncsfl
7083                j = j+1
7084                IF ( acsf(kcsf)%ip /= ip )  THEN
7085!--                 new block of the processor
7086!--                 number of elements of previous block
7087                    IF ( ip>=0) icsflt(ip) = j
7088                    d = d+j
7089!--                 blank blocks
7090                    DO jp = ip+1, acsf(kcsf)%ip-1
7091!--                     number of elements is zero, displacement is equal to previous
7092                        icsflt(jp) = 0
7093                        dcsflt(jp) = d
7094                    ENDDO
7095!--                 the actual block
7096                    ip = acsf(kcsf)%ip
7097                    dcsflt(ip) = d
7098                    j = 0
7099                ENDIF
7100                csflt(1,kcsf) = acsf(kcsf)%rcvf
7101!--             fill out integer values of itz,ity,itx,isurfs
7102                kcsflt(1,kcsf) = acsf(kcsf)%itz
7103                kcsflt(2,kcsf) = acsf(kcsf)%ity
7104                kcsflt(3,kcsf) = acsf(kcsf)%itx
7105                kcsflt(4,kcsf) = acsf(kcsf)%isurfs
7106            ENDDO
7107!--         last blank blocks at the end of array
7108            j = j+1
7109            IF ( ip>=0 ) icsflt(ip) = j
7110            d = d+j
7111            DO jp = ip+1, numprocs-1
7112!--             number of elements is zero, displacement is equal to previous
7113                icsflt(jp) = 0
7114                dcsflt(jp) = d
7115            ENDDO
7116           
7117!--         deallocate temporary acsf array
7118!--         DEALLOCATE(acsf) - ifort has a problem with deallocation of allocatable target
7119!--         via pointing pointer - we need to test original targets
7120            IF ( ALLOCATED(acsf1) )  THEN
7121                DEALLOCATE(acsf1)
7122            ENDIF
7123            IF ( ALLOCATED(acsf2) )  THEN
7124                DEALLOCATE(acsf2)
7125            ENDIF
7126                   
7127#if defined( __parallel )
7128!--         scatter and gather the number of elements to and from all processor
7129!--         and calculate displacements
7130            CALL radiation_write_debug_log( 'Scatter and gather the number of elements to and from all processor' )
7131            CALL MPI_AlltoAll(icsflt,1,MPI_INTEGER,ipcsflt,1,MPI_INTEGER,comm2d, ierr)
7132            IF ( ierr /= 0 ) THEN
7133                WRITE(9,*) 'Error MPI_AlltoAll1:', ierr, SIZE(icsflt), SIZE(ipcsflt)
7134                FLUSH(9)
7135            ENDIF
7136
7137            npcsfl = SUM(ipcsflt)
7138            d = 0
7139            DO i = 0, numprocs-1
7140                dpcsflt(i) = d
7141                d = d + ipcsflt(i)
7142            ENDDO
7143
7144!--         exchange csf fields between processors
7145            CALL radiation_write_debug_log( 'Exchange csf fields between processors' )
7146            udim = max(npcsfl,1)
7147            ALLOCATE( pcsflt_l(ndcsf*udim) )
7148            pcsflt(1:ndcsf,1:udim) => pcsflt_l(1:ndcsf*udim)
7149            ALLOCATE( kpcsflt_l(kdcsf*udim) )
7150            kpcsflt(1:kdcsf,1:udim) => kpcsflt_l(1:kdcsf*udim)
7151            CALL MPI_AlltoAllv(csflt_l, ndcsf*icsflt, ndcsf*dcsflt, MPI_REAL, &
7152                pcsflt_l, ndcsf*ipcsflt, ndcsf*dpcsflt, MPI_REAL, comm2d, ierr)
7153            IF ( ierr /= 0 ) THEN
7154                WRITE(9,*) 'Error MPI_AlltoAllv1:', ierr, SIZE(ipcsflt), ndcsf*icsflt, &
7155                            ndcsf*dcsflt, SIZE(pcsflt_l),ndcsf*ipcsflt, ndcsf*dpcsflt
7156                FLUSH(9)
7157            ENDIF
7158
7159            CALL MPI_AlltoAllv(kcsflt_l, kdcsf*icsflt, kdcsf*dcsflt, MPI_INTEGER, &
7160                kpcsflt_l, kdcsf*ipcsflt, kdcsf*dpcsflt, MPI_INTEGER, comm2d, ierr)
7161            IF ( ierr /= 0 ) THEN
7162                WRITE(9,*) 'Error MPI_AlltoAllv2:', ierr, SIZE(kcsflt_l),kdcsf*icsflt, &
7163                           kdcsf*dcsflt, SIZE(kpcsflt_l), kdcsf*ipcsflt, kdcsf*dpcsflt
7164                FLUSH(9)
7165            ENDIF
7166           
7167#else
7168            npcsfl = ncsfl
7169            ALLOCATE( pcsflt(ndcsf,max(npcsfl,ndcsf)) )
7170            ALLOCATE( kpcsflt(kdcsf,max(npcsfl,kdcsf)) )
7171            pcsflt = csflt
7172            kpcsflt = kcsflt
7173#endif
7174
7175!--         deallocate temporary arrays
7176            DEALLOCATE( csflt_l )
7177            DEALLOCATE( kcsflt_l )
7178            DEALLOCATE( icsflt )
7179            DEALLOCATE( dcsflt )
7180            DEALLOCATE( ipcsflt )
7181            DEALLOCATE( dpcsflt )
7182
7183!--         sort csf ( a version of quicksort )
7184            CALL radiation_write_debug_log( 'Sort csf' )
7185            CALL quicksort_csf2(kpcsflt, pcsflt, 1, npcsfl)
7186
7187!--         aggregate canopy sink factor records with identical box & source
7188!--         againg across all values from all processors
7189            CALL radiation_write_debug_log( 'Aggregate canopy sink factor records with identical box' )
7190
7191            IF ( npcsfl > 0 )  THEN
7192                icsf = 1 !< reading index
7193                kcsf = 1 !< writing index
7194                DO while (icsf < npcsfl)
7195!--                 here kpcsf(kcsf) already has values from kpcsf(icsf)
7196                    IF ( kpcsflt(3,icsf) == kpcsflt(3,icsf+1)  .AND.  &
7197                         kpcsflt(2,icsf) == kpcsflt(2,icsf+1)  .AND.  &
7198                         kpcsflt(1,icsf) == kpcsflt(1,icsf+1)  .AND.  &
7199                         kpcsflt(4,icsf) == kpcsflt(4,icsf+1) )  THEN
7200
7201                        pcsflt(1,kcsf) = pcsflt(1,kcsf) + pcsflt(1,icsf+1)
7202
7203!--                     advance reading index, keep writing index
7204                        icsf = icsf + 1
7205                    ELSE
7206!--                     not identical, just advance and copy
7207                        icsf = icsf + 1
7208                        kcsf = kcsf + 1
7209                        kpcsflt(:,kcsf) = kpcsflt(:,icsf)
7210                        pcsflt(:,kcsf) = pcsflt(:,icsf)
7211                    ENDIF
7212                ENDDO
7213!--             last written item is now also the last item in valid part of array
7214                npcsfl = kcsf
7215            ENDIF
7216
7217            ncsfl = npcsfl
7218            IF ( ncsfl > 0 )  THEN
7219                ALLOCATE( csf(ndcsf,ncsfl) )
7220                ALLOCATE( csfsurf(idcsf,ncsfl) )
7221                DO icsf = 1, ncsfl
7222                    csf(:,icsf) = pcsflt(:,icsf)
7223                    csfsurf(1,icsf) =  gridpcbl(kpcsflt(1,icsf),kpcsflt(2,icsf),kpcsflt(3,icsf))
7224                    csfsurf(2,icsf) =  kpcsflt(4,icsf)
7225                ENDDO
7226            ENDIF
7227           
7228!--         deallocation of temporary arrays
7229            IF ( npcbl > 0 )  DEALLOCATE( gridpcbl )
7230            DEALLOCATE( pcsflt_l )
7231            DEALLOCATE( kpcsflt_l )
7232            CALL radiation_write_debug_log( 'End of aggregate csf' )
7233           
7234        ENDIF
7235
7236#if defined( __parallel )
7237        CALL MPI_BARRIER( comm2d, ierr )
7238#endif
7239        CALL radiation_write_debug_log( 'End of radiation_calc_svf (after mpi_barrier)' )
7240
7241        RETURN
7242       
7243!        WRITE( message_string, * )  &
7244!            'I/O error when processing shape view factors / ',  &
7245!            'plant canopy sink factors / direct irradiance factors.'
7246!        CALL message( 'init_urban_surface', 'PA0502', 2, 2, 0, 6, 0 )
7247       
7248    END SUBROUTINE radiation_calc_svf
7249
7250   
7251!------------------------------------------------------------------------------!
7252! Description:
7253! ------------
7254!> Raytracing for detecting obstacles and calculating compound canopy sink
7255!> factors. (A simple obstacle detection would only need to process faces in
7256!> 3 dimensions without any ordering.)
7257!> Assumtions:
7258!> -----------
7259!> 1. The ray always originates from a face midpoint (only one coordinate equals
7260!>    *.5, i.e. wall) and doesn't travel parallel to the surface (that would mean
7261!>    shape factor=0). Therefore, the ray may never travel exactly along a face
7262!>    or an edge.
7263!> 2. From grid bottom to urban surface top the grid has to be *equidistant*
7264!>    within each of the dimensions, including vertical (but the resolution
7265!>    doesn't need to be the same in all three dimensions).
7266!------------------------------------------------------------------------------!
7267    SUBROUTINE raytrace(src, targ, isrc, difvf, atarg, create_csf, visible, transparency)
7268        IMPLICIT NONE
7269
7270        REAL(wp), DIMENSION(3), INTENT(in)     :: src, targ    !< real coordinates z,y,x
7271        INTEGER(iwp), INTENT(in)               :: isrc         !< index of source face for csf
7272        REAL(wp), INTENT(in)                   :: difvf        !< differential view factor for csf
7273        REAL(wp), INTENT(in)                   :: atarg        !< target surface area for csf
7274        LOGICAL, INTENT(in)                    :: create_csf   !< whether to generate new CSFs during raytracing
7275        LOGICAL, INTENT(out)                   :: visible
7276        REAL(wp), INTENT(out)                  :: transparency !< along whole path
7277        INTEGER(iwp)                           :: i, k, d
7278        INTEGER(iwp)                           :: seldim       !< dimension to be incremented
7279        INTEGER(iwp)                           :: ncsb         !< no of written plant canopy sinkboxes
7280        INTEGER(iwp)                           :: maxboxes     !< max no of gridboxes visited
7281        REAL(wp)                               :: distance     !< euclidean along path
7282        REAL(wp)                               :: crlen        !< length of gridbox crossing
7283        REAL(wp)                               :: lastdist     !< beginning of current crossing
7284        REAL(wp)                               :: nextdist     !< end of current crossing
7285        REAL(wp)                               :: realdist     !< distance in meters per unit distance
7286        REAL(wp)                               :: crmid        !< midpoint of crossing
7287        REAL(wp)                               :: cursink      !< sink factor for current canopy box
7288        REAL(wp), DIMENSION(3)                 :: delta        !< path vector
7289        REAL(wp), DIMENSION(3)                 :: uvect        !< unit vector
7290        REAL(wp), DIMENSION(3)                 :: dimnextdist  !< distance for each dimension increments
7291        INTEGER(iwp), DIMENSION(3)             :: box          !< gridbox being crossed
7292        INTEGER(iwp), DIMENSION(3)             :: dimnext      !< next dimension increments along path
7293        INTEGER(iwp), DIMENSION(3)             :: dimdelta     !< dimension direction = +- 1
7294        INTEGER(iwp)                           :: px, py       !< number of processors in x and y dir before
7295                                                               !< the processor in the question
7296        INTEGER(iwp)                           :: ip           !< number of processor where gridbox reside
7297        INTEGER(iwp)                           :: ig           !< 1D index of gridbox in global 2D array
7298       
7299        REAL(wp)                               :: eps = 1E-10_wp !< epsilon for value comparison
7300        REAL(wp)                               :: lad_s_target   !< recieved lad_s of particular grid box
7301
7302!
7303!--     Maximum number of gridboxes visited equals to maximum number of boundaries crossed in each dimension plus one. That's also
7304!--     the maximum number of plant canopy boxes written. We grow the acsf array accordingly using exponential factor.
7305        maxboxes = SUM(ABS(NINT(targ, iwp) - NINT(src, iwp))) + 1
7306        IF ( plant_canopy  .AND.  ncsfl + maxboxes > ncsfla )  THEN
7307!--         use this code for growing by fixed exponential increments (equivalent to case where ncsfl always increases by 1)
7308!--         k = CEILING(grow_factor ** real(CEILING(log(real(ncsfl + maxboxes, kind=wp)) &
7309!--                                                / log(grow_factor)), kind=wp))
7310!--         or use this code to simply always keep some extra space after growing
7311            k = CEILING(REAL(ncsfl + maxboxes, kind=wp) * grow_factor)
7312
7313            CALL merge_and_grow_csf(k)
7314        ENDIF
7315       
7316        transparency = 1._wp
7317        ncsb = 0
7318
7319        delta(:) = targ(:) - src(:)
7320        distance = SQRT(SUM(delta(:)**2))
7321        IF ( distance == 0._wp )  THEN
7322            visible = .TRUE.
7323            RETURN
7324        ENDIF
7325        uvect(:) = delta(:) / distance
7326        realdist = SQRT(SUM( (uvect(:)*(/dz(1),dy,dx/))**2 ))
7327
7328        lastdist = 0._wp
7329
7330!--     Since all face coordinates have values *.5 and we'd like to use
7331!--     integers, all these have .5 added
7332        DO d = 1, 3
7333            IF ( uvect(d) == 0._wp )  THEN
7334                dimnext(d) = 999999999
7335                dimdelta(d) = 999999999
7336                dimnextdist(d) = 1.0E20_wp
7337            ELSE IF ( uvect(d) > 0._wp )  THEN
7338                dimnext(d) = CEILING(src(d) + .5_wp)
7339                dimdelta(d) = 1
7340                dimnextdist(d) = (dimnext(d) - .5_wp - src(d)) / uvect(d)
7341            ELSE
7342                dimnext(d) = FLOOR(src(d) + .5_wp)
7343                dimdelta(d) = -1
7344                dimnextdist(d) = (dimnext(d) - .5_wp - src(d)) / uvect(d)
7345            ENDIF
7346        ENDDO
7347
7348        DO
7349!--         along what dimension will the next wall crossing be?
7350            seldim = minloc(dimnextdist, 1)
7351            nextdist = dimnextdist(seldim)
7352            IF ( nextdist > distance ) nextdist = distance
7353
7354            crlen = nextdist - lastdist
7355            IF ( crlen > .001_wp )  THEN
7356                crmid = (lastdist + nextdist) * .5_wp
7357                box = NINT(src(:) + uvect(:) * crmid, iwp)
7358
7359!--             calculate index of the grid with global indices (box(2),box(3))
7360!--             in the array nzterr and plantt and id of the coresponding processor
7361                px = box(3)/nnx
7362                py = box(2)/nny
7363                ip = px*pdims(2)+py
7364                ig = ip*nnx*nny + (box(3)-px*nnx)*nny + box(2)-py*nny
7365                IF ( box(1) <= nzterr(ig) )  THEN
7366                    visible = .FALSE.
7367                    RETURN
7368                ENDIF
7369
7370                IF ( plant_canopy )  THEN
7371                    IF ( box(1) <= plantt(ig) )  THEN
7372                        ncsb = ncsb + 1
7373                        boxes(:,ncsb) = box
7374                        crlens(ncsb) = crlen
7375#if defined( __parallel )
7376                        lad_ip(ncsb) = ip
7377                        lad_disp(ncsb) = (box(3)-px*nnx)*(nny*nzp) + (box(2)-py*nny)*nzp + box(1)-nzub
7378#endif
7379                    ENDIF
7380                ENDIF
7381            ENDIF
7382
7383            IF ( ABS(distance - nextdist) < eps )  EXIT
7384            lastdist = nextdist
7385            dimnext(seldim) = dimnext(seldim) + dimdelta(seldim)
7386            dimnextdist(seldim) = (dimnext(seldim) - .5_wp - src(seldim)) / uvect(seldim)
7387        ENDDO
7388       
7389        IF ( plant_canopy )  THEN
7390#if defined( __parallel )
7391            IF ( raytrace_mpi_rma )  THEN
7392!--             send requests for lad_s to appropriate processor
7393                CALL cpu_log( log_point_s(77), 'rad_rma_lad', 'start' )
7394                DO i = 1, ncsb
7395                    CALL MPI_Get(lad_s_ray(i), 1, MPI_REAL, lad_ip(i), lad_disp(i), &
7396                                 1, MPI_REAL, win_lad, ierr)
7397                    IF ( ierr /= 0 )  THEN
7398                        WRITE(9,*) 'Error MPI_Get1:', ierr, lad_s_ray(i), &
7399                                   lad_ip(i), lad_disp(i), win_lad
7400                        FLUSH(9)
7401                    ENDIF
7402                ENDDO
7403               
7404!--             wait for all pending local requests complete
7405                CALL MPI_Win_flush_local_all(win_lad, ierr)
7406                IF ( ierr /= 0 )  THEN
7407                    WRITE(9,*) 'Error MPI_Win_flush_local_all1:', ierr, win_lad
7408                    FLUSH(9)
7409                ENDIF
7410                CALL cpu_log( log_point_s(77), 'rad_rma_lad', 'stop' )
7411               
7412            ENDIF
7413#endif
7414
7415!--         calculate csf and transparency
7416            DO i = 1, ncsb
7417#if defined( __parallel )
7418                IF ( raytrace_mpi_rma )  THEN
7419                    lad_s_target = lad_s_ray(i)
7420                ELSE
7421                    lad_s_target = sub_lad_g(lad_ip(i)*nnx*nny*nzp + lad_disp(i))
7422                ENDIF
7423#else
7424                lad_s_target = sub_lad(boxes(1,i),boxes(2,i),boxes(3,i))
7425#endif
7426                cursink = 1._wp - exp(-ext_coef * lad_s_target * crlens(i)*realdist)
7427
7428                IF ( create_csf )  THEN
7429!--                 write svf values into the array
7430                    ncsfl = ncsfl + 1
7431                    acsf(ncsfl)%ip = lad_ip(i)
7432                    acsf(ncsfl)%itx = boxes(3,i)
7433                    acsf(ncsfl)%ity = boxes(2,i)
7434                    acsf(ncsfl)%itz = boxes(1,i)
7435                    acsf(ncsfl)%isurfs = isrc
7436                    acsf(ncsfl)%rcvf = cursink*transparency*difvf*atarg
7437                ENDIF  !< create_csf
7438
7439                transparency = transparency * (1._wp - cursink)
7440               
7441            ENDDO
7442        ENDIF
7443       
7444        visible = .TRUE.
7445
7446    END SUBROUTINE raytrace
7447   
7448 
7449!------------------------------------------------------------------------------!
7450! Description:
7451! ------------
7452!> A new, more efficient version of ray tracing algorithm that processes a whole
7453!> arc instead of a single ray.
7454!>
7455!> In all comments, horizon means tangent of horizon angle, i.e.
7456!> vertical_delta / horizontal_distance
7457!------------------------------------------------------------------------------!
7458   SUBROUTINE raytrace_2d(origin, yxdir, nrays, zdirs, iorig, aorig, vffrac,  &
7459                              calc_svf, create_csf, skip_1st_pcb,             &
7460                              lowest_free_ray, transparency, itarget)
7461      IMPLICIT NONE
7462
7463      REAL(wp), DIMENSION(3), INTENT(IN)     ::  origin        !< z,y,x coordinates of ray origin
7464      REAL(wp), DIMENSION(2), INTENT(IN)     ::  yxdir         !< y,x *unit* vector of ray direction (in grid units)
7465      INTEGER(iwp)                           ::  nrays         !< number of rays (z directions) to raytrace
7466      REAL(wp), DIMENSION(nrays), INTENT(IN) ::  zdirs         !< list of z directions to raytrace (z/hdist, grid, zenith->nadir)
7467      INTEGER(iwp), INTENT(in)               ::  iorig         !< index of origin face for csf
7468      REAL(wp), INTENT(in)                   ::  aorig         !< origin face area for csf
7469      REAL(wp), DIMENSION(nrays), INTENT(in) ::  vffrac        !< view factor fractions of each ray for csf
7470      LOGICAL, INTENT(in)                    ::  calc_svf      !< whether to calculate SFV (identify obstacle surfaces)
7471      LOGICAL, INTENT(in)                    ::  create_csf    !< whether to create canopy sink factors
7472      LOGICAL, INTENT(in)                    ::  skip_1st_pcb  !< whether to skip first plant canopy box during raytracing
7473      INTEGER(iwp), INTENT(out)              ::  lowest_free_ray !< index into zdirs
7474      REAL(wp), DIMENSION(nrays), INTENT(OUT) ::  transparency !< transparencies of zdirs paths
7475      INTEGER(iwp), DIMENSION(nrays), INTENT(OUT) ::  itarget  !< global indices of target faces for zdirs
7476
7477      INTEGER(iwp), DIMENSION(nrays)         ::  target_procs
7478      REAL(wp)                               ::  horizon       !< highest horizon found after raytracing (z/hdist)
7479      INTEGER(iwp)                           ::  i, k, l, d
7480      INTEGER(iwp)                           ::  seldim       !< dimension to be incremented
7481      REAL(wp), DIMENSION(2)                 ::  yxorigin     !< horizontal copy of origin (y,x)
7482      REAL(wp)                               ::  distance     !< euclidean along path
7483      REAL(wp)                               ::  lastdist     !< beginning of current crossing
7484      REAL(wp)                               ::  nextdist     !< end of current crossing
7485      REAL(wp)                               ::  crmid        !< midpoint of crossing
7486      REAL(wp)                               ::  horz_entry   !< horizon at entry to column
7487      REAL(wp)                               ::  horz_exit    !< horizon at exit from column
7488      REAL(wp)                               ::  bdydim       !< boundary for current dimension
7489      REAL(wp), DIMENSION(2)                 ::  crossdist    !< distances to boundary for dimensions
7490      REAL(wp), DIMENSION(2)                 ::  dimnextdist  !< distance for each dimension increments
7491      INTEGER(iwp), DIMENSION(2)             ::  column       !< grid column being crossed
7492      INTEGER(iwp), DIMENSION(2)             ::  dimnext      !< next dimension increments along path
7493      INTEGER(iwp), DIMENSION(2)             ::  dimdelta     !< dimension direction = +- 1
7494      INTEGER(iwp)                           ::  px, py       !< number of processors in x and y dir before
7495                                                              !< the processor in the question
7496      INTEGER(iwp)                           ::  ip           !< number of processor where gridbox reside
7497      INTEGER(iwp)                           ::  ig           !< 1D index of gridbox in global 2D array
7498      INTEGER(iwp)                           ::  wcount       !< RMA window item count
7499      INTEGER(iwp)                           ::  maxboxes     !< max no of CSF created
7500      INTEGER(iwp)                           ::  nly          !< maximum  plant canopy height
7501      INTEGER(iwp)                           ::  ntrack
7502     
7503      INTEGER(iwp)                           ::  zb0
7504      INTEGER(iwp)                           ::  zb1
7505      INTEGER(iwp)                           ::  nz
7506      INTEGER(iwp)                           ::  iz
7507      INTEGER(iwp)                           ::  zsgn
7508      INTEGER(iwp)                           ::  lowest_lad   !< lowest column cell for which we need LAD
7509      INTEGER(iwp)                           ::  lastdir      !< wall direction before hitting this column
7510      INTEGER(iwp), DIMENSION(2)             ::  lastcolumn
7511
7512#if defined( __parallel )
7513      INTEGER(MPI_ADDRESS_KIND)              ::  wdisp        !< RMA window displacement
7514#endif
7515     
7516      REAL(wp)                               ::  eps = 1E-10_wp !< epsilon for value comparison
7517      REAL(wp)                               ::  zbottom, ztop !< urban surface boundary in real numbers
7518      REAL(wp)                               ::  zorig         !< z coordinate of ray column entry
7519      REAL(wp)                               ::  zexit         !< z coordinate of ray column exit
7520      REAL(wp)                               ::  qdist         !< ratio of real distance to z coord difference
7521      REAL(wp)                               ::  dxxyy         !< square of real horizontal distance
7522      REAL(wp)                               ::  curtrans      !< transparency of current PC box crossing
7523     
7524
7525     
7526      yxorigin(:) = origin(2:3)
7527      transparency(:) = 1._wp !-- Pre-set the all rays to transparent before reducing
7528      horizon = -HUGE(1._wp)
7529      lowest_free_ray = nrays
7530      IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7531         ALLOCATE(target_surfl(nrays))
7532         target_surfl(:) = -1
7533         lastdir = -999
7534         lastcolumn(:) = -999
7535      ENDIF
7536
7537!--   Determine distance to boundary (in 2D xy)
7538      IF ( yxdir(1) > 0._wp )  THEN
7539         bdydim = ny + .5_wp !< north global boundary
7540         crossdist(1) = (bdydim - yxorigin(1)) / yxdir(1)
7541      ELSEIF ( yxdir(1) == 0._wp )  THEN
7542         crossdist(1) = HUGE(1._wp)
7543      ELSE
7544          bdydim = -.5_wp !< south global boundary
7545          crossdist(1) = (bdydim - yxorigin(1)) / yxdir(1)
7546      ENDIF
7547
7548      IF ( yxdir(2) >= 0._wp )  THEN
7549          bdydim = nx + .5_wp !< east global boundary
7550          crossdist(2) = (bdydim - yxorigin(2)) / yxdir(2)
7551      ELSEIF ( yxdir(2) == 0._wp )  THEN
7552         crossdist(2) = HUGE(1._wp)
7553      ELSE
7554          bdydim = -.5_wp !< west global boundary
7555          crossdist(2) = (bdydim - yxorigin(2)) / yxdir(2)
7556      ENDIF
7557      distance = minval(crossdist, 1)
7558
7559      IF ( plant_canopy )  THEN
7560         rt2_track_dist(0) = 0._wp
7561         rt2_track_lad(:,:) = 0._wp
7562         nly = plantt_max - nzub + 1
7563      ENDIF
7564
7565      lastdist = 0._wp
7566
7567!--   Since all face coordinates have values *.5 and we'd like to use
7568!--   integers, all these have .5 added
7569      DO  d = 1, 2
7570          IF ( yxdir(d) == 0._wp )  THEN
7571              dimnext(d) = HUGE(1_iwp)
7572              dimdelta(d) = HUGE(1_iwp)
7573              dimnextdist(d) = HUGE(1._wp)
7574          ELSE IF ( yxdir(d) > 0._wp )  THEN
7575              dimnext(d) = FLOOR(yxorigin(d) + .5_wp) + 1
7576              dimdelta(d) = 1
7577              dimnextdist(d) = (dimnext(d) - .5_wp - yxorigin(d)) / yxdir(d)
7578          ELSE
7579              dimnext(d) = CEILING(yxorigin(d) + .5_wp) - 1
7580              dimdelta(d) = -1
7581              dimnextdist(d) = (dimnext(d) - .5_wp - yxorigin(d)) / yxdir(d)
7582          ENDIF
7583      ENDDO
7584
7585      ntrack = 0
7586      DO
7587!--      along what dimension will the next wall crossing be?
7588         seldim = minloc(dimnextdist, 1)
7589         nextdist = dimnextdist(seldim)
7590         IF ( nextdist > distance )  nextdist = distance
7591
7592         IF ( nextdist > lastdist )  THEN
7593            ntrack = ntrack + 1
7594            crmid = (lastdist + nextdist) * .5_wp
7595            column = NINT(yxorigin(:) + yxdir(:) * crmid, iwp)
7596
7597!--         calculate index of the grid with global indices (column(1),column(2))
7598!--         in the array nzterr and plantt and id of the coresponding processor
7599            px = column(2)/nnx
7600            py = column(1)/nny
7601            ip = px*pdims(2)+py
7602            ig = ip*nnx*nny + (column(2)-px*nnx)*nny + column(1)-py*nny
7603
7604            IF ( lastdist == 0._wp )  THEN
7605               horz_entry = -HUGE(1._wp)
7606            ELSE
7607               horz_entry = (REAL(nzterr(ig), wp) + .5_wp - origin(1)) / lastdist
7608            ENDIF
7609            horz_exit = (REAL(nzterr(ig), wp) + .5_wp - origin(1)) / nextdist
7610
7611            IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7612!
7613!--            Identify vertical obstacles hit by rays in current column
7614               DO WHILE ( lowest_free_ray > 0 )
7615                  IF ( zdirs(lowest_free_ray) > horz_entry )  EXIT
7616!
7617!--               This may only happen after 1st column, so lastdir and lastcolumn are valid
7618                  CALL request_itarget(lastdir,                                         &
7619                        CEILING(-0.5_wp + origin(1) + zdirs(lowest_free_ray)*lastdist), &
7620                        lastcolumn(1), lastcolumn(2),                                   &
7621                        target_surfl(lowest_free_ray), target_procs(lowest_free_ray))
7622                  lowest_free_ray = lowest_free_ray - 1
7623               ENDDO
7624!
7625!--            Identify horizontal obstacles hit by rays in current column
7626               DO WHILE ( lowest_free_ray > 0 )
7627                  IF ( zdirs(lowest_free_ray) > horz_exit )  EXIT
7628                  CALL request_itarget(iup_u, nzterr(ig)+1, column(1), column(2), &
7629                                       target_surfl(lowest_free_ray),           &
7630                                       target_procs(lowest_free_ray))
7631                  lowest_free_ray = lowest_free_ray - 1
7632               ENDDO
7633            ENDIF
7634
7635            horizon = MAX(horizon, horz_entry, horz_exit)
7636
7637            IF ( plant_canopy )  THEN
7638               rt2_track(:, ntrack) = column(:)
7639               rt2_track_dist(ntrack) = nextdist
7640            ENDIF
7641         ENDIF
7642
7643         IF ( ABS(distance - nextdist) < eps )  EXIT
7644
7645         IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7646!
7647!--         Save wall direction of coming building column (= this air column)
7648            IF ( seldim == 1 )  THEN
7649               IF ( dimdelta(seldim) == 1 )  THEN
7650                  lastdir = isouth_u
7651               ELSE
7652                  lastdir = inorth_u
7653               ENDIF
7654            ELSE
7655               IF ( dimdelta(seldim) == 1 )  THEN
7656                  lastdir = iwest_u
7657               ELSE
7658                  lastdir = ieast_u
7659               ENDIF
7660            ENDIF
7661            lastcolumn = column
7662         ENDIF
7663         lastdist = nextdist
7664         dimnext(seldim) = dimnext(seldim) + dimdelta(seldim)
7665         dimnextdist(seldim) = (dimnext(seldim) - .5_wp - yxorigin(seldim)) / yxdir(seldim)
7666      ENDDO
7667
7668      IF ( plant_canopy )  THEN
7669!--      Request LAD WHERE applicable
7670!--     
7671#if defined( __parallel )
7672         IF ( raytrace_mpi_rma )  THEN
7673!--         send requests for lad_s to appropriate processor
7674            !CALL cpu_log( log_point_s(77), 'usm_init_rma', 'start' )
7675            DO  i = 1, ntrack
7676               px = rt2_track(2,i)/nnx
7677               py = rt2_track(1,i)/nny
7678               ip = px*pdims(2)+py
7679               ig = ip*nnx*nny + (rt2_track(2,i)-px*nnx)*nny + rt2_track(1,i)-py*nny
7680
7681               IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7682!
7683!--               For fixed view resolution, we need plant canopy even for rays
7684!--               to opposing surfaces
7685                  lowest_lad = nzterr(ig) + 1
7686               ELSE
7687!
7688!--               We only need LAD for rays directed above horizon (to sky)
7689                  lowest_lad = CEILING( -0.5_wp + origin(1) +            &
7690                                    MIN( horizon * rt2_track_dist(i-1),  & ! entry
7691                                         horizon * rt2_track_dist(i)   ) ) ! exit
7692               ENDIF
7693!
7694!--            Skip asking for LAD where all plant canopy is under requested level
7695               IF ( plantt(ig) < lowest_lad )  CYCLE
7696
7697               wdisp = (rt2_track(2,i)-px*nnx)*(nny*nzp) + (rt2_track(1,i)-py*nny)*nzp + lowest_lad-nzub
7698               wcount = plantt(ig)-lowest_lad+1
7699               ! TODO send request ASAP - even during raytracing
7700               CALL MPI_Get(rt2_track_lad(lowest_lad:plantt(ig), i), wcount, MPI_REAL, ip,    &
7701                            wdisp, wcount, MPI_REAL, win_lad, ierr)
7702               IF ( ierr /= 0 )  THEN
7703                  WRITE(9,*) 'Error MPI_Get2:', ierr, rt2_track_lad(lowest_lad:plantt(ig), i), &
7704                             wcount, ip, wdisp, win_lad
7705                  FLUSH(9)
7706               ENDIF
7707            ENDDO
7708
7709!--         wait for all pending local requests complete
7710            ! TODO WAIT selectively for each column later when needed
7711            CALL MPI_Win_flush_local_all(win_lad, ierr)
7712            IF ( ierr /= 0 )  THEN
7713               WRITE(9,*) 'Error MPI_Win_flush_local_all2:', ierr, win_lad
7714               FLUSH(9)
7715            ENDIF
7716            !CALL cpu_log( log_point_s(77), 'usm_init_rma', 'stop' )
7717
7718         ELSE ! raytrace_mpi_rma = .F.
7719            DO  i = 1, ntrack
7720               px = rt2_track(2,i)/nnx
7721               py = rt2_track(1,i)/nny
7722               ip = px*pdims(2)+py
7723               ig = ip*nnx*nny*nzp + (rt2_track(2,i)-px*nnx)*(nny*nzp) + (rt2_track(1,i)-py*nny)*nzp
7724               rt2_track_lad(nzub:plantt_max, i) = sub_lad_g(ig:ig+nly-1)
7725            ENDDO
7726         ENDIF
7727#else
7728         DO  i = 1, ntrack
7729            rt2_track_lad(nzub:plantt_max, i) = sub_lad(rt2_track(1,i), rt2_track(2,i), nzub:plantt_max)
7730         ENDDO
7731#endif
7732      ENDIF ! plant_canopy
7733
7734      IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7735#if defined( __parallel )
7736!--      wait for all gridsurf requests to complete
7737         CALL MPI_Win_flush_local_all(win_gridsurf, ierr)
7738         IF ( ierr /= 0 )  THEN
7739            WRITE(9,*) 'Error MPI_Win_flush_local_all3:', ierr, win_gridsurf
7740            FLUSH(9)
7741         ENDIF
7742#endif
7743!
7744!--      recalculate local surf indices into global ones
7745         DO i = 1, nrays
7746            IF ( target_surfl(i) == -1 )  THEN
7747               itarget(i) = -1
7748            ELSE
7749               itarget(i) = target_surfl(i) + surfstart(target_procs(i))
7750            ENDIF
7751         ENDDO
7752         
7753         DEALLOCATE( target_surfl )
7754         
7755      ELSE
7756         itarget(:) = -1
7757      ENDIF ! rad_angular_discretization
7758
7759      IF ( plant_canopy )  THEN
7760!--      Skip the PCB around origin if requested (for MRT, the PCB might not be there)
7761!--     
7762         IF ( skip_1st_pcb  .AND.  NINT(origin(1)) <= plantt_max )  THEN
7763            rt2_track_lad(NINT(origin(1), iwp), 1) = 0._wp
7764         ENDIF
7765
7766!--      Assert that we have space allocated for CSFs
7767!--     
7768         maxboxes = (ntrack + MAX(CEILING(origin(1)-.5_wp) - nzub,          &
7769                                  nzut - CEILING(origin(1)-.5_wp))) * nrays
7770         IF ( ncsfl + maxboxes > ncsfla )  THEN
7771!--         use this code for growing by fixed exponential increments (equivalent to case where ncsfl always increases by 1)
7772!--         k = CEILING(grow_factor ** real(CEILING(log(real(ncsfl + maxboxes, kind=wp)) &
7773!--                                                / log(grow_factor)), kind=wp))
7774!--         or use this code to simply always keep some extra space after growing
7775            k = CEILING(REAL(ncsfl + maxboxes, kind=wp) * grow_factor)
7776            CALL merge_and_grow_csf(k)
7777         ENDIF
7778
7779!--      Calculate transparencies and store new CSFs
7780!--     
7781         zbottom = REAL(nzub, wp) - .5_wp
7782         ztop = REAL(plantt_max, wp) + .5_wp
7783
7784!--      Reverse direction of radiation (face->sky), only when calc_svf
7785!--     
7786         IF ( calc_svf )  THEN
7787            DO  i = 1, ntrack ! for each column
7788               dxxyy = ((dy*yxdir(1))**2 + (dx*yxdir(2))**2) * (rt2_track_dist(i)-rt2_track_dist(i-1))**2
7789               px = rt2_track(2,i)/nnx
7790               py = rt2_track(1,i)/nny
7791               ip = px*pdims(2)+py
7792
7793               DO  k = 1, nrays ! for each ray
7794!
7795!--               NOTE 6778:
7796!--               With traditional svf discretization, CSFs under the horizon
7797!--               (i.e. for surface to surface radiation)  are created in
7798!--               raytrace(). With rad_angular_discretization, we must create
7799!--               CSFs under horizon only for one direction, otherwise we would
7800!--               have duplicate amount of energy. Although we could choose
7801!--               either of the two directions (they differ only by
7802!--               discretization error with no bias), we choose the the backward
7803!--               direction, because it tends to cumulate high canopy sink
7804!--               factors closer to raytrace origin, i.e. it should potentially
7805!--               cause less moiree.
7806                  IF ( .NOT. rad_angular_discretization )  THEN
7807                     IF ( zdirs(k) <= horizon )  CYCLE
7808                  ENDIF
7809
7810                  zorig = origin(1) + zdirs(k) * rt2_track_dist(i-1)
7811                  IF ( zorig <= zbottom  .OR.  zorig >= ztop )  CYCLE
7812
7813                  zsgn = INT(SIGN(1._wp, zdirs(k)), iwp)
7814                  rt2_dist(1) = 0._wp
7815                  IF ( zdirs(k) == 0._wp )  THEN ! ray is exactly horizontal
7816                     nz = 2
7817                     rt2_dist(nz) = SQRT(dxxyy)
7818                     iz = CEILING(-.5_wp + zorig, iwp)
7819                  ELSE
7820                     zexit = MIN(MAX(origin(1) + zdirs(k) * rt2_track_dist(i), zbottom), ztop)
7821
7822                     zb0 = FLOOR(  zorig * zsgn - .5_wp) + 1  ! because it must be greater than orig
7823                     zb1 = CEILING(zexit * zsgn - .5_wp) - 1  ! because it must be smaller than exit
7824                     nz = MAX(zb1 - zb0 + 3, 2)
7825                     rt2_dist(nz) = SQRT(((zexit-zorig)*dz(1))**2 + dxxyy)
7826                     qdist = rt2_dist(nz) / (zexit-zorig)
7827                     rt2_dist(2:nz-1) = (/( ((REAL(l, wp) + .5_wp) * zsgn - zorig) * qdist , l = zb0, zb1 )/)
7828                     iz = zb0 * zsgn
7829                  ENDIF
7830
7831                  DO  l = 2, nz
7832                     IF ( rt2_track_lad(iz, i) > 0._wp )  THEN
7833                        curtrans = exp(-ext_coef * rt2_track_lad(iz, i) * (rt2_dist(l)-rt2_dist(l-1)))
7834
7835                        IF ( create_csf )  THEN
7836                           ncsfl = ncsfl + 1
7837                           acsf(ncsfl)%ip = ip
7838                           acsf(ncsfl)%itx = rt2_track(2,i)
7839                           acsf(ncsfl)%ity = rt2_track(1,i)
7840                           acsf(ncsfl)%itz = iz
7841                           acsf(ncsfl)%isurfs = iorig
7842                           acsf(ncsfl)%rcvf = (1._wp - curtrans)*transparency(k)*vffrac(k)
7843                        ENDIF
7844
7845                        transparency(k) = transparency(k) * curtrans
7846                     ENDIF
7847                     iz = iz + zsgn
7848                  ENDDO ! l = 1, nz - 1
7849               ENDDO ! k = 1, nrays
7850            ENDDO ! i = 1, ntrack
7851
7852            transparency(1:lowest_free_ray) = 1._wp !-- Reset rays above horizon to transparent (see NOTE 6778)
7853         ENDIF
7854
7855!--      Forward direction of radiation (sky->face), always
7856!--     
7857         DO  i = ntrack, 1, -1 ! for each column backwards
7858            dxxyy = ((dy*yxdir(1))**2 + (dx*yxdir(2))**2) * (rt2_track_dist(i)-rt2_track_dist(i-1))**2
7859            px = rt2_track(2,i)/nnx
7860            py = rt2_track(1,i)/nny
7861            ip = px*pdims(2)+py
7862
7863            DO  k = 1, nrays ! for each ray
7864!
7865!--            See NOTE 6778 above
7866               IF ( zdirs(k) <= horizon )  CYCLE
7867
7868               zexit = origin(1) + zdirs(k) * rt2_track_dist(i-1)
7869               IF ( zexit <= zbottom  .OR.  zexit >= ztop )  CYCLE
7870
7871               zsgn = -INT(SIGN(1._wp, zdirs(k)), iwp)
7872               rt2_dist(1) = 0._wp
7873               IF ( zdirs(k) == 0._wp )  THEN ! ray is exactly horizontal
7874                  nz = 2
7875                  rt2_dist(nz) = SQRT(dxxyy)
7876                  iz = NINT(zexit, iwp)
7877               ELSE
7878                  zorig = MIN(MAX(origin(1) + zdirs(k) * rt2_track_dist(i), zbottom), ztop)
7879
7880                  zb0 = FLOOR(  zorig * zsgn - .5_wp) + 1  ! because it must be greater than orig
7881                  zb1 = CEILING(zexit * zsgn - .5_wp) - 1  ! because it must be smaller than exit
7882                  nz = MAX(zb1 - zb0 + 3, 2)
7883                  rt2_dist(nz) = SQRT(((zexit-zorig)*dz(1))**2 + dxxyy)
7884                  qdist = rt2_dist(nz) / (zexit-zorig)
7885                  rt2_dist(2:nz-1) = (/( ((REAL(l, wp) + .5_wp) * zsgn - zorig) * qdist , l = zb0, zb1 )/)
7886                  iz = zb0 * zsgn
7887               ENDIF
7888
7889               DO  l = 2, nz
7890                  IF ( rt2_track_lad(iz, i) > 0._wp )  THEN
7891                     curtrans = exp(-ext_coef * rt2_track_lad(iz, i) * (rt2_dist(l)-rt2_dist(l-1)))
7892
7893                     IF ( create_csf )  THEN
7894                        ncsfl = ncsfl + 1
7895                        acsf(ncsfl)%ip = ip
7896                        acsf(ncsfl)%itx = rt2_track(2,i)
7897                        acsf(ncsfl)%ity = rt2_track(1,i)
7898                        acsf(ncsfl)%itz = iz
7899                        IF ( itarget(k) /= -1 )  ERROR STOP !FIXME remove after test
7900                        acsf(ncsfl)%isurfs = -1
7901                        acsf(ncsfl)%rcvf = (1._wp - curtrans)*transparency(k)*aorig*vffrac(k)
7902                     ENDIF  ! create_csf
7903
7904                     transparency(k) = transparency(k) * curtrans
7905                  ENDIF
7906                  iz = iz + zsgn
7907               ENDDO ! l = 1, nz - 1
7908            ENDDO ! k = 1, nrays
7909         ENDDO ! i = 1, ntrack
7910      ENDIF ! plant_canopy
7911
7912      IF ( .NOT. (rad_angular_discretization  .AND.  calc_svf) )  THEN
7913!
7914!--      Just update lowest_free_ray according to horizon
7915         DO WHILE ( lowest_free_ray > 0 )
7916            IF ( zdirs(lowest_free_ray) > horizon )  EXIT
7917            lowest_free_ray = lowest_free_ray - 1
7918         ENDDO
7919      ENDIF
7920
7921   CONTAINS
7922
7923      SUBROUTINE request_itarget( d, z, y, x, isurfl, iproc )
7924
7925         INTEGER(iwp), INTENT(in)            ::  d, z, y, x
7926         INTEGER(iwp), TARGET, INTENT(out)   ::  isurfl
7927         INTEGER(iwp), INTENT(out)           ::  iproc
7928#if defined( __parallel )
7929#else
7930         INTEGER(iwp)                        ::  target_displ  !< index of the grid in the local gridsurf array
7931#endif
7932         INTEGER(iwp)                        ::  px, py        !< number of processors in x and y direction
7933                                                               !< before the processor in the question
7934#if defined( __parallel )
7935         INTEGER(KIND=MPI_ADDRESS_KIND)      ::  target_displ  !< index of the grid in the local gridsurf array
7936
7937!
7938!--      Calculate target processor and index in the remote local target gridsurf array
7939         px = x / nnx
7940         py = y / nny
7941         iproc = px * pdims(2) + py
7942         target_displ = ((x-px*nnx) * nny + y - py*nny ) * nzu * nsurf_type_u +&
7943                        ( z-nzub ) * nsurf_type_u + d
7944!
7945!--      Send MPI_Get request to obtain index target_surfl(i)
7946         CALL MPI_GET( isurfl, 1, MPI_INTEGER, iproc, target_displ,            &
7947                       1, MPI_INTEGER, win_gridsurf, ierr)
7948         IF ( ierr /= 0 )  THEN
7949            WRITE( 9,* ) 'Error MPI_Get3:', ierr, isurfl, iproc, target_displ, &
7950                         win_gridsurf
7951            FLUSH( 9 )
7952         ENDIF
7953#else
7954!--      set index target_surfl(i)
7955         isurfl = gridsurf(d,z,y,x)
7956#endif
7957
7958      END SUBROUTINE request_itarget
7959
7960   END SUBROUTINE raytrace_2d
7961 
7962
7963!------------------------------------------------------------------------------!
7964!
7965! Description:
7966! ------------
7967!> Calculates apparent solar positions for all timesteps and stores discretized
7968!> positions.
7969!------------------------------------------------------------------------------!
7970   SUBROUTINE radiation_presimulate_solar_pos
7971      IMPLICIT NONE
7972
7973      INTEGER(iwp)                              ::  it, i, j
7974      REAL(wp)                                  ::  tsrp_prev
7975      REAL(wp)                                  ::  simulated_time_prev
7976      REAL(wp), DIMENSION(:,:), ALLOCATABLE     ::  dsidir_tmp       !< dsidir_tmp[:,i] = unit vector of i-th
7977                                                                     !< appreant solar direction
7978
7979      ALLOCATE ( dsidir_rev(0:raytrace_discrete_elevs/2-1,                 &
7980                            0:raytrace_discrete_azims-1) )
7981      dsidir_rev(:,:) = -1
7982      ALLOCATE ( dsidir_tmp(3,                                             &
7983                     raytrace_discrete_elevs/2*raytrace_discrete_azims) )
7984      ndsidir = 0
7985
7986!
7987!--   We will artificialy update time_since_reference_point and return to
7988!--   true value later
7989      tsrp_prev = time_since_reference_point
7990      simulated_time_prev = simulated_time
7991      sun_direction = .TRUE.
7992
7993!
7994!--   Process spinup time if configured
7995      IF ( spinup_time > 0._wp )  THEN
7996         DO  it = 0, CEILING(spinup_time / dt_spinup)
7997            time_since_reference_point = -spinup_time + REAL(it, wp) * dt_spinup
7998            simulated_time = simulated_time + dt_spinup
7999            CALL simulate_pos
8000         ENDDO
8001      ENDIF
8002!
8003!--   Process simulation time
8004      DO  it = 0, CEILING(( end_time - spinup_time ) / dt_radiation)
8005         time_since_reference_point = REAL(it, wp) * dt_radiation
8006         simulated_time = simulated_time + dt_spinup
8007         CALL simulate_pos
8008      ENDDO
8009
8010      time_since_reference_point = tsrp_prev
8011      simulated_time = simulated_time_prev
8012
8013!--   Allocate global vars which depend on ndsidir
8014      ALLOCATE ( dsidir ( 3, ndsidir ) )
8015      dsidir(:,:) = dsidir_tmp(:, 1:ndsidir)
8016      DEALLOCATE ( dsidir_tmp )
8017
8018      ALLOCATE ( dsitrans(nsurfl, ndsidir) )
8019      ALLOCATE ( dsitransc(npcbl, ndsidir) )
8020      IF ( nmrtbl > 0 )  ALLOCATE ( mrtdsit(nmrtbl, ndsidir) )
8021
8022      WRITE ( message_string, * ) 'Precalculated', ndsidir, ' solar positions', &
8023                                  'from', it, ' timesteps.'
8024      CALL message( 'radiation_presimulate_solar_pos', 'UI0013', 0, 0, 0, 6, 0 )
8025
8026      CONTAINS
8027
8028      !------------------------------------------------------------------------!
8029      ! Description:
8030      ! ------------
8031      !> Simuates a single position
8032      !------------------------------------------------------------------------!
8033      SUBROUTINE simulate_pos
8034         IMPLICIT NONE
8035!
8036!--      Update apparent solar position based on modified t_s_r_p
8037         CALL calc_zenith
8038         IF ( zenith(0) > 0 )  THEN
8039!--         
8040!--         Identify solar direction vector (discretized number) 1)
8041            i = MODULO(NINT(ATAN2(sun_dir_lon(0), sun_dir_lat(0))               &
8042                            / (2._wp*pi) * raytrace_discrete_azims-.5_wp, iwp), &
8043                       raytrace_discrete_azims)
8044            j = FLOOR(ACOS(zenith(0)) / pi * raytrace_discrete_elevs)
8045            IF ( dsidir_rev(j, i) == -1 )  THEN
8046               ndsidir = ndsidir + 1
8047               dsidir_tmp(:, ndsidir) =                                              &
8048                     (/ COS((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs), &
8049                        SIN((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs)  &
8050                      * COS((REAL(i,wp)+.5_wp) * 2_wp*pi / raytrace_discrete_azims), &
8051                        SIN((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs)  &
8052                      * SIN((REAL(i,wp)+.5_wp) * 2_wp*pi / raytrace_discrete_azims) /)
8053               dsidir_rev(j, i) = ndsidir
8054            ENDIF
8055         ENDIF
8056      END SUBROUTINE simulate_pos
8057
8058   END SUBROUTINE radiation_presimulate_solar_pos
8059
8060
8061
8062!------------------------------------------------------------------------------!
8063! Description:
8064! ------------
8065!> Determines whether two faces are oriented towards each other. Since the
8066!> surfaces follow the gird box surfaces, it checks first whether the two surfaces
8067!> are directed in the same direction, then it checks if the two surfaces are
8068!> located in confronted direction but facing away from each other, e.g. <--| |-->
8069!------------------------------------------------------------------------------!
8070    PURE LOGICAL FUNCTION surface_facing(x, y, z, d, x2, y2, z2, d2)
8071        IMPLICIT NONE
8072        INTEGER(iwp),   INTENT(in)  :: x, y, z, d, x2, y2, z2, d2
8073     
8074        surface_facing = .FALSE.
8075
8076!-- first check: are the two surfaces directed in the same direction
8077        IF ( (d==iup_u  .OR.  d==iup_l )                             &
8078             .AND. (d2==iup_u  .OR. d2==iup_l) ) RETURN
8079        IF ( (d==isouth_u  .OR.  d==isouth_l ) &
8080             .AND.  (d2==isouth_u  .OR.  d2==isouth_l) ) RETURN
8081        IF ( (d==inorth_u  .OR.  d==inorth_l ) &
8082             .AND.  (d2==inorth_u  .OR.  d2==inorth_l) ) RETURN
8083        IF ( (d==iwest_u  .OR.  d==iwest_l )     &
8084             .AND.  (d2==iwest_u  .OR.  d2==iwest_l ) ) RETURN
8085        IF ( (d==ieast_u  .OR.  d==ieast_l )     &
8086             .AND.  (d2==ieast_u  .OR.  d2==ieast_l ) ) RETURN
8087
8088!-- second check: are surfaces facing away from each other
8089        SELECT CASE (d)
8090            CASE (iup_u, iup_l)                     !< upward facing surfaces
8091                IF ( z2 < z ) RETURN
8092            CASE (isouth_u, isouth_l)               !< southward facing surfaces
8093                IF ( y2 > y ) RETURN
8094            CASE (inorth_u, inorth_l)               !< northward facing surfaces
8095                IF ( y2 < y ) RETURN
8096            CASE (iwest_u, iwest_l)                 !< westward facing surfaces
8097                IF ( x2 > x ) RETURN
8098            CASE (ieast_u, ieast_l)                 !< eastward facing surfaces
8099                IF ( x2 < x ) RETURN
8100        END SELECT
8101
8102        SELECT CASE (d2)
8103            CASE (iup_u)                            !< ground, roof
8104                IF ( z < z2 ) RETURN
8105            CASE (isouth_u, isouth_l)               !< south facing
8106                IF ( y > y2 ) RETURN
8107            CASE (inorth_u, inorth_l)               !< north facing
8108                IF ( y < y2 ) RETURN
8109            CASE (iwest_u, iwest_l)                 !< west facing
8110                IF ( x > x2 ) RETURN
8111            CASE (ieast_u, ieast_l)                 !< east facing
8112                IF ( x < x2 ) RETURN
8113            CASE (-1)
8114                CONTINUE
8115        END SELECT
8116
8117        surface_facing = .TRUE.
8118       
8119    END FUNCTION surface_facing
8120
8121
8122!------------------------------------------------------------------------------!
8123!
8124! Description:
8125! ------------
8126!> Soubroutine reads svf and svfsurf data from saved file
8127!> SVF means sky view factors and CSF means canopy sink factors
8128!------------------------------------------------------------------------------!
8129    SUBROUTINE radiation_read_svf
8130
8131       IMPLICIT NONE
8132       
8133       CHARACTER(rad_version_len)   :: rad_version_field
8134       
8135       INTEGER(iwp)                 :: i
8136       INTEGER(iwp)                 :: ndsidir_from_file = 0
8137       INTEGER(iwp)                 :: npcbl_from_file = 0
8138       INTEGER(iwp)                 :: nsurfl_from_file = 0
8139       
8140       DO  i = 0, io_blocks-1
8141          IF ( i == io_group )  THEN
8142
8143!
8144!--          numprocs_previous_run is only known in case of reading restart
8145!--          data. If a new initial run which reads svf data is started the
8146!--          following query will be skipped
8147             IF ( initializing_actions == 'read_restart_data' ) THEN
8148
8149                IF ( numprocs_previous_run /= numprocs ) THEN
8150                   WRITE( message_string, * ) 'A different number of ',        &
8151                                              'processors between the run ',   &
8152                                              'that has written the svf data ',&
8153                                              'and the one that will read it ',&
8154                                              'is not allowed' 
8155                   CALL message( 'check_open', 'PA0491', 1, 2, 0, 6, 0 )
8156                ENDIF
8157
8158             ENDIF
8159             
8160!
8161!--          Open binary file
8162             CALL check_open( 88 )
8163
8164!
8165!--          read and check version
8166             READ ( 88 ) rad_version_field
8167             IF ( TRIM(rad_version_field) /= TRIM(rad_version) )  THEN
8168                 WRITE( message_string, * ) 'Version of binary SVF file "',    &
8169                             TRIM(rad_version_field), '" does not match ',     &
8170                             'the version of model "', TRIM(rad_version), '"'
8171                 CALL message( 'radiation_read_svf', 'PA0482', 1, 2, 0, 6, 0 )
8172             ENDIF
8173             
8174!
8175!--          read nsvfl, ncsfl, nsurfl
8176             READ ( 88 ) nsvfl, ncsfl, nsurfl_from_file, npcbl_from_file,      &
8177                         ndsidir_from_file
8178             
8179             IF ( nsvfl < 0  .OR.  ncsfl < 0 )  THEN
8180                 WRITE( message_string, * ) 'Wrong number of SVF or CSF'
8181                 CALL message( 'radiation_read_svf', 'PA0483', 1, 2, 0, 6, 0 )
8182             ELSE
8183                 WRITE(message_string,*) '    Number of SVF, CSF, and nsurfl ',&
8184                                         'to read', nsvfl, ncsfl,              &
8185                                         nsurfl_from_file
8186                 CALL location_message( message_string, .TRUE. )
8187             ENDIF
8188             
8189             IF ( nsurfl_from_file /= nsurfl )  THEN
8190                 WRITE( message_string, * ) 'nsurfl from SVF file does not ',  &
8191                                            'match calculated nsurfl from ',   &
8192                                            'radiation_interaction_init'
8193                 CALL message( 'radiation_read_svf', 'PA0490', 1, 2, 0, 6, 0 )
8194             ENDIF
8195             
8196             IF ( npcbl_from_file /= npcbl )  THEN
8197                 WRITE( message_string, * ) 'npcbl from SVF file does not ',   &
8198                                            'match calculated npcbl from ',    &
8199                                            'radiation_interaction_init'
8200                 CALL message( 'radiation_read_svf', 'PA0493', 1, 2, 0, 6, 0 )
8201             ENDIF
8202             
8203             IF ( ndsidir_from_file /= ndsidir )  THEN
8204                 WRITE( message_string, * ) 'ndsidir from SVF file does not ', &
8205                                            'match calculated ndsidir from ',  &
8206                                            'radiation_presimulate_solar_pos'
8207                 CALL message( 'radiation_read_svf', 'PA0494', 1, 2, 0, 6, 0 )
8208             ENDIF
8209             
8210!
8211!--          Arrays skyvf, skyvft, dsitrans and dsitransc are allready
8212!--          allocated in radiation_interaction_init and
8213!--          radiation_presimulate_solar_pos
8214             IF ( nsurfl > 0 )  THEN
8215                READ(88) skyvf
8216                READ(88) skyvft
8217                READ(88) dsitrans 
8218             ENDIF
8219             
8220             IF ( plant_canopy  .AND.  npcbl > 0 ) THEN
8221                READ ( 88 )  dsitransc
8222             ENDIF
8223             
8224!
8225!--          The allocation of svf, svfsurf, csf and csfsurf happens in routine
8226!--          radiation_calc_svf which is not called if the program enters
8227!--          radiation_read_svf. Therefore these arrays has to allocate in the
8228!--          following
8229             IF ( nsvfl > 0 )  THEN
8230                ALLOCATE( svf(ndsvf,nsvfl) )
8231                ALLOCATE( svfsurf(idsvf,nsvfl) )
8232                READ(88) svf
8233                READ(88) svfsurf
8234             ENDIF
8235
8236             IF ( plant_canopy  .AND.  ncsfl > 0 )  THEN
8237                ALLOCATE( csf(ndcsf,ncsfl) )
8238                ALLOCATE( csfsurf(idcsf,ncsfl) )
8239                READ(88) csf
8240                READ(88) csfsurf
8241             ENDIF
8242             
8243!
8244!--          Close binary file                 
8245             CALL close_file( 88 )
8246               
8247          ENDIF
8248#if defined( __parallel )
8249          CALL MPI_BARRIER( comm2d, ierr )
8250#endif
8251       ENDDO
8252
8253    END SUBROUTINE radiation_read_svf
8254
8255
8256!------------------------------------------------------------------------------!
8257!
8258! Description:
8259! ------------
8260!> Subroutine stores svf, svfsurf, csf and csfsurf data to a file.
8261!------------------------------------------------------------------------------!
8262    SUBROUTINE radiation_write_svf
8263
8264       IMPLICIT NONE
8265       
8266       INTEGER(iwp)        :: i
8267
8268       DO  i = 0, io_blocks-1
8269          IF ( i == io_group )  THEN
8270!
8271!--          Open binary file
8272             CALL check_open( 89 )
8273
8274             WRITE ( 89 )  rad_version
8275             WRITE ( 89 )  nsvfl, ncsfl, nsurfl, npcbl, ndsidir
8276             IF ( nsurfl > 0 ) THEN
8277                WRITE ( 89 )  skyvf
8278                WRITE ( 89 )  skyvft
8279                WRITE ( 89 )  dsitrans
8280             ENDIF
8281             IF ( npcbl > 0 ) THEN
8282                WRITE ( 89 )  dsitransc
8283             ENDIF
8284             IF ( nsvfl > 0 ) THEN
8285                WRITE ( 89 )  svf
8286                WRITE ( 89 )  svfsurf
8287             ENDIF
8288             IF ( plant_canopy  .AND.  ncsfl > 0 )  THEN
8289                 WRITE ( 89 )  csf
8290                 WRITE ( 89 )  csfsurf
8291             ENDIF
8292
8293!
8294!--          Close binary file                 
8295             CALL close_file( 89 )
8296
8297          ENDIF
8298#if defined( __parallel )
8299          CALL MPI_BARRIER( comm2d, ierr )
8300#endif
8301       ENDDO
8302    END SUBROUTINE radiation_write_svf
8303
8304!------------------------------------------------------------------------------!
8305!
8306! Description:
8307! ------------
8308!> Block of auxiliary subroutines:
8309!> 1. quicksort and corresponding comparison
8310!> 2. merge_and_grow_csf for implementation of "dynamical growing"
8311!>    array for csf
8312!------------------------------------------------------------------------------!
8313!-- quicksort.f -*-f90-*-
8314!-- Author: t-nissie, adaptation J.Resler
8315!-- License: GPLv3
8316!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8317    RECURSIVE SUBROUTINE quicksort_itarget(itarget, vffrac, ztransp, first, last)
8318        IMPLICIT NONE
8319        INTEGER(iwp), DIMENSION(:), INTENT(INOUT)   :: itarget
8320        REAL(wp), DIMENSION(:), INTENT(INOUT)       :: vffrac, ztransp
8321        INTEGER(iwp), INTENT(IN)                    :: first, last
8322        INTEGER(iwp)                                :: x, t
8323        INTEGER(iwp)                                :: i, j
8324        REAL(wp)                                    :: tr
8325
8326        IF ( first>=last ) RETURN
8327        x = itarget((first+last)/2)
8328        i = first
8329        j = last
8330        DO
8331            DO WHILE ( itarget(i) < x )
8332               i=i+1
8333            ENDDO
8334            DO WHILE ( x < itarget(j) )
8335                j=j-1
8336            ENDDO
8337            IF ( i >= j ) EXIT
8338            t = itarget(i);  itarget(i) = itarget(j);  itarget(j) = t
8339            tr = vffrac(i);  vffrac(i) = vffrac(j);  vffrac(j) = tr
8340            tr = ztransp(i);  ztransp(i) = ztransp(j);  ztransp(j) = tr
8341            i=i+1
8342            j=j-1
8343        ENDDO
8344        IF ( first < i-1 ) CALL quicksort_itarget(itarget, vffrac, ztransp, first, i-1)
8345        IF ( j+1 < last )  CALL quicksort_itarget(itarget, vffrac, ztransp, j+1, last)
8346    END SUBROUTINE quicksort_itarget
8347
8348    PURE FUNCTION svf_lt(svf1,svf2) result (res)
8349      TYPE (t_svf), INTENT(in) :: svf1,svf2
8350      LOGICAL                  :: res
8351      IF ( svf1%isurflt < svf2%isurflt  .OR.    &
8352          (svf1%isurflt == svf2%isurflt  .AND.  svf1%isurfs < svf2%isurfs) )  THEN
8353          res = .TRUE.
8354      ELSE
8355          res = .FALSE.
8356      ENDIF
8357    END FUNCTION svf_lt
8358
8359
8360!-- quicksort.f -*-f90-*-
8361!-- Author: t-nissie, adaptation J.Resler
8362!-- License: GPLv3
8363!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8364    RECURSIVE SUBROUTINE quicksort_svf(svfl, first, last)
8365        IMPLICIT NONE
8366        TYPE(t_svf), DIMENSION(:), INTENT(INOUT)  :: svfl
8367        INTEGER(iwp), INTENT(IN)                  :: first, last
8368        TYPE(t_svf)                               :: x, t
8369        INTEGER(iwp)                              :: i, j
8370
8371        IF ( first>=last ) RETURN
8372        x = svfl( (first+last) / 2 )
8373        i = first
8374        j = last
8375        DO
8376            DO while ( svf_lt(svfl(i),x) )
8377               i=i+1
8378            ENDDO
8379            DO while ( svf_lt(x,svfl(j)) )
8380                j=j-1
8381            ENDDO
8382            IF ( i >= j ) EXIT
8383            t = svfl(i);  svfl(i) = svfl(j);  svfl(j) = t
8384            i=i+1
8385            j=j-1
8386        ENDDO
8387        IF ( first < i-1 ) CALL quicksort_svf(svfl, first, i-1)
8388        IF ( j+1 < last )  CALL quicksort_svf(svfl, j+1, last)
8389    END SUBROUTINE quicksort_svf
8390
8391    PURE FUNCTION csf_lt(csf1,csf2) result (res)
8392      TYPE (t_csf), INTENT(in) :: csf1,csf2
8393      LOGICAL                  :: res
8394      IF ( csf1%ip < csf2%ip  .OR.    &
8395           (csf1%ip == csf2%ip  .AND.  csf1%itx < csf2%itx)  .OR.  &
8396           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity < csf2%ity)  .OR.  &
8397           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity == csf2%ity  .AND.   &
8398            csf1%itz < csf2%itz)  .OR.  &
8399           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity == csf2%ity  .AND.   &
8400            csf1%itz == csf2%itz  .AND.  csf1%isurfs < csf2%isurfs) )  THEN
8401          res = .TRUE.
8402      ELSE
8403          res = .FALSE.
8404      ENDIF
8405    END FUNCTION csf_lt
8406
8407
8408!-- quicksort.f -*-f90-*-
8409!-- Author: t-nissie, adaptation J.Resler
8410!-- License: GPLv3
8411!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8412    RECURSIVE SUBROUTINE quicksort_csf(csfl, first, last)
8413        IMPLICIT NONE
8414        TYPE(t_csf), DIMENSION(:), INTENT(INOUT)  :: csfl
8415        INTEGER(iwp), INTENT(IN)                  :: first, last
8416        TYPE(t_csf)                               :: x, t
8417        INTEGER(iwp)                              :: i, j
8418
8419        IF ( first>=last ) RETURN
8420        x = csfl( (first+last)/2 )
8421        i = first
8422        j = last
8423        DO
8424            DO while ( csf_lt(csfl(i),x) )
8425                i=i+1
8426            ENDDO
8427            DO while ( csf_lt(x,csfl(j)) )
8428                j=j-1
8429            ENDDO
8430            IF ( i >= j ) EXIT
8431            t = csfl(i);  csfl(i) = csfl(j);  csfl(j) = t
8432            i=i+1
8433            j=j-1
8434        ENDDO
8435        IF ( first < i-1 ) CALL quicksort_csf(csfl, first, i-1)
8436        IF ( j+1 < last )  CALL quicksort_csf(csfl, j+1, last)
8437    END SUBROUTINE quicksort_csf
8438
8439   
8440    SUBROUTINE merge_and_grow_csf(newsize)
8441        INTEGER(iwp), INTENT(in)                :: newsize  !< new array size after grow, must be >= ncsfl
8442                                                            !< or -1 to shrink to minimum
8443        INTEGER(iwp)                            :: iread, iwrite
8444        TYPE(t_csf), DIMENSION(:), POINTER      :: acsfnew
8445        CHARACTER(100)                          :: msg
8446
8447        IF ( newsize == -1 )  THEN
8448!--         merge in-place
8449            acsfnew => acsf
8450        ELSE
8451!--         allocate new array
8452            IF ( mcsf == 0 )  THEN
8453                ALLOCATE( acsf1(newsize) )
8454                acsfnew => acsf1
8455            ELSE
8456                ALLOCATE( acsf2(newsize) )
8457                acsfnew => acsf2
8458            ENDIF
8459        ENDIF
8460
8461        IF ( ncsfl >= 1 )  THEN
8462!--         sort csf in place (quicksort)
8463            CALL quicksort_csf(acsf,1,ncsfl)
8464
8465!--         while moving to a new array, aggregate canopy sink factor records with identical box & source
8466            acsfnew(1) = acsf(1)
8467            iwrite = 1
8468            DO iread = 2, ncsfl
8469!--             here acsf(kcsf) already has values from acsf(icsf)
8470                IF ( acsfnew(iwrite)%itx == acsf(iread)%itx &
8471                         .AND.  acsfnew(iwrite)%ity == acsf(iread)%ity &
8472                         .AND.  acsfnew(iwrite)%itz == acsf(iread)%itz &
8473                         .AND.  acsfnew(iwrite)%isurfs == acsf(iread)%isurfs )  THEN
8474
8475                    acsfnew(iwrite)%rcvf = acsfnew(iwrite)%rcvf + acsf(iread)%rcvf
8476!--                 advance reading index, keep writing index
8477                ELSE
8478!--                 not identical, just advance and copy
8479                    iwrite = iwrite + 1
8480                    acsfnew(iwrite) = acsf(iread)
8481                ENDIF
8482            ENDDO
8483            ncsfl = iwrite
8484        ENDIF
8485
8486        IF ( newsize == -1 )  THEN
8487!--         allocate new array and copy shrinked data
8488            IF ( mcsf == 0 )  THEN
8489                ALLOCATE( acsf1(ncsfl) )
8490                acsf1(1:ncsfl) = acsf2(1:ncsfl)
8491            ELSE
8492                ALLOCATE( acsf2(ncsfl) )
8493                acsf2(1:ncsfl) = acsf1(1:ncsfl)
8494            ENDIF
8495        ENDIF
8496
8497!--     deallocate old array
8498        IF ( mcsf == 0 )  THEN
8499            mcsf = 1
8500            acsf => acsf1
8501            DEALLOCATE( acsf2 )
8502        ELSE
8503            mcsf = 0
8504            acsf => acsf2
8505            DEALLOCATE( acsf1 )
8506        ENDIF
8507        ncsfla = newsize
8508
8509        WRITE(msg,'(A,2I12)') 'Grow acsf2:',ncsfl,ncsfla
8510        CALL radiation_write_debug_log( msg )
8511
8512    END SUBROUTINE merge_and_grow_csf
8513
8514   
8515!-- quicksort.f -*-f90-*-
8516!-- Author: t-nissie, adaptation J.Resler
8517!-- License: GPLv3
8518!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8519    RECURSIVE SUBROUTINE quicksort_csf2(kpcsflt, pcsflt, first, last)
8520        IMPLICIT NONE
8521        INTEGER(iwp), DIMENSION(:,:), INTENT(INOUT)  :: kpcsflt
8522        REAL(wp), DIMENSION(:,:), INTENT(INOUT)      :: pcsflt
8523        INTEGER(iwp), INTENT(IN)                     :: first, last
8524        REAL(wp), DIMENSION(ndcsf)                   :: t2
8525        INTEGER(iwp), DIMENSION(kdcsf)               :: x, t1
8526        INTEGER(iwp)                                 :: i, j
8527
8528        IF ( first>=last ) RETURN
8529        x = kpcsflt(:, (first+last)/2 )
8530        i = first
8531        j = last
8532        DO
8533            DO while ( csf_lt2(kpcsflt(:,i),x) )
8534                i=i+1
8535            ENDDO
8536            DO while ( csf_lt2(x,kpcsflt(:,j)) )
8537                j=j-1
8538            ENDDO
8539            IF ( i >= j ) EXIT
8540            t1 = kpcsflt(:,i);  kpcsflt(:,i) = kpcsflt(:,j);  kpcsflt(:,j) = t1
8541            t2 = pcsflt(:,i);  pcsflt(:,i) = pcsflt(:,j);  pcsflt(:,j) = t2
8542            i=i+1
8543            j=j-1
8544        ENDDO
8545        IF ( first < i-1 ) CALL quicksort_csf2(kpcsflt, pcsflt, first, i-1)
8546        IF ( j+1 < last )  CALL quicksort_csf2(kpcsflt, pcsflt, j+1, last)
8547    END SUBROUTINE quicksort_csf2
8548   
8549
8550    PURE FUNCTION csf_lt2(item1, item2) result(res)
8551        INTEGER(iwp), DIMENSION(kdcsf), INTENT(in)  :: item1, item2
8552        LOGICAL                                     :: res
8553        res = ( (item1(3) < item2(3))                                                        &
8554             .OR.  (item1(3) == item2(3)  .AND.  item1(2) < item2(2))                            &
8555             .OR.  (item1(3) == item2(3)  .AND.  item1(2) == item2(2)  .AND.  item1(1) < item2(1)) &
8556             .OR.  (item1(3) == item2(3)  .AND.  item1(2) == item2(2)  .AND.  item1(1) == item2(1) &
8557                 .AND.  item1(4) < item2(4)) )
8558    END FUNCTION csf_lt2
8559
8560    PURE FUNCTION searchsorted(athresh, val) result(ind)
8561        REAL(wp), DIMENSION(:), INTENT(IN)  :: athresh
8562        REAL(wp), INTENT(IN)                :: val
8563        INTEGER(iwp)                        :: ind
8564        INTEGER(iwp)                        :: i
8565
8566        DO i = LBOUND(athresh, 1), UBOUND(athresh, 1)
8567            IF ( val < athresh(i) ) THEN
8568                ind = i - 1
8569                RETURN
8570            ENDIF
8571        ENDDO
8572        ind = UBOUND(athresh, 1)
8573    END FUNCTION searchsorted
8574
8575!------------------------------------------------------------------------------!
8576! Description:
8577! ------------
8578!
8579!> radiation_radflux_gridbox subroutine gives the sw and lw radiation fluxes at the
8580!> faces of a gridbox defined at i,j,k and located in the urban layer.
8581!> The total sw and the diffuse sw radiation as well as the lw radiation fluxes at
8582!> the gridbox 6 faces are stored in sw_gridbox, swd_gridbox, and lw_gridbox arrays,
8583!> respectively, in the following order:
8584!>  up_face, down_face, north_face, south_face, east_face, west_face
8585!>
8586!> The subroutine reports also how successful was the search process via the parameter
8587!> i_feedback as follow:
8588!> - i_feedback =  1 : successful
8589!> - i_feedback = -1 : unsuccessful; the requisted point is outside the urban domain
8590!> - i_feedback =  0 : uncomplete; some gridbox faces fluxes are missing
8591!>
8592!>
8593!> It is called outside from usm_urban_surface_mod whenever the radiation fluxes
8594!> are needed.
8595!>
8596!> This routine is not used so far. However, it may serve as an interface for radiation
8597!> fluxes of urban and land surfaces
8598!>
8599!> TODO:
8600!>    - Compare performance when using some combination of the Fortran intrinsic
8601!>      functions, e.g. MINLOC, MAXLOC, ALL, ANY and COUNT functions, which search
8602!>      surfl array for elements meeting user-specified criterion, i.e. i,j,k
8603!>    - Report non-found or incomplete radiation fluxes arrays , if any, at the
8604!>      gridbox faces in an error message form
8605!>
8606!------------------------------------------------------------------------------!
8607    SUBROUTINE radiation_radflux_gridbox(i,j,k,sw_gridbox,swd_gridbox,lw_gridbox,i_feedback)
8608       
8609        IMPLICIT NONE
8610
8611        INTEGER(iwp),                 INTENT(in)  :: i,j,k                 !< gridbox indices at which fluxes are required
8612        INTEGER(iwp)                              :: ii,jj,kk,d            !< surface indices and type
8613        INTEGER(iwp)                              :: l                     !< surface id
8614        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
8615        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
8616        INTEGER(iwp),                 INTENT(out) :: i_feedback            !< feedback to report how the search was successful
8617
8618
8619!-- initialize variables
8620        i_feedback  = -999999
8621        sw_gridbox  = -999999.9_wp
8622        lw_gridbox  = -999999.9_wp
8623        swd_gridbox = -999999.9_wp
8624       
8625!-- check the requisted grid indices
8626        IF ( k < nzb   .OR.  k > nzut  .OR.   &
8627             j < nysg  .OR.  j > nyng  .OR.   &
8628             i < nxlg  .OR.  i > nxrg         &
8629             ) THEN
8630           i_feedback = -1
8631           RETURN
8632        ENDIF
8633
8634!-- search for the required grid and formulate the fluxes at the 6 gridbox faces
8635        DO l = 1, nsurfl
8636            ii = surfl(ix,l)
8637            jj = surfl(iy,l)
8638            kk = surfl(iz,l)
8639
8640            IF ( ii == i  .AND.  jj == j  .AND.  kk == k ) THEN
8641               d = surfl(id,l)
8642
8643               SELECT CASE ( d )
8644
8645               CASE (iup_u,iup_l)                          !- gridbox up_facing face
8646                  sw_gridbox(1) = surfinsw(l)
8647                  lw_gridbox(1) = surfinlw(l)
8648                  swd_gridbox(1) = surfinswdif(l)
8649
8650               CASE (inorth_u,inorth_l)                    !- gridbox north_facing face
8651                  sw_gridbox(3) = surfinsw(l)
8652                  lw_gridbox(3) = surfinlw(l)
8653                  swd_gridbox(3) = surfinswdif(l)
8654
8655               CASE (isouth_u,isouth_l)                    !- gridbox south_facing face
8656                  sw_gridbox(4) = surfinsw(l)
8657                  lw_gridbox(4) = surfinlw(l)
8658                  swd_gridbox(4) = surfinswdif(l)
8659
8660               CASE (ieast_u,ieast_l)                      !- gridbox east_facing face
8661                  sw_gridbox(5) = surfinsw(l)
8662                  lw_gridbox(5) = surfinlw(l)
8663                  swd_gridbox(5) = surfinswdif(l)
8664
8665               CASE (iwest_u,iwest_l)                      !- gridbox west_facing face
8666                  sw_gridbox(6) = surfinsw(l)
8667                  lw_gridbox(6) = surfinlw(l)
8668                  swd_gridbox(6) = surfinswdif(l)
8669
8670               END SELECT
8671
8672            ENDIF
8673
8674        IF ( ALL( sw_gridbox(:)  /= -999999.9_wp )  ) EXIT
8675        ENDDO
8676
8677!-- check the completeness of the fluxes at all gidbox faces       
8678!-- TODO: report non-found or incomplete rad fluxes arrays in an error message form
8679        IF ( ANY( sw_gridbox(:)  <= -999999.9_wp )  .OR.   &
8680             ANY( swd_gridbox(:) <= -999999.9_wp )  .OR.   &
8681             ANY( lw_gridbox(:)  <= -999999.9_wp ) ) THEN
8682           i_feedback = 0
8683        ELSE
8684           i_feedback = 1
8685        ENDIF
8686       
8687        RETURN
8688       
8689    END SUBROUTINE radiation_radflux_gridbox
8690
8691!------------------------------------------------------------------------------!
8692!
8693! Description:
8694! ------------
8695!> Subroutine for averaging 3D data
8696!------------------------------------------------------------------------------!
8697SUBROUTINE radiation_3d_data_averaging( mode, variable )
8698 
8699
8700    USE control_parameters
8701
8702    USE indices
8703
8704    USE kinds
8705
8706    IMPLICIT NONE
8707
8708    CHARACTER (LEN=*) ::  mode    !<
8709    CHARACTER (LEN=*) :: variable !<
8710
8711    LOGICAL      ::  match_lsm !< flag indicating natural-type surface
8712    LOGICAL      ::  match_usm !< flag indicating urban-type surface
8713   
8714    INTEGER(iwp) ::  i !<
8715    INTEGER(iwp) ::  j !<
8716    INTEGER(iwp) ::  k !<
8717    INTEGER(iwp) ::  l, m !< index of current surface element
8718
8719    INTEGER(iwp)                                       :: ids, idsint_u, idsint_l, isurf
8720    CHARACTER(LEN=varnamelength)                       :: var
8721
8722!-- find the real name of the variable
8723    ids = -1
8724    l = -1
8725    var = TRIM(variable)
8726    DO i = 0, nd-1
8727        k = len(TRIM(var))
8728        j = len(TRIM(dirname(i)))
8729        IF ( TRIM(var(k-j+1:k)) == TRIM(dirname(i)) )  THEN
8730            ids = i
8731            idsint_u = dirint_u(ids)
8732            idsint_l = dirint_l(ids)
8733            var = var(:k-j)
8734            EXIT
8735        ENDIF
8736    ENDDO
8737    IF ( ids == -1 )  THEN
8738        var = TRIM(variable)
8739    ENDIF
8740
8741    IF ( mode == 'allocate' )  THEN
8742
8743       SELECT CASE ( TRIM( var ) )
8744!--          block of large scale (e.g. RRTMG) radiation output variables
8745             CASE ( 'rad_net*' )
8746                IF ( .NOT. ALLOCATED( rad_net_av ) )  THEN
8747                   ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
8748                ENDIF
8749                rad_net_av = 0.0_wp
8750             
8751             CASE ( 'rad_lw_in*' )
8752                IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) )  THEN
8753                   ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
8754                ENDIF
8755                rad_lw_in_xy_av = 0.0_wp
8756               
8757             CASE ( 'rad_lw_out*' )
8758                IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) )  THEN
8759                   ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
8760                ENDIF
8761                rad_lw_out_xy_av = 0.0_wp
8762               
8763             CASE ( 'rad_sw_in*' )
8764                IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) )  THEN
8765                   ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
8766                ENDIF
8767                rad_sw_in_xy_av = 0.0_wp
8768               
8769             CASE ( 'rad_sw_out*' )
8770                IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) )  THEN
8771                   ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
8772                ENDIF
8773                rad_sw_out_xy_av = 0.0_wp               
8774
8775             CASE ( 'rad_lw_in' )
8776                IF ( .NOT. ALLOCATED( rad_lw_in_av ) )  THEN
8777                   ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8778                ENDIF
8779                rad_lw_in_av = 0.0_wp
8780
8781             CASE ( 'rad_lw_out' )
8782                IF ( .NOT. ALLOCATED( rad_lw_out_av ) )  THEN
8783                   ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8784                ENDIF
8785                rad_lw_out_av = 0.0_wp
8786
8787             CASE ( 'rad_lw_cs_hr' )
8788                IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) )  THEN
8789                   ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8790                ENDIF
8791                rad_lw_cs_hr_av = 0.0_wp
8792
8793             CASE ( 'rad_lw_hr' )
8794                IF ( .NOT. ALLOCATED( rad_lw_hr_av ) )  THEN
8795                   ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8796                ENDIF
8797                rad_lw_hr_av = 0.0_wp
8798
8799             CASE ( 'rad_sw_in' )
8800                IF ( .NOT. ALLOCATED( rad_sw_in_av ) )  THEN
8801                   ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8802                ENDIF
8803                rad_sw_in_av = 0.0_wp
8804
8805             CASE ( 'rad_sw_out' )
8806                IF ( .NOT. ALLOCATED( rad_sw_out_av ) )  THEN
8807                   ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8808                ENDIF
8809                rad_sw_out_av = 0.0_wp
8810
8811             CASE ( 'rad_sw_cs_hr' )
8812                IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) )  THEN
8813                   ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8814                ENDIF
8815                rad_sw_cs_hr_av = 0.0_wp
8816
8817             CASE ( 'rad_sw_hr' )
8818                IF ( .NOT. ALLOCATED( rad_sw_hr_av ) )  THEN
8819                   ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8820                ENDIF
8821                rad_sw_hr_av = 0.0_wp
8822
8823!--          block of RTM output variables
8824             CASE ( 'rtm_rad_net' )
8825!--              array of complete radiation balance
8826                 IF ( .NOT.  ALLOCATED(surfradnet_av) )  THEN
8827                     ALLOCATE( surfradnet_av(nsurfl) )
8828                     surfradnet_av = 0.0_wp
8829                 ENDIF
8830
8831             CASE ( 'rtm_rad_insw' )
8832!--                 array of sw radiation falling to surface after i-th reflection
8833                 IF ( .NOT.  ALLOCATED(surfinsw_av) )  THEN
8834                     ALLOCATE( surfinsw_av(nsurfl) )
8835                     surfinsw_av = 0.0_wp
8836                 ENDIF
8837
8838             CASE ( 'rtm_rad_inlw' )
8839!--                 array of lw radiation falling to surface after i-th reflection
8840                 IF ( .NOT.  ALLOCATED(surfinlw_av) )  THEN
8841                     ALLOCATE( surfinlw_av(nsurfl) )
8842                     surfinlw_av = 0.0_wp
8843                 ENDIF
8844
8845             CASE ( 'rtm_rad_inswdir' )
8846!--                 array of direct sw radiation falling to surface from sun
8847                 IF ( .NOT.  ALLOCATED(surfinswdir_av) )  THEN
8848                     ALLOCATE( surfinswdir_av(nsurfl) )
8849                     surfinswdir_av = 0.0_wp
8850                 ENDIF
8851
8852             CASE ( 'rtm_rad_inswdif' )
8853!--                 array of difusion sw radiation falling to surface from sky and borders of the domain
8854                 IF ( .NOT.  ALLOCATED(surfinswdif_av) )  THEN
8855                     ALLOCATE( surfinswdif_av(nsurfl) )
8856                     surfinswdif_av = 0.0_wp
8857                 ENDIF
8858
8859             CASE ( 'rtm_rad_inswref' )
8860!--                 array of sw radiation falling to surface from reflections
8861                 IF ( .NOT.  ALLOCATED(surfinswref_av) )  THEN
8862                     ALLOCATE( surfinswref_av(nsurfl) )
8863                     surfinswref_av = 0.0_wp
8864                 ENDIF
8865
8866             CASE ( 'rtm_rad_inlwdif' )
8867!--                 array of sw radiation falling to surface after i-th reflection
8868                IF ( .NOT.  ALLOCATED(surfinlwdif_av) )  THEN
8869                     ALLOCATE( surfinlwdif_av(nsurfl) )
8870                     surfinlwdif_av = 0.0_wp
8871                 ENDIF
8872
8873             CASE ( 'rtm_rad_inlwref' )
8874!--                 array of lw radiation falling to surface from reflections
8875                 IF ( .NOT.  ALLOCATED(surfinlwref_av) )  THEN
8876                     ALLOCATE( surfinlwref_av(nsurfl) )
8877                     surfinlwref_av = 0.0_wp
8878                 ENDIF
8879
8880             CASE ( 'rtm_rad_outsw' )
8881!--                 array of sw radiation emitted from surface after i-th reflection
8882                 IF ( .NOT.  ALLOCATED(surfoutsw_av) )  THEN
8883                     ALLOCATE( surfoutsw_av(nsurfl) )
8884                     surfoutsw_av = 0.0_wp
8885                 ENDIF
8886
8887             CASE ( 'rtm_rad_outlw' )
8888!--                 array of lw radiation emitted from surface after i-th reflection
8889                 IF ( .NOT.  ALLOCATED(surfoutlw_av) )  THEN
8890                     ALLOCATE( surfoutlw_av(nsurfl) )
8891                     surfoutlw_av = 0.0_wp
8892                 ENDIF
8893             CASE ( 'rtm_rad_ressw' )
8894!--                 array of residua of sw radiation absorbed in surface after last reflection
8895                 IF ( .NOT.  ALLOCATED(surfins_av) )  THEN
8896                     ALLOCATE( surfins_av(nsurfl) )
8897                     surfins_av = 0.0_wp
8898                 ENDIF
8899
8900             CASE ( 'rtm_rad_reslw' )
8901!--                 array of residua of lw radiation absorbed in surface after last reflection
8902                 IF ( .NOT.  ALLOCATED(surfinl_av) )  THEN
8903                     ALLOCATE( surfinl_av(nsurfl) )
8904                     surfinl_av = 0.0_wp
8905                 ENDIF
8906
8907             CASE ( 'rtm_rad_pc_inlw' )
8908!--                 array of of lw radiation absorbed in plant canopy
8909                 IF ( .NOT.  ALLOCATED(pcbinlw_av) )  THEN
8910                     ALLOCATE( pcbinlw_av(1:npcbl) )
8911                     pcbinlw_av = 0.0_wp
8912                 ENDIF
8913
8914             CASE ( 'rtm_rad_pc_insw' )
8915!--                 array of of sw radiation absorbed in plant canopy
8916                 IF ( .NOT.  ALLOCATED(pcbinsw_av) )  THEN
8917                     ALLOCATE( pcbinsw_av(1:npcbl) )
8918                     pcbinsw_av = 0.0_wp
8919                 ENDIF
8920
8921             CASE ( 'rtm_rad_pc_inswdir' )
8922!--                 array of of direct sw radiation absorbed in plant canopy
8923                 IF ( .NOT.  ALLOCATED(pcbinswdir_av) )  THEN
8924                     ALLOCATE( pcbinswdir_av(1:npcbl) )
8925                     pcbinswdir_av = 0.0_wp
8926                 ENDIF
8927
8928             CASE ( 'rtm_rad_pc_inswdif' )
8929!--                 array of of diffuse sw radiation absorbed in plant canopy
8930                 IF ( .NOT.  ALLOCATED(pcbinswdif_av) )  THEN
8931                     ALLOCATE( pcbinswdif_av(1:npcbl) )
8932                     pcbinswdif_av = 0.0_wp
8933                 ENDIF
8934
8935             CASE ( 'rtm_rad_pc_inswref' )
8936!--                 array of of reflected sw radiation absorbed in plant canopy
8937                 IF ( .NOT.  ALLOCATED(pcbinswref_av) )  THEN
8938                     ALLOCATE( pcbinswref_av(1:npcbl) )
8939                     pcbinswref_av = 0.0_wp
8940                 ENDIF
8941
8942             CASE ( 'rtm_mrt_sw' )
8943                IF ( .NOT. ALLOCATED( mrtinsw_av ) )  THEN
8944                   ALLOCATE( mrtinsw_av(nmrtbl) )
8945                ENDIF
8946                mrtinsw_av = 0.0_wp
8947
8948             CASE ( 'rtm_mrt_lw' )
8949                IF ( .NOT. ALLOCATED( mrtinlw_av ) )  THEN
8950                   ALLOCATE( mrtinlw_av(nmrtbl) )
8951                ENDIF
8952                mrtinlw_av = 0.0_wp
8953
8954             CASE ( 'rtm_mrt' )
8955                IF ( .NOT. ALLOCATED( mrt_av ) )  THEN
8956                   ALLOCATE( mrt_av(nmrtbl) )
8957                ENDIF
8958                mrt_av = 0.0_wp
8959
8960          CASE DEFAULT
8961             CONTINUE
8962
8963       END SELECT
8964
8965    ELSEIF ( mode == 'sum' )  THEN
8966
8967       SELECT CASE ( TRIM( var ) )
8968!--       block of large scale (e.g. RRTMG) radiation output variables
8969          CASE ( 'rad_net*' )
8970             IF ( ALLOCATED( rad_net_av ) ) THEN
8971                DO  i = nxl, nxr
8972                   DO  j = nys, nyn
8973                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
8974                                  surf_lsm_h%end_index(j,i)
8975                      match_usm = surf_usm_h%start_index(j,i) <=               &
8976                                  surf_usm_h%end_index(j,i)
8977
8978                     IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
8979                         m = surf_lsm_h%end_index(j,i)
8980                         rad_net_av(j,i) = rad_net_av(j,i) +                   &
8981                                         surf_lsm_h%rad_net(m)
8982                      ELSEIF ( match_usm )  THEN
8983                         m = surf_usm_h%end_index(j,i)
8984                         rad_net_av(j,i) = rad_net_av(j,i) +                   &
8985                                         surf_usm_h%rad_net(m)
8986                      ENDIF
8987                   ENDDO
8988                ENDDO
8989             ENDIF
8990
8991          CASE ( 'rad_lw_in*' )
8992             IF ( ALLOCATED( rad_lw_in_xy_av ) ) THEN
8993                DO  i = nxl, nxr
8994                   DO  j = nys, nyn
8995                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
8996                                  surf_lsm_h%end_index(j,i)
8997                      match_usm = surf_usm_h%start_index(j,i) <=               &
8998                                  surf_usm_h%end_index(j,i)
8999
9000                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9001                         m = surf_lsm_h%end_index(j,i)
9002                         rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i) +         &
9003                                         surf_lsm_h%rad_lw_in(m)
9004                      ELSEIF ( match_usm )  THEN
9005                         m = surf_usm_h%end_index(j,i)
9006                         rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i) +         &
9007                                         surf_usm_h%rad_lw_in(m)
9008                      ENDIF
9009                   ENDDO
9010                ENDDO
9011             ENDIF
9012             
9013          CASE ( 'rad_lw_out*' )
9014             IF ( ALLOCATED( rad_lw_out_xy_av ) ) THEN
9015                DO  i = nxl, nxr
9016                   DO  j = nys, nyn
9017                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9018                                  surf_lsm_h%end_index(j,i)
9019                      match_usm = surf_usm_h%start_index(j,i) <=               &
9020                                  surf_usm_h%end_index(j,i)
9021
9022                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9023                         m = surf_lsm_h%end_index(j,i)
9024                         rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i) +       &
9025                                                 surf_lsm_h%rad_lw_out(m)
9026                      ELSEIF ( match_usm )  THEN
9027                         m = surf_usm_h%end_index(j,i)
9028                         rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i) +       &
9029                                                 surf_usm_h%rad_lw_out(m)
9030                      ENDIF
9031                   ENDDO
9032                ENDDO
9033             ENDIF
9034             
9035          CASE ( 'rad_sw_in*' )
9036             IF ( ALLOCATED( rad_sw_in_xy_av ) ) THEN
9037                DO  i = nxl, nxr
9038                   DO  j = nys, nyn
9039                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9040                                  surf_lsm_h%end_index(j,i)
9041                      match_usm = surf_usm_h%start_index(j,i) <=               &
9042                                  surf_usm_h%end_index(j,i)
9043
9044                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9045                         m = surf_lsm_h%end_index(j,i)
9046                         rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i) +         &
9047                                                surf_lsm_h%rad_sw_in(m)
9048                      ELSEIF ( match_usm )  THEN
9049                         m = surf_usm_h%end_index(j,i)
9050                         rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i) +         &
9051                                                surf_usm_h%rad_sw_in(m)
9052                      ENDIF
9053                   ENDDO
9054                ENDDO
9055             ENDIF
9056             
9057          CASE ( 'rad_sw_out*' )
9058             IF ( ALLOCATED( rad_sw_out_xy_av ) ) THEN
9059                DO  i = nxl, nxr
9060                   DO  j = nys, nyn
9061                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9062                                  surf_lsm_h%end_index(j,i)
9063                      match_usm = surf_usm_h%start_index(j,i) <=               &
9064                                  surf_usm_h%end_index(j,i)
9065
9066                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9067                         m = surf_lsm_h%end_index(j,i)
9068                         rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i) +       &
9069                                                 surf_lsm_h%rad_sw_out(m)
9070                      ELSEIF ( match_usm )  THEN
9071                         m = surf_usm_h%end_index(j,i)
9072                         rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i) +       &
9073                                                 surf_usm_h%rad_sw_out(m)
9074                      ENDIF
9075                   ENDDO
9076                ENDDO
9077             ENDIF
9078             
9079          CASE ( 'rad_lw_in' )
9080             IF ( ALLOCATED( rad_lw_in_av ) ) THEN
9081                DO  i = nxlg, nxrg
9082                   DO  j = nysg, nyng
9083                      DO  k = nzb, nzt+1
9084                         rad_lw_in_av(k,j,i) = rad_lw_in_av(k,j,i)             &
9085                                               + rad_lw_in(k,j,i)
9086                      ENDDO
9087                   ENDDO
9088                ENDDO
9089             ENDIF
9090
9091          CASE ( 'rad_lw_out' )
9092             IF ( ALLOCATED( rad_lw_out_av ) ) THEN
9093                DO  i = nxlg, nxrg
9094                   DO  j = nysg, nyng
9095                      DO  k = nzb, nzt+1
9096                         rad_lw_out_av(k,j,i) = rad_lw_out_av(k,j,i)           &
9097                                                + rad_lw_out(k,j,i)
9098                      ENDDO
9099                   ENDDO
9100                ENDDO
9101             ENDIF
9102
9103          CASE ( 'rad_lw_cs_hr' )
9104             IF ( ALLOCATED( rad_lw_cs_hr_av ) ) THEN
9105                DO  i = nxlg, nxrg
9106                   DO  j = nysg, nyng
9107                      DO  k = nzb, nzt+1
9108                         rad_lw_cs_hr_av(k,j,i) = rad_lw_cs_hr_av(k,j,i)       &
9109                                                  + rad_lw_cs_hr(k,j,i)
9110                      ENDDO
9111                   ENDDO
9112                ENDDO
9113             ENDIF
9114
9115          CASE ( 'rad_lw_hr' )
9116             IF ( ALLOCATED( rad_lw_hr_av ) ) THEN
9117                DO  i = nxlg, nxrg
9118                   DO  j = nysg, nyng
9119                      DO  k = nzb, nzt+1
9120                         rad_lw_hr_av(k,j,i) = rad_lw_hr_av(k,j,i)             &
9121                                               + rad_lw_hr(k,j,i)
9122                      ENDDO
9123                   ENDDO
9124                ENDDO
9125             ENDIF
9126
9127          CASE ( 'rad_sw_in' )
9128             IF ( ALLOCATED( rad_sw_in_av ) ) THEN
9129                DO  i = nxlg, nxrg
9130                   DO  j = nysg, nyng
9131                      DO  k = nzb, nzt+1
9132                         rad_sw_in_av(k,j,i) = rad_sw_in_av(k,j,i)             &
9133                                               + rad_sw_in(k,j,i)
9134                      ENDDO
9135                   ENDDO
9136                ENDDO
9137             ENDIF
9138
9139          CASE ( 'rad_sw_out' )
9140             IF ( ALLOCATED( rad_sw_out_av ) ) THEN
9141                DO  i = nxlg, nxrg
9142                   DO  j = nysg, nyng
9143                      DO  k = nzb, nzt+1
9144                         rad_sw_out_av(k,j,i) = rad_sw_out_av(k,j,i)           &
9145                                                + rad_sw_out(k,j,i)
9146                      ENDDO
9147                   ENDDO
9148                ENDDO
9149             ENDIF
9150
9151          CASE ( 'rad_sw_cs_hr' )
9152             IF ( ALLOCATED( rad_sw_cs_hr_av ) ) THEN
9153                DO  i = nxlg, nxrg
9154                   DO  j = nysg, nyng
9155                      DO  k = nzb, nzt+1
9156                         rad_sw_cs_hr_av(k,j,i) = rad_sw_cs_hr_av(k,j,i)       &
9157                                                  + rad_sw_cs_hr(k,j,i)
9158                      ENDDO
9159                   ENDDO
9160                ENDDO
9161             ENDIF
9162
9163          CASE ( 'rad_sw_hr' )
9164             IF ( ALLOCATED( rad_sw_hr_av ) ) THEN
9165                DO  i = nxlg, nxrg
9166                   DO  j = nysg, nyng
9167                      DO  k = nzb, nzt+1
9168                         rad_sw_hr_av(k,j,i) = rad_sw_hr_av(k,j,i)             &
9169                                               + rad_sw_hr(k,j,i)
9170                      ENDDO
9171                   ENDDO
9172                ENDDO
9173             ENDIF
9174
9175!--       block of RTM output variables
9176          CASE ( 'rtm_rad_net' )
9177!--           array of complete radiation balance
9178              DO isurf = dirstart(ids), dirend(ids)
9179                 IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9180                    surfradnet_av(isurf) = surfinsw(isurf) - surfoutsw(isurf) +  surfinlw(isurf) - surfoutlw(isurf)
9181                 ENDIF
9182              ENDDO
9183
9184          CASE ( 'rtm_rad_insw' )
9185!--           array of sw radiation falling to surface after i-th reflection
9186              DO isurf = dirstart(ids), dirend(ids)
9187                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9188                      surfinsw_av(isurf) = surfinsw_av(isurf) + surfinsw(isurf)
9189                  ENDIF
9190              ENDDO
9191
9192          CASE ( 'rtm_rad_inlw' )
9193!--           array of lw radiation falling to surface after i-th reflection
9194              DO isurf = dirstart(ids), dirend(ids)
9195                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9196                      surfinlw_av(isurf) = surfinlw_av(isurf) + surfinlw(isurf)
9197                  ENDIF
9198              ENDDO
9199
9200          CASE ( 'rtm_rad_inswdir' )
9201!--           array of direct sw radiation falling to surface from sun
9202              DO isurf = dirstart(ids), dirend(ids)
9203                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9204                      surfinswdir_av(isurf) = surfinswdir_av(isurf) + surfinswdir(isurf)
9205                  ENDIF
9206              ENDDO
9207
9208          CASE ( 'rtm_rad_inswdif' )
9209!--           array of difusion sw radiation falling to surface from sky and borders of the domain
9210              DO isurf = dirstart(ids), dirend(ids)
9211                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9212                      surfinswdif_av(isurf) = surfinswdif_av(isurf) + surfinswdif(isurf)
9213                  ENDIF
9214              ENDDO
9215
9216          CASE ( 'rtm_rad_inswref' )
9217!--           array of sw radiation falling to surface from reflections
9218              DO isurf = dirstart(ids), dirend(ids)
9219                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9220                      surfinswref_av(isurf) = surfinswref_av(isurf) + surfinsw(isurf) - &
9221                                          surfinswdir(isurf) - surfinswdif(isurf)
9222                  ENDIF
9223              ENDDO
9224
9225
9226          CASE ( 'rtm_rad_inlwdif' )
9227!--           array of sw radiation falling to surface after i-th reflection
9228              DO isurf = dirstart(ids), dirend(ids)
9229                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9230                      surfinlwdif_av(isurf) = surfinlwdif_av(isurf) + surfinlwdif(isurf)
9231                  ENDIF
9232              ENDDO
9233!
9234          CASE ( 'rtm_rad_inlwref' )
9235!--           array of lw radiation falling to surface from reflections
9236              DO isurf = dirstart(ids), dirend(ids)
9237                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9238                      surfinlwref_av(isurf) = surfinlwref_av(isurf) + &
9239                                          surfinlw(isurf) - surfinlwdif(isurf)
9240                  ENDIF
9241              ENDDO
9242
9243          CASE ( 'rtm_rad_outsw' )
9244!--           array of sw radiation emitted from surface after i-th reflection
9245              DO isurf = dirstart(ids), dirend(ids)
9246                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9247                      surfoutsw_av(isurf) = surfoutsw_av(isurf) + surfoutsw(isurf)
9248                  ENDIF
9249              ENDDO
9250
9251          CASE ( 'rtm_rad_outlw' )
9252!--           array of lw radiation emitted from surface after i-th reflection
9253              DO isurf = dirstart(ids), dirend(ids)
9254                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9255                      surfoutlw_av(isurf) = surfoutlw_av(isurf) + surfoutlw(isurf)
9256                  ENDIF
9257              ENDDO
9258
9259          CASE ( 'rtm_rad_ressw' )
9260!--           array of residua of sw radiation absorbed in surface after last reflection
9261              DO isurf = dirstart(ids), dirend(ids)
9262                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9263                      surfins_av(isurf) = surfins_av(isurf) + surfins(isurf)
9264                  ENDIF
9265              ENDDO
9266
9267          CASE ( 'rtm_rad_reslw' )
9268!--           array of residua of lw radiation absorbed in surface after last reflection
9269              DO isurf = dirstart(ids), dirend(ids)
9270                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9271                      surfinl_av(isurf) = surfinl_av(isurf) + surfinl(isurf)
9272                  ENDIF
9273              ENDDO
9274
9275          CASE ( 'rtm_rad_pc_inlw' )
9276              DO l = 1, npcbl
9277                 pcbinlw_av(l) = pcbinlw_av(l) + pcbinlw(l)
9278              ENDDO
9279
9280          CASE ( 'rtm_rad_pc_insw' )
9281              DO l = 1, npcbl
9282                 pcbinsw_av(l) = pcbinsw_av(l) + pcbinsw(l)
9283              ENDDO
9284
9285          CASE ( 'rtm_rad_pc_inswdir' )
9286              DO l = 1, npcbl
9287                 pcbinswdir_av(l) = pcbinswdir_av(l) + pcbinswdir(l)
9288              ENDDO
9289
9290          CASE ( 'rtm_rad_pc_inswdif' )
9291              DO l = 1, npcbl
9292                 pcbinswdif_av(l) = pcbinswdif_av(l) + pcbinswdif(l)
9293              ENDDO
9294
9295          CASE ( 'rtm_rad_pc_inswref' )
9296              DO l = 1, npcbl
9297                 pcbinswref_av(l) = pcbinswref_av(l) + pcbinsw(l) - pcbinswdir(l) - pcbinswdif(l)
9298              ENDDO
9299
9300          CASE ( 'rad_mrt_sw' )
9301             IF ( ALLOCATED( mrtinsw_av ) )  THEN
9302                mrtinsw_av(:) = mrtinsw_av(:) + mrtinsw(:)
9303             ENDIF
9304
9305          CASE ( 'rad_mrt_lw' )
9306             IF ( ALLOCATED( mrtinlw_av ) )  THEN
9307                mrtinlw_av(:) = mrtinlw_av(:) + mrtinlw(:)
9308             ENDIF
9309
9310          CASE ( 'rad_mrt' )
9311             IF ( ALLOCATED( mrt_av ) )  THEN
9312                mrt_av(:) = mrt_av(:) + mrt(:)
9313             ENDIF
9314
9315          CASE DEFAULT
9316             CONTINUE
9317
9318       END SELECT
9319
9320    ELSEIF ( mode == 'average' )  THEN
9321
9322       SELECT CASE ( TRIM( var ) )
9323!--       block of large scale (e.g. RRTMG) radiation output variables
9324          CASE ( 'rad_net*' )
9325             IF ( ALLOCATED( rad_net_av ) ) THEN
9326                DO  i = nxlg, nxrg
9327                   DO  j = nysg, nyng
9328                      rad_net_av(j,i) = rad_net_av(j,i)                        &
9329                                        / REAL( average_count_3d, KIND=wp )
9330                   ENDDO
9331                ENDDO
9332             ENDIF
9333             
9334          CASE ( 'rad_lw_in*' )
9335             IF ( ALLOCATED( rad_lw_in_xy_av ) ) THEN
9336                DO  i = nxlg, nxrg
9337                   DO  j = nysg, nyng
9338                      rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i)              &
9339                                        / REAL( average_count_3d, KIND=wp )
9340                   ENDDO
9341                ENDDO
9342             ENDIF
9343             
9344          CASE ( 'rad_lw_out*' )
9345             IF ( ALLOCATED( rad_lw_out_xy_av ) ) THEN
9346                DO  i = nxlg, nxrg
9347                   DO  j = nysg, nyng
9348                      rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i)            &
9349                                        / REAL( average_count_3d, KIND=wp )
9350                   ENDDO
9351                ENDDO
9352             ENDIF
9353             
9354          CASE ( 'rad_sw_in*' )
9355             IF ( ALLOCATED( rad_sw_in_xy_av ) ) THEN
9356                DO  i = nxlg, nxrg
9357                   DO  j = nysg, nyng
9358                      rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i)              &
9359                                        / REAL( average_count_3d, KIND=wp )
9360                   ENDDO
9361                ENDDO
9362             ENDIF
9363             
9364          CASE ( 'rad_sw_out*' )
9365             IF ( ALLOCATED( rad_sw_out_xy_av ) ) THEN
9366                DO  i = nxlg, nxrg
9367                   DO  j = nysg, nyng
9368                      rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i)             &
9369                                        / REAL( average_count_3d, KIND=wp )
9370                   ENDDO
9371                ENDDO
9372             ENDIF
9373
9374          CASE ( 'rad_lw_in' )
9375             IF ( ALLOCATED( rad_lw_in_av ) ) THEN
9376                DO  i = nxlg, nxrg
9377                   DO  j = nysg, nyng
9378                      DO  k = nzb, nzt+1
9379                         rad_lw_in_av(k,j,i) = rad_lw_in_av(k,j,i)             &
9380                                               / REAL( average_count_3d, KIND=wp )
9381                      ENDDO
9382                   ENDDO
9383                ENDDO
9384             ENDIF
9385
9386          CASE ( 'rad_lw_out' )
9387             IF ( ALLOCATED( rad_lw_out_av ) ) THEN
9388                DO  i = nxlg, nxrg
9389                   DO  j = nysg, nyng
9390                      DO  k = nzb, nzt+1
9391                         rad_lw_out_av(k,j,i) = rad_lw_out_av(k,j,i)           &
9392                                                / REAL( average_count_3d, KIND=wp )
9393                      ENDDO
9394                   ENDDO
9395                ENDDO
9396             ENDIF
9397
9398          CASE ( 'rad_lw_cs_hr' )
9399             IF ( ALLOCATED( rad_lw_cs_hr_av ) ) THEN
9400                DO  i = nxlg, nxrg
9401                   DO  j = nysg, nyng
9402                      DO  k = nzb, nzt+1
9403                         rad_lw_cs_hr_av(k,j,i) = rad_lw_cs_hr_av(k,j,i)       &
9404                                                / REAL( average_count_3d, KIND=wp )
9405                      ENDDO
9406                   ENDDO
9407                ENDDO
9408             ENDIF
9409
9410          CASE ( 'rad_lw_hr' )
9411             IF ( ALLOCATED( rad_lw_hr_av ) ) THEN
9412                DO  i = nxlg, nxrg
9413                   DO  j = nysg, nyng
9414                      DO  k = nzb, nzt+1
9415                         rad_lw_hr_av(k,j,i) = rad_lw_hr_av(k,j,i)             &
9416                                               / REAL( average_count_3d, KIND=wp )
9417                      ENDDO
9418                   ENDDO
9419                ENDDO
9420             ENDIF
9421
9422          CASE ( 'rad_sw_in' )
9423             IF ( ALLOCATED( rad_sw_in_av ) ) THEN
9424                DO  i = nxlg, nxrg
9425                   DO  j = nysg, nyng
9426                      DO  k = nzb, nzt+1
9427                         rad_sw_in_av(k,j,i) = rad_sw_in_av(k,j,i)             &
9428                                               / REAL( average_count_3d, KIND=wp )
9429                      ENDDO
9430                   ENDDO
9431                ENDDO
9432             ENDIF
9433
9434          CASE ( 'rad_sw_out' )
9435             IF ( ALLOCATED( rad_sw_out_av ) ) THEN
9436                DO  i = nxlg, nxrg
9437                   DO  j = nysg, nyng
9438                      DO  k = nzb, nzt+1
9439                         rad_sw_out_av(k,j,i) = rad_sw_out_av(k,j,i)           &
9440                                                / REAL( average_count_3d, KIND=wp )
9441                      ENDDO
9442                   ENDDO
9443                ENDDO
9444             ENDIF
9445
9446          CASE ( 'rad_sw_cs_hr' )
9447             IF ( ALLOCATED( rad_sw_cs_hr_av ) ) THEN
9448                DO  i = nxlg, nxrg
9449                   DO  j = nysg, nyng
9450                      DO  k = nzb, nzt+1
9451                         rad_sw_cs_hr_av(k,j,i) = rad_sw_cs_hr_av(k,j,i)       &
9452                                                / REAL( average_count_3d, KIND=wp )
9453                      ENDDO
9454                   ENDDO
9455                ENDDO
9456             ENDIF
9457
9458          CASE ( 'rad_sw_hr' )
9459             IF ( ALLOCATED( rad_sw_hr_av ) ) THEN
9460                DO  i = nxlg, nxrg
9461                   DO  j = nysg, nyng
9462                      DO  k = nzb, nzt+1
9463                         rad_sw_hr_av(k,j,i) = rad_sw_hr_av(k,j,i)             &
9464                                               / REAL( average_count_3d, KIND=wp )
9465                      ENDDO
9466                   ENDDO
9467                ENDDO
9468             ENDIF
9469
9470!--       block of RTM output variables
9471          CASE ( 'rtm_rad_net' )
9472!--           array of complete radiation balance
9473              DO isurf = dirstart(ids), dirend(ids)
9474                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9475                      surfradnet_av(isurf) = surfinsw_av(isurf) / REAL( average_count_3d, kind=wp )
9476                  ENDIF
9477              ENDDO
9478
9479          CASE ( 'rtm_rad_insw' )
9480!--           array of sw radiation falling to surface after i-th reflection
9481              DO isurf = dirstart(ids), dirend(ids)
9482                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9483                      surfinsw_av(isurf) = surfinsw_av(isurf) / REAL( average_count_3d, kind=wp )
9484                  ENDIF
9485              ENDDO
9486
9487          CASE ( 'rtm_rad_inlw' )
9488!--           array of lw radiation falling to surface after i-th reflection
9489              DO isurf = dirstart(ids), dirend(ids)
9490                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9491                      surfinlw_av(isurf) = surfinlw_av(isurf) / REAL( average_count_3d, kind=wp )
9492                  ENDIF
9493              ENDDO
9494
9495          CASE ( 'rtm_rad_inswdir' )
9496!--           array of direct sw radiation falling to surface from sun
9497              DO isurf = dirstart(ids), dirend(ids)
9498                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9499                      surfinswdir_av(isurf) = surfinswdir_av(isurf) / REAL( average_count_3d, kind=wp )
9500                  ENDIF
9501              ENDDO
9502
9503          CASE ( 'rtm_rad_inswdif' )
9504!--           array of difusion sw radiation falling to surface from sky and borders of the domain
9505              DO isurf = dirstart(ids), dirend(ids)
9506                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9507                      surfinswdif_av(isurf) = surfinswdif_av(isurf) / REAL( average_count_3d, kind=wp )
9508                  ENDIF
9509              ENDDO
9510
9511          CASE ( 'rtm_rad_inswref' )
9512!--           array of sw radiation falling to surface from reflections
9513              DO isurf = dirstart(ids), dirend(ids)
9514                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9515                      surfinswref_av(isurf) = surfinswref_av(isurf) / REAL( average_count_3d, kind=wp )
9516                  ENDIF
9517              ENDDO
9518
9519          CASE ( 'rtm_rad_inlwdif' )
9520!--           array of sw radiation falling to surface after i-th reflection
9521              DO isurf = dirstart(ids), dirend(ids)
9522                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9523                      surfinlwdif_av(isurf) = surfinlwdif_av(isurf) / REAL( average_count_3d, kind=wp )
9524                  ENDIF
9525              ENDDO
9526
9527          CASE ( 'rtm_rad_inlwref' )
9528!--           array of lw radiation falling to surface from reflections
9529              DO isurf = dirstart(ids), dirend(ids)
9530                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9531                      surfinlwref_av(isurf) = surfinlwref_av(isurf) / REAL( average_count_3d, kind=wp )
9532                  ENDIF
9533              ENDDO
9534
9535          CASE ( 'rtm_rad_outsw' )
9536!--           array of sw radiation emitted from surface after i-th reflection
9537              DO isurf = dirstart(ids), dirend(ids)
9538                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9539                      surfoutsw_av(isurf) = surfoutsw_av(isurf) / REAL( average_count_3d, kind=wp )
9540                  ENDIF
9541              ENDDO
9542
9543          CASE ( 'rtm_rad_outlw' )
9544!--           array of lw radiation emitted from surface after i-th reflection
9545              DO isurf = dirstart(ids), dirend(ids)
9546                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9547                      surfoutlw_av(isurf) = surfoutlw_av(isurf) / REAL( average_count_3d, kind=wp )
9548                  ENDIF
9549              ENDDO
9550
9551          CASE ( 'rtm_rad_ressw' )
9552!--           array of residua of sw radiation absorbed in surface after last reflection
9553              DO isurf = dirstart(ids), dirend(ids)
9554                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9555                      surfins_av(isurf) = surfins_av(isurf) / REAL( average_count_3d, kind=wp )
9556                  ENDIF
9557              ENDDO
9558
9559          CASE ( 'rtm_rad_reslw' )
9560!--           array of residua of lw radiation absorbed in surface after last reflection
9561              DO isurf = dirstart(ids), dirend(ids)
9562                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9563                      surfinl_av(isurf) = surfinl_av(isurf) / REAL( average_count_3d, kind=wp )
9564                  ENDIF
9565              ENDDO
9566
9567          CASE ( 'rtm_rad_pc_inlw' )
9568              DO l = 1, npcbl
9569                 pcbinlw_av(:) = pcbinlw_av(:) / REAL( average_count_3d, kind=wp )
9570              ENDDO
9571
9572          CASE ( 'rtm_rad_pc_insw' )
9573              DO l = 1, npcbl
9574                 pcbinsw_av(:) = pcbinsw_av(:) / REAL( average_count_3d, kind=wp )
9575              ENDDO
9576
9577          CASE ( 'rtm_rad_pc_inswdir' )
9578              DO l = 1, npcbl
9579                 pcbinswdir_av(:) = pcbinswdir_av(:) / REAL( average_count_3d, kind=wp )
9580              ENDDO
9581
9582          CASE ( 'rtm_rad_pc_inswdif' )
9583              DO l = 1, npcbl
9584                 pcbinswdif_av(:) = pcbinswdif_av(:) / REAL( average_count_3d, kind=wp )
9585              ENDDO
9586
9587          CASE ( 'rtm_rad_pc_inswref' )
9588              DO l = 1, npcbl
9589                 pcbinswref_av(:) = pcbinswref_av(:) / REAL( average_count_3d, kind=wp )
9590              ENDDO
9591
9592          CASE ( 'rad_mrt_lw' )
9593             IF ( ALLOCATED( mrtinlw_av ) )  THEN
9594                mrtinlw_av(:) = mrtinlw_av(:) / REAL( average_count_3d, KIND=wp )
9595             ENDIF
9596
9597          CASE ( 'rad_mrt' )
9598             IF ( ALLOCATED( mrt_av ) )  THEN
9599                mrt_av(:) = mrt_av(:) / REAL( average_count_3d, KIND=wp )
9600             ENDIF
9601
9602       END SELECT
9603
9604    ENDIF
9605
9606END SUBROUTINE radiation_3d_data_averaging
9607
9608
9609!------------------------------------------------------------------------------!
9610!
9611! Description:
9612! ------------
9613!> Subroutine defining appropriate grid for netcdf variables.
9614!> It is called out from subroutine netcdf.
9615!------------------------------------------------------------------------------!
9616SUBROUTINE radiation_define_netcdf_grid( variable, found, grid_x, grid_y, grid_z )
9617   
9618    IMPLICIT NONE
9619
9620    CHARACTER (LEN=*), INTENT(IN)  ::  variable    !<
9621    LOGICAL, INTENT(OUT)           ::  found       !<
9622    CHARACTER (LEN=*), INTENT(OUT) ::  grid_x      !<
9623    CHARACTER (LEN=*), INTENT(OUT) ::  grid_y      !<
9624    CHARACTER (LEN=*), INTENT(OUT) ::  grid_z      !<
9625
9626    CHARACTER (len=varnamelength)  :: var
9627
9628    found  = .TRUE.
9629
9630!
9631!-- Check for the grid
9632    var = TRIM(variable)
9633!-- RTM directional variables
9634    IF ( var(1:12) == 'rtm_rad_net_'  .OR.  var(1:13) == 'rtm_rad_insw_'  .OR.          &
9635         var(1:13) == 'rtm_rad_inlw_'  .OR.  var(1:16) == 'rtm_rad_inswdir_'  .OR.      &
9636         var(1:16) == 'rtm_rad_inswdif_'  .OR.  var(1:16) == 'rtm_rad_inswref_'  .OR.   &
9637         var(1:16) == 'rtm_rad_inlwdif_'  .OR.  var(1:16) == 'rtm_rad_inlwref_'  .OR.   &
9638         var(1:14) == 'rtm_rad_outsw_'  .OR.  var(1:14) == 'rtm_rad_outlw_'  .OR.       &
9639         var(1:14) == 'rtm_rad_ressw_'  .OR.  var(1:14) == 'rtm_rad_reslw_'  .OR.       &
9640         var == 'rtm_rad_pc_inlw'  .OR.                                                 &
9641         var == 'rtm_rad_pc_insw'  .OR.  var == 'rtm_rad_pc_inswdir'  .OR.              &
9642         var == 'rtm_rad_pc_inswdif'  .OR.  var == 'rtm_rad_pc_inswref'  .OR.           &
9643         var(1:7) == 'rtm_svf'  .OR.  var(1:7) == 'rtm_dif'  .OR.                       &
9644         var(1:9) == 'rtm_skyvf' .OR. var(1:10) == 'rtm_skyvft'  .OR.                   &
9645         var == 'rtm_mrt'  .OR.  var ==  'rtm_mrt_sw'  .OR.  var == 'rtm_mrt_lw' )  THEN
9646
9647         found = .TRUE.
9648         grid_x = 'x'
9649         grid_y = 'y'
9650         grid_z = 'zu'
9651    ELSE
9652
9653       SELECT CASE ( TRIM( var ) )
9654
9655          CASE ( 'rad_lw_cs_hr', 'rad_lw_hr', 'rad_sw_cs_hr', 'rad_sw_hr',        &
9656                 'rad_lw_cs_hr_xy', 'rad_lw_hr_xy', 'rad_sw_cs_hr_xy',            &
9657                 'rad_sw_hr_xy', 'rad_lw_cs_hr_xz', 'rad_lw_hr_xz',               &
9658                 'rad_sw_cs_hr_xz', 'rad_sw_hr_xz', 'rad_lw_cs_hr_yz',            &
9659                 'rad_lw_hr_yz', 'rad_sw_cs_hr_yz', 'rad_sw_hr_yz',               &
9660                 'rad_mrt', 'rad_mrt_sw', 'rad_mrt_lw' )
9661             grid_x = 'x'
9662             grid_y = 'y'
9663             grid_z = 'zu'
9664
9665          CASE ( 'rad_lw_in', 'rad_lw_out', 'rad_sw_in', 'rad_sw_out',            &
9666                 'rad_lw_in_xy', 'rad_lw_out_xy', 'rad_sw_in_xy','rad_sw_out_xy', &
9667                 'rad_lw_in_xz', 'rad_lw_out_xz', 'rad_sw_in_xz','rad_sw_out_xz', &
9668                 'rad_lw_in_yz', 'rad_lw_out_yz', 'rad_sw_in_yz','rad_sw_out_yz' )
9669             grid_x = 'x'
9670             grid_y = 'y'
9671             grid_z = 'zw'
9672
9673
9674          CASE DEFAULT
9675             found  = .FALSE.
9676             grid_x = 'none'
9677             grid_y = 'none'
9678             grid_z = 'none'
9679
9680           END SELECT
9681       ENDIF
9682
9683    END SUBROUTINE radiation_define_netcdf_grid
9684
9685!------------------------------------------------------------------------------!
9686!
9687! Description:
9688! ------------
9689!> Subroutine defining 2D output variables
9690!------------------------------------------------------------------------------!
9691 SUBROUTINE radiation_data_output_2d( av, variable, found, grid, mode,         &
9692                                      local_pf, two_d, nzb_do, nzt_do )
9693 
9694    USE indices
9695
9696    USE kinds
9697
9698
9699    IMPLICIT NONE
9700
9701    CHARACTER (LEN=*) ::  grid     !<
9702    CHARACTER (LEN=*) ::  mode     !<
9703    CHARACTER (LEN=*) ::  variable !<
9704
9705    INTEGER(iwp) ::  av !<
9706    INTEGER(iwp) ::  i  !<
9707    INTEGER(iwp) ::  j  !<
9708    INTEGER(iwp) ::  k  !<
9709    INTEGER(iwp) ::  m  !< index of surface element at grid point (j,i)
9710    INTEGER(iwp) ::  nzb_do   !<
9711    INTEGER(iwp) ::  nzt_do   !<
9712
9713    LOGICAL      ::  found !<
9714    LOGICAL      ::  two_d !< flag parameter that indicates 2D variables (horizontal cross sections)
9715
9716    REAL(wp) ::  fill_value = -999.0_wp    !< value for the _FillValue attribute
9717
9718    REAL(wp), DIMENSION(nxl:nxr,nys:nyn,nzb_do:nzt_do) ::  local_pf !<
9719
9720    found = .TRUE.
9721
9722    SELECT CASE ( TRIM( variable ) )
9723
9724       CASE ( 'rad_net*_xy' )        ! 2d-array
9725          IF ( av == 0 ) THEN
9726             DO  i = nxl, nxr
9727                DO  j = nys, nyn
9728!
9729!--                Obtain rad_net from its respective surface type
9730!--                Natural-type surfaces
9731                   DO  m = surf_lsm_h%start_index(j,i),                        &
9732                           surf_lsm_h%end_index(j,i) 
9733                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_net(m)
9734                   ENDDO
9735!
9736!--                Urban-type surfaces
9737                   DO  m = surf_usm_h%start_index(j,i),                        &
9738                           surf_usm_h%end_index(j,i) 
9739                      local_pf(i,j,nzb+1) = surf_usm_h%rad_net(m)
9740                   ENDDO
9741                ENDDO
9742             ENDDO
9743          ELSE
9744             IF ( .NOT. ALLOCATED( rad_net_av ) ) THEN
9745                ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
9746                rad_net_av = REAL( fill_value, KIND = wp )
9747             ENDIF
9748             DO  i = nxl, nxr
9749                DO  j = nys, nyn 
9750                   local_pf(i,j,nzb+1) = rad_net_av(j,i)
9751                ENDDO
9752             ENDDO
9753          ENDIF
9754          two_d = .TRUE.
9755          grid = 'zu1'
9756         
9757       CASE ( 'rad_lw_in*_xy' )        ! 2d-array
9758          IF ( av == 0 ) THEN
9759             DO  i = nxl, nxr
9760                DO  j = nys, nyn
9761!
9762!--                Obtain rad_net from its respective surface type
9763!--                Natural-type surfaces
9764                   DO  m = surf_lsm_h%start_index(j,i),                        &
9765                           surf_lsm_h%end_index(j,i) 
9766                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_lw_in(m)
9767                   ENDDO
9768!
9769!--                Urban-type surfaces
9770                   DO  m = surf_usm_h%start_index(j,i),                        &
9771                           surf_usm_h%end_index(j,i) 
9772                      local_pf(i,j,nzb+1) = surf_usm_h%rad_lw_in(m)
9773                   ENDDO
9774                ENDDO
9775             ENDDO
9776          ELSE
9777             IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) ) THEN
9778                ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
9779                rad_lw_in_xy_av = REAL( fill_value, KIND = wp )
9780             ENDIF
9781             DO  i = nxl, nxr
9782                DO  j = nys, nyn 
9783                   local_pf(i,j,nzb+1) = rad_lw_in_xy_av(j,i)
9784                ENDDO
9785             ENDDO
9786          ENDIF
9787          two_d = .TRUE.
9788          grid = 'zu1'
9789         
9790       CASE ( 'rad_lw_out*_xy' )        ! 2d-array
9791          IF ( av == 0 ) THEN
9792             DO  i = nxl, nxr
9793                DO  j = nys, nyn
9794!
9795!--                Obtain rad_net from its respective surface type
9796!--                Natural-type surfaces
9797                   DO  m = surf_lsm_h%start_index(j,i),                        &
9798                           surf_lsm_h%end_index(j,i) 
9799                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_lw_out(m)
9800                   ENDDO
9801!
9802!--                Urban-type surfaces
9803                   DO  m = surf_usm_h%start_index(j,i),                        &
9804                           surf_usm_h%end_index(j,i) 
9805                      local_pf(i,j,nzb+1) = surf_usm_h%rad_lw_out(m)
9806                   ENDDO
9807                ENDDO
9808             ENDDO
9809          ELSE
9810             IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) ) THEN
9811                ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
9812                rad_lw_out_xy_av = REAL( fill_value, KIND = wp )
9813             ENDIF
9814             DO  i = nxl, nxr
9815                DO  j = nys, nyn 
9816                   local_pf(i,j,nzb+1) = rad_lw_out_xy_av(j,i)
9817                ENDDO
9818             ENDDO
9819          ENDIF
9820          two_d = .TRUE.
9821          grid = 'zu1'
9822         
9823       CASE ( 'rad_sw_in*_xy' )        ! 2d-array
9824          IF ( av == 0 ) THEN
9825             DO  i = nxl, nxr
9826                DO  j = nys, nyn
9827!
9828!--                Obtain rad_net from its respective surface type
9829!--                Natural-type surfaces
9830                   DO  m = surf_lsm_h%start_index(j,i),                        &
9831                           surf_lsm_h%end_index(j,i) 
9832                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_sw_in(m)
9833                   ENDDO
9834!
9835!--                Urban-type surfaces
9836                   DO  m = surf_usm_h%start_index(j,i),                        &
9837                           surf_usm_h%end_index(j,i) 
9838                      local_pf(i,j,nzb+1) = surf_usm_h%rad_sw_in(m)
9839                   ENDDO
9840                ENDDO
9841             ENDDO
9842          ELSE
9843             IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) ) THEN
9844                ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
9845                rad_sw_in_xy_av = REAL( fill_value, KIND = wp )
9846             ENDIF
9847             DO  i = nxl, nxr
9848                DO  j = nys, nyn 
9849                   local_pf(i,j,nzb+1) = rad_sw_in_xy_av(j,i)
9850                ENDDO
9851             ENDDO
9852          ENDIF
9853          two_d = .TRUE.
9854          grid = 'zu1'
9855         
9856       CASE ( 'rad_sw_out*_xy' )        ! 2d-array
9857          IF ( av == 0 ) THEN
9858             DO  i = nxl, nxr
9859                DO  j = nys, nyn
9860!
9861!--                Obtain rad_net from its respective surface type
9862!--                Natural-type surfaces
9863                   DO  m = surf_lsm_h%start_index(j,i),                        &
9864                           surf_lsm_h%end_index(j,i) 
9865                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_sw_out(m)
9866                   ENDDO
9867!
9868!--                Urban-type surfaces
9869                   DO  m = surf_usm_h%start_index(j,i),                        &
9870                           surf_usm_h%end_index(j,i) 
9871                      local_pf(i,j,nzb+1) = surf_usm_h%rad_sw_out(m)
9872                   ENDDO
9873                ENDDO
9874             ENDDO
9875          ELSE
9876             IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) ) THEN
9877                ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
9878                rad_sw_out_xy_av = REAL( fill_value, KIND = wp )
9879             ENDIF
9880             DO  i = nxl, nxr
9881                DO  j = nys, nyn 
9882                   local_pf(i,j,nzb+1) = rad_sw_out_xy_av(j,i)
9883                ENDDO
9884             ENDDO
9885          ENDIF
9886          two_d = .TRUE.
9887          grid = 'zu1'         
9888         
9889       CASE ( 'rad_lw_in_xy', 'rad_lw_in_xz', 'rad_lw_in_yz' )
9890          IF ( av == 0 ) THEN
9891             DO  i = nxl, nxr
9892                DO  j = nys, nyn
9893                   DO  k = nzb_do, nzt_do
9894                      local_pf(i,j,k) = rad_lw_in(k,j,i)
9895                   ENDDO
9896                ENDDO
9897             ENDDO
9898          ELSE
9899            IF ( .NOT. ALLOCATED( rad_lw_in_av ) ) THEN
9900               ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9901               rad_lw_in_av = REAL( fill_value, KIND = wp )
9902            ENDIF
9903             DO  i = nxl, nxr
9904                DO  j = nys, nyn 
9905                   DO  k = nzb_do, nzt_do
9906                      local_pf(i,j,k) = rad_lw_in_av(k,j,i)
9907                   ENDDO
9908                ENDDO
9909             ENDDO
9910          ENDIF
9911          IF ( mode == 'xy' )  grid = 'zu'
9912
9913       CASE ( 'rad_lw_out_xy', 'rad_lw_out_xz', 'rad_lw_out_yz' )
9914          IF ( av == 0 ) THEN
9915             DO  i = nxl, nxr
9916                DO  j = nys, nyn
9917                   DO  k = nzb_do, nzt_do
9918                      local_pf(i,j,k) = rad_lw_out(k,j,i)
9919                   ENDDO
9920                ENDDO
9921             ENDDO
9922          ELSE
9923            IF ( .NOT. ALLOCATED( rad_lw_out_av ) ) THEN
9924               ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9925               rad_lw_out_av = REAL( fill_value, KIND = wp )
9926            ENDIF
9927             DO  i = nxl, nxr
9928                DO  j = nys, nyn 
9929                   DO  k = nzb_do, nzt_do
9930                      local_pf(i,j,k) = rad_lw_out_av(k,j,i)
9931                   ENDDO
9932                ENDDO
9933             ENDDO
9934          ENDIF   
9935          IF ( mode == 'xy' )  grid = 'zu'
9936
9937       CASE ( 'rad_lw_cs_hr_xy', 'rad_lw_cs_hr_xz', 'rad_lw_cs_hr_yz' )
9938          IF ( av == 0 ) THEN
9939             DO  i = nxl, nxr
9940                DO  j = nys, nyn
9941                   DO  k = nzb_do, nzt_do
9942                      local_pf(i,j,k) = rad_lw_cs_hr(k,j,i)
9943                   ENDDO
9944                ENDDO
9945             ENDDO
9946          ELSE
9947            IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) ) THEN
9948               ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9949               rad_lw_cs_hr_av = REAL( fill_value, KIND = wp )
9950            ENDIF
9951             DO  i = nxl, nxr
9952                DO  j = nys, nyn 
9953                   DO  k = nzb_do, nzt_do
9954                      local_pf(i,j,k) = rad_lw_cs_hr_av(k,j,i)
9955                   ENDDO
9956                ENDDO
9957             ENDDO
9958          ENDIF
9959          IF ( mode == 'xy' )  grid = 'zw'
9960
9961       CASE ( 'rad_lw_hr_xy', 'rad_lw_hr_xz', 'rad_lw_hr_yz' )
9962          IF ( av == 0 ) THEN
9963             DO  i = nxl, nxr
9964                DO  j = nys, nyn
9965                   DO  k = nzb_do, nzt_do
9966                      local_pf(i,j,k) = rad_lw_hr(k,j,i)
9967                   ENDDO
9968                ENDDO
9969             ENDDO
9970          ELSE
9971            IF ( .NOT. ALLOCATED( rad_lw_hr_av ) ) THEN
9972               ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9973               rad_lw_hr_av= REAL( fill_value, KIND = wp )
9974            ENDIF
9975             DO  i = nxl, nxr
9976                DO  j = nys, nyn 
9977                   DO  k = nzb_do, nzt_do
9978                      local_pf(i,j,k) = rad_lw_hr_av(k,j,i)
9979                   ENDDO
9980                ENDDO
9981             ENDDO
9982          ENDIF
9983          IF ( mode == 'xy' )  grid = 'zw'
9984
9985       CASE ( 'rad_sw_in_xy', 'rad_sw_in_xz', 'rad_sw_in_yz' )
9986          IF ( av == 0 ) THEN
9987             DO  i = nxl, nxr
9988                DO  j = nys, nyn
9989                   DO  k = nzb_do, nzt_do
9990                      local_pf(i,j,k) = rad_sw_in(k,j,i)
9991                   ENDDO
9992                ENDDO
9993             ENDDO
9994          ELSE
9995            IF ( .NOT. ALLOCATED( rad_sw_in_av ) ) THEN
9996               ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9997               rad_sw_in_av = REAL( fill_value, KIND = wp )
9998            ENDIF
9999             DO  i = nxl, nxr
10000                DO  j = nys, nyn 
10001                   DO  k = nzb_do, nzt_do
10002                      local_pf(i,j,k) = rad_sw_in_av(k,j,i)
10003                   ENDDO
10004                ENDDO
10005             ENDDO
10006          ENDIF
10007          IF ( mode == 'xy' )  grid = 'zu'
10008
10009       CASE ( 'rad_sw_out_xy', 'rad_sw_out_xz', 'rad_sw_out_yz' )
10010          IF ( av == 0 ) THEN
10011             DO  i = nxl, nxr
10012                DO  j = nys, nyn
10013                   DO  k = nzb_do, nzt_do
10014                      local_pf(i,j,k) = rad_sw_out(k,j,i)
10015                   ENDDO
10016                ENDDO
10017             ENDDO
10018          ELSE
10019            IF ( .NOT. ALLOCATED( rad_sw_out_av ) ) THEN
10020               ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10021               rad_sw_out_av = REAL( fill_value, KIND = wp )
10022            ENDIF
10023             DO  i = nxl, nxr
10024                DO  j = nys, nyn 
10025                   DO  k = nzb, nzt+1
10026                      local_pf(i,j,k) = rad_sw_out_av(k,j,i)
10027                   ENDDO
10028                ENDDO
10029             ENDDO
10030          ENDIF
10031          IF ( mode == 'xy' )  grid = 'zu'
10032
10033       CASE ( 'rad_sw_cs_hr_xy', 'rad_sw_cs_hr_xz', 'rad_sw_cs_hr_yz' )
10034          IF ( av == 0 ) THEN
10035             DO  i = nxl, nxr
10036                DO  j = nys, nyn
10037                   DO  k = nzb_do, nzt_do
10038                      local_pf(i,j,k) = rad_sw_cs_hr(k,j,i)
10039                   ENDDO
10040                ENDDO
10041             ENDDO
10042          ELSE
10043            IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) ) THEN
10044               ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10045               rad_sw_cs_hr_av = REAL( fill_value, KIND = wp )
10046            ENDIF
10047             DO  i = nxl, nxr
10048                DO  j = nys, nyn 
10049                   DO  k = nzb_do, nzt_do
10050                      local_pf(i,j,k) = rad_sw_cs_hr_av(k,j,i)
10051                   ENDDO
10052                ENDDO
10053             ENDDO
10054          ENDIF
10055          IF ( mode == 'xy' )  grid = 'zw'
10056
10057       CASE ( 'rad_sw_hr_xy', 'rad_sw_hr_xz', 'rad_sw_hr_yz' )
10058          IF ( av == 0 ) THEN
10059             DO  i = nxl, nxr
10060                DO  j = nys, nyn
10061                   DO  k = nzb_do, nzt_do
10062                      local_pf(i,j,k) = rad_sw_hr(k,j,i)
10063                   ENDDO
10064                ENDDO
10065             ENDDO
10066          ELSE
10067            IF ( .NOT. ALLOCATED( rad_sw_hr_av ) ) THEN
10068               ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10069               rad_sw_hr_av = REAL( fill_value, KIND = wp )
10070            ENDIF
10071             DO  i = nxl, nxr
10072                DO  j = nys, nyn 
10073                   DO  k = nzb_do, nzt_do
10074                      local_pf(i,j,k) = rad_sw_hr_av(k,j,i)
10075                   ENDDO
10076                ENDDO
10077             ENDDO
10078          ENDIF
10079          IF ( mode == 'xy' )  grid = 'zw'
10080
10081       CASE DEFAULT
10082          found = .FALSE.
10083          grid  = 'none'
10084
10085    END SELECT
10086 
10087 END SUBROUTINE radiation_data_output_2d
10088
10089
10090!------------------------------------------------------------------------------!
10091!
10092! Description:
10093! ------------
10094!> Subroutine defining 3D output variables
10095!------------------------------------------------------------------------------!
10096 SUBROUTINE radiation_data_output_3d( av, variable, found, local_pf, nzb_do, nzt_do )
10097 
10098
10099    USE indices
10100
10101    USE kinds
10102
10103
10104    IMPLICIT NONE
10105
10106    CHARACTER (LEN=*) ::  variable !<
10107
10108    INTEGER(iwp) ::  av          !<
10109    INTEGER(iwp) ::  i, j, k, l  !<
10110    INTEGER(iwp) ::  nzb_do      !<
10111    INTEGER(iwp) ::  nzt_do      !<
10112
10113    LOGICAL      ::  found       !<
10114
10115    REAL(wp)     ::  fill_value = -999.0_wp    !< value for the _FillValue attribute
10116
10117    REAL(sp), DIMENSION(nxl:nxr,nys:nyn,nzb_do:nzt_do) ::  local_pf !<
10118
10119    CHARACTER (len=varnamelength)                   :: var, surfid
10120    INTEGER(iwp)                                    :: ids,idsint_u,idsint_l,isurf,isvf,isurfs,isurflt,ipcgb
10121    INTEGER(iwp)                                    :: is, js, ks, istat
10122
10123    found = .TRUE.
10124
10125    ids = -1
10126    var = TRIM(variable)
10127    DO i = 0, nd-1
10128        k = len(TRIM(var))
10129        j = len(TRIM(dirname(i)))
10130        IF ( TRIM(var(k-j+1:k)) == TRIM(dirname(i)) )  THEN
10131            ids = i
10132            idsint_u = dirint_u(ids)
10133            idsint_l = dirint_l(ids)
10134            var = var(:k-j)
10135            EXIT
10136        ENDIF
10137    ENDDO
10138    IF ( ids == -1 )  THEN
10139        var = TRIM(variable)
10140    ENDIF
10141
10142    IF ( (var(1:8) == 'rtm_svf_'  .OR.  var(1:8) == 'rtm_dif_')  .AND.  len(TRIM(var)) >= 13 )  THEN
10143!--     svf values to particular surface
10144        surfid = var(9:)
10145        i = index(surfid,'_')
10146        j = index(surfid(i+1:),'_')
10147        READ(surfid(1:i-1),*, iostat=istat ) is
10148        IF ( istat == 0 )  THEN
10149            READ(surfid(i+1:i+j-1),*, iostat=istat ) js
10150        ENDIF
10151        IF ( istat == 0 )  THEN
10152            READ(surfid(i+j+1:),*, iostat=istat ) ks
10153        ENDIF
10154        IF ( istat == 0 )  THEN
10155            var = var(1:7)
10156        ENDIF
10157    ENDIF
10158
10159    local_pf = fill_value
10160
10161    SELECT CASE ( TRIM( var ) )
10162!--   block of large scale radiation model (e.g. RRTMG) output variables
10163      CASE ( 'rad_sw_in' )
10164         IF ( av == 0 )  THEN
10165            DO  i = nxl, nxr
10166               DO  j = nys, nyn
10167                  DO  k = nzb_do, nzt_do
10168                     local_pf(i,j,k) = rad_sw_in(k,j,i)
10169                  ENDDO
10170               ENDDO
10171            ENDDO
10172         ELSE
10173            IF ( .NOT. ALLOCATED( rad_sw_in_av ) ) THEN
10174               ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10175               rad_sw_in_av = REAL( fill_value, KIND = wp )
10176            ENDIF
10177            DO  i = nxl, nxr
10178               DO  j = nys, nyn
10179                  DO  k = nzb_do, nzt_do
10180                     local_pf(i,j,k) = rad_sw_in_av(k,j,i)
10181                  ENDDO
10182               ENDDO
10183            ENDDO
10184         ENDIF
10185
10186      CASE ( 'rad_sw_out' )
10187         IF ( av == 0 )  THEN
10188            DO  i = nxl, nxr
10189               DO  j = nys, nyn
10190                  DO  k = nzb_do, nzt_do
10191                     local_pf(i,j,k) = rad_sw_out(k,j,i)
10192                  ENDDO
10193               ENDDO
10194            ENDDO
10195         ELSE
10196            IF ( .NOT. ALLOCATED( rad_sw_out_av ) ) THEN
10197               ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10198               rad_sw_out_av = REAL( fill_value, KIND = wp )
10199            ENDIF
10200            DO  i = nxl, nxr
10201               DO  j = nys, nyn
10202                  DO  k = nzb_do, nzt_do
10203                     local_pf(i,j,k) = rad_sw_out_av(k,j,i)
10204                  ENDDO
10205               ENDDO
10206            ENDDO
10207         ENDIF
10208
10209      CASE ( 'rad_sw_cs_hr' )
10210         IF ( av == 0 )  THEN
10211            DO  i = nxl, nxr
10212               DO  j = nys, nyn
10213                  DO  k = nzb_do, nzt_do
10214                     local_pf(i,j,k) = rad_sw_cs_hr(k,j,i)
10215                  ENDDO
10216               ENDDO
10217            ENDDO
10218         ELSE
10219            IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) ) THEN
10220               ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10221               rad_sw_cs_hr_av = REAL( fill_value, KIND = wp )
10222            ENDIF
10223            DO  i = nxl, nxr
10224               DO  j = nys, nyn
10225                  DO  k = nzb_do, nzt_do
10226                     local_pf(i,j,k) = rad_sw_cs_hr_av(k,j,i)
10227                  ENDDO
10228               ENDDO
10229            ENDDO
10230         ENDIF
10231
10232      CASE ( 'rad_sw_hr' )
10233         IF ( av == 0 )  THEN
10234            DO  i = nxl, nxr
10235               DO  j = nys, nyn
10236                  DO  k = nzb_do, nzt_do
10237                     local_pf(i,j,k) = rad_sw_hr(k,j,i)
10238                  ENDDO
10239               ENDDO
10240            ENDDO
10241         ELSE
10242            IF ( .NOT. ALLOCATED( rad_sw_hr_av ) ) THEN
10243               ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10244               rad_sw_hr_av = REAL( fill_value, KIND = wp )
10245            ENDIF
10246            DO  i = nxl, nxr
10247               DO  j = nys, nyn
10248                  DO  k = nzb_do, nzt_do
10249                     local_pf(i,j,k) = rad_sw_hr_av(k,j,i)
10250                  ENDDO
10251               ENDDO
10252            ENDDO
10253         ENDIF
10254
10255      CASE ( 'rad_lw_in' )
10256         IF ( av == 0 )  THEN
10257            DO  i = nxl, nxr
10258               DO  j = nys, nyn
10259                  DO  k = nzb_do, nzt_do
10260                     local_pf(i,j,k) = rad_lw_in(k,j,i)
10261                  ENDDO
10262               ENDDO
10263            ENDDO
10264         ELSE
10265            IF ( .NOT. ALLOCATED( rad_lw_in_av ) ) THEN
10266               ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10267               rad_lw_in_av = REAL( fill_value, KIND = wp )
10268            ENDIF
10269            DO  i = nxl, nxr
10270               DO  j = nys, nyn
10271                  DO  k = nzb_do, nzt_do
10272                     local_pf(i,j,k) = rad_lw_in_av(k,j,i)
10273                  ENDDO
10274               ENDDO
10275            ENDDO
10276         ENDIF
10277
10278      CASE ( 'rad_lw_out' )
10279         IF ( av == 0 )  THEN
10280            DO  i = nxl, nxr
10281               DO  j = nys, nyn
10282                  DO  k = nzb_do, nzt_do
10283                     local_pf(i,j,k) = rad_lw_out(k,j,i)
10284                  ENDDO
10285               ENDDO
10286            ENDDO
10287         ELSE
10288            IF ( .NOT. ALLOCATED( rad_lw_out_av ) ) THEN
10289               ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10290               rad_lw_out_av = REAL( fill_value, KIND = wp )
10291            ENDIF
10292            DO  i = nxl, nxr
10293               DO  j = nys, nyn
10294                  DO  k = nzb_do, nzt_do
10295                     local_pf(i,j,k) = rad_lw_out_av(k,j,i)
10296                  ENDDO
10297               ENDDO
10298            ENDDO
10299         ENDIF
10300
10301      CASE ( 'rad_lw_cs_hr' )
10302         IF ( av == 0 )  THEN
10303            DO  i = nxl, nxr
10304               DO  j = nys, nyn
10305                  DO  k = nzb_do, nzt_do
10306                     local_pf(i,j,k) = rad_lw_cs_hr(k,j,i)
10307                  ENDDO
10308               ENDDO
10309            ENDDO
10310         ELSE
10311            IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) ) THEN
10312               ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10313               rad_lw_cs_hr_av = REAL( fill_value, KIND = wp )
10314            ENDIF
10315            DO  i = nxl, nxr
10316               DO  j = nys, nyn
10317                  DO  k = nzb_do, nzt_do
10318                     local_pf(i,j,k) = rad_lw_cs_hr_av(k,j,i)
10319                  ENDDO
10320               ENDDO
10321            ENDDO
10322         ENDIF
10323
10324      CASE ( 'rad_lw_hr' )
10325         IF ( av == 0 )  THEN
10326            DO  i = nxl, nxr
10327               DO  j = nys, nyn
10328                  DO  k = nzb_do, nzt_do
10329                     local_pf(i,j,k) = rad_lw_hr(k,j,i)
10330                  ENDDO
10331               ENDDO
10332            ENDDO
10333         ELSE
10334            IF ( .NOT. ALLOCATED( rad_lw_hr_av ) ) THEN
10335               ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10336              rad_lw_hr_av = REAL( fill_value, KIND = wp )
10337            ENDIF
10338            DO  i = nxl, nxr
10339               DO  j = nys, nyn
10340                  DO  k = nzb_do, nzt_do
10341                     local_pf(i,j,k) = rad_lw_hr_av(k,j,i)
10342                  ENDDO
10343               ENDDO
10344            ENDDO
10345         ENDIF
10346
10347!--   block of RTM output variables
10348!--   variables are intended mainly for debugging and detailed analyse purposes
10349      CASE ( 'rtm_skyvf' )
10350!--        sky view factor
10351         DO isurf = dirstart(ids), dirend(ids)
10352            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10353               local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = skyvf(isurf)
10354            ENDIF
10355         ENDDO
10356
10357      CASE ( 'rtm_skyvft' )
10358!--      sky view factor
10359         DO isurf = dirstart(ids), dirend(ids)
10360            IF ( surfl(id,isurf) == ids )  THEN
10361               local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = skyvft(isurf)
10362            ENDIF
10363         ENDDO
10364
10365      CASE ( 'rtm_svf', 'rtm_dif' )
10366!--      shape view factors or iradiance factors to selected surface
10367         IF ( TRIM(var)=='rtm_svf' )  THEN
10368             k = 1
10369         ELSE
10370             k = 2
10371         ENDIF
10372         DO isvf = 1, nsvfl
10373            isurflt = svfsurf(1, isvf)
10374            isurfs = svfsurf(2, isvf)
10375
10376            IF ( surf(ix,isurfs) == is  .AND.  surf(iy,isurfs) == js  .AND. surf(iz,isurfs) == ks  .AND. &
10377                 (surf(id,isurfs) == idsint_u .OR. surfl(id,isurfs) == idsint_l ) ) THEN
10378!--            correct source surface
10379               local_pf(surfl(ix,isurflt),surfl(iy,isurflt),surfl(iz,isurflt)) = svf(k,isvf)
10380            ENDIF
10381         ENDDO
10382
10383      CASE ( 'rtm_rad_net' )
10384!--     array of complete radiation balance
10385         DO isurf = dirstart(ids), dirend(ids)
10386            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10387               IF ( av == 0 )  THEN
10388                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = &
10389                         surfinsw(isurf) - surfoutsw(isurf) +  surfinlw(isurf) - surfoutlw(isurf)
10390               ELSE
10391                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfradnet_av(isurf)
10392               ENDIF
10393            ENDIF
10394         ENDDO
10395
10396      CASE ( 'rtm_rad_insw' )
10397!--      array of sw radiation falling to surface after i-th reflection
10398         DO isurf = dirstart(ids), dirend(ids)
10399            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10400               IF ( av == 0 )  THEN
10401                 local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinsw(isurf)
10402               ELSE
10403                 local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinsw_av(isurf)
10404               ENDIF
10405            ENDIF
10406         ENDDO
10407
10408      CASE ( 'rtm_rad_inlw' )
10409!--      array of lw radiation falling to surface after i-th reflection
10410         DO isurf = dirstart(ids), dirend(ids)
10411            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10412               IF ( av == 0 )  THEN
10413                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlw(isurf)
10414               ELSE
10415                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlw_av(isurf)
10416               ENDIF
10417             ENDIF
10418         ENDDO
10419
10420      CASE ( 'rtm_rad_inswdir' )
10421!--      array of direct sw radiation falling to surface from sun
10422         DO isurf = dirstart(ids), dirend(ids)
10423            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10424               IF ( av == 0 )  THEN
10425                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdir(isurf)
10426               ELSE
10427                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdir_av(isurf)
10428               ENDIF
10429            ENDIF
10430         ENDDO
10431
10432      CASE ( 'rtm_rad_inswdif' )
10433!--      array of difusion sw radiation falling to surface from sky and borders of the domain
10434         DO isurf = dirstart(ids), dirend(ids)
10435            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10436               IF ( av == 0 )  THEN
10437                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdif(isurf)
10438               ELSE
10439                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdif_av(isurf)
10440               ENDIF
10441            ENDIF
10442         ENDDO
10443
10444      CASE ( 'rtm_rad_inswref' )
10445!--      array of sw radiation falling to surface from reflections
10446         DO isurf = dirstart(ids), dirend(ids)
10447            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10448               IF ( av == 0 )  THEN
10449                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = &
10450                    surfinsw(isurf) - surfinswdir(isurf) - surfinswdif(isurf)
10451               ELSE
10452                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswref_av(isurf)
10453               ENDIF
10454            ENDIF
10455         ENDDO
10456
10457      CASE ( 'rtm_rad_inlwdif' )
10458!--      array of difusion lw radiation falling to surface from sky and borders of the domain
10459         DO isurf = dirstart(ids), dirend(ids)
10460            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10461               IF ( av == 0 )  THEN
10462                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlwdif(isurf)
10463               ELSE
10464                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlwdif_av(isurf)
10465               ENDIF
10466            ENDIF
10467         ENDDO
10468
10469      CASE ( 'rtm_rad_inlwref' )
10470!--      array of lw radiation falling to surface from reflections
10471         DO isurf = dirstart(ids), dirend(ids)
10472            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10473               IF ( av == 0 )  THEN
10474                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlw(isurf) - surfinlwdif(isurf)
10475               ELSE
10476                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlwref_av(isurf)
10477               ENDIF
10478            ENDIF
10479         ENDDO
10480
10481      CASE ( 'rtm_rad_outsw' )
10482!--      array of sw radiation emitted from surface after i-th reflection
10483         DO isurf = dirstart(ids), dirend(ids)
10484            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10485               IF ( av == 0 )  THEN
10486                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutsw(isurf)
10487               ELSE
10488                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutsw_av(isurf)
10489               ENDIF
10490            ENDIF
10491         ENDDO
10492
10493      CASE ( 'rtm_rad_outlw' )
10494!--      array of lw radiation emitted from surface after i-th reflection
10495         DO isurf = dirstart(ids), dirend(ids)
10496            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10497               IF ( av == 0 )  THEN
10498                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutlw(isurf)
10499               ELSE
10500                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutlw_av(isurf)
10501               ENDIF
10502            ENDIF
10503         ENDDO
10504
10505      CASE ( 'rtm_rad_ressw' )
10506!--      average of array of residua of sw radiation absorbed in surface after last reflection
10507         DO isurf = dirstart(ids), dirend(ids)
10508            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10509               IF ( av == 0 )  THEN
10510                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfins(isurf)
10511               ELSE
10512                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfins_av(isurf)
10513               ENDIF
10514            ENDIF
10515         ENDDO
10516
10517      CASE ( 'rtm_rad_reslw' )
10518!--      average of array of residua of lw radiation absorbed in surface after last reflection
10519         DO isurf = dirstart(ids), dirend(ids)
10520            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10521               IF ( av == 0 )  THEN
10522                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinl(isurf)
10523               ELSE
10524                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinl_av(isurf)
10525               ENDIF
10526            ENDIF
10527         ENDDO
10528
10529      CASE ( 'rtm_rad_pc_inlw' )
10530!--      array of lw radiation absorbed by plant canopy
10531         DO ipcgb = 1, npcbl
10532            IF ( av == 0 )  THEN
10533               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinlw(ipcgb)
10534            ELSE
10535               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinlw_av(ipcgb)
10536            ENDIF
10537         ENDDO
10538
10539      CASE ( 'rtm_rad_pc_insw' )
10540!--      array of sw radiation absorbed by plant canopy
10541         DO ipcgb = 1, npcbl
10542            IF ( av == 0 )  THEN
10543              local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinsw(ipcgb)
10544            ELSE
10545              local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinsw_av(ipcgb)
10546            ENDIF
10547         ENDDO
10548
10549      CASE ( 'rtm_rad_pc_inswdir' )
10550!--      array of direct sw radiation absorbed by plant canopy
10551         DO ipcgb = 1, npcbl
10552            IF ( av == 0 )  THEN
10553               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdir(ipcgb)
10554            ELSE
10555               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdir_av(ipcgb)
10556            ENDIF
10557         ENDDO
10558
10559      CASE ( 'rtm_rad_pc_inswdif' )
10560!--      array of diffuse sw radiation absorbed by plant canopy
10561         DO ipcgb = 1, npcbl
10562            IF ( av == 0 )  THEN
10563               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdif(ipcgb)
10564            ELSE
10565               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdif_av(ipcgb)
10566            ENDIF
10567         ENDDO
10568
10569      CASE ( 'rtm_rad_pc_inswref' )
10570!--      array of reflected sw radiation absorbed by plant canopy
10571         DO ipcgb = 1, npcbl
10572            IF ( av == 0 )  THEN
10573               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = &
10574                                    pcbinsw(ipcgb) - pcbinswdir(ipcgb) - pcbinswdif(ipcgb)
10575            ELSE
10576               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswref_av(ipcgb)
10577            ENDIF
10578         ENDDO
10579
10580      CASE ( 'rtm_mrt_sw' )
10581         local_pf = REAL( fill_value, KIND = wp )
10582         IF ( av == 0 )  THEN
10583            DO  l = 1, nmrtbl
10584               local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinsw(l)
10585            ENDDO
10586         ELSE
10587            IF ( ALLOCATED( mrtinsw_av ) ) THEN
10588               DO  l = 1, nmrtbl
10589                  local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinsw_av(l)
10590               ENDDO
10591            ENDIF
10592         ENDIF
10593
10594      CASE ( 'rtm_mrt_lw' )
10595         local_pf = REAL( fill_value, KIND = wp )
10596         IF ( av == 0 )  THEN
10597            DO  l = 1, nmrtbl
10598               local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinlw(l)
10599            ENDDO
10600         ELSE
10601            IF ( ALLOCATED( mrtinlw_av ) ) THEN
10602               DO  l = 1, nmrtbl
10603                  local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinlw_av(l)
10604               ENDDO
10605            ENDIF
10606         ENDIF
10607
10608      CASE ( 'rtm_mrt' )
10609         local_pf = REAL( fill_value, KIND = wp )
10610         IF ( av == 0 )  THEN
10611            DO  l = 1, nmrtbl
10612               local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrt(l)
10613            ENDDO
10614         ELSE
10615            IF ( ALLOCATED( mrt_av ) ) THEN
10616               DO  l = 1, nmrtbl
10617                  local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrt_av(l)
10618               ENDDO
10619            ENDIF
10620         ENDIF
10621
10622       CASE DEFAULT
10623          found = .FALSE.
10624
10625    END SELECT
10626
10627
10628 END SUBROUTINE radiation_data_output_3d
10629
10630!------------------------------------------------------------------------------!
10631!
10632! Description:
10633! ------------
10634!> Subroutine defining masked data output
10635!------------------------------------------------------------------------------!
10636 SUBROUTINE radiation_data_output_mask( av, variable, found, local_pf )
10637 
10638    USE control_parameters
10639       
10640    USE indices
10641   
10642    USE kinds
10643   
10644
10645    IMPLICIT NONE
10646
10647    CHARACTER (LEN=*) ::  variable   !<
10648
10649    CHARACTER(LEN=5) ::  grid        !< flag to distinquish between staggered grids
10650
10651    INTEGER(iwp) ::  av              !<
10652    INTEGER(iwp) ::  i               !<
10653    INTEGER(iwp) ::  j               !<
10654    INTEGER(iwp) ::  k               !<
10655    INTEGER(iwp) ::  topo_top_ind    !< k index of highest horizontal surface
10656
10657    LOGICAL ::  found                !< true if output array was found
10658    LOGICAL ::  resorted             !< true if array is resorted
10659
10660
10661    REAL(wp),                                                                  &
10662       DIMENSION(mask_size_l(mid,1),mask_size_l(mid,2),mask_size_l(mid,3)) ::  &
10663          local_pf   !<
10664
10665    REAL(wp), DIMENSION(:,:,:), POINTER ::  to_be_resorted  !< points to array which needs to be resorted for output
10666
10667
10668    found    = .TRUE.
10669    grid     = 's'
10670    resorted = .FALSE.
10671
10672    SELECT CASE ( TRIM( variable ) )
10673
10674
10675       CASE ( 'rad_lw_in' )
10676          IF ( av == 0 )  THEN
10677             to_be_resorted => rad_lw_in
10678          ELSE
10679             to_be_resorted => rad_lw_in_av
10680          ENDIF
10681
10682       CASE ( 'rad_lw_out' )
10683          IF ( av == 0 )  THEN
10684             to_be_resorted => rad_lw_out
10685          ELSE
10686             to_be_resorted => rad_lw_out_av
10687          ENDIF
10688
10689       CASE ( 'rad_lw_cs_hr' )
10690          IF ( av == 0 )  THEN
10691             to_be_resorted => rad_lw_cs_hr
10692          ELSE
10693             to_be_resorted => rad_lw_cs_hr_av
10694          ENDIF
10695
10696       CASE ( 'rad_lw_hr' )
10697          IF ( av == 0 )  THEN
10698             to_be_resorted => rad_lw_hr
10699          ELSE
10700             to_be_resorted => rad_lw_hr_av
10701          ENDIF
10702
10703       CASE ( 'rad_sw_in' )
10704          IF ( av == 0 )  THEN
10705             to_be_resorted => rad_sw_in
10706          ELSE
10707             to_be_resorted => rad_sw_in_av
10708          ENDIF
10709
10710       CASE ( 'rad_sw_out' )
10711          IF ( av == 0 )  THEN
10712             to_be_resorted => rad_sw_out
10713          ELSE
10714             to_be_resorted => rad_sw_out_av
10715          ENDIF
10716
10717       CASE ( 'rad_sw_cs_hr' )
10718          IF ( av == 0 )  THEN
10719             to_be_resorted => rad_sw_cs_hr
10720          ELSE
10721             to_be_resorted => rad_sw_cs_hr_av
10722          ENDIF
10723
10724       CASE ( 'rad_sw_hr' )
10725          IF ( av == 0 )  THEN
10726             to_be_resorted => rad_sw_hr
10727          ELSE
10728             to_be_resorted => rad_sw_hr_av
10729          ENDIF
10730
10731       CASE DEFAULT
10732          found = .FALSE.
10733
10734    END SELECT
10735
10736!
10737!-- Resort the array to be output, if not done above
10738    IF ( .NOT. resorted )  THEN
10739       IF ( .NOT. mask_surface(mid) )  THEN
10740!
10741!--       Default masked output
10742          DO  i = 1, mask_size_l(mid,1)
10743             DO  j = 1, mask_size_l(mid,2)
10744                DO  k = 1, mask_size_l(mid,3)
10745                   local_pf(i,j,k) =  to_be_resorted(mask_k(mid,k), &
10746                                      mask_j(mid,j),mask_i(mid,i))
10747                ENDDO
10748             ENDDO
10749          ENDDO
10750
10751       ELSE
10752!
10753!--       Terrain-following masked output
10754          DO  i = 1, mask_size_l(mid,1)
10755             DO  j = 1, mask_size_l(mid,2)
10756!
10757!--             Get k index of highest horizontal surface
10758                topo_top_ind = get_topography_top_index_ji( mask_j(mid,j), &
10759                                                            mask_i(mid,i), &
10760                                                            grid )
10761!
10762!--             Save output array
10763                DO  k = 1, mask_size_l(mid,3)
10764                   local_pf(i,j,k) = to_be_resorted(                       &
10765                                          MIN( topo_top_ind+mask_k(mid,k), &
10766                                               nzt+1 ),                    &
10767                                          mask_j(mid,j),                   &
10768                                          mask_i(mid,i)                     )
10769                ENDDO
10770             ENDDO
10771          ENDDO
10772
10773       ENDIF
10774    ENDIF
10775
10776
10777
10778 END SUBROUTINE radiation_data_output_mask
10779
10780
10781!------------------------------------------------------------------------------!
10782! Description:
10783! ------------
10784!> Subroutine writes local (subdomain) restart data
10785!------------------------------------------------------------------------------!
10786 SUBROUTINE radiation_wrd_local
10787
10788
10789    IMPLICIT NONE
10790
10791
10792    IF ( ALLOCATED( rad_net_av ) )  THEN
10793       CALL wrd_write_string( 'rad_net_av' )
10794       WRITE ( 14 )  rad_net_av
10795    ENDIF
10796   
10797    IF ( ALLOCATED( rad_lw_in_xy_av ) )  THEN
10798       CALL wrd_write_string( 'rad_lw_in_xy_av' )
10799       WRITE ( 14 )  rad_lw_in_xy_av
10800    ENDIF
10801   
10802    IF ( ALLOCATED( rad_lw_out_xy_av ) )  THEN
10803       CALL wrd_write_string( 'rad_lw_out_xy_av' )
10804       WRITE ( 14 )  rad_lw_out_xy_av
10805    ENDIF
10806   
10807    IF ( ALLOCATED( rad_sw_in_xy_av ) )  THEN
10808       CALL wrd_write_string( 'rad_sw_in_xy_av' )
10809       WRITE ( 14 )  rad_sw_in_xy_av
10810    ENDIF
10811   
10812    IF ( ALLOCATED( rad_sw_out_xy_av ) )  THEN
10813       CALL wrd_write_string( 'rad_sw_out_xy_av' )
10814       WRITE ( 14 )  rad_sw_out_xy_av
10815    ENDIF
10816
10817    IF ( ALLOCATED( rad_lw_in ) )  THEN
10818       CALL wrd_write_string( 'rad_lw_in' )
10819       WRITE ( 14 )  rad_lw_in
10820    ENDIF
10821
10822    IF ( ALLOCATED( rad_lw_in_av ) )  THEN
10823       CALL wrd_write_string( 'rad_lw_in_av' )
10824       WRITE ( 14 )  rad_lw_in_av
10825    ENDIF
10826
10827    IF ( ALLOCATED( rad_lw_out ) )  THEN
10828       CALL wrd_write_string( 'rad_lw_out' )
10829       WRITE ( 14 )  rad_lw_out
10830    ENDIF
10831
10832    IF ( ALLOCATED( rad_lw_out_av) )  THEN
10833       CALL wrd_write_string( 'rad_lw_out_av' )
10834       WRITE ( 14 )  rad_lw_out_av
10835    ENDIF
10836
10837    IF ( ALLOCATED( rad_lw_cs_hr) )  THEN
10838       CALL wrd_write_string( 'rad_lw_cs_hr' )
10839       WRITE ( 14 )  rad_lw_cs_hr
10840    ENDIF
10841
10842    IF ( ALLOCATED( rad_lw_cs_hr_av) )  THEN
10843       CALL wrd_write_string( 'rad_lw_cs_hr_av' )
10844       WRITE ( 14 )  rad_lw_cs_hr_av
10845    ENDIF
10846
10847    IF ( ALLOCATED( rad_lw_hr) )  THEN
10848       CALL wrd_write_string( 'rad_lw_hr' )
10849       WRITE ( 14 )  rad_lw_hr
10850    ENDIF
10851
10852    IF ( ALLOCATED( rad_lw_hr_av) )  THEN
10853       CALL wrd_write_string( 'rad_lw_hr_av' )
10854       WRITE ( 14 )  rad_lw_hr_av
10855    ENDIF
10856
10857    IF ( ALLOCATED( rad_sw_in) )  THEN
10858       CALL wrd_write_string( 'rad_sw_in' )
10859       WRITE ( 14 )  rad_sw_in
10860    ENDIF
10861
10862    IF ( ALLOCATED( rad_sw_in_av) )  THEN
10863       CALL wrd_write_string( 'rad_sw_in_av' )
10864       WRITE ( 14 )  rad_sw_in_av
10865    ENDIF
10866
10867    IF ( ALLOCATED( rad_sw_out) )  THEN
10868       CALL wrd_write_string( 'rad_sw_out' )
10869       WRITE ( 14 )  rad_sw_out
10870    ENDIF
10871
10872    IF ( ALLOCATED( rad_sw_out_av) )  THEN
10873       CALL wrd_write_string( 'rad_sw_out_av' )
10874       WRITE ( 14 )  rad_sw_out_av
10875    ENDIF
10876
10877    IF ( ALLOCATED( rad_sw_cs_hr) )  THEN
10878       CALL wrd_write_string( 'rad_sw_cs_hr' )
10879       WRITE ( 14 )  rad_sw_cs_hr
10880    ENDIF
10881
10882    IF ( ALLOCATED( rad_sw_cs_hr_av) )  THEN
10883       CALL wrd_write_string( 'rad_sw_cs_hr_av' )
10884       WRITE ( 14 )  rad_sw_cs_hr_av
10885    ENDIF
10886
10887    IF ( ALLOCATED( rad_sw_hr) )  THEN
10888       CALL wrd_write_string( 'rad_sw_hr' )
10889       WRITE ( 14 )  rad_sw_hr
10890    ENDIF
10891
10892    IF ( ALLOCATED( rad_sw_hr_av) )  THEN
10893       CALL wrd_write_string( 'rad_sw_hr_av' )
10894       WRITE ( 14 )  rad_sw_hr_av
10895    ENDIF
10896
10897
10898 END SUBROUTINE radiation_wrd_local
10899
10900!------------------------------------------------------------------------------!
10901! Description:
10902! ------------
10903!> Subroutine reads local (subdomain) restart data
10904!------------------------------------------------------------------------------!
10905 SUBROUTINE radiation_rrd_local( i, k, nxlf, nxlc, nxl_on_file, nxrf, nxrc,    &
10906                                nxr_on_file, nynf, nync, nyn_on_file, nysf,    &
10907                                nysc, nys_on_file, tmp_2d, tmp_3d, found )
10908 
10909
10910    USE control_parameters
10911       
10912    USE indices
10913   
10914    USE kinds
10915   
10916    USE pegrid
10917
10918
10919    IMPLICIT NONE
10920
10921    INTEGER(iwp) ::  i               !<
10922    INTEGER(iwp) ::  k               !<
10923    INTEGER(iwp) ::  nxlc            !<
10924    INTEGER(iwp) ::  nxlf            !<
10925    INTEGER(iwp) ::  nxl_on_file     !<
10926    INTEGER(iwp) ::  nxrc            !<
10927    INTEGER(iwp) ::  nxrf            !<
10928    INTEGER(iwp) ::  nxr_on_file     !<
10929    INTEGER(iwp) ::  nync            !<
10930    INTEGER(iwp) ::  nynf            !<
10931    INTEGER(iwp) ::  nyn_on_file     !<
10932    INTEGER(iwp) ::  nysc            !<
10933    INTEGER(iwp) ::  nysf            !<
10934    INTEGER(iwp) ::  nys_on_file     !<
10935
10936    LOGICAL, INTENT(OUT)  :: found
10937
10938    REAL(wp), DIMENSION(nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_2d   !<
10939
10940    REAL(wp), DIMENSION(nzb:nzt+1,nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_3d   !<
10941
10942    REAL(wp), DIMENSION(0:0,nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_3d2   !<
10943
10944
10945    found = .TRUE.
10946
10947
10948    SELECT CASE ( restart_string(1:length) )
10949
10950       CASE ( 'rad_net_av' )
10951          IF ( .NOT. ALLOCATED( rad_net_av ) )  THEN
10952             ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
10953          ENDIF 
10954          IF ( k == 1 )  READ ( 13 )  tmp_2d
10955          rad_net_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =           &
10956                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10957                       
10958       CASE ( 'rad_lw_in_xy_av' )
10959          IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) )  THEN
10960             ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
10961          ENDIF 
10962          IF ( k == 1 )  READ ( 13 )  tmp_2d
10963          rad_lw_in_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =      &
10964                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10965                       
10966       CASE ( 'rad_lw_out_xy_av' )
10967          IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) )  THEN
10968             ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
10969          ENDIF 
10970          IF ( k == 1 )  READ ( 13 )  tmp_2d
10971          rad_lw_out_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =     &
10972                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10973                       
10974       CASE ( 'rad_sw_in_xy_av' )
10975          IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) )  THEN
10976             ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
10977          ENDIF 
10978          IF ( k == 1 )  READ ( 13 )  tmp_2d
10979          rad_sw_in_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =      &
10980                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10981                       
10982       CASE ( 'rad_sw_out_xy_av' )
10983          IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) )  THEN
10984             ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
10985          ENDIF 
10986          IF ( k == 1 )  READ ( 13 )  tmp_2d
10987          rad_sw_out_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =     &
10988                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10989                       
10990       CASE ( 'rad_lw_in' )
10991          IF ( .NOT. ALLOCATED( rad_lw_in ) )  THEN
10992             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
10993                  radiation_scheme == 'constant')  THEN
10994                ALLOCATE( rad_lw_in(0:0,nysg:nyng,nxlg:nxrg) )
10995             ELSE
10996                ALLOCATE( rad_lw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10997             ENDIF
10998          ENDIF 
10999          IF ( k == 1 )  THEN
11000             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11001                  radiation_scheme == 'constant')  THEN
11002                READ ( 13 )  tmp_3d2
11003                rad_lw_in(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =   &
11004                   tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11005             ELSE
11006                READ ( 13 )  tmp_3d
11007                rad_lw_in(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11008                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11009             ENDIF
11010          ENDIF
11011
11012       CASE ( 'rad_lw_in_av' )
11013          IF ( .NOT. ALLOCATED( rad_lw_in_av ) )  THEN
11014             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11015                  radiation_scheme == 'constant')  THEN
11016                ALLOCATE( rad_lw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
11017             ELSE
11018                ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11019             ENDIF
11020          ENDIF 
11021          IF ( k == 1 )  THEN
11022             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11023                  radiation_scheme == 'constant')  THEN
11024                READ ( 13 )  tmp_3d2
11025                rad_lw_in_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =&
11026                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11027             ELSE
11028                READ ( 13 )  tmp_3d
11029                rad_lw_in_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11030                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11031             ENDIF
11032          ENDIF
11033
11034       CASE ( 'rad_lw_out' )
11035          IF ( .NOT. ALLOCATED( rad_lw_out ) )  THEN
11036             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11037                  radiation_scheme == 'constant')  THEN
11038                ALLOCATE( rad_lw_out(0:0,nysg:nyng,nxlg:nxrg) )
11039             ELSE
11040                ALLOCATE( rad_lw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11041             ENDIF
11042          ENDIF 
11043          IF ( k == 1 )  THEN
11044             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11045                  radiation_scheme == 'constant')  THEN
11046                READ ( 13 )  tmp_3d2
11047                rad_lw_out(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11048                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11049             ELSE
11050                READ ( 13 )  tmp_3d
11051                rad_lw_out(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =    &
11052                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11053             ENDIF
11054          ENDIF
11055
11056       CASE ( 'rad_lw_out_av' )
11057          IF ( .NOT. ALLOCATED( rad_lw_out_av ) )  THEN
11058             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11059                  radiation_scheme == 'constant')  THEN
11060                ALLOCATE( rad_lw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
11061             ELSE
11062                ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11063             ENDIF
11064          ENDIF 
11065          IF ( k == 1 )  THEN
11066             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11067                  radiation_scheme == 'constant')  THEN
11068                READ ( 13 )  tmp_3d2
11069                rad_lw_out_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) &
11070                   = tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11071             ELSE
11072                READ ( 13 )  tmp_3d
11073                rad_lw_out_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &
11074                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11075             ENDIF
11076          ENDIF
11077
11078       CASE ( 'rad_lw_cs_hr' )
11079          IF ( .NOT. ALLOCATED( rad_lw_cs_hr ) )  THEN
11080             ALLOCATE( rad_lw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11081          ENDIF
11082          IF ( k == 1 )  READ ( 13 )  tmp_3d
11083          rad_lw_cs_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11084                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11085
11086       CASE ( 'rad_lw_cs_hr_av' )
11087          IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) )  THEN
11088             ALLOCATE( rad_lw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11089          ENDIF
11090          IF ( k == 1 )  READ ( 13 )  tmp_3d
11091          rad_lw_cs_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11092                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11093
11094       CASE ( 'rad_lw_hr' )
11095          IF ( .NOT. ALLOCATED( rad_lw_hr ) )  THEN
11096             ALLOCATE( rad_lw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11097          ENDIF
11098          IF ( k == 1 )  READ ( 13 )  tmp_3d
11099          rad_lw_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =           &
11100                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11101
11102       CASE ( 'rad_lw_hr_av' )
11103          IF ( .NOT. ALLOCATED( rad_lw_hr_av ) )  THEN
11104             ALLOCATE( rad_lw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11105          ENDIF
11106          IF ( k == 1 )  READ ( 13 )  tmp_3d
11107          rad_lw_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11108                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11109
11110       CASE ( 'rad_sw_in' )
11111          IF ( .NOT. ALLOCATED( rad_sw_in ) )  THEN
11112             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11113                  radiation_scheme == 'constant')  THEN
11114                ALLOCATE( rad_sw_in(0:0,nysg:nyng,nxlg:nxrg) )
11115             ELSE
11116                ALLOCATE( rad_sw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11117             ENDIF
11118          ENDIF 
11119          IF ( k == 1 )  THEN
11120             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11121                  radiation_scheme == 'constant')  THEN
11122                READ ( 13 )  tmp_3d2
11123                rad_sw_in(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =   &
11124                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11125             ELSE
11126                READ ( 13 )  tmp_3d
11127                rad_sw_in(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11128                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11129             ENDIF
11130          ENDIF
11131
11132       CASE ( 'rad_sw_in_av' )
11133          IF ( .NOT. ALLOCATED( rad_sw_in_av ) )  THEN
11134             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11135                  radiation_scheme == 'constant')  THEN
11136                ALLOCATE( rad_sw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
11137             ELSE
11138                ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11139             ENDIF
11140          ENDIF 
11141          IF ( k == 1 )  THEN
11142             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11143                  radiation_scheme == 'constant')  THEN
11144                READ ( 13 )  tmp_3d2
11145                rad_sw_in_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =&
11146                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11147             ELSE
11148                READ ( 13 )  tmp_3d
11149                rad_sw_in_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11150                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11151             ENDIF
11152          ENDIF
11153
11154       CASE ( 'rad_sw_out' )
11155          IF ( .NOT. ALLOCATED( rad_sw_out ) )  THEN
11156             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11157                  radiation_scheme == 'constant')  THEN
11158                ALLOCATE( rad_sw_out(0:0,nysg:nyng,nxlg:nxrg) )
11159             ELSE
11160                ALLOCATE( rad_sw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11161             ENDIF
11162          ENDIF 
11163          IF ( k == 1 )  THEN
11164             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11165                  radiation_scheme == 'constant')  THEN
11166                READ ( 13 )  tmp_3d2
11167                rad_sw_out(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11168                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11169             ELSE
11170                READ ( 13 )  tmp_3d
11171                rad_sw_out(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =    &
11172                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11173             ENDIF
11174          ENDIF
11175
11176       CASE ( 'rad_sw_out_av' )
11177          IF ( .NOT. ALLOCATED( rad_sw_out_av ) )  THEN
11178             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11179                  radiation_scheme == 'constant')  THEN
11180                ALLOCATE( rad_sw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
11181             ELSE
11182                ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11183             ENDIF
11184          ENDIF 
11185          IF ( k == 1 )  THEN
11186             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11187                  radiation_scheme == 'constant')  THEN
11188                READ ( 13 )  tmp_3d2
11189                rad_sw_out_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) &
11190                   = tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11191             ELSE
11192                READ ( 13 )  tmp_3d
11193                rad_sw_out_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &
11194                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11195             ENDIF
11196          ENDIF
11197
11198       CASE ( 'rad_sw_cs_hr' )
11199          IF ( .NOT. ALLOCATED( rad_sw_cs_hr ) )  THEN
11200             ALLOCATE( rad_sw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11201          ENDIF
11202          IF ( k == 1 )  READ ( 13 )  tmp_3d
11203          rad_sw_cs_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11204                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11205
11206       CASE ( 'rad_sw_cs_hr_av' )
11207          IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) )  THEN
11208             ALLOCATE( rad_sw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11209          ENDIF
11210          IF ( k == 1 )  READ ( 13 )  tmp_3d
11211          rad_sw_cs_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11212                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11213
11214       CASE ( 'rad_sw_hr' )
11215          IF ( .NOT. ALLOCATED( rad_sw_hr ) )  THEN
11216             ALLOCATE( rad_sw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11217          ENDIF
11218          IF ( k == 1 )  READ ( 13 )  tmp_3d
11219          rad_sw_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =           &
11220                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11221
11222       CASE ( 'rad_sw_hr_av' )
11223          IF ( .NOT. ALLOCATED( rad_sw_hr_av ) )  THEN
11224             ALLOCATE( rad_sw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11225          ENDIF
11226          IF ( k == 1 )  READ ( 13 )  tmp_3d
11227          rad_lw_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11228                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11229
11230       CASE DEFAULT
11231
11232          found = .FALSE.
11233
11234    END SELECT
11235
11236 END SUBROUTINE radiation_rrd_local
11237
11238!------------------------------------------------------------------------------!
11239! Description:
11240! ------------
11241!> Subroutine writes debug information
11242!------------------------------------------------------------------------------!
11243 SUBROUTINE radiation_write_debug_log ( message )
11244    !> it writes debug log with time stamp
11245    CHARACTER(*)  :: message
11246    CHARACTER(15) :: dtc
11247    CHARACTER(8)  :: date
11248    CHARACTER(10) :: time
11249    CHARACTER(5)  :: zone
11250    CALL date_and_time(date, time, zone)
11251    dtc = date(7:8)//','//time(1:2)//':'//time(3:4)//':'//time(5:10)
11252    WRITE(9,'(2A)') dtc, TRIM(message)
11253    FLUSH(9)
11254 END SUBROUTINE radiation_write_debug_log
11255
11256 END MODULE radiation_model_mod
Note: See TracBrowser for help on using the repository browser.