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

Last change on this file since 3767 was 3767, checked in by raasch, 6 years ago

unused variables removed from rrd-subroutines parameter list

  • Property svn:keywords set to Id
  • Property svn:mergeinfo set to (toggle deleted branches)
    /palm/branches/chemistry/SOURCE/radiation_model_mod.f902047-3190,​3218-3297
    /palm/branches/forwind/SOURCE/radiation_model_mod.f901564-1913
    /palm/branches/mosaik_M2/radiation_model_mod.f902360-3471
    /palm/branches/palm4u/SOURCE/radiation_model_mod.f902540-2692
    /palm/branches/radiation/SOURCE/radiation_model_mod.f902081-3493
    /palm/branches/rans/SOURCE/radiation_model_mod.f902078-3128
    /palm/branches/resler/SOURCE/radiation_model_mod.f902023-3605
    /palm/branches/salsa/SOURCE/radiation_model_mod.f902503-3460
    /palm/branches/fricke/SOURCE/radiation_model_mod.f90942-977
    /palm/branches/hoffmann/SOURCE/radiation_model_mod.f90989-1052
    /palm/branches/letzel/masked_output/SOURCE/radiation_model_mod.f90296-409
    /palm/branches/suehring/radiation_model_mod.f90423-666
File size: 500.4 KB
Line 
1!> @file radiation_model_mod.f90
2!------------------------------------------------------------------------------!
3! This file is part of the PALM model system.
4!
5! PALM is free software: you can redistribute it and/or modify it under the
6! terms of the GNU General Public License as published by the Free Software
7! Foundation, either version 3 of the License, or (at your option) any later
8! version.
9!
10! PALM is distributed in the hope that it will be useful, but WITHOUT ANY
11! WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12! A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
13!
14! You should have received a copy of the GNU General Public License along with
15! PALM. If not, see <http://www.gnu.org/licenses/>.
16!
17! Copyright 2015-2018 Institute of Computer Science of the
18!                     Czech Academy of Sciences, Prague
19! Copyright 2015-2018 Czech Technical University in Prague
20! Copyright 1997-2019 Leibniz Universitaet Hannover
21!------------------------------------------------------------------------------!
22!
23! Current revisions:
24! ------------------
25!
26!
27! Former revisions:
28! -----------------
29! $Id: radiation_model_mod.f90 3767 2019-02-27 08:18:02Z raasch $
30! unused variable for file index removed from rrd-subroutines parameter list
31!
32! 3760 2019-02-21 18:47:35Z moh.hefny
33! Bugfix: initialized simulated_time before calculating solar position
34! to enable restart option with reading in SVF from file(s).
35!
36! 3754 2019-02-19 17:02:26Z kanani
37! (resler, pavelkrc)
38! Bugfixes: add further required MRT factors to read/write_svf,
39! fix for aggregating view factors to eliminate local noise in reflected
40! irradiance at mutually close surfaces (corners, presence of trees) in the
41! angular discretization scheme.
42!
43! 3752 2019-02-19 09:37:22Z resler
44! added read/write number of MRT factors to the respective routines
45!
46! 3705 2019-01-29 19:56:39Z suehring
47! Make variables that are sampled in virtual measurement module public
48!
49! 3704 2019-01-29 19:51:41Z suehring
50! Some interface calls moved to module_interface + cleanup
51!
52! 3667 2019-01-10 14:26:24Z schwenkel
53! Modified check for rrtmg input files
54!
55! 3655 2019-01-07 16:51:22Z knoop
56! nopointer option removed
57!
58! 3633 2018-12-17 16:17:57Z schwenkel
59! Include check for rrtmg files
60!
61! 3630 2018-12-17 11:04:17Z knoop
62! - fix initialization of date and time after calling zenith
63! - fix a bug in radiation_solar_pos
64!
65! 3616 2018-12-10 09:44:36Z Salim
66! fix manipulation of time variables in radiation_presimulate_solar_pos
67!
68! 3608 2018-12-07 12:59:57Z suehring $
69! Bugfix radiation output
70!
71! 3607 2018-12-07 11:56:58Z suehring
72! Output of radiation-related quantities migrated to radiation_model_mod.
73!
74! 3589 2018-11-30 15:09:51Z suehring
75! Remove erroneous UTF encoding
76!
77! 3572 2018-11-28 11:40:28Z suehring
78! Add filling the short- and longwave radiation flux arrays (e.g. diffuse,
79! direct, reflected, resedual) for all surfaces. This is required to surface
80! outputs in suface_output_mod. (M. Salim)
81!
82! 3571 2018-11-28 09:24:03Z moh.hefny
83! Add an epsilon value to compare values in if statement to fix possible
84! precsion related errors in raytrace routines.
85!
86! 3524 2018-11-14 13:36:44Z raasch
87! missing cpp-directives added
88!
89! 3495 2018-11-06 15:22:17Z kanani
90! Resort control_parameters ONLY list,
91! From branch radiation@3491 moh.hefny:
92! bugfix in calculating the apparent solar positions by updating
93! the simulated time so that the actual time is correct.
94!
95! 3464 2018-10-30 18:08:55Z kanani
96! From branch resler@3462, pavelkrc:
97! add MRT shaping function for human
98!
99! 3449 2018-10-29 19:36:56Z suehring
100! New RTM version 3.0: (Pavel Krc, Jaroslav Resler, ICS, Prague)
101!   - Interaction of plant canopy with LW radiation
102!   - Transpiration from resolved plant canopy dependent on radiation
103!     called from RTM
104!
105!
106! 3435 2018-10-26 18:25:44Z gronemeier
107! - workaround: return unit=illegal in check_data_output for certain variables
108!   when check called from init_masks
109! - Use pointer in masked output to reduce code redundancies
110! - Add terrain-following masked output
111!
112! 3424 2018-10-25 07:29:10Z gronemeier
113! bugfix: add rad_lw_in, rad_lw_out, rad_sw_out to radiation_check_data_output
114!
115! 3378 2018-10-19 12:34:59Z kanani
116! merge from radiation branch (r3362) into trunk
117! (moh.hefny):
118! - removed read/write_svf_on_init and read_dist_max_svf (not used anymore)
119! - bugfix nzut > nzpt in calculating maxboxes
120!
121! 3372 2018-10-18 14:03:19Z raasch
122! bugfix: kind type of 2nd argument of mpi_win_allocate changed, misplaced
123!         __parallel directive
124!
125! 3351 2018-10-15 18:40:42Z suehring
126! Do not overwrite values of spectral and broadband albedo during initialization
127! if they are already initialized in the urban-surface model via ASCII input.
128!
129! 3337 2018-10-12 15:17:09Z kanani
130! - New RTM version 2.9: (Pavel Krc, Jaroslav Resler, ICS, Prague)
131!   added calculation of the MRT inside the RTM module
132!   MRT fluxes are consequently used in the new biometeorology module
133!   for calculation of biological indices (MRT, PET)
134!   Fixes of v. 2.5 and SVN trunk:
135!    - proper initialization of rad_net_l
136!    - make arrays nsurfs and surfstart TARGET to prevent some MPI problems
137!    - initialization of arrays used in MPI one-sided operation as 1-D arrays
138!      to prevent problems with some MPI/compiler combinations
139!    - fix indexing of target displacement in subroutine request_itarget to
140!      consider nzub
141!    - fix LAD dimmension range in PCB calculation
142!    - check ierr in all MPI calls
143!    - use proper per-gridbox sky and diffuse irradiance
144!    - fix shading for reflected irradiance
145!    - clear away the residuals of "atmospheric surfaces" implementation
146!    - fix rounding bug in raytrace_2d introduced in SVN trunk
147! - New RTM version 2.5: (Pavel Krc, Jaroslav Resler, ICS, Prague)
148!   can use angular discretization for all SVF
149!   (i.e. reflected and emitted radiation in addition to direct and diffuse),
150!   allowing for much better scaling wih high resoltion and/or complex terrain
151! - Unite array grow factors
152! - Fix slightly shifted terrain height in raytrace_2d
153! - Use more efficient MPI_Win_allocate for reverse gridsurf index
154! - Fix random MPI RMA bugs on Intel compilers
155! - Fix approx. double plant canopy sink values for reflected radiation
156! - Fix mostly missing plant canopy sinks for direct radiation
157! - Fix discretization errors for plant canopy sink in diffuse radiation
158! - Fix rounding errors in raytrace_2d
159!
160! 3274 2018-09-24 15:42:55Z knoop
161! Modularization of all bulk cloud physics code components
162!
163! 3272 2018-09-24 10:16:32Z suehring
164! - split direct and diffusion shortwave radiation using RRTMG rather than using
165!   calc_diffusion_radiation, in case of RRTMG
166! - removed the namelist variable split_diffusion_radiation. Now splitting depends
167!   on the choise of radiation radiation scheme
168! - removed calculating the rdiation flux for surfaces at the radiation scheme
169!   in case of using RTM since it will be calculated anyway in the radiation
170!   interaction routine.
171! - set SW radiation flux for surfaces to zero at night in case of no RTM is used
172! - precalculate the unit vector yxdir of ray direction to avoid the temporarly
173!   array allocation during the subroutine call
174! - fixed a bug in calculating the max number of boxes ray can cross in the domain
175!
176! 3264 2018-09-20 13:54:11Z moh.hefny
177! Bugfix in raytrace_2d calls
178!
179! 3248 2018-09-14 09:42:06Z sward
180! Minor formating changes
181!
182! 3246 2018-09-13 15:14:50Z sward
183! Added error handling for input namelist via parin_fail_message
184!
185! 3241 2018-09-12 15:02:00Z raasch
186! unused variables removed or commented
187!
188! 3233 2018-09-07 13:21:24Z schwenkel
189! Adapted for the use of cloud_droplets
190!
191! 3230 2018-09-05 09:29:05Z schwenkel
192! Bugfix in radiation_constant_surf: changed (10.0 - emissivity_urb) to
193! (1.0 - emissivity_urb)
194!
195! 3226 2018-08-31 12:27:09Z suehring
196! Bugfixes in calculation of sky-view factors and canopy-sink factors.
197!
198! 3186 2018-07-30 17:07:14Z suehring
199! Remove print statement
200!
201! 3180 2018-07-27 11:00:56Z suehring
202! Revise concept for calculation of effective radiative temperature and mapping
203! of radiative heating
204!
205! 3175 2018-07-26 14:07:38Z suehring
206! Bugfix for commit 3172
207!
208! 3173 2018-07-26 12:55:23Z suehring
209! Revise output of surface radiation quantities in case of overhanging
210! structures
211!
212! 3172 2018-07-26 12:06:06Z suehring
213! Bugfixes:
214!  - temporal work-around for calculation of effective radiative surface
215!    temperature
216!  - prevent positive solar radiation during nighttime
217!
218! 3170 2018-07-25 15:19:37Z suehring
219! Bugfix, map signle-column radiation forcing profiles on top of any topography
220!
221! 3156 2018-07-19 16:30:54Z knoop
222! Bugfix: replaced usage of the pt array with the surf%pt_surface array
223!
224! 3137 2018-07-17 06:44:21Z maronga
225! String length for trace_names fixed
226!
227! 3127 2018-07-15 08:01:25Z maronga
228! A few pavement parameters updated.
229!
230! 3123 2018-07-12 16:21:53Z suehring
231! Correct working precision for INTEGER number
232!
233! 3122 2018-07-11 21:46:41Z maronga
234! Bugfix: maximum distance for raytracing was set to  -999 m by default,
235! effectively switching off all surface reflections when max_raytracing_dist
236! was not explicitly set in namelist
237!
238! 3117 2018-07-11 09:59:11Z maronga
239! Bugfix: water vapor was not transfered to RRTMG when bulk_cloud_model = .F.
240! Bugfix: changed the calculation of RRTMG boundary conditions (Mohamed Salim)
241! Bugfix: dry residual atmosphere is replaced by standard RRTMG atmosphere
242!
243! 3116 2018-07-10 14:31:58Z suehring
244! Output of long/shortwave radiation at surface
245!
246! 3107 2018-07-06 15:55:51Z suehring
247! Bugfix, missing index for dz
248!
249! 3066 2018-06-12 08:55:55Z Giersch
250! Error message revised
251!
252! 3065 2018-06-12 07:03:02Z Giersch
253! dz was replaced by dz(1), error message concerning vertical stretching was
254! added 
255!
256! 3049 2018-05-29 13:52:36Z Giersch
257! Error messages revised
258!
259! 3045 2018-05-28 07:55:41Z Giersch
260! Error message revised
261!
262! 3026 2018-05-22 10:30:53Z schwenkel
263! Changed the name specific humidity to mixing ratio, since we are computing
264! mixing ratios.
265!
266! 3016 2018-05-09 10:53:37Z Giersch
267! Revised structure of reading svf data according to PALM coding standard:
268! svf_code_field/len and fsvf removed, error messages PA0493 and PA0494 added,
269! allocation status of output arrays checked.
270!
271! 3014 2018-05-09 08:42:38Z maronga
272! Introduced plant canopy height similar to urban canopy height to limit
273! the memory requirement to allocate lad.
274! Deactivated automatic setting of minimum raytracing distance.
275!
276! 3004 2018-04-27 12:33:25Z Giersch
277! Further allocation checks implemented (averaged data will be assigned to fill
278! values if no allocation happened so far)
279!
280! 2995 2018-04-19 12:13:16Z Giersch
281! IF-statement in radiation_init removed so that the calculation of radiative
282! fluxes at model start is done in any case, bugfix in
283! radiation_presimulate_solar_pos (end_time is the sum of end_time and the
284! spinup_time specified in the p3d_file ), list of variables/fields that have
285! to be written out or read in case of restarts has been extended
286!
287! 2977 2018-04-17 10:27:57Z kanani
288! Implement changes from branch radiation (r2948-2971) with minor modifications,
289! plus some formatting.
290! (moh.hefny):
291! - replaced plant_canopy by npcbl to check tree existence to avoid weird
292!   allocation of related arrays (after domain decomposition some domains
293!   contains no trees although plant_canopy (global parameter) is still TRUE).
294! - added a namelist parameter to force RTM settings
295! - enabled the option to switch radiation reflections off
296! - renamed surf_reflections to surface_reflections
297! - removed average_radiation flag from the namelist (now it is implicitly set
298!   in init_3d_model according to RTM)
299! - edited read and write sky view factors and CSF routines to account for
300!   the sub-domains which may not contain any of them
301!
302! 2967 2018-04-13 11:22:08Z raasch
303! bugfix: missing parallel cpp-directives added
304!
305! 2964 2018-04-12 16:04:03Z Giersch
306! Error message PA0491 has been introduced which could be previously found in
307! check_open. The variable numprocs_previous_run is only known in case of
308! initializing_actions == read_restart_data
309!
310! 2963 2018-04-12 14:47:44Z suehring
311! - Introduce index for vegetation/wall, pavement/green-wall and water/window
312!   surfaces, for clearer access of surface fraction, albedo, emissivity, etc. .
313! - Minor bugfix in initialization of albedo for window surfaces
314!
315! 2944 2018-04-03 16:20:18Z suehring
316! Fixed bad commit
317!
318! 2943 2018-04-03 16:17:10Z suehring
319! No read of nsurfl from SVF file since it is calculated in
320! radiation_interaction_init,
321! allocation of arrays in radiation_read_svf only if not yet allocated,
322! update of 2920 revision comment.
323!
324! 2932 2018-03-26 09:39:22Z maronga
325! renamed radiation_par to radiation_parameters
326!
327! 2930 2018-03-23 16:30:46Z suehring
328! Remove default surfaces from radiation model, does not make much sense to
329! apply radiation model without energy-balance solvers; Further, add check for
330! this.
331!
332! 2920 2018-03-22 11:22:01Z kanani
333! - Bugfix: Initialize pcbl array (=-1)
334! RTM version 2.0 (Jaroslav Resler, Pavel Krc, Mohamed Salim):
335! - new major version of radiation interactions
336! - substantially enhanced performance and scalability
337! - processing of direct and diffuse solar radiation separated from reflected
338!   radiation, removed virtual surfaces
339! - new type of sky discretization by azimuth and elevation angles
340! - diffuse radiation processed cumulatively using sky view factor
341! - used precalculated apparent solar positions for direct irradiance
342! - added new 2D raytracing process for processing whole vertical column at once
343!   to increase memory efficiency and decrease number of MPI RMA operations
344! - enabled limiting the number of view factors between surfaces by the distance
345!   and value
346! - fixing issues induced by transferring radiation interactions from
347!   urban_surface_mod to radiation_mod
348! - bugfixes and other minor enhancements
349!
350! 2906 2018-03-19 08:56:40Z Giersch
351! NAMELIST paramter read/write_svf_on_init have been removed, functions
352! check_open and close_file are used now for opening/closing files related to
353! svf data, adjusted unit number and error numbers
354!
355! 2894 2018-03-15 09:17:58Z Giersch
356! Calculations of the index range of the subdomain on file which overlaps with
357! the current subdomain are already done in read_restart_data_mod
358! radiation_read_restart_data was renamed to radiation_rrd_local and
359! radiation_last_actions was renamed to radiation_wrd_local, variable named
360! found has been introduced for checking if restart data was found, reading
361! of restart strings has been moved completely to read_restart_data_mod,
362! radiation_rrd_local is already inside the overlap loop programmed in
363! read_restart_data_mod, the marker *** end rad *** is not necessary anymore,
364! strings and their respective lengths are written out and read now in case of
365! restart runs to get rid of prescribed character lengths (Giersch)
366!
367! 2809 2018-02-15 09:55:58Z suehring
368! Bugfix for gfortran: Replace the function C_SIZEOF with STORAGE_SIZE
369!
370! 2753 2018-01-16 14:16:49Z suehring
371! Tile approach for spectral albedo implemented.
372!
373! 2746 2018-01-15 12:06:04Z suehring
374! Move flag plant canopy to modules
375!
376! 2724 2018-01-05 12:12:38Z maronga
377! Set default of average_radiation to .FALSE.
378!
379! 2723 2018-01-05 09:27:03Z maronga
380! Bugfix in calculation of rad_lw_out (clear-sky). First grid level was used
381! instead of the surface value
382!
383! 2718 2018-01-02 08:49:38Z maronga
384! Corrected "Former revisions" section
385!
386! 2707 2017-12-18 18:34:46Z suehring
387! Changes from last commit documented
388!
389! 2706 2017-12-18 18:33:49Z suehring
390! Bugfix, in average radiation case calculate exner function before using it.
391!
392! 2701 2017-12-15 15:40:50Z suehring
393! Changes from last commit documented
394!
395! 2698 2017-12-14 18:46:24Z suehring
396! Bugfix in get_topography_top_index
397!
398! 2696 2017-12-14 17:12:51Z kanani
399! - Change in file header (GPL part)
400! - Improved reading/writing of SVF from/to file (BM)
401! - Bugfixes concerning RRTMG as well as average_radiation options (M. Salim)
402! - Revised initialization of surface albedo and some minor bugfixes (MS)
403! - Update net radiation after running radiation interaction routine (MS)
404! - Revisions from M Salim included
405! - Adjustment to topography and surface structure (MS)
406! - Initialization of albedo and surface emissivity via input file (MS)
407! - albedo_pars extended (MS)
408!
409! 2604 2017-11-06 13:29:00Z schwenkel
410! bugfix for calculation of effective radius using morrison microphysics
411!
412! 2601 2017-11-02 16:22:46Z scharf
413! added emissivity to namelist
414!
415! 2575 2017-10-24 09:57:58Z maronga
416! Bugfix: calculation of shortwave and longwave albedos for RRTMG swapped
417!
418! 2547 2017-10-16 12:41:56Z schwenkel
419! extended by cloud_droplets option, minor bugfix and correct calculation of
420! cloud droplet number concentration
421!
422! 2544 2017-10-13 18:09:32Z maronga
423! Moved date and time quantitis to separate module date_and_time_mod
424!
425! 2512 2017-10-04 08:26:59Z raasch
426! upper bounds of cross section and 3d output changed from nx+1,ny+1 to nx,ny
427! no output of ghost layer data
428!
429! 2504 2017-09-27 10:36:13Z maronga
430! Updates pavement types and albedo parameters
431!
432! 2328 2017-08-03 12:34:22Z maronga
433! Emissivity can now be set individually for each pixel.
434! Albedo type can be inferred from land surface model.
435! Added default albedo type for bare soil
436!
437! 2318 2017-07-20 17:27:44Z suehring
438! Get topography top index via Function call
439!
440! 2317 2017-07-20 17:27:19Z suehring
441! Improved syntax layout
442!
443! 2298 2017-06-29 09:28:18Z raasch
444! type of write_binary changed from CHARACTER to LOGICAL
445!
446! 2296 2017-06-28 07:53:56Z maronga
447! Added output of rad_sw_out for radiation_scheme = 'constant'
448!
449! 2270 2017-06-09 12:18:47Z maronga
450! Numbering changed (2 timeseries removed)
451!
452! 2249 2017-06-06 13:58:01Z sward
453! Allow for RRTMG runs without humidity/cloud physics
454!
455! 2248 2017-06-06 13:52:54Z sward
456! Error no changed
457!
458! 2233 2017-05-30 18:08:54Z suehring
459!
460! 2232 2017-05-30 17:47:52Z suehring
461! Adjustments to new topography concept
462! Bugfix in read restart
463!
464! 2200 2017-04-11 11:37:51Z suehring
465! Bugfix in call of exchange_horiz_2d and read restart data
466!
467! 2163 2017-03-01 13:23:15Z schwenkel
468! Bugfix in radiation_check_data_output
469!
470! 2157 2017-02-22 15:10:35Z suehring
471! Bugfix in read_restart data
472!
473! 2011 2016-09-19 17:29:57Z kanani
474! Removed CALL of auxiliary SUBROUTINE get_usm_info,
475! flag urban_surface is now defined in module control_parameters.
476!
477! 2007 2016-08-24 15:47:17Z kanani
478! Added calculation of solar directional vector for new urban surface
479! model,
480! accounted for urban_surface model in radiation_check_parameters,
481! correction of comments for zenith angle.
482!
483! 2000 2016-08-20 18:09:15Z knoop
484! Forced header and separation lines into 80 columns
485!
486! 1976 2016-07-27 13:28:04Z maronga
487! Output of 2D/3D/masked data is now directly done within this module. The
488! radiation schemes have been simplified for better usability so that
489! rad_lw_in, rad_lw_out, rad_sw_in, and rad_sw_out are available independent of
490! the radiation code used.
491!
492! 1856 2016-04-13 12:56:17Z maronga
493! Bugfix: allocation of rad_lw_out for radiation_scheme = 'clear-sky'
494!
495! 1853 2016-04-11 09:00:35Z maronga
496! Added routine for radiation_scheme = constant.
497
498! 1849 2016-04-08 11:33:18Z hoffmann
499! Adapted for modularization of microphysics
500!
501! 1826 2016-04-07 12:01:39Z maronga
502! Further modularization.
503!
504! 1788 2016-03-10 11:01:04Z maronga
505! Added new albedo class for pavements / roads.
506!
507! 1783 2016-03-06 18:36:17Z raasch
508! palm-netcdf-module removed in order to avoid a circular module dependency,
509! netcdf-variables moved to netcdf-module, new routine netcdf_handle_error_rad
510! added
511!
512! 1757 2016-02-22 15:49:32Z maronga
513! Added parameter unscheduled_radiation_calls. Bugfix: interpolation of sounding
514! profiles for pressure and temperature above the LES domain.
515!
516! 1709 2015-11-04 14:47:01Z maronga
517! Bugfix: set initial value for rrtm_lwuflx_dt to zero, small formatting
518! corrections
519!
520! 1701 2015-11-02 07:43:04Z maronga
521! Bugfixes: wrong index for output of timeseries, setting of nz_snd_end
522!
523! 1691 2015-10-26 16:17:44Z maronga
524! Added option for spin-up runs without radiation (skip_time_do_radiation). Bugfix
525! in calculation of pressure profiles. Bugfix in calculation of trace gas profiles.
526! Added output of radiative heating rates.
527!
528! 1682 2015-10-07 23:56:08Z knoop
529! Code annotations made doxygen readable
530!
531! 1606 2015-06-29 10:43:37Z maronga
532! Added preprocessor directive __netcdf to allow for compiling without netCDF.
533! Note, however, that RRTMG cannot be used without netCDF.
534!
535! 1590 2015-05-08 13:56:27Z maronga
536! Bugfix: definition of character strings requires same length for all elements
537!
538! 1587 2015-05-04 14:19:01Z maronga
539! Added albedo class for snow
540!
541! 1585 2015-04-30 07:05:52Z maronga
542! Added support for RRTMG
543!
544! 1571 2015-03-12 16:12:49Z maronga
545! Added missing KIND attribute. Removed upper-case variable names
546!
547! 1551 2015-03-03 14:18:16Z maronga
548! Added support for data output. Various variables have been renamed. Added
549! interface for different radiation schemes (currently: clear-sky, constant, and
550! RRTM (not yet implemented).
551!
552! 1496 2014-12-02 17:25:50Z maronga
553! Initial revision
554!
555!
556! Description:
557! ------------
558!> Radiation models and interfaces
559!> @todo Replace dz(1) appropriatly to account for grid stretching
560!> @todo move variable definitions used in radiation_init only to the subroutine
561!>       as they are no longer required after initialization.
562!> @todo Output of full column vertical profiles used in RRTMG
563!> @todo Output of other rrtm arrays (such as volume mixing ratios)
564!> @todo Check for mis-used NINT() calls in raytrace_2d
565!>       RESULT: Original was correct (carefully verified formula), the change
566!>               to INT broke raytracing      -- P. Krc
567!> @todo Optimize radiation_tendency routines
568!>
569!> @note Many variables have a leading dummy dimension (0:0) in order to
570!>       match the assume-size shape expected by the RRTMG model.
571!------------------------------------------------------------------------------!
572 MODULE radiation_model_mod
573 
574    USE arrays_3d,                                                             &
575        ONLY:  dzw, hyp, nc, pt, p, q, ql, u, v, w, zu, zw, exner, d_exner
576
577    USE basic_constants_and_equations_mod,                                     &
578        ONLY:  c_p, g, lv_d_cp, l_v, pi, r_d, rho_l, solar_constant,      &
579               barometric_formula
580
581    USE calc_mean_profile_mod,                                                 &
582        ONLY:  calc_mean_profile
583
584    USE control_parameters,                                                    &
585        ONLY:  cloud_droplets, coupling_char, dz, dt_spinup, end_time,         &
586               humidity,                                                       &
587               initializing_actions, io_blocks, io_group,                      &
588               land_surface, large_scale_forcing,                              &
589               latitude, longitude, lsf_surf,                                  &
590               message_string, plant_canopy, pt_surface,                       &
591               rho_surface, simulated_time, spinup_time, surface_pressure,     &
592               read_svf, write_svf,                                            &
593               time_since_reference_point, urban_surface, varnamelength
594
595    USE cpulog,                                                                &
596        ONLY:  cpu_log, log_point, log_point_s
597
598    USE grid_variables,                                                        &
599         ONLY:  ddx, ddy, dx, dy 
600
601    USE date_and_time_mod,                                                     &
602        ONLY:  calc_date_and_time, d_hours_day, d_seconds_hour, d_seconds_year,&
603               day_of_year, d_seconds_year, day_of_month, day_of_year_init,    &
604               init_date_and_time, month_of_year, time_utc_init, time_utc
605
606    USE indices,                                                               &
607        ONLY:  nnx, nny, nx, nxl, nxlg, nxr, nxrg, ny, nyn, nyng, nys, nysg,   &
608               nzb, nzt
609
610    USE, INTRINSIC :: iso_c_binding
611
612    USE kinds
613
614    USE bulk_cloud_model_mod,                                                  &
615        ONLY:  bulk_cloud_model, microphysics_morrison, na_init, nc_const, sigma_gc
616
617#if defined ( __netcdf )
618    USE NETCDF
619#endif
620
621    USE netcdf_data_input_mod,                                                 &
622        ONLY:  albedo_type_f, albedo_pars_f, building_type_f, pavement_type_f, &
623               vegetation_type_f, water_type_f
624
625    USE plant_canopy_model_mod,                                                &
626        ONLY:  lad_s, pc_heating_rate, pc_transpiration_rate, pc_latent_rate,  &
627               plant_canopy_transpiration, pcm_calc_transpiration_rate
628
629    USE pegrid
630
631#if defined ( __rrtmg )
632    USE parrrsw,                                                               &
633        ONLY:  naerec, nbndsw
634
635    USE parrrtm,                                                               &
636        ONLY:  nbndlw
637
638    USE rrtmg_lw_init,                                                         &
639        ONLY:  rrtmg_lw_ini
640
641    USE rrtmg_sw_init,                                                         &
642        ONLY:  rrtmg_sw_ini
643
644    USE rrtmg_lw_rad,                                                          &
645        ONLY:  rrtmg_lw
646
647    USE rrtmg_sw_rad,                                                          &
648        ONLY:  rrtmg_sw
649#endif
650    USE statistics,                                                            &
651        ONLY:  hom
652
653    USE surface_mod,                                                           &
654        ONLY:  get_topography_top_index, get_topography_top_index_ji,          &
655               ind_pav_green, ind_veg_wall, ind_wat_win,                       &
656               surf_lsm_h, surf_lsm_v, surf_type, surf_usm_h, surf_usm_v,      &
657               vertical_surfaces_exist
658
659    IMPLICIT NONE
660
661    CHARACTER(10) :: radiation_scheme = 'clear-sky' ! 'constant', 'clear-sky', or 'rrtmg'
662
663!
664!-- Predefined Land surface classes (albedo_type) after Briegleb (1992)
665    CHARACTER(37), DIMENSION(0:33), PARAMETER :: albedo_type_name = (/      &
666                                   'user defined                         ', & !  0
667                                   'ocean                                ', & !  1
668                                   'mixed farming, tall grassland        ', & !  2
669                                   'tall/medium grassland                ', & !  3
670                                   'evergreen shrubland                  ', & !  4
671                                   'short grassland/meadow/shrubland     ', & !  5
672                                   'evergreen needleleaf forest          ', & !  6
673                                   'mixed deciduous evergreen forest     ', & !  7
674                                   'deciduous forest                     ', & !  8
675                                   'tropical evergreen broadleaved forest', & !  9
676                                   'medium/tall grassland/woodland       ', & ! 10
677                                   'desert, sandy                        ', & ! 11
678                                   'desert, rocky                        ', & ! 12
679                                   'tundra                               ', & ! 13
680                                   'land ice                             ', & ! 14
681                                   'sea ice                              ', & ! 15
682                                   'snow                                 ', & ! 16
683                                   'bare soil                            ', & ! 17
684                                   'asphalt/concrete mix                 ', & ! 18
685                                   'asphalt (asphalt concrete)           ', & ! 19
686                                   'concrete (Portland concrete)         ', & ! 20
687                                   'sett                                 ', & ! 21
688                                   'paving stones                        ', & ! 22
689                                   'cobblestone                          ', & ! 23
690                                   'metal                                ', & ! 24
691                                   'wood                                 ', & ! 25
692                                   'gravel                               ', & ! 26
693                                   'fine gravel                          ', & ! 27
694                                   'pebblestone                          ', & ! 28
695                                   'woodchips                            ', & ! 29
696                                   'tartan (sports)                      ', & ! 30
697                                   'artifical turf (sports)              ', & ! 31
698                                   'clay (sports)                        ', & ! 32
699                                   'building (dummy)                     '  & ! 33
700                                                         /)
701
702    REAL(wp), PARAMETER :: sigma_sb       = 5.67037321E-8_wp !< Stefan-Boltzmann constant
703
704    INTEGER(iwp) :: albedo_type  = 9999999, & !< Albedo surface type
705                    dots_rad     = 0          !< starting index for timeseries output
706
707    LOGICAL ::  unscheduled_radiation_calls = .TRUE., & !< flag parameter indicating whether additional calls of the radiation code are allowed
708                constant_albedo = .FALSE.,            & !< flag parameter indicating whether the albedo may change depending on zenith
709                force_radiation_call = .FALSE.,       & !< flag parameter for unscheduled radiation calls
710                lw_radiation = .TRUE.,                & !< flag parameter indicating whether longwave radiation shall be calculated
711                radiation = .FALSE.,                  & !< flag parameter indicating whether the radiation model is used
712                sun_up    = .TRUE.,                   & !< flag parameter indicating whether the sun is up or down
713                sw_radiation = .TRUE.,                & !< flag parameter indicating whether shortwave radiation shall be calculated
714                sun_direction = .FALSE.,              & !< flag parameter indicating whether solar direction shall be calculated
715                average_radiation = .FALSE.,          & !< flag to set the calculation of radiation averaging for the domain
716                radiation_interactions = .FALSE.,     & !< flag to activiate RTM (TRUE only if vertical urban/land surface and trees exist)
717                surface_reflections = .TRUE.,         & !< flag to switch the calculation of radiation interaction between surfaces.
718                                                        !< When it switched off, only the effect of buildings and trees shadow
719                                                        !< will be considered. However fewer SVFs are expected.
720                radiation_interactions_on = .TRUE.      !< namelist flag to force RTM activiation regardless to vertical urban/land surface and trees
721
722    REAL(wp) :: albedo = 9999999.9_wp,           & !< NAMELIST alpha
723                albedo_lw_dif = 9999999.9_wp,    & !< NAMELIST aldif
724                albedo_lw_dir = 9999999.9_wp,    & !< NAMELIST aldir
725                albedo_sw_dif = 9999999.9_wp,    & !< NAMELIST asdif
726                albedo_sw_dir = 9999999.9_wp,    & !< NAMELIST asdir
727                decl_1,                          & !< declination coef. 1
728                decl_2,                          & !< declination coef. 2
729                decl_3,                          & !< declination coef. 3
730                dt_radiation = 0.0_wp,           & !< radiation model timestep
731                emissivity = 9999999.9_wp,       & !< NAMELIST surface emissivity
732                lon = 0.0_wp,                    & !< longitude in radians
733                lat = 0.0_wp,                    & !< latitude in radians
734                net_radiation = 0.0_wp,          & !< net radiation at surface
735                skip_time_do_radiation = 0.0_wp, & !< Radiation model is not called before this time
736                sky_trans,                       & !< sky transmissivity
737                time_radiation = 0.0_wp            !< time since last call of radiation code
738
739
740    REAL(wp), DIMENSION(0:0) ::  zenith,         & !< cosine of solar zenith angle
741                                 sun_dir_lat,    & !< solar directional vector in latitudes
742                                 sun_dir_lon       !< solar directional vector in longitudes
743
744    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_net_av       !< average of net radiation (rad_net) at surface
745    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_lw_in_xy_av  !< average of incoming longwave radiation at surface
746    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_lw_out_xy_av !< average of outgoing longwave radiation at surface
747    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_sw_in_xy_av  !< average of incoming shortwave radiation at surface
748    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_sw_out_xy_av !< average of outgoing shortwave radiation at surface
749!
750!-- Land surface albedos for solar zenith angle of 60degree after Briegleb (1992)     
751!-- (shortwave, longwave, broadband):   sw,      lw,      bb,
752    REAL(wp), DIMENSION(0:2,1:33), PARAMETER :: albedo_pars = RESHAPE( (/& 
753                                   0.06_wp, 0.06_wp, 0.06_wp,            & !  1
754                                   0.09_wp, 0.28_wp, 0.19_wp,            & !  2
755                                   0.11_wp, 0.33_wp, 0.23_wp,            & !  3
756                                   0.11_wp, 0.33_wp, 0.23_wp,            & !  4
757                                   0.14_wp, 0.34_wp, 0.25_wp,            & !  5
758                                   0.06_wp, 0.22_wp, 0.14_wp,            & !  6
759                                   0.06_wp, 0.27_wp, 0.17_wp,            & !  7
760                                   0.06_wp, 0.31_wp, 0.19_wp,            & !  8
761                                   0.06_wp, 0.22_wp, 0.14_wp,            & !  9
762                                   0.06_wp, 0.28_wp, 0.18_wp,            & ! 10
763                                   0.35_wp, 0.51_wp, 0.43_wp,            & ! 11
764                                   0.24_wp, 0.40_wp, 0.32_wp,            & ! 12
765                                   0.10_wp, 0.27_wp, 0.19_wp,            & ! 13
766                                   0.90_wp, 0.65_wp, 0.77_wp,            & ! 14
767                                   0.90_wp, 0.65_wp, 0.77_wp,            & ! 15
768                                   0.95_wp, 0.70_wp, 0.82_wp,            & ! 16
769                                   0.08_wp, 0.08_wp, 0.08_wp,            & ! 17
770                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 18
771                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 19
772                                   0.30_wp, 0.30_wp, 0.30_wp,            & ! 20
773                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 21
774                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 22
775                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 23
776                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 24
777                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 25
778                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 26
779                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 27
780                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 28
781                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 29
782                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 30
783                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 31
784                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 32
785                                   0.17_wp, 0.17_wp, 0.17_wp             & ! 33
786                                 /), (/ 3, 33 /) )
787
788    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE, TARGET :: &
789                        rad_lw_cs_hr,                  & !< longwave clear sky radiation heating rate (K/s)
790                        rad_lw_cs_hr_av,               & !< average of rad_lw_cs_hr
791                        rad_lw_hr,                     & !< longwave radiation heating rate (K/s)
792                        rad_lw_hr_av,                  & !< average of rad_sw_hr
793                        rad_lw_in,                     & !< incoming longwave radiation (W/m2)
794                        rad_lw_in_av,                  & !< average of rad_lw_in
795                        rad_lw_out,                    & !< outgoing longwave radiation (W/m2)
796                        rad_lw_out_av,                 & !< average of rad_lw_out
797                        rad_sw_cs_hr,                  & !< shortwave clear sky radiation heating rate (K/s)
798                        rad_sw_cs_hr_av,               & !< average of rad_sw_cs_hr
799                        rad_sw_hr,                     & !< shortwave radiation heating rate (K/s)
800                        rad_sw_hr_av,                  & !< average of rad_sw_hr
801                        rad_sw_in,                     & !< incoming shortwave radiation (W/m2)
802                        rad_sw_in_av,                  & !< average of rad_sw_in
803                        rad_sw_out,                    & !< outgoing shortwave radiation (W/m2)
804                        rad_sw_out_av                    !< average of rad_sw_out
805
806
807!
808!-- Variables and parameters used in RRTMG only
809#if defined ( __rrtmg )
810    CHARACTER(LEN=12) :: rrtm_input_file = "RAD_SND_DATA" !< name of the NetCDF input file (sounding data)
811
812
813!
814!-- Flag parameters for RRTMGS (should not be changed)
815    INTEGER(iwp), PARAMETER :: rrtm_idrv     = 1, & !< flag for longwave upward flux calculation option (0,1)
816                               rrtm_inflglw  = 2, & !< flag for lw cloud optical properties (0,1,2)
817                               rrtm_iceflglw = 0, & !< flag for lw ice particle specifications (0,1,2,3)
818                               rrtm_liqflglw = 1, & !< flag for lw liquid droplet specifications
819                               rrtm_inflgsw  = 2, & !< flag for sw cloud optical properties (0,1,2)
820                               rrtm_iceflgsw = 0, & !< flag for sw ice particle specifications (0,1,2,3)
821                               rrtm_liqflgsw = 1    !< flag for sw liquid droplet specifications
822
823!
824!-- The following variables should be only changed with care, as this will
825!-- require further setting of some variables, which is currently not
826!-- implemented (aerosols, ice phase).
827    INTEGER(iwp) :: nzt_rad,           & !< upper vertical limit for radiation calculations
828                    rrtm_icld = 0,     & !< cloud flag (0: clear sky column, 1: cloudy column)
829                    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)
830
831    INTEGER(iwp) :: nc_stat !< local variable for storin the result of netCDF calls for error message handling
832
833    LOGICAL :: snd_exists = .FALSE.      !< flag parameter to check whether a user-defined input files exists
834    LOGICAL :: sw_exists = .FALSE.       !< flag parameter to check whether that required rrtmg sw file exists
835    LOGICAL :: lw_exists = .FALSE.       !< flag parameter to check whether that required rrtmg lw file exists
836
837
838    REAL(wp), PARAMETER :: mol_mass_air_d_wv = 1.607793_wp !< molecular weight dry air / water vapor
839
840    REAL(wp), DIMENSION(:), ALLOCATABLE :: hyp_snd,     & !< hypostatic pressure from sounding data (hPa)
841                                           rrtm_tsfc,   & !< dummy array for storing surface temperature
842                                           t_snd          !< actual temperature from sounding data (hPa)
843
844    REAL(wp), DIMENSION(:,:), ALLOCATABLE :: rrtm_ccl4vmr,   & !< CCL4 volume mixing ratio (g/mol)
845                                             rrtm_cfc11vmr,  & !< CFC11 volume mixing ratio (g/mol)
846                                             rrtm_cfc12vmr,  & !< CFC12 volume mixing ratio (g/mol)
847                                             rrtm_cfc22vmr,  & !< CFC22 volume mixing ratio (g/mol)
848                                             rrtm_ch4vmr,    & !< CH4 volume mixing ratio
849                                             rrtm_cicewp,    & !< in-cloud ice water path (g/m2)
850                                             rrtm_cldfr,     & !< cloud fraction (0,1)
851                                             rrtm_cliqwp,    & !< in-cloud liquid water path (g/m2)
852                                             rrtm_co2vmr,    & !< CO2 volume mixing ratio (g/mol)
853                                             rrtm_emis,      & !< surface emissivity (0-1) 
854                                             rrtm_h2ovmr,    & !< H2O volume mixing ratio
855                                             rrtm_n2ovmr,    & !< N2O volume mixing ratio
856                                             rrtm_o2vmr,     & !< O2 volume mixing ratio
857                                             rrtm_o3vmr,     & !< O3 volume mixing ratio
858                                             rrtm_play,      & !< pressure layers (hPa, zu-grid)
859                                             rrtm_plev,      & !< pressure layers (hPa, zw-grid)
860                                             rrtm_reice,     & !< cloud ice effective radius (microns)
861                                             rrtm_reliq,     & !< cloud water drop effective radius (microns)
862                                             rrtm_tlay,      & !< actual temperature (K, zu-grid)
863                                             rrtm_tlev,      & !< actual temperature (K, zw-grid)
864                                             rrtm_lwdflx,    & !< RRTM output of incoming longwave radiation flux (W/m2)
865                                             rrtm_lwdflxc,   & !< RRTM output of outgoing clear sky longwave radiation flux (W/m2)
866                                             rrtm_lwuflx,    & !< RRTM output of outgoing longwave radiation flux (W/m2)
867                                             rrtm_lwuflxc,   & !< RRTM output of incoming clear sky longwave radiation flux (W/m2)
868                                             rrtm_lwuflx_dt, & !< RRTM output of incoming clear sky longwave radiation flux (W/m2)
869                                             rrtm_lwuflxc_dt,& !< RRTM output of outgoing clear sky longwave radiation flux (W/m2)
870                                             rrtm_lwhr,      & !< RRTM output of longwave radiation heating rate (K/d)
871                                             rrtm_lwhrc,     & !< RRTM output of incoming longwave clear sky radiation heating rate (K/d)
872                                             rrtm_swdflx,    & !< RRTM output of incoming shortwave radiation flux (W/m2)
873                                             rrtm_swdflxc,   & !< RRTM output of outgoing clear sky shortwave radiation flux (W/m2)
874                                             rrtm_swuflx,    & !< RRTM output of outgoing shortwave radiation flux (W/m2)
875                                             rrtm_swuflxc,   & !< RRTM output of incoming clear sky shortwave radiation flux (W/m2)
876                                             rrtm_swhr,      & !< RRTM output of shortwave radiation heating rate (K/d)
877                                             rrtm_swhrc,     & !< RRTM output of incoming shortwave clear sky radiation heating rate (K/d)
878                                             rrtm_dirdflux,  & !< RRTM output of incoming direct shortwave (W/m2)
879                                             rrtm_difdflux     !< RRTM output of incoming diffuse shortwave (W/m2)
880
881    REAL(wp), DIMENSION(1) ::                rrtm_aldif,     & !< surface albedo for longwave diffuse radiation
882                                             rrtm_aldir,     & !< surface albedo for longwave direct radiation
883                                             rrtm_asdif,     & !< surface albedo for shortwave diffuse radiation
884                                             rrtm_asdir        !< surface albedo for shortwave direct radiation
885
886!
887!-- Definition of arrays that are currently not used for calling RRTMG (due to setting of flag parameters)
888    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::  rad_lw_cs_in,   & !< incoming clear sky longwave radiation (W/m2) (not used)
889                                                rad_lw_cs_out,  & !< outgoing clear sky longwave radiation (W/m2) (not used)
890                                                rad_sw_cs_in,   & !< incoming clear sky shortwave radiation (W/m2) (not used)
891                                                rad_sw_cs_out,  & !< outgoing clear sky shortwave radiation (W/m2) (not used)
892                                                rrtm_lw_tauaer, & !< lw aerosol optical depth
893                                                rrtm_lw_taucld, & !< lw in-cloud optical depth
894                                                rrtm_sw_taucld, & !< sw in-cloud optical depth
895                                                rrtm_sw_ssacld, & !< sw in-cloud single scattering albedo
896                                                rrtm_sw_asmcld, & !< sw in-cloud asymmetry parameter
897                                                rrtm_sw_fsfcld, & !< sw in-cloud forward scattering fraction
898                                                rrtm_sw_tauaer, & !< sw aerosol optical depth
899                                                rrtm_sw_ssaaer, & !< sw aerosol single scattering albedo
900                                                rrtm_sw_asmaer, & !< sw aerosol asymmetry parameter
901                                                rrtm_sw_ecaer     !< sw aerosol optical detph at 0.55 microns (rrtm_iaer = 6 only)
902
903#endif
904!
905!-- Parameters of urban and land surface models
906    INTEGER(iwp)                                   ::  nzu                                !< number of layers of urban surface (will be calculated)
907    INTEGER(iwp)                                   ::  nzp                                !< number of layers of plant canopy (will be calculated)
908    INTEGER(iwp)                                   ::  nzub,nzut                          !< bottom and top layer of urban surface (will be calculated)
909    INTEGER(iwp)                                   ::  nzpt                               !< top layer of plant canopy (will be calculated)
910!-- parameters of urban and land surface models
911    INTEGER(iwp), PARAMETER                        ::  nzut_free = 3                      !< number of free layers above top of of topography
912    INTEGER(iwp), PARAMETER                        ::  ndsvf = 2                          !< number of dimensions of real values in SVF
913    INTEGER(iwp), PARAMETER                        ::  idsvf = 2                          !< number of dimensions of integer values in SVF
914    INTEGER(iwp), PARAMETER                        ::  ndcsf = 1                          !< number of dimensions of real values in CSF
915    INTEGER(iwp), PARAMETER                        ::  idcsf = 2                          !< number of dimensions of integer values in CSF
916    INTEGER(iwp), PARAMETER                        ::  kdcsf = 4                          !< number of dimensions of integer values in CSF calculation array
917    INTEGER(iwp), PARAMETER                        ::  id = 1                             !< position of d-index in surfl and surf
918    INTEGER(iwp), PARAMETER                        ::  iz = 2                             !< position of k-index in surfl and surf
919    INTEGER(iwp), PARAMETER                        ::  iy = 3                             !< position of j-index in surfl and surf
920    INTEGER(iwp), PARAMETER                        ::  ix = 4                             !< position of i-index in surfl and surf
921
922    INTEGER(iwp), PARAMETER                        ::  nsurf_type = 10                    !< number of surf types incl. phys.(land+urban) & (atm.,sky,boundary) surfaces - 1
923
924    INTEGER(iwp), PARAMETER                        ::  iup_u    = 0                       !< 0 - index of urban upward surface (ground or roof)
925    INTEGER(iwp), PARAMETER                        ::  idown_u  = 1                       !< 1 - index of urban downward surface (overhanging)
926    INTEGER(iwp), PARAMETER                        ::  inorth_u = 2                       !< 2 - index of urban northward facing wall
927    INTEGER(iwp), PARAMETER                        ::  isouth_u = 3                       !< 3 - index of urban southward facing wall
928    INTEGER(iwp), PARAMETER                        ::  ieast_u  = 4                       !< 4 - index of urban eastward facing wall
929    INTEGER(iwp), PARAMETER                        ::  iwest_u  = 5                       !< 5 - index of urban westward facing wall
930
931    INTEGER(iwp), PARAMETER                        ::  iup_l    = 6                       !< 6 - index of land upward surface (ground or roof)
932    INTEGER(iwp), PARAMETER                        ::  inorth_l = 7                       !< 7 - index of land northward facing wall
933    INTEGER(iwp), PARAMETER                        ::  isouth_l = 8                       !< 8 - index of land southward facing wall
934    INTEGER(iwp), PARAMETER                        ::  ieast_l  = 9                       !< 9 - index of land eastward facing wall
935    INTEGER(iwp), PARAMETER                        ::  iwest_l  = 10                      !< 10- index of land westward facing wall
936
937    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  idir = (/0, 0,0, 0,1,-1,0,0, 0,1,-1/)   !< surface normal direction x indices
938    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  jdir = (/0, 0,1,-1,0, 0,0,1,-1,0, 0/)   !< surface normal direction y indices
939    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  kdir = (/1,-1,0, 0,0, 0,1,0, 0,0, 0/)   !< surface normal direction z indices
940    REAL(wp),     DIMENSION(0:nsurf_type)          :: facearea                            !< area of single face in respective
941                                                                                          !< direction (will be calc'd)
942
943
944!-- indices and sizes of urban and land surface models
945    INTEGER(iwp)                                   ::  startland        !< start index of block of land and roof surfaces
946    INTEGER(iwp)                                   ::  endland          !< end index of block of land and roof surfaces
947    INTEGER(iwp)                                   ::  nlands           !< number of land and roof surfaces in local processor
948    INTEGER(iwp)                                   ::  startwall        !< start index of block of wall surfaces
949    INTEGER(iwp)                                   ::  endwall          !< end index of block of wall surfaces
950    INTEGER(iwp)                                   ::  nwalls           !< number of wall surfaces in local processor
951
952!-- indices needed for RTM netcdf output subroutines
953    INTEGER(iwp), PARAMETER                        :: nd = 5
954    CHARACTER(LEN=6), DIMENSION(0:nd-1), PARAMETER :: dirname = (/ '_roof ', '_south', '_north', '_west ', '_east ' /)
955    INTEGER(iwp), DIMENSION(0:nd-1), PARAMETER     :: dirint_u = (/ iup_u, isouth_u, inorth_u, iwest_u, ieast_u /)
956    INTEGER(iwp), DIMENSION(0:nd-1), PARAMETER     :: dirint_l = (/ iup_l, isouth_l, inorth_l, iwest_l, ieast_l /)
957    INTEGER(iwp), DIMENSION(0:nd-1)                :: dirstart
958    INTEGER(iwp), DIMENSION(0:nd-1)                :: dirend
959
960!-- indices and sizes of urban and land surface models
961    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surfl_l          !< coordinates of i-th local surface in local grid - surfl[:,k] = [d, z, y, x]
962    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surf_l           !< coordinates of i-th surface in grid - surf[:,k] = [d, z, y, x]
963    INTEGER(iwp), DIMENSION(:,:), POINTER          ::  surfl            !< coordinates of i-th local surface in local grid - surfl[:,k] = [d, z, y, x]
964    INTEGER(iwp), DIMENSION(:,:), POINTER          ::  surf             !< coordinates of i-th surface in grid - surf[:,k] = [d, z, y, x]
965    INTEGER(iwp)                                   ::  nsurfl           !< number of all surfaces in local processor
966    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  nsurfs           !< array of number of all surfaces in individual processors
967    INTEGER(iwp)                                   ::  nsurf            !< global number of surfaces in index array of surfaces (nsurf = proc nsurfs)
968    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surfstart        !< starts of blocks of surfaces for individual processors in array surf (indexed from 1)
969                                                                        !< respective block for particular processor is surfstart[iproc+1]+1 : surfstart[iproc+1]+nsurfs[iproc+1]
970
971!-- block variables needed for calculation of the plant canopy model inside the urban surface model
972    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pct              !< top layer of the plant canopy
973    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pch              !< heights of the plant canopy
974    INTEGER(iwp)                                   ::  npcbl = 0        !< number of the plant canopy gridboxes in local processor
975    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pcbl             !< k,j,i coordinates of l-th local plant canopy box pcbl[:,l] = [k, j, i]
976    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinsw          !< array of absorbed sw radiation for local plant canopy box
977    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdir       !< array of absorbed direct sw radiation for local plant canopy box
978    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdif       !< array of absorbed diffusion sw radiation for local plant canopy box
979    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinlw          !< array of absorbed lw radiation for local plant canopy box
980
981!-- configuration parameters (they can be setup in PALM config)
982    LOGICAL                                        ::  raytrace_mpi_rma = .TRUE.          !< use MPI RMA to access LAD and gridsurf from remote processes during raytracing
983    LOGICAL                                        ::  rad_angular_discretization = .TRUE.!< whether to use fixed resolution discretization of view factors for
984                                                                                          !< reflected radiation (as opposed to all mutually visible pairs)
985    LOGICAL                                        ::  plant_lw_interact = .TRUE.         !< whether plant canopy interacts with LW radiation (in addition to SW)
986    INTEGER(iwp)                                   ::  mrt_nlevels = 0                    !< number of vertical boxes above surface for which to calculate MRT
987    LOGICAL                                        ::  mrt_skip_roof = .TRUE.             !< do not calculate MRT above roof surfaces
988    LOGICAL                                        ::  mrt_include_sw = .TRUE.            !< should MRT calculation include SW radiation as well?
989    LOGICAL                                        ::  mrt_geom_human = .TRUE.            !< MRT direction weights simulate human body instead of a sphere
990    INTEGER(iwp)                                   ::  nrefsteps = 3                      !< number of reflection steps to perform
991    REAL(wp), PARAMETER                            ::  ext_coef = 0.6_wp                  !< extinction coefficient (a.k.a. alpha)
992    INTEGER(iwp), PARAMETER                        ::  rad_version_len = 10               !< length of identification string of rad version
993    CHARACTER(rad_version_len), PARAMETER          ::  rad_version = 'RAD v. 3.0'         !< identification of version of binary svf and restart files
994    INTEGER(iwp)                                   ::  raytrace_discrete_elevs = 40       !< number of discretization steps for elevation (nadir to zenith)
995    INTEGER(iwp)                                   ::  raytrace_discrete_azims = 80       !< number of discretization steps for azimuth (out of 360 degrees)
996    REAL(wp)                                       ::  max_raytracing_dist = -999.0_wp    !< maximum distance for raytracing (in metres)
997    REAL(wp)                                       ::  min_irrf_value = 1e-6_wp           !< minimum potential irradiance factor value for raytracing
998    REAL(wp), DIMENSION(1:30)                      ::  svfnorm_report_thresh = 1e21_wp    !< thresholds of SVF normalization values to report
999    INTEGER(iwp)                                   ::  svfnorm_report_num                 !< number of SVF normalization thresholds to report
1000
1001!-- radiation related arrays to be used in radiation_interaction routine
1002    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_sw_in_dir    !< direct sw radiation
1003    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_sw_in_diff   !< diffusion sw radiation
1004    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_lw_in_diff   !< diffusion lw radiation
1005
1006!-- parameters required for RRTMG lower boundary condition
1007    REAL(wp)                   :: albedo_urb      !< albedo value retuned to RRTMG boundary cond.
1008    REAL(wp)                   :: emissivity_urb  !< emissivity value retuned to RRTMG boundary cond.
1009    REAL(wp)                   :: t_rad_urb       !< temperature value retuned to RRTMG boundary cond.
1010
1011!-- type for calculation of svf
1012    TYPE t_svf
1013        INTEGER(iwp)                               :: isurflt           !<
1014        INTEGER(iwp)                               :: isurfs            !<
1015        REAL(wp)                                   :: rsvf              !<
1016        REAL(wp)                                   :: rtransp           !<
1017    END TYPE
1018
1019!-- type for calculation of csf
1020    TYPE t_csf
1021        INTEGER(iwp)                               :: ip                !<
1022        INTEGER(iwp)                               :: itx               !<
1023        INTEGER(iwp)                               :: ity               !<
1024        INTEGER(iwp)                               :: itz               !<
1025        INTEGER(iwp)                               :: isurfs            !< Idx of source face / -1 for sky
1026        REAL(wp)                                   :: rcvf              !< Canopy view factor for faces /
1027                                                                        !< canopy sink factor for sky (-1)
1028    END TYPE
1029
1030!-- arrays storing the values of USM
1031    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  svfsurf          !< svfsurf[:,isvf] = index of target and source surface for svf[isvf]
1032    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  svf              !< array of shape view factors+direct irradiation factors for local surfaces
1033    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfins          !< array of sw radiation falling to local surface after i-th reflection
1034    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinl          !< array of lw radiation for local surface after i-th reflection
1035
1036    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  skyvf            !< array of sky view factor for each local surface
1037    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  skyvft           !< array of sky view factor including transparency for each local surface
1038    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsitrans         !< dsidir[isvfl,i] = path transmittance of i-th
1039                                                                        !< direction of direct solar irradiance per target surface
1040    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsitransc        !< dtto per plant canopy box
1041    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsidir           !< dsidir[:,i] = unit vector of i-th
1042                                                                        !< direction of direct solar irradiance
1043    INTEGER(iwp)                                   ::  ndsidir          !< number of apparent solar directions used
1044    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  dsidir_rev       !< dsidir_rev[ielev,iazim] = i for dsidir or -1 if not present
1045
1046    INTEGER(iwp)                                   ::  nmrtbl           !< No. of local grid boxes for which MRT is calculated
1047    INTEGER(iwp)                                   ::  nmrtf            !< number of MRT factors for local processor
1048    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  mrtbl            !< coordinates of i-th local MRT box - surfl[:,i] = [z, y, x]
1049    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  mrtfsurf         !< mrtfsurf[:,imrtf] = index of target MRT box and source surface for mrtf[imrtf]
1050    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtf             !< array of MRT factors for each local MRT box
1051    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtft            !< array of MRT factors including transparency for each local MRT box
1052    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtsky           !< array of sky view factor for each local MRT box
1053    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtskyt          !< array of sky view factor including transparency for each local MRT box
1054    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  mrtdsit          !< array of direct solar transparencies for each local MRT box
1055    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinsw          !< mean SW radiant flux for each MRT box
1056    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinlw          !< mean LW radiant flux for each MRT box
1057    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrt              !< mean radiant temperature for each MRT box
1058    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinsw_av       !< time average mean SW radiant flux for each MRT box
1059    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinlw_av       !< time average mean LW radiant flux for each MRT box
1060    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrt_av           !< time average mean radiant temperature for each MRT box
1061
1062    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinsw         !< array of sw radiation falling to local surface including radiation from reflections
1063    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlw         !< array of lw radiation falling to local surface including radiation from reflections
1064    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdir      !< array of direct sw radiation falling to local surface
1065    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdif      !< array of diffuse sw radiation from sky and model boundary falling to local surface
1066    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwdif      !< array of diffuse lw radiation from sky and model boundary falling to local surface
1067   
1068                                                                        !< Outward radiation is only valid for nonvirtual surfaces
1069    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsl        !< array of reflected sw radiation for local surface in i-th reflection
1070    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutll        !< array of reflected + emitted lw radiation for local surface in i-th reflection
1071    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfouts         !< array of reflected sw radiation for all surfaces in i-th reflection
1072    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutl         !< array of reflected + emitted lw radiation for all surfaces in i-th reflection
1073    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlg         !< global array of incoming lw radiation from plant canopy
1074    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsw        !< array of total sw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1075    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutlw        !< array of total lw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1076    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfemitlwl      !< array of emitted lw radiation for local surface used to calculate effective surface temperature for radiation model
1077
1078!-- block variables needed for calculation of the plant canopy model inside the urban surface model
1079    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  csfsurf          !< csfsurf[:,icsf] = index of target surface and csf grid index for csf[icsf]
1080    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  csf              !< array of plant canopy sink fators + direct irradiation factors (transparency)
1081    REAL(wp), DIMENSION(:,:,:), POINTER            ::  sub_lad          !< subset of lad_s within urban surface, transformed to plain Z coordinate
1082    REAL(wp), DIMENSION(:), POINTER                ::  sub_lad_g        !< sub_lad globalized (used to avoid MPI RMA calls in raytracing)
1083    REAL(wp)                                       ::  prototype_lad    !< prototype leaf area density for computing effective optical depth
1084    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  nzterr, plantt   !< temporary global arrays for raytracing
1085    INTEGER(iwp)                                   ::  plantt_max
1086
1087!-- arrays and variables for calculation of svf and csf
1088    TYPE(t_svf), DIMENSION(:), POINTER             ::  asvf             !< pointer to growing svc array
1089    TYPE(t_csf), DIMENSION(:), POINTER             ::  acsf             !< pointer to growing csf array
1090    TYPE(t_svf), DIMENSION(:), POINTER             ::  amrtf            !< pointer to growing mrtf array
1091    TYPE(t_svf), DIMENSION(:), ALLOCATABLE, TARGET ::  asvf1, asvf2     !< realizations of svf array
1092    TYPE(t_csf), DIMENSION(:), ALLOCATABLE, TARGET ::  acsf1, acsf2     !< realizations of csf array
1093    TYPE(t_svf), DIMENSION(:), ALLOCATABLE, TARGET ::  amrtf1, amrtf2   !< realizations of mftf array
1094    INTEGER(iwp)                                   ::  nsvfla           !< dimmension of array allocated for storage of svf in local processor
1095    INTEGER(iwp)                                   ::  ncsfla           !< dimmension of array allocated for storage of csf in local processor
1096    INTEGER(iwp)                                   ::  nmrtfa           !< dimmension of array allocated for storage of mrt
1097    INTEGER(iwp)                                   ::  msvf, mcsf, mmrtf!< mod for swapping the growing array
1098    INTEGER(iwp), PARAMETER                        ::  gasize = 100000  !< initial size of growing arrays
1099    REAL(wp), PARAMETER                            ::  grow_factor = 1.4_wp !< growth factor of growing arrays
1100    INTEGER(iwp)                                   ::  nsvfl            !< number of svf for local processor
1101    INTEGER(iwp)                                   ::  ncsfl            !< no. of csf in local processor
1102                                                                        !< needed only during calc_svf but must be here because it is
1103                                                                        !< shared between subroutines calc_svf and raytrace
1104    INTEGER(iwp), DIMENSION(:,:,:,:), POINTER      ::  gridsurf         !< reverse index of local surfl[d,k,j,i] (for case rad_angular_discretization)
1105    INTEGER(iwp), DIMENSION(:,:,:), ALLOCATABLE    ::  gridpcbl         !< reverse index of local pcbl[k,j,i]
1106    INTEGER(iwp), PARAMETER                        ::  nsurf_type_u = 6 !< number of urban surf types (used in gridsurf)
1107
1108!-- temporary arrays for calculation of csf in raytracing
1109    INTEGER(iwp)                                   ::  maxboxesg        !< max number of boxes ray can cross in the domain
1110    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  boxes            !< coordinates of gridboxes being crossed by ray
1111    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  crlens           !< array of crossing lengths of ray for particular grid boxes
1112    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  lad_ip           !< array of numbers of process where lad is stored
1113#if defined( __parallel )
1114    INTEGER(kind=MPI_ADDRESS_KIND), &
1115                  DIMENSION(:), ALLOCATABLE        ::  lad_disp         !< array of displaycements of lad in local array of proc lad_ip
1116    INTEGER(iwp)                                   ::  win_lad          !< MPI RMA window for leaf area density
1117    INTEGER(iwp)                                   ::  win_gridsurf     !< MPI RMA window for reverse grid surface index
1118#endif
1119    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  lad_s_ray        !< array of received lad_s for appropriate gridboxes crossed by ray
1120    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  target_surfl
1121    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  rt2_track
1122    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rt2_track_lad
1123    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  rt2_track_dist
1124    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  rt2_dist
1125
1126!-- arrays for time averages
1127    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfradnet_av    !< average of net radiation to local surface including radiation from reflections
1128    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinsw_av      !< average of sw radiation falling to local surface including radiation from reflections
1129    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlw_av      !< average of lw radiation falling to local surface including radiation from reflections
1130    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdir_av   !< average of direct sw radiation falling to local surface
1131    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdif_av   !< average of diffuse sw radiation from sky and model boundary falling to local surface
1132    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwdif_av   !< average of diffuse lw radiation from sky and model boundary falling to local surface
1133    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswref_av   !< average of sw radiation falling to surface from reflections
1134    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwref_av   !< average of lw radiation falling to surface from reflections
1135    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsw_av     !< average of total sw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1136    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutlw_av     !< average of total lw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1137    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfins_av       !< average of array of residua of sw radiation absorbed in surface after last reflection
1138    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinl_av       !< average of array of residua of lw radiation absorbed in surface after last reflection
1139    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinlw_av       !< Average of pcbinlw
1140    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinsw_av       !< Average of pcbinsw
1141    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdir_av    !< Average of pcbinswdir
1142    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdif_av    !< Average of pcbinswdif
1143    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswref_av    !< Average of pcbinswref
1144
1145
1146!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1147!-- Energy balance variables
1148!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1149!-- parameters of the land, roof and wall surfaces
1150    REAL(wp), DIMENSION(:), ALLOCATABLE            :: albedo_surf        !< albedo of the surface
1151    REAL(wp), DIMENSION(:), ALLOCATABLE            :: emiss_surf         !< emissivity of the wall surface
1152
1153
1154    INTERFACE radiation_check_data_output
1155       MODULE PROCEDURE radiation_check_data_output
1156    END INTERFACE radiation_check_data_output
1157
1158    INTERFACE radiation_check_data_output_ts
1159       MODULE PROCEDURE radiation_check_data_output_ts
1160    END INTERFACE radiation_check_data_output_ts
1161
1162    INTERFACE radiation_check_data_output_pr
1163       MODULE PROCEDURE radiation_check_data_output_pr
1164    END INTERFACE radiation_check_data_output_pr
1165 
1166    INTERFACE radiation_check_parameters
1167       MODULE PROCEDURE radiation_check_parameters
1168    END INTERFACE radiation_check_parameters
1169 
1170    INTERFACE radiation_clearsky
1171       MODULE PROCEDURE radiation_clearsky
1172    END INTERFACE radiation_clearsky
1173 
1174    INTERFACE radiation_constant
1175       MODULE PROCEDURE radiation_constant
1176    END INTERFACE radiation_constant
1177 
1178    INTERFACE radiation_control
1179       MODULE PROCEDURE radiation_control
1180    END INTERFACE radiation_control
1181
1182    INTERFACE radiation_3d_data_averaging
1183       MODULE PROCEDURE radiation_3d_data_averaging
1184    END INTERFACE radiation_3d_data_averaging
1185
1186    INTERFACE radiation_data_output_2d
1187       MODULE PROCEDURE radiation_data_output_2d
1188    END INTERFACE radiation_data_output_2d
1189
1190    INTERFACE radiation_data_output_3d
1191       MODULE PROCEDURE radiation_data_output_3d
1192    END INTERFACE radiation_data_output_3d
1193
1194    INTERFACE radiation_data_output_mask
1195       MODULE PROCEDURE radiation_data_output_mask
1196    END INTERFACE radiation_data_output_mask
1197
1198    INTERFACE radiation_define_netcdf_grid
1199       MODULE PROCEDURE radiation_define_netcdf_grid
1200    END INTERFACE radiation_define_netcdf_grid
1201
1202    INTERFACE radiation_header
1203       MODULE PROCEDURE radiation_header
1204    END INTERFACE radiation_header 
1205 
1206    INTERFACE radiation_init
1207       MODULE PROCEDURE radiation_init
1208    END INTERFACE radiation_init
1209
1210    INTERFACE radiation_parin
1211       MODULE PROCEDURE radiation_parin
1212    END INTERFACE radiation_parin
1213   
1214    INTERFACE radiation_rrtmg
1215       MODULE PROCEDURE radiation_rrtmg
1216    END INTERFACE radiation_rrtmg
1217
1218    INTERFACE radiation_tendency
1219       MODULE PROCEDURE radiation_tendency
1220       MODULE PROCEDURE radiation_tendency_ij
1221    END INTERFACE radiation_tendency
1222
1223    INTERFACE radiation_rrd_local
1224       MODULE PROCEDURE radiation_rrd_local
1225    END INTERFACE radiation_rrd_local
1226
1227    INTERFACE radiation_wrd_local
1228       MODULE PROCEDURE radiation_wrd_local
1229    END INTERFACE radiation_wrd_local
1230
1231    INTERFACE radiation_interaction
1232       MODULE PROCEDURE radiation_interaction
1233    END INTERFACE radiation_interaction
1234
1235    INTERFACE radiation_interaction_init
1236       MODULE PROCEDURE radiation_interaction_init
1237    END INTERFACE radiation_interaction_init
1238 
1239    INTERFACE radiation_presimulate_solar_pos
1240       MODULE PROCEDURE radiation_presimulate_solar_pos
1241    END INTERFACE radiation_presimulate_solar_pos
1242
1243    INTERFACE radiation_radflux_gridbox
1244       MODULE PROCEDURE radiation_radflux_gridbox
1245    END INTERFACE radiation_radflux_gridbox
1246
1247    INTERFACE radiation_calc_svf
1248       MODULE PROCEDURE radiation_calc_svf
1249    END INTERFACE radiation_calc_svf
1250
1251    INTERFACE radiation_write_svf
1252       MODULE PROCEDURE radiation_write_svf
1253    END INTERFACE radiation_write_svf
1254
1255    INTERFACE radiation_read_svf
1256       MODULE PROCEDURE radiation_read_svf
1257    END INTERFACE radiation_read_svf
1258
1259
1260    SAVE
1261
1262    PRIVATE
1263
1264!
1265!-- Public functions / NEEDS SORTING
1266    PUBLIC radiation_check_data_output, radiation_check_data_output_pr,        &
1267           radiation_check_data_output_ts,                                     &
1268           radiation_check_parameters, radiation_control,                      &
1269           radiation_header, radiation_init, radiation_parin,                  &
1270           radiation_3d_data_averaging, radiation_tendency,                    &
1271           radiation_data_output_2d, radiation_data_output_3d,                 &
1272           radiation_define_netcdf_grid, radiation_wrd_local,                  &
1273           radiation_rrd_local, radiation_data_output_mask,                    &
1274           radiation_radflux_gridbox, radiation_calc_svf, radiation_write_svf, &
1275           radiation_interaction, radiation_interaction_init,                  &
1276           radiation_read_svf, radiation_presimulate_solar_pos
1277           
1278
1279   
1280!
1281!-- Public variables and constants / NEEDS SORTING
1282    PUBLIC albedo, albedo_type, decl_1, decl_2, decl_3, dots_rad, dt_radiation,&
1283           emissivity, force_radiation_call, lat, lon, mrt_geom_human,         &
1284           mrt_include_sw, mrt_nlevels, mrtbl, mrtinsw, mrtinlw, nmrtbl,       &
1285           rad_net_av, radiation, radiation_scheme, rad_lw_in,                 &
1286           rad_lw_in_av, rad_lw_out, rad_lw_out_av,                            &
1287           rad_lw_cs_hr, rad_lw_cs_hr_av, rad_lw_hr, rad_lw_hr_av, rad_sw_in,  &
1288           rad_sw_in_av, rad_sw_out, rad_sw_out_av, rad_sw_cs_hr,              &
1289           rad_sw_cs_hr_av, rad_sw_hr, rad_sw_hr_av, sigma_sb, solar_constant, &
1290           skip_time_do_radiation, time_radiation, unscheduled_radiation_calls,&
1291           zenith, calc_zenith, sun_direction, sun_dir_lat, sun_dir_lon,       &
1292           idir, jdir, kdir, id, iz, iy, ix,                                   &
1293           iup_u, inorth_u, isouth_u, ieast_u, iwest_u,                        &
1294           iup_l, inorth_l, isouth_l, ieast_l, iwest_l,                        &
1295           nsurf_type, nzub, nzut, nzu, pch, nsurf,                            &
1296           idsvf, ndsvf, idcsf, ndcsf, kdcsf, pct,                             &
1297           radiation_interactions, startwall, startland, endland, endwall,     &
1298           skyvf, skyvft, radiation_interactions_on, average_radiation,        &
1299           rad_sw_in_diff, rad_sw_in_dir
1300
1301
1302#if defined ( __rrtmg )
1303    PUBLIC rrtm_aldif, rrtm_aldir, rrtm_asdif, rrtm_asdir
1304#endif
1305
1306 CONTAINS
1307
1308
1309!------------------------------------------------------------------------------!
1310! Description:
1311! ------------
1312!> This subroutine controls the calls of the radiation schemes
1313!------------------------------------------------------------------------------!
1314    SUBROUTINE radiation_control
1315 
1316 
1317       IMPLICIT NONE
1318
1319
1320       SELECT CASE ( TRIM( radiation_scheme ) )
1321
1322          CASE ( 'constant' )
1323             CALL radiation_constant
1324         
1325          CASE ( 'clear-sky' ) 
1326             CALL radiation_clearsky
1327       
1328          CASE ( 'rrtmg' )
1329             CALL radiation_rrtmg
1330
1331          CASE DEFAULT
1332
1333       END SELECT
1334
1335
1336    END SUBROUTINE radiation_control
1337
1338!------------------------------------------------------------------------------!
1339! Description:
1340! ------------
1341!> Check data output for radiation model
1342!------------------------------------------------------------------------------!
1343    SUBROUTINE radiation_check_data_output( variable, unit, i, ilen, k )
1344 
1345 
1346       USE control_parameters,                                                 &
1347           ONLY: data_output, message_string
1348
1349       IMPLICIT NONE
1350
1351       CHARACTER (LEN=*) ::  unit          !<
1352       CHARACTER (LEN=*) ::  variable      !<
1353
1354       INTEGER(iwp) :: i, j, k, l
1355       INTEGER(iwp) :: ilen
1356       CHARACTER(LEN=varnamelength) :: var          !< TRIM(variable)
1357
1358       var = TRIM(variable)
1359
1360!--    first process diractional variables
1361       IF ( var(1:12) == 'rtm_rad_net_'  .OR.  var(1:13) == 'rtm_rad_insw_'  .OR.        &
1362            var(1:13) == 'rtm_rad_inlw_'  .OR.  var(1:16) == 'rtm_rad_inswdir_'  .OR.    &
1363            var(1:16) == 'rtm_rad_inswdif_'  .OR.  var(1:16) == 'rtm_rad_inswref_'  .OR. &
1364            var(1:16) == 'rtm_rad_inlwdif_'  .OR.  var(1:16) == 'rtm_rad_inlwref_'  .OR. &
1365            var(1:14) == 'rtm_rad_outsw_'  .OR.  var(1:14) == 'rtm_rad_outlw_'  .OR.     &
1366            var(1:14) == 'rtm_rad_ressw_'  .OR.  var(1:14) == 'rtm_rad_reslw_'  ) THEN
1367          IF ( .NOT.  radiation ) THEN
1368                message_string = 'output of "' // TRIM( var ) // '" require'&
1369                                 // 's radiation = .TRUE.'
1370                CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1371          ENDIF
1372          unit = 'W/m2'
1373       ELSE IF ( var(1:7) == 'rtm_svf'  .OR.  var(1:7) == 'rtm_dif'  .OR.                &
1374                 var(1:9) == 'rtm_skyvf' .OR. var(1:9) == 'rtm_skyvft' )  THEN
1375          IF ( .NOT.  radiation ) THEN
1376                message_string = 'output of "' // TRIM( var ) // '" require'&
1377                                 // 's radiation = .TRUE.'
1378                CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1379          ENDIF
1380          unit = '1'
1381       ELSE
1382!--       non-directional variables
1383          SELECT CASE ( TRIM( var ) )
1384             CASE ( 'rad_lw_cs_hr', 'rad_lw_hr', 'rad_lw_in', 'rad_lw_out', &
1385                    'rad_sw_cs_hr', 'rad_sw_hr', 'rad_sw_in', 'rad_sw_out'  )
1386                IF (  .NOT.  radiation  .OR.  radiation_scheme /= 'rrtmg' )  THEN
1387                   message_string = '"output of "' // TRIM( var ) // '" requi' // &
1388                                    'res radiation = .TRUE. and ' //              &
1389                                    'radiation_scheme = "rrtmg"'
1390                   CALL message( 'check_parameters', 'PA0406', 1, 2, 0, 6, 0 )
1391                ENDIF
1392                unit = 'K/h'
1393
1394             CASE ( 'rad_net*', 'rrtm_aldif*', 'rrtm_aldir*', 'rrtm_asdif*',      &
1395                    'rrtm_asdir*', 'rad_lw_in*', 'rad_lw_out*', 'rad_sw_in*',     &
1396                    'rad_sw_out*')
1397                IF ( i == 0 .AND. ilen == 0 .AND. k == 0)  THEN
1398                   ! Workaround for masked output (calls with i=ilen=k=0)
1399                   unit = 'illegal'
1400                   RETURN
1401                ENDIF
1402                IF ( k == 0  .OR.  data_output(i)(ilen-2:ilen) /= '_xy' )  THEN
1403                   message_string = 'illegal value for data_output: "' //         &
1404                                    TRIM( var ) // '" & only 2d-horizontal ' //   &
1405                                    'cross sections are allowed for this value'
1406                   CALL message( 'check_parameters', 'PA0111', 1, 2, 0, 6, 0 )
1407                ENDIF
1408                IF (  .NOT.  radiation  .OR.  radiation_scheme /= "rrtmg" )  THEN
1409                   IF ( TRIM( var ) == 'rrtm_aldif*'  .OR.                        &
1410                        TRIM( var ) == 'rrtm_aldir*'  .OR.                        &
1411                        TRIM( var ) == 'rrtm_asdif*'  .OR.                        &
1412                        TRIM( var ) == 'rrtm_asdir*'      )                       &
1413                   THEN
1414                      message_string = 'output of "' // TRIM( var ) // '" require'&
1415                                       // 's radiation = .TRUE. and radiation_sch'&
1416                                       // 'eme = "rrtmg"'
1417                      CALL message( 'check_parameters', 'PA0409', 1, 2, 0, 6, 0 )
1418                   ENDIF
1419                ENDIF
1420
1421                IF ( TRIM( var ) == 'rad_net*'      ) unit = 'W/m2'
1422                IF ( TRIM( var ) == 'rad_lw_in*'    ) unit = 'W/m2'
1423                IF ( TRIM( var ) == 'rad_lw_out*'   ) unit = 'W/m2'
1424                IF ( TRIM( var ) == 'rad_sw_in*'    ) unit = 'W/m2'
1425                IF ( TRIM( var ) == 'rad_sw_out*'   ) unit = 'W/m2'
1426                IF ( TRIM( var ) == 'rad_sw_in'     ) unit = 'W/m2'
1427                IF ( TRIM( var ) == 'rrtm_aldif*'   ) unit = ''
1428                IF ( TRIM( var ) == 'rrtm_aldir*'   ) unit = ''
1429                IF ( TRIM( var ) == 'rrtm_asdif*'   ) unit = ''
1430                IF ( TRIM( var ) == 'rrtm_asdir*'   ) unit = ''
1431
1432             CASE ( 'rtm_rad_pc_inlw', 'rtm_rad_pc_insw', 'rtm_rad_pc_inswdir', &
1433                    'rtm_rad_pc_inswdif', 'rtm_rad_pc_inswref')
1434                IF ( .NOT.  radiation ) THEN
1435                   message_string = 'output of "' // TRIM( var ) // '" require'&
1436                                    // 's radiation = .TRUE.'
1437                   CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1438                ENDIF
1439                unit = 'W'
1440
1441             CASE ( 'rtm_mrt', 'rtm_mrt_sw', 'rtm_mrt_lw'  )
1442                IF ( i == 0 .AND. ilen == 0 .AND. k == 0)  THEN
1443                   ! Workaround for masked output (calls with i=ilen=k=0)
1444                   unit = 'illegal'
1445                   RETURN
1446                ENDIF
1447
1448                IF ( .NOT.  radiation ) THEN
1449                   message_string = 'output of "' // TRIM( var ) // '" require'&
1450                                    // 's radiation = .TRUE.'
1451                   CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1452                ENDIF
1453                IF ( mrt_nlevels == 0 ) THEN
1454                   message_string = 'output of "' // TRIM( var ) // '" require'&
1455                                    // 's mrt_nlevels > 0'
1456                   CALL message( 'check_parameters', 'PA0510', 1, 2, 0, 6, 0 )
1457                ENDIF
1458                IF ( TRIM( var ) == 'rtm_mrt_sw'  .AND.  .NOT. mrt_include_sw ) THEN
1459                   message_string = 'output of "' // TRIM( var ) // '" require'&
1460                                    // 's rtm_mrt_sw = .TRUE.'
1461                   CALL message( 'check_parameters', 'PA0511', 1, 2, 0, 6, 0 )
1462                ENDIF
1463                IF ( TRIM( var ) == 'rtm_mrt' ) THEN
1464                   unit = 'K'
1465                ELSE
1466                   unit = 'W m-2'
1467                ENDIF
1468
1469             CASE DEFAULT
1470                unit = 'illegal'
1471
1472          END SELECT
1473       ENDIF
1474
1475    END SUBROUTINE radiation_check_data_output
1476
1477
1478!------------------------------------------------------------------------------!
1479! Description:
1480! ------------
1481!> Set module-specific timeseries units and labels
1482!------------------------------------------------------------------------------!
1483 SUBROUTINE radiation_check_data_output_ts( dots_max, dots_num, dots_label, dots_unit )
1484
1485
1486   INTEGER(iwp),      INTENT(IN)     ::  dots_max
1487   INTEGER(iwp),      INTENT(INOUT)  ::  dots_num
1488   CHARACTER (LEN=*), DIMENSION(dots_max), INTENT(INOUT)  :: dots_label
1489   CHARACTER (LEN=*), DIMENSION(dots_max), INTENT(INOUT)  :: dots_unit
1490
1491!
1492!-- Temporary solution to add LSM and radiation time series to the default
1493!-- output
1494    IF ( land_surface  .OR.  radiation )  THEN
1495       IF ( TRIM( radiation_scheme ) == 'rrtmg' )  THEN
1496          dots_num = dots_num + 15
1497       ELSE
1498          dots_num = dots_num + 11
1499       ENDIF
1500    ENDIF
1501
1502
1503 END SUBROUTINE radiation_check_data_output_ts
1504
1505!------------------------------------------------------------------------------!
1506! Description:
1507! ------------
1508!> Check data output of profiles for radiation model
1509!------------------------------------------------------------------------------! 
1510    SUBROUTINE radiation_check_data_output_pr( variable, var_count, unit,      &
1511               dopr_unit )
1512 
1513       USE arrays_3d,                                                          &
1514           ONLY: zu
1515
1516       USE control_parameters,                                                 &
1517           ONLY: data_output_pr, message_string
1518
1519       USE indices
1520
1521       USE profil_parameter
1522
1523       USE statistics
1524
1525       IMPLICIT NONE
1526   
1527       CHARACTER (LEN=*) ::  unit      !<
1528       CHARACTER (LEN=*) ::  variable  !<
1529       CHARACTER (LEN=*) ::  dopr_unit !< local value of dopr_unit
1530 
1531       INTEGER(iwp) ::  var_count     !<
1532
1533       SELECT CASE ( TRIM( variable ) )
1534       
1535         CASE ( 'rad_net' )
1536             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme == 'constant' )&
1537             THEN
1538                message_string = 'data_output_pr = ' //                        &
1539                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1540                                 'not available for radiation = .FALSE. or ' //&
1541                                 'radiation_scheme = "constant"'
1542                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1543             ELSE
1544                dopr_index(var_count) = 99
1545                dopr_unit  = 'W/m2'
1546                hom(:,2,99,:)  = SPREAD( zw, 2, statistic_regions+1 )
1547                unit = dopr_unit
1548             ENDIF
1549
1550          CASE ( 'rad_lw_in' )
1551             IF ( (  .NOT.  radiation)  .OR.  radiation_scheme == 'constant' ) &
1552             THEN
1553                message_string = 'data_output_pr = ' //                        &
1554                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1555                                 'not available for radiation = .FALSE. or ' //&
1556                                 'radiation_scheme = "constant"'
1557                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1558             ELSE
1559                dopr_index(var_count) = 100
1560                dopr_unit  = 'W/m2'
1561                hom(:,2,100,:)  = SPREAD( zw, 2, statistic_regions+1 )
1562                unit = dopr_unit 
1563             ENDIF
1564
1565          CASE ( 'rad_lw_out' )
1566             IF ( (  .NOT. radiation )  .OR.  radiation_scheme == 'constant' ) &
1567             THEN
1568                message_string = 'data_output_pr = ' //                        &
1569                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1570                                 'not available for radiation = .FALSE. or ' //&
1571                                 'radiation_scheme = "constant"'
1572                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1573             ELSE
1574                dopr_index(var_count) = 101
1575                dopr_unit  = 'W/m2'
1576                hom(:,2,101,:)  = SPREAD( zw, 2, statistic_regions+1 )
1577                unit = dopr_unit   
1578             ENDIF
1579
1580          CASE ( 'rad_sw_in' )
1581             IF ( (  .NOT. radiation )  .OR.  radiation_scheme == 'constant' ) &
1582             THEN
1583                message_string = 'data_output_pr = ' //                        &
1584                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1585                                 'not available for radiation = .FALSE. or ' //&
1586                                 'radiation_scheme = "constant"'
1587                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1588             ELSE
1589                dopr_index(var_count) = 102
1590                dopr_unit  = 'W/m2'
1591                hom(:,2,102,:)  = SPREAD( zw, 2, statistic_regions+1 )
1592                unit = dopr_unit
1593             ENDIF
1594
1595          CASE ( 'rad_sw_out')
1596             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme == 'constant' )&
1597             THEN
1598                message_string = 'data_output_pr = ' //                        &
1599                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1600                                 'not available for radiation = .FALSE. or ' //&
1601                                 'radiation_scheme = "constant"'
1602                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1603             ELSE
1604                dopr_index(var_count) = 103
1605                dopr_unit  = 'W/m2'
1606                hom(:,2,103,:)  = SPREAD( zw, 2, statistic_regions+1 )
1607                unit = dopr_unit
1608             ENDIF
1609
1610          CASE ( 'rad_lw_cs_hr' )
1611             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1612             THEN
1613                message_string = 'data_output_pr = ' //                        &
1614                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1615                                 'not available for radiation = .FALSE. or ' //&
1616                                 'radiation_scheme /= "rrtmg"'
1617                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1618             ELSE
1619                dopr_index(var_count) = 104
1620                dopr_unit  = 'K/h'
1621                hom(:,2,104,:)  = SPREAD( zu, 2, statistic_regions+1 )
1622                unit = dopr_unit
1623             ENDIF
1624
1625          CASE ( 'rad_lw_hr' )
1626             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1627             THEN
1628                message_string = 'data_output_pr = ' //                        &
1629                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1630                                 'not available for radiation = .FALSE. or ' //&
1631                                 'radiation_scheme /= "rrtmg"'
1632                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1633             ELSE
1634                dopr_index(var_count) = 105
1635                dopr_unit  = 'K/h'
1636                hom(:,2,105,:)  = SPREAD( zu, 2, statistic_regions+1 )
1637                unit = dopr_unit
1638             ENDIF
1639
1640          CASE ( 'rad_sw_cs_hr' )
1641             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1642             THEN
1643                message_string = 'data_output_pr = ' //                        &
1644                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1645                                 'not available for radiation = .FALSE. or ' //&
1646                                 'radiation_scheme /= "rrtmg"'
1647                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1648             ELSE
1649                dopr_index(var_count) = 106
1650                dopr_unit  = 'K/h'
1651                hom(:,2,106,:)  = SPREAD( zu, 2, statistic_regions+1 )
1652                unit = dopr_unit
1653             ENDIF
1654
1655          CASE ( 'rad_sw_hr' )
1656             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1657             THEN
1658                message_string = 'data_output_pr = ' //                        &
1659                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1660                                 'not available for radiation = .FALSE. or ' //&
1661                                 'radiation_scheme /= "rrtmg"'
1662                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1663             ELSE
1664                dopr_index(var_count) = 107
1665                dopr_unit  = 'K/h'
1666                hom(:,2,107,:)  = SPREAD( zu, 2, statistic_regions+1 )
1667                unit = dopr_unit
1668             ENDIF
1669
1670
1671          CASE DEFAULT
1672             unit = 'illegal'
1673
1674       END SELECT
1675
1676
1677    END SUBROUTINE radiation_check_data_output_pr
1678 
1679 
1680!------------------------------------------------------------------------------!
1681! Description:
1682! ------------
1683!> Check parameters routine for radiation model
1684!------------------------------------------------------------------------------!
1685    SUBROUTINE radiation_check_parameters
1686
1687       USE control_parameters,                                                 &
1688           ONLY: land_surface, message_string, urban_surface
1689
1690       USE netcdf_data_input_mod,                                              &
1691           ONLY:  input_pids_static                 
1692   
1693       IMPLICIT NONE
1694       
1695!
1696!--    In case no urban-surface or land-surface model is applied, usage of
1697!--    a radiation model make no sense.         
1698       IF ( .NOT. land_surface  .AND.  .NOT. urban_surface )  THEN
1699          message_string = 'Usage of radiation module is only allowed if ' //  &
1700                           'land-surface and/or urban-surface model is applied.'
1701          CALL message( 'check_parameters', 'PA0486', 1, 2, 0, 6, 0 )
1702       ENDIF
1703
1704       IF ( radiation_scheme /= 'constant'   .AND.                             &
1705            radiation_scheme /= 'clear-sky'  .AND.                             &
1706            radiation_scheme /= 'rrtmg' )  THEN
1707          message_string = 'unknown radiation_scheme = '//                     &
1708                           TRIM( radiation_scheme )
1709          CALL message( 'check_parameters', 'PA0405', 1, 2, 0, 6, 0 )
1710       ELSEIF ( radiation_scheme == 'rrtmg' )  THEN
1711#if ! defined ( __rrtmg )
1712          message_string = 'radiation_scheme = "rrtmg" requires ' //           & 
1713                           'compilation of PALM with pre-processor ' //        &
1714                           'directive -D__rrtmg'
1715          CALL message( 'check_parameters', 'PA0407', 1, 2, 0, 6, 0 )
1716#endif
1717#if defined ( __rrtmg ) && ! defined( __netcdf )
1718          message_string = 'radiation_scheme = "rrtmg" requires ' //           & 
1719                           'the use of NetCDF (preprocessor directive ' //     &
1720                           '-D__netcdf'
1721          CALL message( 'check_parameters', 'PA0412', 1, 2, 0, 6, 0 )
1722#endif
1723
1724       ENDIF
1725!
1726!--    Checks performed only if data is given via namelist only.
1727       IF ( .NOT. input_pids_static )  THEN
1728          IF ( albedo_type == 0  .AND.  albedo == 9999999.9_wp  .AND.          &
1729               radiation_scheme == 'clear-sky')  THEN
1730             message_string = 'radiation_scheme = "clear-sky" in combination'//& 
1731                              'with albedo_type = 0 requires setting of'//     &
1732                              'albedo /= 9999999.9'
1733             CALL message( 'check_parameters', 'PA0410', 1, 2, 0, 6, 0 )
1734          ENDIF
1735
1736          IF ( albedo_type == 0  .AND.  radiation_scheme == 'rrtmg'  .AND.     &
1737             ( albedo_lw_dif == 9999999.9_wp .OR. albedo_lw_dir == 9999999.9_wp&
1738          .OR. albedo_sw_dif == 9999999.9_wp .OR. albedo_sw_dir == 9999999.9_wp& 
1739             ) ) THEN
1740             message_string = 'radiation_scheme = "rrtmg" in combination' //   & 
1741                              'with albedo_type = 0 requires setting of ' //   &
1742                              'albedo_lw_dif /= 9999999.9' //                  &
1743                              'albedo_lw_dir /= 9999999.9' //                  &
1744                              'albedo_sw_dif /= 9999999.9 and' //              &
1745                              'albedo_sw_dir /= 9999999.9'
1746             CALL message( 'check_parameters', 'PA0411', 1, 2, 0, 6, 0 )
1747          ENDIF
1748       ENDIF
1749!
1750!--    Parallel rad_angular_discretization without raytrace_mpi_rma is not implemented
1751#if defined( __parallel )     
1752       IF ( rad_angular_discretization  .AND.  .NOT. raytrace_mpi_rma )  THEN
1753          message_string = 'rad_angular_discretization can only be used ' //  &
1754                           'together with raytrace_mpi_rma or when ' //  &
1755                           'no parallelization is applied.'
1756          CALL message( 'check_parameters', 'PA0486', 1, 2, 0, 6, 0 )
1757       ENDIF
1758#endif
1759
1760       IF ( cloud_droplets  .AND.   radiation_scheme == 'rrtmg'  .AND.         &
1761            average_radiation ) THEN
1762          message_string = 'average_radiation = .T. with radiation_scheme'//   & 
1763                           '= "rrtmg" in combination cloud_droplets = .T.'//   &
1764                           'is not implementd'
1765          CALL message( 'check_parameters', 'PA0560', 1, 2, 0, 6, 0 )
1766       ENDIF
1767
1768!
1769!--    Incialize svf normalization reporting histogram
1770       svfnorm_report_num = 1
1771       DO WHILE ( svfnorm_report_thresh(svfnorm_report_num) < 1e20_wp          &
1772                   .AND. svfnorm_report_num <= 30 )
1773          svfnorm_report_num = svfnorm_report_num + 1
1774       ENDDO
1775       svfnorm_report_num = svfnorm_report_num - 1
1776
1777
1778 
1779    END SUBROUTINE radiation_check_parameters 
1780 
1781 
1782!------------------------------------------------------------------------------!
1783! Description:
1784! ------------
1785!> Initialization of the radiation model
1786!------------------------------------------------------------------------------!
1787    SUBROUTINE radiation_init
1788   
1789       IMPLICIT NONE
1790
1791       INTEGER(iwp) ::  i         !< running index x-direction
1792       INTEGER(iwp) ::  ioff      !< offset in x between surface element reference grid point in atmosphere and actual surface
1793       INTEGER(iwp) ::  j         !< running index y-direction
1794       INTEGER(iwp) ::  joff      !< offset in y between surface element reference grid point in atmosphere and actual surface
1795       INTEGER(iwp) ::  l         !< running index for orientation of vertical surfaces
1796       INTEGER(iwp) ::  m         !< running index for surface elements
1797#if defined( __rrtmg )
1798       INTEGER(iwp) ::  ind_type  !< running index for subgrid-surface tiles
1799#endif
1800
1801!
1802!--    Activate radiation_interactions according to the existence of vertical surfaces and/or trees.
1803!--    The namelist parameter radiation_interactions_on can override this behavior.
1804!--    (This check cannot be performed in check_parameters, because vertical_surfaces_exist is first set in
1805!--    init_surface_arrays.)
1806       IF ( radiation_interactions_on )  THEN
1807          IF ( vertical_surfaces_exist  .OR.  plant_canopy )  THEN
1808             radiation_interactions    = .TRUE.
1809             average_radiation         = .TRUE.
1810          ELSE
1811             radiation_interactions_on = .FALSE.   !< reset namelist parameter: no interactions
1812                                                   !< calculations necessary in case of flat surface
1813          ENDIF
1814       ELSEIF ( vertical_surfaces_exist  .OR.  plant_canopy )  THEN
1815          message_string = 'radiation_interactions_on is set to .FALSE. although '     // &
1816                           'vertical surfaces and/or trees exist. The model will run ' // &
1817                           'without RTM (no shadows, no radiation reflections)'
1818          CALL message( 'init_3d_model', 'PA0348', 0, 1, 0, 6, 0 )
1819       ENDIF
1820!
1821!--    If required, initialize radiation interactions between surfaces
1822!--    via sky-view factors. This must be done before radiation is initialized.
1823       IF ( radiation_interactions )  CALL radiation_interaction_init
1824
1825!
1826!--    Initialize radiation model
1827       CALL location_message( 'initializing radiation model', .FALSE. )
1828
1829!
1830!--    Allocate array for storing the surface net radiation
1831       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_net )  .AND.                      &
1832                  surf_lsm_h%ns > 0  )   THEN
1833          ALLOCATE( surf_lsm_h%rad_net(1:surf_lsm_h%ns) )
1834          surf_lsm_h%rad_net = 0.0_wp 
1835       ENDIF
1836       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_net )  .AND.                      &
1837                  surf_usm_h%ns > 0  )  THEN
1838          ALLOCATE( surf_usm_h%rad_net(1:surf_usm_h%ns) )
1839          surf_usm_h%rad_net = 0.0_wp 
1840       ENDIF
1841       DO  l = 0, 3
1842          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_net )  .AND.                &
1843                     surf_lsm_v(l)%ns > 0  )  THEN
1844             ALLOCATE( surf_lsm_v(l)%rad_net(1:surf_lsm_v(l)%ns) )
1845             surf_lsm_v(l)%rad_net = 0.0_wp 
1846          ENDIF
1847          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_net )  .AND.                &
1848                     surf_usm_v(l)%ns > 0  )  THEN
1849             ALLOCATE( surf_usm_v(l)%rad_net(1:surf_usm_v(l)%ns) )
1850             surf_usm_v(l)%rad_net = 0.0_wp 
1851          ENDIF
1852       ENDDO
1853
1854
1855!
1856!--    Allocate array for storing the surface longwave (out) radiation change
1857       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_lw_out_change_0 )  .AND.          &
1858                  surf_lsm_h%ns > 0  )   THEN
1859          ALLOCATE( surf_lsm_h%rad_lw_out_change_0(1:surf_lsm_h%ns) )
1860          surf_lsm_h%rad_lw_out_change_0 = 0.0_wp 
1861       ENDIF
1862       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_lw_out_change_0 )  .AND.          &
1863                  surf_usm_h%ns > 0  )  THEN
1864          ALLOCATE( surf_usm_h%rad_lw_out_change_0(1:surf_usm_h%ns) )
1865          surf_usm_h%rad_lw_out_change_0 = 0.0_wp 
1866       ENDIF
1867       DO  l = 0, 3
1868          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_lw_out_change_0 )  .AND.    &
1869                     surf_lsm_v(l)%ns > 0  )  THEN
1870             ALLOCATE( surf_lsm_v(l)%rad_lw_out_change_0(1:surf_lsm_v(l)%ns) )
1871             surf_lsm_v(l)%rad_lw_out_change_0 = 0.0_wp 
1872          ENDIF
1873          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_lw_out_change_0 )  .AND.    &
1874                     surf_usm_v(l)%ns > 0  )  THEN
1875             ALLOCATE( surf_usm_v(l)%rad_lw_out_change_0(1:surf_usm_v(l)%ns) )
1876             surf_usm_v(l)%rad_lw_out_change_0 = 0.0_wp 
1877          ENDIF
1878       ENDDO
1879
1880!
1881!--    Allocate surface arrays for incoming/outgoing short/longwave radiation
1882       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_sw_in )  .AND.                    &
1883                  surf_lsm_h%ns > 0  )   THEN
1884          ALLOCATE( surf_lsm_h%rad_sw_in(1:surf_lsm_h%ns)  )
1885          ALLOCATE( surf_lsm_h%rad_sw_out(1:surf_lsm_h%ns) )
1886          ALLOCATE( surf_lsm_h%rad_sw_dir(1:surf_lsm_h%ns) )
1887          ALLOCATE( surf_lsm_h%rad_sw_dif(1:surf_lsm_h%ns) )
1888          ALLOCATE( surf_lsm_h%rad_sw_ref(1:surf_lsm_h%ns) )
1889          ALLOCATE( surf_lsm_h%rad_sw_res(1:surf_lsm_h%ns) )
1890          ALLOCATE( surf_lsm_h%rad_lw_in(1:surf_lsm_h%ns)  )
1891          ALLOCATE( surf_lsm_h%rad_lw_out(1:surf_lsm_h%ns) )
1892          ALLOCATE( surf_lsm_h%rad_lw_dif(1:surf_lsm_h%ns) )
1893          ALLOCATE( surf_lsm_h%rad_lw_ref(1:surf_lsm_h%ns) )
1894          ALLOCATE( surf_lsm_h%rad_lw_res(1:surf_lsm_h%ns) )
1895          surf_lsm_h%rad_sw_in  = 0.0_wp 
1896          surf_lsm_h%rad_sw_out = 0.0_wp 
1897          surf_lsm_h%rad_sw_dir = 0.0_wp 
1898          surf_lsm_h%rad_sw_dif = 0.0_wp 
1899          surf_lsm_h%rad_sw_ref = 0.0_wp 
1900          surf_lsm_h%rad_sw_res = 0.0_wp 
1901          surf_lsm_h%rad_lw_in  = 0.0_wp 
1902          surf_lsm_h%rad_lw_out = 0.0_wp 
1903          surf_lsm_h%rad_lw_dif = 0.0_wp 
1904          surf_lsm_h%rad_lw_ref = 0.0_wp 
1905          surf_lsm_h%rad_lw_res = 0.0_wp 
1906       ENDIF
1907       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_sw_in )  .AND.                    &
1908                  surf_usm_h%ns > 0  )  THEN
1909          ALLOCATE( surf_usm_h%rad_sw_in(1:surf_usm_h%ns)  )
1910          ALLOCATE( surf_usm_h%rad_sw_out(1:surf_usm_h%ns) )
1911          ALLOCATE( surf_usm_h%rad_sw_dir(1:surf_usm_h%ns) )
1912          ALLOCATE( surf_usm_h%rad_sw_dif(1:surf_usm_h%ns) )
1913          ALLOCATE( surf_usm_h%rad_sw_ref(1:surf_usm_h%ns) )
1914          ALLOCATE( surf_usm_h%rad_sw_res(1:surf_usm_h%ns) )
1915          ALLOCATE( surf_usm_h%rad_lw_in(1:surf_usm_h%ns)  )
1916          ALLOCATE( surf_usm_h%rad_lw_out(1:surf_usm_h%ns) )
1917          ALLOCATE( surf_usm_h%rad_lw_dif(1:surf_usm_h%ns) )
1918          ALLOCATE( surf_usm_h%rad_lw_ref(1:surf_usm_h%ns) )
1919          ALLOCATE( surf_usm_h%rad_lw_res(1:surf_usm_h%ns) )
1920          surf_usm_h%rad_sw_in  = 0.0_wp 
1921          surf_usm_h%rad_sw_out = 0.0_wp 
1922          surf_usm_h%rad_sw_dir = 0.0_wp 
1923          surf_usm_h%rad_sw_dif = 0.0_wp 
1924          surf_usm_h%rad_sw_ref = 0.0_wp 
1925          surf_usm_h%rad_sw_res = 0.0_wp 
1926          surf_usm_h%rad_lw_in  = 0.0_wp 
1927          surf_usm_h%rad_lw_out = 0.0_wp 
1928          surf_usm_h%rad_lw_dif = 0.0_wp 
1929          surf_usm_h%rad_lw_ref = 0.0_wp 
1930          surf_usm_h%rad_lw_res = 0.0_wp 
1931       ENDIF
1932       DO  l = 0, 3
1933          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_sw_in )  .AND.              &
1934                     surf_lsm_v(l)%ns > 0  )  THEN
1935             ALLOCATE( surf_lsm_v(l)%rad_sw_in(1:surf_lsm_v(l)%ns)  )
1936             ALLOCATE( surf_lsm_v(l)%rad_sw_out(1:surf_lsm_v(l)%ns) )
1937             ALLOCATE( surf_lsm_v(l)%rad_sw_dir(1:surf_lsm_v(l)%ns) )
1938             ALLOCATE( surf_lsm_v(l)%rad_sw_dif(1:surf_lsm_v(l)%ns) )
1939             ALLOCATE( surf_lsm_v(l)%rad_sw_ref(1:surf_lsm_v(l)%ns) )
1940             ALLOCATE( surf_lsm_v(l)%rad_sw_res(1:surf_lsm_v(l)%ns) )
1941
1942             ALLOCATE( surf_lsm_v(l)%rad_lw_in(1:surf_lsm_v(l)%ns)  )
1943             ALLOCATE( surf_lsm_v(l)%rad_lw_out(1:surf_lsm_v(l)%ns) )
1944             ALLOCATE( surf_lsm_v(l)%rad_lw_dif(1:surf_lsm_v(l)%ns) )
1945             ALLOCATE( surf_lsm_v(l)%rad_lw_ref(1:surf_lsm_v(l)%ns) )
1946             ALLOCATE( surf_lsm_v(l)%rad_lw_res(1:surf_lsm_v(l)%ns) )
1947
1948             surf_lsm_v(l)%rad_sw_in  = 0.0_wp 
1949             surf_lsm_v(l)%rad_sw_out = 0.0_wp
1950             surf_lsm_v(l)%rad_sw_dir = 0.0_wp
1951             surf_lsm_v(l)%rad_sw_dif = 0.0_wp
1952             surf_lsm_v(l)%rad_sw_ref = 0.0_wp
1953             surf_lsm_v(l)%rad_sw_res = 0.0_wp
1954
1955             surf_lsm_v(l)%rad_lw_in  = 0.0_wp 
1956             surf_lsm_v(l)%rad_lw_out = 0.0_wp 
1957             surf_lsm_v(l)%rad_lw_dif = 0.0_wp 
1958             surf_lsm_v(l)%rad_lw_ref = 0.0_wp 
1959             surf_lsm_v(l)%rad_lw_res = 0.0_wp 
1960          ENDIF
1961          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_sw_in )  .AND.              &
1962                     surf_usm_v(l)%ns > 0  )  THEN
1963             ALLOCATE( surf_usm_v(l)%rad_sw_in(1:surf_usm_v(l)%ns)  )
1964             ALLOCATE( surf_usm_v(l)%rad_sw_out(1:surf_usm_v(l)%ns) )
1965             ALLOCATE( surf_usm_v(l)%rad_sw_dir(1:surf_usm_v(l)%ns) )
1966             ALLOCATE( surf_usm_v(l)%rad_sw_dif(1:surf_usm_v(l)%ns) )
1967             ALLOCATE( surf_usm_v(l)%rad_sw_ref(1:surf_usm_v(l)%ns) )
1968             ALLOCATE( surf_usm_v(l)%rad_sw_res(1:surf_usm_v(l)%ns) )
1969             ALLOCATE( surf_usm_v(l)%rad_lw_in(1:surf_usm_v(l)%ns)  )
1970             ALLOCATE( surf_usm_v(l)%rad_lw_out(1:surf_usm_v(l)%ns) )
1971             ALLOCATE( surf_usm_v(l)%rad_lw_dif(1:surf_usm_v(l)%ns) )
1972             ALLOCATE( surf_usm_v(l)%rad_lw_ref(1:surf_usm_v(l)%ns) )
1973             ALLOCATE( surf_usm_v(l)%rad_lw_res(1:surf_usm_v(l)%ns) )
1974             surf_usm_v(l)%rad_sw_in  = 0.0_wp 
1975             surf_usm_v(l)%rad_sw_out = 0.0_wp
1976             surf_usm_v(l)%rad_sw_dir = 0.0_wp
1977             surf_usm_v(l)%rad_sw_dif = 0.0_wp
1978             surf_usm_v(l)%rad_sw_ref = 0.0_wp
1979             surf_usm_v(l)%rad_sw_res = 0.0_wp
1980             surf_usm_v(l)%rad_lw_in  = 0.0_wp 
1981             surf_usm_v(l)%rad_lw_out = 0.0_wp 
1982             surf_usm_v(l)%rad_lw_dif = 0.0_wp 
1983             surf_usm_v(l)%rad_lw_ref = 0.0_wp 
1984             surf_usm_v(l)%rad_lw_res = 0.0_wp 
1985          ENDIF
1986       ENDDO
1987!
1988!--    Fix net radiation in case of radiation_scheme = 'constant'
1989       IF ( radiation_scheme == 'constant' )  THEN
1990          IF ( ALLOCATED( surf_lsm_h%rad_net ) )                               &
1991             surf_lsm_h%rad_net    = net_radiation
1992          IF ( ALLOCATED( surf_usm_h%rad_net ) )                               &
1993             surf_usm_h%rad_net    = net_radiation
1994!
1995!--       Todo: weight with inclination angle
1996          DO  l = 0, 3
1997             IF ( ALLOCATED( surf_lsm_v(l)%rad_net ) )                         &
1998                surf_lsm_v(l)%rad_net = net_radiation
1999             IF ( ALLOCATED( surf_usm_v(l)%rad_net ) )                         &
2000                surf_usm_v(l)%rad_net = net_radiation
2001          ENDDO
2002!          radiation = .FALSE.
2003!
2004!--    Calculate orbital constants
2005       ELSE
2006          decl_1 = SIN(23.45_wp * pi / 180.0_wp)
2007          decl_2 = 2.0_wp * pi / 365.0_wp
2008          decl_3 = decl_2 * 81.0_wp
2009          lat    = latitude * pi / 180.0_wp
2010          lon    = longitude * pi / 180.0_wp
2011       ENDIF
2012
2013       IF ( radiation_scheme == 'clear-sky'  .OR.                              &
2014            radiation_scheme == 'constant')  THEN
2015
2016
2017!
2018!--       Allocate arrays for incoming/outgoing short/longwave radiation
2019          IF ( .NOT. ALLOCATED ( rad_sw_in ) )  THEN
2020             ALLOCATE ( rad_sw_in(0:0,nysg:nyng,nxlg:nxrg) )
2021          ENDIF
2022          IF ( .NOT. ALLOCATED ( rad_sw_out ) )  THEN
2023             ALLOCATE ( rad_sw_out(0:0,nysg:nyng,nxlg:nxrg) )
2024          ENDIF
2025
2026          IF ( .NOT. ALLOCATED ( rad_lw_in ) )  THEN
2027             ALLOCATE ( rad_lw_in(0:0,nysg:nyng,nxlg:nxrg) )
2028          ENDIF
2029          IF ( .NOT. ALLOCATED ( rad_lw_out ) )  THEN
2030             ALLOCATE ( rad_lw_out(0:0,nysg:nyng,nxlg:nxrg) )
2031          ENDIF
2032
2033!
2034!--       Allocate average arrays for incoming/outgoing short/longwave radiation
2035          IF ( .NOT. ALLOCATED ( rad_sw_in_av ) )  THEN
2036             ALLOCATE ( rad_sw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
2037          ENDIF
2038          IF ( .NOT. ALLOCATED ( rad_sw_out_av ) )  THEN
2039             ALLOCATE ( rad_sw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
2040          ENDIF
2041
2042          IF ( .NOT. ALLOCATED ( rad_lw_in_av ) )  THEN
2043             ALLOCATE ( rad_lw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
2044          ENDIF
2045          IF ( .NOT. ALLOCATED ( rad_lw_out_av ) )  THEN
2046             ALLOCATE ( rad_lw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
2047          ENDIF
2048!
2049!--       Allocate arrays for broadband albedo, and level 1 initialization
2050!--       via namelist paramter, unless not already allocated.
2051          IF ( .NOT. ALLOCATED(surf_lsm_h%albedo) )  THEN
2052             ALLOCATE( surf_lsm_h%albedo(0:2,1:surf_lsm_h%ns)     )
2053             surf_lsm_h%albedo    = albedo
2054          ENDIF
2055          IF ( .NOT. ALLOCATED(surf_usm_h%albedo) )  THEN
2056             ALLOCATE( surf_usm_h%albedo(0:2,1:surf_usm_h%ns)     )
2057             surf_usm_h%albedo    = albedo
2058          ENDIF
2059
2060          DO  l = 0, 3
2061             IF ( .NOT. ALLOCATED( surf_lsm_v(l)%albedo ) )  THEN
2062                ALLOCATE( surf_lsm_v(l)%albedo(0:2,1:surf_lsm_v(l)%ns) )
2063                surf_lsm_v(l)%albedo = albedo
2064             ENDIF
2065             IF ( .NOT. ALLOCATED( surf_usm_v(l)%albedo ) )  THEN
2066                ALLOCATE( surf_usm_v(l)%albedo(0:2,1:surf_usm_v(l)%ns) )
2067                surf_usm_v(l)%albedo = albedo
2068             ENDIF
2069          ENDDO
2070!
2071!--       Level 2 initialization of broadband albedo via given albedo_type.
2072!--       Only if albedo_type is non-zero. In case of urban surface and
2073!--       input data is read from ASCII file, albedo_type will be zero, so that
2074!--       albedo won't be overwritten.
2075          DO  m = 1, surf_lsm_h%ns
2076             IF ( surf_lsm_h%albedo_type(ind_veg_wall,m) /= 0 )                &
2077                surf_lsm_h%albedo(ind_veg_wall,m) =                            &
2078                           albedo_pars(2,surf_lsm_h%albedo_type(ind_veg_wall,m))
2079             IF ( surf_lsm_h%albedo_type(ind_pav_green,m) /= 0 )               &
2080                surf_lsm_h%albedo(ind_pav_green,m) =                           &
2081                           albedo_pars(2,surf_lsm_h%albedo_type(ind_pav_green,m))
2082             IF ( surf_lsm_h%albedo_type(ind_wat_win,m) /= 0 )                 &
2083                surf_lsm_h%albedo(ind_wat_win,m) =                             &
2084                           albedo_pars(2,surf_lsm_h%albedo_type(ind_wat_win,m))
2085          ENDDO
2086          DO  m = 1, surf_usm_h%ns
2087             IF ( surf_usm_h%albedo_type(ind_veg_wall,m) /= 0 )                &
2088                surf_usm_h%albedo(ind_veg_wall,m) =                            &
2089                           albedo_pars(2,surf_usm_h%albedo_type(ind_veg_wall,m))
2090             IF ( surf_usm_h%albedo_type(ind_pav_green,m) /= 0 )               &
2091                surf_usm_h%albedo(ind_pav_green,m) =                           &
2092                           albedo_pars(2,surf_usm_h%albedo_type(ind_pav_green,m))
2093             IF ( surf_usm_h%albedo_type(ind_wat_win,m) /= 0 )                 &
2094                surf_usm_h%albedo(ind_wat_win,m) =                             &
2095                           albedo_pars(2,surf_usm_h%albedo_type(ind_wat_win,m))
2096          ENDDO
2097
2098          DO  l = 0, 3
2099             DO  m = 1, surf_lsm_v(l)%ns
2100                IF ( surf_lsm_v(l)%albedo_type(ind_veg_wall,m) /= 0 )          &
2101                   surf_lsm_v(l)%albedo(ind_veg_wall,m) =                      &
2102                        albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_veg_wall,m))
2103                IF ( surf_lsm_v(l)%albedo_type(ind_pav_green,m) /= 0 )         &
2104                   surf_lsm_v(l)%albedo(ind_pav_green,m) =                     &
2105                        albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_pav_green,m))
2106                IF ( surf_lsm_v(l)%albedo_type(ind_wat_win,m) /= 0 )           &
2107                   surf_lsm_v(l)%albedo(ind_wat_win,m) =                       &
2108                        albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_wat_win,m))
2109             ENDDO
2110             DO  m = 1, surf_usm_v(l)%ns
2111                IF ( surf_usm_v(l)%albedo_type(ind_veg_wall,m) /= 0 )          &
2112                   surf_usm_v(l)%albedo(ind_veg_wall,m) =                      &
2113                        albedo_pars(2,surf_usm_v(l)%albedo_type(ind_veg_wall,m))
2114                IF ( surf_usm_v(l)%albedo_type(ind_pav_green,m) /= 0 )         &
2115                   surf_usm_v(l)%albedo(ind_pav_green,m) =                     &
2116                        albedo_pars(2,surf_usm_v(l)%albedo_type(ind_pav_green,m))
2117                IF ( surf_usm_v(l)%albedo_type(ind_wat_win,m) /= 0 )           &
2118                   surf_usm_v(l)%albedo(ind_wat_win,m) =                       &
2119                        albedo_pars(2,surf_usm_v(l)%albedo_type(ind_wat_win,m))
2120             ENDDO
2121          ENDDO
2122
2123!
2124!--       Level 3 initialization at grid points where albedo type is zero.
2125!--       This case, albedo is taken from file. In case of constant radiation
2126!--       or clear sky, only broadband albedo is given.
2127          IF ( albedo_pars_f%from_file )  THEN
2128!
2129!--          Horizontal surfaces
2130             DO  m = 1, surf_lsm_h%ns
2131                i = surf_lsm_h%i(m)
2132                j = surf_lsm_h%j(m)
2133                IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2134                   IF ( surf_lsm_h%albedo_type(ind_veg_wall,m) == 0 )          &
2135                      surf_lsm_h%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2136                   IF ( surf_lsm_h%albedo_type(ind_pav_green,m) == 0 )         &
2137                      surf_lsm_h%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2138                   IF ( surf_lsm_h%albedo_type(ind_wat_win,m) == 0 )           &
2139                      surf_lsm_h%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2140                ENDIF
2141             ENDDO
2142             DO  m = 1, surf_usm_h%ns
2143                i = surf_usm_h%i(m)
2144                j = surf_usm_h%j(m)
2145                IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2146                   IF ( surf_usm_h%albedo_type(ind_veg_wall,m) == 0 )          &
2147                      surf_usm_h%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2148                   IF ( surf_usm_h%albedo_type(ind_pav_green,m) == 0 )         &
2149                      surf_usm_h%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2150                   IF ( surf_usm_h%albedo_type(ind_wat_win,m) == 0 )           &
2151                      surf_usm_h%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2152                ENDIF
2153             ENDDO 
2154!
2155!--          Vertical surfaces           
2156             DO  l = 0, 3
2157
2158                ioff = surf_lsm_v(l)%ioff
2159                joff = surf_lsm_v(l)%joff
2160                DO  m = 1, surf_lsm_v(l)%ns
2161                   i = surf_lsm_v(l)%i(m) + ioff
2162                   j = surf_lsm_v(l)%j(m) + joff
2163                   IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2164                      IF ( surf_lsm_v(l)%albedo_type(ind_veg_wall,m) == 0 )    &
2165                         surf_lsm_v(l)%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2166                      IF ( surf_lsm_v(l)%albedo_type(ind_pav_green,m) == 0 )   &
2167                         surf_lsm_v(l)%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2168                      IF ( surf_lsm_v(l)%albedo_type(ind_wat_win,m) == 0 )     &
2169                         surf_lsm_v(l)%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2170                   ENDIF
2171                ENDDO
2172
2173                ioff = surf_usm_v(l)%ioff
2174                joff = surf_usm_v(l)%joff
2175                DO  m = 1, surf_usm_h%ns
2176                   i = surf_usm_h%i(m) + joff
2177                   j = surf_usm_h%j(m) + joff
2178                   IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2179                      IF ( surf_usm_v(l)%albedo_type(ind_veg_wall,m) == 0 )    &
2180                         surf_usm_v(l)%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2181                      IF ( surf_usm_v(l)%albedo_type(ind_pav_green,m) == 0 )   &
2182                         surf_usm_v(l)%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2183                      IF ( surf_usm_v(l)%albedo_type(ind_wat_win,m) == 0 )     &
2184                         surf_lsm_v(l)%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2185                   ENDIF
2186                ENDDO
2187             ENDDO
2188
2189          ENDIF 
2190!
2191!--    Initialization actions for RRTMG
2192       ELSEIF ( radiation_scheme == 'rrtmg' )  THEN
2193#if defined ( __rrtmg )
2194!
2195!--       Allocate albedos for short/longwave radiation, horizontal surfaces
2196!--       for wall/green/window (USM) or vegetation/pavement/water surfaces
2197!--       (LSM).
2198          ALLOCATE ( surf_lsm_h%aldif(0:2,1:surf_lsm_h%ns)       )
2199          ALLOCATE ( surf_lsm_h%aldir(0:2,1:surf_lsm_h%ns)       )
2200          ALLOCATE ( surf_lsm_h%asdif(0:2,1:surf_lsm_h%ns)       )
2201          ALLOCATE ( surf_lsm_h%asdir(0:2,1:surf_lsm_h%ns)       )
2202          ALLOCATE ( surf_lsm_h%rrtm_aldif(0:2,1:surf_lsm_h%ns)  )
2203          ALLOCATE ( surf_lsm_h%rrtm_aldir(0:2,1:surf_lsm_h%ns)  )
2204          ALLOCATE ( surf_lsm_h%rrtm_asdif(0:2,1:surf_lsm_h%ns)  )
2205          ALLOCATE ( surf_lsm_h%rrtm_asdir(0:2,1:surf_lsm_h%ns)  )
2206
2207          ALLOCATE ( surf_usm_h%aldif(0:2,1:surf_usm_h%ns)       )
2208          ALLOCATE ( surf_usm_h%aldir(0:2,1:surf_usm_h%ns)       )
2209          ALLOCATE ( surf_usm_h%asdif(0:2,1:surf_usm_h%ns)       )
2210          ALLOCATE ( surf_usm_h%asdir(0:2,1:surf_usm_h%ns)       )
2211          ALLOCATE ( surf_usm_h%rrtm_aldif(0:2,1:surf_usm_h%ns)  )
2212          ALLOCATE ( surf_usm_h%rrtm_aldir(0:2,1:surf_usm_h%ns)  )
2213          ALLOCATE ( surf_usm_h%rrtm_asdif(0:2,1:surf_usm_h%ns)  )
2214          ALLOCATE ( surf_usm_h%rrtm_asdir(0:2,1:surf_usm_h%ns)  )
2215
2216!
2217!--       Allocate broadband albedo (temporary for the current radiation
2218!--       implementations)
2219          IF ( .NOT. ALLOCATED(surf_lsm_h%albedo) )                            &
2220             ALLOCATE( surf_lsm_h%albedo(0:2,1:surf_lsm_h%ns)     )
2221          IF ( .NOT. ALLOCATED(surf_usm_h%albedo) )                            &
2222             ALLOCATE( surf_usm_h%albedo(0:2,1:surf_usm_h%ns)     )
2223
2224!
2225!--       Allocate albedos for short/longwave radiation, vertical surfaces
2226          DO  l = 0, 3
2227
2228             ALLOCATE ( surf_lsm_v(l)%aldif(0:2,1:surf_lsm_v(l)%ns)      )
2229             ALLOCATE ( surf_lsm_v(l)%aldir(0:2,1:surf_lsm_v(l)%ns)      )
2230             ALLOCATE ( surf_lsm_v(l)%asdif(0:2,1:surf_lsm_v(l)%ns)      )
2231             ALLOCATE ( surf_lsm_v(l)%asdir(0:2,1:surf_lsm_v(l)%ns)      )
2232
2233             ALLOCATE ( surf_lsm_v(l)%rrtm_aldif(0:2,1:surf_lsm_v(l)%ns) )
2234             ALLOCATE ( surf_lsm_v(l)%rrtm_aldir(0:2,1:surf_lsm_v(l)%ns) )
2235             ALLOCATE ( surf_lsm_v(l)%rrtm_asdif(0:2,1:surf_lsm_v(l)%ns) )
2236             ALLOCATE ( surf_lsm_v(l)%rrtm_asdir(0:2,1:surf_lsm_v(l)%ns) )
2237
2238             ALLOCATE ( surf_usm_v(l)%aldif(0:2,1:surf_usm_v(l)%ns)      )
2239             ALLOCATE ( surf_usm_v(l)%aldir(0:2,1:surf_usm_v(l)%ns)      )
2240             ALLOCATE ( surf_usm_v(l)%asdif(0:2,1:surf_usm_v(l)%ns)      )
2241             ALLOCATE ( surf_usm_v(l)%asdir(0:2,1:surf_usm_v(l)%ns)      )
2242
2243             ALLOCATE ( surf_usm_v(l)%rrtm_aldif(0:2,1:surf_usm_v(l)%ns) )
2244             ALLOCATE ( surf_usm_v(l)%rrtm_aldir(0:2,1:surf_usm_v(l)%ns) )
2245             ALLOCATE ( surf_usm_v(l)%rrtm_asdif(0:2,1:surf_usm_v(l)%ns) )
2246             ALLOCATE ( surf_usm_v(l)%rrtm_asdir(0:2,1:surf_usm_v(l)%ns) )
2247!
2248!--          Allocate broadband albedo (temporary for the current radiation
2249!--          implementations)
2250             IF ( .NOT. ALLOCATED( surf_lsm_v(l)%albedo ) )                    &
2251                ALLOCATE( surf_lsm_v(l)%albedo(0:2,1:surf_lsm_v(l)%ns) )
2252             IF ( .NOT. ALLOCATED( surf_usm_v(l)%albedo ) )                    &
2253                ALLOCATE( surf_usm_v(l)%albedo(0:2,1:surf_usm_v(l)%ns) )
2254
2255          ENDDO
2256!
2257!--       Level 1 initialization of spectral albedos via namelist
2258!--       paramters. Please note, this case all surface tiles are initialized
2259!--       the same.
2260          IF ( surf_lsm_h%ns > 0 )  THEN
2261             surf_lsm_h%aldif  = albedo_lw_dif
2262             surf_lsm_h%aldir  = albedo_lw_dir
2263             surf_lsm_h%asdif  = albedo_sw_dif
2264             surf_lsm_h%asdir  = albedo_sw_dir
2265             surf_lsm_h%albedo = albedo_sw_dif
2266          ENDIF
2267          IF ( surf_usm_h%ns > 0 )  THEN
2268             IF ( surf_usm_h%albedo_from_ascii )  THEN
2269                surf_usm_h%aldif  = surf_usm_h%albedo
2270                surf_usm_h%aldir  = surf_usm_h%albedo
2271                surf_usm_h%asdif  = surf_usm_h%albedo
2272                surf_usm_h%asdir  = surf_usm_h%albedo
2273             ELSE
2274                surf_usm_h%aldif  = albedo_lw_dif
2275                surf_usm_h%aldir  = albedo_lw_dir
2276                surf_usm_h%asdif  = albedo_sw_dif
2277                surf_usm_h%asdir  = albedo_sw_dir
2278                surf_usm_h%albedo = albedo_sw_dif
2279             ENDIF
2280          ENDIF
2281
2282          DO  l = 0, 3
2283
2284             IF ( surf_lsm_v(l)%ns > 0 )  THEN
2285                surf_lsm_v(l)%aldif  = albedo_lw_dif
2286                surf_lsm_v(l)%aldir  = albedo_lw_dir
2287                surf_lsm_v(l)%asdif  = albedo_sw_dif
2288                surf_lsm_v(l)%asdir  = albedo_sw_dir
2289                surf_lsm_v(l)%albedo = albedo_sw_dif
2290             ENDIF
2291
2292             IF ( surf_usm_v(l)%ns > 0 )  THEN
2293                IF ( surf_usm_v(l)%albedo_from_ascii )  THEN
2294                   surf_usm_v(l)%aldif  = surf_usm_v(l)%albedo
2295                   surf_usm_v(l)%aldir  = surf_usm_v(l)%albedo
2296                   surf_usm_v(l)%asdif  = surf_usm_v(l)%albedo
2297                   surf_usm_v(l)%asdir  = surf_usm_v(l)%albedo
2298                ELSE
2299                   surf_usm_v(l)%aldif  = albedo_lw_dif
2300                   surf_usm_v(l)%aldir  = albedo_lw_dir
2301                   surf_usm_v(l)%asdif  = albedo_sw_dif
2302                   surf_usm_v(l)%asdir  = albedo_sw_dir
2303                ENDIF
2304             ENDIF
2305          ENDDO
2306
2307!
2308!--       Level 2 initialization of spectral albedos via albedo_type.
2309!--       Please note, for natural- and urban-type surfaces, a tile approach
2310!--       is applied so that the resulting albedo is calculated via the weighted
2311!--       average of respective surface fractions.
2312          DO  m = 1, surf_lsm_h%ns
2313!
2314!--          Spectral albedos for vegetation/pavement/water surfaces
2315             DO  ind_type = 0, 2
2316                IF ( surf_lsm_h%albedo_type(ind_type,m) /= 0 )  THEN
2317                   surf_lsm_h%aldif(ind_type,m) =                              &
2318                               albedo_pars(0,surf_lsm_h%albedo_type(ind_type,m))
2319                   surf_lsm_h%asdif(ind_type,m) =                              &
2320                               albedo_pars(1,surf_lsm_h%albedo_type(ind_type,m))
2321                   surf_lsm_h%aldir(ind_type,m) =                              &
2322                               albedo_pars(0,surf_lsm_h%albedo_type(ind_type,m))
2323                   surf_lsm_h%asdir(ind_type,m) =                              &
2324                               albedo_pars(1,surf_lsm_h%albedo_type(ind_type,m))
2325                   surf_lsm_h%albedo(ind_type,m) =                             &
2326                               albedo_pars(2,surf_lsm_h%albedo_type(ind_type,m))
2327                ENDIF
2328             ENDDO
2329
2330          ENDDO
2331!
2332!--       For urban surface only if albedo has not been already initialized
2333!--       in the urban-surface model via the ASCII file.
2334          IF ( .NOT. surf_usm_h%albedo_from_ascii )  THEN
2335             DO  m = 1, surf_usm_h%ns
2336!
2337!--             Spectral albedos for wall/green/window surfaces
2338                DO  ind_type = 0, 2
2339                   IF ( surf_usm_h%albedo_type(ind_type,m) /= 0 )  THEN
2340                      surf_usm_h%aldif(ind_type,m) =                           &
2341                               albedo_pars(0,surf_usm_h%albedo_type(ind_type,m))
2342                      surf_usm_h%asdif(ind_type,m) =                           &
2343                               albedo_pars(1,surf_usm_h%albedo_type(ind_type,m))
2344                      surf_usm_h%aldir(ind_type,m) =                           &
2345                               albedo_pars(0,surf_usm_h%albedo_type(ind_type,m))
2346                      surf_usm_h%asdir(ind_type,m) =                           &
2347                               albedo_pars(1,surf_usm_h%albedo_type(ind_type,m))
2348                      surf_usm_h%albedo(ind_type,m) =                          &
2349                               albedo_pars(2,surf_usm_h%albedo_type(ind_type,m))
2350                   ENDIF
2351                ENDDO
2352
2353             ENDDO
2354          ENDIF
2355
2356          DO l = 0, 3
2357
2358             DO  m = 1, surf_lsm_v(l)%ns
2359!
2360!--             Spectral albedos for vegetation/pavement/water surfaces
2361                DO  ind_type = 0, 2
2362                   IF ( surf_lsm_v(l)%albedo_type(ind_type,m) /= 0 )  THEN
2363                      surf_lsm_v(l)%aldif(ind_type,m) =                        &
2364                            albedo_pars(0,surf_lsm_v(l)%albedo_type(ind_type,m))
2365                      surf_lsm_v(l)%asdif(ind_type,m) =                        &
2366                            albedo_pars(1,surf_lsm_v(l)%albedo_type(ind_type,m))
2367                      surf_lsm_v(l)%aldir(ind_type,m) =                        &
2368                            albedo_pars(0,surf_lsm_v(l)%albedo_type(ind_type,m))
2369                      surf_lsm_v(l)%asdir(ind_type,m) =                        &
2370                            albedo_pars(1,surf_lsm_v(l)%albedo_type(ind_type,m))
2371                      surf_lsm_v(l)%albedo(ind_type,m) =                       &
2372                            albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_type,m))
2373                   ENDIF
2374                ENDDO
2375             ENDDO
2376!
2377!--          For urban surface only if albedo has not been already initialized
2378!--          in the urban-surface model via the ASCII file.
2379             IF ( .NOT. surf_usm_v(l)%albedo_from_ascii )  THEN
2380                DO  m = 1, surf_usm_v(l)%ns
2381!
2382!--                Spectral albedos for wall/green/window surfaces
2383                   DO  ind_type = 0, 2
2384                      IF ( surf_usm_v(l)%albedo_type(ind_type,m) /= 0 )  THEN
2385                         surf_usm_v(l)%aldif(ind_type,m) =                     &
2386                            albedo_pars(0,surf_usm_v(l)%albedo_type(ind_type,m))
2387                         surf_usm_v(l)%asdif(ind_type,m) =                     &
2388                            albedo_pars(1,surf_usm_v(l)%albedo_type(ind_type,m))
2389                         surf_usm_v(l)%aldir(ind_type,m) =                     &
2390                            albedo_pars(0,surf_usm_v(l)%albedo_type(ind_type,m))
2391                         surf_usm_v(l)%asdir(ind_type,m) =                     &
2392                            albedo_pars(1,surf_usm_v(l)%albedo_type(ind_type,m))
2393                         surf_usm_v(l)%albedo(ind_type,m) =                    &
2394                            albedo_pars(2,surf_usm_v(l)%albedo_type(ind_type,m))
2395                      ENDIF
2396                   ENDDO
2397
2398                ENDDO
2399             ENDIF
2400          ENDDO
2401!
2402!--       Level 3 initialization at grid points where albedo type is zero.
2403!--       This case, spectral albedos are taken from file if available
2404          IF ( albedo_pars_f%from_file )  THEN
2405!
2406!--          Horizontal
2407             DO  m = 1, surf_lsm_h%ns
2408                i = surf_lsm_h%i(m)
2409                j = surf_lsm_h%j(m)
2410!
2411!--             Spectral albedos for vegetation/pavement/water surfaces
2412                DO  ind_type = 0, 2
2413                   IF ( surf_lsm_h%albedo_type(ind_type,m) == 0 )  THEN
2414                      IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2415                         surf_lsm_h%albedo(ind_type,m) =                       &
2416                                                albedo_pars_f%pars_xy(1,j,i)
2417                      IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2418                         surf_lsm_h%aldir(ind_type,m) =                        &
2419                                                albedo_pars_f%pars_xy(1,j,i)
2420                      IF ( albedo_pars_f%pars_xy(2,j,i) /= albedo_pars_f%fill )&
2421                         surf_lsm_h%aldif(ind_type,m) =                        &
2422                                                albedo_pars_f%pars_xy(2,j,i)
2423                      IF ( albedo_pars_f%pars_xy(3,j,i) /= albedo_pars_f%fill )&
2424                         surf_lsm_h%asdir(ind_type,m) =                        &
2425                                                albedo_pars_f%pars_xy(3,j,i)
2426                      IF ( albedo_pars_f%pars_xy(4,j,i) /= albedo_pars_f%fill )&
2427                         surf_lsm_h%asdif(ind_type,m) =                        &
2428                                                albedo_pars_f%pars_xy(4,j,i)
2429                   ENDIF
2430                ENDDO
2431             ENDDO
2432!
2433!--          For urban surface only if albedo has not been already initialized
2434!--          in the urban-surface model via the ASCII file.
2435             IF ( .NOT. surf_usm_h%albedo_from_ascii )  THEN
2436                DO  m = 1, surf_usm_h%ns
2437                   i = surf_usm_h%i(m)
2438                   j = surf_usm_h%j(m)
2439!
2440!--                Spectral albedos for wall/green/window surfaces
2441                   DO  ind_type = 0, 2
2442                      IF ( surf_usm_h%albedo_type(ind_type,m) == 0 )  THEN
2443                         IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2444                            surf_usm_h%albedo(ind_type,m) =                       &
2445                                                albedo_pars_f%pars_xy(1,j,i)
2446                         IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2447                            surf_usm_h%aldir(ind_type,m) =                        &
2448                                                albedo_pars_f%pars_xy(1,j,i)
2449                         IF ( albedo_pars_f%pars_xy(2,j,i) /= albedo_pars_f%fill )&
2450                            surf_usm_h%aldif(ind_type,m) =                        &
2451                                                albedo_pars_f%pars_xy(2,j,i)
2452                         IF ( albedo_pars_f%pars_xy(3,j,i) /= albedo_pars_f%fill )&
2453                            surf_usm_h%asdir(ind_type,m) =                        &
2454                                                albedo_pars_f%pars_xy(3,j,i)
2455                         IF ( albedo_pars_f%pars_xy(4,j,i) /= albedo_pars_f%fill )&
2456                            surf_usm_h%asdif(ind_type,m) =                        &
2457                                                albedo_pars_f%pars_xy(4,j,i)
2458                      ENDIF
2459                   ENDDO
2460
2461                ENDDO
2462             ENDIF
2463!
2464!--          Vertical
2465             DO  l = 0, 3
2466                ioff = surf_lsm_v(l)%ioff
2467                joff = surf_lsm_v(l)%joff
2468
2469                DO  m = 1, surf_lsm_v(l)%ns
2470                   i = surf_lsm_v(l)%i(m)
2471                   j = surf_lsm_v(l)%j(m)
2472!
2473!--                Spectral albedos for vegetation/pavement/water surfaces
2474                   DO  ind_type = 0, 2
2475                      IF ( surf_lsm_v(l)%albedo_type(ind_type,m) == 0 )  THEN
2476                         IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2477                              albedo_pars_f%fill )                             &
2478                            surf_lsm_v(l)%albedo(ind_type,m) =                 &
2479                                          albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2480                         IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2481                              albedo_pars_f%fill )                             &
2482                            surf_lsm_v(l)%aldir(ind_type,m) =                  &
2483                                          albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2484                         IF ( albedo_pars_f%pars_xy(2,j+joff,i+ioff) /=        &
2485                              albedo_pars_f%fill )                             &
2486                            surf_lsm_v(l)%aldif(ind_type,m) =                  &
2487                                          albedo_pars_f%pars_xy(2,j+joff,i+ioff)
2488                         IF ( albedo_pars_f%pars_xy(3,j+joff,i+ioff) /=        &
2489                              albedo_pars_f%fill )                             &
2490                            surf_lsm_v(l)%asdir(ind_type,m) =                  &
2491                                          albedo_pars_f%pars_xy(3,j+joff,i+ioff)
2492                         IF ( albedo_pars_f%pars_xy(4,j+joff,i+ioff) /=        &
2493                              albedo_pars_f%fill )                             &
2494                            surf_lsm_v(l)%asdif(ind_type,m) =                  &
2495                                          albedo_pars_f%pars_xy(4,j+joff,i+ioff)
2496                      ENDIF
2497                   ENDDO
2498                ENDDO
2499!
2500!--             For urban surface only if albedo has not been already initialized
2501!--             in the urban-surface model via the ASCII file.
2502                IF ( .NOT. surf_usm_v(l)%albedo_from_ascii )  THEN
2503                   ioff = surf_usm_v(l)%ioff
2504                   joff = surf_usm_v(l)%joff
2505
2506                   DO  m = 1, surf_usm_v(l)%ns
2507                      i = surf_usm_v(l)%i(m)
2508                      j = surf_usm_v(l)%j(m)
2509!
2510!--                   Spectral albedos for wall/green/window surfaces
2511                      DO  ind_type = 0, 2
2512                         IF ( surf_usm_v(l)%albedo_type(ind_type,m) == 0 )  THEN
2513                            IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2514                                 albedo_pars_f%fill )                             &
2515                               surf_usm_v(l)%albedo(ind_type,m) =                 &
2516                                             albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2517                            IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2518                                 albedo_pars_f%fill )                             &
2519                               surf_usm_v(l)%aldir(ind_type,m) =                  &
2520                                             albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2521                            IF ( albedo_pars_f%pars_xy(2,j+joff,i+ioff) /=        &
2522                                 albedo_pars_f%fill )                             &
2523                               surf_usm_v(l)%aldif(ind_type,m) =                  &
2524                                             albedo_pars_f%pars_xy(2,j+joff,i+ioff)
2525                            IF ( albedo_pars_f%pars_xy(3,j+joff,i+ioff) /=        &
2526                                 albedo_pars_f%fill )                             &
2527                               surf_usm_v(l)%asdir(ind_type,m) =                  &
2528                                             albedo_pars_f%pars_xy(3,j+joff,i+ioff)
2529                            IF ( albedo_pars_f%pars_xy(4,j+joff,i+ioff) /=        &
2530                                 albedo_pars_f%fill )                             &
2531                               surf_usm_v(l)%asdif(ind_type,m) =                  &
2532                                             albedo_pars_f%pars_xy(4,j+joff,i+ioff)
2533                         ENDIF
2534                      ENDDO
2535
2536                   ENDDO
2537                ENDIF
2538             ENDDO
2539
2540          ENDIF
2541
2542!
2543!--       Calculate initial values of current (cosine of) the zenith angle and
2544!--       whether the sun is up
2545          CALL calc_zenith     
2546          ! readjust date and time to its initial value
2547          CALL init_date_and_time
2548!
2549!--       Calculate initial surface albedo for different surfaces
2550          IF ( .NOT. constant_albedo )  THEN
2551#if defined( __netcdf )
2552!
2553!--          Horizontally aligned natural and urban surfaces
2554             CALL calc_albedo( surf_lsm_h    )
2555             CALL calc_albedo( surf_usm_h    )
2556!
2557!--          Vertically aligned natural and urban surfaces
2558             DO  l = 0, 3
2559                CALL calc_albedo( surf_lsm_v(l) )
2560                CALL calc_albedo( surf_usm_v(l) )
2561             ENDDO
2562#endif
2563          ELSE
2564!
2565!--          Initialize sun-inclination independent spectral albedos
2566!--          Horizontal surfaces
2567             IF ( surf_lsm_h%ns > 0 )  THEN
2568                surf_lsm_h%rrtm_aldir = surf_lsm_h%aldir
2569                surf_lsm_h%rrtm_asdir = surf_lsm_h%asdir
2570                surf_lsm_h%rrtm_aldif = surf_lsm_h%aldif
2571                surf_lsm_h%rrtm_asdif = surf_lsm_h%asdif
2572             ENDIF
2573             IF ( surf_usm_h%ns > 0 )  THEN
2574                surf_usm_h%rrtm_aldir = surf_usm_h%aldir
2575                surf_usm_h%rrtm_asdir = surf_usm_h%asdir
2576                surf_usm_h%rrtm_aldif = surf_usm_h%aldif
2577                surf_usm_h%rrtm_asdif = surf_usm_h%asdif
2578             ENDIF
2579!
2580!--          Vertical surfaces
2581             DO  l = 0, 3
2582                IF ( surf_lsm_v(l)%ns > 0 )  THEN
2583                   surf_lsm_v(l)%rrtm_aldir = surf_lsm_v(l)%aldir
2584                   surf_lsm_v(l)%rrtm_asdir = surf_lsm_v(l)%asdir
2585                   surf_lsm_v(l)%rrtm_aldif = surf_lsm_v(l)%aldif
2586                   surf_lsm_v(l)%rrtm_asdif = surf_lsm_v(l)%asdif
2587                ENDIF
2588                IF ( surf_usm_v(l)%ns > 0 )  THEN
2589                   surf_usm_v(l)%rrtm_aldir = surf_usm_v(l)%aldir
2590                   surf_usm_v(l)%rrtm_asdir = surf_usm_v(l)%asdir
2591                   surf_usm_v(l)%rrtm_aldif = surf_usm_v(l)%aldif
2592                   surf_usm_v(l)%rrtm_asdif = surf_usm_v(l)%asdif
2593                ENDIF
2594             ENDDO
2595
2596          ENDIF
2597
2598!
2599!--       Allocate 3d arrays of radiative fluxes and heating rates
2600          IF ( .NOT. ALLOCATED ( rad_sw_in ) )  THEN
2601             ALLOCATE ( rad_sw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2602             rad_sw_in = 0.0_wp
2603          ENDIF
2604
2605          IF ( .NOT. ALLOCATED ( rad_sw_in_av ) )  THEN
2606             ALLOCATE ( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2607          ENDIF
2608
2609          IF ( .NOT. ALLOCATED ( rad_sw_out ) )  THEN
2610             ALLOCATE ( rad_sw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2611             rad_sw_out = 0.0_wp
2612          ENDIF
2613
2614          IF ( .NOT. ALLOCATED ( rad_sw_out_av ) )  THEN
2615             ALLOCATE ( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2616          ENDIF
2617
2618          IF ( .NOT. ALLOCATED ( rad_sw_hr ) )  THEN
2619             ALLOCATE ( rad_sw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2620             rad_sw_hr = 0.0_wp
2621          ENDIF
2622
2623          IF ( .NOT. ALLOCATED ( rad_sw_hr_av ) )  THEN
2624             ALLOCATE ( rad_sw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2625             rad_sw_hr_av = 0.0_wp
2626          ENDIF
2627
2628          IF ( .NOT. ALLOCATED ( rad_sw_cs_hr ) )  THEN
2629             ALLOCATE ( rad_sw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2630             rad_sw_cs_hr = 0.0_wp
2631          ENDIF
2632
2633          IF ( .NOT. ALLOCATED ( rad_sw_cs_hr_av ) )  THEN
2634             ALLOCATE ( rad_sw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2635             rad_sw_cs_hr_av = 0.0_wp
2636          ENDIF
2637
2638          IF ( .NOT. ALLOCATED ( rad_lw_in ) )  THEN
2639             ALLOCATE ( rad_lw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2640             rad_lw_in     = 0.0_wp
2641          ENDIF
2642
2643          IF ( .NOT. ALLOCATED ( rad_lw_in_av ) )  THEN
2644             ALLOCATE ( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2645          ENDIF
2646
2647          IF ( .NOT. ALLOCATED ( rad_lw_out ) )  THEN
2648             ALLOCATE ( rad_lw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2649            rad_lw_out    = 0.0_wp
2650          ENDIF
2651
2652          IF ( .NOT. ALLOCATED ( rad_lw_out_av ) )  THEN
2653             ALLOCATE ( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2654          ENDIF
2655
2656          IF ( .NOT. ALLOCATED ( rad_lw_hr ) )  THEN
2657             ALLOCATE ( rad_lw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2658             rad_lw_hr = 0.0_wp
2659          ENDIF
2660
2661          IF ( .NOT. ALLOCATED ( rad_lw_hr_av ) )  THEN
2662             ALLOCATE ( rad_lw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2663             rad_lw_hr_av = 0.0_wp
2664          ENDIF
2665
2666          IF ( .NOT. ALLOCATED ( rad_lw_cs_hr ) )  THEN
2667             ALLOCATE ( rad_lw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2668             rad_lw_cs_hr = 0.0_wp
2669          ENDIF
2670
2671          IF ( .NOT. ALLOCATED ( rad_lw_cs_hr_av ) )  THEN
2672             ALLOCATE ( rad_lw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2673             rad_lw_cs_hr_av = 0.0_wp
2674          ENDIF
2675
2676          ALLOCATE ( rad_sw_cs_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2677          ALLOCATE ( rad_sw_cs_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2678          rad_sw_cs_in  = 0.0_wp
2679          rad_sw_cs_out = 0.0_wp
2680
2681          ALLOCATE ( rad_lw_cs_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2682          ALLOCATE ( rad_lw_cs_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2683          rad_lw_cs_in  = 0.0_wp
2684          rad_lw_cs_out = 0.0_wp
2685
2686!
2687!--       Allocate 1-element array for surface temperature
2688!--       (RRTMG anticipates an array as passed argument).
2689          ALLOCATE ( rrtm_tsfc(1) )
2690!
2691!--       Allocate surface emissivity.
2692!--       Values will be given directly before calling rrtm_lw.
2693          ALLOCATE ( rrtm_emis(0:0,1:nbndlw+1) )
2694
2695!
2696!--       Initialize RRTMG, before check if files are existent
2697          INQUIRE( FILE='rrtmg_lw.nc', EXIST=lw_exists )
2698          IF ( .NOT. lw_exists )  THEN
2699             message_string = 'Input file rrtmg_lw.nc' //                &
2700                            '&for rrtmg missing. ' // &
2701                            '&Please provide <jobname>_lsw file in the INPUT directory.'
2702             CALL message( 'radiation_init', 'PA0583', 1, 2, 0, 6, 0 )
2703          ENDIF         
2704          INQUIRE( FILE='rrtmg_sw.nc', EXIST=sw_exists )
2705          IF ( .NOT. sw_exists )  THEN
2706             message_string = 'Input file rrtmg_sw.nc' //                &
2707                            '&for rrtmg missing. ' // &
2708                            '&Please provide <jobname>_rsw file in the INPUT directory.'
2709             CALL message( 'radiation_init', 'PA0584', 1, 2, 0, 6, 0 )
2710          ENDIF         
2711         
2712          IF ( lw_radiation )  CALL rrtmg_lw_ini ( c_p )
2713          IF ( sw_radiation )  CALL rrtmg_sw_ini ( c_p )
2714         
2715!
2716!--       Set input files for RRTMG
2717          INQUIRE(FILE="RAD_SND_DATA", EXIST=snd_exists) 
2718          IF ( .NOT. snd_exists )  THEN
2719             rrtm_input_file = "rrtmg_lw.nc"
2720          ENDIF
2721
2722!
2723!--       Read vertical layers for RRTMG from sounding data
2724!--       The routine provides nzt_rad, hyp_snd(1:nzt_rad),
2725!--       t_snd(nzt+2:nzt_rad), rrtm_play(1:nzt_rad), rrtm_plev(1_nzt_rad+1),
2726!--       rrtm_tlay(nzt+2:nzt_rad), rrtm_tlev(nzt+2:nzt_rad+1)
2727          CALL read_sounding_data
2728
2729!
2730!--       Read trace gas profiles from file. This routine provides
2731!--       the rrtm_ arrays (1:nzt_rad+1)
2732          CALL read_trace_gas_data
2733#endif
2734       ENDIF
2735
2736!
2737!--    Perform user actions if required
2738       CALL user_init_radiation
2739
2740!
2741!--    Calculate radiative fluxes at model start
2742       SELECT CASE ( TRIM( radiation_scheme ) )
2743
2744          CASE ( 'rrtmg' )
2745             CALL radiation_rrtmg
2746
2747          CASE ( 'clear-sky' )
2748             CALL radiation_clearsky
2749
2750          CASE ( 'constant' )
2751             CALL radiation_constant
2752
2753          CASE DEFAULT
2754
2755       END SELECT
2756
2757! readjust date and time to its initial value
2758       CALL init_date_and_time
2759
2760       CALL location_message( 'finished', .TRUE. )
2761
2762!
2763!--    Find all discretized apparent solar positions for radiation interaction.
2764       IF ( radiation_interactions )  CALL radiation_presimulate_solar_pos
2765
2766!
2767!--    If required, read or calculate and write out the SVF
2768       IF ( radiation_interactions .AND. read_svf)  THEN
2769!
2770!--       Read sky-view factors and further required data from file
2771          CALL location_message( '    Start reading SVF from file', .FALSE. )
2772          CALL radiation_read_svf()
2773          CALL location_message( '    Reading SVF from file has finished', .TRUE. )
2774
2775       ELSEIF ( radiation_interactions .AND. .NOT. read_svf)  THEN
2776!
2777!--       calculate SFV and CSF
2778          CALL location_message( '    Start calculation of SVF', .FALSE. )
2779          CALL radiation_calc_svf()
2780          CALL location_message( '    Calculation of SVF has finished', .TRUE. )
2781       ENDIF
2782
2783       IF ( radiation_interactions .AND. write_svf)  THEN
2784!
2785!--       Write svf, csf svfsurf and csfsurf data to file
2786          CALL location_message( '    Start writing SVF in file', .FALSE. )
2787          CALL radiation_write_svf()
2788          CALL location_message( '    Writing SVF in file has finished', .TRUE. )
2789       ENDIF
2790
2791!
2792!--    Adjust radiative fluxes. In case of urban and land surfaces, also
2793!--    call an initial interaction.
2794       IF ( radiation_interactions )  THEN
2795          CALL radiation_interaction
2796       ENDIF
2797
2798       RETURN
2799
2800    END SUBROUTINE radiation_init
2801
2802
2803!------------------------------------------------------------------------------!
2804! Description:
2805! ------------
2806!> A simple clear sky radiation model
2807!------------------------------------------------------------------------------!
2808    SUBROUTINE radiation_clearsky
2809
2810
2811       IMPLICIT NONE
2812
2813       INTEGER(iwp) ::  l         !< running index for surface orientation
2814       REAL(wp)     ::  pt1       !< potential temperature at first grid level or mean value at urban layer top
2815       REAL(wp)     ::  pt1_l     !< potential temperature at first grid level or mean value at urban layer top at local subdomain
2816       REAL(wp)     ::  ql1       !< liquid water mixing ratio at first grid level or mean value at urban layer top
2817       REAL(wp)     ::  ql1_l     !< liquid water mixing ratio at first grid level or mean value at urban layer top at local subdomain
2818
2819       TYPE(surf_type), POINTER ::  surf !< pointer on respective surface type, used to generalize routine   
2820
2821!
2822!--    Calculate current zenith angle
2823       CALL calc_zenith
2824
2825!
2826!--    Calculate sky transmissivity
2827       sky_trans = 0.6_wp + 0.2_wp * zenith(0)
2828
2829!
2830!--    Calculate value of the Exner function at model surface
2831!
2832!--    In case averaged radiation is used, calculate mean temperature and
2833!--    liquid water mixing ratio at the urban-layer top.
2834       IF ( average_radiation ) THEN
2835          pt1   = 0.0_wp
2836          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1   = 0.0_wp
2837
2838          pt1_l = SUM( pt(nzut,nys:nyn,nxl:nxr) )
2839          IF ( bulk_cloud_model  .OR.  cloud_droplets  )  ql1_l = SUM( ql(nzut,nys:nyn,nxl:nxr) )
2840
2841#if defined( __parallel )     
2842          IF ( collective_wait )  CALL MPI_BARRIER( comm2d, ierr )
2843          CALL MPI_ALLREDUCE( pt1_l, pt1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
2844          IF ( ierr /= 0 ) THEN
2845              WRITE(9,*) 'Error MPI_AllReduce1:', ierr, pt1_l, pt1
2846              FLUSH(9)
2847          ENDIF
2848
2849          IF ( bulk_cloud_model  .OR.  cloud_droplets ) THEN
2850              CALL MPI_ALLREDUCE( ql1_l, ql1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
2851              IF ( ierr /= 0 ) THEN
2852                  WRITE(9,*) 'Error MPI_AllReduce2:', ierr, ql1_l, ql1
2853                  FLUSH(9)
2854              ENDIF
2855          ENDIF
2856#else
2857          pt1 = pt1_l 
2858          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1 = ql1_l
2859#endif
2860
2861          IF ( bulk_cloud_model  .OR.  cloud_droplets  )  pt1 = pt1 + lv_d_cp / exner(nzut) * ql1
2862!
2863!--       Finally, divide by number of grid points
2864          pt1 = pt1 / REAL( ( nx + 1 ) * ( ny + 1 ), KIND=wp )
2865       ENDIF
2866!
2867!--    Call clear-sky calculation for each surface orientation.
2868!--    First, horizontal surfaces
2869       surf => surf_lsm_h
2870       CALL radiation_clearsky_surf
2871       surf => surf_usm_h
2872       CALL radiation_clearsky_surf
2873!
2874!--    Vertical surfaces
2875       DO  l = 0, 3
2876          surf => surf_lsm_v(l)
2877          CALL radiation_clearsky_surf
2878          surf => surf_usm_v(l)
2879          CALL radiation_clearsky_surf
2880       ENDDO
2881
2882       CONTAINS
2883
2884          SUBROUTINE radiation_clearsky_surf
2885
2886             IMPLICIT NONE
2887
2888             INTEGER(iwp) ::  i         !< index x-direction
2889             INTEGER(iwp) ::  j         !< index y-direction
2890             INTEGER(iwp) ::  k         !< index z-direction
2891             INTEGER(iwp) ::  m         !< running index for surface elements
2892
2893             IF ( surf%ns < 1 )  RETURN
2894
2895!
2896!--          Calculate radiation fluxes and net radiation (rad_net) assuming
2897!--          homogeneous urban radiation conditions.
2898             IF ( average_radiation ) THEN       
2899
2900                k = nzut
2901
2902                surf%rad_sw_in  = solar_constant * sky_trans * zenith(0)
2903                surf%rad_sw_out = albedo_urb * surf%rad_sw_in
2904               
2905                surf%rad_lw_in  = 0.8_wp * sigma_sb * (pt1 * exner(k+1))**4
2906
2907                surf%rad_lw_out = emissivity_urb * sigma_sb * (t_rad_urb)**4   &
2908                                    + (1.0_wp - emissivity_urb) * surf%rad_lw_in
2909
2910                surf%rad_net = surf%rad_sw_in - surf%rad_sw_out                &
2911                             + surf%rad_lw_in - surf%rad_lw_out
2912
2913                surf%rad_lw_out_change_0 = 3.0_wp * emissivity_urb * sigma_sb  &
2914                                           * (t_rad_urb)**3
2915
2916!
2917!--          Calculate radiation fluxes and net radiation (rad_net) for each surface
2918!--          element.
2919             ELSE
2920
2921                DO  m = 1, surf%ns
2922                   i = surf%i(m)
2923                   j = surf%j(m)
2924                   k = surf%k(m)
2925
2926                   surf%rad_sw_in(m) = solar_constant * sky_trans * zenith(0)
2927
2928!
2929!--                Weighted average according to surface fraction.
2930!--                ATTENTION: when radiation interactions are switched on the
2931!--                calculated fluxes below are not actually used as they are
2932!--                overwritten in radiation_interaction.
2933                   surf%rad_sw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
2934                                          surf%albedo(ind_veg_wall,m)          &
2935                                        + surf%frac(ind_pav_green,m) *         &
2936                                          surf%albedo(ind_pav_green,m)         &
2937                                        + surf%frac(ind_wat_win,m)   *         &
2938                                          surf%albedo(ind_wat_win,m) )         &
2939                                        * surf%rad_sw_in(m)
2940
2941                   surf%rad_lw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
2942                                          surf%emissivity(ind_veg_wall,m)      &
2943                                        + surf%frac(ind_pav_green,m) *         &
2944                                          surf%emissivity(ind_pav_green,m)     &
2945                                        + surf%frac(ind_wat_win,m)   *         &
2946                                          surf%emissivity(ind_wat_win,m)       &
2947                                        )                                      &
2948                                        * sigma_sb                             &
2949                                        * ( surf%pt_surface(m) * exner(nzb) )**4
2950
2951                   surf%rad_lw_out_change_0(m) =                               &
2952                                      ( surf%frac(ind_veg_wall,m)  *           &
2953                                        surf%emissivity(ind_veg_wall,m)        &
2954                                      + surf%frac(ind_pav_green,m) *           &
2955                                        surf%emissivity(ind_pav_green,m)       &
2956                                      + surf%frac(ind_wat_win,m)   *           &
2957                                        surf%emissivity(ind_wat_win,m)         &
2958                                      ) * 3.0_wp * sigma_sb                    &
2959                                      * ( surf%pt_surface(m) * exner(nzb) )** 3
2960
2961
2962                   IF ( bulk_cloud_model  .OR.  cloud_droplets  )  THEN
2963                      pt1 = pt(k,j,i) + lv_d_cp / exner(k) * ql(k,j,i)
2964                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb * (pt1 * exner(k))**4
2965                   ELSE
2966                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb * (pt(k,j,i) * exner(k))**4
2967                   ENDIF
2968
2969                   surf%rad_net(m) = surf%rad_sw_in(m) - surf%rad_sw_out(m)    &
2970                                   + surf%rad_lw_in(m) - surf%rad_lw_out(m)
2971
2972                ENDDO
2973
2974             ENDIF
2975
2976!
2977!--          Fill out values in radiation arrays
2978             DO  m = 1, surf%ns
2979                i = surf%i(m)
2980                j = surf%j(m)
2981                rad_sw_in(0,j,i) = surf%rad_sw_in(m)
2982                rad_sw_out(0,j,i) = surf%rad_sw_out(m)
2983                rad_lw_in(0,j,i) = surf%rad_lw_in(m)
2984                rad_lw_out(0,j,i) = surf%rad_lw_out(m)
2985             ENDDO
2986 
2987          END SUBROUTINE radiation_clearsky_surf
2988
2989    END SUBROUTINE radiation_clearsky
2990
2991
2992!------------------------------------------------------------------------------!
2993! Description:
2994! ------------
2995!> This scheme keeps the prescribed net radiation constant during the run
2996!------------------------------------------------------------------------------!
2997    SUBROUTINE radiation_constant
2998
2999
3000       IMPLICIT NONE
3001
3002       INTEGER(iwp) ::  l         !< running index for surface orientation
3003
3004       REAL(wp)     ::  pt1       !< potential temperature at first grid level or mean value at urban layer top
3005       REAL(wp)     ::  pt1_l     !< potential temperature at first grid level or mean value at urban layer top at local subdomain
3006       REAL(wp)     ::  ql1       !< liquid water mixing ratio at first grid level or mean value at urban layer top
3007       REAL(wp)     ::  ql1_l     !< liquid water mixing ratio at first grid level or mean value at urban layer top at local subdomain
3008
3009       TYPE(surf_type), POINTER ::  surf !< pointer on respective surface type, used to generalize routine
3010
3011!
3012!--    In case averaged radiation is used, calculate mean temperature and
3013!--    liquid water mixing ratio at the urban-layer top.
3014       IF ( average_radiation ) THEN   
3015          pt1   = 0.0_wp
3016          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1   = 0.0_wp
3017
3018          pt1_l = SUM( pt(nzut,nys:nyn,nxl:nxr) )
3019          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1_l = SUM( ql(nzut,nys:nyn,nxl:nxr) )
3020
3021#if defined( __parallel )     
3022          IF ( collective_wait )  CALL MPI_BARRIER( comm2d, ierr )
3023          CALL MPI_ALLREDUCE( pt1_l, pt1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
3024          IF ( ierr /= 0 ) THEN
3025              WRITE(9,*) 'Error MPI_AllReduce3:', ierr, pt1_l, pt1
3026              FLUSH(9)
3027          ENDIF
3028          IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
3029             CALL MPI_ALLREDUCE( ql1_l, ql1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
3030             IF ( ierr /= 0 ) THEN
3031                 WRITE(9,*) 'Error MPI_AllReduce4:', ierr, ql1_l, ql1
3032                 FLUSH(9)
3033             ENDIF
3034          ENDIF
3035#else
3036          pt1 = pt1_l
3037          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1 = ql1_l
3038#endif
3039          IF ( bulk_cloud_model  .OR.  cloud_droplets )  pt1 = pt1 + lv_d_cp / exner(nzut+1) * ql1
3040!
3041!--       Finally, divide by number of grid points
3042          pt1 = pt1 / REAL( ( nx + 1 ) * ( ny + 1 ), KIND=wp )
3043       ENDIF
3044
3045!
3046!--    First, horizontal surfaces
3047       surf => surf_lsm_h
3048       CALL radiation_constant_surf
3049       surf => surf_usm_h
3050       CALL radiation_constant_surf
3051!
3052!--    Vertical surfaces
3053       DO  l = 0, 3
3054          surf => surf_lsm_v(l)
3055          CALL radiation_constant_surf
3056          surf => surf_usm_v(l)
3057          CALL radiation_constant_surf
3058       ENDDO
3059
3060       CONTAINS
3061
3062          SUBROUTINE radiation_constant_surf
3063
3064             IMPLICIT NONE
3065
3066             INTEGER(iwp) ::  i         !< index x-direction
3067             INTEGER(iwp) ::  ioff      !< offset between surface element and adjacent grid point along x
3068             INTEGER(iwp) ::  j         !< index y-direction
3069             INTEGER(iwp) ::  joff      !< offset between surface element and adjacent grid point along y
3070             INTEGER(iwp) ::  k         !< index z-direction
3071             INTEGER(iwp) ::  koff      !< offset between surface element and adjacent grid point along z
3072             INTEGER(iwp) ::  m         !< running index for surface elements
3073
3074             IF ( surf%ns < 1 )  RETURN
3075
3076!--          Calculate homogenoeus urban radiation fluxes
3077             IF ( average_radiation ) THEN
3078
3079                surf%rad_net = net_radiation
3080
3081                surf%rad_lw_in  = 0.8_wp * sigma_sb * (pt1 * exner(nzut+1))**4
3082
3083                surf%rad_lw_out = emissivity_urb * sigma_sb * (t_rad_urb)**4   &
3084                                    + ( 1.0_wp - emissivity_urb )             & ! shouldn't be this a bulk value -- emissivity_urb?
3085                                    * surf%rad_lw_in
3086
3087                surf%rad_lw_out_change_0 = 3.0_wp * emissivity_urb * sigma_sb  &
3088                                           * t_rad_urb**3
3089
3090                surf%rad_sw_in = ( surf%rad_net - surf%rad_lw_in               &
3091                                     + surf%rad_lw_out )                       &
3092                                     / ( 1.0_wp - albedo_urb )
3093
3094                surf%rad_sw_out =  albedo_urb * surf%rad_sw_in
3095
3096!
3097!--          Calculate radiation fluxes for each surface element
3098             ELSE
3099!
3100!--             Determine index offset between surface element and adjacent
3101!--             atmospheric grid point
3102                ioff = surf%ioff
3103                joff = surf%joff
3104                koff = surf%koff
3105
3106!
3107!--             Prescribe net radiation and estimate the remaining radiative fluxes
3108                DO  m = 1, surf%ns
3109                   i = surf%i(m)
3110                   j = surf%j(m)
3111                   k = surf%k(m)
3112
3113                   surf%rad_net(m) = net_radiation
3114
3115                   IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
3116                      pt1 = pt(k,j,i) + lv_d_cp / exner(k) * ql(k,j,i)
3117                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb * (pt1 * exner(k))**4
3118                   ELSE
3119                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb *                 &
3120                                             ( pt(k,j,i) * exner(k) )**4
3121                   ENDIF
3122
3123!
3124!--                Weighted average according to surface fraction.
3125                   surf%rad_lw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
3126                                          surf%emissivity(ind_veg_wall,m)      &
3127                                        + surf%frac(ind_pav_green,m) *         &
3128                                          surf%emissivity(ind_pav_green,m)     &
3129                                        + surf%frac(ind_wat_win,m)   *         &
3130                                          surf%emissivity(ind_wat_win,m)       &
3131                                        )                                      &
3132                                      * sigma_sb                               &
3133                                      * ( surf%pt_surface(m) * exner(nzb) )**4
3134
3135                   surf%rad_sw_in(m) = ( surf%rad_net(m) - surf%rad_lw_in(m)   &
3136                                       + surf%rad_lw_out(m) )                  &
3137                                       / ( 1.0_wp -                            &
3138                                          ( surf%frac(ind_veg_wall,m)  *       &
3139                                            surf%albedo(ind_veg_wall,m)        &
3140                                         +  surf%frac(ind_pav_green,m) *       &
3141                                            surf%albedo(ind_pav_green,m)       &
3142                                         +  surf%frac(ind_wat_win,m)   *       &
3143                                            surf%albedo(ind_wat_win,m) )       &
3144                                         )
3145
3146                   surf%rad_sw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
3147                                          surf%albedo(ind_veg_wall,m)          &
3148                                        + surf%frac(ind_pav_green,m) *         &
3149                                          surf%albedo(ind_pav_green,m)         &
3150                                        + surf%frac(ind_wat_win,m)   *         &
3151                                          surf%albedo(ind_wat_win,m) )         &
3152                                      * surf%rad_sw_in(m)
3153
3154                ENDDO
3155
3156             ENDIF
3157
3158!
3159!--          Fill out values in radiation arrays
3160             DO  m = 1, surf%ns
3161                i = surf%i(m)
3162                j = surf%j(m)
3163                rad_sw_in(0,j,i) = surf%rad_sw_in(m)
3164                rad_sw_out(0,j,i) = surf%rad_sw_out(m)
3165                rad_lw_in(0,j,i) = surf%rad_lw_in(m)
3166                rad_lw_out(0,j,i) = surf%rad_lw_out(m)
3167             ENDDO
3168
3169          END SUBROUTINE radiation_constant_surf
3170         
3171
3172    END SUBROUTINE radiation_constant
3173
3174!------------------------------------------------------------------------------!
3175! Description:
3176! ------------
3177!> Header output for radiation model
3178!------------------------------------------------------------------------------!
3179    SUBROUTINE radiation_header ( io )
3180
3181
3182       IMPLICIT NONE
3183 
3184       INTEGER(iwp), INTENT(IN) ::  io            !< Unit of the output file
3185   
3186
3187       
3188!
3189!--    Write radiation model header
3190       WRITE( io, 3 )
3191
3192       IF ( radiation_scheme == "constant" )  THEN
3193          WRITE( io, 4 ) net_radiation
3194       ELSEIF ( radiation_scheme == "clear-sky" )  THEN
3195          WRITE( io, 5 )
3196       ELSEIF ( radiation_scheme == "rrtmg" )  THEN
3197          WRITE( io, 6 )
3198          IF ( .NOT. lw_radiation )  WRITE( io, 10 )
3199          IF ( .NOT. sw_radiation )  WRITE( io, 11 )
3200       ENDIF
3201
3202       IF ( albedo_type_f%from_file  .OR.  vegetation_type_f%from_file  .OR.   &
3203            pavement_type_f%from_file  .OR.  water_type_f%from_file  .OR.      &
3204            building_type_f%from_file )  THEN
3205             WRITE( io, 13 )
3206       ELSE 
3207          IF ( albedo_type == 0 )  THEN
3208             WRITE( io, 7 ) albedo
3209          ELSE
3210             WRITE( io, 8 ) TRIM( albedo_type_name(albedo_type) )
3211          ENDIF
3212       ENDIF
3213       IF ( constant_albedo )  THEN
3214          WRITE( io, 9 )
3215       ENDIF
3216       
3217       WRITE( io, 12 ) dt_radiation
3218 
3219
3220 3 FORMAT (//' Radiation model information:'/                                  &
3221              ' ----------------------------'/)
3222 4 FORMAT ('    --> Using constant net radiation: net_radiation = ', F6.2,     &
3223           // 'W/m**2')
3224 5 FORMAT ('    --> Simple radiation scheme for clear sky is used (no clouds,',&
3225                   ' default)')
3226 6 FORMAT ('    --> RRTMG scheme is used')
3227 7 FORMAT (/'    User-specific surface albedo: albedo =', F6.3)
3228 8 FORMAT (/'    Albedo is set for land surface type: ', A)
3229 9 FORMAT (/'    --> Albedo is fixed during the run')
323010 FORMAT (/'    --> Longwave radiation is disabled')
323111 FORMAT (/'    --> Shortwave radiation is disabled.')
323212 FORMAT  ('    Timestep: dt_radiation = ', F6.2, '  s')
323313 FORMAT (/'    Albedo is set individually for each xy-location, according ', &
3234                 'to given surface type.')
3235
3236
3237    END SUBROUTINE radiation_header
3238   
3239
3240!------------------------------------------------------------------------------!
3241! Description:
3242! ------------
3243!> Parin for &radiation_parameters for radiation model
3244!------------------------------------------------------------------------------!
3245    SUBROUTINE radiation_parin
3246
3247
3248       IMPLICIT NONE
3249
3250       CHARACTER (LEN=80) ::  line  !< dummy string that contains the current line of the parameter file
3251       
3252       NAMELIST /radiation_par/   albedo, albedo_lw_dif, albedo_lw_dir,         &
3253                                  albedo_sw_dif, albedo_sw_dir, albedo_type,    &
3254                                  constant_albedo, dt_radiation, emissivity,    &
3255                                  lw_radiation, max_raytracing_dist,            &
3256                                  min_irrf_value, mrt_geom_human,               &
3257                                  mrt_include_sw, mrt_nlevels,                  &
3258                                  mrt_skip_roof, net_radiation, nrefsteps,      &
3259                                  plant_lw_interact, rad_angular_discretization,&
3260                                  radiation_interactions_on, radiation_scheme,  &
3261                                  raytrace_discrete_azims,                      &
3262                                  raytrace_discrete_elevs, raytrace_mpi_rma,    &
3263                                  skip_time_do_radiation, surface_reflections,  &
3264                                  svfnorm_report_thresh, sw_radiation,          &
3265                                  unscheduled_radiation_calls
3266
3267   
3268       NAMELIST /radiation_parameters/ albedo, albedo_lw_dif, albedo_lw_dir,    &
3269                                  albedo_sw_dif, albedo_sw_dir, albedo_type,    &
3270                                  constant_albedo, dt_radiation, emissivity,    &
3271                                  lw_radiation, max_raytracing_dist,            &
3272                                  min_irrf_value, mrt_geom_human,               &
3273                                  mrt_include_sw, mrt_nlevels,                  &
3274                                  mrt_skip_roof, net_radiation, nrefsteps,      &
3275                                  plant_lw_interact, rad_angular_discretization,&
3276                                  radiation_interactions_on, radiation_scheme,  &
3277                                  raytrace_discrete_azims,                      &
3278                                  raytrace_discrete_elevs, raytrace_mpi_rma,    &
3279                                  skip_time_do_radiation, surface_reflections,  &
3280                                  svfnorm_report_thresh, sw_radiation,          &
3281                                  unscheduled_radiation_calls
3282   
3283       line = ' '
3284       
3285!
3286!--    Try to find radiation model namelist
3287       REWIND ( 11 )
3288       line = ' '
3289       DO WHILE ( INDEX( line, '&radiation_parameters' ) == 0 )
3290          READ ( 11, '(A)', END=12 )  line
3291       ENDDO
3292       BACKSPACE ( 11 )
3293
3294!
3295!--    Read user-defined namelist
3296       READ ( 11, radiation_parameters, ERR = 10 )
3297
3298!
3299!--    Set flag that indicates that the radiation model is switched on
3300       radiation = .TRUE.
3301
3302       GOTO 14
3303
3304 10    BACKSPACE( 11 )
3305       READ( 11 , '(A)') line
3306       CALL parin_fail_message( 'radiation_parameters', line )
3307!
3308!--    Try to find old namelist
3309 12    REWIND ( 11 )
3310       line = ' '
3311       DO WHILE ( INDEX( line, '&radiation_par' ) == 0 )
3312          READ ( 11, '(A)', END=14 )  line
3313       ENDDO
3314       BACKSPACE ( 11 )
3315
3316!
3317!--    Read user-defined namelist
3318       READ ( 11, radiation_par, ERR = 13, END = 14 )
3319
3320       message_string = 'namelist radiation_par is deprecated and will be ' // &
3321                     'removed in near future. Please use namelist ' //         &
3322                     'radiation_parameters instead'
3323       CALL message( 'radiation_parin', 'PA0487', 0, 1, 0, 6, 0 )
3324
3325!
3326!--    Set flag that indicates that the radiation model is switched on
3327       radiation = .TRUE.
3328
3329       IF ( .NOT.  radiation_interactions_on  .AND.  surface_reflections )  THEN
3330          message_string = 'surface_reflections is allowed only when '      // &
3331               'radiation_interactions_on is set to TRUE'
3332          CALL message( 'radiation_parin', 'PA0293',1, 2, 0, 6, 0 )
3333       ENDIF
3334
3335       GOTO 14
3336
3337 13    BACKSPACE( 11 )
3338       READ( 11 , '(A)') line
3339       CALL parin_fail_message( 'radiation_par', line )
3340
3341 14    CONTINUE
3342       
3343    END SUBROUTINE radiation_parin
3344
3345
3346!------------------------------------------------------------------------------!
3347! Description:
3348! ------------
3349!> Implementation of the RRTMG radiation_scheme
3350!------------------------------------------------------------------------------!
3351    SUBROUTINE radiation_rrtmg
3352
3353#if defined ( __rrtmg )
3354       USE indices,                                                            &
3355           ONLY:  nbgp
3356
3357       USE particle_attributes,                                                &
3358           ONLY:  grid_particles, number_of_particles, particles,              &
3359                  particle_advection_start, prt_count
3360
3361       IMPLICIT NONE
3362
3363
3364       INTEGER(iwp) ::  i, j, k, l, m, n !< loop indices
3365       INTEGER(iwp) ::  k_topo     !< topography top index
3366
3367       REAL(wp)     ::  nc_rad, &    !< number concentration of cloud droplets
3368                        s_r2,   &    !< weighted sum over all droplets with r^2
3369                        s_r3         !< weighted sum over all droplets with r^3
3370
3371       REAL(wp), DIMENSION(0:nzt+1) :: pt_av, q_av, ql_av
3372!
3373!--    Just dummy arguments
3374       REAL(wp), DIMENSION(:,:,:), ALLOCATABLE :: rrtm_lw_taucld_dum,          &
3375                                                  rrtm_lw_tauaer_dum,          &
3376                                                  rrtm_sw_taucld_dum,          &
3377                                                  rrtm_sw_ssacld_dum,          &
3378                                                  rrtm_sw_asmcld_dum,          &
3379                                                  rrtm_sw_fsfcld_dum,          &
3380                                                  rrtm_sw_tauaer_dum,          &
3381                                                  rrtm_sw_ssaaer_dum,          &
3382                                                  rrtm_sw_asmaer_dum,          &
3383                                                  rrtm_sw_ecaer_dum
3384
3385!
3386!--    Calculate current (cosine of) zenith angle and whether the sun is up
3387       CALL calc_zenith     
3388!
3389!--    Calculate surface albedo. In case average radiation is applied,
3390!--    this is not required.
3391#if defined( __netcdf )
3392       IF ( .NOT. constant_albedo )  THEN
3393!
3394!--       Horizontally aligned default, natural and urban surfaces
3395          CALL calc_albedo( surf_lsm_h    )
3396          CALL calc_albedo( surf_usm_h    )
3397!
3398!--       Vertically aligned default, natural and urban surfaces
3399          DO  l = 0, 3
3400             CALL calc_albedo( surf_lsm_v(l) )
3401             CALL calc_albedo( surf_usm_v(l) )
3402          ENDDO
3403       ENDIF
3404#endif
3405
3406!
3407!--    Prepare input data for RRTMG
3408
3409!
3410!--    In case of large scale forcing with surface data, calculate new pressure
3411!--    profile. nzt_rad might be modified by these calls and all required arrays
3412!--    will then be re-allocated
3413       IF ( large_scale_forcing  .AND.  lsf_surf )  THEN
3414          CALL read_sounding_data
3415          CALL read_trace_gas_data
3416       ENDIF
3417
3418
3419       IF ( average_radiation ) THEN
3420
3421          rrtm_asdir(1)  = albedo_urb
3422          rrtm_asdif(1)  = albedo_urb
3423          rrtm_aldir(1)  = albedo_urb
3424          rrtm_aldif(1)  = albedo_urb
3425
3426          rrtm_emis = emissivity_urb
3427!
3428!--       Calculate mean pt profile. Actually, only one height level is required.
3429          CALL calc_mean_profile( pt, 4 )
3430          pt_av = hom(:, 1, 4, 0)
3431         
3432          IF ( humidity )  THEN
3433             CALL calc_mean_profile( q, 41 )
3434             q_av  = hom(:, 1, 41, 0)
3435          ENDIF
3436!
3437!--       Prepare profiles of temperature and H2O volume mixing ratio
3438          rrtm_tlev(0,nzb+1) = t_rad_urb
3439
3440          IF ( bulk_cloud_model )  THEN
3441
3442             CALL calc_mean_profile( ql, 54 )
3443             ! average ql is now in hom(:, 1, 54, 0)
3444             ql_av = hom(:, 1, 54, 0)
3445             
3446             DO k = nzb+1, nzt+1
3447                rrtm_tlay(0,k) = pt_av(k) * ( (hyp(k) ) / 100000._wp       &
3448                                 )**.286_wp + lv_d_cp * ql_av(k)
3449                rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * (q_av(k) - ql_av(k))
3450             ENDDO
3451          ELSE
3452             DO k = nzb+1, nzt+1
3453                rrtm_tlay(0,k) = pt_av(k) * ( (hyp(k) ) / 100000._wp       &
3454                                 )**.286_wp
3455             ENDDO
3456
3457             IF ( humidity )  THEN
3458                DO k = nzb+1, nzt+1
3459                   rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * q_av(k)
3460                ENDDO
3461             ELSE
3462                rrtm_h2ovmr(0,nzb+1:nzt+1) = 0.0_wp
3463             ENDIF
3464          ENDIF
3465
3466!
3467!--       Avoid temperature/humidity jumps at the top of the LES domain by
3468!--       linear interpolation from nzt+2 to nzt+7
3469          DO k = nzt+2, nzt+7
3470             rrtm_tlay(0,k) = rrtm_tlay(0,nzt+1)                            &
3471                           + ( rrtm_tlay(0,nzt+8) - rrtm_tlay(0,nzt+1) )    &
3472                           / ( rrtm_play(0,nzt+8) - rrtm_play(0,nzt+1) )    &
3473                           * ( rrtm_play(0,k) - rrtm_play(0,nzt+1) )
3474
3475             rrtm_h2ovmr(0,k) = rrtm_h2ovmr(0,nzt+1)                        &
3476                           + ( rrtm_h2ovmr(0,nzt+8) - rrtm_h2ovmr(0,nzt+1) )&
3477                           / ( rrtm_play(0,nzt+8)   - rrtm_play(0,nzt+1)   )&
3478                           * ( rrtm_play(0,k) - rrtm_play(0,nzt+1) )
3479
3480          ENDDO
3481
3482!--       Linear interpolate to zw grid
3483          DO k = nzb+2, nzt+8
3484             rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k) -        &
3485                                rrtm_tlay(0,k-1))                           &
3486                                / ( rrtm_play(0,k) - rrtm_play(0,k-1) )     &
3487                                * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
3488          ENDDO
3489
3490
3491!
3492!--       Calculate liquid water path and cloud fraction for each column.
3493!--       Note that LWP is required in g/m2 instead of kg/kg m.
3494          rrtm_cldfr  = 0.0_wp
3495          rrtm_reliq  = 0.0_wp
3496          rrtm_cliqwp = 0.0_wp
3497          rrtm_icld   = 0
3498
3499          IF ( bulk_cloud_model )  THEN
3500             DO k = nzb+1, nzt+1
3501                rrtm_cliqwp(0,k) =  ql_av(k) * 1000._wp *                   &
3502                                    (rrtm_plev(0,k) - rrtm_plev(0,k+1))     &
3503                                    * 100._wp / g 
3504
3505                IF ( rrtm_cliqwp(0,k) > 0._wp )  THEN
3506                   rrtm_cldfr(0,k) = 1._wp
3507                   IF ( rrtm_icld == 0 )  rrtm_icld = 1
3508
3509!
3510!--                Calculate cloud droplet effective radius
3511                   rrtm_reliq(0,k) = 1.0E6_wp * ( 3.0_wp * ql_av(k)         &
3512                                     * rho_surface                          &
3513                                     / ( 4.0_wp * pi * nc_const * rho_l )   &
3514                                     )**0.33333333333333_wp                 &
3515                                     * EXP( LOG( sigma_gc )**2 )
3516!
3517!--                Limit effective radius
3518                   IF ( rrtm_reliq(0,k) > 0.0_wp )  THEN
3519                      rrtm_reliq(0,k) = MAX(rrtm_reliq(0,k),2.5_wp)
3520                      rrtm_reliq(0,k) = MIN(rrtm_reliq(0,k),60.0_wp)
3521                   ENDIF
3522                ENDIF
3523             ENDDO
3524          ENDIF
3525
3526!
3527!--       Set surface temperature
3528          rrtm_tsfc = t_rad_urb
3529         
3530          IF ( lw_radiation )  THEN       
3531         
3532             CALL rrtmg_lw( 1, nzt_rad      , rrtm_icld    , rrtm_idrv      ,&
3533             rrtm_play       , rrtm_plev    , rrtm_tlay    , rrtm_tlev      ,&
3534             rrtm_tsfc       , rrtm_h2ovmr  , rrtm_o3vmr   , rrtm_co2vmr    ,&
3535             rrtm_ch4vmr     , rrtm_n2ovmr  , rrtm_o2vmr   , rrtm_cfc11vmr  ,&
3536             rrtm_cfc12vmr   , rrtm_cfc22vmr, rrtm_ccl4vmr , rrtm_emis      ,&
3537             rrtm_inflglw    , rrtm_iceflglw, rrtm_liqflglw, rrtm_cldfr     ,&
3538             rrtm_lw_taucld  , rrtm_cicewp  , rrtm_cliqwp  , rrtm_reice     ,& 
3539             rrtm_reliq      , rrtm_lw_tauaer,                               &
3540             rrtm_lwuflx     , rrtm_lwdflx  , rrtm_lwhr  ,                   &
3541             rrtm_lwuflxc    , rrtm_lwdflxc , rrtm_lwhrc ,                   &
3542             rrtm_lwuflx_dt  ,  rrtm_lwuflxc_dt )
3543
3544!
3545!--          Save fluxes
3546             DO k = nzb, nzt+1
3547                rad_lw_in(k,:,:)  = rrtm_lwdflx(0,k)
3548                rad_lw_out(k,:,:) = rrtm_lwuflx(0,k)
3549             ENDDO
3550             rad_lw_in_diff(:,:) = rad_lw_in(0,:,:)
3551!
3552!--          Save heating rates (convert from K/d to K/h).
3553!--          Further, even though an aggregated radiation is computed, map
3554!--          signle-column profiles on top of any topography, in order to
3555!--          obtain correct near surface radiation heating/cooling rates.
3556             DO  i = nxl, nxr
3557                DO  j = nys, nyn
3558                   k_topo = get_topography_top_index_ji( j, i, 's' )
3559                   DO k = k_topo+1, nzt+1
3560                      rad_lw_hr(k,j,i)     = rrtm_lwhr(0,k-k_topo)  * d_hours_day
3561                      rad_lw_cs_hr(k,j,i)  = rrtm_lwhrc(0,k-k_topo) * d_hours_day
3562                   ENDDO
3563                ENDDO
3564             ENDDO
3565
3566          ENDIF
3567
3568          IF ( sw_radiation .AND. sun_up )  THEN
3569             CALL rrtmg_sw( 1, nzt_rad      , rrtm_icld     , rrtm_iaer      ,&
3570             rrtm_play      , rrtm_plev     , rrtm_tlay     , rrtm_tlev      ,&
3571             rrtm_tsfc      , rrtm_h2ovmr   , rrtm_o3vmr    , rrtm_co2vmr    ,&
3572             rrtm_ch4vmr    , rrtm_n2ovmr   , rrtm_o2vmr    , rrtm_asdir     ,&
3573             rrtm_asdif     , rrtm_aldir    , rrtm_aldif    , zenith         ,&
3574             0.0_wp         , day_of_year   , solar_constant, rrtm_inflgsw   ,&
3575             rrtm_iceflgsw  , rrtm_liqflgsw , rrtm_cldfr    , rrtm_sw_taucld ,&
3576             rrtm_sw_ssacld , rrtm_sw_asmcld, rrtm_sw_fsfcld, rrtm_cicewp    ,&
3577             rrtm_cliqwp    , rrtm_reice    , rrtm_reliq    , rrtm_sw_tauaer ,&
3578             rrtm_sw_ssaaer , rrtm_sw_asmaer, rrtm_sw_ecaer , rrtm_swuflx    ,&
3579             rrtm_swdflx    , rrtm_swhr     , rrtm_swuflxc  , rrtm_swdflxc   ,&
3580             rrtm_swhrc     , rrtm_dirdflux , rrtm_difdflux )
3581 
3582!
3583!--          Save fluxes:
3584!--          - whole domain
3585             DO k = nzb, nzt+1
3586                rad_sw_in(k,:,:)  = rrtm_swdflx(0,k)
3587                rad_sw_out(k,:,:) = rrtm_swuflx(0,k)
3588             ENDDO
3589!--          - direct and diffuse SW at urban-surface-layer (required by RTM)
3590             rad_sw_in_dir(:,:) = rrtm_dirdflux(0,nzb)
3591             rad_sw_in_diff(:,:) = rrtm_difdflux(0,nzb)
3592
3593!
3594!--          Save heating rates (convert from K/d to K/s)
3595             DO k = nzb+1, nzt+1
3596                rad_sw_hr(k,:,:)     = rrtm_swhr(0,k)  * d_hours_day
3597                rad_sw_cs_hr(k,:,:)  = rrtm_swhrc(0,k) * d_hours_day
3598             ENDDO
3599!
3600!--       Solar radiation is zero during night
3601          ELSE
3602             rad_sw_in  = 0.0_wp
3603             rad_sw_out = 0.0_wp
3604             rad_sw_in_dir(:,:) = 0.0_wp
3605             rad_sw_in_diff(:,:) = 0.0_wp
3606          ENDIF
3607!
3608!--    RRTMG is called for each (j,i) grid point separately, starting at the
3609!--    highest topography level. Here no RTM is used since average_radiation is false
3610       ELSE
3611!
3612!--       Loop over all grid points
3613          DO i = nxl, nxr
3614             DO j = nys, nyn
3615
3616!
3617!--             Prepare profiles of temperature and H2O volume mixing ratio
3618                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
3619                   rrtm_tlev(0,nzb+1) = surf_lsm_h%pt_surface(m) * exner(nzb)
3620                ENDDO
3621                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
3622                   rrtm_tlev(0,nzb+1) = surf_usm_h%pt_surface(m) * exner(nzb)
3623                ENDDO
3624
3625
3626                IF ( bulk_cloud_model )  THEN
3627                   DO k = nzb+1, nzt+1
3628                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)                    &
3629                                        + lv_d_cp * ql(k,j,i)
3630                      rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * (q(k,j,i) - ql(k,j,i))
3631                   ENDDO
3632                ELSEIF ( cloud_droplets )  THEN
3633                   DO k = nzb+1, nzt+1
3634                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)                     &
3635                                        + lv_d_cp * ql(k,j,i)
3636                      rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * q(k,j,i) 
3637                   ENDDO
3638                ELSE
3639                   DO k = nzb+1, nzt+1
3640                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)
3641                   ENDDO
3642
3643                   IF ( humidity )  THEN
3644                      DO k = nzb+1, nzt+1
3645                         rrtm_h2ovmr(0,k) =  mol_mass_air_d_wv * q(k,j,i)
3646                      ENDDO   
3647                   ELSE
3648                      rrtm_h2ovmr(0,nzb+1:nzt+1) = 0.0_wp
3649                   ENDIF
3650                ENDIF
3651
3652!
3653!--             Avoid temperature/humidity jumps at the top of the LES domain by
3654!--             linear interpolation from nzt+2 to nzt+7
3655                DO k = nzt+2, nzt+7
3656                   rrtm_tlay(0,k) = rrtm_tlay(0,nzt+1)                         &
3657                                 + ( rrtm_tlay(0,nzt+8) - rrtm_tlay(0,nzt+1) ) &
3658                                 / ( rrtm_play(0,nzt+8) - rrtm_play(0,nzt+1) ) &
3659                                 * ( rrtm_play(0,k)     - rrtm_play(0,nzt+1) )
3660
3661                   rrtm_h2ovmr(0,k) = rrtm_h2ovmr(0,nzt+1)                     &
3662                              + ( rrtm_h2ovmr(0,nzt+8) - rrtm_h2ovmr(0,nzt+1) )&
3663                              / ( rrtm_play(0,nzt+8)   - rrtm_play(0,nzt+1)   )&
3664                              * ( rrtm_play(0,k)       - rrtm_play(0,nzt+1) )
3665
3666                ENDDO
3667
3668!--             Linear interpolate to zw grid
3669                DO k = nzb+2, nzt+8
3670                   rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k) -     &
3671                                      rrtm_tlay(0,k-1))                        &
3672                                      / ( rrtm_play(0,k) - rrtm_play(0,k-1) )  &
3673                                      * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
3674                ENDDO
3675
3676
3677!
3678!--             Calculate liquid water path and cloud fraction for each column.
3679!--             Note that LWP is required in g/m2 instead of kg/kg m.
3680                rrtm_cldfr  = 0.0_wp
3681                rrtm_reliq  = 0.0_wp
3682                rrtm_cliqwp = 0.0_wp
3683                rrtm_icld   = 0
3684
3685                IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
3686                   DO k = nzb+1, nzt+1
3687                      rrtm_cliqwp(0,k) =  ql(k,j,i) * 1000.0_wp *              &
3688                                          (rrtm_plev(0,k) - rrtm_plev(0,k+1))  &
3689                                          * 100.0_wp / g 
3690
3691                      IF ( rrtm_cliqwp(0,k) > 0.0_wp )  THEN
3692                         rrtm_cldfr(0,k) = 1.0_wp
3693                         IF ( rrtm_icld == 0 )  rrtm_icld = 1
3694
3695!
3696!--                      Calculate cloud droplet effective radius
3697                         IF ( bulk_cloud_model )  THEN
3698!
3699!--                         Calculete effective droplet radius. In case of using
3700!--                         cloud_scheme = 'morrison' and a non reasonable number
3701!--                         of cloud droplets the inital aerosol number 
3702!--                         concentration is considered.
3703                            IF ( microphysics_morrison )  THEN
3704                               IF ( nc(k,j,i) > 1.0E-20_wp )  THEN
3705                                  nc_rad = nc(k,j,i)
3706                               ELSE
3707                                  nc_rad = na_init
3708                               ENDIF
3709                            ELSE
3710                               nc_rad = nc_const
3711                            ENDIF 
3712
3713                            rrtm_reliq(0,k) = 1.0E6_wp * ( 3.0_wp * ql(k,j,i)     &
3714                                              * rho_surface                       &
3715                                              / ( 4.0_wp * pi * nc_rad * rho_l )  &
3716                                              )**0.33333333333333_wp              &
3717                                              * EXP( LOG( sigma_gc )**2 )
3718
3719                         ELSEIF ( cloud_droplets )  THEN
3720                            number_of_particles = prt_count(k,j,i)
3721
3722                            IF (number_of_particles <= 0)  CYCLE
3723                            particles => grid_particles(k,j,i)%particles(1:number_of_particles)
3724                            s_r2 = 0.0_wp
3725                            s_r3 = 0.0_wp
3726
3727                            DO  n = 1, number_of_particles
3728                               IF ( particles(n)%particle_mask )  THEN
3729                                  s_r2 = s_r2 + particles(n)%radius**2 *       &
3730                                         particles(n)%weight_factor
3731                                  s_r3 = s_r3 + particles(n)%radius**3 *       &
3732                                         particles(n)%weight_factor
3733                               ENDIF
3734                            ENDDO
3735
3736                            IF ( s_r2 > 0.0_wp )  rrtm_reliq(0,k) = s_r3 / s_r2
3737
3738                         ENDIF
3739
3740!
3741!--                      Limit effective radius
3742                         IF ( rrtm_reliq(0,k) > 0.0_wp )  THEN
3743                            rrtm_reliq(0,k) = MAX(rrtm_reliq(0,k),2.5_wp)
3744                            rrtm_reliq(0,k) = MIN(rrtm_reliq(0,k),60.0_wp)
3745                        ENDIF
3746                      ENDIF
3747                   ENDDO
3748                ENDIF
3749
3750!
3751!--             Write surface emissivity and surface temperature at current
3752!--             surface element on RRTMG-shaped array.
3753!--             Please note, as RRTMG is a single column model, surface attributes
3754!--             are only obtained from horizontally aligned surfaces (for
3755!--             simplicity). Taking surface attributes from horizontal and
3756!--             vertical walls would lead to multiple solutions. 
3757!--             Moreover, for natural- and urban-type surfaces, several surface
3758!--             classes can exist at a surface element next to each other.
3759!--             To obtain bulk parameters, apply a weighted average for these
3760!--             surfaces.
3761                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
3762                   rrtm_emis = surf_lsm_h%frac(ind_veg_wall,m)  *              &
3763                               surf_lsm_h%emissivity(ind_veg_wall,m)  +        &
3764                               surf_lsm_h%frac(ind_pav_green,m) *              &
3765                               surf_lsm_h%emissivity(ind_pav_green,m) +        & 
3766                               surf_lsm_h%frac(ind_wat_win,m)   *              &
3767                               surf_lsm_h%emissivity(ind_wat_win,m)
3768                   rrtm_tsfc = surf_lsm_h%pt_surface(m) * exner(nzb)
3769                ENDDO             
3770                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
3771                   rrtm_emis = surf_usm_h%frac(ind_veg_wall,m)  *              &
3772                               surf_usm_h%emissivity(ind_veg_wall,m)  +        &
3773                               surf_usm_h%frac(ind_pav_green,m) *              &
3774                               surf_usm_h%emissivity(ind_pav_green,m) +        & 
3775                               surf_usm_h%frac(ind_wat_win,m)   *              &
3776                               surf_usm_h%emissivity(ind_wat_win,m)
3777                   rrtm_tsfc = surf_usm_h%pt_surface(m) * exner(nzb)
3778                ENDDO
3779!
3780!--             Obtain topography top index (lower bound of RRTMG)
3781                k_topo = get_topography_top_index_ji( j, i, 's' )
3782
3783                IF ( lw_radiation )  THEN
3784!
3785!--                Due to technical reasons, copy optical depth to dummy arguments
3786!--                which are allocated on the exact size as the rrtmg_lw is called.
3787!--                As one dimesion is allocated with zero size, compiler complains
3788!--                that rank of the array does not match that of the
3789!--                assumed-shaped arguments in the RRTMG library. In order to
3790!--                avoid this, write to dummy arguments and give pass the entire
3791!--                dummy array. Seems to be the only existing work-around. 
3792                   ALLOCATE( rrtm_lw_taucld_dum(1:nbndlw+1,0:0,k_topo+1:nzt_rad+1) )
3793                   ALLOCATE( rrtm_lw_tauaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndlw+1) )
3794
3795                   rrtm_lw_taucld_dum =                                        &
3796                               rrtm_lw_taucld(1:nbndlw+1,0:0,k_topo+1:nzt_rad+1)
3797                   rrtm_lw_tauaer_dum =                                        &
3798                               rrtm_lw_tauaer(0:0,k_topo+1:nzt_rad+1,1:nbndlw+1)
3799
3800                   CALL rrtmg_lw( 1,                                           &                                       
3801                                  nzt_rad-k_topo,                              &
3802                                  rrtm_icld,                                   &
3803                                  rrtm_idrv,                                   &
3804                                  rrtm_play(:,k_topo+1:nzt_rad+1),             &
3805                                  rrtm_plev(:,k_topo+1:nzt_rad+2),             &
3806                                  rrtm_tlay(:,k_topo+1:nzt_rad+1),             &
3807                                  rrtm_tlev(:,k_topo+1:nzt_rad+2),             &
3808                                  rrtm_tsfc,                                   &
3809                                  rrtm_h2ovmr(:,k_topo+1:nzt_rad+1),           &
3810                                  rrtm_o3vmr(:,k_topo+1:nzt_rad+1),            &
3811                                  rrtm_co2vmr(:,k_topo+1:nzt_rad+1),           &
3812                                  rrtm_ch4vmr(:,k_topo+1:nzt_rad+1),           &
3813                                  rrtm_n2ovmr(:,k_topo+1:nzt_rad+1),           &
3814                                  rrtm_o2vmr(:,k_topo+1:nzt_rad+1),            &
3815                                  rrtm_cfc11vmr(:,k_topo+1:nzt_rad+1),         &
3816                                  rrtm_cfc12vmr(:,k_topo+1:nzt_rad+1),         &
3817                                  rrtm_cfc22vmr(:,k_topo+1:nzt_rad+1),         &
3818                                  rrtm_ccl4vmr(:,k_topo+1:nzt_rad+1),          &
3819                                  rrtm_emis,                                   &
3820                                  rrtm_inflglw,                                &
3821                                  rrtm_iceflglw,                               &
3822                                  rrtm_liqflglw,                               &
3823                                  rrtm_cldfr(:,k_topo+1:nzt_rad+1),            &
3824                                  rrtm_lw_taucld_dum,                          &
3825                                  rrtm_cicewp(:,k_topo+1:nzt_rad+1),           &
3826                                  rrtm_cliqwp(:,k_topo+1:nzt_rad+1),           &
3827                                  rrtm_reice(:,k_topo+1:nzt_rad+1),            & 
3828                                  rrtm_reliq(:,k_topo+1:nzt_rad+1),            &
3829                                  rrtm_lw_tauaer_dum,                          &
3830                                  rrtm_lwuflx(:,k_topo:nzt_rad+1),             &
3831                                  rrtm_lwdflx(:,k_topo:nzt_rad+1),             &
3832                                  rrtm_lwhr(:,k_topo+1:nzt_rad+1),             &
3833                                  rrtm_lwuflxc(:,k_topo:nzt_rad+1),            &
3834                                  rrtm_lwdflxc(:,k_topo:nzt_rad+1),            &
3835                                  rrtm_lwhrc(:,k_topo+1:nzt_rad+1),            &
3836                                  rrtm_lwuflx_dt(:,k_topo:nzt_rad+1),          &
3837                                  rrtm_lwuflxc_dt(:,k_topo:nzt_rad+1) )
3838
3839                   DEALLOCATE ( rrtm_lw_taucld_dum )
3840                   DEALLOCATE ( rrtm_lw_tauaer_dum )
3841!
3842!--                Save fluxes
3843                   DO k = k_topo, nzt+1
3844                      rad_lw_in(k,j,i)  = rrtm_lwdflx(0,k)
3845                      rad_lw_out(k,j,i) = rrtm_lwuflx(0,k)
3846                   ENDDO
3847
3848!
3849!--                Save heating rates (convert from K/d to K/h)
3850                   DO k = k_topo+1, nzt+1
3851                      rad_lw_hr(k,j,i)     = rrtm_lwhr(0,k-k_topo)  * d_hours_day
3852                      rad_lw_cs_hr(k,j,i)  = rrtm_lwhrc(0,k-k_topo) * d_hours_day
3853                   ENDDO
3854
3855!
3856!--                Save surface radiative fluxes and change in LW heating rate
3857!--                onto respective surface elements
3858!--                Horizontal surfaces
3859                   DO  m = surf_lsm_h%start_index(j,i),                        &
3860                           surf_lsm_h%end_index(j,i)
3861                      surf_lsm_h%rad_lw_in(m)           = rrtm_lwdflx(0,k_topo)
3862                      surf_lsm_h%rad_lw_out(m)          = rrtm_lwuflx(0,k_topo)
3863                      surf_lsm_h%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k_topo)
3864                   ENDDO             
3865                   DO  m = surf_usm_h%start_index(j,i),                        &
3866                           surf_usm_h%end_index(j,i)
3867                      surf_usm_h%rad_lw_in(m)           = rrtm_lwdflx(0,k_topo)
3868                      surf_usm_h%rad_lw_out(m)          = rrtm_lwuflx(0,k_topo)
3869                      surf_usm_h%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k_topo)
3870                   ENDDO 
3871!
3872!--                Vertical surfaces. Fluxes are obtain at vertical level of the
3873!--                respective surface element
3874                   DO  l = 0, 3
3875                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
3876                              surf_lsm_v(l)%end_index(j,i)
3877                         k                                    = surf_lsm_v(l)%k(m)
3878                         surf_lsm_v(l)%rad_lw_in(m)           = rrtm_lwdflx(0,k)
3879                         surf_lsm_v(l)%rad_lw_out(m)          = rrtm_lwuflx(0,k)
3880                         surf_lsm_v(l)%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k)
3881                      ENDDO             
3882                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
3883                              surf_usm_v(l)%end_index(j,i)
3884                         k                                    = surf_usm_v(l)%k(m)
3885                         surf_usm_v(l)%rad_lw_in(m)           = rrtm_lwdflx(0,k)
3886                         surf_usm_v(l)%rad_lw_out(m)          = rrtm_lwuflx(0,k)
3887                         surf_usm_v(l)%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k)
3888                      ENDDO 
3889                   ENDDO
3890
3891                ENDIF
3892
3893                IF ( sw_radiation .AND. sun_up )  THEN
3894!
3895!--                Get albedo for direct/diffusive long/shortwave radiation at
3896!--                current (y,x)-location from surface variables.
3897!--                Only obtain it from horizontal surfaces, as RRTMG is a single
3898!--                column model
3899!--                (Please note, only one loop will entered, controlled by
3900!--                start-end index.)
3901                   DO  m = surf_lsm_h%start_index(j,i),                        &
3902                           surf_lsm_h%end_index(j,i)
3903                      rrtm_asdir(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3904                                            surf_lsm_h%rrtm_asdir(:,m) )
3905                      rrtm_asdif(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3906                                            surf_lsm_h%rrtm_asdif(:,m) )
3907                      rrtm_aldir(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3908                                            surf_lsm_h%rrtm_aldir(:,m) )
3909                      rrtm_aldif(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3910                                            surf_lsm_h%rrtm_aldif(:,m) )
3911                   ENDDO             
3912                   DO  m = surf_usm_h%start_index(j,i),                        &
3913                           surf_usm_h%end_index(j,i)
3914                      rrtm_asdir(1)  = SUM( surf_usm_h%frac(:,m) *             &
3915                                            surf_usm_h%rrtm_asdir(:,m) )
3916                      rrtm_asdif(1)  = SUM( surf_usm_h%frac(:,m) *             &
3917                                            surf_usm_h%rrtm_asdif(:,m) )
3918                      rrtm_aldir(1)  = SUM( surf_usm_h%frac(:,m) *             &
3919                                            surf_usm_h%rrtm_aldir(:,m) )
3920                      rrtm_aldif(1)  = SUM( surf_usm_h%frac(:,m) *             &
3921                                            surf_usm_h%rrtm_aldif(:,m) )
3922                   ENDDO
3923!
3924!--                Due to technical reasons, copy optical depths and other
3925!--                to dummy arguments which are allocated on the exact size as the
3926!--                rrtmg_sw is called.
3927!--                As one dimesion is allocated with zero size, compiler complains
3928!--                that rank of the array does not match that of the
3929!--                assumed-shaped arguments in the RRTMG library. In order to
3930!--                avoid this, write to dummy arguments and give pass the entire
3931!--                dummy array. Seems to be the only existing work-around. 
3932                   ALLOCATE( rrtm_sw_taucld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3933                   ALLOCATE( rrtm_sw_ssacld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3934                   ALLOCATE( rrtm_sw_asmcld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3935                   ALLOCATE( rrtm_sw_fsfcld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3936                   ALLOCATE( rrtm_sw_tauaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3937                   ALLOCATE( rrtm_sw_ssaaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3938                   ALLOCATE( rrtm_sw_asmaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3939                   ALLOCATE( rrtm_sw_ecaer_dum(0:0,k_topo+1:nzt_rad+1,1:naerec+1)  )
3940     
3941                   rrtm_sw_taucld_dum = rrtm_sw_taucld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3942                   rrtm_sw_ssacld_dum = rrtm_sw_ssacld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3943                   rrtm_sw_asmcld_dum = rrtm_sw_asmcld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3944                   rrtm_sw_fsfcld_dum = rrtm_sw_fsfcld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3945                   rrtm_sw_tauaer_dum = rrtm_sw_tauaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3946                   rrtm_sw_ssaaer_dum = rrtm_sw_ssaaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3947                   rrtm_sw_asmaer_dum = rrtm_sw_asmaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3948                   rrtm_sw_ecaer_dum  = rrtm_sw_ecaer(0:0,k_topo+1:nzt_rad+1,1:naerec+1)
3949
3950                   CALL rrtmg_sw( 1,                                           &
3951                                  nzt_rad-k_topo,                              &
3952                                  rrtm_icld,                                   &
3953                                  rrtm_iaer,                                   &
3954                                  rrtm_play(:,k_topo+1:nzt_rad+1),             &
3955                                  rrtm_plev(:,k_topo+1:nzt_rad+2),             &
3956                                  rrtm_tlay(:,k_topo+1:nzt_rad+1),             &
3957                                  rrtm_tlev(:,k_topo+1:nzt_rad+2),             &
3958                                  rrtm_tsfc,                                   &
3959                                  rrtm_h2ovmr(:,k_topo+1:nzt_rad+1),           &                               
3960                                  rrtm_o3vmr(:,k_topo+1:nzt_rad+1),            &       
3961                                  rrtm_co2vmr(:,k_topo+1:nzt_rad+1),           &
3962                                  rrtm_ch4vmr(:,k_topo+1:nzt_rad+1),           &
3963                                  rrtm_n2ovmr(:,k_topo+1:nzt_rad+1),           &
3964                                  rrtm_o2vmr(:,k_topo+1:nzt_rad+1),            &
3965                                  rrtm_asdir,                                  & 
3966                                  rrtm_asdif,                                  &
3967                                  rrtm_aldir,                                  &
3968                                  rrtm_aldif,                                  &
3969                                  zenith,                                      &
3970                                  0.0_wp,                                      &
3971                                  day_of_year,                                 &
3972                                  solar_constant,                              &
3973                                  rrtm_inflgsw,                                &
3974                                  rrtm_iceflgsw,                               &
3975                                  rrtm_liqflgsw,                               &
3976                                  rrtm_cldfr(:,k_topo+1:nzt_rad+1),            &
3977                                  rrtm_sw_taucld_dum,                          &
3978                                  rrtm_sw_ssacld_dum,                          &
3979                                  rrtm_sw_asmcld_dum,                          &
3980                                  rrtm_sw_fsfcld_dum,                          &
3981                                  rrtm_cicewp(:,k_topo+1:nzt_rad+1),           &
3982                                  rrtm_cliqwp(:,k_topo+1:nzt_rad+1),           &
3983                                  rrtm_reice(:,k_topo+1:nzt_rad+1),            &
3984                                  rrtm_reliq(:,k_topo+1:nzt_rad+1),            &
3985                                  rrtm_sw_tauaer_dum,                          &
3986                                  rrtm_sw_ssaaer_dum,                          &
3987                                  rrtm_sw_asmaer_dum,                          &
3988                                  rrtm_sw_ecaer_dum,                           &
3989                                  rrtm_swuflx(:,k_topo:nzt_rad+1),             & 
3990                                  rrtm_swdflx(:,k_topo:nzt_rad+1),             & 
3991                                  rrtm_swhr(:,k_topo+1:nzt_rad+1),             & 
3992                                  rrtm_swuflxc(:,k_topo:nzt_rad+1),            & 
3993                                  rrtm_swdflxc(:,k_topo:nzt_rad+1),            &
3994                                  rrtm_swhrc(:,k_topo+1:nzt_rad+1),            &
3995                                  rrtm_dirdflux(:,k_topo:nzt_rad+1),           &
3996                                  rrtm_difdflux(:,k_topo:nzt_rad+1) )
3997
3998                   DEALLOCATE( rrtm_sw_taucld_dum )
3999                   DEALLOCATE( rrtm_sw_ssacld_dum )
4000                   DEALLOCATE( rrtm_sw_asmcld_dum )
4001                   DEALLOCATE( rrtm_sw_fsfcld_dum )
4002                   DEALLOCATE( rrtm_sw_tauaer_dum )
4003                   DEALLOCATE( rrtm_sw_ssaaer_dum )
4004                   DEALLOCATE( rrtm_sw_asmaer_dum )
4005                   DEALLOCATE( rrtm_sw_ecaer_dum )
4006!
4007!--                Save fluxes
4008                   DO k = nzb, nzt+1
4009                      rad_sw_in(k,j,i)  = rrtm_swdflx(0,k)
4010                      rad_sw_out(k,j,i) = rrtm_swuflx(0,k)
4011                   ENDDO
4012!
4013!--                Save heating rates (convert from K/d to K/s)
4014                   DO k = nzb+1, nzt+1
4015                      rad_sw_hr(k,j,i)     = rrtm_swhr(0,k)  * d_hours_day
4016                      rad_sw_cs_hr(k,j,i)  = rrtm_swhrc(0,k) * d_hours_day
4017                   ENDDO
4018
4019!
4020!--                Save surface radiative fluxes onto respective surface elements
4021!--                Horizontal surfaces
4022                   DO  m = surf_lsm_h%start_index(j,i),                        &
4023                           surf_lsm_h%end_index(j,i)
4024                      surf_lsm_h%rad_sw_in(m)     = rrtm_swdflx(0,k_topo)
4025                      surf_lsm_h%rad_sw_out(m)    = rrtm_swuflx(0,k_topo)
4026                   ENDDO             
4027                   DO  m = surf_usm_h%start_index(j,i),                        &
4028                           surf_usm_h%end_index(j,i)
4029                      surf_usm_h%rad_sw_in(m)     = rrtm_swdflx(0,k_topo)
4030                      surf_usm_h%rad_sw_out(m)    = rrtm_swuflx(0,k_topo)
4031                   ENDDO 
4032!
4033!--                Vertical surfaces. Fluxes are obtain at respective vertical
4034!--                level of the surface element
4035                   DO  l = 0, 3
4036                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
4037                              surf_lsm_v(l)%end_index(j,i)
4038                         k                           = surf_lsm_v(l)%k(m)
4039                         surf_lsm_v(l)%rad_sw_in(m)  = rrtm_swdflx(0,k)
4040                         surf_lsm_v(l)%rad_sw_out(m) = rrtm_swuflx(0,k)
4041                      ENDDO             
4042                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
4043                              surf_usm_v(l)%end_index(j,i)
4044                         k                           = surf_usm_v(l)%k(m)
4045                         surf_usm_v(l)%rad_sw_in(m)  = rrtm_swdflx(0,k)
4046                         surf_usm_v(l)%rad_sw_out(m) = rrtm_swuflx(0,k)
4047                      ENDDO 
4048                   ENDDO
4049!
4050!--             Solar radiation is zero during night
4051                ELSE
4052                   rad_sw_in  = 0.0_wp
4053                   rad_sw_out = 0.0_wp
4054!--             !!!!!!!! ATTENSION !!!!!!!!!!!!!!!
4055!--             Surface radiative fluxes should be also set to zero here                 
4056!--                Save surface radiative fluxes onto respective surface elements
4057!--                Horizontal surfaces
4058                   DO  m = surf_lsm_h%start_index(j,i),                        &
4059                           surf_lsm_h%end_index(j,i)
4060                      surf_lsm_h%rad_sw_in(m)     = 0.0_wp
4061                      surf_lsm_h%rad_sw_out(m)    = 0.0_wp
4062                   ENDDO             
4063                   DO  m = surf_usm_h%start_index(j,i),                        &
4064                           surf_usm_h%end_index(j,i)
4065                      surf_usm_h%rad_sw_in(m)     = 0.0_wp
4066                      surf_usm_h%rad_sw_out(m)    = 0.0_wp
4067                   ENDDO 
4068!
4069!--                Vertical surfaces. Fluxes are obtain at respective vertical
4070!--                level of the surface element
4071                   DO  l = 0, 3
4072                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
4073                              surf_lsm_v(l)%end_index(j,i)
4074                         k                           = surf_lsm_v(l)%k(m)
4075                         surf_lsm_v(l)%rad_sw_in(m)  = 0.0_wp
4076                         surf_lsm_v(l)%rad_sw_out(m) = 0.0_wp
4077                      ENDDO             
4078                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
4079                              surf_usm_v(l)%end_index(j,i)
4080                         k                           = surf_usm_v(l)%k(m)
4081                         surf_usm_v(l)%rad_sw_in(m)  = 0.0_wp
4082                         surf_usm_v(l)%rad_sw_out(m) = 0.0_wp
4083                      ENDDO 
4084                   ENDDO
4085                ENDIF
4086
4087             ENDDO
4088          ENDDO
4089
4090       ENDIF
4091!
4092!--    Finally, calculate surface net radiation for surface elements.
4093       IF (  .NOT.  radiation_interactions  ) THEN
4094!--       First, for horizontal surfaces   
4095          DO  m = 1, surf_lsm_h%ns
4096             surf_lsm_h%rad_net(m) = surf_lsm_h%rad_sw_in(m)                   &
4097                                   - surf_lsm_h%rad_sw_out(m)                  &
4098                                   + surf_lsm_h%rad_lw_in(m)                   &
4099                                   - surf_lsm_h%rad_lw_out(m)
4100          ENDDO
4101          DO  m = 1, surf_usm_h%ns
4102             surf_usm_h%rad_net(m) = surf_usm_h%rad_sw_in(m)                   &
4103                                   - surf_usm_h%rad_sw_out(m)                  &
4104                                   + surf_usm_h%rad_lw_in(m)                   &
4105                                   - surf_usm_h%rad_lw_out(m)
4106          ENDDO
4107!
4108!--       Vertical surfaces.
4109!--       Todo: weight with azimuth and zenith angle according to their orientation!
4110          DO  l = 0, 3     
4111             DO  m = 1, surf_lsm_v(l)%ns
4112                surf_lsm_v(l)%rad_net(m) = surf_lsm_v(l)%rad_sw_in(m)          &
4113                                         - surf_lsm_v(l)%rad_sw_out(m)         &
4114                                         + surf_lsm_v(l)%rad_lw_in(m)          &
4115                                         - surf_lsm_v(l)%rad_lw_out(m)
4116             ENDDO
4117             DO  m = 1, surf_usm_v(l)%ns
4118                surf_usm_v(l)%rad_net(m) = surf_usm_v(l)%rad_sw_in(m)          &
4119                                         - surf_usm_v(l)%rad_sw_out(m)         &
4120                                         + surf_usm_v(l)%rad_lw_in(m)          &
4121                                         - surf_usm_v(l)%rad_lw_out(m)
4122             ENDDO
4123          ENDDO
4124       ENDIF
4125
4126
4127       CALL exchange_horiz( rad_lw_in,  nbgp )
4128       CALL exchange_horiz( rad_lw_out, nbgp )
4129       CALL exchange_horiz( rad_lw_hr,    nbgp )
4130       CALL exchange_horiz( rad_lw_cs_hr, nbgp )
4131
4132       CALL exchange_horiz( rad_sw_in,  nbgp )
4133       CALL exchange_horiz( rad_sw_out, nbgp ) 
4134       CALL exchange_horiz( rad_sw_hr,    nbgp )
4135       CALL exchange_horiz( rad_sw_cs_hr, nbgp )
4136
4137#endif
4138
4139    END SUBROUTINE radiation_rrtmg
4140
4141
4142!------------------------------------------------------------------------------!
4143! Description:
4144! ------------
4145!> Calculate the cosine of the zenith angle (variable is called zenith)
4146!------------------------------------------------------------------------------!
4147    SUBROUTINE calc_zenith
4148
4149       IMPLICIT NONE
4150
4151       REAL(wp) ::  declination,  & !< solar declination angle
4152                    hour_angle      !< solar hour angle
4153!
4154!--    Calculate current day and time based on the initial values and simulation
4155!--    time
4156       CALL calc_date_and_time
4157
4158!
4159!--    Calculate solar declination and hour angle   
4160       declination = ASIN( decl_1 * SIN(decl_2 * REAL(day_of_year, KIND=wp) - decl_3) )
4161       hour_angle  = 2.0_wp * pi * (time_utc / 86400.0_wp) + lon - pi
4162
4163!
4164!--    Calculate cosine of solar zenith angle
4165       zenith(0) = SIN(lat) * SIN(declination) + COS(lat) * COS(declination)   &
4166                                            * COS(hour_angle)
4167       zenith(0) = MAX(0.0_wp,zenith(0))
4168
4169!
4170!--    Calculate solar directional vector
4171       IF ( sun_direction )  THEN
4172
4173!
4174!--       Direction in longitudes equals to sin(solar_azimuth) * sin(zenith)
4175          sun_dir_lon(0) = -SIN(hour_angle) * COS(declination)
4176
4177!
4178!--       Direction in latitues equals to cos(solar_azimuth) * sin(zenith)
4179          sun_dir_lat(0) = SIN(declination) * COS(lat) - COS(hour_angle) &
4180                              * COS(declination) * SIN(lat)
4181       ENDIF
4182
4183!
4184!--    Check if the sun is up (otheriwse shortwave calculations can be skipped)
4185       IF ( zenith(0) > 0.0_wp )  THEN
4186          sun_up = .TRUE.
4187       ELSE
4188          sun_up = .FALSE.
4189       END IF
4190
4191    END SUBROUTINE calc_zenith
4192
4193#if defined ( __rrtmg ) && defined ( __netcdf )
4194!------------------------------------------------------------------------------!
4195! Description:
4196! ------------
4197!> Calculates surface albedo components based on Briegleb (1992) and
4198!> Briegleb et al. (1986)
4199!------------------------------------------------------------------------------!
4200    SUBROUTINE calc_albedo( surf )
4201
4202        IMPLICIT NONE
4203
4204        INTEGER(iwp)    ::  ind_type !< running index surface tiles
4205        INTEGER(iwp)    ::  m        !< running index surface elements
4206
4207        TYPE(surf_type) ::  surf !< treated surfaces
4208
4209        IF ( sun_up  .AND.  .NOT. average_radiation )  THEN
4210
4211           DO  m = 1, surf%ns
4212!
4213!--           Loop over surface elements
4214              DO  ind_type = 0, SIZE( surf%albedo_type, 1 ) - 1
4215           
4216!
4217!--              Ocean
4218                 IF ( surf%albedo_type(ind_type,m) == 1 )  THEN
4219                    surf%rrtm_aldir(ind_type,m) = 0.026_wp /                    &
4220                                                ( zenith(0)**1.7_wp + 0.065_wp )&
4221                                     + 0.15_wp * ( zenith(0) - 0.1_wp )         &
4222                                               * ( zenith(0) - 0.5_wp )         &
4223                                               * ( zenith(0) - 1.0_wp )
4224                    surf%rrtm_asdir(ind_type,m) = surf%rrtm_aldir(ind_type,m)
4225!
4226!--              Snow
4227                 ELSEIF ( surf%albedo_type(ind_type,m) == 16 )  THEN
4228                    IF ( zenith(0) < 0.5_wp )  THEN
4229                       surf%rrtm_aldir(ind_type,m) =                           &
4230                                 0.5_wp * ( 1.0_wp - surf%aldif(ind_type,m) )  &
4231                                        * ( 3.0_wp / ( 1.0_wp + 4.0_wp         &
4232                                        * zenith(0) ) ) - 1.0_wp
4233                       surf%rrtm_asdir(ind_type,m) =                           &
4234                                 0.5_wp * ( 1.0_wp - surf%asdif(ind_type,m) )  &
4235                                        * ( 3.0_wp / ( 1.0_wp + 4.0_wp         &
4236                                        * zenith(0) ) ) - 1.0_wp
4237
4238                       surf%rrtm_aldir(ind_type,m) =                           &
4239                                       MIN(0.98_wp, surf%rrtm_aldir(ind_type,m))
4240                       surf%rrtm_asdir(ind_type,m) =                           &
4241                                       MIN(0.98_wp, surf%rrtm_asdir(ind_type,m))
4242                    ELSE
4243                       surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4244                       surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4245                    ENDIF
4246!
4247!--              Sea ice
4248                 ELSEIF ( surf%albedo_type(ind_type,m) == 15 )  THEN
4249                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4250                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4251
4252!
4253!--              Asphalt
4254                 ELSEIF ( surf%albedo_type(ind_type,m) == 17 )  THEN
4255                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4256                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4257
4258
4259!
4260!--              Bare soil
4261                 ELSEIF ( surf%albedo_type(ind_type,m) == 18 )  THEN
4262                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4263                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4264
4265!
4266!--              Land surfaces
4267                 ELSE
4268                    SELECT CASE ( surf%albedo_type(ind_type,m) )
4269
4270!
4271!--                    Surface types with strong zenith dependence
4272                       CASE ( 1, 2, 3, 4, 11, 12, 13 )
4273                          surf%rrtm_aldir(ind_type,m) =                        &
4274                                surf%aldif(ind_type,m) * 1.4_wp /              &
4275                                           ( 1.0_wp + 0.8_wp * zenith(0) )
4276                          surf%rrtm_asdir(ind_type,m) =                        &
4277                                surf%asdif(ind_type,m) * 1.4_wp /              &
4278                                           ( 1.0_wp + 0.8_wp * zenith(0) )
4279!
4280!--                    Surface types with weak zenith dependence
4281                       CASE ( 5, 6, 7, 8, 9, 10, 14 )
4282                          surf%rrtm_aldir(ind_type,m) =                        &
4283                                surf%aldif(ind_type,m) * 1.1_wp /              &
4284                                           ( 1.0_wp + 0.2_wp * zenith(0) )
4285                          surf%rrtm_asdir(ind_type,m) =                        &
4286                                surf%asdif(ind_type,m) * 1.1_wp /              &
4287                                           ( 1.0_wp + 0.2_wp * zenith(0) )
4288
4289                       CASE DEFAULT
4290
4291                    END SELECT
4292                 ENDIF
4293!
4294!--              Diffusive albedo is taken from Table 2
4295                 surf%rrtm_aldif(ind_type,m) = surf%aldif(ind_type,m)
4296                 surf%rrtm_asdif(ind_type,m) = surf%asdif(ind_type,m)
4297              ENDDO
4298           ENDDO
4299!
4300!--     Set albedo in case of average radiation
4301        ELSEIF ( sun_up  .AND.  average_radiation )  THEN
4302           surf%rrtm_asdir = albedo_urb
4303           surf%rrtm_asdif = albedo_urb
4304           surf%rrtm_aldir = albedo_urb
4305           surf%rrtm_aldif = albedo_urb 
4306!
4307!--     Darkness
4308        ELSE
4309           surf%rrtm_aldir = 0.0_wp
4310           surf%rrtm_asdir = 0.0_wp
4311           surf%rrtm_aldif = 0.0_wp
4312           surf%rrtm_asdif = 0.0_wp
4313        ENDIF
4314
4315    END SUBROUTINE calc_albedo
4316
4317!------------------------------------------------------------------------------!
4318! Description:
4319! ------------
4320!> Read sounding data (pressure and temperature) from RADIATION_DATA.
4321!------------------------------------------------------------------------------!
4322    SUBROUTINE read_sounding_data
4323
4324       IMPLICIT NONE
4325
4326       INTEGER(iwp) :: id,           & !< NetCDF id of input file
4327                       id_dim_zrad,  & !< pressure level id in the NetCDF file
4328                       id_var,       & !< NetCDF variable id
4329                       k,            & !< loop index
4330                       nz_snd,       & !< number of vertical levels in the sounding data
4331                       nz_snd_start, & !< start vertical index for sounding data to be used
4332                       nz_snd_end      !< end vertical index for souding data to be used
4333
4334       REAL(wp) :: t_surface           !< actual surface temperature
4335
4336       REAL(wp), DIMENSION(:), ALLOCATABLE ::  hyp_snd_tmp, & !< temporary hydrostatic pressure profile (sounding)
4337                                               t_snd_tmp      !< temporary temperature profile (sounding)
4338
4339!
4340!--    In case of updates, deallocate arrays first (sufficient to check one
4341!--    array as the others are automatically allocated). This is required
4342!--    because nzt_rad might change during the update
4343       IF ( ALLOCATED ( hyp_snd ) )  THEN
4344          DEALLOCATE( hyp_snd )
4345          DEALLOCATE( t_snd )
4346          DEALLOCATE ( rrtm_play )
4347          DEALLOCATE ( rrtm_plev )
4348          DEALLOCATE ( rrtm_tlay )
4349          DEALLOCATE ( rrtm_tlev )
4350
4351          DEALLOCATE ( rrtm_cicewp )
4352          DEALLOCATE ( rrtm_cldfr )
4353          DEALLOCATE ( rrtm_cliqwp )
4354          DEALLOCATE ( rrtm_reice )
4355          DEALLOCATE ( rrtm_reliq )
4356          DEALLOCATE ( rrtm_lw_taucld )
4357          DEALLOCATE ( rrtm_lw_tauaer )
4358
4359          DEALLOCATE ( rrtm_lwdflx  )
4360          DEALLOCATE ( rrtm_lwdflxc )
4361          DEALLOCATE ( rrtm_lwuflx  )
4362          DEALLOCATE ( rrtm_lwuflxc )
4363          DEALLOCATE ( rrtm_lwuflx_dt )
4364          DEALLOCATE ( rrtm_lwuflxc_dt )
4365          DEALLOCATE ( rrtm_lwhr  )
4366          DEALLOCATE ( rrtm_lwhrc )
4367
4368          DEALLOCATE ( rrtm_sw_taucld )
4369          DEALLOCATE ( rrtm_sw_ssacld )
4370          DEALLOCATE ( rrtm_sw_asmcld )
4371          DEALLOCATE ( rrtm_sw_fsfcld )
4372          DEALLOCATE ( rrtm_sw_tauaer )
4373          DEALLOCATE ( rrtm_sw_ssaaer )
4374          DEALLOCATE ( rrtm_sw_asmaer ) 
4375          DEALLOCATE ( rrtm_sw_ecaer )   
4376 
4377          DEALLOCATE ( rrtm_swdflx  )
4378          DEALLOCATE ( rrtm_swdflxc )
4379          DEALLOCATE ( rrtm_swuflx  )
4380          DEALLOCATE ( rrtm_swuflxc )
4381          DEALLOCATE ( rrtm_swhr  )
4382          DEALLOCATE ( rrtm_swhrc )
4383          DEALLOCATE ( rrtm_dirdflux )
4384          DEALLOCATE ( rrtm_difdflux )
4385
4386       ENDIF
4387
4388!
4389!--    Open file for reading
4390       nc_stat = NF90_OPEN( rrtm_input_file, NF90_NOWRITE, id )
4391       CALL netcdf_handle_error_rad( 'read_sounding_data', 549 )
4392
4393!
4394!--    Inquire dimension of z axis and save in nz_snd
4395       nc_stat = NF90_INQ_DIMID( id, "Pressure", id_dim_zrad )
4396       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim_zrad, len = nz_snd )
4397       CALL netcdf_handle_error_rad( 'read_sounding_data', 551 )
4398
4399!
4400! !--    Allocate temporary array for storing pressure data
4401       ALLOCATE( hyp_snd_tmp(1:nz_snd) )
4402       hyp_snd_tmp = 0.0_wp
4403
4404
4405!--    Read pressure from file
4406       nc_stat = NF90_INQ_VARID( id, "Pressure", id_var )
4407       nc_stat = NF90_GET_VAR( id, id_var, hyp_snd_tmp(:), start = (/1/),      &
4408                               count = (/nz_snd/) )
4409       CALL netcdf_handle_error_rad( 'read_sounding_data', 552 )
4410
4411!
4412!--    Allocate temporary array for storing temperature data
4413       ALLOCATE( t_snd_tmp(1:nz_snd) )
4414       t_snd_tmp = 0.0_wp
4415
4416!
4417!--    Read temperature from file
4418       nc_stat = NF90_INQ_VARID( id, "ReferenceTemperature", id_var )
4419       nc_stat = NF90_GET_VAR( id, id_var, t_snd_tmp(:), start = (/1/),        &
4420                               count = (/nz_snd/) )
4421       CALL netcdf_handle_error_rad( 'read_sounding_data', 553 )
4422
4423!
4424!--    Calculate start of sounding data
4425       nz_snd_start = nz_snd + 1
4426       nz_snd_end   = nz_snd + 1
4427
4428!
4429!--    Start filling vertical dimension at 10hPa above the model domain (hyp is
4430!--    in Pa, hyp_snd in hPa).
4431       DO  k = 1, nz_snd
4432          IF ( hyp_snd_tmp(k) < ( hyp(nzt+1) - 1000.0_wp) * 0.01_wp )  THEN
4433             nz_snd_start = k
4434             EXIT
4435          END IF
4436       END DO
4437
4438       IF ( nz_snd_start <= nz_snd )  THEN
4439          nz_snd_end = nz_snd
4440       END IF
4441
4442
4443!
4444!--    Calculate of total grid points for RRTMG calculations
4445       nzt_rad = nzt + nz_snd_end - nz_snd_start + 1
4446
4447!
4448!--    Save data above LES domain in hyp_snd, t_snd
4449       ALLOCATE( hyp_snd(nzb+1:nzt_rad) )
4450       ALLOCATE( t_snd(nzb+1:nzt_rad)   )
4451       hyp_snd = 0.0_wp
4452       t_snd = 0.0_wp
4453
4454       hyp_snd(nzt+2:nzt_rad) = hyp_snd_tmp(nz_snd_start+1:nz_snd_end)
4455       t_snd(nzt+2:nzt_rad)   = t_snd_tmp(nz_snd_start+1:nz_snd_end)
4456
4457       nc_stat = NF90_CLOSE( id )
4458
4459!
4460!--    Calculate pressure levels on zu and zw grid. Sounding data is added at
4461!--    top of the LES domain. This routine does not consider horizontal or
4462!--    vertical variability of pressure and temperature
4463       ALLOCATE ( rrtm_play(0:0,nzb+1:nzt_rad+1)   )
4464       ALLOCATE ( rrtm_plev(0:0,nzb+1:nzt_rad+2)   )
4465
4466       t_surface = pt_surface * exner(nzb)
4467       DO k = nzb+1, nzt+1
4468          rrtm_play(0,k) = hyp(k) * 0.01_wp
4469          rrtm_plev(0,k) = barometric_formula(zw(k-1),                         &
4470                              pt_surface * exner(nzb), &
4471                              surface_pressure )
4472       ENDDO
4473
4474       DO k = nzt+2, nzt_rad
4475          rrtm_play(0,k) = hyp_snd(k)
4476          rrtm_plev(0,k) = 0.5_wp * ( rrtm_play(0,k) + rrtm_play(0,k-1) )
4477       ENDDO
4478       rrtm_plev(0,nzt_rad+1) = MAX( 0.5 * hyp_snd(nzt_rad),                   &
4479                                   1.5 * hyp_snd(nzt_rad)                      &
4480                                 - 0.5 * hyp_snd(nzt_rad-1) )
4481       rrtm_plev(0,nzt_rad+2)  = MIN( 1.0E-4_wp,                               &
4482                                      0.25_wp * rrtm_plev(0,nzt_rad+1) )
4483
4484       rrtm_play(0,nzt_rad+1) = 0.5 * rrtm_plev(0,nzt_rad+1)
4485
4486!
4487!--    Calculate temperature/humidity levels at top of the LES domain.
4488!--    Currently, the temperature is taken from sounding data (might lead to a
4489!--    temperature jump at interface. To do: Humidity is currently not
4490!--    calculated above the LES domain.
4491       ALLOCATE ( rrtm_tlay(0:0,nzb+1:nzt_rad+1)   )
4492       ALLOCATE ( rrtm_tlev(0:0,nzb+1:nzt_rad+2)   )
4493
4494       DO k = nzt+8, nzt_rad
4495          rrtm_tlay(0,k)   = t_snd(k)
4496       ENDDO
4497       rrtm_tlay(0,nzt_rad+1) = 2.0_wp * rrtm_tlay(0,nzt_rad)                  &
4498                                - rrtm_tlay(0,nzt_rad-1)
4499       DO k = nzt+9, nzt_rad+1
4500          rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k)                &
4501                             - rrtm_tlay(0,k-1))                               &
4502                             / ( rrtm_play(0,k) - rrtm_play(0,k-1) )           &
4503                             * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
4504       ENDDO
4505
4506       rrtm_tlev(0,nzt_rad+2)   = 2.0_wp * rrtm_tlay(0,nzt_rad+1)              &
4507                                  - rrtm_tlev(0,nzt_rad)
4508!
4509!--    Allocate remaining RRTMG arrays
4510       ALLOCATE ( rrtm_cicewp(0:0,nzb+1:nzt_rad+1) )
4511       ALLOCATE ( rrtm_cldfr(0:0,nzb+1:nzt_rad+1) )
4512       ALLOCATE ( rrtm_cliqwp(0:0,nzb+1:nzt_rad+1) )
4513       ALLOCATE ( rrtm_reice(0:0,nzb+1:nzt_rad+1) )
4514       ALLOCATE ( rrtm_reliq(0:0,nzb+1:nzt_rad+1) )
4515       ALLOCATE ( rrtm_lw_taucld(1:nbndlw+1,0:0,nzb+1:nzt_rad+1) )
4516       ALLOCATE ( rrtm_lw_tauaer(0:0,nzb+1:nzt_rad+1,1:nbndlw+1) )
4517       ALLOCATE ( rrtm_sw_taucld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4518       ALLOCATE ( rrtm_sw_ssacld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4519       ALLOCATE ( rrtm_sw_asmcld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4520       ALLOCATE ( rrtm_sw_fsfcld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4521       ALLOCATE ( rrtm_sw_tauaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) )
4522       ALLOCATE ( rrtm_sw_ssaaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) )
4523       ALLOCATE ( rrtm_sw_asmaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) ) 
4524       ALLOCATE ( rrtm_sw_ecaer(0:0,nzb+1:nzt_rad+1,1:naerec+1) )   
4525
4526!
4527!--    The ice phase is currently not considered in PALM
4528       rrtm_cicewp = 0.0_wp
4529       rrtm_reice  = 0.0_wp
4530
4531!
4532!--    Set other parameters (move to NAMELIST parameters in the future)
4533       rrtm_lw_tauaer = 0.0_wp
4534       rrtm_lw_taucld = 0.0_wp
4535       rrtm_sw_taucld = 0.0_wp
4536       rrtm_sw_ssacld = 0.0_wp
4537       rrtm_sw_asmcld = 0.0_wp
4538       rrtm_sw_fsfcld = 0.0_wp
4539       rrtm_sw_tauaer = 0.0_wp
4540       rrtm_sw_ssaaer = 0.0_wp
4541       rrtm_sw_asmaer = 0.0_wp
4542       rrtm_sw_ecaer  = 0.0_wp
4543
4544
4545       ALLOCATE ( rrtm_swdflx(0:0,nzb:nzt_rad+1)  )
4546       ALLOCATE ( rrtm_swuflx(0:0,nzb:nzt_rad+1)  )
4547       ALLOCATE ( rrtm_swhr(0:0,nzb+1:nzt_rad+1)  )
4548       ALLOCATE ( rrtm_swuflxc(0:0,nzb:nzt_rad+1) )
4549       ALLOCATE ( rrtm_swdflxc(0:0,nzb:nzt_rad+1) )
4550       ALLOCATE ( rrtm_swhrc(0:0,nzb+1:nzt_rad+1) )
4551       ALLOCATE ( rrtm_dirdflux(0:0,nzb:nzt_rad+1) )
4552       ALLOCATE ( rrtm_difdflux(0:0,nzb:nzt_rad+1) )
4553
4554       rrtm_swdflx  = 0.0_wp
4555       rrtm_swuflx  = 0.0_wp
4556       rrtm_swhr    = 0.0_wp 
4557       rrtm_swuflxc = 0.0_wp
4558       rrtm_swdflxc = 0.0_wp
4559       rrtm_swhrc   = 0.0_wp
4560       rrtm_dirdflux = 0.0_wp
4561       rrtm_difdflux = 0.0_wp
4562
4563       ALLOCATE ( rrtm_lwdflx(0:0,nzb:nzt_rad+1)  )
4564       ALLOCATE ( rrtm_lwuflx(0:0,nzb:nzt_rad+1)  )
4565       ALLOCATE ( rrtm_lwhr(0:0,nzb+1:nzt_rad+1)  )
4566       ALLOCATE ( rrtm_lwuflxc(0:0,nzb:nzt_rad+1) )
4567       ALLOCATE ( rrtm_lwdflxc(0:0,nzb:nzt_rad+1) )
4568       ALLOCATE ( rrtm_lwhrc(0:0,nzb+1:nzt_rad+1) )
4569
4570       rrtm_lwdflx  = 0.0_wp
4571       rrtm_lwuflx  = 0.0_wp
4572       rrtm_lwhr    = 0.0_wp 
4573       rrtm_lwuflxc = 0.0_wp
4574       rrtm_lwdflxc = 0.0_wp
4575       rrtm_lwhrc   = 0.0_wp
4576
4577       ALLOCATE ( rrtm_lwuflx_dt(0:0,nzb:nzt_rad+1) )
4578       ALLOCATE ( rrtm_lwuflxc_dt(0:0,nzb:nzt_rad+1) )
4579
4580       rrtm_lwuflx_dt = 0.0_wp
4581       rrtm_lwuflxc_dt = 0.0_wp
4582
4583    END SUBROUTINE read_sounding_data
4584
4585
4586!------------------------------------------------------------------------------!
4587! Description:
4588! ------------
4589!> Read trace gas data from file
4590!------------------------------------------------------------------------------!
4591    SUBROUTINE read_trace_gas_data
4592
4593       USE rrsw_ncpar
4594
4595       IMPLICIT NONE
4596
4597       INTEGER(iwp), PARAMETER :: num_trace_gases = 10 !< number of trace gases (absorbers)
4598
4599       CHARACTER(LEN=5), DIMENSION(num_trace_gases), PARAMETER ::              & !< trace gas names
4600           trace_names = (/'O3   ', 'CO2  ', 'CH4  ', 'N2O  ', 'O2   ',        &
4601                           'CFC11', 'CFC12', 'CFC22', 'CCL4 ', 'H2O  '/)
4602
4603       INTEGER(iwp) :: id,     & !< NetCDF id
4604                       k,      & !< loop index
4605                       m,      & !< loop index
4606                       n,      & !< loop index
4607                       nabs,   & !< number of absorbers
4608                       np,     & !< number of pressure levels
4609                       id_abs, & !< NetCDF id of the respective absorber
4610                       id_dim, & !< NetCDF id of asborber's dimension
4611                       id_var    !< NetCDf id ot the absorber
4612
4613       REAL(wp) :: p_mls_l, p_mls_u, p_wgt_l, p_wgt_u, p_mls_m
4614
4615
4616       REAL(wp), DIMENSION(:), ALLOCATABLE   ::  p_mls,          & !< pressure levels for the absorbers
4617                                                 rrtm_play_tmp,  & !< temporary array for pressure zu-levels
4618                                                 rrtm_plev_tmp,  & !< temporary array for pressure zw-levels
4619                                                 trace_path_tmp    !< temporary array for storing trace gas path data
4620
4621       REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  trace_mls,      & !< array for storing the absorber amounts
4622                                                 trace_mls_path, & !< array for storing trace gas path data
4623                                                 trace_mls_tmp     !< temporary array for storing trace gas data
4624
4625
4626!
4627!--    In case of updates, deallocate arrays first (sufficient to check one
4628!--    array as the others are automatically allocated)
4629       IF ( ALLOCATED ( rrtm_o3vmr ) )  THEN
4630          DEALLOCATE ( rrtm_o3vmr  )
4631          DEALLOCATE ( rrtm_co2vmr )
4632          DEALLOCATE ( rrtm_ch4vmr )
4633          DEALLOCATE ( rrtm_n2ovmr )
4634          DEALLOCATE ( rrtm_o2vmr  )
4635          DEALLOCATE ( rrtm_cfc11vmr )
4636          DEALLOCATE ( rrtm_cfc12vmr )
4637          DEALLOCATE ( rrtm_cfc22vmr )
4638          DEALLOCATE ( rrtm_ccl4vmr  )
4639          DEALLOCATE ( rrtm_h2ovmr  )     
4640       ENDIF
4641
4642!
4643!--    Allocate trace gas profiles
4644       ALLOCATE ( rrtm_o3vmr(0:0,1:nzt_rad+1)  )
4645       ALLOCATE ( rrtm_co2vmr(0:0,1:nzt_rad+1) )
4646       ALLOCATE ( rrtm_ch4vmr(0:0,1:nzt_rad+1) )
4647       ALLOCATE ( rrtm_n2ovmr(0:0,1:nzt_rad+1) )
4648       ALLOCATE ( rrtm_o2vmr(0:0,1:nzt_rad+1)  )
4649       ALLOCATE ( rrtm_cfc11vmr(0:0,1:nzt_rad+1) )
4650       ALLOCATE ( rrtm_cfc12vmr(0:0,1:nzt_rad+1) )
4651       ALLOCATE ( rrtm_cfc22vmr(0:0,1:nzt_rad+1) )
4652       ALLOCATE ( rrtm_ccl4vmr(0:0,1:nzt_rad+1)  )
4653       ALLOCATE ( rrtm_h2ovmr(0:0,1:nzt_rad+1)  )
4654
4655!
4656!--    Open file for reading
4657       nc_stat = NF90_OPEN( rrtm_input_file, NF90_NOWRITE, id )
4658       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 549 )
4659!
4660!--    Inquire dimension ids and dimensions
4661       nc_stat = NF90_INQ_DIMID( id, "Pressure", id_dim )
4662       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4663       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim, len = np) 
4664       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4665
4666       nc_stat = NF90_INQ_DIMID( id, "Absorber", id_dim )
4667       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4668       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim, len = nabs ) 
4669       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4670   
4671
4672!
4673!--    Allocate pressure, and trace gas arrays     
4674       ALLOCATE( p_mls(1:np) )
4675       ALLOCATE( trace_mls(1:num_trace_gases,1:np) ) 
4676       ALLOCATE( trace_mls_tmp(1:nabs,1:np) ) 
4677
4678
4679       nc_stat = NF90_INQ_VARID( id, "Pressure", id_var )
4680       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4681       nc_stat = NF90_GET_VAR( id, id_var, p_mls )
4682       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4683
4684       nc_stat = NF90_INQ_VARID( id, "AbsorberAmountMLS", id_var )
4685       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4686       nc_stat = NF90_GET_VAR( id, id_var, trace_mls_tmp )
4687       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4688
4689
4690!
4691!--    Write absorber amounts (mls) to trace_mls
4692       DO n = 1, num_trace_gases
4693          CALL getAbsorberIndex( TRIM( trace_names(n) ), id_abs )
4694
4695          trace_mls(n,1:np) = trace_mls_tmp(id_abs,1:np)
4696
4697!
4698!--       Replace missing values by zero
4699          WHERE ( trace_mls(n,:) > 2.0_wp ) 
4700             trace_mls(n,:) = 0.0_wp
4701          END WHERE
4702       END DO
4703
4704       DEALLOCATE ( trace_mls_tmp )
4705
4706       nc_stat = NF90_CLOSE( id )
4707       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 551 )
4708
4709!
4710!--    Add extra pressure level for calculations of the trace gas paths
4711       ALLOCATE ( rrtm_play_tmp(1:nzt_rad+1) )
4712       ALLOCATE ( rrtm_plev_tmp(1:nzt_rad+2) )
4713
4714       rrtm_play_tmp(1:nzt_rad)   = rrtm_play(0,1:nzt_rad) 
4715       rrtm_plev_tmp(1:nzt_rad+1) = rrtm_plev(0,1:nzt_rad+1)
4716       rrtm_play_tmp(nzt_rad+1)   = rrtm_plev(0,nzt_rad+1) * 0.5_wp
4717       rrtm_plev_tmp(nzt_rad+2)   = MIN( 1.0E-4_wp, 0.25_wp                    &
4718                                         * rrtm_plev(0,nzt_rad+1) )
4719 
4720!
4721!--    Calculate trace gas path (zero at surface) with interpolation to the
4722!--    sounding levels
4723       ALLOCATE ( trace_mls_path(1:nzt_rad+2,1:num_trace_gases) )
4724
4725       trace_mls_path(nzb+1,:) = 0.0_wp
4726       
4727       DO k = nzb+2, nzt_rad+2
4728          DO m = 1, num_trace_gases
4729             trace_mls_path(k,m) = trace_mls_path(k-1,m)
4730
4731!
4732!--          When the pressure level is higher than the trace gas pressure
4733!--          level, assume that
4734             IF ( rrtm_plev_tmp(k-1) > p_mls(1) )  THEN             
4735               
4736                trace_mls_path(k,m) = trace_mls_path(k,m) + trace_mls(m,1)     &
4737                                      * ( rrtm_plev_tmp(k-1)                   &
4738                                          - MAX( p_mls(1), rrtm_plev_tmp(k) )  &
4739                                        ) / g
4740             ENDIF
4741
4742!
4743!--          Integrate for each sounding level from the contributing p_mls
4744!--          levels
4745             DO n = 2, np
4746!
4747!--             Limit p_mls so that it is within the model level
4748                p_mls_u = MIN( rrtm_plev_tmp(k-1),                             &
4749                          MAX( rrtm_plev_tmp(k), p_mls(n) ) )
4750                p_mls_l = MIN( rrtm_plev_tmp(k-1),                             &
4751                          MAX( rrtm_plev_tmp(k), p_mls(n-1) ) )
4752
4753                IF ( p_mls_l > p_mls_u )  THEN
4754
4755!
4756!--                Calculate weights for interpolation
4757                   p_mls_m = 0.5_wp * (p_mls_l + p_mls_u)
4758                   p_wgt_u = (p_mls(n-1) - p_mls_m) / (p_mls(n-1) - p_mls(n))
4759                   p_wgt_l = (p_mls_m - p_mls(n))   / (p_mls(n-1) - p_mls(n))
4760
4761!
4762!--                Add level to trace gas path
4763                   trace_mls_path(k,m) = trace_mls_path(k,m)                   &
4764                                         +  ( p_wgt_u * trace_mls(m,n)         &
4765                                            + p_wgt_l * trace_mls(m,n-1) )     &
4766                                         * (p_mls_l - p_mls_u) / g
4767                ENDIF
4768             ENDDO
4769
4770             IF ( rrtm_plev_tmp(k) < p_mls(np) )  THEN
4771                trace_mls_path(k,m) = trace_mls_path(k,m) + trace_mls(m,np)    &
4772                                      * ( MIN( rrtm_plev_tmp(k-1), p_mls(np) ) &
4773                                          - rrtm_plev_tmp(k)                   &
4774                                        ) / g 
4775             ENDIF 
4776          ENDDO
4777       ENDDO
4778
4779
4780!
4781!--    Prepare trace gas path profiles
4782       ALLOCATE ( trace_path_tmp(1:nzt_rad+1) )
4783
4784       DO m = 1, num_trace_gases
4785
4786          trace_path_tmp(1:nzt_rad+1) = ( trace_mls_path(2:nzt_rad+2,m)        &
4787                                       - trace_mls_path(1:nzt_rad+1,m) ) * g   &
4788                                       / ( rrtm_plev_tmp(1:nzt_rad+1)          &
4789                                       - rrtm_plev_tmp(2:nzt_rad+2) )
4790
4791!
4792!--       Save trace gas paths to the respective arrays
4793          SELECT CASE ( TRIM( trace_names(m) ) )
4794
4795             CASE ( 'O3' )
4796
4797                rrtm_o3vmr(0,:) = trace_path_tmp(:)
4798
4799             CASE ( 'CO2' )
4800
4801                rrtm_co2vmr(0,:) = trace_path_tmp(:)
4802
4803             CASE ( 'CH4' )
4804
4805                rrtm_ch4vmr(0,:) = trace_path_tmp(:)
4806
4807             CASE ( 'N2O' )
4808
4809                rrtm_n2ovmr(0,:) = trace_path_tmp(:)
4810
4811             CASE ( 'O2' )
4812
4813                rrtm_o2vmr(0,:) = trace_path_tmp(:)
4814
4815             CASE ( 'CFC11' )
4816
4817                rrtm_cfc11vmr(0,:) = trace_path_tmp(:)
4818
4819             CASE ( 'CFC12' )
4820
4821                rrtm_cfc12vmr(0,:) = trace_path_tmp(:)
4822
4823             CASE ( 'CFC22' )
4824
4825                rrtm_cfc22vmr(0,:) = trace_path_tmp(:)
4826
4827             CASE ( 'CCL4' )
4828
4829                rrtm_ccl4vmr(0,:) = trace_path_tmp(:)
4830
4831             CASE ( 'H2O' )
4832
4833                rrtm_h2ovmr(0,:) = trace_path_tmp(:)
4834               
4835             CASE DEFAULT
4836
4837          END SELECT
4838
4839       ENDDO
4840
4841       DEALLOCATE ( trace_path_tmp )
4842       DEALLOCATE ( trace_mls_path )
4843       DEALLOCATE ( rrtm_play_tmp )
4844       DEALLOCATE ( rrtm_plev_tmp )
4845       DEALLOCATE ( trace_mls )
4846       DEALLOCATE ( p_mls )
4847
4848    END SUBROUTINE read_trace_gas_data
4849
4850
4851    SUBROUTINE netcdf_handle_error_rad( routine_name, errno )
4852
4853       USE control_parameters,                                                 &
4854           ONLY:  message_string
4855
4856       USE NETCDF
4857
4858       USE pegrid
4859
4860       IMPLICIT NONE
4861
4862       CHARACTER(LEN=6) ::  message_identifier
4863       CHARACTER(LEN=*) ::  routine_name
4864
4865       INTEGER(iwp) ::  errno
4866
4867       IF ( nc_stat /= NF90_NOERR )  THEN
4868
4869          WRITE( message_identifier, '(''NC'',I4.4)' )  errno
4870          message_string = TRIM( NF90_STRERROR( nc_stat ) )
4871
4872          CALL message( routine_name, message_identifier, 2, 2, 0, 6, 1 )
4873
4874       ENDIF
4875
4876    END SUBROUTINE netcdf_handle_error_rad
4877#endif
4878
4879
4880!------------------------------------------------------------------------------!
4881! Description:
4882! ------------
4883!> Calculate temperature tendency due to radiative cooling/heating.
4884!> Cache-optimized version.
4885!------------------------------------------------------------------------------!
4886 SUBROUTINE radiation_tendency_ij ( i, j, tend )
4887
4888    IMPLICIT NONE
4889
4890    INTEGER(iwp) :: i, j, k !< loop indices
4891
4892    REAL(wp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg) :: tend !< pt tendency term
4893
4894    IF ( radiation_scheme == 'rrtmg' )  THEN
4895#if defined  ( __rrtmg )
4896!
4897!--    Calculate tendency based on heating rate
4898       DO k = nzb+1, nzt+1
4899          tend(k,j,i) = tend(k,j,i) + (rad_lw_hr(k,j,i) + rad_sw_hr(k,j,i))    &
4900                                         * d_exner(k) * d_seconds_hour
4901       ENDDO
4902#endif
4903    ENDIF
4904
4905    END SUBROUTINE radiation_tendency_ij
4906
4907
4908!------------------------------------------------------------------------------!
4909! Description:
4910! ------------
4911!> Calculate temperature tendency due to radiative cooling/heating.
4912!> Vector-optimized version
4913!------------------------------------------------------------------------------!
4914 SUBROUTINE radiation_tendency ( tend )
4915
4916    USE indices,                                                               &
4917        ONLY:  nxl, nxr, nyn, nys
4918
4919    IMPLICIT NONE
4920
4921    INTEGER(iwp) :: i, j, k !< loop indices
4922
4923    REAL(wp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg) :: tend !< pt tendency term
4924
4925    IF ( radiation_scheme == 'rrtmg' )  THEN
4926#if defined  ( __rrtmg )
4927!
4928!--    Calculate tendency based on heating rate
4929       DO  i = nxl, nxr
4930          DO  j = nys, nyn
4931             DO k = nzb+1, nzt+1
4932                tend(k,j,i) = tend(k,j,i) + ( rad_lw_hr(k,j,i)                 &
4933                                          +  rad_sw_hr(k,j,i) ) * d_exner(k)   &
4934                                          * d_seconds_hour
4935             ENDDO
4936          ENDDO
4937       ENDDO
4938#endif
4939    ENDIF
4940
4941
4942 END SUBROUTINE radiation_tendency
4943
4944!------------------------------------------------------------------------------!
4945! Description:
4946! ------------
4947!> This subroutine calculates interaction of the solar radiation
4948!> with urban and land surfaces and updates all surface heatfluxes.
4949!> It calculates also the required parameters for RRTMG lower BC.
4950!>
4951!> For more info. see Resler et al. 2017
4952!>
4953!> The new version 2.0 was radically rewriten, the discretization scheme
4954!> has been changed. This new version significantly improves effectivity
4955!> of the paralelization and the scalability of the model.
4956!------------------------------------------------------------------------------!
4957
4958 SUBROUTINE radiation_interaction
4959
4960     IMPLICIT NONE
4961
4962     INTEGER(iwp)                      :: i, j, k, kk, is, js, d, ku, refstep, m, mm, l, ll
4963     INTEGER(iwp)                      :: isurf, isurfsrc, isvf, icsf, ipcgb
4964     INTEGER(iwp)                      :: imrt, imrtf
4965     INTEGER(iwp)                      :: isd                !< solar direction number
4966     INTEGER(iwp)                      :: pc_box_dimshift    !< transform for best accuracy
4967     INTEGER(iwp), DIMENSION(0:3)      :: reorder = (/ 1, 0, 3, 2 /)
4968     
4969     REAL(wp), DIMENSION(3,3)          :: mrot               !< grid rotation matrix (zyx)
4970     REAL(wp), DIMENSION(3,0:nsurf_type):: vnorm             !< face direction normal vectors (zyx)
4971     REAL(wp), DIMENSION(3)            :: sunorig            !< grid rotated solar direction unit vector (zyx)
4972     REAL(wp), DIMENSION(3)            :: sunorig_grid       !< grid squashed solar direction unit vector (zyx)
4973     REAL(wp), DIMENSION(0:nsurf_type) :: costheta           !< direct irradiance factor of solar angle
4974     REAL(wp), DIMENSION(nzub:nzut)    :: pchf_prep          !< precalculated factor for canopy temperature tendency
4975     REAL(wp), PARAMETER               :: alpha = 0._wp      !< grid rotation (TODO: add to namelist or remove)
4976     REAL(wp)                          :: pc_box_area, pc_abs_frac, pc_abs_eff
4977     REAL(wp)                          :: asrc               !< area of source face
4978     REAL(wp)                          :: pcrad              !< irradiance from plant canopy
4979     REAL(wp)                          :: pabsswl  = 0.0_wp  !< total absorbed SW radiation energy in local processor (W)
4980     REAL(wp)                          :: pabssw   = 0.0_wp  !< total absorbed SW radiation energy in all processors (W)
4981     REAL(wp)                          :: pabslwl  = 0.0_wp  !< total absorbed LW radiation energy in local processor (W)
4982     REAL(wp)                          :: pabslw   = 0.0_wp  !< total absorbed LW radiation energy in all processors (W)
4983     REAL(wp)                          :: pemitlwl = 0.0_wp  !< total emitted LW radiation energy in all processors (W)
4984     REAL(wp)                          :: pemitlw  = 0.0_wp  !< total emitted LW radiation energy in all processors (W)
4985     REAL(wp)                          :: pinswl   = 0.0_wp  !< total received SW radiation energy in local processor (W)
4986     REAL(wp)                          :: pinsw    = 0.0_wp  !< total received SW radiation energy in all processor (W)
4987     REAL(wp)                          :: pinlwl   = 0.0_wp  !< total received LW radiation energy in local processor (W)
4988     REAL(wp)                          :: pinlw    = 0.0_wp  !< total received LW radiation energy in all processor (W)
4989     REAL(wp)                          :: emiss_sum_surfl    !< sum of emissisivity of surfaces in local processor
4990     REAL(wp)                          :: emiss_sum_surf     !< sum of emissisivity of surfaces in all processor
4991     REAL(wp)                          :: area_surfl         !< total area of surfaces in local processor
4992     REAL(wp)                          :: area_surf          !< total area of surfaces in all processor
4993     REAL(wp)                          :: area_hor           !< total horizontal area of domain in all processor
4994
4995
4996     IF ( plant_canopy )  THEN
4997         pchf_prep(:) = r_d * exner(nzub:nzut)                                 &
4998                     / (c_p * hyp(nzub:nzut) * dx*dy*dz(1)) !< equals to 1 / (rho * c_p * Vbox * T)
4999     ENDIF
5000
5001     sun_direction = .TRUE.
5002     CALL calc_zenith  !< required also for diffusion radiation
5003
5004!--     prepare rotated normal vectors and irradiance factor
5005     vnorm(1,:) = kdir(:)
5006     vnorm(2,:) = jdir(:)
5007     vnorm(3,:) = idir(:)
5008     mrot(1, :) = (/ 1._wp,  0._wp,      0._wp      /)
5009     mrot(2, :) = (/ 0._wp,  COS(alpha), SIN(alpha) /)
5010     mrot(3, :) = (/ 0._wp, -SIN(alpha), COS(alpha) /)
5011     sunorig = (/ zenith(0), sun_dir_lat, sun_dir_lon /)
5012     sunorig = MATMUL(mrot, sunorig)
5013     DO d = 0, nsurf_type
5014         costheta(d) = DOT_PRODUCT(sunorig, vnorm(:,d))
5015     ENDDO
5016
5017     IF ( zenith(0) > 0 )  THEN
5018!--      now we will "squash" the sunorig vector by grid box size in
5019!--      each dimension, so that this new direction vector will allow us
5020!--      to traverse the ray path within grid coordinates directly
5021         sunorig_grid = (/ sunorig(1)/dz(1), sunorig(2)/dy, sunorig(3)/dx /)
5022!--      sunorig_grid = sunorig_grid / norm2(sunorig_grid)
5023         sunorig_grid = sunorig_grid / SQRT(SUM(sunorig_grid**2))
5024
5025         IF ( npcbl > 0 )  THEN
5026!--         precompute effective box depth with prototype Leaf Area Density
5027            pc_box_dimshift = MAXLOC(ABS(sunorig), 1) - 1
5028            CALL box_absorb(CSHIFT((/dz(1),dy,dx/), pc_box_dimshift),       &
5029                                60, prototype_lad,                          &
5030                                CSHIFT(ABS(sunorig), pc_box_dimshift),      &
5031                                pc_box_area, pc_abs_frac)
5032            pc_box_area = pc_box_area * ABS(sunorig(pc_box_dimshift+1)      &
5033                          / sunorig(1))
5034            pc_abs_eff = LOG(1._wp - pc_abs_frac) / prototype_lad
5035         ENDIF
5036     ENDIF
5037
5038!--  if radiation scheme is not RRTMG, split diffusion and direct part of the solar downward radiation
5039!--  comming from radiation model and store it in 2D arrays
5040     IF (  radiation_scheme /= 'rrtmg'  )  CALL calc_diffusion_radiation
5041
5042!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5043!--     First pass: direct + diffuse irradiance + thermal
5044!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5045     surfinswdir   = 0._wp !nsurfl
5046     surfins       = 0._wp !nsurfl
5047     surfinl       = 0._wp !nsurfl
5048     surfoutsl(:)  = 0.0_wp !start-end
5049     surfoutll(:)  = 0.0_wp !start-end
5050     IF ( nmrtbl > 0 )  THEN
5051        mrtinsw(:) = 0._wp
5052        mrtinlw(:) = 0._wp
5053     ENDIF
5054     surfinlg(:)  = 0._wp !global
5055
5056
5057!--  Set up thermal radiation from surfaces
5058!--  emiss_surf is defined only for surfaces for which energy balance is calculated
5059!--  Workaround: reorder surface data type back on 1D array including all surfaces,
5060!--  which implies to reorder horizontal and vertical surfaces
5061!
5062!--  Horizontal walls
5063     mm = 1
5064     DO  i = nxl, nxr
5065        DO  j = nys, nyn
5066!--           urban
5067           DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
5068              surfoutll(mm) = SUM ( surf_usm_h%frac(:,m) *                  &
5069                                    surf_usm_h%emissivity(:,m) )            &
5070                                  * sigma_sb                                &
5071                                  * surf_usm_h%pt_surface(m)**4
5072              albedo_surf(mm) = SUM ( surf_usm_h%frac(:,m) *                &
5073                                      surf_usm_h%albedo(:,m) )
5074              emiss_surf(mm)  = SUM ( surf_usm_h%frac(:,m) *                &
5075                                      surf_usm_h%emissivity(:,m) )
5076              mm = mm + 1
5077           ENDDO
5078!--           land
5079           DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
5080              surfoutll(mm) = SUM ( surf_lsm_h%frac(:,m) *                  &
5081                                    surf_lsm_h%emissivity(:,m) )            &
5082                                  * sigma_sb                                &
5083                                  * surf_lsm_h%pt_surface(m)**4
5084              albedo_surf(mm) = SUM ( surf_lsm_h%frac(:,m) *                &
5085                                      surf_lsm_h%albedo(:,m) )
5086              emiss_surf(mm)  = SUM ( surf_lsm_h%frac(:,m) *                &
5087                                      surf_lsm_h%emissivity(:,m) )
5088              mm = mm + 1
5089           ENDDO
5090        ENDDO
5091     ENDDO
5092!
5093!--     Vertical walls
5094     DO  i = nxl, nxr
5095        DO  j = nys, nyn
5096           DO  ll = 0, 3
5097              l = reorder(ll)
5098!--              urban
5099              DO  m = surf_usm_v(l)%start_index(j,i),                       &
5100                      surf_usm_v(l)%end_index(j,i)
5101                 surfoutll(mm) = SUM ( surf_usm_v(l)%frac(:,m) *            &
5102                                       surf_usm_v(l)%emissivity(:,m) )      &
5103                                  * sigma_sb                                &
5104                                  * surf_usm_v(l)%pt_surface(m)**4
5105                 albedo_surf(mm) = SUM ( surf_usm_v(l)%frac(:,m) *          &
5106                                         surf_usm_v(l)%albedo(:,m) )
5107                 emiss_surf(mm)  = SUM ( surf_usm_v(l)%frac(:,m) *          &
5108                                         surf_usm_v(l)%emissivity(:,m) )
5109                 mm = mm + 1
5110              ENDDO
5111!--              land
5112              DO  m = surf_lsm_v(l)%start_index(j,i),                       &
5113                      surf_lsm_v(l)%end_index(j,i)
5114                 surfoutll(mm) = SUM ( surf_lsm_v(l)%frac(:,m) *            &
5115                                       surf_lsm_v(l)%emissivity(:,m) )      &
5116                                  * sigma_sb                                &
5117                                  * surf_lsm_v(l)%pt_surface(m)**4
5118                 albedo_surf(mm) = SUM ( surf_lsm_v(l)%frac(:,m) *          &
5119                                         surf_lsm_v(l)%albedo(:,m) )
5120                 emiss_surf(mm)  = SUM ( surf_lsm_v(l)%frac(:,m) *          &
5121                                         surf_lsm_v(l)%emissivity(:,m) )
5122                 mm = mm + 1
5123              ENDDO
5124           ENDDO
5125        ENDDO
5126     ENDDO
5127
5128#if defined( __parallel )
5129!--     might be optimized and gather only values relevant for current processor
5130     CALL MPI_AllGatherv(surfoutll, nsurfl, MPI_REAL, &
5131                         surfoutl, nsurfs, surfstart, MPI_REAL, comm2d, ierr) !nsurf global
5132     IF ( ierr /= 0 ) THEN
5133         WRITE(9,*) 'Error MPI_AllGatherv1:', ierr, SIZE(surfoutll), nsurfl, &
5134                     SIZE(surfoutl), nsurfs, surfstart
5135         FLUSH(9)
5136     ENDIF
5137#else
5138     surfoutl(:) = surfoutll(:) !nsurf global
5139#endif
5140
5141     IF ( surface_reflections)  THEN
5142        DO  isvf = 1, nsvfl
5143           isurf = svfsurf(1, isvf)
5144           k     = surfl(iz, isurf)
5145           j     = surfl(iy, isurf)
5146           i     = surfl(ix, isurf)
5147           isurfsrc = svfsurf(2, isvf)
5148!
5149!--        For surface-to-surface factors we calculate thermal radiation in 1st pass
5150           IF ( plant_lw_interact )  THEN
5151              surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * svf(2,isvf) * surfoutl(isurfsrc)
5152           ELSE
5153              surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * surfoutl(isurfsrc)
5154           ENDIF
5155        ENDDO
5156     ENDIF
5157!
5158!--  diffuse radiation using sky view factor
5159     DO isurf = 1, nsurfl
5160        j = surfl(iy, isurf)
5161        i = surfl(ix, isurf)
5162        surfinswdif(isurf) = rad_sw_in_diff(j,i) * skyvft(isurf)
5163        IF ( plant_lw_interact )  THEN
5164           surfinlwdif(isurf) = rad_lw_in_diff(j,i) * skyvft(isurf)
5165        ELSE
5166           surfinlwdif(isurf) = rad_lw_in_diff(j,i) * skyvf(isurf)
5167        ENDIF
5168     ENDDO
5169!
5170!--  MRT diffuse irradiance
5171     DO  imrt = 1, nmrtbl
5172        j = mrtbl(iy, imrt)
5173        i = mrtbl(ix, imrt)
5174        mrtinsw(imrt) = mrtskyt(imrt) * rad_sw_in_diff(j,i)
5175        mrtinlw(imrt) = mrtsky(imrt) * rad_lw_in_diff(j,i)
5176     ENDDO
5177
5178     !-- direct radiation
5179     IF ( zenith(0) > 0 )  THEN
5180        !--Identify solar direction vector (discretized number) 1)
5181        !--
5182        j = FLOOR(ACOS(zenith(0)) / pi * raytrace_discrete_elevs)
5183        i = MODULO(NINT(ATAN2(sun_dir_lon(0), sun_dir_lat(0))               &
5184                        / (2._wp*pi) * raytrace_discrete_azims-.5_wp, iwp), &
5185                   raytrace_discrete_azims)
5186        isd = dsidir_rev(j, i)
5187!-- TODO: check if isd = -1 to report that this solar position is not precalculated
5188        DO isurf = 1, nsurfl
5189           j = surfl(iy, isurf)
5190           i = surfl(ix, isurf)
5191           surfinswdir(isurf) = rad_sw_in_dir(j,i) *                        &
5192                costheta(surfl(id, isurf)) * dsitrans(isurf, isd) / zenith(0)
5193        ENDDO
5194!
5195!--     MRT direct irradiance
5196        DO  imrt = 1, nmrtbl
5197           j = mrtbl(iy, imrt)
5198           i = mrtbl(ix, imrt)
5199           mrtinsw(imrt) = mrtinsw(imrt) + mrtdsit(imrt, isd) * rad_sw_in_dir(j,i) &
5200                                     / zenith(0) / 4._wp ! normal to sphere
5201        ENDDO
5202     ENDIF
5203!
5204!--  MRT first pass thermal
5205     DO  imrtf = 1, nmrtf
5206        imrt = mrtfsurf(1, imrtf)
5207        isurfsrc = mrtfsurf(2, imrtf)
5208        mrtinlw(imrt) = mrtinlw(imrt) + mrtf(imrtf) * surfoutl(isurfsrc)
5209     ENDDO
5210
5211     IF ( npcbl > 0 )  THEN
5212
5213         pcbinswdir(:) = 0._wp
5214         pcbinswdif(:) = 0._wp
5215         pcbinlw(:) = 0._wp
5216!
5217!--      pcsf first pass
5218         DO icsf = 1, ncsfl
5219             ipcgb = csfsurf(1, icsf)
5220             i = pcbl(ix,ipcgb)
5221             j = pcbl(iy,ipcgb)
5222             k = pcbl(iz,ipcgb)
5223             isurfsrc = csfsurf(2, icsf)
5224
5225             IF ( isurfsrc == -1 )  THEN
5226!
5227!--             Diffuse rad from sky.
5228                pcbinswdif(ipcgb) = csf(1,icsf) * rad_sw_in_diff(j,i)
5229!
5230!--             Absorbed diffuse LW from sky minus emitted to sky
5231                IF ( plant_lw_interact )  THEN
5232                   pcbinlw(ipcgb) = csf(1,icsf)                                  &
5233                                       * (rad_lw_in_diff(j, i)                   &
5234                                          - sigma_sb * (pt(k,j,i)*exner(k))**4)
5235                ENDIF
5236!
5237!--             Direct rad
5238                IF ( zenith(0) > 0 )  THEN
5239!--                Estimate directed box absorption
5240                   pc_abs_frac = 1._wp - exp(pc_abs_eff * lad_s(k,j,i))
5241!
5242!--                isd has already been established, see 1)
5243                   pcbinswdir(ipcgb) = rad_sw_in_dir(j, i) * pc_box_area &
5244                                       * pc_abs_frac * dsitransc(ipcgb, isd)
5245                ENDIF
5246             ELSE
5247                IF ( plant_lw_interact )  THEN
5248!
5249!--                Thermal emission from plan canopy towards respective face
5250                   pcrad = sigma_sb * (pt(k,j,i) * exner(k))**4 * csf(1,icsf)
5251                   surfinlg(isurfsrc) = surfinlg(isurfsrc) + pcrad
5252!
5253!--                Remove the flux above + absorb LW from first pass from surfaces
5254                   asrc = facearea(surf(id, isurfsrc))
5255                   pcbinlw(ipcgb) = pcbinlw(ipcgb)                      &
5256                                    + (csf(1,icsf) * surfoutl(isurfsrc) & ! Absorb from first pass surf emit
5257                                       - pcrad)                         & ! Remove emitted heatflux
5258                                    * asrc
5259                ENDIF
5260             ENDIF
5261         ENDDO
5262
5263         pcbinsw(:) = pcbinswdir(:) + pcbinswdif(:)
5264     ENDIF
5265
5266     IF ( plant_lw_interact )  THEN
5267!
5268!--     Exchange incoming lw radiation from plant canopy
5269#if defined( __parallel )
5270        CALL MPI_Allreduce(MPI_IN_PLACE, surfinlg, nsurf, MPI_REAL, MPI_SUM, comm2d, ierr)
5271        IF ( ierr /= 0 )  THEN
5272           WRITE (9,*) 'Error MPI_Allreduce:', ierr
5273           FLUSH(9)
5274        ENDIF
5275        surfinl(:) = surfinl(:) + surfinlg(surfstart(myid)+1:surfstart(myid+1))
5276#else
5277        surfinl(:) = surfinl(:) + surfinlg(:)
5278#endif
5279     ENDIF
5280
5281     surfins = surfinswdir + surfinswdif
5282     surfinl = surfinl + surfinlwdif
5283     surfinsw = surfins
5284     surfinlw = surfinl
5285     surfoutsw = 0.0_wp
5286     surfoutlw = surfoutll
5287     surfemitlwl = surfoutll
5288
5289     IF ( .NOT.  surface_reflections )  THEN
5290!
5291!--     Set nrefsteps to 0 to disable reflections       
5292        nrefsteps = 0
5293        surfoutsl = albedo_surf * surfins
5294        surfoutll = (1._wp - emiss_surf) * surfinl
5295        surfoutsw = surfoutsw + surfoutsl
5296        surfoutlw = surfoutlw + surfoutll
5297     ENDIF
5298
5299!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5300!--     Next passes - reflections
5301!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5302     DO refstep = 1, nrefsteps
5303
5304         surfoutsl = albedo_surf * surfins
5305!--         for non-transparent surfaces, longwave albedo is 1 - emissivity
5306         surfoutll = (1._wp - emiss_surf) * surfinl
5307
5308#if defined( __parallel )
5309         CALL MPI_AllGatherv(surfoutsl, nsurfl, MPI_REAL, &
5310             surfouts, nsurfs, surfstart, MPI_REAL, comm2d, ierr)
5311         IF ( ierr /= 0 ) THEN
5312             WRITE(9,*) 'Error MPI_AllGatherv2:', ierr, SIZE(surfoutsl), nsurfl, &
5313                        SIZE(surfouts), nsurfs, surfstart
5314             FLUSH(9)
5315         ENDIF
5316
5317         CALL MPI_AllGatherv(surfoutll, nsurfl, MPI_REAL, &
5318             surfoutl, nsurfs, surfstart, MPI_REAL, comm2d, ierr)
5319         IF ( ierr /= 0 ) THEN
5320             WRITE(9,*) 'Error MPI_AllGatherv3:', ierr, SIZE(surfoutll), nsurfl, &
5321                        SIZE(surfoutl), nsurfs, surfstart
5322             FLUSH(9)
5323         ENDIF
5324
5325#else
5326         surfouts = surfoutsl
5327         surfoutl = surfoutll
5328#endif
5329
5330!--         reset for next pass input
5331         surfins = 0._wp
5332         surfinl = 0._wp
5333
5334!--         reflected radiation
5335         DO isvf = 1, nsvfl
5336             isurf = svfsurf(1, isvf)
5337             isurfsrc = svfsurf(2, isvf)
5338             surfins(isurf) = surfins(isurf) + svf(1,isvf) * svf(2,isvf) * surfouts(isurfsrc)
5339             IF ( plant_lw_interact )  THEN
5340                surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * svf(2,isvf) * surfoutl(isurfsrc)
5341             ELSE
5342                surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * surfoutl(isurfsrc)
5343             ENDIF
5344         ENDDO
5345!
5346!--      NOTE: PC absorbtion and MRT from reflected can both be done at once
5347!--      after all reflections if we do one more MPI_ALLGATHERV on surfout.
5348!--      Advantage: less local computation. Disadvantage: one more collective
5349!--      MPI call.
5350!
5351!--      Radiation absorbed by plant canopy
5352         DO  icsf = 1, ncsfl
5353             ipcgb = csfsurf(1, icsf)
5354             isurfsrc = csfsurf(2, icsf)
5355             IF ( isurfsrc == -1 )  CYCLE ! sky->face only in 1st pass, not here
5356!
5357!--          Calculate source surface area. If the `surf' array is removed
5358!--          before timestepping starts (future version), then asrc must be
5359!--          stored within `csf'
5360             asrc = facearea(surf(id, isurfsrc))
5361             pcbinsw(ipcgb) = pcbinsw(ipcgb) + csf(1,icsf) * surfouts(isurfsrc) * asrc
5362             IF ( plant_lw_interact )  THEN
5363                pcbinlw(ipcgb) = pcbinlw(ipcgb) + csf(1,icsf) * surfoutl(isurfsrc) * asrc
5364             ENDIF
5365         ENDDO
5366!
5367!--      MRT reflected
5368         DO  imrtf = 1, nmrtf
5369            imrt = mrtfsurf(1, imrtf)
5370            isurfsrc = mrtfsurf(2, imrtf)
5371            mrtinsw(imrt) = mrtinsw(imrt) + mrtft(imrtf) * surfouts(isurfsrc)
5372            mrtinlw(imrt) = mrtinlw(imrt) + mrtf(imrtf) * surfoutl(isurfsrc)
5373         ENDDO
5374
5375         surfinsw = surfinsw  + surfins
5376         surfinlw = surfinlw  + surfinl
5377         surfoutsw = surfoutsw + surfoutsl
5378         surfoutlw = surfoutlw + surfoutll
5379
5380     ENDDO ! refstep
5381
5382!--  push heat flux absorbed by plant canopy to respective 3D arrays
5383     IF ( npcbl > 0 )  THEN
5384         pc_heating_rate(:,:,:) = 0.0_wp
5385         DO ipcgb = 1, npcbl
5386             j = pcbl(iy, ipcgb)
5387             i = pcbl(ix, ipcgb)
5388             k = pcbl(iz, ipcgb)
5389!
5390!--          Following expression equals former kk = k - nzb_s_inner(j,i)
5391             kk = k - get_topography_top_index_ji( j, i, 's' )  !- lad arrays are defined flat
5392             pc_heating_rate(kk, j, i) = (pcbinsw(ipcgb) + pcbinlw(ipcgb)) &
5393                 * pchf_prep(k) * pt(k, j, i) !-- = dT/dt
5394         ENDDO
5395
5396         IF ( humidity .AND. plant_canopy_transpiration ) THEN
5397!--          Calculation of plant canopy transpiration rate and correspondidng latent heat rate
5398             pc_transpiration_rate(:,:,:) = 0.0_wp
5399             pc_latent_rate(:,:,:) = 0.0_wp
5400             DO ipcgb = 1, npcbl
5401                 i = pcbl(ix, ipcgb)
5402                 j = pcbl(iy, ipcgb)
5403                 k = pcbl(iz, ipcgb)
5404                 kk = k - get_topography_top_index_ji( j, i, 's' )  !- lad arrays are defined flat
5405                 CALL pcm_calc_transpiration_rate( i, j, k, kk, pcbinsw(ipcgb), pcbinlw(ipcgb), &
5406                                                   pc_transpiration_rate(kk,j,i), pc_latent_rate(kk,j,i) )
5407              ENDDO
5408         ENDIF
5409     ENDIF
5410!
5411!--  Calculate black body MRT (after all reflections)
5412     IF ( nmrtbl > 0 )  THEN
5413        IF ( mrt_include_sw )  THEN
5414           mrt(:) = ((mrtinsw(:) + mrtinlw(:)) / sigma_sb) ** .25_wp
5415        ELSE
5416           mrt(:) = (mrtinlw(:) / sigma_sb) ** .25_wp
5417        ENDIF
5418     ENDIF
5419!
5420!--     Transfer radiation arrays required for energy balance to the respective data types
5421     DO  i = 1, nsurfl
5422        m  = surfl(5,i)
5423!
5424!--     (1) Urban surfaces
5425!--     upward-facing
5426        IF ( surfl(1,i) == iup_u )  THEN
5427           surf_usm_h%rad_sw_in(m)  = surfinsw(i)
5428           surf_usm_h%rad_sw_out(m) = surfoutsw(i)
5429           surf_usm_h%rad_sw_dir(m) = surfinswdir(i)
5430           surf_usm_h%rad_sw_dif(m) = surfinswdif(i)
5431           surf_usm_h%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -        &
5432                                      surfinswdif(i)
5433           surf_usm_h%rad_sw_res(m) = surfins(i)
5434           surf_usm_h%rad_lw_in(m)  = surfinlw(i)
5435           surf_usm_h%rad_lw_out(m) = surfoutlw(i)
5436           surf_usm_h%rad_net(m)    = surfinsw(i) - surfoutsw(i) +          &
5437                                      surfinlw(i) - surfoutlw(i)
5438           surf_usm_h%rad_net_l(m)  = surf_usm_h%rad_net(m)
5439           surf_usm_h%rad_lw_dif(m) = surfinlwdif(i)
5440           surf_usm_h%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5441           surf_usm_h%rad_lw_res(m) = surfinl(i)
5442!
5443!--     northward-facding
5444        ELSEIF ( surfl(1,i) == inorth_u )  THEN
5445           surf_usm_v(0)%rad_sw_in(m)  = surfinsw(i)
5446           surf_usm_v(0)%rad_sw_out(m) = surfoutsw(i)
5447           surf_usm_v(0)%rad_sw_dir(m) = surfinswdir(i)
5448           surf_usm_v(0)%rad_sw_dif(m) = surfinswdif(i)
5449           surf_usm_v(0)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5450                                         surfinswdif(i)
5451           surf_usm_v(0)%rad_sw_res(m) = surfins(i)
5452           surf_usm_v(0)%rad_lw_in(m)  = surfinlw(i)
5453           surf_usm_v(0)%rad_lw_out(m) = surfoutlw(i)
5454           surf_usm_v(0)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5455                                         surfinlw(i) - surfoutlw(i)
5456           surf_usm_v(0)%rad_net_l(m)  = surf_usm_v(0)%rad_net(m)
5457           surf_usm_v(0)%rad_lw_dif(m) = surfinlwdif(i)
5458           surf_usm_v(0)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5459           surf_usm_v(0)%rad_lw_res(m) = surfinl(i)
5460!
5461!--     southward-facding
5462        ELSEIF ( surfl(1,i) == isouth_u )  THEN
5463           surf_usm_v(1)%rad_sw_in(m)  = surfinsw(i)
5464           surf_usm_v(1)%rad_sw_out(m) = surfoutsw(i)
5465           surf_usm_v(1)%rad_sw_dir(m) = surfinswdir(i)
5466           surf_usm_v(1)%rad_sw_dif(m) = surfinswdif(i)
5467           surf_usm_v(1)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5468                                         surfinswdif(i)
5469           surf_usm_v(1)%rad_sw_res(m) = surfins(i)
5470           surf_usm_v(1)%rad_lw_in(m)  = surfinlw(i)
5471           surf_usm_v(1)%rad_lw_out(m) = surfoutlw(i)
5472           surf_usm_v(1)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5473                                         surfinlw(i) - surfoutlw(i)
5474           surf_usm_v(1)%rad_net_l(m)  = surf_usm_v(1)%rad_net(m)
5475           surf_usm_v(1)%rad_lw_dif(m) = surfinlwdif(i)
5476           surf_usm_v(1)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5477           surf_usm_v(1)%rad_lw_res(m) = surfinl(i)
5478!
5479!--     eastward-facing
5480        ELSEIF ( surfl(1,i) == ieast_u )  THEN
5481           surf_usm_v(2)%rad_sw_in(m)  = surfinsw(i)
5482           surf_usm_v(2)%rad_sw_out(m) = surfoutsw(i)
5483           surf_usm_v(2)%rad_sw_dir(m) = surfinswdir(i)
5484           surf_usm_v(2)%rad_sw_dif(m) = surfinswdif(i)
5485           surf_usm_v(2)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5486                                         surfinswdif(i)
5487           surf_usm_v(2)%rad_sw_res(m) = surfins(i)
5488           surf_usm_v(2)%rad_lw_in(m)  = surfinlw(i)
5489           surf_usm_v(2)%rad_lw_out(m) = surfoutlw(i)
5490           surf_usm_v(2)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5491                                         surfinlw(i) - surfoutlw(i)
5492           surf_usm_v(2)%rad_net_l(m)  = surf_usm_v(2)%rad_net(m)
5493           surf_usm_v(2)%rad_lw_dif(m) = surfinlwdif(i)
5494           surf_usm_v(2)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5495           surf_usm_v(2)%rad_lw_res(m) = surfinl(i)
5496!
5497!--     westward-facding
5498        ELSEIF ( surfl(1,i) == iwest_u )  THEN
5499           surf_usm_v(3)%rad_sw_in(m)  = surfinsw(i)
5500           surf_usm_v(3)%rad_sw_out(m) = surfoutsw(i)
5501           surf_usm_v(3)%rad_sw_dir(m) = surfinswdir(i)
5502           surf_usm_v(3)%rad_sw_dif(m) = surfinswdif(i)
5503           surf_usm_v(3)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5504                                         surfinswdif(i)
5505           surf_usm_v(3)%rad_sw_res(m) = surfins(i)
5506           surf_usm_v(3)%rad_lw_in(m)  = surfinlw(i)
5507           surf_usm_v(3)%rad_lw_out(m) = surfoutlw(i)
5508           surf_usm_v(3)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5509                                         surfinlw(i) - surfoutlw(i)
5510           surf_usm_v(3)%rad_net_l(m)  = surf_usm_v(3)%rad_net(m)
5511           surf_usm_v(3)%rad_lw_dif(m) = surfinlwdif(i)
5512           surf_usm_v(3)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5513           surf_usm_v(3)%rad_lw_res(m) = surfinl(i)
5514!
5515!--     (2) land surfaces
5516!--     upward-facing
5517        ELSEIF ( surfl(1,i) == iup_l )  THEN
5518           surf_lsm_h%rad_sw_in(m)  = surfinsw(i)
5519           surf_lsm_h%rad_sw_out(m) = surfoutsw(i)
5520           surf_lsm_h%rad_sw_dir(m) = surfinswdir(i)
5521           surf_lsm_h%rad_sw_dif(m) = surfinswdif(i)
5522           surf_lsm_h%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -        &
5523                                         surfinswdif(i)
5524           surf_lsm_h%rad_sw_res(m) = surfins(i)
5525           surf_lsm_h%rad_lw_in(m)  = surfinlw(i)
5526           surf_lsm_h%rad_lw_out(m) = surfoutlw(i)
5527           surf_lsm_h%rad_net(m)    = surfinsw(i) - surfoutsw(i) +          &
5528                                      surfinlw(i) - surfoutlw(i)
5529           surf_lsm_h%rad_lw_dif(m) = surfinlwdif(i)
5530           surf_lsm_h%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5531           surf_lsm_h%rad_lw_res(m) = surfinl(i)
5532!
5533!--     northward-facding
5534        ELSEIF ( surfl(1,i) == inorth_l )  THEN
5535           surf_lsm_v(0)%rad_sw_in(m)  = surfinsw(i)
5536           surf_lsm_v(0)%rad_sw_out(m) = surfoutsw(i)
5537           surf_lsm_v(0)%rad_sw_dir(m) = surfinswdir(i)
5538           surf_lsm_v(0)%rad_sw_dif(m) = surfinswdif(i)
5539           surf_lsm_v(0)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5540                                         surfinswdif(i)
5541           surf_lsm_v(0)%rad_sw_res(m) = surfins(i)
5542           surf_lsm_v(0)%rad_lw_in(m)  = surfinlw(i)
5543           surf_lsm_v(0)%rad_lw_out(m) = surfoutlw(i)
5544           surf_lsm_v(0)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5545                                         surfinlw(i) - surfoutlw(i)
5546           surf_lsm_v(0)%rad_lw_dif(m) = surfinlwdif(i)
5547           surf_lsm_v(0)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5548           surf_lsm_v(0)%rad_lw_res(m) = surfinl(i)
5549!
5550!--     southward-facding
5551        ELSEIF ( surfl(1,i) == isouth_l )  THEN
5552           surf_lsm_v(1)%rad_sw_in(m)  = surfinsw(i)
5553           surf_lsm_v(1)%rad_sw_out(m) = surfoutsw(i)
5554           surf_lsm_v(1)%rad_sw_dir(m) = surfinswdir(i)
5555           surf_lsm_v(1)%rad_sw_dif(m) = surfinswdif(i)
5556           surf_lsm_v(1)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5557                                         surfinswdif(i)
5558           surf_lsm_v(1)%rad_sw_res(m) = surfins(i)
5559           surf_lsm_v(1)%rad_lw_in(m)  = surfinlw(i)
5560           surf_lsm_v(1)%rad_lw_out(m) = surfoutlw(i)
5561           surf_lsm_v(1)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5562                                         surfinlw(i) - surfoutlw(i)
5563           surf_lsm_v(1)%rad_lw_dif(m) = surfinlwdif(i)
5564           surf_lsm_v(1)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5565           surf_lsm_v(1)%rad_lw_res(m) = surfinl(i)
5566!
5567!--     eastward-facing
5568        ELSEIF ( surfl(1,i) == ieast_l )  THEN
5569           surf_lsm_v(2)%rad_sw_in(m)  = surfinsw(i)
5570           surf_lsm_v(2)%rad_sw_out(m) = surfoutsw(i)
5571           surf_lsm_v(2)%rad_sw_dir(m) = surfinswdir(i)
5572           surf_lsm_v(2)%rad_sw_dif(m) = surfinswdif(i)
5573           surf_lsm_v(2)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5574                                         surfinswdif(i)
5575           surf_lsm_v(2)%rad_sw_res(m) = surfins(i)
5576           surf_lsm_v(2)%rad_lw_in(m)  = surfinlw(i)
5577           surf_lsm_v(2)%rad_lw_out(m) = surfoutlw(i)
5578           surf_lsm_v(2)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5579                                         surfinlw(i) - surfoutlw(i)
5580           surf_lsm_v(2)%rad_lw_dif(m) = surfinlwdif(i)
5581           surf_lsm_v(2)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5582           surf_lsm_v(2)%rad_lw_res(m) = surfinl(i)
5583!
5584!--     westward-facing
5585        ELSEIF ( surfl(1,i) == iwest_l )  THEN
5586           surf_lsm_v(3)%rad_sw_in(m)  = surfinsw(i)
5587           surf_lsm_v(3)%rad_sw_out(m) = surfoutsw(i)
5588           surf_lsm_v(3)%rad_sw_dir(m) = surfinswdir(i)
5589           surf_lsm_v(3)%rad_sw_dif(m) = surfinswdif(i)
5590           surf_lsm_v(3)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5591                                         surfinswdif(i)
5592           surf_lsm_v(3)%rad_sw_res(m) = surfins(i)
5593           surf_lsm_v(3)%rad_lw_in(m)  = surfinlw(i)
5594           surf_lsm_v(3)%rad_lw_out(m) = surfoutlw(i)
5595           surf_lsm_v(3)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5596                                         surfinlw(i) - surfoutlw(i)
5597           surf_lsm_v(3)%rad_lw_dif(m) = surfinlwdif(i)
5598           surf_lsm_v(3)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5599           surf_lsm_v(3)%rad_lw_res(m) = surfinl(i)
5600        ENDIF
5601
5602     ENDDO
5603
5604     DO  m = 1, surf_usm_h%ns
5605        surf_usm_h%surfhf(m) = surf_usm_h%rad_sw_in(m)  +                   &
5606                               surf_usm_h%rad_lw_in(m)  -                   &
5607                               surf_usm_h%rad_sw_out(m) -                   &
5608                               surf_usm_h%rad_lw_out(m)
5609     ENDDO
5610     DO  m = 1, surf_lsm_h%ns
5611        surf_lsm_h%surfhf(m) = surf_lsm_h%rad_sw_in(m)  +                   &
5612                               surf_lsm_h%rad_lw_in(m)  -                   &
5613                               surf_lsm_h%rad_sw_out(m) -                   &
5614                               surf_lsm_h%rad_lw_out(m)
5615     ENDDO
5616
5617     DO  l = 0, 3
5618!--     urban
5619        DO  m = 1, surf_usm_v(l)%ns
5620           surf_usm_v(l)%surfhf(m) = surf_usm_v(l)%rad_sw_in(m)  +          &
5621                                     surf_usm_v(l)%rad_lw_in(m)  -          &
5622                                     surf_usm_v(l)%rad_sw_out(m) -          &
5623                                     surf_usm_v(l)%rad_lw_out(m)
5624        ENDDO
5625!--     land
5626        DO  m = 1, surf_lsm_v(l)%ns
5627           surf_lsm_v(l)%surfhf(m) = surf_lsm_v(l)%rad_sw_in(m)  +          &
5628                                     surf_lsm_v(l)%rad_lw_in(m)  -          &
5629                                     surf_lsm_v(l)%rad_sw_out(m) -          &
5630                                     surf_lsm_v(l)%rad_lw_out(m)
5631
5632        ENDDO
5633     ENDDO
5634!
5635!--  Calculate the average temperature, albedo, and emissivity for urban/land
5636!--  domain when using average_radiation in the respective radiation model
5637
5638!--  calculate horizontal area
5639! !!! ATTENTION!!! uniform grid is assumed here
5640     area_hor = (nx+1) * (ny+1) * dx * dy
5641!
5642!--  absorbed/received SW & LW and emitted LW energy of all physical
5643!--  surfaces (land and urban) in local processor
5644     pinswl = 0._wp
5645     pinlwl = 0._wp
5646     pabsswl = 0._wp
5647     pabslwl = 0._wp
5648     pemitlwl = 0._wp
5649     emiss_sum_surfl = 0._wp
5650     area_surfl = 0._wp
5651     DO  i = 1, nsurfl
5652        d = surfl(id, i)
5653!--  received SW & LW
5654        pinswl = pinswl + (surfinswdir(i) + surfinswdif(i)) * facearea(d)
5655        pinlwl = pinlwl + surfinlwdif(i) * facearea(d)
5656!--   absorbed SW & LW
5657        pabsswl = pabsswl + (1._wp - albedo_surf(i)) *                   &
5658                                                surfinsw(i) * facearea(d)
5659        pabslwl = pabslwl + emiss_surf(i) * surfinlw(i) * facearea(d)
5660!--   emitted LW
5661        pemitlwl = pemitlwl + surfemitlwl(i) * facearea(d)
5662!--   emissivity and area sum
5663        emiss_sum_surfl = emiss_sum_surfl + emiss_surf(i) * facearea(d)
5664        area_surfl = area_surfl + facearea(d)
5665     END DO
5666!
5667!--  add the absorbed SW energy by plant canopy
5668     IF ( npcbl > 0 )  THEN
5669        pabsswl = pabsswl + SUM(pcbinsw)
5670        pabslwl = pabslwl + SUM(pcbinlw)
5671        pinswl = pinswl + SUM(pcbinswdir) + SUM(pcbinswdif)
5672     ENDIF
5673!
5674!--  gather all rad flux energy in all processors
5675#if defined( __parallel )
5676     CALL MPI_ALLREDUCE( pinswl, pinsw, 1, MPI_REAL, MPI_SUM, comm2d, ierr)
5677     IF ( ierr /= 0 ) THEN
5678         WRITE(9,*) 'Error MPI_AllReduce5:', ierr, pinswl, pinsw
5679         FLUSH(9)
5680     ENDIF
5681     CALL MPI_ALLREDUCE( pinlwl, pinlw, 1, MPI_REAL, MPI_SUM, comm2d, ierr)
5682     IF ( ierr /= 0 ) THEN
5683         WRITE(9,*) 'Error MPI_AllReduce6:', ierr, pinlwl, pinlw
5684         FLUSH(9)
5685     ENDIF
5686     CALL MPI_ALLREDUCE( pabsswl, pabssw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5687     IF ( ierr /= 0 ) THEN
5688         WRITE(9,*) 'Error MPI_AllReduce7:', ierr, pabsswl, pabssw
5689         FLUSH(9)
5690     ENDIF
5691     CALL MPI_ALLREDUCE( pabslwl, pabslw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5692     IF ( ierr /= 0 ) THEN
5693         WRITE(9,*) 'Error MPI_AllReduce8:', ierr, pabslwl, pabslw
5694         FLUSH(9)
5695     ENDIF
5696     CALL MPI_ALLREDUCE( pemitlwl, pemitlw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5697     IF ( ierr /= 0 ) THEN
5698         WRITE(9,*) 'Error MPI_AllReduce8:', ierr, pemitlwl, pemitlw
5699         FLUSH(9)
5700     ENDIF
5701     CALL MPI_ALLREDUCE( emiss_sum_surfl, emiss_sum_surf, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5702     IF ( ierr /= 0 ) THEN
5703         WRITE(9,*) 'Error MPI_AllReduce9:', ierr, emiss_sum_surfl, emiss_sum_surf
5704         FLUSH(9)
5705     ENDIF
5706     CALL MPI_ALLREDUCE( area_surfl, area_surf, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5707     IF ( ierr /= 0 ) THEN
5708         WRITE(9,*) 'Error MPI_AllReduce10:', ierr, area_surfl, area_surf
5709         FLUSH(9)
5710     ENDIF
5711#else
5712     pinsw = pinswl
5713     pinlw = pinlwl
5714     pabssw = pabsswl
5715     pabslw = pabslwl
5716     pemitlw = pemitlwl
5717     emiss_sum_surf = emiss_sum_surfl
5718     area_surf = area_surfl
5719#endif
5720
5721!--  (1) albedo
5722     IF ( pinsw /= 0.0_wp )  &
5723          albedo_urb = (pinsw - pabssw) / pinsw
5724!--  (2) average emmsivity
5725     IF ( area_surf /= 0.0_wp ) &
5726          emissivity_urb = emiss_sum_surf / area_surf
5727!
5728!--  Temporally comment out calculation of effective radiative temperature.
5729!--  See below for more explanation.
5730!--  (3) temperature
5731!--   first we calculate an effective horizontal area to account for
5732!--   the effect of vertical surfaces (which contributes to LW emission)
5733!--   We simply use the ratio of the total LW to the incoming LW flux
5734      area_hor = pinlw/rad_lw_in_diff(nyn,nxl)
5735      t_rad_urb = ( (pemitlw - pabslw + emissivity_urb*pinlw) / &
5736           (emissivity_urb*sigma_sb * area_hor) )**0.25_wp
5737
5738    CONTAINS
5739
5740!------------------------------------------------------------------------------!
5741!> Calculates radiation absorbed by box with given size and LAD.
5742!>
5743!> Simulates resol**2 rays (by equally spacing a bounding horizontal square
5744!> conatining all possible rays that would cross the box) and calculates
5745!> average transparency per ray. Returns fraction of absorbed radiation flux
5746!> and area for which this fraction is effective.
5747!------------------------------------------------------------------------------!
5748    PURE SUBROUTINE box_absorb(boxsize, resol, dens, uvec, area, absorb)
5749       IMPLICIT NONE
5750
5751       REAL(wp), DIMENSION(3), INTENT(in) :: &
5752            boxsize, &      !< z, y, x size of box in m
5753            uvec            !< z, y, x unit vector of incoming flux
5754       INTEGER(iwp), INTENT(in) :: &
5755            resol           !< No. of rays in x and y dimensions
5756       REAL(wp), INTENT(in) :: &
5757            dens            !< box density (e.g. Leaf Area Density)
5758       REAL(wp), INTENT(out) :: &
5759            area, &         !< horizontal area for flux absorbtion
5760            absorb          !< fraction of absorbed flux
5761       REAL(wp) :: &
5762            xshift, yshift, &
5763            xmin, xmax, ymin, ymax, &
5764            xorig, yorig, &
5765            dx1, dy1, dz1, dx2, dy2, dz2, &
5766            crdist, &
5767            transp
5768       INTEGER(iwp) :: &
5769            i, j
5770
5771       xshift = uvec(3) / uvec(1) * boxsize(1)
5772       xmin = min(0._wp, -xshift)
5773       xmax = boxsize(3) + max(0._wp, -xshift)
5774       yshift = uvec(2) / uvec(1) * boxsize(1)
5775       ymin = min(0._wp, -yshift)
5776       ymax = boxsize(2) + max(0._wp, -yshift)
5777
5778       transp = 0._wp
5779       DO i = 1, resol
5780          xorig = xmin + (xmax-xmin) * (i-.5_wp) / resol
5781          DO j = 1, resol
5782             yorig = ymin + (ymax-ymin) * (j-.5_wp) / resol
5783
5784             dz1 = 0._wp
5785             dz2 = boxsize(1)/uvec(1)
5786
5787             IF ( uvec(2) > 0._wp )  THEN
5788                dy1 = -yorig             / uvec(2) !< crossing with y=0
5789                dy2 = (boxsize(2)-yorig) / uvec(2) !< crossing with y=boxsize(2)
5790             ELSE !uvec(2)==0
5791                dy1 = -huge(1._wp)
5792                dy2 = huge(1._wp)
5793             ENDIF
5794
5795             IF ( uvec(3) > 0._wp )  THEN
5796                dx1 = -xorig             / uvec(3) !< crossing with x=0
5797                dx2 = (boxsize(3)-xorig) / uvec(3) !< crossing with x=boxsize(3)
5798             ELSE !uvec(3)==0
5799                dx1 = -huge(1._wp)
5800                dx2 = huge(1._wp)
5801             ENDIF
5802
5803             crdist = max(0._wp, (min(dz2, dy2, dx2) - max(dz1, dy1, dx1)))
5804             transp = transp + exp(-ext_coef * dens * crdist)
5805          ENDDO
5806       ENDDO
5807       transp = transp / resol**2
5808       area = (boxsize(3)+xshift)*(boxsize(2)+yshift)
5809       absorb = 1._wp - transp
5810
5811    END SUBROUTINE box_absorb
5812
5813!------------------------------------------------------------------------------!
5814! Description:
5815! ------------
5816!> This subroutine splits direct and diffusion dw radiation
5817!> It sould not be called in case the radiation model already does it
5818!> It follows <CITATION>
5819!------------------------------------------------------------------------------!
5820    SUBROUTINE calc_diffusion_radiation 
5821   
5822        REAL(wp), PARAMETER                          :: lowest_solarUp = 0.1_wp  !< limit the sun elevation to protect stability of the calculation
5823        INTEGER(iwp)                                 :: i, j
5824        REAL(wp)                                     ::  year_angle              !< angle
5825        REAL(wp)                                     ::  etr                     !< extraterestrial radiation
5826        REAL(wp)                                     ::  corrected_solarUp       !< corrected solar up radiation
5827        REAL(wp)                                     ::  horizontalETR           !< horizontal extraterestrial radiation
5828        REAL(wp)                                     ::  clearnessIndex          !< clearness index
5829        REAL(wp)                                     ::  diff_frac               !< diffusion fraction of the radiation
5830
5831       
5832!--     Calculate current day and time based on the initial values and simulation time
5833        year_angle = ( (day_of_year_init * 86400) + time_utc_init              &
5834                        + time_since_reference_point )  * d_seconds_year       &
5835                        * 2.0_wp * pi
5836       
5837        etr = solar_constant * (1.00011_wp +                                   &
5838                          0.034221_wp * cos(year_angle) +                      &
5839                          0.001280_wp * sin(year_angle) +                      &
5840                          0.000719_wp * cos(2.0_wp * year_angle) +             &
5841                          0.000077_wp * sin(2.0_wp * year_angle))
5842       
5843!--   
5844!--     Under a very low angle, we keep extraterestrial radiation at
5845!--     the last small value, therefore the clearness index will be pushed
5846!--     towards 0 while keeping full continuity.
5847!--   
5848        IF ( zenith(0) <= lowest_solarUp )  THEN
5849            corrected_solarUp = lowest_solarUp
5850        ELSE
5851            corrected_solarUp = zenith(0)
5852        ENDIF
5853       
5854        horizontalETR = etr * corrected_solarUp
5855       
5856        DO i = nxl, nxr
5857            DO j = nys, nyn
5858                clearnessIndex = rad_sw_in(0,j,i) / horizontalETR
5859                diff_frac = 1.0_wp / (1.0_wp + exp(-5.0033_wp + 8.6025_wp * clearnessIndex))
5860                rad_sw_in_diff(j,i) = rad_sw_in(0,j,i) * diff_frac
5861                rad_sw_in_dir(j,i)  = rad_sw_in(0,j,i) * (1.0_wp - diff_frac)
5862                rad_lw_in_diff(j,i) = rad_lw_in(0,j,i)
5863            ENDDO
5864        ENDDO
5865       
5866    END SUBROUTINE calc_diffusion_radiation
5867
5868
5869 END SUBROUTINE radiation_interaction
5870   
5871!------------------------------------------------------------------------------!
5872! Description:
5873! ------------
5874!> This subroutine initializes structures needed for radiative transfer
5875!> model. This model calculates transformation processes of the
5876!> radiation inside urban and land canopy layer. The module includes also
5877!> the interaction of the radiation with the resolved plant canopy.
5878!>
5879!> For more info. see Resler et al. 2017
5880!>
5881!> The new version 2.0 was radically rewriten, the discretization scheme
5882!> has been changed. This new version significantly improves effectivity
5883!> of the paralelization and the scalability of the model.
5884!>
5885!------------------------------------------------------------------------------!
5886    SUBROUTINE radiation_interaction_init
5887
5888       USE control_parameters,                                                 &
5889           ONLY:  dz_stretch_level_start
5890           
5891       USE netcdf_data_input_mod,                                              &
5892           ONLY:  leaf_area_density_f
5893
5894       USE plant_canopy_model_mod,                                             &
5895           ONLY:  pch_index, lad_s
5896
5897       IMPLICIT NONE
5898
5899       INTEGER(iwp) :: i, j, k, l, m, d
5900       INTEGER(iwp) :: k_topo     !< vertical index indicating topography top for given (j,i)
5901       INTEGER(iwp) :: nzptl, nzubl, nzutl, isurf, ipcgb, imrt
5902       REAL(wp)     :: mrl
5903#if defined( __parallel )
5904       INTEGER(iwp), DIMENSION(:), POINTER       ::  gridsurf_rma   !< fortran pointer, but lower bounds are 1
5905       TYPE(c_ptr)                               ::  gridsurf_rma_p !< allocated c pointer
5906       INTEGER(iwp)                              ::  minfo          !< MPI RMA window info handle
5907#endif
5908
5909!
5910!--     precalculate face areas for different face directions using normal vector
5911        DO d = 0, nsurf_type
5912            facearea(d) = 1._wp
5913            IF ( idir(d) == 0 ) facearea(d) = facearea(d) * dx
5914            IF ( jdir(d) == 0 ) facearea(d) = facearea(d) * dy
5915            IF ( kdir(d) == 0 ) facearea(d) = facearea(d) * dz(1)
5916        ENDDO
5917!
5918!--    Find nzub, nzut, nzu via wall_flag_0 array (nzb_s_inner will be
5919!--    removed later). The following contruct finds the lowest / largest index
5920!--    for any upward-facing wall (see bit 12).
5921       nzubl = MINVAL( get_topography_top_index( 's' ) )
5922       nzutl = MAXVAL( get_topography_top_index( 's' ) )
5923
5924       nzubl = MAX( nzubl, nzb )
5925
5926       IF ( plant_canopy )  THEN
5927!--        allocate needed arrays
5928           ALLOCATE( pct(nys:nyn,nxl:nxr) )
5929           ALLOCATE( pch(nys:nyn,nxl:nxr) )
5930
5931!--        calculate plant canopy height
5932           npcbl = 0
5933           pct   = 0
5934           pch   = 0
5935           DO i = nxl, nxr
5936               DO j = nys, nyn
5937!
5938!--                Find topography top index
5939                   k_topo = get_topography_top_index_ji( j, i, 's' )
5940
5941                   DO k = nzt+1, 0, -1
5942                       IF ( lad_s(k,j,i) /= 0.0_wp )  THEN
5943!--                        we are at the top of the pcs
5944                           pct(j,i) = k + k_topo
5945                           pch(j,i) = k
5946                           npcbl = npcbl + pch(j,i)
5947                           EXIT
5948                       ENDIF
5949                   ENDDO
5950               ENDDO
5951           ENDDO
5952
5953           nzutl = MAX( nzutl, MAXVAL( pct ) )
5954           nzptl = MAXVAL( pct )
5955!--        code of plant canopy model uses parameter pch_index
5956!--        we need to setup it here to right value
5957!--        (pch_index, lad_s and other arrays in PCM are defined flat)
5958           pch_index = MERGE( leaf_area_density_f%nz - 1, MAXVAL( pch ),       &
5959                              leaf_area_density_f%from_file )
5960
5961           prototype_lad = MAXVAL( lad_s ) * .9_wp  !< better be *1.0 if lad is either 0 or maxval(lad) everywhere
5962           IF ( prototype_lad <= 0._wp ) prototype_lad = .3_wp
5963           !WRITE(message_string, '(a,f6.3)') 'Precomputing effective box optical ' &
5964           !    // 'depth using prototype leaf area density = ', prototype_lad
5965           !CALL message('radiation_interaction_init', 'PA0520', 0, 0, -1, 6, 0)
5966       ENDIF
5967
5968       nzutl = MIN( nzutl + nzut_free, nzt )
5969
5970#if defined( __parallel )
5971       CALL MPI_AllReduce(nzubl, nzub, 1, MPI_INTEGER, MPI_MIN, comm2d, ierr )
5972       IF ( ierr /= 0 ) THEN
5973           WRITE(9,*) 'Error MPI_AllReduce11:', ierr, nzubl, nzub
5974           FLUSH(9)
5975       ENDIF
5976       CALL MPI_AllReduce(nzutl, nzut, 1, MPI_INTEGER, MPI_MAX, comm2d, ierr )
5977       IF ( ierr /= 0 ) THEN
5978           WRITE(9,*) 'Error MPI_AllReduce12:', ierr, nzutl, nzut
5979           FLUSH(9)
5980       ENDIF
5981       CALL MPI_AllReduce(nzptl, nzpt, 1, MPI_INTEGER, MPI_MAX, comm2d, ierr )
5982       IF ( ierr /= 0 ) THEN
5983           WRITE(9,*) 'Error MPI_AllReduce13:', ierr, nzptl, nzpt
5984           FLUSH(9)
5985       ENDIF
5986#else
5987       nzub = nzubl
5988       nzut = nzutl
5989       nzpt = nzptl
5990#endif
5991!
5992!--    Stretching (non-uniform grid spacing) is not considered in the radiation
5993!--    model. Therefore, vertical stretching has to be applied above the area
5994!--    where the parts of the radiation model which assume constant grid spacing
5995!--    are active. ABS (...) is required because the default value of
5996!--    dz_stretch_level_start is -9999999.9_wp (negative).
5997       IF ( ABS( dz_stretch_level_start(1) ) <= zw(nzut) ) THEN
5998          WRITE( message_string, * ) 'The lowest level where vertical ',       &
5999                                     'stretching is applied have to be ',      &
6000                                     'greater than ', zw(nzut)
6001          CALL message( 'radiation_interaction_init', 'PA0496', 1, 2, 0, 6, 0 )
6002       ENDIF 
6003!
6004!--    global number of urban and plant layers
6005       nzu = nzut - nzub + 1
6006       nzp = nzpt - nzub + 1
6007!
6008!--    check max_raytracing_dist relative to urban surface layer height
6009       mrl = 2.0_wp * nzu * dz(1)
6010!--    set max_raytracing_dist to double the urban surface layer height, if not set
6011       IF ( max_raytracing_dist == -999.0_wp ) THEN
6012          max_raytracing_dist = mrl
6013       ENDIF
6014!--    check if max_raytracing_dist set too low (here we only warn the user. Other
6015!      option is to correct the value again to double the urban surface layer height)
6016       IF ( max_raytracing_dist  <  mrl ) THEN
6017          WRITE(message_string, '(a,f6.1)') 'Max_raytracing_dist is set less than ', &
6018               'double the urban surface layer height, i.e. ', mrl
6019          CALL message('radiation_interaction_init', 'PA0521', 0, 0, -1, 6, 0)
6020       ENDIF
6021!        IF ( max_raytracing_dist <= mrl ) THEN
6022!           IF ( max_raytracing_dist /= -999.0_wp ) THEN
6023! !--          max_raytracing_dist too low
6024!              WRITE(message_string, '(a,f6.1)') 'Max_raytracing_dist too low, ' &
6025!                    // 'override to value ', mrl
6026!              CALL message('radiation_interaction_init', 'PA0521', 0, 0, -1, 6, 0)
6027!           ENDIF
6028!           max_raytracing_dist = mrl
6029!        ENDIF
6030!
6031!--    allocate urban surfaces grid
6032!--    calc number of surfaces in local proc
6033       CALL location_message( '    calculation of indices for surfaces', .TRUE. )
6034       nsurfl = 0
6035!
6036!--    Number of horizontal surfaces including land- and roof surfaces in both USM and LSM. Note that
6037!--    All horizontal surface elements are already counted in surface_mod.
6038       startland = 1
6039       nsurfl    = surf_usm_h%ns + surf_lsm_h%ns
6040       endland   = nsurfl
6041       nlands    = endland - startland + 1
6042
6043!
6044!--    Number of vertical surfaces in both USM and LSM. Note that all vertical surface elements are
6045!--    already counted in surface_mod.
6046       startwall = nsurfl+1
6047       DO  i = 0,3
6048          nsurfl = nsurfl + surf_usm_v(i)%ns + surf_lsm_v(i)%ns
6049       ENDDO
6050       endwall = nsurfl
6051       nwalls  = endwall - startwall + 1
6052       dirstart = (/ startland, startwall, startwall, startwall, startwall /)
6053       dirend = (/ endland, endwall, endwall, endwall, endwall /)
6054
6055!--    fill gridpcbl and pcbl
6056       IF ( npcbl > 0 )  THEN
6057           ALLOCATE( pcbl(iz:ix, 1:npcbl) )
6058           ALLOCATE( gridpcbl(nzub:nzpt,nys:nyn,nxl:nxr) )
6059           pcbl = -1
6060           gridpcbl(:,:,:) = 0
6061           ipcgb = 0
6062           DO i = nxl, nxr
6063               DO j = nys, nyn
6064!
6065!--                Find topography top index
6066                   k_topo = get_topography_top_index_ji( j, i, 's' )
6067
6068                   DO k = k_topo + 1, pct(j,i)
6069                       ipcgb = ipcgb + 1
6070                       gridpcbl(k,j,i) = ipcgb
6071                       pcbl(:,ipcgb) = (/ k, j, i /)
6072                   ENDDO
6073               ENDDO
6074           ENDDO
6075           ALLOCATE( pcbinsw( 1:npcbl ) )
6076           ALLOCATE( pcbinswdir( 1:npcbl ) )
6077           ALLOCATE( pcbinswdif( 1:npcbl ) )
6078           ALLOCATE( pcbinlw( 1:npcbl ) )
6079       ENDIF
6080
6081!--    fill surfl (the ordering of local surfaces given by the following
6082!--    cycles must not be altered, certain file input routines may depend
6083!--    on it)
6084       ALLOCATE(surfl_l(5*nsurfl))  ! is it necessary to allocate it with (5,nsurfl)?
6085       surfl(1:5,1:nsurfl) => surfl_l(1:5*nsurfl)
6086       isurf = 0
6087       IF ( rad_angular_discretization )  THEN
6088!
6089!--       Allocate and fill the reverse indexing array gridsurf
6090#if defined( __parallel )
6091!
6092!--       raytrace_mpi_rma is asserted
6093
6094          CALL MPI_Info_create(minfo, ierr)
6095          IF ( ierr /= 0 ) THEN
6096              WRITE(9,*) 'Error MPI_Info_create1:', ierr
6097              FLUSH(9)
6098          ENDIF
6099          CALL MPI_Info_set(minfo, 'accumulate_ordering', '', ierr)
6100          IF ( ierr /= 0 ) THEN
6101              WRITE(9,*) 'Error MPI_Info_set1:', ierr
6102              FLUSH(9)
6103          ENDIF
6104          CALL MPI_Info_set(minfo, 'accumulate_ops', 'same_op', ierr)
6105          IF ( ierr /= 0 ) THEN
6106              WRITE(9,*) 'Error MPI_Info_set2:', ierr
6107              FLUSH(9)
6108          ENDIF
6109          CALL MPI_Info_set(minfo, 'same_size', 'true', ierr)
6110          IF ( ierr /= 0 ) THEN
6111              WRITE(9,*) 'Error MPI_Info_set3:', ierr
6112              FLUSH(9)
6113          ENDIF
6114          CALL MPI_Info_set(minfo, 'same_disp_unit', 'true', ierr)
6115          IF ( ierr /= 0 ) THEN
6116              WRITE(9,*) 'Error MPI_Info_set4:', ierr
6117              FLUSH(9)
6118          ENDIF
6119
6120          CALL MPI_Win_allocate(INT(STORAGE_SIZE(1_iwp)/8*nsurf_type_u*nzu*nny*nnx, &
6121                                    kind=MPI_ADDRESS_KIND), STORAGE_SIZE(1_iwp)/8,  &
6122                                minfo, comm2d, gridsurf_rma_p, win_gridsurf, ierr)
6123          IF ( ierr /= 0 ) THEN
6124              WRITE(9,*) 'Error MPI_Win_allocate1:', ierr, &
6125                 INT(STORAGE_SIZE(1_iwp)/8*nsurf_type_u*nzu*nny*nnx,kind=MPI_ADDRESS_KIND), &
6126                 STORAGE_SIZE(1_iwp)/8, win_gridsurf
6127              FLUSH(9)
6128          ENDIF
6129
6130          CALL MPI_Info_free(minfo, ierr)
6131          IF ( ierr /= 0 ) THEN
6132              WRITE(9,*) 'Error MPI_Info_free1:', ierr
6133              FLUSH(9)
6134          ENDIF
6135
6136!
6137!--       On Intel compilers, calling c_f_pointer to transform a C pointer
6138!--       directly to a multi-dimensional Fotran pointer leads to strange
6139!--       errors on dimension boundaries. However, transforming to a 1D
6140!--       pointer and then redirecting a multidimensional pointer to it works
6141!--       fine.
6142          CALL c_f_pointer(gridsurf_rma_p, gridsurf_rma, (/ nsurf_type_u*nzu*nny*nnx /))
6143          gridsurf(0:nsurf_type_u-1, nzub:nzut, nys:nyn, nxl:nxr) =>                &
6144                     gridsurf_rma(1:nsurf_type_u*nzu*nny*nnx)
6145#else
6146          ALLOCATE(gridsurf(0:nsurf_type_u-1,nzub:nzut,nys:nyn,nxl:nxr) )
6147#endif
6148          gridsurf(:,:,:,:) = -999
6149       ENDIF
6150
6151!--    add horizontal surface elements (land and urban surfaces)
6152!--    TODO: add urban overhanging surfaces (idown_u)
6153       DO i = nxl, nxr
6154           DO j = nys, nyn
6155              DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
6156                 k = surf_usm_h%k(m)
6157                 isurf = isurf + 1
6158                 surfl(:,isurf) = (/iup_u,k,j,i,m/)
6159                 IF ( rad_angular_discretization ) THEN
6160                    gridsurf(iup_u,k,j,i) = isurf
6161                 ENDIF
6162              ENDDO
6163
6164              DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6165                 k = surf_lsm_h%k(m)
6166                 isurf = isurf + 1
6167                 surfl(:,isurf) = (/iup_l,k,j,i,m/)
6168                 IF ( rad_angular_discretization ) THEN
6169                    gridsurf(iup_u,k,j,i) = isurf
6170                 ENDIF
6171              ENDDO
6172
6173           ENDDO
6174       ENDDO
6175
6176!--    add vertical surface elements (land and urban surfaces)
6177!--    TODO: remove the hard coding of l = 0 to l = idirection
6178       DO i = nxl, nxr
6179           DO j = nys, nyn
6180              l = 0
6181              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6182                 k = surf_usm_v(l)%k(m)
6183                 isurf = isurf + 1
6184                 surfl(:,isurf) = (/inorth_u,k,j,i,m/)
6185                 IF ( rad_angular_discretization ) THEN
6186                    gridsurf(inorth_u,k,j,i) = isurf
6187                 ENDIF
6188              ENDDO
6189              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6190                 k = surf_lsm_v(l)%k(m)
6191                 isurf = isurf + 1
6192                 surfl(:,isurf) = (/inorth_l,k,j,i,m/)
6193                 IF ( rad_angular_discretization ) THEN
6194                    gridsurf(inorth_u,k,j,i) = isurf
6195                 ENDIF
6196              ENDDO
6197
6198              l = 1
6199              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6200                 k = surf_usm_v(l)%k(m)
6201                 isurf = isurf + 1
6202                 surfl(:,isurf) = (/isouth_u,k,j,i,m/)
6203                 IF ( rad_angular_discretization ) THEN
6204                    gridsurf(isouth_u,k,j,i) = isurf
6205                 ENDIF
6206              ENDDO
6207              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6208                 k = surf_lsm_v(l)%k(m)
6209                 isurf = isurf + 1
6210                 surfl(:,isurf) = (/isouth_l,k,j,i,m/)
6211                 IF ( rad_angular_discretization ) THEN
6212                    gridsurf(isouth_u,k,j,i) = isurf
6213                 ENDIF
6214              ENDDO
6215
6216              l = 2
6217              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6218                 k = surf_usm_v(l)%k(m)
6219                 isurf = isurf + 1
6220                 surfl(:,isurf) = (/ieast_u,k,j,i,m/)
6221                 IF ( rad_angular_discretization ) THEN
6222                    gridsurf(ieast_u,k,j,i) = isurf
6223                 ENDIF
6224              ENDDO
6225              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6226                 k = surf_lsm_v(l)%k(m)
6227                 isurf = isurf + 1
6228                 surfl(:,isurf) = (/ieast_l,k,j,i,m/)
6229                 IF ( rad_angular_discretization ) THEN
6230                    gridsurf(ieast_u,k,j,i) = isurf
6231                 ENDIF
6232              ENDDO
6233
6234              l = 3
6235              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6236                 k = surf_usm_v(l)%k(m)
6237                 isurf = isurf + 1
6238                 surfl(:,isurf) = (/iwest_u,k,j,i,m/)
6239                 IF ( rad_angular_discretization ) THEN
6240                    gridsurf(iwest_u,k,j,i) = isurf
6241                 ENDIF
6242              ENDDO
6243              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6244                 k = surf_lsm_v(l)%k(m)
6245                 isurf = isurf + 1
6246                 surfl(:,isurf) = (/iwest_l,k,j,i,m/)
6247                 IF ( rad_angular_discretization ) THEN
6248                    gridsurf(iwest_u,k,j,i) = isurf
6249                 ENDIF
6250              ENDDO
6251           ENDDO
6252       ENDDO
6253!
6254!--    Add local MRT boxes for specified number of levels
6255       nmrtbl = 0
6256       IF ( mrt_nlevels > 0 )  THEN
6257          DO  i = nxl, nxr
6258             DO  j = nys, nyn
6259                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
6260!
6261!--                Skip roof if requested
6262                   IF ( mrt_skip_roof  .AND.  surf_usm_h%isroof_surf(m) )  CYCLE
6263!
6264!--                Cycle over specified no of levels
6265                   nmrtbl = nmrtbl + mrt_nlevels
6266                ENDDO
6267!
6268!--             Dtto for LSM
6269                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6270                   nmrtbl = nmrtbl + mrt_nlevels
6271                ENDDO
6272             ENDDO
6273          ENDDO
6274
6275          ALLOCATE( mrtbl(iz:ix,nmrtbl), mrtsky(nmrtbl), mrtskyt(nmrtbl), &
6276                    mrtinsw(nmrtbl), mrtinlw(nmrtbl), mrt(nmrtbl) )
6277
6278          imrt = 0
6279          DO  i = nxl, nxr
6280             DO  j = nys, nyn
6281                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
6282!
6283!--                Skip roof if requested
6284                   IF ( mrt_skip_roof  .AND.  surf_usm_h%isroof_surf(m) )  CYCLE
6285!
6286!--                Cycle over specified no of levels
6287                   l = surf_usm_h%k(m)
6288                   DO  k = l, l + mrt_nlevels - 1
6289                      imrt = imrt + 1
6290                      mrtbl(:,imrt) = (/k,j,i/)
6291                   ENDDO
6292                ENDDO
6293!
6294!--             Dtto for LSM
6295                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6296                   l = surf_lsm_h%k(m)
6297                   DO  k = l, l + mrt_nlevels - 1
6298                      imrt = imrt + 1
6299                      mrtbl(:,imrt) = (/k,j,i/)
6300                   ENDDO
6301                ENDDO
6302             ENDDO
6303          ENDDO
6304       ENDIF
6305
6306!
6307!--    broadband albedo of the land, roof and wall surface
6308!--    for domain border and sky set artifically to 1.0
6309!--    what allows us to calculate heat flux leaving over
6310!--    side and top borders of the domain
6311       ALLOCATE ( albedo_surf(nsurfl) )
6312       albedo_surf = 1.0_wp
6313!
6314!--    Also allocate further array for emissivity with identical order of
6315!--    surface elements as radiation arrays.
6316       ALLOCATE ( emiss_surf(nsurfl)  )
6317
6318
6319!
6320!--    global array surf of indices of surfaces and displacement index array surfstart
6321       ALLOCATE(nsurfs(0:numprocs-1))
6322
6323#if defined( __parallel )
6324       CALL MPI_Allgather(nsurfl,1,MPI_INTEGER,nsurfs,1,MPI_INTEGER,comm2d,ierr)
6325       IF ( ierr /= 0 ) THEN
6326         WRITE(9,*) 'Error MPI_AllGather1:', ierr, nsurfl, nsurfs
6327         FLUSH(9)
6328     ENDIF
6329
6330#else
6331       nsurfs(0) = nsurfl
6332#endif
6333       ALLOCATE(surfstart(0:numprocs))
6334       k = 0
6335       DO i=0,numprocs-1
6336           surfstart(i) = k
6337           k = k+nsurfs(i)
6338       ENDDO
6339       surfstart(numprocs) = k
6340       nsurf = k
6341       ALLOCATE(surf_l(5*nsurf))
6342       surf(1:5,1:nsurf) => surf_l(1:5*nsurf)
6343
6344#if defined( __parallel )
6345       CALL MPI_AllGatherv(surfl_l, nsurfl*5, MPI_INTEGER, surf_l, nsurfs*5, &
6346           surfstart(0:numprocs-1)*5, MPI_INTEGER, comm2d, ierr)
6347       IF ( ierr /= 0 ) THEN
6348           WRITE(9,*) 'Error MPI_AllGatherv4:', ierr, SIZE(surfl_l), nsurfl*5, &
6349                      SIZE(surf_l), nsurfs*5, surfstart(0:numprocs-1)*5
6350           FLUSH(9)
6351       ENDIF
6352#else
6353       surf = surfl
6354#endif
6355
6356!--
6357!--    allocation of the arrays for direct and diffusion radiation
6358       CALL location_message( '    allocation of radiation arrays', .TRUE. )
6359!--    rad_sw_in, rad_lw_in are computed in radiation model,
6360!--    splitting of direct and diffusion part is done
6361!--    in calc_diffusion_radiation for now
6362
6363       ALLOCATE( rad_sw_in_dir(nysg:nyng,nxlg:nxrg) )
6364       ALLOCATE( rad_sw_in_diff(nysg:nyng,nxlg:nxrg) )
6365       ALLOCATE( rad_lw_in_diff(nysg:nyng,nxlg:nxrg) )
6366       rad_sw_in_dir  = 0.0_wp
6367       rad_sw_in_diff = 0.0_wp
6368       rad_lw_in_diff = 0.0_wp
6369
6370!--    allocate radiation arrays
6371       ALLOCATE( surfins(nsurfl) )
6372       ALLOCATE( surfinl(nsurfl) )
6373       ALLOCATE( surfinsw(nsurfl) )
6374       ALLOCATE( surfinlw(nsurfl) )
6375       ALLOCATE( surfinswdir(nsurfl) )
6376       ALLOCATE( surfinswdif(nsurfl) )
6377       ALLOCATE( surfinlwdif(nsurfl) )
6378       ALLOCATE( surfoutsl(nsurfl) )
6379       ALLOCATE( surfoutll(nsurfl) )
6380       ALLOCATE( surfoutsw(nsurfl) )
6381       ALLOCATE( surfoutlw(nsurfl) )
6382       ALLOCATE( surfouts(nsurf) )
6383       ALLOCATE( surfoutl(nsurf) )
6384       ALLOCATE( surfinlg(nsurf) )
6385       ALLOCATE( skyvf(nsurfl) )
6386       ALLOCATE( skyvft(nsurfl) )
6387       ALLOCATE( surfemitlwl(nsurfl) )
6388
6389!
6390!--    In case of average_radiation, aggregated surface albedo and emissivity,
6391!--    also set initial value for t_rad_urb.
6392!--    For now set an arbitrary initial value.
6393       IF ( average_radiation )  THEN
6394          albedo_urb = 0.1_wp
6395          emissivity_urb = 0.9_wp
6396          t_rad_urb = pt_surface
6397       ENDIF
6398
6399    END SUBROUTINE radiation_interaction_init
6400
6401!------------------------------------------------------------------------------!
6402! Description:
6403! ------------
6404!> Calculates shape view factors (SVF), plant sink canopy factors (PCSF),
6405!> sky-view factors, discretized path for direct solar radiation, MRT factors
6406!> and other preprocessed data needed for radiation_interaction.
6407!------------------------------------------------------------------------------!
6408    SUBROUTINE radiation_calc_svf
6409   
6410        IMPLICIT NONE
6411       
6412        INTEGER(iwp)                                  :: i, j, k, d, ip, jp
6413        INTEGER(iwp)                                  :: isvf, ksvf, icsf, kcsf, npcsfl, isvf_surflt, imrt, imrtf, ipcgb
6414        INTEGER(iwp)                                  :: sd, td
6415        INTEGER(iwp)                                  :: iaz, izn      !< azimuth, zenith counters
6416        INTEGER(iwp)                                  :: naz, nzn      !< azimuth, zenith num of steps
6417        REAL(wp)                                      :: az0, zn0      !< starting azimuth/zenith
6418        REAL(wp)                                      :: azs, zns      !< azimuth/zenith cycle step
6419        REAL(wp)                                      :: az1, az2      !< relative azimuth of section borders
6420        REAL(wp)                                      :: azmid         !< ray (center) azimuth
6421        REAL(wp)                                      :: yxlen         !< |yxdir|
6422        REAL(wp), DIMENSION(2)                        :: yxdir         !< y,x *unit* vector of ray direction (in grid units)
6423        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zdirs         !< directions in z (tangent of elevation)
6424        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zcent         !< zenith angle centers
6425        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zbdry         !< zenith angle boundaries
6426        REAL(wp), DIMENSION(:), ALLOCATABLE           :: vffrac        !< view factor fractions for individual rays
6427        REAL(wp), DIMENSION(:), ALLOCATABLE           :: vffrac0       !< dtto (original values)
6428        REAL(wp), DIMENSION(:), ALLOCATABLE           :: ztransp       !< array of transparency in z steps
6429        INTEGER(iwp)                                  :: lowest_free_ray !< index into zdirs
6430        INTEGER(iwp), DIMENSION(:), ALLOCATABLE       :: itarget       !< face indices of detected obstacles
6431        INTEGER(iwp)                                  :: itarg0, itarg1
6432
6433        INTEGER(iwp)                                  :: udim
6434        INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET:: nzterrl_l
6435        INTEGER(iwp), DIMENSION(:,:), POINTER         :: nzterrl
6436        REAL(wp),     DIMENSION(:), ALLOCATABLE,TARGET:: csflt_l, pcsflt_l
6437        REAL(wp),     DIMENSION(:,:), POINTER         :: csflt, pcsflt
6438        INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET:: kcsflt_l,kpcsflt_l
6439        INTEGER(iwp), DIMENSION(:,:), POINTER         :: kcsflt,kpcsflt
6440        INTEGER(iwp), DIMENSION(:), ALLOCATABLE       :: icsflt,dcsflt,ipcsflt,dpcsflt
6441        REAL(wp), DIMENSION(3)                        :: uv
6442        LOGICAL                                       :: visible
6443        REAL(wp), DIMENSION(3)                        :: sa, ta          !< real coordinates z,y,x of source and target
6444        REAL(wp)                                      :: difvf           !< differential view factor
6445        REAL(wp)                                      :: transparency, rirrf, sqdist, svfsum
6446        INTEGER(iwp)                                  :: isurflt, isurfs, isurflt_prev
6447        INTEGER(idp)                                  :: ray_skip_maxdist, ray_skip_minval !< skipped raytracing counts
6448        INTEGER(iwp)                                  :: max_track_len !< maximum 2d track length
6449        INTEGER(iwp)                                  :: minfo
6450        REAL(wp), DIMENSION(:), POINTER               :: lad_s_rma       !< fortran 1D pointer
6451        TYPE(c_ptr)                                   :: lad_s_rma_p     !< allocated c pointer
6452#if defined( __parallel )
6453        INTEGER(kind=MPI_ADDRESS_KIND)                :: size_lad_rma
6454#endif
6455!   
6456        INTEGER(iwp), DIMENSION(0:svfnorm_report_num) :: svfnorm_counts
6457        CHARACTER(200)                                :: msg
6458
6459!--     calculation of the SVF
6460        CALL location_message( '    calculation of SVF and CSF', .TRUE. )
6461        CALL radiation_write_debug_log('Start calculation of SVF and CSF')
6462
6463!--     initialize variables and temporary arrays for calculation of svf and csf
6464        nsvfl  = 0
6465        ncsfl  = 0
6466        nsvfla = gasize
6467        msvf   = 1
6468        ALLOCATE( asvf1(nsvfla) )
6469        asvf => asvf1
6470        IF ( plant_canopy )  THEN
6471            ncsfla = gasize
6472            mcsf   = 1
6473            ALLOCATE( acsf1(ncsfla) )
6474            acsf => acsf1
6475        ENDIF
6476        nmrtf = 0
6477        IF ( mrt_nlevels > 0 )  THEN
6478           nmrtfa = gasize
6479           mmrtf = 1
6480           ALLOCATE ( amrtf1(nmrtfa) )
6481           amrtf => amrtf1
6482        ENDIF
6483        ray_skip_maxdist = 0
6484        ray_skip_minval = 0
6485       
6486!--     initialize temporary terrain and plant canopy height arrays (global 2D array!)
6487        ALLOCATE( nzterr(0:(nx+1)*(ny+1)-1) )
6488#if defined( __parallel )
6489        !ALLOCATE( nzterrl(nys:nyn,nxl:nxr) )
6490        ALLOCATE( nzterrl_l((nyn-nys+1)*(nxr-nxl+1)) )
6491        nzterrl(nys:nyn,nxl:nxr) => nzterrl_l(1:(nyn-nys+1)*(nxr-nxl+1))
6492        nzterrl = get_topography_top_index( 's' )
6493        CALL MPI_AllGather( nzterrl_l, nnx*nny, MPI_INTEGER, &
6494                            nzterr, nnx*nny, MPI_INTEGER, comm2d, ierr )
6495        IF ( ierr /= 0 ) THEN
6496            WRITE(9,*) 'Error MPI_AllGather1:', ierr, SIZE(nzterrl_l), nnx*nny, &
6497                       SIZE(nzterr), nnx*nny
6498            FLUSH(9)
6499        ENDIF
6500        DEALLOCATE(nzterrl_l)
6501#else
6502        nzterr = RESHAPE( get_topography_top_index( 's' ), (/(nx+1)*(ny+1)/) )
6503#endif
6504        IF ( plant_canopy )  THEN
6505            ALLOCATE( plantt(0:(nx+1)*(ny+1)-1) )
6506            maxboxesg = nx + ny + nzp + 1
6507            max_track_len = nx + ny + 1
6508!--         temporary arrays storing values for csf calculation during raytracing
6509            ALLOCATE( boxes(3, maxboxesg) )
6510            ALLOCATE( crlens(maxboxesg) )
6511
6512#if defined( __parallel )
6513            CALL MPI_AllGather( pct, nnx*nny, MPI_INTEGER, &
6514                                plantt, nnx*nny, MPI_INTEGER, comm2d, ierr )
6515            IF ( ierr /= 0 ) THEN
6516                WRITE(9,*) 'Error MPI_AllGather2:', ierr, SIZE(pct), nnx*nny, &
6517                           SIZE(plantt), nnx*nny
6518                FLUSH(9)
6519            ENDIF
6520
6521!--         temporary arrays storing values for csf calculation during raytracing
6522            ALLOCATE( lad_ip(maxboxesg) )
6523            ALLOCATE( lad_disp(maxboxesg) )
6524
6525            IF ( raytrace_mpi_rma )  THEN
6526                ALLOCATE( lad_s_ray(maxboxesg) )
6527               
6528                ! set conditions for RMA communication
6529                CALL MPI_Info_create(minfo, ierr)
6530                IF ( ierr /= 0 ) THEN
6531                    WRITE(9,*) 'Error MPI_Info_create2:', ierr
6532                    FLUSH(9)
6533                ENDIF
6534                CALL MPI_Info_set(minfo, 'accumulate_ordering', '', ierr)
6535                IF ( ierr /= 0 ) THEN
6536                    WRITE(9,*) 'Error MPI_Info_set5:', ierr
6537                    FLUSH(9)
6538                ENDIF
6539                CALL MPI_Info_set(minfo, 'accumulate_ops', 'same_op', ierr)
6540                IF ( ierr /= 0 ) THEN
6541                    WRITE(9,*) 'Error MPI_Info_set6:', ierr
6542                    FLUSH(9)
6543                ENDIF
6544                CALL MPI_Info_set(minfo, 'same_size', 'true', ierr)
6545                IF ( ierr /= 0 ) THEN
6546                    WRITE(9,*) 'Error MPI_Info_set7:', ierr
6547                    FLUSH(9)
6548                ENDIF
6549                CALL MPI_Info_set(minfo, 'same_disp_unit', 'true', ierr)
6550                IF ( ierr /= 0 ) THEN
6551                    WRITE(9,*) 'Error MPI_Info_set8:', ierr
6552                    FLUSH(9)
6553                ENDIF
6554
6555!--             Allocate and initialize the MPI RMA window
6556!--             must be in accordance with allocation of lad_s in plant_canopy_model
6557!--             optimization of memory should be done
6558!--             Argument X of function STORAGE_SIZE(X) needs arbitrary REAL(wp) value, set to 1.0_wp for now
6559                size_lad_rma = STORAGE_SIZE(1.0_wp)/8*nnx*nny*nzp
6560                CALL MPI_Win_allocate(size_lad_rma, STORAGE_SIZE(1.0_wp)/8, minfo, comm2d, &
6561                                        lad_s_rma_p, win_lad, ierr)
6562                IF ( ierr /= 0 ) THEN
6563                    WRITE(9,*) 'Error MPI_Win_allocate2:', ierr, size_lad_rma, &
6564                                STORAGE_SIZE(1.0_wp)/8, win_lad
6565                    FLUSH(9)
6566                ENDIF
6567                CALL c_f_pointer(lad_s_rma_p, lad_s_rma, (/ nzp*nny*nnx /))
6568                sub_lad(nzub:nzpt, nys:nyn, nxl:nxr) => lad_s_rma(1:nzp*nny*nnx)
6569            ELSE
6570                ALLOCATE(sub_lad(nzub:nzpt, nys:nyn, nxl:nxr))
6571            ENDIF
6572#else
6573            plantt = RESHAPE( pct(nys:nyn,nxl:nxr), (/(nx+1)*(ny+1)/) )
6574            ALLOCATE(sub_lad(nzub:nzpt, nys:nyn, nxl:nxr))
6575#endif
6576            plantt_max = MAXVAL(plantt)
6577            ALLOCATE( rt2_track(2, max_track_len), rt2_track_lad(nzub:plantt_max, max_track_len), &
6578                      rt2_track_dist(0:max_track_len), rt2_dist(plantt_max-nzub+2) )
6579
6580            sub_lad(:,:,:) = 0._wp
6581            DO i = nxl, nxr
6582                DO j = nys, nyn
6583                    k = get_topography_top_index_ji( j, i, 's' )
6584
6585                    sub_lad(k:nzpt, j, i) = lad_s(0:nzpt-k, j, i)
6586                ENDDO
6587            ENDDO
6588
6589#if defined( __parallel )
6590            IF ( raytrace_mpi_rma )  THEN
6591                CALL MPI_Info_free(minfo, ierr)
6592                IF ( ierr /= 0 ) THEN
6593                    WRITE(9,*) 'Error MPI_Info_free2:', ierr
6594                    FLUSH(9)
6595                ENDIF
6596                CALL MPI_Win_lock_all(0, win_lad, ierr)
6597                IF ( ierr /= 0 ) THEN
6598                    WRITE(9,*) 'Error MPI_Win_lock_all1:', ierr, win_lad
6599                    FLUSH(9)
6600                ENDIF
6601               
6602            ELSE
6603                ALLOCATE( sub_lad_g(0:(nx+1)*(ny+1)*nzp-1) )
6604                CALL MPI_AllGather( sub_lad, nnx*nny*nzp, MPI_REAL, &
6605                                    sub_lad_g, nnx*nny*nzp, MPI_REAL, comm2d, ierr )
6606                IF ( ierr /= 0 ) THEN
6607                    WRITE(9,*) 'Error MPI_AllGather3:', ierr, SIZE(sub_lad), &
6608                                nnx*nny*nzp, SIZE(sub_lad_g), nnx*nny*nzp
6609                    FLUSH(9)
6610                ENDIF
6611            ENDIF
6612#endif
6613        ENDIF
6614
6615!--     prepare the MPI_Win for collecting the surface indices
6616!--     from the reverse index arrays gridsurf from processors of target surfaces
6617#if defined( __parallel )
6618        IF ( rad_angular_discretization )  THEN
6619!
6620!--         raytrace_mpi_rma is asserted
6621            CALL MPI_Win_lock_all(0, win_gridsurf, ierr)
6622            IF ( ierr /= 0 ) THEN
6623                WRITE(9,*) 'Error MPI_Win_lock_all2:', ierr, win_gridsurf
6624                FLUSH(9)
6625            ENDIF
6626        ENDIF
6627#endif
6628
6629
6630        !--Directions opposite to face normals are not even calculated,
6631        !--they must be preset to 0
6632        !--
6633        dsitrans(:,:) = 0._wp
6634       
6635        DO isurflt = 1, nsurfl
6636!--         determine face centers
6637            td = surfl(id, isurflt)
6638            ta = (/ REAL(surfl(iz, isurflt), wp) - 0.5_wp * kdir(td),  &
6639                      REAL(surfl(iy, isurflt), wp) - 0.5_wp * jdir(td),  &
6640                      REAL(surfl(ix, isurflt), wp) - 0.5_wp * idir(td)  /)
6641
6642            !--Calculate sky view factor and raytrace DSI paths
6643            skyvf(isurflt) = 0._wp
6644            skyvft(isurflt) = 0._wp
6645
6646            !--Select a proper half-sphere for 2D raytracing
6647            SELECT CASE ( td )
6648               CASE ( iup_u, iup_l )
6649                  az0 = 0._wp
6650                  naz = raytrace_discrete_azims
6651                  azs = 2._wp * pi / REAL(naz, wp)
6652                  zn0 = 0._wp
6653                  nzn = raytrace_discrete_elevs / 2
6654                  zns = pi / 2._wp / REAL(nzn, wp)
6655               CASE ( isouth_u, isouth_l )
6656                  az0 = pi / 2._wp
6657                  naz = raytrace_discrete_azims / 2
6658                  azs = pi / REAL(naz, wp)
6659                  zn0 = 0._wp
6660                  nzn = raytrace_discrete_elevs
6661                  zns = pi / REAL(nzn, wp)
6662               CASE ( inorth_u, inorth_l )
6663                  az0 = - pi / 2._wp
6664                  naz = raytrace_discrete_azims / 2
6665                  azs = pi / REAL(naz, wp)
6666                  zn0 = 0._wp
6667                  nzn = raytrace_discrete_elevs
6668                  zns = pi / REAL(nzn, wp)
6669               CASE ( iwest_u, iwest_l )
6670                  az0 = pi
6671                  naz = raytrace_discrete_azims / 2
6672                  azs = pi / REAL(naz, wp)
6673                  zn0 = 0._wp
6674                  nzn = raytrace_discrete_elevs
6675                  zns = pi / REAL(nzn, wp)
6676               CASE ( ieast_u, ieast_l )
6677                  az0 = 0._wp
6678                  naz = raytrace_discrete_azims / 2
6679                  azs = pi / REAL(naz, wp)
6680                  zn0 = 0._wp
6681                  nzn = raytrace_discrete_elevs
6682                  zns = pi / REAL(nzn, wp)
6683               CASE DEFAULT
6684                  WRITE(message_string, *) 'ERROR: the surface type ', td,     &
6685                                           ' is not supported for calculating',&
6686                                           ' SVF'
6687                  CALL message( 'radiation_calc_svf', 'PA0488', 1, 2, 0, 6, 0 )
6688            END SELECT
6689
6690            ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), zbdry(0:nzn), vffrac(1:nzn*naz), &
6691                       ztransp(1:nzn*naz), itarget(1:nzn*naz) )   !FIXME allocate itarget only
6692                                                                  !in case of rad_angular_discretization
6693
6694            itarg0 = 1
6695            itarg1 = nzn
6696            zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
6697            zbdry(:) = (/( zn0+REAL(izn,wp)*zns, izn=0, nzn )/)
6698            IF ( td == iup_u  .OR.  td == iup_l )  THEN
6699               vffrac(1:nzn) = (COS(2 * zbdry(0:nzn-1)) - COS(2 * zbdry(1:nzn))) / 2._wp / REAL(naz, wp)
6700!
6701!--            For horizontal target, vf fractions are constant per azimuth
6702               DO iaz = 1, naz-1
6703                  vffrac(iaz*nzn+1:(iaz+1)*nzn) = vffrac(1:nzn)
6704               ENDDO
6705!--            sum of whole vffrac equals 1, verified
6706            ENDIF
6707!
6708!--         Calculate sky-view factor and direct solar visibility using 2D raytracing
6709            DO iaz = 1, naz
6710               azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
6711               IF ( td /= iup_u  .AND.  td /= iup_l )  THEN
6712                  az2 = REAL(iaz, wp) * azs - pi/2._wp
6713                  az1 = az2 - azs
6714                  !TODO precalculate after 1st line
6715                  vffrac(itarg0:itarg1) = (SIN(az2) - SIN(az1))               &
6716                              * (zbdry(1:nzn) - zbdry(0:nzn-1)                &
6717                                 + SIN(zbdry(0:nzn-1))*COS(zbdry(0:nzn-1))    &
6718                                 - SIN(zbdry(1:nzn))*COS(zbdry(1:nzn)))       &
6719                              / (2._wp * pi)
6720!--               sum of whole vffrac equals 1, verified
6721               ENDIF
6722               yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
6723               yxlen = SQRT(SUM(yxdir(:)**2))
6724               zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
6725               yxdir(:) = yxdir(:) / yxlen
6726
6727               CALL raytrace_2d(ta, yxdir, nzn, zdirs,                        &
6728                                    surfstart(myid) + isurflt, facearea(td),  &
6729                                    vffrac(itarg0:itarg1), .TRUE., .TRUE.,    &
6730                                    .FALSE., lowest_free_ray,                 &
6731                                    ztransp(itarg0:itarg1),                   &
6732                                    itarget(itarg0:itarg1))
6733
6734               skyvf(isurflt) = skyvf(isurflt) + &
6735                                SUM(vffrac(itarg0:itarg0+lowest_free_ray-1))
6736               skyvft(isurflt) = skyvft(isurflt) + &
6737                                 SUM(ztransp(itarg0:itarg0+lowest_free_ray-1) &
6738                                             * vffrac(itarg0:itarg0+lowest_free_ray-1))
6739 
6740!--            Save direct solar transparency
6741               j = MODULO(NINT(azmid/                                          &
6742                               (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
6743                          raytrace_discrete_azims)
6744
6745               DO k = 1, raytrace_discrete_elevs/2
6746                  i = dsidir_rev(k-1, j)
6747                  IF ( i /= -1  .AND.  k <= lowest_free_ray )  &
6748                     dsitrans(isurflt, i) = ztransp(itarg0+k-1)
6749               ENDDO
6750
6751!
6752!--            Advance itarget indices
6753               itarg0 = itarg1 + 1
6754               itarg1 = itarg1 + nzn
6755            ENDDO
6756
6757            IF ( rad_angular_discretization )  THEN
6758!--            sort itarget by face id
6759               CALL quicksort_itarget(itarget,vffrac,ztransp,1,nzn*naz)
6760!
6761!--            For aggregation, we need fractions multiplied by transmissivities
6762               ztransp(:) = vffrac(:) * ztransp(:)
6763!
6764!--            find the first valid position
6765               itarg0 = 1
6766               DO WHILE ( itarg0 <= nzn*naz )
6767                  IF ( itarget(itarg0) /= -1 )  EXIT
6768                  itarg0 = itarg0 + 1
6769               ENDDO
6770
6771               DO  i = itarg0, nzn*naz
6772!
6773!--               For duplicate values, only sum up vf fraction value
6774                  IF ( i < nzn*naz )  THEN
6775                     IF ( itarget(i+1) == itarget(i) )  THEN
6776                        vffrac(i+1) = vffrac(i+1) + vffrac(i)
6777                        ztransp(i+1) = ztransp(i+1) + ztransp(i)
6778                        CYCLE
6779                     ENDIF
6780                  ENDIF
6781!
6782!--               write to the svf array
6783                  nsvfl = nsvfl + 1
6784!--               check dimmension of asvf array and enlarge it if needed
6785                  IF ( nsvfla < nsvfl )  THEN
6786                     k = CEILING(REAL(nsvfla, kind=wp) * grow_factor)
6787                     IF ( msvf == 0 )  THEN
6788                        msvf = 1
6789                        ALLOCATE( asvf1(k) )
6790                        asvf => asvf1
6791                        asvf1(1:nsvfla) = asvf2
6792                        DEALLOCATE( asvf2 )
6793                     ELSE
6794                        msvf = 0
6795                        ALLOCATE( asvf2(k) )
6796                        asvf => asvf2
6797                        asvf2(1:nsvfla) = asvf1
6798                        DEALLOCATE( asvf1 )
6799                     ENDIF
6800
6801                     WRITE (msg,'(A,3I12)') 'Grow asvf:',nsvfl,nsvfla,k
6802                     CALL radiation_write_debug_log( msg )
6803                     
6804                     nsvfla = k
6805                  ENDIF
6806!--               write svf values into the array
6807                  asvf(nsvfl)%isurflt = isurflt
6808                  asvf(nsvfl)%isurfs = itarget(i)
6809                  asvf(nsvfl)%rsvf = vffrac(i)
6810                  asvf(nsvfl)%rtransp = ztransp(i) / vffrac(i)
6811               END DO
6812
6813            ENDIF ! rad_angular_discretization
6814
6815            DEALLOCATE ( zdirs, zcent, zbdry, vffrac, ztransp, itarget ) !FIXME itarget shall be allocated only
6816                                                                  !in case of rad_angular_discretization
6817!
6818!--         Following calculations only required for surface_reflections
6819            IF ( surface_reflections  .AND.  .NOT. rad_angular_discretization )  THEN
6820
6821               DO  isurfs = 1, nsurf
6822                  IF ( .NOT.  surface_facing(surfl(ix, isurflt), surfl(iy, isurflt), &
6823                     surfl(iz, isurflt), surfl(id, isurflt), &
6824                     surf(ix, isurfs), surf(iy, isurfs), &
6825                     surf(iz, isurfs), surf(id, isurfs)) )  THEN
6826                     CYCLE
6827                  ENDIF
6828                 
6829                  sd = surf(id, isurfs)
6830                  sa = (/ REAL(surf(iz, isurfs), wp) - 0.5_wp * kdir(sd),  &
6831                          REAL(surf(iy, isurfs), wp) - 0.5_wp * jdir(sd),  &
6832                          REAL(surf(ix, isurfs), wp) - 0.5_wp * idir(sd)  /)
6833
6834!--               unit vector source -> target
6835                  uv = (/ (ta(1)-sa(1))*dz(1), (ta(2)-sa(2))*dy, (ta(3)-sa(3))*dx /)
6836                  sqdist = SUM(uv(:)**2)
6837                  uv = uv / SQRT(sqdist)
6838
6839!--               reject raytracing above max distance
6840                  IF ( SQRT(sqdist) > max_raytracing_dist ) THEN
6841                     ray_skip_maxdist = ray_skip_maxdist + 1
6842                     CYCLE
6843                  ENDIF
6844                 
6845                  difvf = dot_product((/ kdir(sd), jdir(sd), idir(sd) /), uv) & ! cosine of source normal and direction
6846                      * dot_product((/ kdir(td), jdir(td), idir(td) /), -uv) &  ! cosine of target normal and reverse direction
6847                      / (pi * sqdist) ! square of distance between centers
6848!
6849!--               irradiance factor (our unshaded shape view factor) = view factor per differential target area * source area
6850                  rirrf = difvf * facearea(sd)
6851
6852!--               reject raytracing for potentially too small view factor values
6853                  IF ( rirrf < min_irrf_value ) THEN
6854                      ray_skip_minval = ray_skip_minval + 1
6855                      CYCLE
6856                  ENDIF
6857
6858!--               raytrace + process plant canopy sinks within
6859                  CALL raytrace(sa, ta, isurfs, difvf, facearea(td), .TRUE., &
6860                                visible, transparency)
6861
6862                  IF ( .NOT.  visible ) CYCLE
6863                 ! rsvf = rirrf * transparency
6864
6865!--               write to the svf array
6866                  nsvfl = nsvfl + 1
6867!--               check dimmension of asvf array and enlarge it if needed
6868                  IF ( nsvfla < nsvfl )  THEN
6869                     k = CEILING(REAL(nsvfla, kind=wp) * grow_factor)
6870                     IF ( msvf == 0 )  THEN
6871                        msvf = 1
6872                        ALLOCATE( asvf1(k) )
6873                        asvf => asvf1
6874                        asvf1(1:nsvfla) = asvf2
6875                        DEALLOCATE( asvf2 )
6876                     ELSE
6877                        msvf = 0
6878                        ALLOCATE( asvf2(k) )
6879                        asvf => asvf2
6880                        asvf2(1:nsvfla) = asvf1
6881                        DEALLOCATE( asvf1 )
6882                     ENDIF
6883
6884                     WRITE(msg,'(A,3I12)') 'Grow asvf:',nsvfl,nsvfla,k
6885                     CALL radiation_write_debug_log( msg )
6886                     
6887                     nsvfla = k
6888                  ENDIF
6889!--               write svf values into the array
6890                  asvf(nsvfl)%isurflt = isurflt
6891                  asvf(nsvfl)%isurfs = isurfs
6892                  asvf(nsvfl)%rsvf = rirrf !we postopne multiplication by transparency
6893                  asvf(nsvfl)%rtransp = transparency !a.k.a. Direct Irradiance Factor
6894               ENDDO
6895            ENDIF
6896        ENDDO
6897
6898!--
6899!--     Raytrace to canopy boxes to fill dsitransc TODO optimize
6900        dsitransc(:,:) = 0._wp
6901        az0 = 0._wp
6902        naz = raytrace_discrete_azims
6903        azs = 2._wp * pi / REAL(naz, wp)
6904        zn0 = 0._wp
6905        nzn = raytrace_discrete_elevs / 2
6906        zns = pi / 2._wp / REAL(nzn, wp)
6907        ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), vffrac(1:nzn), ztransp(1:nzn), &
6908               itarget(1:nzn) )
6909        zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
6910        vffrac(:) = 0._wp
6911
6912        DO  ipcgb = 1, npcbl
6913           ta = (/ REAL(pcbl(iz, ipcgb), wp),  &
6914                   REAL(pcbl(iy, ipcgb), wp),  &
6915                   REAL(pcbl(ix, ipcgb), wp) /)
6916!--        Calculate direct solar visibility using 2D raytracing
6917           DO  iaz = 1, naz
6918              azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
6919              yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
6920              yxlen = SQRT(SUM(yxdir(:)**2))
6921              zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
6922              yxdir(:) = yxdir(:) / yxlen
6923              CALL raytrace_2d(ta, yxdir, nzn, zdirs,                                &
6924                                   -999, -999._wp, vffrac, .FALSE., .FALSE., .TRUE., &
6925                                   lowest_free_ray, ztransp, itarget)
6926
6927!--           Save direct solar transparency
6928              j = MODULO(NINT(azmid/                                         &
6929                             (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
6930                         raytrace_discrete_azims)
6931              DO  k = 1, raytrace_discrete_elevs/2
6932                 i = dsidir_rev(k-1, j)
6933                 IF ( i /= -1  .AND.  k <= lowest_free_ray ) &
6934                    dsitransc(ipcgb, i) = ztransp(k)
6935              ENDDO
6936           ENDDO
6937        ENDDO
6938        DEALLOCATE ( zdirs, zcent, vffrac, ztransp, itarget )
6939!--
6940!--     Raytrace to MRT boxes
6941        IF ( nmrtbl > 0 )  THEN
6942           mrtdsit(:,:) = 0._wp
6943           mrtsky(:) = 0._wp
6944           mrtskyt(:) = 0._wp
6945           az0 = 0._wp
6946           naz = raytrace_discrete_azims
6947           azs = 2._wp * pi / REAL(naz, wp)
6948           zn0 = 0._wp
6949           nzn = raytrace_discrete_elevs
6950           zns = pi / REAL(nzn, wp)
6951           ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), zbdry(0:nzn), vffrac(1:nzn*naz), vffrac0(1:nzn), &
6952                      ztransp(1:nzn*naz), itarget(1:nzn*naz) )   !FIXME allocate itarget only
6953                                                                 !in case of rad_angular_discretization
6954
6955           zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
6956           zbdry(:) = (/( zn0+REAL(izn,wp)*zns, izn=0, nzn )/)
6957           vffrac0(:) = (COS(zbdry(0:nzn-1)) - COS(zbdry(1:nzn))) / 2._wp / REAL(naz, wp)
6958           !
6959           !--Modify direction weights to simulate human body (lower weight for top-down)
6960           IF ( mrt_geom_human )  THEN
6961              vffrac0(:) = vffrac0(:) * MAX(0._wp, SIN(zcent(:))*0.88_wp + COS(zcent(:))*0.12_wp)
6962              vffrac0(:) = vffrac0(:) / (SUM(vffrac0) * REAL(naz, wp))
6963           ENDIF
6964
6965           DO  imrt = 1, nmrtbl
6966              ta = (/ REAL(mrtbl(iz, imrt), wp),  &
6967                      REAL(mrtbl(iy, imrt), wp),  &
6968                      REAL(mrtbl(ix, imrt), wp) /)
6969!
6970!--           vf fractions are constant per azimuth
6971              DO iaz = 0, naz-1
6972                 vffrac(iaz*nzn+1:(iaz+1)*nzn) = vffrac0(:)
6973              ENDDO
6974!--           sum of whole vffrac equals 1, verified
6975              itarg0 = 1
6976              itarg1 = nzn
6977!
6978!--           Calculate sky-view factor and direct solar visibility using 2D raytracing
6979              DO  iaz = 1, naz
6980                 azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
6981                 yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
6982                 yxlen = SQRT(SUM(yxdir(:)**2))
6983                 zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
6984                 yxdir(:) = yxdir(:) / yxlen
6985
6986                 CALL raytrace_2d(ta, yxdir, nzn, zdirs,                         &
6987                                  -999, -999._wp, vffrac(itarg0:itarg1), .TRUE., &
6988                                  .FALSE., .TRUE., lowest_free_ray,              &
6989                                  ztransp(itarg0:itarg1),                        &
6990                                  itarget(itarg0:itarg1))
6991
6992!--              Sky view factors for MRT
6993                 mrtsky(imrt) = mrtsky(imrt) + &
6994                                  SUM(vffrac(itarg0:itarg0+lowest_free_ray-1))
6995                 mrtskyt(imrt) = mrtskyt(imrt) + &
6996                                   SUM(ztransp(itarg0:itarg0+lowest_free_ray-1) &
6997                                               * vffrac(itarg0:itarg0+lowest_free_ray-1))
6998!--              Direct solar transparency for MRT
6999                 j = MODULO(NINT(azmid/                                         &
7000                                (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
7001                            raytrace_discrete_azims)
7002                 DO  k = 1, raytrace_discrete_elevs/2
7003                    i = dsidir_rev(k-1, j)
7004                    IF ( i /= -1  .AND.  k <= lowest_free_ray ) &
7005                       mrtdsit(imrt, i) = ztransp(itarg0+k-1)
7006                 ENDDO
7007!
7008!--              Advance itarget indices
7009                 itarg0 = itarg1 + 1
7010                 itarg1 = itarg1 + nzn
7011              ENDDO
7012
7013!--           sort itarget by face id
7014              CALL quicksort_itarget(itarget,vffrac,ztransp,1,nzn*naz)
7015!
7016!--           find the first valid position
7017              itarg0 = 1
7018              DO WHILE ( itarg0 <= nzn*naz )
7019                 IF ( itarget(itarg0) /= -1 )  EXIT
7020                 itarg0 = itarg0 + 1
7021              ENDDO
7022
7023              DO  i = itarg0, nzn*naz
7024!
7025!--              For duplicate values, only sum up vf fraction value
7026                 IF ( i < nzn*naz )  THEN
7027                    IF ( itarget(i+1) == itarget(i) )  THEN
7028                       vffrac(i+1) = vffrac(i+1) + vffrac(i)
7029                       CYCLE
7030                    ENDIF
7031                 ENDIF
7032!
7033!--              write to the mrtf array
7034                 nmrtf = nmrtf + 1
7035!--              check dimmension of mrtf array and enlarge it if needed
7036                 IF ( nmrtfa < nmrtf )  THEN
7037                    k = CEILING(REAL(nmrtfa, kind=wp) * grow_factor)
7038                    IF ( mmrtf == 0 )  THEN
7039                       mmrtf = 1
7040                       ALLOCATE( amrtf1(k) )
7041                       amrtf => amrtf1
7042                       amrtf1(1:nmrtfa) = amrtf2
7043                       DEALLOCATE( amrtf2 )
7044                    ELSE
7045                       mmrtf = 0
7046                       ALLOCATE( amrtf2(k) )
7047                       amrtf => amrtf2
7048                       amrtf2(1:nmrtfa) = amrtf1
7049                       DEALLOCATE( amrtf1 )
7050                    ENDIF
7051
7052                    WRITE (msg,'(A,3I12)') 'Grow amrtf:', nmrtf, nmrtfa, k
7053                    CALL radiation_write_debug_log( msg )
7054
7055                    nmrtfa = k
7056                 ENDIF
7057!--              write mrtf values into the array
7058                 amrtf(nmrtf)%isurflt = imrt
7059                 amrtf(nmrtf)%isurfs = itarget(i)
7060                 amrtf(nmrtf)%rsvf = vffrac(i)
7061                 amrtf(nmrtf)%rtransp = ztransp(i)
7062              ENDDO ! itarg
7063
7064           ENDDO ! imrt
7065           DEALLOCATE ( zdirs, zcent, zbdry, vffrac, vffrac0, ztransp, itarget )
7066!
7067!--        Move MRT factors to final arrays
7068           ALLOCATE ( mrtf(nmrtf), mrtft(nmrtf), mrtfsurf(2,nmrtf) )
7069           DO  imrtf = 1, nmrtf
7070              mrtf(imrtf) = amrtf(imrtf)%rsvf
7071              mrtft(imrtf) = amrtf(imrtf)%rsvf * amrtf(imrtf)%rtransp
7072              mrtfsurf(:,imrtf) = (/amrtf(imrtf)%isurflt, amrtf(imrtf)%isurfs /)
7073           ENDDO
7074           IF ( ALLOCATED(amrtf1) )  DEALLOCATE( amrtf1 )
7075           IF ( ALLOCATED(amrtf2) )  DEALLOCATE( amrtf2 )
7076        ENDIF ! nmrtbl > 0
7077
7078        IF ( rad_angular_discretization )  THEN
7079#if defined( __parallel )
7080!--        finalize MPI_RMA communication established to get global index of the surface from grid indices
7081!--        flush all MPI window pending requests
7082           CALL MPI_Win_flush_all(win_gridsurf, ierr)
7083           IF ( ierr /= 0 ) THEN
7084               WRITE(9,*) 'Error MPI_Win_flush_all1:', ierr, win_gridsurf
7085               FLUSH(9)
7086           ENDIF
7087!--        unlock MPI window
7088           CALL MPI_Win_unlock_all(win_gridsurf, ierr)
7089           IF ( ierr /= 0 ) THEN
7090               WRITE(9,*) 'Error MPI_Win_unlock_all1:', ierr, win_gridsurf
7091               FLUSH(9)
7092           ENDIF
7093!--        free MPI window
7094           CALL MPI_Win_free(win_gridsurf, ierr)
7095           IF ( ierr /= 0 ) THEN
7096               WRITE(9,*) 'Error MPI_Win_free1:', ierr, win_gridsurf
7097               FLUSH(9)
7098           ENDIF
7099#else
7100           DEALLOCATE ( gridsurf )
7101#endif
7102        ENDIF
7103
7104        CALL radiation_write_debug_log( 'End of calculation SVF' )
7105        WRITE(msg, *) 'Raytracing skipped for maximum distance of ', &
7106           max_raytracing_dist, ' m on ', ray_skip_maxdist, ' pairs.'
7107        CALL radiation_write_debug_log( msg )
7108        WRITE(msg, *) 'Raytracing skipped for minimum potential value of ', &
7109           min_irrf_value , ' on ', ray_skip_minval, ' pairs.'
7110        CALL radiation_write_debug_log( msg )
7111
7112        CALL location_message( '    waiting for completion of SVF and CSF calculation in all processes', .TRUE. )
7113!--     deallocate temporary global arrays
7114        DEALLOCATE(nzterr)
7115       
7116        IF ( plant_canopy )  THEN
7117!--         finalize mpi_rma communication and deallocate temporary arrays
7118#if defined( __parallel )
7119            IF ( raytrace_mpi_rma )  THEN
7120                CALL MPI_Win_flush_all(win_lad, ierr)
7121                IF ( ierr /= 0 ) THEN
7122                    WRITE(9,*) 'Error MPI_Win_flush_all2:', ierr, win_lad
7123                    FLUSH(9)
7124                ENDIF
7125!--             unlock MPI window
7126                CALL MPI_Win_unlock_all(win_lad, ierr)
7127                IF ( ierr /= 0 ) THEN
7128                    WRITE(9,*) 'Error MPI_Win_unlock_all2:', ierr, win_lad
7129                    FLUSH(9)
7130                ENDIF
7131!--             free MPI window
7132                CALL MPI_Win_free(win_lad, ierr)
7133                IF ( ierr /= 0 ) THEN
7134                    WRITE(9,*) 'Error MPI_Win_free2:', ierr, win_lad
7135                    FLUSH(9)
7136                ENDIF
7137!--             deallocate temporary arrays storing values for csf calculation during raytracing
7138                DEALLOCATE( lad_s_ray )
7139!--             sub_lad is the pointer to lad_s_rma in case of raytrace_mpi_rma
7140!--             and must not be deallocated here
7141            ELSE
7142                DEALLOCATE(sub_lad)
7143                DEALLOCATE(sub_lad_g)
7144            ENDIF
7145#else
7146            DEALLOCATE(sub_lad)
7147#endif
7148            DEALLOCATE( boxes )
7149            DEALLOCATE( crlens )
7150            DEALLOCATE( plantt )
7151            DEALLOCATE( rt2_track, rt2_track_lad, rt2_track_dist, rt2_dist )
7152        ENDIF
7153
7154        CALL location_message( '    calculation of the complete SVF array', .TRUE. )
7155
7156        IF ( rad_angular_discretization )  THEN
7157           CALL radiation_write_debug_log( 'Load svf from the structure array to plain arrays' )
7158           ALLOCATE( svf(ndsvf,nsvfl) )
7159           ALLOCATE( svfsurf(idsvf,nsvfl) )
7160
7161           DO isvf = 1, nsvfl
7162               svf(:, isvf) = (/ asvf(isvf)%rsvf, asvf(isvf)%rtransp /)
7163               svfsurf(:, isvf) = (/ asvf(isvf)%isurflt, asvf(isvf)%isurfs /)
7164           ENDDO
7165        ELSE
7166           CALL radiation_write_debug_log( 'Start SVF sort' )
7167!--        sort svf ( a version of quicksort )
7168           CALL quicksort_svf(asvf,1,nsvfl)
7169
7170           !< load svf from the structure array to plain arrays
7171           CALL radiation_write_debug_log( 'Load svf from the structure array to plain arrays' )
7172           ALLOCATE( svf(ndsvf,nsvfl) )
7173           ALLOCATE( svfsurf(idsvf,nsvfl) )
7174           svfnorm_counts(:) = 0._wp
7175           isurflt_prev = -1
7176           ksvf = 1
7177           svfsum = 0._wp
7178           DO isvf = 1, nsvfl
7179!--            normalize svf per target face
7180               IF ( asvf(ksvf)%isurflt /= isurflt_prev )  THEN
7181                   IF ( isurflt_prev /= -1  .AND.  svfsum /= 0._wp )  THEN
7182                       !< update histogram of logged svf normalization values
7183                       i = searchsorted(svfnorm_report_thresh, svfsum / (1._wp-skyvf(isurflt_prev)))
7184                       svfnorm_counts(i) = svfnorm_counts(i) + 1
7185
7186                       svf(1, isvf_surflt:isvf-1) = svf(1, isvf_surflt:isvf-1) / svfsum * (1._wp-skyvf(isurflt_prev))
7187                   ENDIF
7188                   isurflt_prev = asvf(ksvf)%isurflt
7189                   isvf_surflt = isvf
7190                   svfsum = asvf(ksvf)%rsvf !?? / asvf(ksvf)%rtransp
7191               ELSE
7192                   svfsum = svfsum + asvf(ksvf)%rsvf !?? / asvf(ksvf)%rtransp
7193               ENDIF
7194
7195               svf(:, isvf) = (/ asvf(ksvf)%rsvf, asvf(ksvf)%rtransp /)
7196               svfsurf(:, isvf) = (/ asvf(ksvf)%isurflt, asvf(ksvf)%isurfs /)
7197
7198!--            next element
7199               ksvf = ksvf + 1
7200           ENDDO
7201
7202           IF ( isurflt_prev /= -1  .AND.  svfsum /= 0._wp )  THEN
7203               i = searchsorted(svfnorm_report_thresh, svfsum / (1._wp-skyvf(isurflt_prev)))
7204               svfnorm_counts(i) = svfnorm_counts(i) + 1
7205
7206               svf(1, isvf_surflt:nsvfl) = svf(1, isvf_surflt:nsvfl) / svfsum * (1._wp-skyvf(isurflt_prev))
7207           ENDIF
7208           WRITE(9, *) 'SVF normalization histogram:', svfnorm_counts,  &
7209                       'on thresholds:', svfnorm_report_thresh(1:svfnorm_report_num), '(val < thresh <= val)'
7210           !TODO we should be able to deallocate skyvf, from now on we only need skyvft
7211        ENDIF ! rad_angular_discretization
7212
7213!--     deallocate temporary asvf array
7214!--     DEALLOCATE(asvf) - ifort has a problem with deallocation of allocatable target
7215!--     via pointing pointer - we need to test original targets
7216        IF ( ALLOCATED(asvf1) )  THEN
7217            DEALLOCATE(asvf1)
7218        ENDIF
7219        IF ( ALLOCATED(asvf2) )  THEN
7220            DEALLOCATE(asvf2)
7221        ENDIF
7222
7223        npcsfl = 0
7224        IF ( plant_canopy )  THEN
7225
7226            CALL location_message( '    calculation of the complete CSF array', .TRUE. )
7227            CALL radiation_write_debug_log( 'Calculation of the complete CSF array' )
7228!--         sort and merge csf for the last time, keeping the array size to minimum
7229            CALL merge_and_grow_csf(-1)
7230           
7231!--         aggregate csb among processors
7232!--         allocate necessary arrays
7233            udim = max(ncsfl,1)
7234            ALLOCATE( csflt_l(ndcsf*udim) )
7235            csflt(1:ndcsf,1:udim) => csflt_l(1:ndcsf*udim)
7236            ALLOCATE( kcsflt_l(kdcsf*udim) )
7237            kcsflt(1:kdcsf,1:udim) => kcsflt_l(1:kdcsf*udim)
7238            ALLOCATE( icsflt(0:numprocs-1) )
7239            ALLOCATE( dcsflt(0:numprocs-1) )
7240            ALLOCATE( ipcsflt(0:numprocs-1) )
7241            ALLOCATE( dpcsflt(0:numprocs-1) )
7242           
7243!--         fill out arrays of csf values and
7244!--         arrays of number of elements and displacements
7245!--         for particular precessors
7246            icsflt = 0
7247            dcsflt = 0
7248            ip = -1
7249            j = -1
7250            d = 0
7251            DO kcsf = 1, ncsfl
7252                j = j+1
7253                IF ( acsf(kcsf)%ip /= ip )  THEN
7254!--                 new block of the processor
7255!--                 number of elements of previous block
7256                    IF ( ip>=0) icsflt(ip) = j
7257                    d = d+j
7258!--                 blank blocks
7259                    DO jp = ip+1, acsf(kcsf)%ip-1
7260!--                     number of elements is zero, displacement is equal to previous
7261                        icsflt(jp) = 0
7262                        dcsflt(jp) = d
7263                    ENDDO
7264!--                 the actual block
7265                    ip = acsf(kcsf)%ip
7266                    dcsflt(ip) = d
7267                    j = 0
7268                ENDIF
7269                csflt(1,kcsf) = acsf(kcsf)%rcvf
7270!--             fill out integer values of itz,ity,itx,isurfs
7271                kcsflt(1,kcsf) = acsf(kcsf)%itz
7272                kcsflt(2,kcsf) = acsf(kcsf)%ity
7273                kcsflt(3,kcsf) = acsf(kcsf)%itx
7274                kcsflt(4,kcsf) = acsf(kcsf)%isurfs
7275            ENDDO
7276!--         last blank blocks at the end of array
7277            j = j+1
7278            IF ( ip>=0 ) icsflt(ip) = j
7279            d = d+j
7280            DO jp = ip+1, numprocs-1
7281!--             number of elements is zero, displacement is equal to previous
7282                icsflt(jp) = 0
7283                dcsflt(jp) = d
7284            ENDDO
7285           
7286!--         deallocate temporary acsf array
7287!--         DEALLOCATE(acsf) - ifort has a problem with deallocation of allocatable target
7288!--         via pointing pointer - we need to test original targets
7289            IF ( ALLOCATED(acsf1) )  THEN
7290                DEALLOCATE(acsf1)
7291            ENDIF
7292            IF ( ALLOCATED(acsf2) )  THEN
7293                DEALLOCATE(acsf2)
7294            ENDIF
7295                   
7296#if defined( __parallel )
7297!--         scatter and gather the number of elements to and from all processor
7298!--         and calculate displacements
7299            CALL radiation_write_debug_log( 'Scatter and gather the number of elements to and from all processor' )
7300            CALL MPI_AlltoAll(icsflt,1,MPI_INTEGER,ipcsflt,1,MPI_INTEGER,comm2d, ierr)
7301            IF ( ierr /= 0 ) THEN
7302                WRITE(9,*) 'Error MPI_AlltoAll1:', ierr, SIZE(icsflt), SIZE(ipcsflt)
7303                FLUSH(9)
7304            ENDIF
7305
7306            npcsfl = SUM(ipcsflt)
7307            d = 0
7308            DO i = 0, numprocs-1
7309                dpcsflt(i) = d
7310                d = d + ipcsflt(i)
7311            ENDDO
7312
7313!--         exchange csf fields between processors
7314            CALL radiation_write_debug_log( 'Exchange csf fields between processors' )
7315            udim = max(npcsfl,1)
7316            ALLOCATE( pcsflt_l(ndcsf*udim) )
7317            pcsflt(1:ndcsf,1:udim) => pcsflt_l(1:ndcsf*udim)
7318            ALLOCATE( kpcsflt_l(kdcsf*udim) )
7319            kpcsflt(1:kdcsf,1:udim) => kpcsflt_l(1:kdcsf*udim)
7320            CALL MPI_AlltoAllv(csflt_l, ndcsf*icsflt, ndcsf*dcsflt, MPI_REAL, &
7321                pcsflt_l, ndcsf*ipcsflt, ndcsf*dpcsflt, MPI_REAL, comm2d, ierr)
7322            IF ( ierr /= 0 ) THEN
7323                WRITE(9,*) 'Error MPI_AlltoAllv1:', ierr, SIZE(ipcsflt), ndcsf*icsflt, &
7324                            ndcsf*dcsflt, SIZE(pcsflt_l),ndcsf*ipcsflt, ndcsf*dpcsflt
7325                FLUSH(9)
7326            ENDIF
7327
7328            CALL MPI_AlltoAllv(kcsflt_l, kdcsf*icsflt, kdcsf*dcsflt, MPI_INTEGER, &
7329                kpcsflt_l, kdcsf*ipcsflt, kdcsf*dpcsflt, MPI_INTEGER, comm2d, ierr)
7330            IF ( ierr /= 0 ) THEN
7331                WRITE(9,*) 'Error MPI_AlltoAllv2:', ierr, SIZE(kcsflt_l),kdcsf*icsflt, &
7332                           kdcsf*dcsflt, SIZE(kpcsflt_l), kdcsf*ipcsflt, kdcsf*dpcsflt
7333                FLUSH(9)
7334            ENDIF
7335           
7336#else
7337            npcsfl = ncsfl
7338            ALLOCATE( pcsflt(ndcsf,max(npcsfl,ndcsf)) )
7339            ALLOCATE( kpcsflt(kdcsf,max(npcsfl,kdcsf)) )
7340            pcsflt = csflt
7341            kpcsflt = kcsflt
7342#endif
7343
7344!--         deallocate temporary arrays
7345            DEALLOCATE( csflt_l )
7346            DEALLOCATE( kcsflt_l )
7347            DEALLOCATE( icsflt )
7348            DEALLOCATE( dcsflt )
7349            DEALLOCATE( ipcsflt )
7350            DEALLOCATE( dpcsflt )
7351
7352!--         sort csf ( a version of quicksort )
7353            CALL radiation_write_debug_log( 'Sort csf' )
7354            CALL quicksort_csf2(kpcsflt, pcsflt, 1, npcsfl)
7355
7356!--         aggregate canopy sink factor records with identical box & source
7357!--         againg across all values from all processors
7358            CALL radiation_write_debug_log( 'Aggregate canopy sink factor records with identical box' )
7359
7360            IF ( npcsfl > 0 )  THEN
7361                icsf = 1 !< reading index
7362                kcsf = 1 !< writing index
7363                DO while (icsf < npcsfl)
7364!--                 here kpcsf(kcsf) already has values from kpcsf(icsf)
7365                    IF ( kpcsflt(3,icsf) == kpcsflt(3,icsf+1)  .AND.  &
7366                         kpcsflt(2,icsf) == kpcsflt(2,icsf+1)  .AND.  &
7367                         kpcsflt(1,icsf) == kpcsflt(1,icsf+1)  .AND.  &
7368                         kpcsflt(4,icsf) == kpcsflt(4,icsf+1) )  THEN
7369
7370                        pcsflt(1,kcsf) = pcsflt(1,kcsf) + pcsflt(1,icsf+1)
7371
7372!--                     advance reading index, keep writing index
7373                        icsf = icsf + 1
7374                    ELSE
7375!--                     not identical, just advance and copy
7376                        icsf = icsf + 1
7377                        kcsf = kcsf + 1
7378                        kpcsflt(:,kcsf) = kpcsflt(:,icsf)
7379                        pcsflt(:,kcsf) = pcsflt(:,icsf)
7380                    ENDIF
7381                ENDDO
7382!--             last written item is now also the last item in valid part of array
7383                npcsfl = kcsf
7384            ENDIF
7385
7386            ncsfl = npcsfl
7387            IF ( ncsfl > 0 )  THEN
7388                ALLOCATE( csf(ndcsf,ncsfl) )
7389                ALLOCATE( csfsurf(idcsf,ncsfl) )
7390                DO icsf = 1, ncsfl
7391                    csf(:,icsf) = pcsflt(:,icsf)
7392                    csfsurf(1,icsf) =  gridpcbl(kpcsflt(1,icsf),kpcsflt(2,icsf),kpcsflt(3,icsf))
7393                    csfsurf(2,icsf) =  kpcsflt(4,icsf)
7394                ENDDO
7395            ENDIF
7396           
7397!--         deallocation of temporary arrays
7398            IF ( npcbl > 0 )  DEALLOCATE( gridpcbl )
7399            DEALLOCATE( pcsflt_l )
7400            DEALLOCATE( kpcsflt_l )
7401            CALL radiation_write_debug_log( 'End of aggregate csf' )
7402           
7403        ENDIF
7404
7405#if defined( __parallel )
7406        CALL MPI_BARRIER( comm2d, ierr )
7407#endif
7408        CALL radiation_write_debug_log( 'End of radiation_calc_svf (after mpi_barrier)' )
7409
7410        RETURN
7411       
7412!        WRITE( message_string, * )  &
7413!            'I/O error when processing shape view factors / ',  &
7414!            'plant canopy sink factors / direct irradiance factors.'
7415!        CALL message( 'init_urban_surface', 'PA0502', 2, 2, 0, 6, 0 )
7416       
7417    END SUBROUTINE radiation_calc_svf
7418
7419   
7420!------------------------------------------------------------------------------!
7421! Description:
7422! ------------
7423!> Raytracing for detecting obstacles and calculating compound canopy sink
7424!> factors. (A simple obstacle detection would only need to process faces in
7425!> 3 dimensions without any ordering.)
7426!> Assumtions:
7427!> -----------
7428!> 1. The ray always originates from a face midpoint (only one coordinate equals
7429!>    *.5, i.e. wall) and doesn't travel parallel to the surface (that would mean
7430!>    shape factor=0). Therefore, the ray may never travel exactly along a face
7431!>    or an edge.
7432!> 2. From grid bottom to urban surface top the grid has to be *equidistant*
7433!>    within each of the dimensions, including vertical (but the resolution
7434!>    doesn't need to be the same in all three dimensions).
7435!------------------------------------------------------------------------------!
7436    SUBROUTINE raytrace(src, targ, isrc, difvf, atarg, create_csf, visible, transparency)
7437        IMPLICIT NONE
7438
7439        REAL(wp), DIMENSION(3), INTENT(in)     :: src, targ    !< real coordinates z,y,x
7440        INTEGER(iwp), INTENT(in)               :: isrc         !< index of source face for csf
7441        REAL(wp), INTENT(in)                   :: difvf        !< differential view factor for csf
7442        REAL(wp), INTENT(in)                   :: atarg        !< target surface area for csf
7443        LOGICAL, INTENT(in)                    :: create_csf   !< whether to generate new CSFs during raytracing
7444        LOGICAL, INTENT(out)                   :: visible
7445        REAL(wp), INTENT(out)                  :: transparency !< along whole path
7446        INTEGER(iwp)                           :: i, k, d
7447        INTEGER(iwp)                           :: seldim       !< dimension to be incremented
7448        INTEGER(iwp)                           :: ncsb         !< no of written plant canopy sinkboxes
7449        INTEGER(iwp)                           :: maxboxes     !< max no of gridboxes visited
7450        REAL(wp)                               :: distance     !< euclidean along path
7451        REAL(wp)                               :: crlen        !< length of gridbox crossing
7452        REAL(wp)                               :: lastdist     !< beginning of current crossing
7453        REAL(wp)                               :: nextdist     !< end of current crossing
7454        REAL(wp)                               :: realdist     !< distance in meters per unit distance
7455        REAL(wp)                               :: crmid        !< midpoint of crossing
7456        REAL(wp)                               :: cursink      !< sink factor for current canopy box
7457        REAL(wp), DIMENSION(3)                 :: delta        !< path vector
7458        REAL(wp), DIMENSION(3)                 :: uvect        !< unit vector
7459        REAL(wp), DIMENSION(3)                 :: dimnextdist  !< distance for each dimension increments
7460        INTEGER(iwp), DIMENSION(3)             :: box          !< gridbox being crossed
7461        INTEGER(iwp), DIMENSION(3)             :: dimnext      !< next dimension increments along path
7462        INTEGER(iwp), DIMENSION(3)             :: dimdelta     !< dimension direction = +- 1
7463        INTEGER(iwp)                           :: px, py       !< number of processors in x and y dir before
7464                                                               !< the processor in the question
7465        INTEGER(iwp)                           :: ip           !< number of processor where gridbox reside
7466        INTEGER(iwp)                           :: ig           !< 1D index of gridbox in global 2D array
7467       
7468        REAL(wp)                               :: eps = 1E-10_wp !< epsilon for value comparison
7469        REAL(wp)                               :: lad_s_target   !< recieved lad_s of particular grid box
7470
7471!
7472!--     Maximum number of gridboxes visited equals to maximum number of boundaries crossed in each dimension plus one. That's also
7473!--     the maximum number of plant canopy boxes written. We grow the acsf array accordingly using exponential factor.
7474        maxboxes = SUM(ABS(NINT(targ, iwp) - NINT(src, iwp))) + 1
7475        IF ( plant_canopy  .AND.  ncsfl + maxboxes > ncsfla )  THEN
7476!--         use this code for growing by fixed exponential increments (equivalent to case where ncsfl always increases by 1)
7477!--         k = CEILING(grow_factor ** real(CEILING(log(real(ncsfl + maxboxes, kind=wp)) &
7478!--                                                / log(grow_factor)), kind=wp))
7479!--         or use this code to simply always keep some extra space after growing
7480            k = CEILING(REAL(ncsfl + maxboxes, kind=wp) * grow_factor)
7481
7482            CALL merge_and_grow_csf(k)
7483        ENDIF
7484       
7485        transparency = 1._wp
7486        ncsb = 0
7487
7488        delta(:) = targ(:) - src(:)
7489        distance = SQRT(SUM(delta(:)**2))
7490        IF ( distance == 0._wp )  THEN
7491            visible = .TRUE.
7492            RETURN
7493        ENDIF
7494        uvect(:) = delta(:) / distance
7495        realdist = SQRT(SUM( (uvect(:)*(/dz(1),dy,dx/))**2 ))
7496
7497        lastdist = 0._wp
7498
7499!--     Since all face coordinates have values *.5 and we'd like to use
7500!--     integers, all these have .5 added
7501        DO d = 1, 3
7502            IF ( uvect(d) == 0._wp )  THEN
7503                dimnext(d) = 999999999
7504                dimdelta(d) = 999999999
7505                dimnextdist(d) = 1.0E20_wp
7506            ELSE IF ( uvect(d) > 0._wp )  THEN
7507                dimnext(d) = CEILING(src(d) + .5_wp)
7508                dimdelta(d) = 1
7509                dimnextdist(d) = (dimnext(d) - .5_wp - src(d)) / uvect(d)
7510            ELSE
7511                dimnext(d) = FLOOR(src(d) + .5_wp)
7512                dimdelta(d) = -1
7513                dimnextdist(d) = (dimnext(d) - .5_wp - src(d)) / uvect(d)
7514            ENDIF
7515        ENDDO
7516
7517        DO
7518!--         along what dimension will the next wall crossing be?
7519            seldim = minloc(dimnextdist, 1)
7520            nextdist = dimnextdist(seldim)
7521            IF ( nextdist > distance ) nextdist = distance
7522
7523            crlen = nextdist - lastdist
7524            IF ( crlen > .001_wp )  THEN
7525                crmid = (lastdist + nextdist) * .5_wp
7526                box = NINT(src(:) + uvect(:) * crmid, iwp)
7527
7528!--             calculate index of the grid with global indices (box(2),box(3))
7529!--             in the array nzterr and plantt and id of the coresponding processor
7530                px = box(3)/nnx
7531                py = box(2)/nny
7532                ip = px*pdims(2)+py
7533                ig = ip*nnx*nny + (box(3)-px*nnx)*nny + box(2)-py*nny
7534                IF ( box(1) <= nzterr(ig) )  THEN
7535                    visible = .FALSE.
7536                    RETURN
7537                ENDIF
7538
7539                IF ( plant_canopy )  THEN
7540                    IF ( box(1) <= plantt(ig) )  THEN
7541                        ncsb = ncsb + 1
7542                        boxes(:,ncsb) = box
7543                        crlens(ncsb) = crlen
7544#if defined( __parallel )
7545                        lad_ip(ncsb) = ip
7546                        lad_disp(ncsb) = (box(3)-px*nnx)*(nny*nzp) + (box(2)-py*nny)*nzp + box(1)-nzub
7547#endif
7548                    ENDIF
7549                ENDIF
7550            ENDIF
7551
7552            IF ( ABS(distance - nextdist) < eps )  EXIT
7553            lastdist = nextdist
7554            dimnext(seldim) = dimnext(seldim) + dimdelta(seldim)
7555            dimnextdist(seldim) = (dimnext(seldim) - .5_wp - src(seldim)) / uvect(seldim)
7556        ENDDO
7557       
7558        IF ( plant_canopy )  THEN
7559#if defined( __parallel )
7560            IF ( raytrace_mpi_rma )  THEN
7561!--             send requests for lad_s to appropriate processor
7562                CALL cpu_log( log_point_s(77), 'rad_rma_lad', 'start' )
7563                DO i = 1, ncsb
7564                    CALL MPI_Get(lad_s_ray(i), 1, MPI_REAL, lad_ip(i), lad_disp(i), &
7565                                 1, MPI_REAL, win_lad, ierr)
7566                    IF ( ierr /= 0 )  THEN
7567                        WRITE(9,*) 'Error MPI_Get1:', ierr, lad_s_ray(i), &
7568                                   lad_ip(i), lad_disp(i), win_lad
7569                        FLUSH(9)
7570                    ENDIF
7571                ENDDO
7572               
7573!--             wait for all pending local requests complete
7574                CALL MPI_Win_flush_local_all(win_lad, ierr)
7575                IF ( ierr /= 0 )  THEN
7576                    WRITE(9,*) 'Error MPI_Win_flush_local_all1:', ierr, win_lad
7577                    FLUSH(9)
7578                ENDIF
7579                CALL cpu_log( log_point_s(77), 'rad_rma_lad', 'stop' )
7580               
7581            ENDIF
7582#endif
7583
7584!--         calculate csf and transparency
7585            DO i = 1, ncsb
7586#if defined( __parallel )
7587                IF ( raytrace_mpi_rma )  THEN
7588                    lad_s_target = lad_s_ray(i)
7589                ELSE
7590                    lad_s_target = sub_lad_g(lad_ip(i)*nnx*nny*nzp + lad_disp(i))
7591                ENDIF
7592#else
7593                lad_s_target = sub_lad(boxes(1,i),boxes(2,i),boxes(3,i))
7594#endif
7595                cursink = 1._wp - exp(-ext_coef * lad_s_target * crlens(i)*realdist)
7596
7597                IF ( create_csf )  THEN
7598!--                 write svf values into the array
7599                    ncsfl = ncsfl + 1
7600                    acsf(ncsfl)%ip = lad_ip(i)
7601                    acsf(ncsfl)%itx = boxes(3,i)
7602                    acsf(ncsfl)%ity = boxes(2,i)
7603                    acsf(ncsfl)%itz = boxes(1,i)
7604                    acsf(ncsfl)%isurfs = isrc
7605                    acsf(ncsfl)%rcvf = cursink*transparency*difvf*atarg
7606                ENDIF  !< create_csf
7607
7608                transparency = transparency * (1._wp - cursink)
7609               
7610            ENDDO
7611        ENDIF
7612       
7613        visible = .TRUE.
7614
7615    END SUBROUTINE raytrace
7616   
7617 
7618!------------------------------------------------------------------------------!
7619! Description:
7620! ------------
7621!> A new, more efficient version of ray tracing algorithm that processes a whole
7622!> arc instead of a single ray.
7623!>
7624!> In all comments, horizon means tangent of horizon angle, i.e.
7625!> vertical_delta / horizontal_distance
7626!------------------------------------------------------------------------------!
7627   SUBROUTINE raytrace_2d(origin, yxdir, nrays, zdirs, iorig, aorig, vffrac,  &
7628                              calc_svf, create_csf, skip_1st_pcb,             &
7629                              lowest_free_ray, transparency, itarget)
7630      IMPLICIT NONE
7631
7632      REAL(wp), DIMENSION(3), INTENT(IN)     ::  origin        !< z,y,x coordinates of ray origin
7633      REAL(wp), DIMENSION(2), INTENT(IN)     ::  yxdir         !< y,x *unit* vector of ray direction (in grid units)
7634      INTEGER(iwp)                           ::  nrays         !< number of rays (z directions) to raytrace
7635      REAL(wp), DIMENSION(nrays), INTENT(IN) ::  zdirs         !< list of z directions to raytrace (z/hdist, grid, zenith->nadir)
7636      INTEGER(iwp), INTENT(in)               ::  iorig         !< index of origin face for csf
7637      REAL(wp), INTENT(in)                   ::  aorig         !< origin face area for csf
7638      REAL(wp), DIMENSION(nrays), INTENT(in) ::  vffrac        !< view factor fractions of each ray for csf
7639      LOGICAL, INTENT(in)                    ::  calc_svf      !< whether to calculate SFV (identify obstacle surfaces)
7640      LOGICAL, INTENT(in)                    ::  create_csf    !< whether to create canopy sink factors
7641      LOGICAL, INTENT(in)                    ::  skip_1st_pcb  !< whether to skip first plant canopy box during raytracing
7642      INTEGER(iwp), INTENT(out)              ::  lowest_free_ray !< index into zdirs
7643      REAL(wp), DIMENSION(nrays), INTENT(OUT) ::  transparency !< transparencies of zdirs paths
7644      INTEGER(iwp), DIMENSION(nrays), INTENT(OUT) ::  itarget  !< global indices of target faces for zdirs
7645
7646      INTEGER(iwp), DIMENSION(nrays)         ::  target_procs
7647      REAL(wp)                               ::  horizon       !< highest horizon found after raytracing (z/hdist)
7648      INTEGER(iwp)                           ::  i, k, l, d
7649      INTEGER(iwp)                           ::  seldim       !< dimension to be incremented
7650      REAL(wp), DIMENSION(2)                 ::  yxorigin     !< horizontal copy of origin (y,x)
7651      REAL(wp)                               ::  distance     !< euclidean along path
7652      REAL(wp)                               ::  lastdist     !< beginning of current crossing
7653      REAL(wp)                               ::  nextdist     !< end of current crossing
7654      REAL(wp)                               ::  crmid        !< midpoint of crossing
7655      REAL(wp)                               ::  horz_entry   !< horizon at entry to column
7656      REAL(wp)                               ::  horz_exit    !< horizon at exit from column
7657      REAL(wp)                               ::  bdydim       !< boundary for current dimension
7658      REAL(wp), DIMENSION(2)                 ::  crossdist    !< distances to boundary for dimensions
7659      REAL(wp), DIMENSION(2)                 ::  dimnextdist  !< distance for each dimension increments
7660      INTEGER(iwp), DIMENSION(2)             ::  column       !< grid column being crossed
7661      INTEGER(iwp), DIMENSION(2)             ::  dimnext      !< next dimension increments along path
7662      INTEGER(iwp), DIMENSION(2)             ::  dimdelta     !< dimension direction = +- 1
7663      INTEGER(iwp)                           ::  px, py       !< number of processors in x and y dir before
7664                                                              !< the processor in the question
7665      INTEGER(iwp)                           ::  ip           !< number of processor where gridbox reside
7666      INTEGER(iwp)                           ::  ig           !< 1D index of gridbox in global 2D array
7667      INTEGER(iwp)                           ::  wcount       !< RMA window item count
7668      INTEGER(iwp)                           ::  maxboxes     !< max no of CSF created
7669      INTEGER(iwp)                           ::  nly          !< maximum  plant canopy height
7670      INTEGER(iwp)                           ::  ntrack
7671     
7672      INTEGER(iwp)                           ::  zb0
7673      INTEGER(iwp)                           ::  zb1
7674      INTEGER(iwp)                           ::  nz
7675      INTEGER(iwp)                           ::  iz
7676      INTEGER(iwp)                           ::  zsgn
7677      INTEGER(iwp)                           ::  lowest_lad   !< lowest column cell for which we need LAD
7678      INTEGER(iwp)                           ::  lastdir      !< wall direction before hitting this column
7679      INTEGER(iwp), DIMENSION(2)             ::  lastcolumn
7680
7681#if defined( __parallel )
7682      INTEGER(MPI_ADDRESS_KIND)              ::  wdisp        !< RMA window displacement
7683#endif
7684     
7685      REAL(wp)                               ::  eps = 1E-10_wp !< epsilon for value comparison
7686      REAL(wp)                               ::  zbottom, ztop !< urban surface boundary in real numbers
7687      REAL(wp)                               ::  zorig         !< z coordinate of ray column entry
7688      REAL(wp)                               ::  zexit         !< z coordinate of ray column exit
7689      REAL(wp)                               ::  qdist         !< ratio of real distance to z coord difference
7690      REAL(wp)                               ::  dxxyy         !< square of real horizontal distance
7691      REAL(wp)                               ::  curtrans      !< transparency of current PC box crossing
7692     
7693
7694     
7695      yxorigin(:) = origin(2:3)
7696      transparency(:) = 1._wp !-- Pre-set the all rays to transparent before reducing
7697      horizon = -HUGE(1._wp)
7698      lowest_free_ray = nrays
7699      IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7700         ALLOCATE(target_surfl(nrays))
7701         target_surfl(:) = -1
7702         lastdir = -999
7703         lastcolumn(:) = -999
7704      ENDIF
7705
7706!--   Determine distance to boundary (in 2D xy)
7707      IF ( yxdir(1) > 0._wp )  THEN
7708         bdydim = ny + .5_wp !< north global boundary
7709         crossdist(1) = (bdydim - yxorigin(1)) / yxdir(1)
7710      ELSEIF ( yxdir(1) == 0._wp )  THEN
7711         crossdist(1) = HUGE(1._wp)
7712      ELSE
7713          bdydim = -.5_wp !< south global boundary
7714          crossdist(1) = (bdydim - yxorigin(1)) / yxdir(1)
7715      ENDIF
7716
7717      IF ( yxdir(2) > 0._wp )  THEN
7718          bdydim = nx + .5_wp !< east global boundary
7719          crossdist(2) = (bdydim - yxorigin(2)) / yxdir(2)
7720      ELSEIF ( yxdir(2) == 0._wp )  THEN
7721         crossdist(2) = HUGE(1._wp)
7722      ELSE
7723          bdydim = -.5_wp !< west global boundary
7724          crossdist(2) = (bdydim - yxorigin(2)) / yxdir(2)
7725      ENDIF
7726      distance = minval(crossdist, 1)
7727
7728      IF ( plant_canopy )  THEN
7729         rt2_track_dist(0) = 0._wp
7730         rt2_track_lad(:,:) = 0._wp
7731         nly = plantt_max - nzub + 1
7732      ENDIF
7733
7734      lastdist = 0._wp
7735
7736!--   Since all face coordinates have values *.5 and we'd like to use
7737!--   integers, all these have .5 added
7738      DO  d = 1, 2
7739          IF ( yxdir(d) == 0._wp )  THEN
7740              dimnext(d) = HUGE(1_iwp)
7741              dimdelta(d) = HUGE(1_iwp)
7742              dimnextdist(d) = HUGE(1._wp)
7743          ELSE IF ( yxdir(d) > 0._wp )  THEN
7744              dimnext(d) = FLOOR(yxorigin(d) + .5_wp) + 1
7745              dimdelta(d) = 1
7746              dimnextdist(d) = (dimnext(d) - .5_wp - yxorigin(d)) / yxdir(d)
7747          ELSE
7748              dimnext(d) = CEILING(yxorigin(d) + .5_wp) - 1
7749              dimdelta(d) = -1
7750              dimnextdist(d) = (dimnext(d) - .5_wp - yxorigin(d)) / yxdir(d)
7751          ENDIF
7752      ENDDO
7753
7754      ntrack = 0
7755      DO
7756!--      along what dimension will the next wall crossing be?
7757         seldim = minloc(dimnextdist, 1)
7758         nextdist = dimnextdist(seldim)
7759         IF ( nextdist > distance )  nextdist = distance
7760
7761         IF ( nextdist > lastdist )  THEN
7762            ntrack = ntrack + 1
7763            crmid = (lastdist + nextdist) * .5_wp
7764            column = NINT(yxorigin(:) + yxdir(:) * crmid, iwp)
7765
7766!--         calculate index of the grid with global indices (column(1),column(2))
7767!--         in the array nzterr and plantt and id of the coresponding processor
7768            px = column(2)/nnx
7769            py = column(1)/nny
7770            ip = px*pdims(2)+py
7771            ig = ip*nnx*nny + (column(2)-px*nnx)*nny + column(1)-py*nny
7772
7773            IF ( lastdist == 0._wp )  THEN
7774               horz_entry = -HUGE(1._wp)
7775            ELSE
7776               horz_entry = (REAL(nzterr(ig), wp) + .5_wp - origin(1)) / lastdist
7777            ENDIF
7778            horz_exit = (REAL(nzterr(ig), wp) + .5_wp - origin(1)) / nextdist
7779
7780            IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7781!
7782!--            Identify vertical obstacles hit by rays in current column
7783               DO WHILE ( lowest_free_ray > 0 )
7784                  IF ( zdirs(lowest_free_ray) > horz_entry )  EXIT
7785!
7786!--               This may only happen after 1st column, so lastdir and lastcolumn are valid
7787                  CALL request_itarget(lastdir,                                         &
7788                        CEILING(-0.5_wp + origin(1) + zdirs(lowest_free_ray)*lastdist), &
7789                        lastcolumn(1), lastcolumn(2),                                   &
7790                        target_surfl(lowest_free_ray), target_procs(lowest_free_ray))
7791                  lowest_free_ray = lowest_free_ray - 1
7792               ENDDO
7793!
7794!--            Identify horizontal obstacles hit by rays in current column
7795               DO WHILE ( lowest_free_ray > 0 )
7796                  IF ( zdirs(lowest_free_ray) > horz_exit )  EXIT
7797                  CALL request_itarget(iup_u, nzterr(ig)+1, column(1), column(2), &
7798                                       target_surfl(lowest_free_ray),           &
7799                                       target_procs(lowest_free_ray))
7800                  lowest_free_ray = lowest_free_ray - 1
7801               ENDDO
7802            ENDIF
7803
7804            horizon = MAX(horizon, horz_entry, horz_exit)
7805
7806            IF ( plant_canopy )  THEN
7807               rt2_track(:, ntrack) = column(:)
7808               rt2_track_dist(ntrack) = nextdist
7809            ENDIF
7810         ENDIF
7811
7812         IF ( nextdist + eps >= distance )  EXIT
7813
7814         IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7815!
7816!--         Save wall direction of coming building column (= this air column)
7817            IF ( seldim == 1 )  THEN
7818               IF ( dimdelta(seldim) == 1 )  THEN
7819                  lastdir = isouth_u
7820               ELSE
7821                  lastdir = inorth_u
7822               ENDIF
7823            ELSE
7824               IF ( dimdelta(seldim) == 1 )  THEN
7825                  lastdir = iwest_u
7826               ELSE
7827                  lastdir = ieast_u
7828               ENDIF
7829            ENDIF
7830            lastcolumn = column
7831         ENDIF
7832         lastdist = nextdist
7833         dimnext(seldim) = dimnext(seldim) + dimdelta(seldim)
7834         dimnextdist(seldim) = (dimnext(seldim) - .5_wp - yxorigin(seldim)) / yxdir(seldim)
7835      ENDDO
7836
7837      IF ( plant_canopy )  THEN
7838!--      Request LAD WHERE applicable
7839!--     
7840#if defined( __parallel )
7841         IF ( raytrace_mpi_rma )  THEN
7842!--         send requests for lad_s to appropriate processor
7843            !CALL cpu_log( log_point_s(77), 'usm_init_rma', 'start' )
7844            DO  i = 1, ntrack
7845               px = rt2_track(2,i)/nnx
7846               py = rt2_track(1,i)/nny
7847               ip = px*pdims(2)+py
7848               ig = ip*nnx*nny + (rt2_track(2,i)-px*nnx)*nny + rt2_track(1,i)-py*nny
7849
7850               IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7851!
7852!--               For fixed view resolution, we need plant canopy even for rays
7853!--               to opposing surfaces
7854                  lowest_lad = nzterr(ig) + 1
7855               ELSE
7856!
7857!--               We only need LAD for rays directed above horizon (to sky)
7858                  lowest_lad = CEILING( -0.5_wp + origin(1) +            &
7859                                    MIN( horizon * rt2_track_dist(i-1),  & ! entry
7860                                         horizon * rt2_track_dist(i)   ) ) ! exit
7861               ENDIF
7862!
7863!--            Skip asking for LAD where all plant canopy is under requested level
7864               IF ( plantt(ig) < lowest_lad )  CYCLE
7865
7866               wdisp = (rt2_track(2,i)-px*nnx)*(nny*nzp) + (rt2_track(1,i)-py*nny)*nzp + lowest_lad-nzub
7867               wcount = plantt(ig)-lowest_lad+1
7868               ! TODO send request ASAP - even during raytracing
7869               CALL MPI_Get(rt2_track_lad(lowest_lad:plantt(ig), i), wcount, MPI_REAL, ip,    &
7870                            wdisp, wcount, MPI_REAL, win_lad, ierr)
7871               IF ( ierr /= 0 )  THEN
7872                  WRITE(9,*) 'Error MPI_Get2:', ierr, rt2_track_lad(lowest_lad:plantt(ig), i), &
7873                             wcount, ip, wdisp, win_lad
7874                  FLUSH(9)
7875               ENDIF
7876            ENDDO
7877
7878!--         wait for all pending local requests complete
7879            ! TODO WAIT selectively for each column later when needed
7880            CALL MPI_Win_flush_local_all(win_lad, ierr)
7881            IF ( ierr /= 0 )  THEN
7882               WRITE(9,*) 'Error MPI_Win_flush_local_all2:', ierr, win_lad
7883               FLUSH(9)
7884            ENDIF
7885            !CALL cpu_log( log_point_s(77), 'usm_init_rma', 'stop' )
7886
7887         ELSE ! raytrace_mpi_rma = .F.
7888            DO  i = 1, ntrack
7889               px = rt2_track(2,i)/nnx
7890               py = rt2_track(1,i)/nny
7891               ip = px*pdims(2)+py
7892               ig = ip*nnx*nny*nzp + (rt2_track(2,i)-px*nnx)*(nny*nzp) + (rt2_track(1,i)-py*nny)*nzp
7893               rt2_track_lad(nzub:plantt_max, i) = sub_lad_g(ig:ig+nly-1)
7894            ENDDO
7895         ENDIF
7896#else
7897         DO  i = 1, ntrack
7898            rt2_track_lad(nzub:plantt_max, i) = sub_lad(rt2_track(1,i), rt2_track(2,i), nzub:plantt_max)
7899         ENDDO
7900#endif
7901      ENDIF ! plant_canopy
7902
7903      IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7904#if defined( __parallel )
7905!--      wait for all gridsurf requests to complete
7906         CALL MPI_Win_flush_local_all(win_gridsurf, ierr)
7907         IF ( ierr /= 0 )  THEN
7908            WRITE(9,*) 'Error MPI_Win_flush_local_all3:', ierr, win_gridsurf
7909            FLUSH(9)
7910         ENDIF
7911#endif
7912!
7913!--      recalculate local surf indices into global ones
7914         DO i = 1, nrays
7915            IF ( target_surfl(i) == -1 )  THEN
7916               itarget(i) = -1
7917            ELSE
7918               itarget(i) = target_surfl(i) + surfstart(target_procs(i))
7919            ENDIF
7920         ENDDO
7921         
7922         DEALLOCATE( target_surfl )
7923         
7924      ELSE
7925         itarget(:) = -1
7926      ENDIF ! rad_angular_discretization
7927
7928      IF ( plant_canopy )  THEN
7929!--      Skip the PCB around origin if requested (for MRT, the PCB might not be there)
7930!--     
7931         IF ( skip_1st_pcb  .AND.  NINT(origin(1)) <= plantt_max )  THEN
7932            rt2_track_lad(NINT(origin(1), iwp), 1) = 0._wp
7933         ENDIF
7934
7935!--      Assert that we have space allocated for CSFs
7936!--     
7937         maxboxes = (ntrack + MAX(CEILING(origin(1)-.5_wp) - nzub,          &
7938                                  nzut - CEILING(origin(1)-.5_wp))) * nrays
7939         IF ( ncsfl + maxboxes > ncsfla )  THEN
7940!--         use this code for growing by fixed exponential increments (equivalent to case where ncsfl always increases by 1)
7941!--         k = CEILING(grow_factor ** real(CEILING(log(real(ncsfl + maxboxes, kind=wp)) &
7942!--                                                / log(grow_factor)), kind=wp))
7943!--         or use this code to simply always keep some extra space after growing
7944            k = CEILING(REAL(ncsfl + maxboxes, kind=wp) * grow_factor)
7945            CALL merge_and_grow_csf(k)
7946         ENDIF
7947
7948!--      Calculate transparencies and store new CSFs
7949!--     
7950         zbottom = REAL(nzub, wp) - .5_wp
7951         ztop = REAL(plantt_max, wp) + .5_wp
7952
7953!--      Reverse direction of radiation (face->sky), only when calc_svf
7954!--     
7955         IF ( calc_svf )  THEN
7956            DO  i = 1, ntrack ! for each column
7957               dxxyy = ((dy*yxdir(1))**2 + (dx*yxdir(2))**2) * (rt2_track_dist(i)-rt2_track_dist(i-1))**2
7958               px = rt2_track(2,i)/nnx
7959               py = rt2_track(1,i)/nny
7960               ip = px*pdims(2)+py
7961
7962               DO  k = 1, nrays ! for each ray
7963!
7964!--               NOTE 6778:
7965!--               With traditional svf discretization, CSFs under the horizon
7966!--               (i.e. for surface to surface radiation)  are created in
7967!--               raytrace(). With rad_angular_discretization, we must create
7968!--               CSFs under horizon only for one direction, otherwise we would
7969!--               have duplicate amount of energy. Although we could choose
7970!--               either of the two directions (they differ only by
7971!--               discretization error with no bias), we choose the the backward
7972!--               direction, because it tends to cumulate high canopy sink
7973!--               factors closer to raytrace origin, i.e. it should potentially
7974!--               cause less moiree.
7975                  IF ( .NOT. rad_angular_discretization )  THEN
7976                     IF ( zdirs(k) <= horizon )  CYCLE
7977                  ENDIF
7978
7979                  zorig = origin(1) + zdirs(k) * rt2_track_dist(i-1)
7980                  IF ( zorig <= zbottom  .OR.  zorig >= ztop )  CYCLE
7981
7982                  zsgn = INT(SIGN(1._wp, zdirs(k)), iwp)
7983                  rt2_dist(1) = 0._wp
7984                  IF ( zdirs(k) == 0._wp )  THEN ! ray is exactly horizontal
7985                     nz = 2
7986                     rt2_dist(nz) = SQRT(dxxyy)
7987                     iz = CEILING(-.5_wp + zorig, iwp)
7988                  ELSE
7989                     zexit = MIN(MAX(origin(1) + zdirs(k) * rt2_track_dist(i), zbottom), ztop)
7990
7991                     zb0 = FLOOR(  zorig * zsgn - .5_wp) + 1  ! because it must be greater than orig
7992                     zb1 = CEILING(zexit * zsgn - .5_wp) - 1  ! because it must be smaller than exit
7993                     nz = MAX(zb1 - zb0 + 3, 2)
7994                     rt2_dist(nz) = SQRT(((zexit-zorig)*dz(1))**2 + dxxyy)
7995                     qdist = rt2_dist(nz) / (zexit-zorig)
7996                     rt2_dist(2:nz-1) = (/( ((REAL(l, wp) + .5_wp) * zsgn - zorig) * qdist , l = zb0, zb1 )/)
7997                     iz = zb0 * zsgn
7998                  ENDIF
7999
8000                  DO  l = 2, nz
8001                     IF ( rt2_track_lad(iz, i) > 0._wp )  THEN
8002                        curtrans = exp(-ext_coef * rt2_track_lad(iz, i) * (rt2_dist(l)-rt2_dist(l-1)))
8003
8004                        IF ( create_csf )  THEN
8005                           ncsfl = ncsfl + 1
8006                           acsf(ncsfl)%ip = ip
8007                           acsf(ncsfl)%itx = rt2_track(2,i)
8008                           acsf(ncsfl)%ity = rt2_track(1,i)
8009                           acsf(ncsfl)%itz = iz
8010                           acsf(ncsfl)%isurfs = iorig
8011                           acsf(ncsfl)%rcvf = (1._wp - curtrans)*transparency(k)*vffrac(k)
8012                        ENDIF
8013
8014                        transparency(k) = transparency(k) * curtrans
8015                     ENDIF
8016                     iz = iz + zsgn
8017                  ENDDO ! l = 1, nz - 1
8018               ENDDO ! k = 1, nrays
8019            ENDDO ! i = 1, ntrack
8020
8021            transparency(1:lowest_free_ray) = 1._wp !-- Reset rays above horizon to transparent (see NOTE 6778)
8022         ENDIF
8023
8024!--      Forward direction of radiation (sky->face), always
8025!--     
8026         DO  i = ntrack, 1, -1 ! for each column backwards
8027            dxxyy = ((dy*yxdir(1))**2 + (dx*yxdir(2))**2) * (rt2_track_dist(i)-rt2_track_dist(i-1))**2
8028            px = rt2_track(2,i)/nnx
8029            py = rt2_track(1,i)/nny
8030            ip = px*pdims(2)+py
8031
8032            DO  k = 1, nrays ! for each ray
8033!
8034!--            See NOTE 6778 above
8035               IF ( zdirs(k) <= horizon )  CYCLE
8036
8037               zexit = origin(1) + zdirs(k) * rt2_track_dist(i-1)
8038               IF ( zexit <= zbottom  .OR.  zexit >= ztop )  CYCLE
8039
8040               zsgn = -INT(SIGN(1._wp, zdirs(k)), iwp)
8041               rt2_dist(1) = 0._wp
8042               IF ( zdirs(k) == 0._wp )  THEN ! ray is exactly horizontal
8043                  nz = 2
8044                  rt2_dist(nz) = SQRT(dxxyy)
8045                  iz = NINT(zexit, iwp)
8046               ELSE
8047                  zorig = MIN(MAX(origin(1) + zdirs(k) * rt2_track_dist(i), zbottom), ztop)
8048
8049                  zb0 = FLOOR(  zorig * zsgn - .5_wp) + 1  ! because it must be greater than orig
8050                  zb1 = CEILING(zexit * zsgn - .5_wp) - 1  ! because it must be smaller than exit
8051                  nz = MAX(zb1 - zb0 + 3, 2)
8052                  rt2_dist(nz) = SQRT(((zexit-zorig)*dz(1))**2 + dxxyy)
8053                  qdist = rt2_dist(nz) / (zexit-zorig)
8054                  rt2_dist(2:nz-1) = (/( ((REAL(l, wp) + .5_wp) * zsgn - zorig) * qdist , l = zb0, zb1 )/)
8055                  iz = zb0 * zsgn
8056               ENDIF
8057
8058               DO  l = 2, nz
8059                  IF ( rt2_track_lad(iz, i) > 0._wp )  THEN
8060                     curtrans = exp(-ext_coef * rt2_track_lad(iz, i) * (rt2_dist(l)-rt2_dist(l-1)))
8061
8062                     IF ( create_csf )  THEN
8063                        ncsfl = ncsfl + 1
8064                        acsf(ncsfl)%ip = ip
8065                        acsf(ncsfl)%itx = rt2_track(2,i)
8066                        acsf(ncsfl)%ity = rt2_track(1,i)
8067                        acsf(ncsfl)%itz = iz
8068                        IF ( itarget(k) /= -1 ) STOP 1 !FIXME remove after test
8069                        acsf(ncsfl)%isurfs = -1
8070                        acsf(ncsfl)%rcvf = (1._wp - curtrans)*transparency(k)*aorig*vffrac(k)
8071                     ENDIF  ! create_csf
8072
8073                     transparency(k) = transparency(k) * curtrans
8074                  ENDIF
8075                  iz = iz + zsgn
8076               ENDDO ! l = 1, nz - 1
8077            ENDDO ! k = 1, nrays
8078         ENDDO ! i = 1, ntrack
8079      ENDIF ! plant_canopy
8080
8081      IF ( .NOT. (rad_angular_discretization  .AND.  calc_svf) )  THEN
8082!
8083!--      Just update lowest_free_ray according to horizon
8084         DO WHILE ( lowest_free_ray > 0 )
8085            IF ( zdirs(lowest_free_ray) > horizon )  EXIT
8086            lowest_free_ray = lowest_free_ray - 1
8087         ENDDO
8088      ENDIF
8089
8090   CONTAINS
8091
8092      SUBROUTINE request_itarget( d, z, y, x, isurfl, iproc )
8093
8094         INTEGER(iwp), INTENT(in)            ::  d, z, y, x
8095         INTEGER(iwp), TARGET, INTENT(out)   ::  isurfl
8096         INTEGER(iwp), INTENT(out)           ::  iproc
8097#if defined( __parallel )
8098#else
8099         INTEGER(iwp)                        ::  target_displ  !< index of the grid in the local gridsurf array
8100#endif
8101         INTEGER(iwp)                        ::  px, py        !< number of processors in x and y direction
8102                                                               !< before the processor in the question
8103#if defined( __parallel )
8104         INTEGER(KIND=MPI_ADDRESS_KIND)      ::  target_displ  !< index of the grid in the local gridsurf array
8105
8106!
8107!--      Calculate target processor and index in the remote local target gridsurf array
8108         px = x / nnx
8109         py = y / nny
8110         iproc = px * pdims(2) + py
8111         target_displ = ((x-px*nnx) * nny + y - py*nny ) * nzu * nsurf_type_u +&
8112                        ( z-nzub ) * nsurf_type_u + d
8113!
8114!--      Send MPI_Get request to obtain index target_surfl(i)
8115         CALL MPI_GET( isurfl, 1, MPI_INTEGER, iproc, target_displ,            &
8116                       1, MPI_INTEGER, win_gridsurf, ierr)
8117         IF ( ierr /= 0 )  THEN
8118            WRITE( 9,* ) 'Error MPI_Get3:', ierr, isurfl, iproc, target_displ, &
8119                         win_gridsurf
8120            FLUSH( 9 )
8121         ENDIF
8122#else
8123!--      set index target_surfl(i)
8124         isurfl = gridsurf(d,z,y,x)
8125#endif
8126
8127      END SUBROUTINE request_itarget
8128
8129   END SUBROUTINE raytrace_2d
8130 
8131
8132!------------------------------------------------------------------------------!
8133!
8134! Description:
8135! ------------
8136!> Calculates apparent solar positions for all timesteps and stores discretized
8137!> positions.
8138!------------------------------------------------------------------------------!
8139   SUBROUTINE radiation_presimulate_solar_pos
8140
8141      IMPLICIT NONE
8142
8143      INTEGER(iwp)                              ::  it, i, j
8144      INTEGER(iwp)                              ::  day_of_month_prev,month_of_year_prev
8145      REAL(wp)                                  ::  tsrp_prev
8146      REAL(wp)                                  ::  simulated_time_prev
8147      REAL(wp), DIMENSION(:,:), ALLOCATABLE     ::  dsidir_tmp       !< dsidir_tmp[:,i] = unit vector of i-th
8148                                                                     !< appreant solar direction
8149
8150      ALLOCATE ( dsidir_rev(0:raytrace_discrete_elevs/2-1,                 &
8151                            0:raytrace_discrete_azims-1) )
8152      dsidir_rev(:,:) = -1
8153      ALLOCATE ( dsidir_tmp(3,                                             &
8154                     raytrace_discrete_elevs/2*raytrace_discrete_azims) )
8155      ndsidir = 0
8156
8157!
8158!--   We will artificialy update time_since_reference_point and return to
8159!--   true value later
8160      tsrp_prev = time_since_reference_point
8161      simulated_time_prev = simulated_time
8162      day_of_month_prev = day_of_month
8163      month_of_year_prev = month_of_year
8164      sun_direction = .TRUE.
8165
8166!
8167!--   initialize the simulated_time
8168      simulated_time = 0._wp
8169!
8170!--   Process spinup time if configured
8171      IF ( spinup_time > 0._wp )  THEN
8172         DO  it = 0, CEILING(spinup_time / dt_spinup)
8173            time_since_reference_point = -spinup_time + REAL(it, wp) * dt_spinup
8174            simulated_time = simulated_time + dt_spinup
8175            CALL simulate_pos
8176         ENDDO
8177      ENDIF
8178!
8179!--   Process simulation time
8180      DO  it = 0, CEILING(( end_time - spinup_time ) / dt_radiation)
8181         time_since_reference_point = REAL(it, wp) * dt_radiation
8182         simulated_time = simulated_time + dt_radiation
8183         CALL simulate_pos
8184      ENDDO
8185!
8186!--   Return date and time to its original values
8187      time_since_reference_point = tsrp_prev
8188      simulated_time = simulated_time_prev
8189      day_of_month = day_of_month_prev
8190      month_of_year = month_of_year_prev
8191      CALL init_date_and_time
8192
8193!--   Allocate global vars which depend on ndsidir
8194      ALLOCATE ( dsidir ( 3, ndsidir ) )
8195      dsidir(:,:) = dsidir_tmp(:, 1:ndsidir)
8196      DEALLOCATE ( dsidir_tmp )
8197
8198      ALLOCATE ( dsitrans(nsurfl, ndsidir) )
8199      ALLOCATE ( dsitransc(npcbl, ndsidir) )
8200      IF ( nmrtbl > 0 )  ALLOCATE ( mrtdsit(nmrtbl, ndsidir) )
8201
8202      WRITE ( message_string, * ) 'Precalculated', ndsidir, ' solar positions', &
8203                                  'from', it, ' timesteps.'
8204      CALL message( 'radiation_presimulate_solar_pos', 'UI0013', 0, 0, 0, 6, 0 )
8205
8206      CONTAINS
8207
8208      !------------------------------------------------------------------------!
8209      ! Description:
8210      ! ------------
8211      !> Simuates a single position
8212      !------------------------------------------------------------------------!
8213      SUBROUTINE simulate_pos
8214         IMPLICIT NONE
8215!
8216!--      Update apparent solar position based on modified t_s_r_p
8217         CALL calc_zenith
8218         IF ( zenith(0) > 0 )  THEN
8219!--         
8220!--         Identify solar direction vector (discretized number) 1)
8221            i = MODULO(NINT(ATAN2(sun_dir_lon(0), sun_dir_lat(0))               &
8222                            / (2._wp*pi) * raytrace_discrete_azims-.5_wp, iwp), &
8223                       raytrace_discrete_azims)
8224            j = FLOOR(ACOS(zenith(0)) / pi * raytrace_discrete_elevs)
8225            IF ( dsidir_rev(j, i) == -1 )  THEN
8226               ndsidir = ndsidir + 1
8227               dsidir_tmp(:, ndsidir) =                                              &
8228                     (/ COS((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs), &
8229                        SIN((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs)  &
8230                      * COS((REAL(i,wp)+.5_wp) * 2_wp*pi / raytrace_discrete_azims), &
8231                        SIN((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs)  &
8232                      * SIN((REAL(i,wp)+.5_wp) * 2_wp*pi / raytrace_discrete_azims) /)
8233               dsidir_rev(j, i) = ndsidir
8234            ENDIF
8235         ENDIF
8236      END SUBROUTINE simulate_pos
8237
8238   END SUBROUTINE radiation_presimulate_solar_pos
8239
8240
8241
8242!------------------------------------------------------------------------------!
8243! Description:
8244! ------------
8245!> Determines whether two faces are oriented towards each other. Since the
8246!> surfaces follow the gird box surfaces, it checks first whether the two surfaces
8247!> are directed in the same direction, then it checks if the two surfaces are
8248!> located in confronted direction but facing away from each other, e.g. <--| |-->
8249!------------------------------------------------------------------------------!
8250    PURE LOGICAL FUNCTION surface_facing(x, y, z, d, x2, y2, z2, d2)
8251        IMPLICIT NONE
8252        INTEGER(iwp),   INTENT(in)  :: x, y, z, d, x2, y2, z2, d2
8253     
8254        surface_facing = .FALSE.
8255
8256!-- first check: are the two surfaces directed in the same direction
8257        IF ( (d==iup_u  .OR.  d==iup_l )                             &
8258             .AND. (d2==iup_u  .OR. d2==iup_l) ) RETURN
8259        IF ( (d==isouth_u  .OR.  d==isouth_l ) &
8260             .AND.  (d2==isouth_u  .OR.  d2==isouth_l) ) RETURN
8261        IF ( (d==inorth_u  .OR.  d==inorth_l ) &
8262             .AND.  (d2==inorth_u  .OR.  d2==inorth_l) ) RETURN
8263        IF ( (d==iwest_u  .OR.  d==iwest_l )     &
8264             .AND.  (d2==iwest_u  .OR.  d2==iwest_l ) ) RETURN
8265        IF ( (d==ieast_u  .OR.  d==ieast_l )     &
8266             .AND.  (d2==ieast_u  .OR.  d2==ieast_l ) ) RETURN
8267
8268!-- second check: are surfaces facing away from each other
8269        SELECT CASE (d)
8270            CASE (iup_u, iup_l)                     !< upward facing surfaces
8271                IF ( z2 < z ) RETURN
8272            CASE (isouth_u, isouth_l)               !< southward facing surfaces
8273                IF ( y2 > y ) RETURN
8274            CASE (inorth_u, inorth_l)               !< northward facing surfaces
8275                IF ( y2 < y ) RETURN
8276            CASE (iwest_u, iwest_l)                 !< westward facing surfaces
8277                IF ( x2 > x ) RETURN
8278            CASE (ieast_u, ieast_l)                 !< eastward facing surfaces
8279                IF ( x2 < x ) RETURN
8280        END SELECT
8281
8282        SELECT CASE (d2)
8283            CASE (iup_u)                            !< ground, roof
8284                IF ( z < z2 ) RETURN
8285            CASE (isouth_u, isouth_l)               !< south facing
8286                IF ( y > y2 ) RETURN
8287            CASE (inorth_u, inorth_l)               !< north facing
8288                IF ( y < y2 ) RETURN
8289            CASE (iwest_u, iwest_l)                 !< west facing
8290                IF ( x > x2 ) RETURN
8291            CASE (ieast_u, ieast_l)                 !< east facing
8292                IF ( x < x2 ) RETURN
8293            CASE (-1)
8294                CONTINUE
8295        END SELECT
8296
8297        surface_facing = .TRUE.
8298       
8299    END FUNCTION surface_facing
8300
8301
8302!------------------------------------------------------------------------------!
8303!
8304! Description:
8305! ------------
8306!> Reads svf, svfsurf, csf, csfsurf and mrt factors data from saved file
8307!> SVF means sky view factors and CSF means canopy sink factors
8308!------------------------------------------------------------------------------!
8309    SUBROUTINE radiation_read_svf
8310
8311       IMPLICIT NONE
8312       
8313       CHARACTER(rad_version_len)   :: rad_version_field
8314       
8315       INTEGER(iwp)                 :: i
8316       INTEGER(iwp)                 :: ndsidir_from_file = 0
8317       INTEGER(iwp)                 :: npcbl_from_file = 0
8318       INTEGER(iwp)                 :: nsurfl_from_file = 0
8319       INTEGER(iwp)                 :: nmrtbl_from_file = 0
8320       
8321       DO  i = 0, io_blocks-1
8322          IF ( i == io_group )  THEN
8323
8324!
8325!--          numprocs_previous_run is only known in case of reading restart
8326!--          data. If a new initial run which reads svf data is started the
8327!--          following query will be skipped
8328             IF ( initializing_actions == 'read_restart_data' ) THEN
8329
8330                IF ( numprocs_previous_run /= numprocs ) THEN
8331                   WRITE( message_string, * ) 'A different number of ',        &
8332                                              'processors between the run ',   &
8333                                              'that has written the svf data ',&
8334                                              'and the one that will read it ',&
8335                                              'is not allowed' 
8336                   CALL message( 'check_open', 'PA0491', 1, 2, 0, 6, 0 )
8337                ENDIF
8338
8339             ENDIF
8340             
8341!
8342!--          Open binary file
8343             CALL check_open( 88 )
8344
8345!
8346!--          read and check version
8347             READ ( 88 ) rad_version_field
8348             IF ( TRIM(rad_version_field) /= TRIM(rad_version) )  THEN
8349                 WRITE( message_string, * ) 'Version of binary SVF file "',    &
8350                             TRIM(rad_version_field), '" does not match ',     &
8351                             'the version of model "', TRIM(rad_version), '"'
8352                 CALL message( 'radiation_read_svf', 'PA0482', 1, 2, 0, 6, 0 )
8353             ENDIF
8354             
8355!
8356!--          read nsvfl, ncsfl, nsurfl, nmrtf
8357             READ ( 88 ) nsvfl, ncsfl, nsurfl_from_file, npcbl_from_file,      &
8358                         ndsidir_from_file, nmrtbl_from_file, nmrtf
8359             
8360             IF ( nsvfl < 0  .OR.  ncsfl < 0 )  THEN
8361                 WRITE( message_string, * ) 'Wrong number of SVF or CSF'
8362                 CALL message( 'radiation_read_svf', 'PA0483', 1, 2, 0, 6, 0 )
8363             ELSE
8364                 WRITE(message_string,*) '    Number of SVF, CSF, and nsurfl ',&
8365                                         'to read', nsvfl, ncsfl,              &
8366                                         nsurfl_from_file
8367                 CALL location_message( message_string, .TRUE. )
8368             ENDIF
8369             
8370             IF ( nsurfl_from_file /= nsurfl )  THEN
8371                 WRITE( message_string, * ) 'nsurfl from SVF file does not ',  &
8372                                            'match calculated nsurfl from ',   &
8373                                            'radiation_interaction_init'
8374                 CALL message( 'radiation_read_svf', 'PA0490', 1, 2, 0, 6, 0 )
8375             ENDIF
8376             
8377             IF ( npcbl_from_file /= npcbl )  THEN
8378                 WRITE( message_string, * ) 'npcbl from SVF file does not ',   &
8379                                            'match calculated npcbl from ',    &
8380                                            'radiation_interaction_init'
8381                 CALL message( 'radiation_read_svf', 'PA0493', 1, 2, 0, 6, 0 )
8382             ENDIF
8383             
8384             IF ( ndsidir_from_file /= ndsidir )  THEN
8385                 WRITE( message_string, * ) 'ndsidir from SVF file does not ', &
8386                                            'match calculated ndsidir from ',  &
8387                                            'radiation_presimulate_solar_pos'
8388                 CALL message( 'radiation_read_svf', 'PA0494', 1, 2, 0, 6, 0 )
8389             ENDIF
8390             IF ( nmrtbl_from_file /= nmrtbl )  THEN
8391                 WRITE( message_string, * ) 'nmrtbl from SVF file does not ',  &
8392                                            'match calculated nmrtbl from ',   &
8393                                            'radiation_interaction_init'
8394                 CALL message( 'radiation_read_svf', 'PA0494', 1, 2, 0, 6, 0 )
8395             ELSE
8396                 WRITE(message_string,*) '    Number of nmrtf to read ', nmrtf
8397                 CALL location_message( message_string, .TRUE. )
8398             ENDIF
8399             
8400!
8401!--          Arrays skyvf, skyvft, dsitrans and dsitransc are allready
8402!--          allocated in radiation_interaction_init and
8403!--          radiation_presimulate_solar_pos
8404             IF ( nsurfl > 0 )  THEN
8405                READ(88) skyvf
8406                READ(88) skyvft
8407                READ(88) dsitrans 
8408             ENDIF
8409             
8410             IF ( plant_canopy  .AND.  npcbl > 0 ) THEN
8411                READ ( 88 )  dsitransc
8412             ENDIF
8413             
8414!
8415!--          The allocation of svf, svfsurf, csf, csfsurf, mrtf, mrtft, and
8416!--          mrtfsurf happens in routine radiation_calc_svf which is not
8417!--          called if the program enters radiation_read_svf. Therefore
8418!--          these arrays has to allocate in the following
8419             IF ( nsvfl > 0 )  THEN
8420                ALLOCATE( svf(ndsvf,nsvfl) )
8421                ALLOCATE( svfsurf(idsvf,nsvfl) )
8422                READ(88) svf
8423                READ(88) svfsurf
8424             ENDIF
8425
8426             IF ( plant_canopy  .AND.  ncsfl > 0 )  THEN
8427                ALLOCATE( csf(ndcsf,ncsfl) )
8428                ALLOCATE( csfsurf(idcsf,ncsfl) )
8429                READ(88) csf
8430                READ(88) csfsurf
8431             ENDIF
8432
8433             IF ( nmrtbl > 0 )  THEN
8434                READ(88) mrtsky
8435                READ(88) mrtskyt
8436                READ(88) mrtdsit
8437             ENDIF
8438
8439             IF ( nmrtf > 0 )  THEN
8440                ALLOCATE ( mrtf(nmrtf) )
8441                ALLOCATE ( mrtft(nmrtf) )
8442                ALLOCATE ( mrtfsurf(2,nmrtf) )
8443                READ(88) mrtf
8444                READ(88) mrtft
8445                READ(88) mrtfsurf
8446             ENDIF
8447             
8448!
8449!--          Close binary file                 
8450             CALL close_file( 88 )
8451               
8452          ENDIF
8453#if defined( __parallel )
8454          CALL MPI_BARRIER( comm2d, ierr )
8455#endif
8456       ENDDO
8457
8458    END SUBROUTINE radiation_read_svf
8459
8460
8461!------------------------------------------------------------------------------!
8462!
8463! Description:
8464! ------------
8465!> Subroutine stores svf, svfsurf, csf, csfsurf and mrt data to a file.
8466!------------------------------------------------------------------------------!
8467    SUBROUTINE radiation_write_svf
8468
8469       IMPLICIT NONE
8470       
8471       INTEGER(iwp)        :: i
8472
8473       DO  i = 0, io_blocks-1
8474          IF ( i == io_group )  THEN
8475!
8476!--          Open binary file
8477             CALL check_open( 89 )
8478
8479             WRITE ( 89 )  rad_version
8480             WRITE ( 89 )  nsvfl, ncsfl, nsurfl, npcbl, ndsidir, nmrtbl, nmrtf
8481             IF ( nsurfl > 0 ) THEN
8482                WRITE ( 89 )  skyvf
8483                WRITE ( 89 )  skyvft
8484                WRITE ( 89 )  dsitrans
8485             ENDIF
8486             IF ( npcbl > 0 ) THEN
8487                WRITE ( 89 )  dsitransc
8488             ENDIF
8489             IF ( nsvfl > 0 ) THEN
8490                WRITE ( 89 )  svf
8491                WRITE ( 89 )  svfsurf
8492             ENDIF
8493             IF ( plant_canopy  .AND.  ncsfl > 0 )  THEN
8494                 WRITE ( 89 )  csf
8495                 WRITE ( 89 )  csfsurf
8496             ENDIF
8497             IF ( nmrtbl > 0 )  THEN
8498                WRITE ( 89 ) mrtsky
8499                WRITE ( 89 ) mrtskyt
8500                WRITE ( 89 ) mrtdsit
8501             ENDIF
8502             IF ( nmrtf > 0 )  THEN
8503                 WRITE ( 89 )  mrtf
8504                 WRITE ( 89 )  mrtft               
8505                 WRITE ( 89 )  mrtfsurf
8506             ENDIF
8507!
8508!--          Close binary file                 
8509             CALL close_file( 89 )
8510
8511          ENDIF
8512#if defined( __parallel )
8513          CALL MPI_BARRIER( comm2d, ierr )
8514#endif
8515       ENDDO
8516    END SUBROUTINE radiation_write_svf
8517
8518
8519!------------------------------------------------------------------------------!
8520!
8521! Description:
8522! ------------
8523!> Block of auxiliary subroutines:
8524!> 1. quicksort and corresponding comparison
8525!> 2. merge_and_grow_csf for implementation of "dynamical growing"
8526!>    array for csf
8527!------------------------------------------------------------------------------!
8528!-- quicksort.f -*-f90-*-
8529!-- Author: t-nissie, adaptation J.Resler
8530!-- License: GPLv3
8531!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8532    RECURSIVE SUBROUTINE quicksort_itarget(itarget, vffrac, ztransp, first, last)
8533        IMPLICIT NONE
8534        INTEGER(iwp), DIMENSION(:), INTENT(INOUT)   :: itarget
8535        REAL(wp), DIMENSION(:), INTENT(INOUT)       :: vffrac, ztransp
8536        INTEGER(iwp), INTENT(IN)                    :: first, last
8537        INTEGER(iwp)                                :: x, t
8538        INTEGER(iwp)                                :: i, j
8539        REAL(wp)                                    :: tr
8540
8541        IF ( first>=last ) RETURN
8542        x = itarget((first+last)/2)
8543        i = first
8544        j = last
8545        DO
8546            DO WHILE ( itarget(i) < x )
8547               i=i+1
8548            ENDDO
8549            DO WHILE ( x < itarget(j) )
8550                j=j-1
8551            ENDDO
8552            IF ( i >= j ) EXIT
8553            t = itarget(i);  itarget(i) = itarget(j);  itarget(j) = t
8554            tr = vffrac(i);  vffrac(i) = vffrac(j);  vffrac(j) = tr
8555            tr = ztransp(i);  ztransp(i) = ztransp(j);  ztransp(j) = tr
8556            i=i+1
8557            j=j-1
8558        ENDDO
8559        IF ( first < i-1 ) CALL quicksort_itarget(itarget, vffrac, ztransp, first, i-1)
8560        IF ( j+1 < last )  CALL quicksort_itarget(itarget, vffrac, ztransp, j+1, last)
8561    END SUBROUTINE quicksort_itarget
8562
8563    PURE FUNCTION svf_lt(svf1,svf2) result (res)
8564      TYPE (t_svf), INTENT(in) :: svf1,svf2
8565      LOGICAL                  :: res
8566      IF ( svf1%isurflt < svf2%isurflt  .OR.    &
8567          (svf1%isurflt == svf2%isurflt  .AND.  svf1%isurfs < svf2%isurfs) )  THEN
8568          res = .TRUE.
8569      ELSE
8570          res = .FALSE.
8571      ENDIF
8572    END FUNCTION svf_lt
8573
8574
8575!-- quicksort.f -*-f90-*-
8576!-- Author: t-nissie, adaptation J.Resler
8577!-- License: GPLv3
8578!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8579    RECURSIVE SUBROUTINE quicksort_svf(svfl, first, last)
8580        IMPLICIT NONE
8581        TYPE(t_svf), DIMENSION(:), INTENT(INOUT)  :: svfl
8582        INTEGER(iwp), INTENT(IN)                  :: first, last
8583        TYPE(t_svf)                               :: x, t
8584        INTEGER(iwp)                              :: i, j
8585
8586        IF ( first>=last ) RETURN
8587        x = svfl( (first+last) / 2 )
8588        i = first
8589        j = last
8590        DO
8591            DO while ( svf_lt(svfl(i),x) )
8592               i=i+1
8593            ENDDO
8594            DO while ( svf_lt(x,svfl(j)) )
8595                j=j-1
8596            ENDDO
8597            IF ( i >= j ) EXIT
8598            t = svfl(i);  svfl(i) = svfl(j);  svfl(j) = t
8599            i=i+1
8600            j=j-1
8601        ENDDO
8602        IF ( first < i-1 ) CALL quicksort_svf(svfl, first, i-1)
8603        IF ( j+1 < last )  CALL quicksort_svf(svfl, j+1, last)
8604    END SUBROUTINE quicksort_svf
8605
8606    PURE FUNCTION csf_lt(csf1,csf2) result (res)
8607      TYPE (t_csf), INTENT(in) :: csf1,csf2
8608      LOGICAL                  :: res
8609      IF ( csf1%ip < csf2%ip  .OR.    &
8610           (csf1%ip == csf2%ip  .AND.  csf1%itx < csf2%itx)  .OR.  &
8611           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity < csf2%ity)  .OR.  &
8612           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity == csf2%ity  .AND.   &
8613            csf1%itz < csf2%itz)  .OR.  &
8614           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity == csf2%ity  .AND.   &
8615            csf1%itz == csf2%itz  .AND.  csf1%isurfs < csf2%isurfs) )  THEN
8616          res = .TRUE.
8617      ELSE
8618          res = .FALSE.
8619      ENDIF
8620    END FUNCTION csf_lt
8621
8622
8623!-- quicksort.f -*-f90-*-
8624!-- Author: t-nissie, adaptation J.Resler
8625!-- License: GPLv3
8626!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8627    RECURSIVE SUBROUTINE quicksort_csf(csfl, first, last)
8628        IMPLICIT NONE
8629        TYPE(t_csf), DIMENSION(:), INTENT(INOUT)  :: csfl
8630        INTEGER(iwp), INTENT(IN)                  :: first, last
8631        TYPE(t_csf)                               :: x, t
8632        INTEGER(iwp)                              :: i, j
8633
8634        IF ( first>=last ) RETURN
8635        x = csfl( (first+last)/2 )
8636        i = first
8637        j = last
8638        DO
8639            DO while ( csf_lt(csfl(i),x) )
8640                i=i+1
8641            ENDDO
8642            DO while ( csf_lt(x,csfl(j)) )
8643                j=j-1
8644            ENDDO
8645            IF ( i >= j ) EXIT
8646            t = csfl(i);  csfl(i) = csfl(j);  csfl(j) = t
8647            i=i+1
8648            j=j-1
8649        ENDDO
8650        IF ( first < i-1 ) CALL quicksort_csf(csfl, first, i-1)
8651        IF ( j+1 < last )  CALL quicksort_csf(csfl, j+1, last)
8652    END SUBROUTINE quicksort_csf
8653
8654   
8655    SUBROUTINE merge_and_grow_csf(newsize)
8656        INTEGER(iwp), INTENT(in)                :: newsize  !< new array size after grow, must be >= ncsfl
8657                                                            !< or -1 to shrink to minimum
8658        INTEGER(iwp)                            :: iread, iwrite
8659        TYPE(t_csf), DIMENSION(:), POINTER      :: acsfnew
8660        CHARACTER(100)                          :: msg
8661
8662        IF ( newsize == -1 )  THEN
8663!--         merge in-place
8664            acsfnew => acsf
8665        ELSE
8666!--         allocate new array
8667            IF ( mcsf == 0 )  THEN
8668                ALLOCATE( acsf1(newsize) )
8669                acsfnew => acsf1
8670            ELSE
8671                ALLOCATE( acsf2(newsize) )
8672                acsfnew => acsf2
8673            ENDIF
8674        ENDIF
8675
8676        IF ( ncsfl >= 1 )  THEN
8677!--         sort csf in place (quicksort)
8678            CALL quicksort_csf(acsf,1,ncsfl)
8679
8680!--         while moving to a new array, aggregate canopy sink factor records with identical box & source
8681            acsfnew(1) = acsf(1)
8682            iwrite = 1
8683            DO iread = 2, ncsfl
8684!--             here acsf(kcsf) already has values from acsf(icsf)
8685                IF ( acsfnew(iwrite)%itx == acsf(iread)%itx &
8686                         .AND.  acsfnew(iwrite)%ity == acsf(iread)%ity &
8687                         .AND.  acsfnew(iwrite)%itz == acsf(iread)%itz &
8688                         .AND.  acsfnew(iwrite)%isurfs == acsf(iread)%isurfs )  THEN
8689
8690                    acsfnew(iwrite)%rcvf = acsfnew(iwrite)%rcvf + acsf(iread)%rcvf
8691!--                 advance reading index, keep writing index
8692                ELSE
8693!--                 not identical, just advance and copy
8694                    iwrite = iwrite + 1
8695                    acsfnew(iwrite) = acsf(iread)
8696                ENDIF
8697            ENDDO
8698            ncsfl = iwrite
8699        ENDIF
8700
8701        IF ( newsize == -1 )  THEN
8702!--         allocate new array and copy shrinked data
8703            IF ( mcsf == 0 )  THEN
8704                ALLOCATE( acsf1(ncsfl) )
8705                acsf1(1:ncsfl) = acsf2(1:ncsfl)
8706            ELSE
8707                ALLOCATE( acsf2(ncsfl) )
8708                acsf2(1:ncsfl) = acsf1(1:ncsfl)
8709            ENDIF
8710        ENDIF
8711
8712!--     deallocate old array
8713        IF ( mcsf == 0 )  THEN
8714            mcsf = 1
8715            acsf => acsf1
8716            DEALLOCATE( acsf2 )
8717        ELSE
8718            mcsf = 0
8719            acsf => acsf2
8720            DEALLOCATE( acsf1 )
8721        ENDIF
8722        ncsfla = newsize
8723
8724        WRITE(msg,'(A,2I12)') 'Grow acsf2:',ncsfl,ncsfla
8725        CALL radiation_write_debug_log( msg )
8726
8727    END SUBROUTINE merge_and_grow_csf
8728
8729   
8730!-- quicksort.f -*-f90-*-
8731!-- Author: t-nissie, adaptation J.Resler
8732!-- License: GPLv3
8733!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8734    RECURSIVE SUBROUTINE quicksort_csf2(kpcsflt, pcsflt, first, last)
8735        IMPLICIT NONE
8736        INTEGER(iwp), DIMENSION(:,:), INTENT(INOUT)  :: kpcsflt
8737        REAL(wp), DIMENSION(:,:), INTENT(INOUT)      :: pcsflt
8738        INTEGER(iwp), INTENT(IN)                     :: first, last
8739        REAL(wp), DIMENSION(ndcsf)                   :: t2
8740        INTEGER(iwp), DIMENSION(kdcsf)               :: x, t1
8741        INTEGER(iwp)                                 :: i, j
8742
8743        IF ( first>=last ) RETURN
8744        x = kpcsflt(:, (first+last)/2 )
8745        i = first
8746        j = last
8747        DO
8748            DO while ( csf_lt2(kpcsflt(:,i),x) )
8749                i=i+1
8750            ENDDO
8751            DO while ( csf_lt2(x,kpcsflt(:,j)) )
8752                j=j-1
8753            ENDDO
8754            IF ( i >= j ) EXIT
8755            t1 = kpcsflt(:,i);  kpcsflt(:,i) = kpcsflt(:,j);  kpcsflt(:,j) = t1
8756            t2 = pcsflt(:,i);  pcsflt(:,i) = pcsflt(:,j);  pcsflt(:,j) = t2
8757            i=i+1
8758            j=j-1
8759        ENDDO
8760        IF ( first < i-1 ) CALL quicksort_csf2(kpcsflt, pcsflt, first, i-1)
8761        IF ( j+1 < last )  CALL quicksort_csf2(kpcsflt, pcsflt, j+1, last)
8762    END SUBROUTINE quicksort_csf2
8763   
8764
8765    PURE FUNCTION csf_lt2(item1, item2) result(res)
8766        INTEGER(iwp), DIMENSION(kdcsf), INTENT(in)  :: item1, item2
8767        LOGICAL                                     :: res
8768        res = ( (item1(3) < item2(3))                                                        &
8769             .OR.  (item1(3) == item2(3)  .AND.  item1(2) < item2(2))                            &
8770             .OR.  (item1(3) == item2(3)  .AND.  item1(2) == item2(2)  .AND.  item1(1) < item2(1)) &
8771             .OR.  (item1(3) == item2(3)  .AND.  item1(2) == item2(2)  .AND.  item1(1) == item2(1) &
8772                 .AND.  item1(4) < item2(4)) )
8773    END FUNCTION csf_lt2
8774
8775    PURE FUNCTION searchsorted(athresh, val) result(ind)
8776        REAL(wp), DIMENSION(:), INTENT(IN)  :: athresh
8777        REAL(wp), INTENT(IN)                :: val
8778        INTEGER(iwp)                        :: ind
8779        INTEGER(iwp)                        :: i
8780
8781        DO i = LBOUND(athresh, 1), UBOUND(athresh, 1)
8782            IF ( val < athresh(i) ) THEN
8783                ind = i - 1
8784                RETURN
8785            ENDIF
8786        ENDDO
8787        ind = UBOUND(athresh, 1)
8788    END FUNCTION searchsorted
8789
8790!------------------------------------------------------------------------------!
8791! Description:
8792! ------------
8793!
8794!> radiation_radflux_gridbox subroutine gives the sw and lw radiation fluxes at the
8795!> faces of a gridbox defined at i,j,k and located in the urban layer.
8796!> The total sw and the diffuse sw radiation as well as the lw radiation fluxes at
8797!> the gridbox 6 faces are stored in sw_gridbox, swd_gridbox, and lw_gridbox arrays,
8798!> respectively, in the following order:
8799!>  up_face, down_face, north_face, south_face, east_face, west_face
8800!>
8801!> The subroutine reports also how successful was the search process via the parameter
8802!> i_feedback as follow:
8803!> - i_feedback =  1 : successful
8804!> - i_feedback = -1 : unsuccessful; the requisted point is outside the urban domain
8805!> - i_feedback =  0 : uncomplete; some gridbox faces fluxes are missing
8806!>
8807!>
8808!> It is called outside from usm_urban_surface_mod whenever the radiation fluxes
8809!> are needed.
8810!>
8811!> This routine is not used so far. However, it may serve as an interface for radiation
8812!> fluxes of urban and land surfaces
8813!>
8814!> TODO:
8815!>    - Compare performance when using some combination of the Fortran intrinsic
8816!>      functions, e.g. MINLOC, MAXLOC, ALL, ANY and COUNT functions, which search
8817!>      surfl array for elements meeting user-specified criterion, i.e. i,j,k
8818!>    - Report non-found or incomplete radiation fluxes arrays , if any, at the
8819!>      gridbox faces in an error message form
8820!>
8821!------------------------------------------------------------------------------!
8822    SUBROUTINE radiation_radflux_gridbox(i,j,k,sw_gridbox,swd_gridbox,lw_gridbox,i_feedback)
8823       
8824        IMPLICIT NONE
8825
8826        INTEGER(iwp),                 INTENT(in)  :: i,j,k                 !< gridbox indices at which fluxes are required
8827        INTEGER(iwp)                              :: ii,jj,kk,d            !< surface indices and type
8828        INTEGER(iwp)                              :: l                     !< surface id
8829        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
8830        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
8831        INTEGER(iwp),                 INTENT(out) :: i_feedback            !< feedback to report how the search was successful
8832
8833
8834!-- initialize variables
8835        i_feedback  = -999999
8836        sw_gridbox  = -999999.9_wp
8837        lw_gridbox  = -999999.9_wp
8838        swd_gridbox = -999999.9_wp
8839       
8840!-- check the requisted grid indices
8841        IF ( k < nzb   .OR.  k > nzut  .OR.   &
8842             j < nysg  .OR.  j > nyng  .OR.   &
8843             i < nxlg  .OR.  i > nxrg         &
8844             ) THEN
8845           i_feedback = -1
8846           RETURN
8847        ENDIF
8848
8849!-- search for the required grid and formulate the fluxes at the 6 gridbox faces
8850        DO l = 1, nsurfl
8851            ii = surfl(ix,l)
8852            jj = surfl(iy,l)
8853            kk = surfl(iz,l)
8854
8855            IF ( ii == i  .AND.  jj == j  .AND.  kk == k ) THEN
8856               d = surfl(id,l)
8857
8858               SELECT CASE ( d )
8859
8860               CASE (iup_u,iup_l)                          !- gridbox up_facing face
8861                  sw_gridbox(1) = surfinsw(l)
8862                  lw_gridbox(1) = surfinlw(l)
8863                  swd_gridbox(1) = surfinswdif(l)
8864
8865               CASE (inorth_u,inorth_l)                    !- gridbox north_facing face
8866                  sw_gridbox(3) = surfinsw(l)
8867                  lw_gridbox(3) = surfinlw(l)
8868                  swd_gridbox(3) = surfinswdif(l)
8869
8870               CASE (isouth_u,isouth_l)                    !- gridbox south_facing face
8871                  sw_gridbox(4) = surfinsw(l)
8872                  lw_gridbox(4) = surfinlw(l)
8873                  swd_gridbox(4) = surfinswdif(l)
8874
8875               CASE (ieast_u,ieast_l)                      !- gridbox east_facing face
8876                  sw_gridbox(5) = surfinsw(l)
8877                  lw_gridbox(5) = surfinlw(l)
8878                  swd_gridbox(5) = surfinswdif(l)
8879
8880               CASE (iwest_u,iwest_l)                      !- gridbox west_facing face
8881                  sw_gridbox(6) = surfinsw(l)
8882                  lw_gridbox(6) = surfinlw(l)
8883                  swd_gridbox(6) = surfinswdif(l)
8884
8885               END SELECT
8886
8887            ENDIF
8888
8889        IF ( ALL( sw_gridbox(:)  /= -999999.9_wp )  ) EXIT
8890        ENDDO
8891
8892!-- check the completeness of the fluxes at all gidbox faces       
8893!-- TODO: report non-found or incomplete rad fluxes arrays in an error message form
8894        IF ( ANY( sw_gridbox(:)  <= -999999.9_wp )  .OR.   &
8895             ANY( swd_gridbox(:) <= -999999.9_wp )  .OR.   &
8896             ANY( lw_gridbox(:)  <= -999999.9_wp ) ) THEN
8897           i_feedback = 0
8898        ELSE
8899           i_feedback = 1
8900        ENDIF
8901       
8902        RETURN
8903       
8904    END SUBROUTINE radiation_radflux_gridbox
8905
8906!------------------------------------------------------------------------------!
8907!
8908! Description:
8909! ------------
8910!> Subroutine for averaging 3D data
8911!------------------------------------------------------------------------------!
8912SUBROUTINE radiation_3d_data_averaging( mode, variable )
8913 
8914
8915    USE control_parameters
8916
8917    USE indices
8918
8919    USE kinds
8920
8921    IMPLICIT NONE
8922
8923    CHARACTER (LEN=*) ::  mode    !<
8924    CHARACTER (LEN=*) :: variable !<
8925
8926    LOGICAL      ::  match_lsm !< flag indicating natural-type surface
8927    LOGICAL      ::  match_usm !< flag indicating urban-type surface
8928   
8929    INTEGER(iwp) ::  i !<
8930    INTEGER(iwp) ::  j !<
8931    INTEGER(iwp) ::  k !<
8932    INTEGER(iwp) ::  l, m !< index of current surface element
8933
8934    INTEGER(iwp)                                       :: ids, idsint_u, idsint_l, isurf
8935    CHARACTER(LEN=varnamelength)                       :: var
8936
8937!-- find the real name of the variable
8938    ids = -1
8939    l = -1
8940    var = TRIM(variable)
8941    DO i = 0, nd-1
8942        k = len(TRIM(var))
8943        j = len(TRIM(dirname(i)))
8944        IF ( k-j+1 >= 1_iwp ) THEN
8945           IF ( TRIM(var(k-j+1:k)) == TRIM(dirname(i)) )  THEN
8946               ids = i
8947               idsint_u = dirint_u(ids)
8948               idsint_l = dirint_l(ids)
8949               var = var(:k-j)
8950               EXIT
8951           ENDIF
8952        ENDIF
8953    ENDDO
8954    IF ( ids == -1 )  THEN
8955        var = TRIM(variable)
8956    ENDIF
8957
8958    IF ( mode == 'allocate' )  THEN
8959
8960       SELECT CASE ( TRIM( var ) )
8961!--          block of large scale (e.g. RRTMG) radiation output variables
8962             CASE ( 'rad_net*' )
8963                IF ( .NOT. ALLOCATED( rad_net_av ) )  THEN
8964                   ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
8965                ENDIF
8966                rad_net_av = 0.0_wp
8967             
8968             CASE ( 'rad_lw_in*' )
8969                IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) )  THEN
8970                   ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
8971                ENDIF
8972                rad_lw_in_xy_av = 0.0_wp
8973               
8974             CASE ( 'rad_lw_out*' )
8975                IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) )  THEN
8976                   ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
8977                ENDIF
8978                rad_lw_out_xy_av = 0.0_wp
8979               
8980             CASE ( 'rad_sw_in*' )
8981                IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) )  THEN
8982                   ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
8983                ENDIF
8984                rad_sw_in_xy_av = 0.0_wp
8985               
8986             CASE ( 'rad_sw_out*' )
8987                IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) )  THEN
8988                   ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
8989                ENDIF
8990                rad_sw_out_xy_av = 0.0_wp               
8991
8992             CASE ( 'rad_lw_in' )
8993                IF ( .NOT. ALLOCATED( rad_lw_in_av ) )  THEN
8994                   ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8995                ENDIF
8996                rad_lw_in_av = 0.0_wp
8997
8998             CASE ( 'rad_lw_out' )
8999                IF ( .NOT. ALLOCATED( rad_lw_out_av ) )  THEN
9000                   ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9001                ENDIF
9002                rad_lw_out_av = 0.0_wp
9003
9004             CASE ( 'rad_lw_cs_hr' )
9005                IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) )  THEN
9006                   ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9007                ENDIF
9008                rad_lw_cs_hr_av = 0.0_wp
9009
9010             CASE ( 'rad_lw_hr' )
9011                IF ( .NOT. ALLOCATED( rad_lw_hr_av ) )  THEN
9012                   ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9013                ENDIF
9014                rad_lw_hr_av = 0.0_wp
9015
9016             CASE ( 'rad_sw_in' )
9017                IF ( .NOT. ALLOCATED( rad_sw_in_av ) )  THEN
9018                   ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9019                ENDIF
9020                rad_sw_in_av = 0.0_wp
9021
9022             CASE ( 'rad_sw_out' )
9023                IF ( .NOT. ALLOCATED( rad_sw_out_av ) )  THEN
9024                   ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9025                ENDIF
9026                rad_sw_out_av = 0.0_wp
9027
9028             CASE ( 'rad_sw_cs_hr' )
9029                IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) )  THEN
9030                   ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9031                ENDIF
9032                rad_sw_cs_hr_av = 0.0_wp
9033
9034             CASE ( 'rad_sw_hr' )
9035                IF ( .NOT. ALLOCATED( rad_sw_hr_av ) )  THEN
9036                   ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9037                ENDIF
9038                rad_sw_hr_av = 0.0_wp
9039
9040!--          block of RTM output variables
9041             CASE ( 'rtm_rad_net' )
9042!--              array of complete radiation balance
9043                 IF ( .NOT.  ALLOCATED(surfradnet_av) )  THEN
9044                     ALLOCATE( surfradnet_av(nsurfl) )
9045                     surfradnet_av = 0.0_wp
9046                 ENDIF
9047
9048             CASE ( 'rtm_rad_insw' )
9049!--                 array of sw radiation falling to surface after i-th reflection
9050                 IF ( .NOT.  ALLOCATED(surfinsw_av) )  THEN
9051                     ALLOCATE( surfinsw_av(nsurfl) )
9052                     surfinsw_av = 0.0_wp
9053                 ENDIF
9054
9055             CASE ( 'rtm_rad_inlw' )
9056!--                 array of lw radiation falling to surface after i-th reflection
9057                 IF ( .NOT.  ALLOCATED(surfinlw_av) )  THEN
9058                     ALLOCATE( surfinlw_av(nsurfl) )
9059                     surfinlw_av = 0.0_wp
9060                 ENDIF
9061
9062             CASE ( 'rtm_rad_inswdir' )
9063!--                 array of direct sw radiation falling to surface from sun
9064                 IF ( .NOT.  ALLOCATED(surfinswdir_av) )  THEN
9065                     ALLOCATE( surfinswdir_av(nsurfl) )
9066                     surfinswdir_av = 0.0_wp
9067                 ENDIF
9068
9069             CASE ( 'rtm_rad_inswdif' )
9070!--                 array of difusion sw radiation falling to surface from sky and borders of the domain
9071                 IF ( .NOT.  ALLOCATED(surfinswdif_av) )  THEN
9072                     ALLOCATE( surfinswdif_av(nsurfl) )
9073                     surfinswdif_av = 0.0_wp
9074                 ENDIF
9075
9076             CASE ( 'rtm_rad_inswref' )
9077!--                 array of sw radiation falling to surface from reflections
9078                 IF ( .NOT.  ALLOCATED(surfinswref_av) )  THEN
9079                     ALLOCATE( surfinswref_av(nsurfl) )
9080                     surfinswref_av = 0.0_wp
9081                 ENDIF
9082
9083             CASE ( 'rtm_rad_inlwdif' )
9084!--                 array of sw radiation falling to surface after i-th reflection
9085                IF ( .NOT.  ALLOCATED(surfinlwdif_av) )  THEN
9086                     ALLOCATE( surfinlwdif_av(nsurfl) )
9087                     surfinlwdif_av = 0.0_wp
9088                 ENDIF
9089
9090             CASE ( 'rtm_rad_inlwref' )
9091!--                 array of lw radiation falling to surface from reflections
9092                 IF ( .NOT.  ALLOCATED(surfinlwref_av) )  THEN
9093                     ALLOCATE( surfinlwref_av(nsurfl) )
9094                     surfinlwref_av = 0.0_wp
9095                 ENDIF
9096
9097             CASE ( 'rtm_rad_outsw' )
9098!--                 array of sw radiation emitted from surface after i-th reflection
9099                 IF ( .NOT.  ALLOCATED(surfoutsw_av) )  THEN
9100                     ALLOCATE( surfoutsw_av(nsurfl) )
9101                     surfoutsw_av = 0.0_wp
9102                 ENDIF
9103
9104             CASE ( 'rtm_rad_outlw' )
9105!--                 array of lw radiation emitted from surface after i-th reflection
9106                 IF ( .NOT.  ALLOCATED(surfoutlw_av) )  THEN
9107                     ALLOCATE( surfoutlw_av(nsurfl) )
9108                     surfoutlw_av = 0.0_wp
9109                 ENDIF
9110             CASE ( 'rtm_rad_ressw' )
9111!--                 array of residua of sw radiation absorbed in surface after last reflection
9112                 IF ( .NOT.  ALLOCATED(surfins_av) )  THEN
9113                     ALLOCATE( surfins_av(nsurfl) )
9114                     surfins_av = 0.0_wp
9115                 ENDIF
9116
9117             CASE ( 'rtm_rad_reslw' )
9118!--                 array of residua of lw radiation absorbed in surface after last reflection
9119                 IF ( .NOT.  ALLOCATED(surfinl_av) )  THEN
9120                     ALLOCATE( surfinl_av(nsurfl) )
9121                     surfinl_av = 0.0_wp
9122                 ENDIF
9123
9124             CASE ( 'rtm_rad_pc_inlw' )
9125!--                 array of of lw radiation absorbed in plant canopy
9126                 IF ( .NOT.  ALLOCATED(pcbinlw_av) )  THEN
9127                     ALLOCATE( pcbinlw_av(1:npcbl) )
9128                     pcbinlw_av = 0.0_wp
9129                 ENDIF
9130
9131             CASE ( 'rtm_rad_pc_insw' )
9132!--                 array of of sw radiation absorbed in plant canopy
9133                 IF ( .NOT.  ALLOCATED(pcbinsw_av) )  THEN
9134                     ALLOCATE( pcbinsw_av(1:npcbl) )
9135                     pcbinsw_av = 0.0_wp
9136                 ENDIF
9137
9138             CASE ( 'rtm_rad_pc_inswdir' )
9139!--                 array of of direct sw radiation absorbed in plant canopy
9140                 IF ( .NOT.  ALLOCATED(pcbinswdir_av) )  THEN
9141                     ALLOCATE( pcbinswdir_av(1:npcbl) )
9142                     pcbinswdir_av = 0.0_wp
9143                 ENDIF
9144
9145             CASE ( 'rtm_rad_pc_inswdif' )
9146!--                 array of of diffuse sw radiation absorbed in plant canopy
9147                 IF ( .NOT.  ALLOCATED(pcbinswdif_av) )  THEN
9148                     ALLOCATE( pcbinswdif_av(1:npcbl) )
9149                     pcbinswdif_av = 0.0_wp
9150                 ENDIF
9151
9152             CASE ( 'rtm_rad_pc_inswref' )
9153!--                 array of of reflected sw radiation absorbed in plant canopy
9154                 IF ( .NOT.  ALLOCATED(pcbinswref_av) )  THEN
9155                     ALLOCATE( pcbinswref_av(1:npcbl) )
9156                     pcbinswref_av = 0.0_wp
9157                 ENDIF
9158
9159             CASE ( 'rtm_mrt_sw' )
9160                IF ( .NOT. ALLOCATED( mrtinsw_av ) )  THEN
9161                   ALLOCATE( mrtinsw_av(nmrtbl) )
9162                ENDIF
9163                mrtinsw_av = 0.0_wp
9164
9165             CASE ( 'rtm_mrt_lw' )
9166                IF ( .NOT. ALLOCATED( mrtinlw_av ) )  THEN
9167                   ALLOCATE( mrtinlw_av(nmrtbl) )
9168                ENDIF
9169                mrtinlw_av = 0.0_wp
9170
9171             CASE ( 'rtm_mrt' )
9172                IF ( .NOT. ALLOCATED( mrt_av ) )  THEN
9173                   ALLOCATE( mrt_av(nmrtbl) )
9174                ENDIF
9175                mrt_av = 0.0_wp
9176
9177          CASE DEFAULT
9178             CONTINUE
9179
9180       END SELECT
9181
9182    ELSEIF ( mode == 'sum' )  THEN
9183
9184       SELECT CASE ( TRIM( var ) )
9185!--       block of large scale (e.g. RRTMG) radiation output variables
9186          CASE ( 'rad_net*' )
9187             IF ( ALLOCATED( rad_net_av ) ) THEN
9188                DO  i = nxl, nxr
9189                   DO  j = nys, nyn
9190                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9191                                  surf_lsm_h%end_index(j,i)
9192                      match_usm = surf_usm_h%start_index(j,i) <=               &
9193                                  surf_usm_h%end_index(j,i)
9194
9195                     IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9196                         m = surf_lsm_h%end_index(j,i)
9197                         rad_net_av(j,i) = rad_net_av(j,i) +                   &
9198                                         surf_lsm_h%rad_net(m)
9199                      ELSEIF ( match_usm )  THEN
9200                         m = surf_usm_h%end_index(j,i)
9201                         rad_net_av(j,i) = rad_net_av(j,i) +                   &
9202                                         surf_usm_h%rad_net(m)
9203                      ENDIF
9204                   ENDDO
9205                ENDDO
9206             ENDIF
9207
9208          CASE ( 'rad_lw_in*' )
9209             IF ( ALLOCATED( rad_lw_in_xy_av ) ) THEN
9210                DO  i = nxl, nxr
9211                   DO  j = nys, nyn
9212                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9213                                  surf_lsm_h%end_index(j,i)
9214                      match_usm = surf_usm_h%start_index(j,i) <=               &
9215                                  surf_usm_h%end_index(j,i)
9216
9217                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9218                         m = surf_lsm_h%end_index(j,i)
9219                         rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i) +         &
9220                                         surf_lsm_h%rad_lw_in(m)
9221                      ELSEIF ( match_usm )  THEN
9222                         m = surf_usm_h%end_index(j,i)
9223                         rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i) +         &
9224                                         surf_usm_h%rad_lw_in(m)
9225                      ENDIF
9226                   ENDDO
9227                ENDDO
9228             ENDIF
9229             
9230          CASE ( 'rad_lw_out*' )
9231             IF ( ALLOCATED( rad_lw_out_xy_av ) ) THEN
9232                DO  i = nxl, nxr
9233                   DO  j = nys, nyn
9234                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9235                                  surf_lsm_h%end_index(j,i)
9236                      match_usm = surf_usm_h%start_index(j,i) <=               &
9237                                  surf_usm_h%end_index(j,i)
9238
9239                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9240                         m = surf_lsm_h%end_index(j,i)
9241                         rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i) +       &
9242                                                 surf_lsm_h%rad_lw_out(m)
9243                      ELSEIF ( match_usm )  THEN
9244                         m = surf_usm_h%end_index(j,i)
9245                         rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i) +       &
9246                                                 surf_usm_h%rad_lw_out(m)
9247                      ENDIF
9248                   ENDDO
9249                ENDDO
9250             ENDIF
9251             
9252          CASE ( 'rad_sw_in*' )
9253             IF ( ALLOCATED( rad_sw_in_xy_av ) ) THEN
9254                DO  i = nxl, nxr
9255                   DO  j = nys, nyn
9256                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9257                                  surf_lsm_h%end_index(j,i)
9258                      match_usm = surf_usm_h%start_index(j,i) <=               &
9259                                  surf_usm_h%end_index(j,i)
9260
9261                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9262                         m = surf_lsm_h%end_index(j,i)
9263                         rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i) +         &
9264                                                surf_lsm_h%rad_sw_in(m)
9265                      ELSEIF ( match_usm )  THEN
9266                         m = surf_usm_h%end_index(j,i)
9267                         rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i) +         &
9268                                                surf_usm_h%rad_sw_in(m)
9269                      ENDIF
9270                   ENDDO
9271                ENDDO
9272             ENDIF
9273             
9274          CASE ( 'rad_sw_out*' )
9275             IF ( ALLOCATED( rad_sw_out_xy_av ) ) THEN
9276                DO  i = nxl, nxr
9277                   DO  j = nys, nyn
9278                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9279                                  surf_lsm_h%end_index(j,i)
9280                      match_usm = surf_usm_h%start_index(j,i) <=               &
9281                                  surf_usm_h%end_index(j,i)
9282
9283                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9284                         m = surf_lsm_h%end_index(j,i)
9285                         rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i) +       &
9286                                                 surf_lsm_h%rad_sw_out(m)
9287                      ELSEIF ( match_usm )  THEN
9288                         m = surf_usm_h%end_index(j,i)
9289                         rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i) +       &
9290                                                 surf_usm_h%rad_sw_out(m)
9291                      ENDIF
9292                   ENDDO
9293                ENDDO
9294             ENDIF
9295             
9296          CASE ( 'rad_lw_in' )
9297             IF ( ALLOCATED( rad_lw_in_av ) ) THEN
9298                DO  i = nxlg, nxrg
9299                   DO  j = nysg, nyng
9300                      DO  k = nzb, nzt+1
9301                         rad_lw_in_av(k,j,i) = rad_lw_in_av(k,j,i)             &
9302                                               + rad_lw_in(k,j,i)
9303                      ENDDO
9304                   ENDDO
9305                ENDDO
9306             ENDIF
9307
9308          CASE ( 'rad_lw_out' )
9309             IF ( ALLOCATED( rad_lw_out_av ) ) THEN
9310                DO  i = nxlg, nxrg
9311                   DO  j = nysg, nyng
9312                      DO  k = nzb, nzt+1
9313                         rad_lw_out_av(k,j,i) = rad_lw_out_av(k,j,i)           &
9314                                                + rad_lw_out(k,j,i)
9315                      ENDDO
9316                   ENDDO
9317                ENDDO
9318             ENDIF
9319
9320          CASE ( 'rad_lw_cs_hr' )
9321             IF ( ALLOCATED( rad_lw_cs_hr_av ) ) THEN
9322                DO  i = nxlg, nxrg
9323                   DO  j = nysg, nyng
9324                      DO  k = nzb, nzt+1
9325                         rad_lw_cs_hr_av(k,j,i) = rad_lw_cs_hr_av(k,j,i)       &
9326                                                  + rad_lw_cs_hr(k,j,i)
9327                      ENDDO
9328                   ENDDO
9329                ENDDO
9330             ENDIF
9331
9332          CASE ( 'rad_lw_hr' )
9333             IF ( ALLOCATED( rad_lw_hr_av ) ) THEN
9334                DO  i = nxlg, nxrg
9335                   DO  j = nysg, nyng
9336                      DO  k = nzb, nzt+1
9337                         rad_lw_hr_av(k,j,i) = rad_lw_hr_av(k,j,i)             &
9338                                               + rad_lw_hr(k,j,i)
9339                      ENDDO
9340                   ENDDO
9341                ENDDO
9342             ENDIF
9343
9344          CASE ( 'rad_sw_in' )
9345             IF ( ALLOCATED( rad_sw_in_av ) ) THEN
9346                DO  i = nxlg, nxrg
9347                   DO  j = nysg, nyng
9348                      DO  k = nzb, nzt+1
9349                         rad_sw_in_av(k,j,i) = rad_sw_in_av(k,j,i)             &
9350                                               + rad_sw_in(k,j,i)
9351                      ENDDO
9352                   ENDDO
9353                ENDDO
9354             ENDIF
9355
9356          CASE ( 'rad_sw_out' )
9357             IF ( ALLOCATED( rad_sw_out_av ) ) THEN
9358                DO  i = nxlg, nxrg
9359                   DO  j = nysg, nyng
9360                      DO  k = nzb, nzt+1
9361                         rad_sw_out_av(k,j,i) = rad_sw_out_av(k,j,i)           &
9362                                                + rad_sw_out(k,j,i)
9363                      ENDDO
9364                   ENDDO
9365                ENDDO
9366             ENDIF
9367
9368          CASE ( 'rad_sw_cs_hr' )
9369             IF ( ALLOCATED( rad_sw_cs_hr_av ) ) THEN
9370                DO  i = nxlg, nxrg
9371                   DO  j = nysg, nyng
9372                      DO  k = nzb, nzt+1
9373                         rad_sw_cs_hr_av(k,j,i) = rad_sw_cs_hr_av(k,j,i)       &
9374                                                  + rad_sw_cs_hr(k,j,i)
9375                      ENDDO
9376                   ENDDO
9377                ENDDO
9378             ENDIF
9379
9380          CASE ( 'rad_sw_hr' )
9381             IF ( ALLOCATED( rad_sw_hr_av ) ) THEN
9382                DO  i = nxlg, nxrg
9383                   DO  j = nysg, nyng
9384                      DO  k = nzb, nzt+1
9385                         rad_sw_hr_av(k,j,i) = rad_sw_hr_av(k,j,i)             &
9386                                               + rad_sw_hr(k,j,i)
9387                      ENDDO
9388                   ENDDO
9389                ENDDO
9390             ENDIF
9391
9392!--       block of RTM output variables
9393          CASE ( 'rtm_rad_net' )
9394!--           array of complete radiation balance
9395              DO isurf = dirstart(ids), dirend(ids)
9396                 IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9397                    surfradnet_av(isurf) = surfinsw(isurf) - surfoutsw(isurf) +  surfinlw(isurf) - surfoutlw(isurf)
9398                 ENDIF
9399              ENDDO
9400
9401          CASE ( 'rtm_rad_insw' )
9402!--           array of sw radiation falling to surface after i-th reflection
9403              DO isurf = dirstart(ids), dirend(ids)
9404                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9405                      surfinsw_av(isurf) = surfinsw_av(isurf) + surfinsw(isurf)
9406                  ENDIF
9407              ENDDO
9408
9409          CASE ( 'rtm_rad_inlw' )
9410!--           array of lw radiation falling to surface after i-th reflection
9411              DO isurf = dirstart(ids), dirend(ids)
9412                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9413                      surfinlw_av(isurf) = surfinlw_av(isurf) + surfinlw(isurf)
9414                  ENDIF
9415              ENDDO
9416
9417          CASE ( 'rtm_rad_inswdir' )
9418!--           array of direct sw radiation falling to surface from sun
9419              DO isurf = dirstart(ids), dirend(ids)
9420                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9421                      surfinswdir_av(isurf) = surfinswdir_av(isurf) + surfinswdir(isurf)
9422                  ENDIF
9423              ENDDO
9424
9425          CASE ( 'rtm_rad_inswdif' )
9426!--           array of difusion sw radiation falling to surface from sky and borders of the domain
9427              DO isurf = dirstart(ids), dirend(ids)
9428                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9429                      surfinswdif_av(isurf) = surfinswdif_av(isurf) + surfinswdif(isurf)
9430                  ENDIF
9431              ENDDO
9432
9433          CASE ( 'rtm_rad_inswref' )
9434!--           array of sw radiation falling to surface from reflections
9435              DO isurf = dirstart(ids), dirend(ids)
9436                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9437                      surfinswref_av(isurf) = surfinswref_av(isurf) + surfinsw(isurf) - &
9438                                          surfinswdir(isurf) - surfinswdif(isurf)
9439                  ENDIF
9440              ENDDO
9441
9442
9443          CASE ( 'rtm_rad_inlwdif' )
9444!--           array of sw radiation falling to surface after i-th reflection
9445              DO isurf = dirstart(ids), dirend(ids)
9446                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9447                      surfinlwdif_av(isurf) = surfinlwdif_av(isurf) + surfinlwdif(isurf)
9448                  ENDIF
9449              ENDDO
9450!
9451          CASE ( 'rtm_rad_inlwref' )
9452!--           array of lw radiation falling to surface from reflections
9453              DO isurf = dirstart(ids), dirend(ids)
9454                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9455                      surfinlwref_av(isurf) = surfinlwref_av(isurf) + &
9456                                          surfinlw(isurf) - surfinlwdif(isurf)
9457                  ENDIF
9458              ENDDO
9459
9460          CASE ( 'rtm_rad_outsw' )
9461!--           array of sw radiation emitted from surface after i-th reflection
9462              DO isurf = dirstart(ids), dirend(ids)
9463                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9464                      surfoutsw_av(isurf) = surfoutsw_av(isurf) + surfoutsw(isurf)
9465                  ENDIF
9466              ENDDO
9467
9468          CASE ( 'rtm_rad_outlw' )
9469!--           array of lw radiation emitted from surface after i-th reflection
9470              DO isurf = dirstart(ids), dirend(ids)
9471                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9472                      surfoutlw_av(isurf) = surfoutlw_av(isurf) + surfoutlw(isurf)
9473                  ENDIF
9474              ENDDO
9475
9476          CASE ( 'rtm_rad_ressw' )
9477!--           array of residua of sw radiation absorbed in surface after last reflection
9478              DO isurf = dirstart(ids), dirend(ids)
9479                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9480                      surfins_av(isurf) = surfins_av(isurf) + surfins(isurf)
9481                  ENDIF
9482              ENDDO
9483
9484          CASE ( 'rtm_rad_reslw' )
9485!--           array of residua of lw radiation absorbed in surface after last reflection
9486              DO isurf = dirstart(ids), dirend(ids)
9487                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9488                      surfinl_av(isurf) = surfinl_av(isurf) + surfinl(isurf)
9489                  ENDIF
9490              ENDDO
9491
9492          CASE ( 'rtm_rad_pc_inlw' )
9493              DO l = 1, npcbl
9494                 pcbinlw_av(l) = pcbinlw_av(l) + pcbinlw(l)
9495              ENDDO
9496
9497          CASE ( 'rtm_rad_pc_insw' )
9498              DO l = 1, npcbl
9499                 pcbinsw_av(l) = pcbinsw_av(l) + pcbinsw(l)
9500              ENDDO
9501
9502          CASE ( 'rtm_rad_pc_inswdir' )
9503              DO l = 1, npcbl
9504                 pcbinswdir_av(l) = pcbinswdir_av(l) + pcbinswdir(l)
9505              ENDDO
9506
9507          CASE ( 'rtm_rad_pc_inswdif' )
9508              DO l = 1, npcbl
9509                 pcbinswdif_av(l) = pcbinswdif_av(l) + pcbinswdif(l)
9510              ENDDO
9511
9512          CASE ( 'rtm_rad_pc_inswref' )
9513              DO l = 1, npcbl
9514                 pcbinswref_av(l) = pcbinswref_av(l) + pcbinsw(l) - pcbinswdir(l) - pcbinswdif(l)
9515              ENDDO
9516
9517          CASE ( 'rad_mrt_sw' )
9518             IF ( ALLOCATED( mrtinsw_av ) )  THEN
9519                mrtinsw_av(:) = mrtinsw_av(:) + mrtinsw(:)
9520             ENDIF
9521
9522          CASE ( 'rad_mrt_lw' )
9523             IF ( ALLOCATED( mrtinlw_av ) )  THEN
9524                mrtinlw_av(:) = mrtinlw_av(:) + mrtinlw(:)
9525             ENDIF
9526
9527          CASE ( 'rad_mrt' )
9528             IF ( ALLOCATED( mrt_av ) )  THEN
9529                mrt_av(:) = mrt_av(:) + mrt(:)
9530             ENDIF
9531
9532          CASE DEFAULT
9533             CONTINUE
9534
9535       END SELECT
9536
9537    ELSEIF ( mode == 'average' )  THEN
9538
9539       SELECT CASE ( TRIM( var ) )
9540!--       block of large scale (e.g. RRTMG) radiation output variables
9541          CASE ( 'rad_net*' )
9542             IF ( ALLOCATED( rad_net_av ) ) THEN
9543                DO  i = nxlg, nxrg
9544                   DO  j = nysg, nyng
9545                      rad_net_av(j,i) = rad_net_av(j,i)                        &
9546                                        / REAL( average_count_3d, KIND=wp )
9547                   ENDDO
9548                ENDDO
9549             ENDIF
9550             
9551          CASE ( 'rad_lw_in*' )
9552             IF ( ALLOCATED( rad_lw_in_xy_av ) ) THEN
9553                DO  i = nxlg, nxrg
9554                   DO  j = nysg, nyng
9555                      rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i)              &
9556                                        / REAL( average_count_3d, KIND=wp )
9557                   ENDDO
9558                ENDDO
9559             ENDIF
9560             
9561          CASE ( 'rad_lw_out*' )
9562             IF ( ALLOCATED( rad_lw_out_xy_av ) ) THEN
9563                DO  i = nxlg, nxrg
9564                   DO  j = nysg, nyng
9565                      rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i)            &
9566                                        / REAL( average_count_3d, KIND=wp )
9567                   ENDDO
9568                ENDDO
9569             ENDIF
9570             
9571          CASE ( 'rad_sw_in*' )
9572             IF ( ALLOCATED( rad_sw_in_xy_av ) ) THEN
9573                DO  i = nxlg, nxrg
9574                   DO  j = nysg, nyng
9575                      rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i)              &
9576                                        / REAL( average_count_3d, KIND=wp )
9577                   ENDDO
9578                ENDDO
9579             ENDIF
9580             
9581          CASE ( 'rad_sw_out*' )
9582             IF ( ALLOCATED( rad_sw_out_xy_av ) ) THEN
9583                DO  i = nxlg, nxrg
9584                   DO  j = nysg, nyng
9585                      rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i)             &
9586                                        / REAL( average_count_3d, KIND=wp )
9587                   ENDDO
9588                ENDDO
9589             ENDIF
9590
9591          CASE ( 'rad_lw_in' )
9592             IF ( ALLOCATED( rad_lw_in_av ) ) THEN
9593                DO  i = nxlg, nxrg
9594                   DO  j = nysg, nyng
9595                      DO  k = nzb, nzt+1
9596                         rad_lw_in_av(k,j,i) = rad_lw_in_av(k,j,i)             &
9597                                               / REAL( average_count_3d, KIND=wp )
9598                      ENDDO
9599                   ENDDO
9600                ENDDO
9601             ENDIF
9602
9603          CASE ( 'rad_lw_out' )
9604             IF ( ALLOCATED( rad_lw_out_av ) ) THEN
9605                DO  i = nxlg, nxrg
9606                   DO  j = nysg, nyng
9607                      DO  k = nzb, nzt+1
9608                         rad_lw_out_av(k,j,i) = rad_lw_out_av(k,j,i)           &
9609                                                / REAL( average_count_3d, KIND=wp )
9610                      ENDDO
9611                   ENDDO
9612                ENDDO
9613             ENDIF
9614
9615          CASE ( 'rad_lw_cs_hr' )
9616             IF ( ALLOCATED( rad_lw_cs_hr_av ) ) THEN
9617                DO  i = nxlg, nxrg
9618                   DO  j = nysg, nyng
9619                      DO  k = nzb, nzt+1
9620                         rad_lw_cs_hr_av(k,j,i) = rad_lw_cs_hr_av(k,j,i)       &
9621                                                / REAL( average_count_3d, KIND=wp )
9622                      ENDDO
9623                   ENDDO
9624                ENDDO
9625             ENDIF
9626
9627          CASE ( 'rad_lw_hr' )
9628             IF ( ALLOCATED( rad_lw_hr_av ) ) THEN
9629                DO  i = nxlg, nxrg
9630                   DO  j = nysg, nyng
9631                      DO  k = nzb, nzt+1
9632                         rad_lw_hr_av(k,j,i) = rad_lw_hr_av(k,j,i)             &
9633                                               / REAL( average_count_3d, KIND=wp )
9634                      ENDDO
9635                   ENDDO
9636                ENDDO
9637             ENDIF
9638
9639          CASE ( 'rad_sw_in' )
9640             IF ( ALLOCATED( rad_sw_in_av ) ) THEN
9641                DO  i = nxlg, nxrg
9642                   DO  j = nysg, nyng
9643                      DO  k = nzb, nzt+1
9644                         rad_sw_in_av(k,j,i) = rad_sw_in_av(k,j,i)             &
9645                                               / REAL( average_count_3d, KIND=wp )
9646                      ENDDO
9647                   ENDDO
9648                ENDDO
9649             ENDIF
9650
9651          CASE ( 'rad_sw_out' )
9652             IF ( ALLOCATED( rad_sw_out_av ) ) THEN
9653                DO  i = nxlg, nxrg
9654                   DO  j = nysg, nyng
9655                      DO  k = nzb, nzt+1
9656                         rad_sw_out_av(k,j,i) = rad_sw_out_av(k,j,i)           &
9657                                                / REAL( average_count_3d, KIND=wp )
9658                      ENDDO
9659                   ENDDO
9660                ENDDO
9661             ENDIF
9662
9663          CASE ( 'rad_sw_cs_hr' )
9664             IF ( ALLOCATED( rad_sw_cs_hr_av ) ) THEN
9665                DO  i = nxlg, nxrg
9666                   DO  j = nysg, nyng
9667                      DO  k = nzb, nzt+1
9668                         rad_sw_cs_hr_av(k,j,i) = rad_sw_cs_hr_av(k,j,i)       &
9669                                                / REAL( average_count_3d, KIND=wp )
9670                      ENDDO
9671                   ENDDO
9672                ENDDO
9673             ENDIF
9674
9675          CASE ( 'rad_sw_hr' )
9676             IF ( ALLOCATED( rad_sw_hr_av ) ) THEN
9677                DO  i = nxlg, nxrg
9678                   DO  j = nysg, nyng
9679                      DO  k = nzb, nzt+1
9680                         rad_sw_hr_av(k,j,i) = rad_sw_hr_av(k,j,i)             &
9681                                               / REAL( average_count_3d, KIND=wp )
9682                      ENDDO
9683                   ENDDO
9684                ENDDO
9685             ENDIF
9686
9687!--       block of RTM output variables
9688          CASE ( 'rtm_rad_net' )
9689!--           array of complete radiation balance
9690              DO isurf = dirstart(ids), dirend(ids)
9691                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9692                      surfradnet_av(isurf) = surfinsw_av(isurf) / REAL( average_count_3d, kind=wp )
9693                  ENDIF
9694              ENDDO
9695
9696          CASE ( 'rtm_rad_insw' )
9697!--           array of sw radiation falling to surface after i-th reflection
9698              DO isurf = dirstart(ids), dirend(ids)
9699                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9700                      surfinsw_av(isurf) = surfinsw_av(isurf) / REAL( average_count_3d, kind=wp )
9701                  ENDIF
9702              ENDDO
9703
9704          CASE ( 'rtm_rad_inlw' )
9705!--           array of lw radiation falling to surface after i-th reflection
9706              DO isurf = dirstart(ids), dirend(ids)
9707                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9708                      surfinlw_av(isurf) = surfinlw_av(isurf) / REAL( average_count_3d, kind=wp )
9709                  ENDIF
9710              ENDDO
9711
9712          CASE ( 'rtm_rad_inswdir' )
9713!--           array of direct sw radiation falling to surface from sun
9714              DO isurf = dirstart(ids), dirend(ids)
9715                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9716                      surfinswdir_av(isurf) = surfinswdir_av(isurf) / REAL( average_count_3d, kind=wp )
9717                  ENDIF
9718              ENDDO
9719
9720          CASE ( 'rtm_rad_inswdif' )
9721!--           array of difusion sw radiation falling to surface from sky and borders of the domain
9722              DO isurf = dirstart(ids), dirend(ids)
9723                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9724                      surfinswdif_av(isurf) = surfinswdif_av(isurf) / REAL( average_count_3d, kind=wp )
9725                  ENDIF
9726              ENDDO
9727
9728          CASE ( 'rtm_rad_inswref' )
9729!--           array of sw radiation falling to surface from reflections
9730              DO isurf = dirstart(ids), dirend(ids)
9731                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9732                      surfinswref_av(isurf) = surfinswref_av(isurf) / REAL( average_count_3d, kind=wp )
9733                  ENDIF
9734              ENDDO
9735
9736          CASE ( 'rtm_rad_inlwdif' )
9737!--           array of sw radiation falling to surface after i-th reflection
9738              DO isurf = dirstart(ids), dirend(ids)
9739                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9740                      surfinlwdif_av(isurf) = surfinlwdif_av(isurf) / REAL( average_count_3d, kind=wp )
9741                  ENDIF
9742              ENDDO
9743
9744          CASE ( 'rtm_rad_inlwref' )
9745!--           array of lw radiation falling to surface from reflections
9746              DO isurf = dirstart(ids), dirend(ids)
9747                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9748                      surfinlwref_av(isurf) = surfinlwref_av(isurf) / REAL( average_count_3d, kind=wp )
9749                  ENDIF
9750              ENDDO
9751
9752          CASE ( 'rtm_rad_outsw' )
9753!--           array of sw radiation emitted from surface after i-th reflection
9754              DO isurf = dirstart(ids), dirend(ids)
9755                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9756                      surfoutsw_av(isurf) = surfoutsw_av(isurf) / REAL( average_count_3d, kind=wp )
9757                  ENDIF
9758              ENDDO
9759
9760          CASE ( 'rtm_rad_outlw' )
9761!--           array of lw radiation emitted from surface after i-th reflection
9762              DO isurf = dirstart(ids), dirend(ids)
9763                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9764                      surfoutlw_av(isurf) = surfoutlw_av(isurf) / REAL( average_count_3d, kind=wp )
9765                  ENDIF
9766              ENDDO
9767
9768          CASE ( 'rtm_rad_ressw' )
9769!--           array of residua of sw radiation absorbed in surface after last reflection
9770              DO isurf = dirstart(ids), dirend(ids)
9771                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9772                      surfins_av(isurf) = surfins_av(isurf) / REAL( average_count_3d, kind=wp )
9773                  ENDIF
9774              ENDDO
9775
9776          CASE ( 'rtm_rad_reslw' )
9777!--           array of residua of lw radiation absorbed in surface after last reflection
9778              DO isurf = dirstart(ids), dirend(ids)
9779                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9780                      surfinl_av(isurf) = surfinl_av(isurf) / REAL( average_count_3d, kind=wp )
9781                  ENDIF
9782              ENDDO
9783
9784          CASE ( 'rtm_rad_pc_inlw' )
9785              DO l = 1, npcbl
9786                 pcbinlw_av(:) = pcbinlw_av(:) / REAL( average_count_3d, kind=wp )
9787              ENDDO
9788
9789          CASE ( 'rtm_rad_pc_insw' )
9790              DO l = 1, npcbl
9791                 pcbinsw_av(:) = pcbinsw_av(:) / REAL( average_count_3d, kind=wp )
9792              ENDDO
9793
9794          CASE ( 'rtm_rad_pc_inswdir' )
9795              DO l = 1, npcbl
9796                 pcbinswdir_av(:) = pcbinswdir_av(:) / REAL( average_count_3d, kind=wp )
9797              ENDDO
9798
9799          CASE ( 'rtm_rad_pc_inswdif' )
9800              DO l = 1, npcbl
9801                 pcbinswdif_av(:) = pcbinswdif_av(:) / REAL( average_count_3d, kind=wp )
9802              ENDDO
9803
9804          CASE ( 'rtm_rad_pc_inswref' )
9805              DO l = 1, npcbl
9806                 pcbinswref_av(:) = pcbinswref_av(:) / REAL( average_count_3d, kind=wp )
9807              ENDDO
9808
9809          CASE ( 'rad_mrt_lw' )
9810             IF ( ALLOCATED( mrtinlw_av ) )  THEN
9811                mrtinlw_av(:) = mrtinlw_av(:) / REAL( average_count_3d, KIND=wp )
9812             ENDIF
9813
9814          CASE ( 'rad_mrt' )
9815             IF ( ALLOCATED( mrt_av ) )  THEN
9816                mrt_av(:) = mrt_av(:) / REAL( average_count_3d, KIND=wp )
9817             ENDIF
9818
9819       END SELECT
9820
9821    ENDIF
9822
9823END SUBROUTINE radiation_3d_data_averaging
9824
9825
9826!------------------------------------------------------------------------------!
9827!
9828! Description:
9829! ------------
9830!> Subroutine defining appropriate grid for netcdf variables.
9831!> It is called out from subroutine netcdf.
9832!------------------------------------------------------------------------------!
9833SUBROUTINE radiation_define_netcdf_grid( variable, found, grid_x, grid_y, grid_z )
9834   
9835    IMPLICIT NONE
9836
9837    CHARACTER (LEN=*), INTENT(IN)  ::  variable    !<
9838    LOGICAL, INTENT(OUT)           ::  found       !<
9839    CHARACTER (LEN=*), INTENT(OUT) ::  grid_x      !<
9840    CHARACTER (LEN=*), INTENT(OUT) ::  grid_y      !<
9841    CHARACTER (LEN=*), INTENT(OUT) ::  grid_z      !<
9842
9843    CHARACTER (len=varnamelength)  :: var
9844
9845    found  = .TRUE.
9846
9847!
9848!-- Check for the grid
9849    var = TRIM(variable)
9850!-- RTM directional variables
9851    IF ( var(1:12) == 'rtm_rad_net_'  .OR.  var(1:13) == 'rtm_rad_insw_'  .OR.          &
9852         var(1:13) == 'rtm_rad_inlw_'  .OR.  var(1:16) == 'rtm_rad_inswdir_'  .OR.      &
9853         var(1:16) == 'rtm_rad_inswdif_'  .OR.  var(1:16) == 'rtm_rad_inswref_'  .OR.   &
9854         var(1:16) == 'rtm_rad_inlwdif_'  .OR.  var(1:16) == 'rtm_rad_inlwref_'  .OR.   &
9855         var(1:14) == 'rtm_rad_outsw_'  .OR.  var(1:14) == 'rtm_rad_outlw_'  .OR.       &
9856         var(1:14) == 'rtm_rad_ressw_'  .OR.  var(1:14) == 'rtm_rad_reslw_'  .OR.       &
9857         var == 'rtm_rad_pc_inlw'  .OR.                                                 &
9858         var == 'rtm_rad_pc_insw'  .OR.  var == 'rtm_rad_pc_inswdir'  .OR.              &
9859         var == 'rtm_rad_pc_inswdif'  .OR.  var == 'rtm_rad_pc_inswref'  .OR.           &
9860         var(1:7) == 'rtm_svf'  .OR.  var(1:7) == 'rtm_dif'  .OR.                       &
9861         var(1:9) == 'rtm_skyvf' .OR. var(1:10) == 'rtm_skyvft'  .OR.                   &
9862         var == 'rtm_mrt'  .OR.  var ==  'rtm_mrt_sw'  .OR.  var == 'rtm_mrt_lw' )  THEN
9863
9864         found = .TRUE.
9865         grid_x = 'x'
9866         grid_y = 'y'
9867         grid_z = 'zu'
9868    ELSE
9869
9870       SELECT CASE ( TRIM( var ) )
9871
9872          CASE ( 'rad_lw_cs_hr', 'rad_lw_hr', 'rad_sw_cs_hr', 'rad_sw_hr',        &
9873                 'rad_lw_cs_hr_xy', 'rad_lw_hr_xy', 'rad_sw_cs_hr_xy',            &
9874                 'rad_sw_hr_xy', 'rad_lw_cs_hr_xz', 'rad_lw_hr_xz',               &
9875                 'rad_sw_cs_hr_xz', 'rad_sw_hr_xz', 'rad_lw_cs_hr_yz',            &
9876                 'rad_lw_hr_yz', 'rad_sw_cs_hr_yz', 'rad_sw_hr_yz',               &
9877                 'rad_mrt', 'rad_mrt_sw', 'rad_mrt_lw' )
9878             grid_x = 'x'
9879             grid_y = 'y'
9880             grid_z = 'zu'
9881
9882          CASE ( 'rad_lw_in', 'rad_lw_out', 'rad_sw_in', 'rad_sw_out',            &
9883                 'rad_lw_in_xy', 'rad_lw_out_xy', 'rad_sw_in_xy','rad_sw_out_xy', &
9884                 'rad_lw_in_xz', 'rad_lw_out_xz', 'rad_sw_in_xz','rad_sw_out_xz', &
9885                 'rad_lw_in_yz', 'rad_lw_out_yz', 'rad_sw_in_yz','rad_sw_out_yz' )
9886             grid_x = 'x'
9887             grid_y = 'y'
9888             grid_z = 'zw'
9889
9890
9891          CASE DEFAULT
9892             found  = .FALSE.
9893             grid_x = 'none'
9894             grid_y = 'none'
9895             grid_z = 'none'
9896
9897           END SELECT
9898       ENDIF
9899
9900    END SUBROUTINE radiation_define_netcdf_grid
9901
9902!------------------------------------------------------------------------------!
9903!
9904! Description:
9905! ------------
9906!> Subroutine defining 2D output variables
9907!------------------------------------------------------------------------------!
9908 SUBROUTINE radiation_data_output_2d( av, variable, found, grid, mode,         &
9909                                      local_pf, two_d, nzb_do, nzt_do )
9910 
9911    USE indices
9912
9913    USE kinds
9914
9915
9916    IMPLICIT NONE
9917
9918    CHARACTER (LEN=*) ::  grid     !<
9919    CHARACTER (LEN=*) ::  mode     !<
9920    CHARACTER (LEN=*) ::  variable !<
9921
9922    INTEGER(iwp) ::  av !<
9923    INTEGER(iwp) ::  i  !<
9924    INTEGER(iwp) ::  j  !<
9925    INTEGER(iwp) ::  k  !<
9926    INTEGER(iwp) ::  m  !< index of surface element at grid point (j,i)
9927    INTEGER(iwp) ::  nzb_do   !<
9928    INTEGER(iwp) ::  nzt_do   !<
9929
9930    LOGICAL      ::  found !<
9931    LOGICAL      ::  two_d !< flag parameter that indicates 2D variables (horizontal cross sections)
9932
9933    REAL(wp) ::  fill_value = -999.0_wp    !< value for the _FillValue attribute
9934
9935    REAL(wp), DIMENSION(nxl:nxr,nys:nyn,nzb_do:nzt_do) ::  local_pf !<
9936
9937    found = .TRUE.
9938
9939    SELECT CASE ( TRIM( variable ) )
9940
9941       CASE ( 'rad_net*_xy' )        ! 2d-array
9942          IF ( av == 0 ) THEN
9943             DO  i = nxl, nxr
9944                DO  j = nys, nyn
9945!
9946!--                Obtain rad_net from its respective surface type
9947!--                Natural-type surfaces
9948                   DO  m = surf_lsm_h%start_index(j,i),                        &
9949                           surf_lsm_h%end_index(j,i) 
9950                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_net(m)
9951                   ENDDO
9952!
9953!--                Urban-type surfaces
9954                   DO  m = surf_usm_h%start_index(j,i),                        &
9955                           surf_usm_h%end_index(j,i) 
9956                      local_pf(i,j,nzb+1) = surf_usm_h%rad_net(m)
9957                   ENDDO
9958                ENDDO
9959             ENDDO
9960          ELSE
9961             IF ( .NOT. ALLOCATED( rad_net_av ) ) THEN
9962                ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
9963                rad_net_av = REAL( fill_value, KIND = wp )
9964             ENDIF
9965             DO  i = nxl, nxr
9966                DO  j = nys, nyn 
9967                   local_pf(i,j,nzb+1) = rad_net_av(j,i)
9968                ENDDO
9969             ENDDO
9970          ENDIF
9971          two_d = .TRUE.
9972          grid = 'zu1'
9973         
9974       CASE ( 'rad_lw_in*_xy' )        ! 2d-array
9975          IF ( av == 0 ) THEN
9976             DO  i = nxl, nxr
9977                DO  j = nys, nyn
9978!
9979!--                Obtain rad_net from its respective surface type
9980!--                Natural-type surfaces
9981                   DO  m = surf_lsm_h%start_index(j,i),                        &
9982                           surf_lsm_h%end_index(j,i) 
9983                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_lw_in(m)
9984                   ENDDO
9985!
9986!--                Urban-type surfaces
9987                   DO  m = surf_usm_h%start_index(j,i),                        &
9988                           surf_usm_h%end_index(j,i) 
9989                      local_pf(i,j,nzb+1) = surf_usm_h%rad_lw_in(m)
9990                   ENDDO
9991                ENDDO
9992             ENDDO
9993          ELSE
9994             IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) ) THEN
9995                ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
9996                rad_lw_in_xy_av = REAL( fill_value, KIND = wp )
9997             ENDIF
9998             DO  i = nxl, nxr
9999                DO  j = nys, nyn 
10000                   local_pf(i,j,nzb+1) = rad_lw_in_xy_av(j,i)
10001                ENDDO
10002             ENDDO
10003          ENDIF
10004          two_d = .TRUE.
10005          grid = 'zu1'
10006         
10007       CASE ( 'rad_lw_out*_xy' )        ! 2d-array
10008          IF ( av == 0 ) THEN
10009             DO  i = nxl, nxr
10010                DO  j = nys, nyn
10011!
10012!--                Obtain rad_net from its respective surface type
10013!--                Natural-type surfaces
10014                   DO  m = surf_lsm_h%start_index(j,i),                        &
10015                           surf_lsm_h%end_index(j,i) 
10016                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_lw_out(m)
10017                   ENDDO
10018!
10019!--                Urban-type surfaces
10020                   DO  m = surf_usm_h%start_index(j,i),                        &
10021                           surf_usm_h%end_index(j,i) 
10022                      local_pf(i,j,nzb+1) = surf_usm_h%rad_lw_out(m)
10023                   ENDDO
10024                ENDDO
10025             ENDDO
10026          ELSE
10027             IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) ) THEN
10028                ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
10029                rad_lw_out_xy_av = REAL( fill_value, KIND = wp )
10030             ENDIF
10031             DO  i = nxl, nxr
10032                DO  j = nys, nyn 
10033                   local_pf(i,j,nzb+1) = rad_lw_out_xy_av(j,i)
10034                ENDDO
10035             ENDDO
10036          ENDIF
10037          two_d = .TRUE.
10038          grid = 'zu1'
10039         
10040       CASE ( 'rad_sw_in*_xy' )        ! 2d-array
10041          IF ( av == 0 ) THEN
10042             DO  i = nxl, nxr
10043                DO  j = nys, nyn
10044!
10045!--                Obtain rad_net from its respective surface type
10046!--                Natural-type surfaces
10047                   DO  m = surf_lsm_h%start_index(j,i),                        &
10048                           surf_lsm_h%end_index(j,i) 
10049                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_sw_in(m)
10050                   ENDDO
10051!
10052!--                Urban-type surfaces
10053                   DO  m = surf_usm_h%start_index(j,i),                        &
10054                           surf_usm_h%end_index(j,i) 
10055                      local_pf(i,j,nzb+1) = surf_usm_h%rad_sw_in(m)
10056                   ENDDO
10057                ENDDO
10058             ENDDO
10059          ELSE
10060             IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) ) THEN
10061                ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
10062                rad_sw_in_xy_av = REAL( fill_value, KIND = wp )
10063             ENDIF
10064             DO  i = nxl, nxr
10065                DO  j = nys, nyn 
10066                   local_pf(i,j,nzb+1) = rad_sw_in_xy_av(j,i)
10067                ENDDO
10068             ENDDO
10069          ENDIF
10070          two_d = .TRUE.
10071          grid = 'zu1'
10072         
10073       CASE ( 'rad_sw_out*_xy' )        ! 2d-array
10074          IF ( av == 0 ) THEN
10075             DO  i = nxl, nxr
10076                DO  j = nys, nyn
10077!
10078!--                Obtain rad_net from its respective surface type
10079!--                Natural-type surfaces
10080                   DO  m = surf_lsm_h%start_index(j,i),                        &
10081                           surf_lsm_h%end_index(j,i) 
10082                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_sw_out(m)
10083                   ENDDO
10084!
10085!--                Urban-type surfaces
10086                   DO  m = surf_usm_h%start_index(j,i),                        &
10087                           surf_usm_h%end_index(j,i) 
10088                      local_pf(i,j,nzb+1) = surf_usm_h%rad_sw_out(m)
10089                   ENDDO
10090                ENDDO
10091             ENDDO
10092          ELSE
10093             IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) ) THEN
10094                ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
10095                rad_sw_out_xy_av = REAL( fill_value, KIND = wp )
10096             ENDIF
10097             DO  i = nxl, nxr
10098                DO  j = nys, nyn 
10099                   local_pf(i,j,nzb+1) = rad_sw_out_xy_av(j,i)
10100                ENDDO
10101             ENDDO
10102          ENDIF
10103          two_d = .TRUE.
10104          grid = 'zu1'         
10105         
10106       CASE ( 'rad_lw_in_xy', 'rad_lw_in_xz', 'rad_lw_in_yz' )
10107          IF ( av == 0 ) THEN
10108             DO  i = nxl, nxr
10109                DO  j = nys, nyn
10110                   DO  k = nzb_do, nzt_do
10111                      local_pf(i,j,k) = rad_lw_in(k,j,i)
10112                   ENDDO
10113                ENDDO
10114             ENDDO
10115          ELSE
10116            IF ( .NOT. ALLOCATED( rad_lw_in_av ) ) THEN
10117               ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10118               rad_lw_in_av = REAL( fill_value, KIND = wp )
10119            ENDIF
10120             DO  i = nxl, nxr
10121                DO  j = nys, nyn 
10122                   DO  k = nzb_do, nzt_do
10123                      local_pf(i,j,k) = rad_lw_in_av(k,j,i)
10124                   ENDDO
10125                ENDDO
10126             ENDDO
10127          ENDIF
10128          IF ( mode == 'xy' )  grid = 'zu'
10129
10130       CASE ( 'rad_lw_out_xy', 'rad_lw_out_xz', 'rad_lw_out_yz' )
10131          IF ( av == 0 ) THEN
10132             DO  i = nxl, nxr
10133                DO  j = nys, nyn
10134                   DO  k = nzb_do, nzt_do
10135                      local_pf(i,j,k) = rad_lw_out(k,j,i)
10136                   ENDDO
10137                ENDDO
10138             ENDDO
10139          ELSE
10140            IF ( .NOT. ALLOCATED( rad_lw_out_av ) ) THEN
10141               ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10142               rad_lw_out_av = REAL( fill_value, KIND = wp )
10143            ENDIF
10144             DO  i = nxl, nxr
10145                DO  j = nys, nyn 
10146                   DO  k = nzb_do, nzt_do
10147                      local_pf(i,j,k) = rad_lw_out_av(k,j,i)
10148                   ENDDO
10149                ENDDO
10150             ENDDO
10151          ENDIF   
10152          IF ( mode == 'xy' )  grid = 'zu'
10153
10154       CASE ( 'rad_lw_cs_hr_xy', 'rad_lw_cs_hr_xz', 'rad_lw_cs_hr_yz' )
10155          IF ( av == 0 ) THEN
10156             DO  i = nxl, nxr
10157                DO  j = nys, nyn
10158                   DO  k = nzb_do, nzt_do
10159                      local_pf(i,j,k) = rad_lw_cs_hr(k,j,i)
10160                   ENDDO
10161                ENDDO
10162             ENDDO
10163          ELSE
10164            IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) ) THEN
10165               ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10166               rad_lw_cs_hr_av = REAL( fill_value, KIND = wp )
10167            ENDIF
10168             DO  i = nxl, nxr
10169                DO  j = nys, nyn 
10170                   DO  k = nzb_do, nzt_do
10171                      local_pf(i,j,k) = rad_lw_cs_hr_av(k,j,i)
10172                   ENDDO
10173                ENDDO
10174             ENDDO
10175          ENDIF
10176          IF ( mode == 'xy' )  grid = 'zw'
10177
10178       CASE ( 'rad_lw_hr_xy', 'rad_lw_hr_xz', 'rad_lw_hr_yz' )
10179          IF ( av == 0 ) THEN
10180             DO  i = nxl, nxr
10181                DO  j = nys, nyn
10182                   DO  k = nzb_do, nzt_do
10183                      local_pf(i,j,k) = rad_lw_hr(k,j,i)
10184                   ENDDO
10185                ENDDO
10186             ENDDO
10187          ELSE
10188            IF ( .NOT. ALLOCATED( rad_lw_hr_av ) ) THEN
10189               ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10190               rad_lw_hr_av= REAL( fill_value, KIND = wp )
10191            ENDIF
10192             DO  i = nxl, nxr
10193                DO  j = nys, nyn 
10194                   DO  k = nzb_do, nzt_do
10195                      local_pf(i,j,k) = rad_lw_hr_av(k,j,i)
10196                   ENDDO
10197                ENDDO
10198             ENDDO
10199          ENDIF
10200          IF ( mode == 'xy' )  grid = 'zw'
10201
10202       CASE ( 'rad_sw_in_xy', 'rad_sw_in_xz', 'rad_sw_in_yz' )
10203          IF ( av == 0 ) THEN
10204             DO  i = nxl, nxr
10205                DO  j = nys, nyn
10206                   DO  k = nzb_do, nzt_do
10207                      local_pf(i,j,k) = rad_sw_in(k,j,i)
10208                   ENDDO
10209                ENDDO
10210             ENDDO
10211          ELSE
10212            IF ( .NOT. ALLOCATED( rad_sw_in_av ) ) THEN
10213               ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10214               rad_sw_in_av = REAL( fill_value, KIND = wp )
10215            ENDIF
10216             DO  i = nxl, nxr
10217                DO  j = nys, nyn 
10218                   DO  k = nzb_do, nzt_do
10219                      local_pf(i,j,k) = rad_sw_in_av(k,j,i)
10220                   ENDDO
10221                ENDDO
10222             ENDDO
10223          ENDIF
10224          IF ( mode == 'xy' )  grid = 'zu'
10225
10226       CASE ( 'rad_sw_out_xy', 'rad_sw_out_xz', 'rad_sw_out_yz' )
10227          IF ( av == 0 ) THEN
10228             DO  i = nxl, nxr
10229                DO  j = nys, nyn
10230                   DO  k = nzb_do, nzt_do
10231                      local_pf(i,j,k) = rad_sw_out(k,j,i)
10232                   ENDDO
10233                ENDDO
10234             ENDDO
10235          ELSE
10236            IF ( .NOT. ALLOCATED( rad_sw_out_av ) ) THEN
10237               ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10238               rad_sw_out_av = REAL( fill_value, KIND = wp )
10239            ENDIF
10240             DO  i = nxl, nxr
10241                DO  j = nys, nyn 
10242                   DO  k = nzb, nzt+1
10243                      local_pf(i,j,k) = rad_sw_out_av(k,j,i)
10244                   ENDDO
10245                ENDDO
10246             ENDDO
10247          ENDIF
10248          IF ( mode == 'xy' )  grid = 'zu'
10249
10250       CASE ( 'rad_sw_cs_hr_xy', 'rad_sw_cs_hr_xz', 'rad_sw_cs_hr_yz' )
10251          IF ( av == 0 ) THEN
10252             DO  i = nxl, nxr
10253                DO  j = nys, nyn
10254                   DO  k = nzb_do, nzt_do
10255                      local_pf(i,j,k) = rad_sw_cs_hr(k,j,i)
10256                   ENDDO
10257                ENDDO
10258             ENDDO
10259          ELSE
10260            IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) ) THEN
10261               ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10262               rad_sw_cs_hr_av = REAL( fill_value, KIND = wp )
10263            ENDIF
10264             DO  i = nxl, nxr
10265                DO  j = nys, nyn 
10266                   DO  k = nzb_do, nzt_do
10267                      local_pf(i,j,k) = rad_sw_cs_hr_av(k,j,i)
10268                   ENDDO
10269                ENDDO
10270             ENDDO
10271          ENDIF
10272          IF ( mode == 'xy' )  grid = 'zw'
10273
10274       CASE ( 'rad_sw_hr_xy', 'rad_sw_hr_xz', 'rad_sw_hr_yz' )
10275          IF ( av == 0 ) THEN
10276             DO  i = nxl, nxr
10277                DO  j = nys, nyn
10278                   DO  k = nzb_do, nzt_do
10279                      local_pf(i,j,k) = rad_sw_hr(k,j,i)
10280                   ENDDO
10281                ENDDO
10282             ENDDO
10283          ELSE
10284            IF ( .NOT. ALLOCATED( rad_sw_hr_av ) ) THEN
10285               ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10286               rad_sw_hr_av = REAL( fill_value, KIND = wp )
10287            ENDIF
10288             DO  i = nxl, nxr
10289                DO  j = nys, nyn 
10290                   DO  k = nzb_do, nzt_do
10291                      local_pf(i,j,k) = rad_sw_hr_av(k,j,i)
10292                   ENDDO
10293                ENDDO
10294             ENDDO
10295          ENDIF
10296          IF ( mode == 'xy' )  grid = 'zw'
10297
10298       CASE DEFAULT
10299          found = .FALSE.
10300          grid  = 'none'
10301
10302    END SELECT
10303 
10304 END SUBROUTINE radiation_data_output_2d
10305
10306
10307!------------------------------------------------------------------------------!
10308!
10309! Description:
10310! ------------
10311!> Subroutine defining 3D output variables
10312!------------------------------------------------------------------------------!
10313 SUBROUTINE radiation_data_output_3d( av, variable, found, local_pf, nzb_do, nzt_do )
10314 
10315
10316    USE indices
10317
10318    USE kinds
10319
10320
10321    IMPLICIT NONE
10322
10323    CHARACTER (LEN=*) ::  variable !<
10324
10325    INTEGER(iwp) ::  av          !<
10326    INTEGER(iwp) ::  i, j, k, l  !<
10327    INTEGER(iwp) ::  nzb_do      !<
10328    INTEGER(iwp) ::  nzt_do      !<
10329
10330    LOGICAL      ::  found       !<
10331
10332    REAL(wp)     ::  fill_value = -999.0_wp    !< value for the _FillValue attribute
10333
10334    REAL(sp), DIMENSION(nxl:nxr,nys:nyn,nzb_do:nzt_do) ::  local_pf !<
10335
10336    CHARACTER (len=varnamelength)                   :: var, surfid
10337    INTEGER(iwp)                                    :: ids,idsint_u,idsint_l,isurf,isvf,isurfs,isurflt,ipcgb
10338    INTEGER(iwp)                                    :: is, js, ks, istat
10339
10340    found = .TRUE.
10341
10342    ids = -1
10343    var = TRIM(variable)
10344    DO i = 0, nd-1
10345        k = len(TRIM(var))
10346        j = len(TRIM(dirname(i)))
10347        IF ( TRIM(var(k-j+1:k)) == TRIM(dirname(i)) )  THEN
10348            ids = i
10349            idsint_u = dirint_u(ids)
10350            idsint_l = dirint_l(ids)
10351            var = var(:k-j)
10352            EXIT
10353        ENDIF
10354    ENDDO
10355    IF ( ids == -1 )  THEN
10356        var = TRIM(variable)
10357    ENDIF
10358
10359    IF ( (var(1:8) == 'rtm_svf_'  .OR.  var(1:8) == 'rtm_dif_')  .AND.  len(TRIM(var)) >= 13 )  THEN
10360!--     svf values to particular surface
10361        surfid = var(9:)
10362        i = index(surfid,'_')
10363        j = index(surfid(i+1:),'_')
10364        READ(surfid(1:i-1),*, iostat=istat ) is
10365        IF ( istat == 0 )  THEN
10366            READ(surfid(i+1:i+j-1),*, iostat=istat ) js
10367        ENDIF
10368        IF ( istat == 0 )  THEN
10369            READ(surfid(i+j+1:),*, iostat=istat ) ks
10370        ENDIF
10371        IF ( istat == 0 )  THEN
10372            var = var(1:7)
10373        ENDIF
10374    ENDIF
10375
10376    local_pf = fill_value
10377
10378    SELECT CASE ( TRIM( var ) )
10379!--   block of large scale radiation model (e.g. RRTMG) output variables
10380      CASE ( 'rad_sw_in' )
10381         IF ( av == 0 )  THEN
10382            DO  i = nxl, nxr
10383               DO  j = nys, nyn
10384                  DO  k = nzb_do, nzt_do
10385                     local_pf(i,j,k) = rad_sw_in(k,j,i)
10386                  ENDDO
10387               ENDDO
10388            ENDDO
10389         ELSE
10390            IF ( .NOT. ALLOCATED( rad_sw_in_av ) ) THEN
10391               ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10392               rad_sw_in_av = REAL( fill_value, KIND = wp )
10393            ENDIF
10394            DO  i = nxl, nxr
10395               DO  j = nys, nyn
10396                  DO  k = nzb_do, nzt_do
10397                     local_pf(i,j,k) = rad_sw_in_av(k,j,i)
10398                  ENDDO
10399               ENDDO
10400            ENDDO
10401         ENDIF
10402
10403      CASE ( 'rad_sw_out' )
10404         IF ( av == 0 )  THEN
10405            DO  i = nxl, nxr
10406               DO  j = nys, nyn
10407                  DO  k = nzb_do, nzt_do
10408                     local_pf(i,j,k) = rad_sw_out(k,j,i)
10409                  ENDDO
10410               ENDDO
10411            ENDDO
10412         ELSE
10413            IF ( .NOT. ALLOCATED( rad_sw_out_av ) ) THEN
10414               ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10415               rad_sw_out_av = REAL( fill_value, KIND = wp )
10416            ENDIF
10417            DO  i = nxl, nxr
10418               DO  j = nys, nyn
10419                  DO  k = nzb_do, nzt_do
10420                     local_pf(i,j,k) = rad_sw_out_av(k,j,i)
10421                  ENDDO
10422               ENDDO
10423            ENDDO
10424         ENDIF
10425
10426      CASE ( 'rad_sw_cs_hr' )
10427         IF ( av == 0 )  THEN
10428            DO  i = nxl, nxr
10429               DO  j = nys, nyn
10430                  DO  k = nzb_do, nzt_do
10431                     local_pf(i,j,k) = rad_sw_cs_hr(k,j,i)
10432                  ENDDO
10433               ENDDO
10434            ENDDO
10435         ELSE
10436            IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) ) THEN
10437               ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10438               rad_sw_cs_hr_av = REAL( fill_value, KIND = wp )
10439            ENDIF
10440            DO  i = nxl, nxr
10441               DO  j = nys, nyn
10442                  DO  k = nzb_do, nzt_do
10443                     local_pf(i,j,k) = rad_sw_cs_hr_av(k,j,i)
10444                  ENDDO
10445               ENDDO
10446            ENDDO
10447         ENDIF
10448
10449      CASE ( 'rad_sw_hr' )
10450         IF ( av == 0 )  THEN
10451            DO  i = nxl, nxr
10452               DO  j = nys, nyn
10453                  DO  k = nzb_do, nzt_do
10454                     local_pf(i,j,k) = rad_sw_hr(k,j,i)
10455                  ENDDO
10456               ENDDO
10457            ENDDO
10458         ELSE
10459            IF ( .NOT. ALLOCATED( rad_sw_hr_av ) ) THEN
10460               ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10461               rad_sw_hr_av = REAL( fill_value, KIND = wp )
10462            ENDIF
10463            DO  i = nxl, nxr
10464               DO  j = nys, nyn
10465                  DO  k = nzb_do, nzt_do
10466                     local_pf(i,j,k) = rad_sw_hr_av(k,j,i)
10467                  ENDDO
10468               ENDDO
10469            ENDDO
10470         ENDIF
10471
10472      CASE ( 'rad_lw_in' )
10473         IF ( av == 0 )  THEN
10474            DO  i = nxl, nxr
10475               DO  j = nys, nyn
10476                  DO  k = nzb_do, nzt_do
10477                     local_pf(i,j,k) = rad_lw_in(k,j,i)
10478                  ENDDO
10479               ENDDO
10480            ENDDO
10481         ELSE
10482            IF ( .NOT. ALLOCATED( rad_lw_in_av ) ) THEN
10483               ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10484               rad_lw_in_av = REAL( fill_value, KIND = wp )
10485            ENDIF
10486            DO  i = nxl, nxr
10487               DO  j = nys, nyn
10488                  DO  k = nzb_do, nzt_do
10489                     local_pf(i,j,k) = rad_lw_in_av(k,j,i)
10490                  ENDDO
10491               ENDDO
10492            ENDDO
10493         ENDIF
10494
10495      CASE ( 'rad_lw_out' )
10496         IF ( av == 0 )  THEN
10497            DO  i = nxl, nxr
10498               DO  j = nys, nyn
10499                  DO  k = nzb_do, nzt_do
10500                     local_pf(i,j,k) = rad_lw_out(k,j,i)
10501                  ENDDO
10502               ENDDO
10503            ENDDO
10504         ELSE
10505            IF ( .NOT. ALLOCATED( rad_lw_out_av ) ) THEN
10506               ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10507               rad_lw_out_av = REAL( fill_value, KIND = wp )
10508            ENDIF
10509            DO  i = nxl, nxr
10510               DO  j = nys, nyn
10511                  DO  k = nzb_do, nzt_do
10512                     local_pf(i,j,k) = rad_lw_out_av(k,j,i)
10513                  ENDDO
10514               ENDDO
10515            ENDDO
10516         ENDIF
10517
10518      CASE ( 'rad_lw_cs_hr' )
10519         IF ( av == 0 )  THEN
10520            DO  i = nxl, nxr
10521               DO  j = nys, nyn
10522                  DO  k = nzb_do, nzt_do
10523                     local_pf(i,j,k) = rad_lw_cs_hr(k,j,i)
10524                  ENDDO
10525               ENDDO
10526            ENDDO
10527         ELSE
10528            IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) ) THEN
10529               ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10530               rad_lw_cs_hr_av = REAL( fill_value, KIND = wp )
10531            ENDIF
10532            DO  i = nxl, nxr
10533               DO  j = nys, nyn
10534                  DO  k = nzb_do, nzt_do
10535                     local_pf(i,j,k) = rad_lw_cs_hr_av(k,j,i)
10536                  ENDDO
10537               ENDDO
10538            ENDDO
10539         ENDIF
10540
10541      CASE ( 'rad_lw_hr' )
10542         IF ( av == 0 )  THEN
10543            DO  i = nxl, nxr
10544               DO  j = nys, nyn
10545                  DO  k = nzb_do, nzt_do
10546                     local_pf(i,j,k) = rad_lw_hr(k,j,i)
10547                  ENDDO
10548               ENDDO
10549            ENDDO
10550         ELSE
10551            IF ( .NOT. ALLOCATED( rad_lw_hr_av ) ) THEN
10552               ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10553              rad_lw_hr_av = REAL( fill_value, KIND = wp )
10554            ENDIF
10555            DO  i = nxl, nxr
10556               DO  j = nys, nyn
10557                  DO  k = nzb_do, nzt_do
10558                     local_pf(i,j,k) = rad_lw_hr_av(k,j,i)
10559                  ENDDO
10560               ENDDO
10561            ENDDO
10562         ENDIF
10563
10564!--   block of RTM output variables
10565!--   variables are intended mainly for debugging and detailed analyse purposes
10566      CASE ( 'rtm_skyvf' )
10567!--        sky view factor
10568         DO isurf = dirstart(ids), dirend(ids)
10569            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10570               local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = skyvf(isurf)
10571            ENDIF
10572         ENDDO
10573
10574      CASE ( 'rtm_skyvft' )
10575!--      sky view factor
10576         DO isurf = dirstart(ids), dirend(ids)
10577            IF ( surfl(id,isurf) == ids )  THEN
10578               local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = skyvft(isurf)
10579            ENDIF
10580         ENDDO
10581
10582      CASE ( 'rtm_svf', 'rtm_dif' )
10583!--      shape view factors or iradiance factors to selected surface
10584         IF ( TRIM(var)=='rtm_svf' )  THEN
10585             k = 1
10586         ELSE
10587             k = 2
10588         ENDIF
10589         DO isvf = 1, nsvfl
10590            isurflt = svfsurf(1, isvf)
10591            isurfs = svfsurf(2, isvf)
10592
10593            IF ( surf(ix,isurfs) == is  .AND.  surf(iy,isurfs) == js  .AND. surf(iz,isurfs) == ks  .AND. &
10594                 (surf(id,isurfs) == idsint_u .OR. surfl(id,isurfs) == idsint_l ) ) THEN
10595!--            correct source surface
10596               local_pf(surfl(ix,isurflt),surfl(iy,isurflt),surfl(iz,isurflt)) = svf(k,isvf)
10597            ENDIF
10598         ENDDO
10599
10600      CASE ( 'rtm_rad_net' )
10601!--     array of complete radiation balance
10602         DO isurf = dirstart(ids), dirend(ids)
10603            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10604               IF ( av == 0 )  THEN
10605                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = &
10606                         surfinsw(isurf) - surfoutsw(isurf) +  surfinlw(isurf) - surfoutlw(isurf)
10607               ELSE
10608                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfradnet_av(isurf)
10609               ENDIF
10610            ENDIF
10611         ENDDO
10612
10613      CASE ( 'rtm_rad_insw' )
10614!--      array of sw radiation falling to surface after i-th reflection
10615         DO isurf = dirstart(ids), dirend(ids)
10616            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10617               IF ( av == 0 )  THEN
10618                 local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinsw(isurf)
10619               ELSE
10620                 local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinsw_av(isurf)
10621               ENDIF
10622            ENDIF
10623         ENDDO
10624
10625      CASE ( 'rtm_rad_inlw' )
10626!--      array of lw radiation falling to surface after i-th reflection
10627         DO isurf = dirstart(ids), dirend(ids)
10628            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10629               IF ( av == 0 )  THEN
10630                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlw(isurf)
10631               ELSE
10632                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlw_av(isurf)
10633               ENDIF
10634             ENDIF
10635         ENDDO
10636
10637      CASE ( 'rtm_rad_inswdir' )
10638!--      array of direct sw radiation falling to surface from sun
10639         DO isurf = dirstart(ids), dirend(ids)
10640            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10641               IF ( av == 0 )  THEN
10642                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdir(isurf)
10643               ELSE
10644                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdir_av(isurf)
10645               ENDIF
10646            ENDIF
10647         ENDDO
10648
10649      CASE ( 'rtm_rad_inswdif' )
10650!--      array of difusion sw radiation falling to surface from sky and borders of the domain
10651         DO isurf = dirstart(ids), dirend(ids)
10652            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10653               IF ( av == 0 )  THEN
10654                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdif(isurf)
10655               ELSE
10656                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdif_av(isurf)
10657               ENDIF
10658            ENDIF
10659         ENDDO
10660
10661      CASE ( 'rtm_rad_inswref' )
10662!--      array of sw radiation falling to surface from reflections
10663         DO isurf = dirstart(ids), dirend(ids)
10664            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10665               IF ( av == 0 )  THEN
10666                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = &
10667                    surfinsw(isurf) - surfinswdir(isurf) - surfinswdif(isurf)
10668               ELSE
10669                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswref_av(isurf)
10670               ENDIF
10671            ENDIF
10672         ENDDO
10673
10674      CASE ( 'rtm_rad_inlwdif' )
10675!--      array of difusion lw radiation falling to surface from sky and borders of the domain
10676         DO isurf = dirstart(ids), dirend(ids)
10677            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10678               IF ( av == 0 )  THEN
10679                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlwdif(isurf)
10680               ELSE
10681                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlwdif_av(isurf)
10682               ENDIF
10683            ENDIF
10684         ENDDO
10685
10686      CASE ( 'rtm_rad_inlwref' )
10687!--      array of lw radiation falling to surface from reflections
10688         DO isurf = dirstart(ids), dirend(ids)
10689            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10690               IF ( av == 0 )  THEN
10691                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlw(isurf) - surfinlwdif(isurf)
10692               ELSE
10693                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlwref_av(isurf)
10694               ENDIF
10695            ENDIF
10696         ENDDO
10697
10698      CASE ( 'rtm_rad_outsw' )
10699!--      array of sw radiation emitted from surface after i-th reflection
10700         DO isurf = dirstart(ids), dirend(ids)
10701            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10702               IF ( av == 0 )  THEN
10703                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutsw(isurf)
10704               ELSE
10705                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutsw_av(isurf)
10706               ENDIF
10707            ENDIF
10708         ENDDO
10709
10710      CASE ( 'rtm_rad_outlw' )
10711!--      array of lw radiation emitted from surface after i-th reflection
10712         DO isurf = dirstart(ids), dirend(ids)
10713            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10714               IF ( av == 0 )  THEN
10715                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutlw(isurf)
10716               ELSE
10717                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutlw_av(isurf)
10718               ENDIF
10719            ENDIF
10720         ENDDO
10721
10722      CASE ( 'rtm_rad_ressw' )
10723!--      average of array of residua of sw radiation absorbed in surface after last reflection
10724         DO isurf = dirstart(ids), dirend(ids)
10725            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10726               IF ( av == 0 )  THEN
10727                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfins(isurf)
10728               ELSE
10729                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfins_av(isurf)
10730               ENDIF
10731            ENDIF
10732         ENDDO
10733
10734      CASE ( 'rtm_rad_reslw' )
10735!--      average of array of residua of lw radiation absorbed in surface after last reflection
10736         DO isurf = dirstart(ids), dirend(ids)
10737            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10738               IF ( av == 0 )  THEN
10739                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinl(isurf)
10740               ELSE
10741                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinl_av(isurf)
10742               ENDIF
10743            ENDIF
10744         ENDDO
10745
10746      CASE ( 'rtm_rad_pc_inlw' )
10747!--      array of lw radiation absorbed by plant canopy
10748         DO ipcgb = 1, npcbl
10749            IF ( av == 0 )  THEN
10750               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinlw(ipcgb)
10751            ELSE
10752               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinlw_av(ipcgb)
10753            ENDIF
10754         ENDDO
10755
10756      CASE ( 'rtm_rad_pc_insw' )
10757!--      array of sw radiation absorbed by plant canopy
10758         DO ipcgb = 1, npcbl
10759            IF ( av == 0 )  THEN
10760              local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinsw(ipcgb)
10761            ELSE
10762              local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinsw_av(ipcgb)
10763            ENDIF
10764         ENDDO
10765
10766      CASE ( 'rtm_rad_pc_inswdir' )
10767!--      array of direct sw radiation absorbed by plant canopy
10768         DO ipcgb = 1, npcbl
10769            IF ( av == 0 )  THEN
10770               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdir(ipcgb)
10771            ELSE
10772               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdir_av(ipcgb)
10773            ENDIF
10774         ENDDO
10775
10776      CASE ( 'rtm_rad_pc_inswdif' )
10777!--      array of diffuse sw radiation absorbed by plant canopy
10778         DO ipcgb = 1, npcbl
10779            IF ( av == 0 )  THEN
10780               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdif(ipcgb)
10781            ELSE
10782               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdif_av(ipcgb)
10783            ENDIF
10784         ENDDO
10785
10786      CASE ( 'rtm_rad_pc_inswref' )
10787!--      array of reflected sw radiation absorbed by plant canopy
10788         DO ipcgb = 1, npcbl
10789            IF ( av == 0 )  THEN
10790               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = &
10791                                    pcbinsw(ipcgb) - pcbinswdir(ipcgb) - pcbinswdif(ipcgb)
10792            ELSE
10793               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswref_av(ipcgb)
10794            ENDIF
10795         ENDDO
10796
10797      CASE ( 'rtm_mrt_sw' )
10798         local_pf = REAL( fill_value, KIND = wp )
10799         IF ( av == 0 )  THEN
10800            DO  l = 1, nmrtbl
10801               local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinsw(l)
10802            ENDDO
10803         ELSE
10804            IF ( ALLOCATED( mrtinsw_av ) ) THEN
10805               DO  l = 1, nmrtbl
10806                  local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinsw_av(l)
10807               ENDDO
10808            ENDIF
10809         ENDIF
10810
10811      CASE ( 'rtm_mrt_lw' )
10812         local_pf = REAL( fill_value, KIND = wp )
10813         IF ( av == 0 )  THEN
10814            DO  l = 1, nmrtbl
10815               local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinlw(l)
10816            ENDDO
10817         ELSE
10818            IF ( ALLOCATED( mrtinlw_av ) ) THEN
10819               DO  l = 1, nmrtbl
10820                  local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinlw_av(l)
10821               ENDDO
10822            ENDIF
10823         ENDIF
10824
10825      CASE ( 'rtm_mrt' )
10826         local_pf = REAL( fill_value, KIND = wp )
10827         IF ( av == 0 )  THEN
10828            DO  l = 1, nmrtbl
10829               local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrt(l)
10830            ENDDO
10831         ELSE
10832            IF ( ALLOCATED( mrt_av ) ) THEN
10833               DO  l = 1, nmrtbl
10834                  local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrt_av(l)
10835               ENDDO
10836            ENDIF
10837         ENDIF
10838
10839       CASE DEFAULT
10840          found = .FALSE.
10841
10842    END SELECT
10843
10844
10845 END SUBROUTINE radiation_data_output_3d
10846
10847!------------------------------------------------------------------------------!
10848!
10849! Description:
10850! ------------
10851!> Subroutine defining masked data output
10852!------------------------------------------------------------------------------!
10853 SUBROUTINE radiation_data_output_mask( av, variable, found, local_pf )
10854 
10855    USE control_parameters
10856       
10857    USE indices
10858   
10859    USE kinds
10860   
10861
10862    IMPLICIT NONE
10863
10864    CHARACTER (LEN=*) ::  variable   !<
10865
10866    CHARACTER(LEN=5) ::  grid        !< flag to distinquish between staggered grids
10867
10868    INTEGER(iwp) ::  av              !<
10869    INTEGER(iwp) ::  i               !<
10870    INTEGER(iwp) ::  j               !<
10871    INTEGER(iwp) ::  k               !<
10872    INTEGER(iwp) ::  topo_top_ind    !< k index of highest horizontal surface
10873
10874    LOGICAL ::  found                !< true if output array was found
10875    LOGICAL ::  resorted             !< true if array is resorted
10876
10877
10878    REAL(wp),                                                                  &
10879       DIMENSION(mask_size_l(mid,1),mask_size_l(mid,2),mask_size_l(mid,3)) ::  &
10880          local_pf   !<
10881
10882    REAL(wp), DIMENSION(:,:,:), POINTER ::  to_be_resorted  !< points to array which needs to be resorted for output
10883
10884
10885    found    = .TRUE.
10886    grid     = 's'
10887    resorted = .FALSE.
10888
10889    SELECT CASE ( TRIM( variable ) )
10890
10891
10892       CASE ( 'rad_lw_in' )
10893          IF ( av == 0 )  THEN
10894             to_be_resorted => rad_lw_in
10895          ELSE
10896             to_be_resorted => rad_lw_in_av
10897          ENDIF
10898
10899       CASE ( 'rad_lw_out' )
10900          IF ( av == 0 )  THEN
10901             to_be_resorted => rad_lw_out
10902          ELSE
10903             to_be_resorted => rad_lw_out_av
10904          ENDIF
10905
10906       CASE ( 'rad_lw_cs_hr' )
10907          IF ( av == 0 )  THEN
10908             to_be_resorted => rad_lw_cs_hr
10909          ELSE
10910             to_be_resorted => rad_lw_cs_hr_av
10911          ENDIF
10912
10913       CASE ( 'rad_lw_hr' )
10914          IF ( av == 0 )  THEN
10915             to_be_resorted => rad_lw_hr
10916          ELSE
10917             to_be_resorted => rad_lw_hr_av
10918          ENDIF
10919
10920       CASE ( 'rad_sw_in' )
10921          IF ( av == 0 )  THEN
10922             to_be_resorted => rad_sw_in
10923          ELSE
10924             to_be_resorted => rad_sw_in_av
10925          ENDIF
10926
10927       CASE ( 'rad_sw_out' )
10928          IF ( av == 0 )  THEN
10929             to_be_resorted => rad_sw_out
10930          ELSE
10931             to_be_resorted => rad_sw_out_av
10932          ENDIF
10933
10934       CASE ( 'rad_sw_cs_hr' )
10935          IF ( av == 0 )  THEN
10936             to_be_resorted => rad_sw_cs_hr
10937          ELSE
10938             to_be_resorted => rad_sw_cs_hr_av
10939          ENDIF
10940
10941       CASE ( 'rad_sw_hr' )
10942          IF ( av == 0 )  THEN
10943             to_be_resorted => rad_sw_hr
10944          ELSE
10945             to_be_resorted => rad_sw_hr_av
10946          ENDIF
10947
10948       CASE DEFAULT
10949          found = .FALSE.
10950
10951    END SELECT
10952
10953!
10954!-- Resort the array to be output, if not done above
10955    IF ( .NOT. resorted )  THEN
10956       IF ( .NOT. mask_surface(mid) )  THEN
10957!
10958!--       Default masked output
10959          DO  i = 1, mask_size_l(mid,1)
10960             DO  j = 1, mask_size_l(mid,2)
10961                DO  k = 1, mask_size_l(mid,3)
10962                   local_pf(i,j,k) =  to_be_resorted(mask_k(mid,k), &
10963                                      mask_j(mid,j),mask_i(mid,i))
10964                ENDDO
10965             ENDDO
10966          ENDDO
10967
10968       ELSE
10969!
10970!--       Terrain-following masked output
10971          DO  i = 1, mask_size_l(mid,1)
10972             DO  j = 1, mask_size_l(mid,2)
10973!
10974!--             Get k index of highest horizontal surface
10975                topo_top_ind = get_topography_top_index_ji( mask_j(mid,j), &
10976                                                            mask_i(mid,i), &
10977                                                            grid )
10978!
10979!--             Save output array
10980                DO  k = 1, mask_size_l(mid,3)
10981                   local_pf(i,j,k) = to_be_resorted(                       &
10982                                          MIN( topo_top_ind+mask_k(mid,k), &
10983                                               nzt+1 ),                    &
10984                                          mask_j(mid,j),                   &
10985                                          mask_i(mid,i)                     )
10986                ENDDO
10987             ENDDO
10988          ENDDO
10989
10990       ENDIF
10991    ENDIF
10992
10993
10994
10995 END SUBROUTINE radiation_data_output_mask
10996
10997
10998!------------------------------------------------------------------------------!
10999! Description:
11000! ------------
11001!> Subroutine writes local (subdomain) restart data
11002!------------------------------------------------------------------------------!
11003 SUBROUTINE radiation_wrd_local
11004
11005
11006    IMPLICIT NONE
11007
11008
11009    IF ( ALLOCATED( rad_net_av ) )  THEN
11010       CALL wrd_write_string( 'rad_net_av' )
11011       WRITE ( 14 )  rad_net_av
11012    ENDIF
11013   
11014    IF ( ALLOCATED( rad_lw_in_xy_av ) )  THEN
11015       CALL wrd_write_string( 'rad_lw_in_xy_av' )
11016       WRITE ( 14 )  rad_lw_in_xy_av
11017    ENDIF
11018   
11019    IF ( ALLOCATED( rad_lw_out_xy_av ) )  THEN
11020       CALL wrd_write_string( 'rad_lw_out_xy_av' )
11021       WRITE ( 14 )  rad_lw_out_xy_av
11022    ENDIF
11023   
11024    IF ( ALLOCATED( rad_sw_in_xy_av ) )  THEN
11025       CALL wrd_write_string( 'rad_sw_in_xy_av' )
11026       WRITE ( 14 )  rad_sw_in_xy_av
11027    ENDIF
11028   
11029    IF ( ALLOCATED( rad_sw_out_xy_av ) )  THEN
11030       CALL wrd_write_string( 'rad_sw_out_xy_av' )
11031       WRITE ( 14 )  rad_sw_out_xy_av
11032    ENDIF
11033
11034    IF ( ALLOCATED( rad_lw_in ) )  THEN
11035       CALL wrd_write_string( 'rad_lw_in' )
11036       WRITE ( 14 )  rad_lw_in
11037    ENDIF
11038
11039    IF ( ALLOCATED( rad_lw_in_av ) )  THEN
11040       CALL wrd_write_string( 'rad_lw_in_av' )
11041       WRITE ( 14 )  rad_lw_in_av
11042    ENDIF
11043
11044    IF ( ALLOCATED( rad_lw_out ) )  THEN
11045       CALL wrd_write_string( 'rad_lw_out' )
11046       WRITE ( 14 )  rad_lw_out
11047    ENDIF
11048
11049    IF ( ALLOCATED( rad_lw_out_av) )  THEN
11050       CALL wrd_write_string( 'rad_lw_out_av' )
11051       WRITE ( 14 )  rad_lw_out_av
11052    ENDIF
11053
11054    IF ( ALLOCATED( rad_lw_cs_hr) )  THEN
11055       CALL wrd_write_string( 'rad_lw_cs_hr' )
11056       WRITE ( 14 )  rad_lw_cs_hr
11057    ENDIF
11058
11059    IF ( ALLOCATED( rad_lw_cs_hr_av) )  THEN
11060       CALL wrd_write_string( 'rad_lw_cs_hr_av' )
11061       WRITE ( 14 )  rad_lw_cs_hr_av
11062    ENDIF
11063
11064    IF ( ALLOCATED( rad_lw_hr) )  THEN
11065       CALL wrd_write_string( 'rad_lw_hr' )
11066       WRITE ( 14 )  rad_lw_hr
11067    ENDIF
11068
11069    IF ( ALLOCATED( rad_lw_hr_av) )  THEN
11070       CALL wrd_write_string( 'rad_lw_hr_av' )
11071       WRITE ( 14 )  rad_lw_hr_av
11072    ENDIF
11073
11074    IF ( ALLOCATED( rad_sw_in) )  THEN
11075       CALL wrd_write_string( 'rad_sw_in' )
11076       WRITE ( 14 )  rad_sw_in
11077    ENDIF
11078
11079    IF ( ALLOCATED( rad_sw_in_av) )  THEN
11080       CALL wrd_write_string( 'rad_sw_in_av' )
11081       WRITE ( 14 )  rad_sw_in_av
11082    ENDIF
11083
11084    IF ( ALLOCATED( rad_sw_out) )  THEN
11085       CALL wrd_write_string( 'rad_sw_out' )
11086       WRITE ( 14 )  rad_sw_out
11087    ENDIF
11088
11089    IF ( ALLOCATED( rad_sw_out_av) )  THEN
11090       CALL wrd_write_string( 'rad_sw_out_av' )
11091       WRITE ( 14 )  rad_sw_out_av
11092    ENDIF
11093
11094    IF ( ALLOCATED( rad_sw_cs_hr) )  THEN
11095       CALL wrd_write_string( 'rad_sw_cs_hr' )
11096       WRITE ( 14 )  rad_sw_cs_hr
11097    ENDIF
11098
11099    IF ( ALLOCATED( rad_sw_cs_hr_av) )  THEN
11100       CALL wrd_write_string( 'rad_sw_cs_hr_av' )
11101       WRITE ( 14 )  rad_sw_cs_hr_av
11102    ENDIF
11103
11104    IF ( ALLOCATED( rad_sw_hr) )  THEN
11105       CALL wrd_write_string( 'rad_sw_hr' )
11106       WRITE ( 14 )  rad_sw_hr
11107    ENDIF
11108
11109    IF ( ALLOCATED( rad_sw_hr_av) )  THEN
11110       CALL wrd_write_string( 'rad_sw_hr_av' )
11111       WRITE ( 14 )  rad_sw_hr_av
11112    ENDIF
11113
11114
11115 END SUBROUTINE radiation_wrd_local
11116
11117!------------------------------------------------------------------------------!
11118! Description:
11119! ------------
11120!> Subroutine reads local (subdomain) restart data
11121!------------------------------------------------------------------------------!
11122 SUBROUTINE radiation_rrd_local( k, nxlf, nxlc, nxl_on_file, nxrf, nxrc,       &
11123                                nxr_on_file, nynf, nync, nyn_on_file, nysf,    &
11124                                nysc, nys_on_file, tmp_2d, tmp_3d, found )
11125 
11126
11127    USE control_parameters
11128       
11129    USE indices
11130   
11131    USE kinds
11132   
11133    USE pegrid
11134
11135
11136    IMPLICIT NONE
11137
11138    INTEGER(iwp) ::  k               !<
11139    INTEGER(iwp) ::  nxlc            !<
11140    INTEGER(iwp) ::  nxlf            !<
11141    INTEGER(iwp) ::  nxl_on_file     !<
11142    INTEGER(iwp) ::  nxrc            !<
11143    INTEGER(iwp) ::  nxrf            !<
11144    INTEGER(iwp) ::  nxr_on_file     !<
11145    INTEGER(iwp) ::  nync            !<
11146    INTEGER(iwp) ::  nynf            !<
11147    INTEGER(iwp) ::  nyn_on_file     !<
11148    INTEGER(iwp) ::  nysc            !<
11149    INTEGER(iwp) ::  nysf            !<
11150    INTEGER(iwp) ::  nys_on_file     !<
11151
11152    LOGICAL, INTENT(OUT)  :: found
11153
11154    REAL(wp), DIMENSION(nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_2d   !<
11155
11156    REAL(wp), DIMENSION(nzb:nzt+1,nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_3d   !<
11157
11158    REAL(wp), DIMENSION(0:0,nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_3d2   !<
11159
11160
11161    found = .TRUE.
11162
11163
11164    SELECT CASE ( restart_string(1:length) )
11165
11166       CASE ( 'rad_net_av' )
11167          IF ( .NOT. ALLOCATED( rad_net_av ) )  THEN
11168             ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
11169          ENDIF 
11170          IF ( k == 1 )  READ ( 13 )  tmp_2d
11171          rad_net_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =           &
11172                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11173                       
11174       CASE ( 'rad_lw_in_xy_av' )
11175          IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) )  THEN
11176             ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
11177          ENDIF 
11178          IF ( k == 1 )  READ ( 13 )  tmp_2d
11179          rad_lw_in_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =      &
11180                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11181                       
11182       CASE ( 'rad_lw_out_xy_av' )
11183          IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) )  THEN
11184             ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
11185          ENDIF 
11186          IF ( k == 1 )  READ ( 13 )  tmp_2d
11187          rad_lw_out_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =     &
11188                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11189                       
11190       CASE ( 'rad_sw_in_xy_av' )
11191          IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) )  THEN
11192             ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
11193          ENDIF 
11194          IF ( k == 1 )  READ ( 13 )  tmp_2d
11195          rad_sw_in_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =      &
11196                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11197                       
11198       CASE ( 'rad_sw_out_xy_av' )
11199          IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) )  THEN
11200             ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
11201          ENDIF 
11202          IF ( k == 1 )  READ ( 13 )  tmp_2d
11203          rad_sw_out_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =     &
11204                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11205                       
11206       CASE ( 'rad_lw_in' )
11207          IF ( .NOT. ALLOCATED( rad_lw_in ) )  THEN
11208             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11209                  radiation_scheme == 'constant')  THEN
11210                ALLOCATE( rad_lw_in(0:0,nysg:nyng,nxlg:nxrg) )
11211             ELSE
11212                ALLOCATE( rad_lw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11213             ENDIF
11214          ENDIF 
11215          IF ( k == 1 )  THEN
11216             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11217                  radiation_scheme == 'constant')  THEN
11218                READ ( 13 )  tmp_3d2
11219                rad_lw_in(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =   &
11220                   tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11221             ELSE
11222                READ ( 13 )  tmp_3d
11223                rad_lw_in(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11224                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11225             ENDIF
11226          ENDIF
11227
11228       CASE ( 'rad_lw_in_av' )
11229          IF ( .NOT. ALLOCATED( rad_lw_in_av ) )  THEN
11230             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11231                  radiation_scheme == 'constant')  THEN
11232                ALLOCATE( rad_lw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
11233             ELSE
11234                ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11235             ENDIF
11236          ENDIF 
11237          IF ( k == 1 )  THEN
11238             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11239                  radiation_scheme == 'constant')  THEN
11240                READ ( 13 )  tmp_3d2
11241                rad_lw_in_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =&
11242                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11243             ELSE
11244                READ ( 13 )  tmp_3d
11245                rad_lw_in_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11246                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11247             ENDIF
11248          ENDIF
11249
11250       CASE ( 'rad_lw_out' )
11251          IF ( .NOT. ALLOCATED( rad_lw_out ) )  THEN
11252             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11253                  radiation_scheme == 'constant')  THEN
11254                ALLOCATE( rad_lw_out(0:0,nysg:nyng,nxlg:nxrg) )
11255             ELSE
11256                ALLOCATE( rad_lw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11257             ENDIF
11258          ENDIF 
11259          IF ( k == 1 )  THEN
11260             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11261                  radiation_scheme == 'constant')  THEN
11262                READ ( 13 )  tmp_3d2
11263                rad_lw_out(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11264                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11265             ELSE
11266                READ ( 13 )  tmp_3d
11267                rad_lw_out(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =    &
11268                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11269             ENDIF
11270          ENDIF
11271
11272       CASE ( 'rad_lw_out_av' )
11273          IF ( .NOT. ALLOCATED( rad_lw_out_av ) )  THEN
11274             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11275                  radiation_scheme == 'constant')  THEN
11276                ALLOCATE( rad_lw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
11277             ELSE
11278                ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11279             ENDIF
11280          ENDIF 
11281          IF ( k == 1 )  THEN
11282             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11283                  radiation_scheme == 'constant')  THEN
11284                READ ( 13 )  tmp_3d2
11285                rad_lw_out_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) &
11286                   = tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11287             ELSE
11288                READ ( 13 )  tmp_3d
11289                rad_lw_out_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &
11290                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11291             ENDIF
11292          ENDIF
11293
11294       CASE ( 'rad_lw_cs_hr' )
11295          IF ( .NOT. ALLOCATED( rad_lw_cs_hr ) )  THEN
11296             ALLOCATE( rad_lw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11297          ENDIF
11298          IF ( k == 1 )  READ ( 13 )  tmp_3d
11299          rad_lw_cs_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11300                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11301
11302       CASE ( 'rad_lw_cs_hr_av' )
11303          IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) )  THEN
11304             ALLOCATE( rad_lw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11305          ENDIF
11306          IF ( k == 1 )  READ ( 13 )  tmp_3d
11307          rad_lw_cs_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11308                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11309
11310       CASE ( 'rad_lw_hr' )
11311          IF ( .NOT. ALLOCATED( rad_lw_hr ) )  THEN
11312             ALLOCATE( rad_lw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11313          ENDIF
11314          IF ( k == 1 )  READ ( 13 )  tmp_3d
11315          rad_lw_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =           &
11316                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11317
11318       CASE ( 'rad_lw_hr_av' )
11319          IF ( .NOT. ALLOCATED( rad_lw_hr_av ) )  THEN
11320             ALLOCATE( rad_lw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11321          ENDIF
11322          IF ( k == 1 )  READ ( 13 )  tmp_3d
11323          rad_lw_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11324                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11325
11326       CASE ( 'rad_sw_in' )
11327          IF ( .NOT. ALLOCATED( rad_sw_in ) )  THEN
11328             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11329                  radiation_scheme == 'constant')  THEN
11330                ALLOCATE( rad_sw_in(0:0,nysg:nyng,nxlg:nxrg) )
11331             ELSE
11332                ALLOCATE( rad_sw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11333             ENDIF
11334          ENDIF 
11335          IF ( k == 1 )  THEN
11336             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11337                  radiation_scheme == 'constant')  THEN
11338                READ ( 13 )  tmp_3d2
11339                rad_sw_in(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =   &
11340                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11341             ELSE
11342                READ ( 13 )  tmp_3d
11343                rad_sw_in(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11344                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11345             ENDIF
11346          ENDIF
11347
11348       CASE ( 'rad_sw_in_av' )
11349          IF ( .NOT. ALLOCATED( rad_sw_in_av ) )  THEN
11350             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11351                  radiation_scheme == 'constant')  THEN
11352                ALLOCATE( rad_sw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
11353             ELSE
11354                ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11355             ENDIF
11356          ENDIF 
11357          IF ( k == 1 )  THEN
11358             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11359                  radiation_scheme == 'constant')  THEN
11360                READ ( 13 )  tmp_3d2
11361                rad_sw_in_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =&
11362                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11363             ELSE
11364                READ ( 13 )  tmp_3d
11365                rad_sw_in_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11366                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11367             ENDIF
11368          ENDIF
11369
11370       CASE ( 'rad_sw_out' )
11371          IF ( .NOT. ALLOCATED( rad_sw_out ) )  THEN
11372             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11373                  radiation_scheme == 'constant')  THEN
11374                ALLOCATE( rad_sw_out(0:0,nysg:nyng,nxlg:nxrg) )
11375             ELSE
11376                ALLOCATE( rad_sw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11377             ENDIF
11378          ENDIF 
11379          IF ( k == 1 )  THEN
11380             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11381                  radiation_scheme == 'constant')  THEN
11382                READ ( 13 )  tmp_3d2
11383                rad_sw_out(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11384                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11385             ELSE
11386                READ ( 13 )  tmp_3d
11387                rad_sw_out(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =    &
11388                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11389             ENDIF
11390          ENDIF
11391
11392       CASE ( 'rad_sw_out_av' )
11393          IF ( .NOT. ALLOCATED( rad_sw_out_av ) )  THEN
11394             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11395                  radiation_scheme == 'constant')  THEN
11396                ALLOCATE( rad_sw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
11397             ELSE
11398                ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11399             ENDIF
11400          ENDIF 
11401          IF ( k == 1 )  THEN
11402             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11403                  radiation_scheme == 'constant')  THEN
11404                READ ( 13 )  tmp_3d2
11405                rad_sw_out_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) &
11406                   = tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11407             ELSE
11408                READ ( 13 )  tmp_3d
11409                rad_sw_out_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &
11410                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11411             ENDIF
11412          ENDIF
11413
11414       CASE ( 'rad_sw_cs_hr' )
11415          IF ( .NOT. ALLOCATED( rad_sw_cs_hr ) )  THEN
11416             ALLOCATE( rad_sw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11417          ENDIF
11418          IF ( k == 1 )  READ ( 13 )  tmp_3d
11419          rad_sw_cs_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11420                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11421
11422       CASE ( 'rad_sw_cs_hr_av' )
11423          IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) )  THEN
11424             ALLOCATE( rad_sw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11425          ENDIF
11426          IF ( k == 1 )  READ ( 13 )  tmp_3d
11427          rad_sw_cs_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11428                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11429
11430       CASE ( 'rad_sw_hr' )
11431          IF ( .NOT. ALLOCATED( rad_sw_hr ) )  THEN
11432             ALLOCATE( rad_sw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11433          ENDIF
11434          IF ( k == 1 )  READ ( 13 )  tmp_3d
11435          rad_sw_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =           &
11436                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11437
11438       CASE ( 'rad_sw_hr_av' )
11439          IF ( .NOT. ALLOCATED( rad_sw_hr_av ) )  THEN
11440             ALLOCATE( rad_sw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11441          ENDIF
11442          IF ( k == 1 )  READ ( 13 )  tmp_3d
11443          rad_lw_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11444                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11445
11446       CASE DEFAULT
11447
11448          found = .FALSE.
11449
11450    END SELECT
11451
11452 END SUBROUTINE radiation_rrd_local
11453
11454!------------------------------------------------------------------------------!
11455! Description:
11456! ------------
11457!> Subroutine writes debug information
11458!------------------------------------------------------------------------------!
11459 SUBROUTINE radiation_write_debug_log ( message )
11460    !> it writes debug log with time stamp
11461    CHARACTER(*)  :: message
11462    CHARACTER(15) :: dtc
11463    CHARACTER(8)  :: date
11464    CHARACTER(10) :: time
11465    CHARACTER(5)  :: zone
11466    CALL date_and_time(date, time, zone)
11467    dtc = date(7:8)//','//time(1:2)//':'//time(3:4)//':'//time(5:10)
11468    WRITE(9,'(2A)') dtc, TRIM(message)
11469    FLUSH(9)
11470 END SUBROUTINE radiation_write_debug_log
11471
11472 END MODULE radiation_model_mod
Note: See TracBrowser for help on using the repository browser.