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

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

Revision of virtual-measurement module and data output enabled. Further, post-processing tool added to merge distributed virtually sampled data and to output it into NetCDF files.

  • 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: 498.0 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! Make variables that are sampled in virtual measurement module public
26!
27! Former revisions:
28! -----------------
29! $Id: radiation_model_mod.f90 3704 2019-01-29 19:51:41Z suehring $
30! Some interface calls moved to module_interface + cleanup
31!
32! 3667 2019-01-10 14:26:24Z schwenkel
33! Modified check for rrtmg input files
34!
35! 3655 2019-01-07 16:51:22Z knoop
36! nopointer option removed
37!
38! 3633 2018-12-17 16:17:57Z schwenkel
39! Include check for rrtmg files
40!
41! 3630 2018-12-17 11:04:17Z knoop
42! - fix initialization of date and time after calling zenith
43! - fix a bug in radiation_solar_pos
44!
45! 3616 2018-12-10 09:44:36Z Salim
46! fix manipulation of time variables in radiation_presimulate_solar_pos
47!
48! 3608 2018-12-07 12:59:57Z suehring $
49! Bugfix radiation output
50!
51! 3607 2018-12-07 11:56:58Z suehring
52! Output of radiation-related quantities migrated to radiation_model_mod.
53!
54! 3589 2018-11-30 15:09:51Z suehring
55! Remove erroneous UTF encoding
56!
57! 3572 2018-11-28 11:40:28Z suehring
58! Add filling the short- and longwave radiation flux arrays (e.g. diffuse,
59! direct, reflected, resedual) for all surfaces. This is required to surface
60! outputs in suface_output_mod. (M. Salim)
61!
62! 3571 2018-11-28 09:24:03Z moh.hefny
63! Add an epsilon value to compare values in if statement to fix possible
64! precsion related errors in raytrace routines.
65!
66! 3524 2018-11-14 13:36:44Z raasch
67! missing cpp-directives added
68!
69! 3495 2018-11-06 15:22:17Z kanani
70! Resort control_parameters ONLY list,
71! From branch radiation@3491 moh.hefny:
72! bugfix in calculating the apparent solar positions by updating
73! the simulated time so that the actual time is correct.
74!
75! 3464 2018-10-30 18:08:55Z kanani
76! From branch resler@3462, pavelkrc:
77! add MRT shaping function for human
78!
79! 3449 2018-10-29 19:36:56Z suehring
80! New RTM version 3.0: (Pavel Krc, Jaroslav Resler, ICS, Prague)
81!   - Interaction of plant canopy with LW radiation
82!   - Transpiration from resolved plant canopy dependent on radiation
83!     called from RTM
84!
85!
86! 3435 2018-10-26 18:25:44Z gronemeier
87! - workaround: return unit=illegal in check_data_output for certain variables
88!   when check called from init_masks
89! - Use pointer in masked output to reduce code redundancies
90! - Add terrain-following masked output
91!
92! 3424 2018-10-25 07:29:10Z gronemeier
93! bugfix: add rad_lw_in, rad_lw_out, rad_sw_out to radiation_check_data_output
94!
95! 3378 2018-10-19 12:34:59Z kanani
96! merge from radiation branch (r3362) into trunk
97! (moh.hefny):
98! - removed read/write_svf_on_init and read_dist_max_svf (not used anymore)
99! - bugfix nzut > nzpt in calculating maxboxes
100!
101! 3372 2018-10-18 14:03:19Z raasch
102! bugfix: kind type of 2nd argument of mpi_win_allocate changed, misplaced
103!         __parallel directive
104!
105! 3351 2018-10-15 18:40:42Z suehring
106! Do not overwrite values of spectral and broadband albedo during initialization
107! if they are already initialized in the urban-surface model via ASCII input.
108!
109! 3337 2018-10-12 15:17:09Z kanani
110! - New RTM version 2.9: (Pavel Krc, Jaroslav Resler, ICS, Prague)
111!   added calculation of the MRT inside the RTM module
112!   MRT fluxes are consequently used in the new biometeorology module
113!   for calculation of biological indices (MRT, PET)
114!   Fixes of v. 2.5 and SVN trunk:
115!    - proper initialization of rad_net_l
116!    - make arrays nsurfs and surfstart TARGET to prevent some MPI problems
117!    - initialization of arrays used in MPI one-sided operation as 1-D arrays
118!      to prevent problems with some MPI/compiler combinations
119!    - fix indexing of target displacement in subroutine request_itarget to
120!      consider nzub
121!    - fix LAD dimmension range in PCB calculation
122!    - check ierr in all MPI calls
123!    - use proper per-gridbox sky and diffuse irradiance
124!    - fix shading for reflected irradiance
125!    - clear away the residuals of "atmospheric surfaces" implementation
126!    - fix rounding bug in raytrace_2d introduced in SVN trunk
127! - New RTM version 2.5: (Pavel Krc, Jaroslav Resler, ICS, Prague)
128!   can use angular discretization for all SVF
129!   (i.e. reflected and emitted radiation in addition to direct and diffuse),
130!   allowing for much better scaling wih high resoltion and/or complex terrain
131! - Unite array grow factors
132! - Fix slightly shifted terrain height in raytrace_2d
133! - Use more efficient MPI_Win_allocate for reverse gridsurf index
134! - Fix random MPI RMA bugs on Intel compilers
135! - Fix approx. double plant canopy sink values for reflected radiation
136! - Fix mostly missing plant canopy sinks for direct radiation
137! - Fix discretization errors for plant canopy sink in diffuse radiation
138! - Fix rounding errors in raytrace_2d
139!
140! 3274 2018-09-24 15:42:55Z knoop
141! Modularization of all bulk cloud physics code components
142!
143! 3272 2018-09-24 10:16:32Z suehring
144! - split direct and diffusion shortwave radiation using RRTMG rather than using
145!   calc_diffusion_radiation, in case of RRTMG
146! - removed the namelist variable split_diffusion_radiation. Now splitting depends
147!   on the choise of radiation radiation scheme
148! - removed calculating the rdiation flux for surfaces at the radiation scheme
149!   in case of using RTM since it will be calculated anyway in the radiation
150!   interaction routine.
151! - set SW radiation flux for surfaces to zero at night in case of no RTM is used
152! - precalculate the unit vector yxdir of ray direction to avoid the temporarly
153!   array allocation during the subroutine call
154! - fixed a bug in calculating the max number of boxes ray can cross in the domain
155!
156! 3264 2018-09-20 13:54:11Z moh.hefny
157! Bugfix in raytrace_2d calls
158!
159! 3248 2018-09-14 09:42:06Z sward
160! Minor formating changes
161!
162! 3246 2018-09-13 15:14:50Z sward
163! Added error handling for input namelist via parin_fail_message
164!
165! 3241 2018-09-12 15:02:00Z raasch
166! unused variables removed or commented
167!
168! 3233 2018-09-07 13:21:24Z schwenkel
169! Adapted for the use of cloud_droplets
170!
171! 3230 2018-09-05 09:29:05Z schwenkel
172! Bugfix in radiation_constant_surf: changed (10.0 - emissivity_urb) to
173! (1.0 - emissivity_urb)
174!
175! 3226 2018-08-31 12:27:09Z suehring
176! Bugfixes in calculation of sky-view factors and canopy-sink factors.
177!
178! 3186 2018-07-30 17:07:14Z suehring
179! Remove print statement
180!
181! 3180 2018-07-27 11:00:56Z suehring
182! Revise concept for calculation of effective radiative temperature and mapping
183! of radiative heating
184!
185! 3175 2018-07-26 14:07:38Z suehring
186! Bugfix for commit 3172
187!
188! 3173 2018-07-26 12:55:23Z suehring
189! Revise output of surface radiation quantities in case of overhanging
190! structures
191!
192! 3172 2018-07-26 12:06:06Z suehring
193! Bugfixes:
194!  - temporal work-around for calculation of effective radiative surface
195!    temperature
196!  - prevent positive solar radiation during nighttime
197!
198! 3170 2018-07-25 15:19:37Z suehring
199! Bugfix, map signle-column radiation forcing profiles on top of any topography
200!
201! 3156 2018-07-19 16:30:54Z knoop
202! Bugfix: replaced usage of the pt array with the surf%pt_surface array
203!
204! 3137 2018-07-17 06:44:21Z maronga
205! String length for trace_names fixed
206!
207! 3127 2018-07-15 08:01:25Z maronga
208! A few pavement parameters updated.
209!
210! 3123 2018-07-12 16:21:53Z suehring
211! Correct working precision for INTEGER number
212!
213! 3122 2018-07-11 21:46:41Z maronga
214! Bugfix: maximum distance for raytracing was set to  -999 m by default,
215! effectively switching off all surface reflections when max_raytracing_dist
216! was not explicitly set in namelist
217!
218! 3117 2018-07-11 09:59:11Z maronga
219! Bugfix: water vapor was not transfered to RRTMG when bulk_cloud_model = .F.
220! Bugfix: changed the calculation of RRTMG boundary conditions (Mohamed Salim)
221! Bugfix: dry residual atmosphere is replaced by standard RRTMG atmosphere
222!
223! 3116 2018-07-10 14:31:58Z suehring
224! Output of long/shortwave radiation at surface
225!
226! 3107 2018-07-06 15:55:51Z suehring
227! Bugfix, missing index for dz
228!
229! 3066 2018-06-12 08:55:55Z Giersch
230! Error message revised
231!
232! 3065 2018-06-12 07:03:02Z Giersch
233! dz was replaced by dz(1), error message concerning vertical stretching was
234! added 
235!
236! 3049 2018-05-29 13:52:36Z Giersch
237! Error messages revised
238!
239! 3045 2018-05-28 07:55:41Z Giersch
240! Error message revised
241!
242! 3026 2018-05-22 10:30:53Z schwenkel
243! Changed the name specific humidity to mixing ratio, since we are computing
244! mixing ratios.
245!
246! 3016 2018-05-09 10:53:37Z Giersch
247! Revised structure of reading svf data according to PALM coding standard:
248! svf_code_field/len and fsvf removed, error messages PA0493 and PA0494 added,
249! allocation status of output arrays checked.
250!
251! 3014 2018-05-09 08:42:38Z maronga
252! Introduced plant canopy height similar to urban canopy height to limit
253! the memory requirement to allocate lad.
254! Deactivated automatic setting of minimum raytracing distance.
255!
256! 3004 2018-04-27 12:33:25Z Giersch
257! Further allocation checks implemented (averaged data will be assigned to fill
258! values if no allocation happened so far)
259!
260! 2995 2018-04-19 12:13:16Z Giersch
261! IF-statement in radiation_init removed so that the calculation of radiative
262! fluxes at model start is done in any case, bugfix in
263! radiation_presimulate_solar_pos (end_time is the sum of end_time and the
264! spinup_time specified in the p3d_file ), list of variables/fields that have
265! to be written out or read in case of restarts has been extended
266!
267! 2977 2018-04-17 10:27:57Z kanani
268! Implement changes from branch radiation (r2948-2971) with minor modifications,
269! plus some formatting.
270! (moh.hefny):
271! - replaced plant_canopy by npcbl to check tree existence to avoid weird
272!   allocation of related arrays (after domain decomposition some domains
273!   contains no trees although plant_canopy (global parameter) is still TRUE).
274! - added a namelist parameter to force RTM settings
275! - enabled the option to switch radiation reflections off
276! - renamed surf_reflections to surface_reflections
277! - removed average_radiation flag from the namelist (now it is implicitly set
278!   in init_3d_model according to RTM)
279! - edited read and write sky view factors and CSF routines to account for
280!   the sub-domains which may not contain any of them
281!
282! 2967 2018-04-13 11:22:08Z raasch
283! bugfix: missing parallel cpp-directives added
284!
285! 2964 2018-04-12 16:04:03Z Giersch
286! Error message PA0491 has been introduced which could be previously found in
287! check_open. The variable numprocs_previous_run is only known in case of
288! initializing_actions == read_restart_data
289!
290! 2963 2018-04-12 14:47:44Z suehring
291! - Introduce index for vegetation/wall, pavement/green-wall and water/window
292!   surfaces, for clearer access of surface fraction, albedo, emissivity, etc. .
293! - Minor bugfix in initialization of albedo for window surfaces
294!
295! 2944 2018-04-03 16:20:18Z suehring
296! Fixed bad commit
297!
298! 2943 2018-04-03 16:17:10Z suehring
299! No read of nsurfl from SVF file since it is calculated in
300! radiation_interaction_init,
301! allocation of arrays in radiation_read_svf only if not yet allocated,
302! update of 2920 revision comment.
303!
304! 2932 2018-03-26 09:39:22Z maronga
305! renamed radiation_par to radiation_parameters
306!
307! 2930 2018-03-23 16:30:46Z suehring
308! Remove default surfaces from radiation model, does not make much sense to
309! apply radiation model without energy-balance solvers; Further, add check for
310! this.
311!
312! 2920 2018-03-22 11:22:01Z kanani
313! - Bugfix: Initialize pcbl array (=-1)
314! RTM version 2.0 (Jaroslav Resler, Pavel Krc, Mohamed Salim):
315! - new major version of radiation interactions
316! - substantially enhanced performance and scalability
317! - processing of direct and diffuse solar radiation separated from reflected
318!   radiation, removed virtual surfaces
319! - new type of sky discretization by azimuth and elevation angles
320! - diffuse radiation processed cumulatively using sky view factor
321! - used precalculated apparent solar positions for direct irradiance
322! - added new 2D raytracing process for processing whole vertical column at once
323!   to increase memory efficiency and decrease number of MPI RMA operations
324! - enabled limiting the number of view factors between surfaces by the distance
325!   and value
326! - fixing issues induced by transferring radiation interactions from
327!   urban_surface_mod to radiation_mod
328! - bugfixes and other minor enhancements
329!
330! 2906 2018-03-19 08:56:40Z Giersch
331! NAMELIST paramter read/write_svf_on_init have been removed, functions
332! check_open and close_file are used now for opening/closing files related to
333! svf data, adjusted unit number and error numbers
334!
335! 2894 2018-03-15 09:17:58Z Giersch
336! Calculations of the index range of the subdomain on file which overlaps with
337! the current subdomain are already done in read_restart_data_mod
338! radiation_read_restart_data was renamed to radiation_rrd_local and
339! radiation_last_actions was renamed to radiation_wrd_local, variable named
340! found has been introduced for checking if restart data was found, reading
341! of restart strings has been moved completely to read_restart_data_mod,
342! radiation_rrd_local is already inside the overlap loop programmed in
343! read_restart_data_mod, the marker *** end rad *** is not necessary anymore,
344! strings and their respective lengths are written out and read now in case of
345! restart runs to get rid of prescribed character lengths (Giersch)
346!
347! 2809 2018-02-15 09:55:58Z suehring
348! Bugfix for gfortran: Replace the function C_SIZEOF with STORAGE_SIZE
349!
350! 2753 2018-01-16 14:16:49Z suehring
351! Tile approach for spectral albedo implemented.
352!
353! 2746 2018-01-15 12:06:04Z suehring
354! Move flag plant canopy to modules
355!
356! 2724 2018-01-05 12:12:38Z maronga
357! Set default of average_radiation to .FALSE.
358!
359! 2723 2018-01-05 09:27:03Z maronga
360! Bugfix in calculation of rad_lw_out (clear-sky). First grid level was used
361! instead of the surface value
362!
363! 2718 2018-01-02 08:49:38Z maronga
364! Corrected "Former revisions" section
365!
366! 2707 2017-12-18 18:34:46Z suehring
367! Changes from last commit documented
368!
369! 2706 2017-12-18 18:33:49Z suehring
370! Bugfix, in average radiation case calculate exner function before using it.
371!
372! 2701 2017-12-15 15:40:50Z suehring
373! Changes from last commit documented
374!
375! 2698 2017-12-14 18:46:24Z suehring
376! Bugfix in get_topography_top_index
377!
378! 2696 2017-12-14 17:12:51Z kanani
379! - Change in file header (GPL part)
380! - Improved reading/writing of SVF from/to file (BM)
381! - Bugfixes concerning RRTMG as well as average_radiation options (M. Salim)
382! - Revised initialization of surface albedo and some minor bugfixes (MS)
383! - Update net radiation after running radiation interaction routine (MS)
384! - Revisions from M Salim included
385! - Adjustment to topography and surface structure (MS)
386! - Initialization of albedo and surface emissivity via input file (MS)
387! - albedo_pars extended (MS)
388!
389! 2604 2017-11-06 13:29:00Z schwenkel
390! bugfix for calculation of effective radius using morrison microphysics
391!
392! 2601 2017-11-02 16:22:46Z scharf
393! added emissivity to namelist
394!
395! 2575 2017-10-24 09:57:58Z maronga
396! Bugfix: calculation of shortwave and longwave albedos for RRTMG swapped
397!
398! 2547 2017-10-16 12:41:56Z schwenkel
399! extended by cloud_droplets option, minor bugfix and correct calculation of
400! cloud droplet number concentration
401!
402! 2544 2017-10-13 18:09:32Z maronga
403! Moved date and time quantitis to separate module date_and_time_mod
404!
405! 2512 2017-10-04 08:26:59Z raasch
406! upper bounds of cross section and 3d output changed from nx+1,ny+1 to nx,ny
407! no output of ghost layer data
408!
409! 2504 2017-09-27 10:36:13Z maronga
410! Updates pavement types and albedo parameters
411!
412! 2328 2017-08-03 12:34:22Z maronga
413! Emissivity can now be set individually for each pixel.
414! Albedo type can be inferred from land surface model.
415! Added default albedo type for bare soil
416!
417! 2318 2017-07-20 17:27:44Z suehring
418! Get topography top index via Function call
419!
420! 2317 2017-07-20 17:27:19Z suehring
421! Improved syntax layout
422!
423! 2298 2017-06-29 09:28:18Z raasch
424! type of write_binary changed from CHARACTER to LOGICAL
425!
426! 2296 2017-06-28 07:53:56Z maronga
427! Added output of rad_sw_out for radiation_scheme = 'constant'
428!
429! 2270 2017-06-09 12:18:47Z maronga
430! Numbering changed (2 timeseries removed)
431!
432! 2249 2017-06-06 13:58:01Z sward
433! Allow for RRTMG runs without humidity/cloud physics
434!
435! 2248 2017-06-06 13:52:54Z sward
436! Error no changed
437!
438! 2233 2017-05-30 18:08:54Z suehring
439!
440! 2232 2017-05-30 17:47:52Z suehring
441! Adjustments to new topography concept
442! Bugfix in read restart
443!
444! 2200 2017-04-11 11:37:51Z suehring
445! Bugfix in call of exchange_horiz_2d and read restart data
446!
447! 2163 2017-03-01 13:23:15Z schwenkel
448! Bugfix in radiation_check_data_output
449!
450! 2157 2017-02-22 15:10:35Z suehring
451! Bugfix in read_restart data
452!
453! 2011 2016-09-19 17:29:57Z kanani
454! Removed CALL of auxiliary SUBROUTINE get_usm_info,
455! flag urban_surface is now defined in module control_parameters.
456!
457! 2007 2016-08-24 15:47:17Z kanani
458! Added calculation of solar directional vector for new urban surface
459! model,
460! accounted for urban_surface model in radiation_check_parameters,
461! correction of comments for zenith angle.
462!
463! 2000 2016-08-20 18:09:15Z knoop
464! Forced header and separation lines into 80 columns
465!
466! 1976 2016-07-27 13:28:04Z maronga
467! Output of 2D/3D/masked data is now directly done within this module. The
468! radiation schemes have been simplified for better usability so that
469! rad_lw_in, rad_lw_out, rad_sw_in, and rad_sw_out are available independent of
470! the radiation code used.
471!
472! 1856 2016-04-13 12:56:17Z maronga
473! Bugfix: allocation of rad_lw_out for radiation_scheme = 'clear-sky'
474!
475! 1853 2016-04-11 09:00:35Z maronga
476! Added routine for radiation_scheme = constant.
477
478! 1849 2016-04-08 11:33:18Z hoffmann
479! Adapted for modularization of microphysics
480!
481! 1826 2016-04-07 12:01:39Z maronga
482! Further modularization.
483!
484! 1788 2016-03-10 11:01:04Z maronga
485! Added new albedo class for pavements / roads.
486!
487! 1783 2016-03-06 18:36:17Z raasch
488! palm-netcdf-module removed in order to avoid a circular module dependency,
489! netcdf-variables moved to netcdf-module, new routine netcdf_handle_error_rad
490! added
491!
492! 1757 2016-02-22 15:49:32Z maronga
493! Added parameter unscheduled_radiation_calls. Bugfix: interpolation of sounding
494! profiles for pressure and temperature above the LES domain.
495!
496! 1709 2015-11-04 14:47:01Z maronga
497! Bugfix: set initial value for rrtm_lwuflx_dt to zero, small formatting
498! corrections
499!
500! 1701 2015-11-02 07:43:04Z maronga
501! Bugfixes: wrong index for output of timeseries, setting of nz_snd_end
502!
503! 1691 2015-10-26 16:17:44Z maronga
504! Added option for spin-up runs without radiation (skip_time_do_radiation). Bugfix
505! in calculation of pressure profiles. Bugfix in calculation of trace gas profiles.
506! Added output of radiative heating rates.
507!
508! 1682 2015-10-07 23:56:08Z knoop
509! Code annotations made doxygen readable
510!
511! 1606 2015-06-29 10:43:37Z maronga
512! Added preprocessor directive __netcdf to allow for compiling without netCDF.
513! Note, however, that RRTMG cannot be used without netCDF.
514!
515! 1590 2015-05-08 13:56:27Z maronga
516! Bugfix: definition of character strings requires same length for all elements
517!
518! 1587 2015-05-04 14:19:01Z maronga
519! Added albedo class for snow
520!
521! 1585 2015-04-30 07:05:52Z maronga
522! Added support for RRTMG
523!
524! 1571 2015-03-12 16:12:49Z maronga
525! Added missing KIND attribute. Removed upper-case variable names
526!
527! 1551 2015-03-03 14:18:16Z maronga
528! Added support for data output. Various variables have been renamed. Added
529! interface for different radiation schemes (currently: clear-sky, constant, and
530! RRTM (not yet implemented).
531!
532! 1496 2014-12-02 17:25:50Z maronga
533! Initial revision
534!
535!
536! Description:
537! ------------
538!> Radiation models and interfaces
539!> @todo Replace dz(1) appropriatly to account for grid stretching
540!> @todo move variable definitions used in radiation_init only to the subroutine
541!>       as they are no longer required after initialization.
542!> @todo Output of full column vertical profiles used in RRTMG
543!> @todo Output of other rrtm arrays (such as volume mixing ratios)
544!> @todo Check for mis-used NINT() calls in raytrace_2d
545!>       RESULT: Original was correct (carefully verified formula), the change
546!>               to INT broke raytracing      -- P. Krc
547!> @todo Optimize radiation_tendency routines
548!>
549!> @note Many variables have a leading dummy dimension (0:0) in order to
550!>       match the assume-size shape expected by the RRTMG model.
551!------------------------------------------------------------------------------!
552 MODULE radiation_model_mod
553 
554    USE arrays_3d,                                                             &
555        ONLY:  dzw, hyp, nc, pt, p, q, ql, u, v, w, zu, zw, exner, d_exner
556
557    USE basic_constants_and_equations_mod,                                     &
558        ONLY:  c_p, g, lv_d_cp, l_v, pi, r_d, rho_l, solar_constant,      &
559               barometric_formula
560
561    USE calc_mean_profile_mod,                                                 &
562        ONLY:  calc_mean_profile
563
564    USE control_parameters,                                                    &
565        ONLY:  cloud_droplets, coupling_char, dz, dt_spinup, end_time,         &
566               humidity,                                                       &
567               initializing_actions, io_blocks, io_group,                      &
568               land_surface, large_scale_forcing,                              &
569               latitude, longitude, lsf_surf,                                  &
570               message_string, plant_canopy, pt_surface,                       &
571               rho_surface, simulated_time, spinup_time, surface_pressure,     &
572               read_svf, write_svf,                                            &
573               time_since_reference_point, urban_surface, varnamelength
574
575    USE cpulog,                                                                &
576        ONLY:  cpu_log, log_point, log_point_s
577
578    USE grid_variables,                                                        &
579         ONLY:  ddx, ddy, dx, dy 
580
581    USE date_and_time_mod,                                                     &
582        ONLY:  calc_date_and_time, d_hours_day, d_seconds_hour, d_seconds_year,&
583               day_of_year, d_seconds_year, day_of_month, day_of_year_init,    &
584               init_date_and_time, month_of_year, time_utc_init, time_utc
585
586    USE indices,                                                               &
587        ONLY:  nnx, nny, nx, nxl, nxlg, nxr, nxrg, ny, nyn, nyng, nys, nysg,   &
588               nzb, nzt
589
590    USE, INTRINSIC :: iso_c_binding
591
592    USE kinds
593
594    USE bulk_cloud_model_mod,                                                  &
595        ONLY:  bulk_cloud_model, microphysics_morrison, na_init, nc_const, sigma_gc
596
597#if defined ( __netcdf )
598    USE NETCDF
599#endif
600
601    USE netcdf_data_input_mod,                                                 &
602        ONLY:  albedo_type_f, albedo_pars_f, building_type_f, pavement_type_f, &
603               vegetation_type_f, water_type_f
604
605    USE plant_canopy_model_mod,                                                &
606        ONLY:  lad_s, pc_heating_rate, pc_transpiration_rate, pc_latent_rate,  &
607               plant_canopy_transpiration, pcm_calc_transpiration_rate
608
609    USE pegrid
610
611#if defined ( __rrtmg )
612    USE parrrsw,                                                               &
613        ONLY:  naerec, nbndsw
614
615    USE parrrtm,                                                               &
616        ONLY:  nbndlw
617
618    USE rrtmg_lw_init,                                                         &
619        ONLY:  rrtmg_lw_ini
620
621    USE rrtmg_sw_init,                                                         &
622        ONLY:  rrtmg_sw_ini
623
624    USE rrtmg_lw_rad,                                                          &
625        ONLY:  rrtmg_lw
626
627    USE rrtmg_sw_rad,                                                          &
628        ONLY:  rrtmg_sw
629#endif
630    USE statistics,                                                            &
631        ONLY:  hom
632
633    USE surface_mod,                                                           &
634        ONLY:  get_topography_top_index, get_topography_top_index_ji,          &
635               ind_pav_green, ind_veg_wall, ind_wat_win,                       &
636               surf_lsm_h, surf_lsm_v, surf_type, surf_usm_h, surf_usm_v,      &
637               vertical_surfaces_exist
638
639    IMPLICIT NONE
640
641    CHARACTER(10) :: radiation_scheme = 'clear-sky' ! 'constant', 'clear-sky', or 'rrtmg'
642
643!
644!-- Predefined Land surface classes (albedo_type) after Briegleb (1992)
645    CHARACTER(37), DIMENSION(0:33), PARAMETER :: albedo_type_name = (/      &
646                                   'user defined                         ', & !  0
647                                   'ocean                                ', & !  1
648                                   'mixed farming, tall grassland        ', & !  2
649                                   'tall/medium grassland                ', & !  3
650                                   'evergreen shrubland                  ', & !  4
651                                   'short grassland/meadow/shrubland     ', & !  5
652                                   'evergreen needleleaf forest          ', & !  6
653                                   'mixed deciduous evergreen forest     ', & !  7
654                                   'deciduous forest                     ', & !  8
655                                   'tropical evergreen broadleaved forest', & !  9
656                                   'medium/tall grassland/woodland       ', & ! 10
657                                   'desert, sandy                        ', & ! 11
658                                   'desert, rocky                        ', & ! 12
659                                   'tundra                               ', & ! 13
660                                   'land ice                             ', & ! 14
661                                   'sea ice                              ', & ! 15
662                                   'snow                                 ', & ! 16
663                                   'bare soil                            ', & ! 17
664                                   'asphalt/concrete mix                 ', & ! 18
665                                   'asphalt (asphalt concrete)           ', & ! 19
666                                   'concrete (Portland concrete)         ', & ! 20
667                                   'sett                                 ', & ! 21
668                                   'paving stones                        ', & ! 22
669                                   'cobblestone                          ', & ! 23
670                                   'metal                                ', & ! 24
671                                   'wood                                 ', & ! 25
672                                   'gravel                               ', & ! 26
673                                   'fine gravel                          ', & ! 27
674                                   'pebblestone                          ', & ! 28
675                                   'woodchips                            ', & ! 29
676                                   'tartan (sports)                      ', & ! 30
677                                   'artifical turf (sports)              ', & ! 31
678                                   'clay (sports)                        ', & ! 32
679                                   'building (dummy)                     '  & ! 33
680                                                         /)
681
682    REAL(wp), PARAMETER :: sigma_sb       = 5.67037321E-8_wp !< Stefan-Boltzmann constant
683
684    INTEGER(iwp) :: albedo_type  = 9999999, & !< Albedo surface type
685                    dots_rad     = 0          !< starting index for timeseries output
686
687    LOGICAL ::  unscheduled_radiation_calls = .TRUE., & !< flag parameter indicating whether additional calls of the radiation code are allowed
688                constant_albedo = .FALSE.,            & !< flag parameter indicating whether the albedo may change depending on zenith
689                force_radiation_call = .FALSE.,       & !< flag parameter for unscheduled radiation calls
690                lw_radiation = .TRUE.,                & !< flag parameter indicating whether longwave radiation shall be calculated
691                radiation = .FALSE.,                  & !< flag parameter indicating whether the radiation model is used
692                sun_up    = .TRUE.,                   & !< flag parameter indicating whether the sun is up or down
693                sw_radiation = .TRUE.,                & !< flag parameter indicating whether shortwave radiation shall be calculated
694                sun_direction = .FALSE.,              & !< flag parameter indicating whether solar direction shall be calculated
695                average_radiation = .FALSE.,          & !< flag to set the calculation of radiation averaging for the domain
696                radiation_interactions = .FALSE.,     & !< flag to activiate RTM (TRUE only if vertical urban/land surface and trees exist)
697                surface_reflections = .TRUE.,         & !< flag to switch the calculation of radiation interaction between surfaces.
698                                                        !< When it switched off, only the effect of buildings and trees shadow
699                                                        !< will be considered. However fewer SVFs are expected.
700                radiation_interactions_on = .TRUE.      !< namelist flag to force RTM activiation regardless to vertical urban/land surface and trees
701
702    REAL(wp) :: albedo = 9999999.9_wp,           & !< NAMELIST alpha
703                albedo_lw_dif = 9999999.9_wp,    & !< NAMELIST aldif
704                albedo_lw_dir = 9999999.9_wp,    & !< NAMELIST aldir
705                albedo_sw_dif = 9999999.9_wp,    & !< NAMELIST asdif
706                albedo_sw_dir = 9999999.9_wp,    & !< NAMELIST asdir
707                decl_1,                          & !< declination coef. 1
708                decl_2,                          & !< declination coef. 2
709                decl_3,                          & !< declination coef. 3
710                dt_radiation = 0.0_wp,           & !< radiation model timestep
711                emissivity = 9999999.9_wp,       & !< NAMELIST surface emissivity
712                lon = 0.0_wp,                    & !< longitude in radians
713                lat = 0.0_wp,                    & !< latitude in radians
714                net_radiation = 0.0_wp,          & !< net radiation at surface
715                skip_time_do_radiation = 0.0_wp, & !< Radiation model is not called before this time
716                sky_trans,                       & !< sky transmissivity
717                time_radiation = 0.0_wp            !< time since last call of radiation code
718
719
720    REAL(wp), DIMENSION(0:0) ::  zenith,         & !< cosine of solar zenith angle
721                                 sun_dir_lat,    & !< solar directional vector in latitudes
722                                 sun_dir_lon       !< solar directional vector in longitudes
723
724    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_net_av       !< average of net radiation (rad_net) at surface
725    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_lw_in_xy_av  !< average of incoming longwave radiation at surface
726    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_lw_out_xy_av !< average of outgoing longwave radiation at surface
727    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_sw_in_xy_av  !< average of incoming shortwave radiation at surface
728    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_sw_out_xy_av !< average of outgoing shortwave radiation at surface
729!
730!-- Land surface albedos for solar zenith angle of 60degree after Briegleb (1992)     
731!-- (shortwave, longwave, broadband):   sw,      lw,      bb,
732    REAL(wp), DIMENSION(0:2,1:33), PARAMETER :: albedo_pars = RESHAPE( (/& 
733                                   0.06_wp, 0.06_wp, 0.06_wp,            & !  1
734                                   0.09_wp, 0.28_wp, 0.19_wp,            & !  2
735                                   0.11_wp, 0.33_wp, 0.23_wp,            & !  3
736                                   0.11_wp, 0.33_wp, 0.23_wp,            & !  4
737                                   0.14_wp, 0.34_wp, 0.25_wp,            & !  5
738                                   0.06_wp, 0.22_wp, 0.14_wp,            & !  6
739                                   0.06_wp, 0.27_wp, 0.17_wp,            & !  7
740                                   0.06_wp, 0.31_wp, 0.19_wp,            & !  8
741                                   0.06_wp, 0.22_wp, 0.14_wp,            & !  9
742                                   0.06_wp, 0.28_wp, 0.18_wp,            & ! 10
743                                   0.35_wp, 0.51_wp, 0.43_wp,            & ! 11
744                                   0.24_wp, 0.40_wp, 0.32_wp,            & ! 12
745                                   0.10_wp, 0.27_wp, 0.19_wp,            & ! 13
746                                   0.90_wp, 0.65_wp, 0.77_wp,            & ! 14
747                                   0.90_wp, 0.65_wp, 0.77_wp,            & ! 15
748                                   0.95_wp, 0.70_wp, 0.82_wp,            & ! 16
749                                   0.08_wp, 0.08_wp, 0.08_wp,            & ! 17
750                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 18
751                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 19
752                                   0.30_wp, 0.30_wp, 0.30_wp,            & ! 20
753                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 21
754                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 22
755                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 23
756                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 24
757                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 25
758                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 26
759                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 27
760                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 28
761                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 29
762                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 30
763                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 31
764                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 32
765                                   0.17_wp, 0.17_wp, 0.17_wp             & ! 33
766                                 /), (/ 3, 33 /) )
767
768    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE, TARGET :: &
769                        rad_lw_cs_hr,                  & !< longwave clear sky radiation heating rate (K/s)
770                        rad_lw_cs_hr_av,               & !< average of rad_lw_cs_hr
771                        rad_lw_hr,                     & !< longwave radiation heating rate (K/s)
772                        rad_lw_hr_av,                  & !< average of rad_sw_hr
773                        rad_lw_in,                     & !< incoming longwave radiation (W/m2)
774                        rad_lw_in_av,                  & !< average of rad_lw_in
775                        rad_lw_out,                    & !< outgoing longwave radiation (W/m2)
776                        rad_lw_out_av,                 & !< average of rad_lw_out
777                        rad_sw_cs_hr,                  & !< shortwave clear sky radiation heating rate (K/s)
778                        rad_sw_cs_hr_av,               & !< average of rad_sw_cs_hr
779                        rad_sw_hr,                     & !< shortwave radiation heating rate (K/s)
780                        rad_sw_hr_av,                  & !< average of rad_sw_hr
781                        rad_sw_in,                     & !< incoming shortwave radiation (W/m2)
782                        rad_sw_in_av,                  & !< average of rad_sw_in
783                        rad_sw_out,                    & !< outgoing shortwave radiation (W/m2)
784                        rad_sw_out_av                    !< average of rad_sw_out
785
786
787!
788!-- Variables and parameters used in RRTMG only
789#if defined ( __rrtmg )
790    CHARACTER(LEN=12) :: rrtm_input_file = "RAD_SND_DATA" !< name of the NetCDF input file (sounding data)
791
792
793!
794!-- Flag parameters for RRTMGS (should not be changed)
795    INTEGER(iwp), PARAMETER :: rrtm_idrv     = 1, & !< flag for longwave upward flux calculation option (0,1)
796                               rrtm_inflglw  = 2, & !< flag for lw cloud optical properties (0,1,2)
797                               rrtm_iceflglw = 0, & !< flag for lw ice particle specifications (0,1,2,3)
798                               rrtm_liqflglw = 1, & !< flag for lw liquid droplet specifications
799                               rrtm_inflgsw  = 2, & !< flag for sw cloud optical properties (0,1,2)
800                               rrtm_iceflgsw = 0, & !< flag for sw ice particle specifications (0,1,2,3)
801                               rrtm_liqflgsw = 1    !< flag for sw liquid droplet specifications
802
803!
804!-- The following variables should be only changed with care, as this will
805!-- require further setting of some variables, which is currently not
806!-- implemented (aerosols, ice phase).
807    INTEGER(iwp) :: nzt_rad,           & !< upper vertical limit for radiation calculations
808                    rrtm_icld = 0,     & !< cloud flag (0: clear sky column, 1: cloudy column)
809                    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)
810
811    INTEGER(iwp) :: nc_stat !< local variable for storin the result of netCDF calls for error message handling
812
813    LOGICAL :: snd_exists = .FALSE.      !< flag parameter to check whether a user-defined input files exists
814    LOGICAL :: sw_exists = .FALSE.       !< flag parameter to check whether that required rrtmg sw file exists
815    LOGICAL :: lw_exists = .FALSE.       !< flag parameter to check whether that required rrtmg lw file exists
816
817
818    REAL(wp), PARAMETER :: mol_mass_air_d_wv = 1.607793_wp !< molecular weight dry air / water vapor
819
820    REAL(wp), DIMENSION(:), ALLOCATABLE :: hyp_snd,     & !< hypostatic pressure from sounding data (hPa)
821                                           rrtm_tsfc,   & !< dummy array for storing surface temperature
822                                           t_snd          !< actual temperature from sounding data (hPa)
823
824    REAL(wp), DIMENSION(:,:), ALLOCATABLE :: rrtm_ccl4vmr,   & !< CCL4 volume mixing ratio (g/mol)
825                                             rrtm_cfc11vmr,  & !< CFC11 volume mixing ratio (g/mol)
826                                             rrtm_cfc12vmr,  & !< CFC12 volume mixing ratio (g/mol)
827                                             rrtm_cfc22vmr,  & !< CFC22 volume mixing ratio (g/mol)
828                                             rrtm_ch4vmr,    & !< CH4 volume mixing ratio
829                                             rrtm_cicewp,    & !< in-cloud ice water path (g/m2)
830                                             rrtm_cldfr,     & !< cloud fraction (0,1)
831                                             rrtm_cliqwp,    & !< in-cloud liquid water path (g/m2)
832                                             rrtm_co2vmr,    & !< CO2 volume mixing ratio (g/mol)
833                                             rrtm_emis,      & !< surface emissivity (0-1) 
834                                             rrtm_h2ovmr,    & !< H2O volume mixing ratio
835                                             rrtm_n2ovmr,    & !< N2O volume mixing ratio
836                                             rrtm_o2vmr,     & !< O2 volume mixing ratio
837                                             rrtm_o3vmr,     & !< O3 volume mixing ratio
838                                             rrtm_play,      & !< pressure layers (hPa, zu-grid)
839                                             rrtm_plev,      & !< pressure layers (hPa, zw-grid)
840                                             rrtm_reice,     & !< cloud ice effective radius (microns)
841                                             rrtm_reliq,     & !< cloud water drop effective radius (microns)
842                                             rrtm_tlay,      & !< actual temperature (K, zu-grid)
843                                             rrtm_tlev,      & !< actual temperature (K, zw-grid)
844                                             rrtm_lwdflx,    & !< RRTM output of incoming longwave radiation flux (W/m2)
845                                             rrtm_lwdflxc,   & !< RRTM output of outgoing clear sky longwave radiation flux (W/m2)
846                                             rrtm_lwuflx,    & !< RRTM output of outgoing longwave radiation flux (W/m2)
847                                             rrtm_lwuflxc,   & !< RRTM output of incoming clear sky longwave radiation flux (W/m2)
848                                             rrtm_lwuflx_dt, & !< RRTM output of incoming clear sky longwave radiation flux (W/m2)
849                                             rrtm_lwuflxc_dt,& !< RRTM output of outgoing clear sky longwave radiation flux (W/m2)
850                                             rrtm_lwhr,      & !< RRTM output of longwave radiation heating rate (K/d)
851                                             rrtm_lwhrc,     & !< RRTM output of incoming longwave clear sky radiation heating rate (K/d)
852                                             rrtm_swdflx,    & !< RRTM output of incoming shortwave radiation flux (W/m2)
853                                             rrtm_swdflxc,   & !< RRTM output of outgoing clear sky shortwave radiation flux (W/m2)
854                                             rrtm_swuflx,    & !< RRTM output of outgoing shortwave radiation flux (W/m2)
855                                             rrtm_swuflxc,   & !< RRTM output of incoming clear sky shortwave radiation flux (W/m2)
856                                             rrtm_swhr,      & !< RRTM output of shortwave radiation heating rate (K/d)
857                                             rrtm_swhrc,     & !< RRTM output of incoming shortwave clear sky radiation heating rate (K/d)
858                                             rrtm_dirdflux,  & !< RRTM output of incoming direct shortwave (W/m2)
859                                             rrtm_difdflux     !< RRTM output of incoming diffuse shortwave (W/m2)
860
861    REAL(wp), DIMENSION(1) ::                rrtm_aldif,     & !< surface albedo for longwave diffuse radiation
862                                             rrtm_aldir,     & !< surface albedo for longwave direct radiation
863                                             rrtm_asdif,     & !< surface albedo for shortwave diffuse radiation
864                                             rrtm_asdir        !< surface albedo for shortwave direct radiation
865
866!
867!-- Definition of arrays that are currently not used for calling RRTMG (due to setting of flag parameters)
868    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::  rad_lw_cs_in,   & !< incoming clear sky longwave radiation (W/m2) (not used)
869                                                rad_lw_cs_out,  & !< outgoing clear sky longwave radiation (W/m2) (not used)
870                                                rad_sw_cs_in,   & !< incoming clear sky shortwave radiation (W/m2) (not used)
871                                                rad_sw_cs_out,  & !< outgoing clear sky shortwave radiation (W/m2) (not used)
872                                                rrtm_lw_tauaer, & !< lw aerosol optical depth
873                                                rrtm_lw_taucld, & !< lw in-cloud optical depth
874                                                rrtm_sw_taucld, & !< sw in-cloud optical depth
875                                                rrtm_sw_ssacld, & !< sw in-cloud single scattering albedo
876                                                rrtm_sw_asmcld, & !< sw in-cloud asymmetry parameter
877                                                rrtm_sw_fsfcld, & !< sw in-cloud forward scattering fraction
878                                                rrtm_sw_tauaer, & !< sw aerosol optical depth
879                                                rrtm_sw_ssaaer, & !< sw aerosol single scattering albedo
880                                                rrtm_sw_asmaer, & !< sw aerosol asymmetry parameter
881                                                rrtm_sw_ecaer     !< sw aerosol optical detph at 0.55 microns (rrtm_iaer = 6 only)
882
883#endif
884!
885!-- Parameters of urban and land surface models
886    INTEGER(iwp)                                   ::  nzu                                !< number of layers of urban surface (will be calculated)
887    INTEGER(iwp)                                   ::  nzp                                !< number of layers of plant canopy (will be calculated)
888    INTEGER(iwp)                                   ::  nzub,nzut                          !< bottom and top layer of urban surface (will be calculated)
889    INTEGER(iwp)                                   ::  nzpt                               !< top layer of plant canopy (will be calculated)
890!-- parameters of urban and land surface models
891    INTEGER(iwp), PARAMETER                        ::  nzut_free = 3                      !< number of free layers above top of of topography
892    INTEGER(iwp), PARAMETER                        ::  ndsvf = 2                          !< number of dimensions of real values in SVF
893    INTEGER(iwp), PARAMETER                        ::  idsvf = 2                          !< number of dimensions of integer values in SVF
894    INTEGER(iwp), PARAMETER                        ::  ndcsf = 1                          !< number of dimensions of real values in CSF
895    INTEGER(iwp), PARAMETER                        ::  idcsf = 2                          !< number of dimensions of integer values in CSF
896    INTEGER(iwp), PARAMETER                        ::  kdcsf = 4                          !< number of dimensions of integer values in CSF calculation array
897    INTEGER(iwp), PARAMETER                        ::  id = 1                             !< position of d-index in surfl and surf
898    INTEGER(iwp), PARAMETER                        ::  iz = 2                             !< position of k-index in surfl and surf
899    INTEGER(iwp), PARAMETER                        ::  iy = 3                             !< position of j-index in surfl and surf
900    INTEGER(iwp), PARAMETER                        ::  ix = 4                             !< position of i-index in surfl and surf
901
902    INTEGER(iwp), PARAMETER                        ::  nsurf_type = 10                    !< number of surf types incl. phys.(land+urban) & (atm.,sky,boundary) surfaces - 1
903
904    INTEGER(iwp), PARAMETER                        ::  iup_u    = 0                       !< 0 - index of urban upward surface (ground or roof)
905    INTEGER(iwp), PARAMETER                        ::  idown_u  = 1                       !< 1 - index of urban downward surface (overhanging)
906    INTEGER(iwp), PARAMETER                        ::  inorth_u = 2                       !< 2 - index of urban northward facing wall
907    INTEGER(iwp), PARAMETER                        ::  isouth_u = 3                       !< 3 - index of urban southward facing wall
908    INTEGER(iwp), PARAMETER                        ::  ieast_u  = 4                       !< 4 - index of urban eastward facing wall
909    INTEGER(iwp), PARAMETER                        ::  iwest_u  = 5                       !< 5 - index of urban westward facing wall
910
911    INTEGER(iwp), PARAMETER                        ::  iup_l    = 6                       !< 6 - index of land upward surface (ground or roof)
912    INTEGER(iwp), PARAMETER                        ::  inorth_l = 7                       !< 7 - index of land northward facing wall
913    INTEGER(iwp), PARAMETER                        ::  isouth_l = 8                       !< 8 - index of land southward facing wall
914    INTEGER(iwp), PARAMETER                        ::  ieast_l  = 9                       !< 9 - index of land eastward facing wall
915    INTEGER(iwp), PARAMETER                        ::  iwest_l  = 10                      !< 10- index of land westward facing wall
916
917    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  idir = (/0, 0,0, 0,1,-1,0,0, 0,1,-1/)   !< surface normal direction x indices
918    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  jdir = (/0, 0,1,-1,0, 0,0,1,-1,0, 0/)   !< surface normal direction y indices
919    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  kdir = (/1,-1,0, 0,0, 0,1,0, 0,0, 0/)   !< surface normal direction z indices
920    REAL(wp),     DIMENSION(0:nsurf_type)          :: facearea                            !< area of single face in respective
921                                                                                          !< direction (will be calc'd)
922
923
924!-- indices and sizes of urban and land surface models
925    INTEGER(iwp)                                   ::  startland        !< start index of block of land and roof surfaces
926    INTEGER(iwp)                                   ::  endland          !< end index of block of land and roof surfaces
927    INTEGER(iwp)                                   ::  nlands           !< number of land and roof surfaces in local processor
928    INTEGER(iwp)                                   ::  startwall        !< start index of block of wall surfaces
929    INTEGER(iwp)                                   ::  endwall          !< end index of block of wall surfaces
930    INTEGER(iwp)                                   ::  nwalls           !< number of wall surfaces in local processor
931
932!-- indices needed for RTM netcdf output subroutines
933    INTEGER(iwp), PARAMETER                        :: nd = 5
934    CHARACTER(LEN=6), DIMENSION(0:nd-1), PARAMETER :: dirname = (/ '_roof ', '_south', '_north', '_west ', '_east ' /)
935    INTEGER(iwp), DIMENSION(0:nd-1), PARAMETER     :: dirint_u = (/ iup_u, isouth_u, inorth_u, iwest_u, ieast_u /)
936    INTEGER(iwp), DIMENSION(0:nd-1), PARAMETER     :: dirint_l = (/ iup_l, isouth_l, inorth_l, iwest_l, ieast_l /)
937    INTEGER(iwp), DIMENSION(0:nd-1)                :: dirstart
938    INTEGER(iwp), DIMENSION(0:nd-1)                :: dirend
939
940!-- indices and sizes of urban and land surface models
941    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surfl_l          !< coordinates of i-th local surface in local grid - surfl[:,k] = [d, z, y, x]
942    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surf_l           !< coordinates of i-th surface in grid - surf[:,k] = [d, z, y, x]
943    INTEGER(iwp), DIMENSION(:,:), POINTER          ::  surfl            !< coordinates of i-th local surface in local grid - surfl[:,k] = [d, z, y, x]
944    INTEGER(iwp), DIMENSION(:,:), POINTER          ::  surf             !< coordinates of i-th surface in grid - surf[:,k] = [d, z, y, x]
945    INTEGER(iwp)                                   ::  nsurfl           !< number of all surfaces in local processor
946    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  nsurfs           !< array of number of all surfaces in individual processors
947    INTEGER(iwp)                                   ::  nsurf            !< global number of surfaces in index array of surfaces (nsurf = proc nsurfs)
948    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surfstart        !< starts of blocks of surfaces for individual processors in array surf (indexed from 1)
949                                                                        !< respective block for particular processor is surfstart[iproc+1]+1 : surfstart[iproc+1]+nsurfs[iproc+1]
950
951!-- block variables needed for calculation of the plant canopy model inside the urban surface model
952    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pct              !< top layer of the plant canopy
953    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pch              !< heights of the plant canopy
954    INTEGER(iwp)                                   ::  npcbl = 0        !< number of the plant canopy gridboxes in local processor
955    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pcbl             !< k,j,i coordinates of l-th local plant canopy box pcbl[:,l] = [k, j, i]
956    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinsw          !< array of absorbed sw radiation for local plant canopy box
957    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdir       !< array of absorbed direct sw radiation for local plant canopy box
958    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdif       !< array of absorbed diffusion sw radiation for local plant canopy box
959    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinlw          !< array of absorbed lw radiation for local plant canopy box
960
961!-- configuration parameters (they can be setup in PALM config)
962    LOGICAL                                        ::  raytrace_mpi_rma = .TRUE.          !< use MPI RMA to access LAD and gridsurf from remote processes during raytracing
963    LOGICAL                                        ::  rad_angular_discretization = .TRUE.!< whether to use fixed resolution discretization of view factors for
964                                                                                          !< reflected radiation (as opposed to all mutually visible pairs)
965    LOGICAL                                        ::  plant_lw_interact = .TRUE.         !< whether plant canopy interacts with LW radiation (in addition to SW)
966    INTEGER(iwp)                                   ::  mrt_nlevels = 0                    !< number of vertical boxes above surface for which to calculate MRT
967    LOGICAL                                        ::  mrt_skip_roof = .TRUE.             !< do not calculate MRT above roof surfaces
968    LOGICAL                                        ::  mrt_include_sw = .TRUE.            !< should MRT calculation include SW radiation as well?
969    LOGICAL                                        ::  mrt_geom_human = .TRUE.            !< MRT direction weights simulate human body instead of a sphere
970    INTEGER(iwp)                                   ::  nrefsteps = 3                      !< number of reflection steps to perform
971    REAL(wp), PARAMETER                            ::  ext_coef = 0.6_wp                  !< extinction coefficient (a.k.a. alpha)
972    INTEGER(iwp), PARAMETER                        ::  rad_version_len = 10               !< length of identification string of rad version
973    CHARACTER(rad_version_len), PARAMETER          ::  rad_version = 'RAD v. 3.0'         !< identification of version of binary svf and restart files
974    INTEGER(iwp)                                   ::  raytrace_discrete_elevs = 40       !< number of discretization steps for elevation (nadir to zenith)
975    INTEGER(iwp)                                   ::  raytrace_discrete_azims = 80       !< number of discretization steps for azimuth (out of 360 degrees)
976    REAL(wp)                                       ::  max_raytracing_dist = -999.0_wp    !< maximum distance for raytracing (in metres)
977    REAL(wp)                                       ::  min_irrf_value = 1e-6_wp           !< minimum potential irradiance factor value for raytracing
978    REAL(wp), DIMENSION(1:30)                      ::  svfnorm_report_thresh = 1e21_wp    !< thresholds of SVF normalization values to report
979    INTEGER(iwp)                                   ::  svfnorm_report_num                 !< number of SVF normalization thresholds to report
980
981!-- radiation related arrays to be used in radiation_interaction routine
982    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_sw_in_dir    !< direct sw radiation
983    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_sw_in_diff   !< diffusion sw radiation
984    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_lw_in_diff   !< diffusion lw radiation
985
986!-- parameters required for RRTMG lower boundary condition
987    REAL(wp)                   :: albedo_urb      !< albedo value retuned to RRTMG boundary cond.
988    REAL(wp)                   :: emissivity_urb  !< emissivity value retuned to RRTMG boundary cond.
989    REAL(wp)                   :: t_rad_urb       !< temperature value retuned to RRTMG boundary cond.
990
991!-- type for calculation of svf
992    TYPE t_svf
993        INTEGER(iwp)                               :: isurflt           !<
994        INTEGER(iwp)                               :: isurfs            !<
995        REAL(wp)                                   :: rsvf              !<
996        REAL(wp)                                   :: rtransp           !<
997    END TYPE
998
999!-- type for calculation of csf
1000    TYPE t_csf
1001        INTEGER(iwp)                               :: ip                !<
1002        INTEGER(iwp)                               :: itx               !<
1003        INTEGER(iwp)                               :: ity               !<
1004        INTEGER(iwp)                               :: itz               !<
1005        INTEGER(iwp)                               :: isurfs            !< Idx of source face / -1 for sky
1006        REAL(wp)                                   :: rcvf              !< Canopy view factor for faces /
1007                                                                        !< canopy sink factor for sky (-1)
1008    END TYPE
1009
1010!-- arrays storing the values of USM
1011    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  svfsurf          !< svfsurf[:,isvf] = index of target and source surface for svf[isvf]
1012    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  svf              !< array of shape view factors+direct irradiation factors for local surfaces
1013    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfins          !< array of sw radiation falling to local surface after i-th reflection
1014    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinl          !< array of lw radiation for local surface after i-th reflection
1015
1016    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  skyvf            !< array of sky view factor for each local surface
1017    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  skyvft           !< array of sky view factor including transparency for each local surface
1018    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsitrans         !< dsidir[isvfl,i] = path transmittance of i-th
1019                                                                        !< direction of direct solar irradiance per target surface
1020    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsitransc        !< dtto per plant canopy box
1021    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsidir           !< dsidir[:,i] = unit vector of i-th
1022                                                                        !< direction of direct solar irradiance
1023    INTEGER(iwp)                                   ::  ndsidir          !< number of apparent solar directions used
1024    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  dsidir_rev       !< dsidir_rev[ielev,iazim] = i for dsidir or -1 if not present
1025
1026    INTEGER(iwp)                                   ::  nmrtbl           !< No. of local grid boxes for which MRT is calculated
1027    INTEGER(iwp)                                   ::  nmrtf            !< number of MRT factors for local processor
1028    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  mrtbl            !< coordinates of i-th local MRT box - surfl[:,i] = [z, y, x]
1029    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  mrtfsurf         !< mrtfsurf[:,imrtf] = index of target MRT box and source surface for mrtf[imrtf]
1030    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtf             !< array of MRT factors for each local MRT box
1031    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtft            !< array of MRT factors including transparency for each local MRT box
1032    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtsky           !< array of sky view factor for each local MRT box
1033    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtskyt          !< array of sky view factor including transparency for each local MRT box
1034    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  mrtdsit          !< array of direct solar transparencies for each local MRT box
1035    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinsw          !< mean SW radiant flux for each MRT box
1036    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinlw          !< mean LW radiant flux for each MRT box
1037    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrt              !< mean radiant temperature for each MRT box
1038    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinsw_av       !< time average mean SW radiant flux for each MRT box
1039    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinlw_av       !< time average mean LW radiant flux for each MRT box
1040    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrt_av           !< time average mean radiant temperature for each MRT box
1041
1042    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinsw         !< array of sw radiation falling to local surface including radiation from reflections
1043    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlw         !< array of lw radiation falling to local surface including radiation from reflections
1044    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdir      !< array of direct sw radiation falling to local surface
1045    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdif      !< array of diffuse sw radiation from sky and model boundary falling to local surface
1046    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwdif      !< array of diffuse lw radiation from sky and model boundary falling to local surface
1047   
1048                                                                        !< Outward radiation is only valid for nonvirtual surfaces
1049    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsl        !< array of reflected sw radiation for local surface in i-th reflection
1050    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutll        !< array of reflected + emitted lw radiation for local surface in i-th reflection
1051    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfouts         !< array of reflected sw radiation for all surfaces in i-th reflection
1052    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutl         !< array of reflected + emitted lw radiation for all surfaces in i-th reflection
1053    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlg         !< global array of incoming lw radiation from plant canopy
1054    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsw        !< array of total sw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1055    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutlw        !< array of total lw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1056    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfemitlwl      !< array of emitted lw radiation for local surface used to calculate effective surface temperature for radiation model
1057
1058!-- block variables needed for calculation of the plant canopy model inside the urban surface model
1059    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  csfsurf          !< csfsurf[:,icsf] = index of target surface and csf grid index for csf[icsf]
1060    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  csf              !< array of plant canopy sink fators + direct irradiation factors (transparency)
1061    REAL(wp), DIMENSION(:,:,:), POINTER            ::  sub_lad          !< subset of lad_s within urban surface, transformed to plain Z coordinate
1062    REAL(wp), DIMENSION(:), POINTER                ::  sub_lad_g        !< sub_lad globalized (used to avoid MPI RMA calls in raytracing)
1063    REAL(wp)                                       ::  prototype_lad    !< prototype leaf area density for computing effective optical depth
1064    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  nzterr, plantt   !< temporary global arrays for raytracing
1065    INTEGER(iwp)                                   ::  plantt_max
1066
1067!-- arrays and variables for calculation of svf and csf
1068    TYPE(t_svf), DIMENSION(:), POINTER             ::  asvf             !< pointer to growing svc array
1069    TYPE(t_csf), DIMENSION(:), POINTER             ::  acsf             !< pointer to growing csf array
1070    TYPE(t_svf), DIMENSION(:), POINTER             ::  amrtf            !< pointer to growing mrtf array
1071    TYPE(t_svf), DIMENSION(:), ALLOCATABLE, TARGET ::  asvf1, asvf2     !< realizations of svf array
1072    TYPE(t_csf), DIMENSION(:), ALLOCATABLE, TARGET ::  acsf1, acsf2     !< realizations of csf array
1073    TYPE(t_svf), DIMENSION(:), ALLOCATABLE, TARGET ::  amrtf1, amrtf2   !< realizations of mftf array
1074    INTEGER(iwp)                                   ::  nsvfla           !< dimmension of array allocated for storage of svf in local processor
1075    INTEGER(iwp)                                   ::  ncsfla           !< dimmension of array allocated for storage of csf in local processor
1076    INTEGER(iwp)                                   ::  nmrtfa           !< dimmension of array allocated for storage of mrt
1077    INTEGER(iwp)                                   ::  msvf, mcsf, mmrtf!< mod for swapping the growing array
1078    INTEGER(iwp), PARAMETER                        ::  gasize = 100000  !< initial size of growing arrays
1079    REAL(wp), PARAMETER                            ::  grow_factor = 1.4_wp !< growth factor of growing arrays
1080    INTEGER(iwp)                                   ::  nsvfl            !< number of svf for local processor
1081    INTEGER(iwp)                                   ::  ncsfl            !< no. of csf in local processor
1082                                                                        !< needed only during calc_svf but must be here because it is
1083                                                                        !< shared between subroutines calc_svf and raytrace
1084    INTEGER(iwp), DIMENSION(:,:,:,:), POINTER      ::  gridsurf         !< reverse index of local surfl[d,k,j,i] (for case rad_angular_discretization)
1085    INTEGER(iwp), DIMENSION(:,:,:), ALLOCATABLE    ::  gridpcbl         !< reverse index of local pcbl[k,j,i]
1086    INTEGER(iwp), PARAMETER                        ::  nsurf_type_u = 6 !< number of urban surf types (used in gridsurf)
1087
1088!-- temporary arrays for calculation of csf in raytracing
1089    INTEGER(iwp)                                   ::  maxboxesg        !< max number of boxes ray can cross in the domain
1090    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  boxes            !< coordinates of gridboxes being crossed by ray
1091    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  crlens           !< array of crossing lengths of ray for particular grid boxes
1092    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  lad_ip           !< array of numbers of process where lad is stored
1093#if defined( __parallel )
1094    INTEGER(kind=MPI_ADDRESS_KIND), &
1095                  DIMENSION(:), ALLOCATABLE        ::  lad_disp         !< array of displaycements of lad in local array of proc lad_ip
1096    INTEGER(iwp)                                   ::  win_lad          !< MPI RMA window for leaf area density
1097    INTEGER(iwp)                                   ::  win_gridsurf     !< MPI RMA window for reverse grid surface index
1098#endif
1099    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  lad_s_ray        !< array of received lad_s for appropriate gridboxes crossed by ray
1100    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  target_surfl
1101    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  rt2_track
1102    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rt2_track_lad
1103    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  rt2_track_dist
1104    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  rt2_dist
1105
1106!-- arrays for time averages
1107    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfradnet_av    !< average of net radiation to local surface including radiation from reflections
1108    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinsw_av      !< average of sw radiation falling to local surface including radiation from reflections
1109    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlw_av      !< average of lw radiation falling to local surface including radiation from reflections
1110    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdir_av   !< average of direct sw radiation falling to local surface
1111    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdif_av   !< average of diffuse sw radiation from sky and model boundary falling to local surface
1112    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwdif_av   !< average of diffuse lw radiation from sky and model boundary falling to local surface
1113    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswref_av   !< average of sw radiation falling to surface from reflections
1114    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwref_av   !< average of lw radiation falling to surface from reflections
1115    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsw_av     !< average of total sw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1116    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutlw_av     !< average of total lw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1117    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfins_av       !< average of array of residua of sw radiation absorbed in surface after last reflection
1118    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinl_av       !< average of array of residua of lw radiation absorbed in surface after last reflection
1119    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinlw_av       !< Average of pcbinlw
1120    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinsw_av       !< Average of pcbinsw
1121    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdir_av    !< Average of pcbinswdir
1122    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdif_av    !< Average of pcbinswdif
1123    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswref_av    !< Average of pcbinswref
1124
1125
1126!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1127!-- Energy balance variables
1128!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1129!-- parameters of the land, roof and wall surfaces
1130    REAL(wp), DIMENSION(:), ALLOCATABLE            :: albedo_surf        !< albedo of the surface
1131    REAL(wp), DIMENSION(:), ALLOCATABLE            :: emiss_surf         !< emissivity of the wall surface
1132
1133
1134    INTERFACE radiation_check_data_output
1135       MODULE PROCEDURE radiation_check_data_output
1136    END INTERFACE radiation_check_data_output
1137
1138    INTERFACE radiation_check_data_output_ts
1139       MODULE PROCEDURE radiation_check_data_output_ts
1140    END INTERFACE radiation_check_data_output_ts
1141
1142    INTERFACE radiation_check_data_output_pr
1143       MODULE PROCEDURE radiation_check_data_output_pr
1144    END INTERFACE radiation_check_data_output_pr
1145 
1146    INTERFACE radiation_check_parameters
1147       MODULE PROCEDURE radiation_check_parameters
1148    END INTERFACE radiation_check_parameters
1149 
1150    INTERFACE radiation_clearsky
1151       MODULE PROCEDURE radiation_clearsky
1152    END INTERFACE radiation_clearsky
1153 
1154    INTERFACE radiation_constant
1155       MODULE PROCEDURE radiation_constant
1156    END INTERFACE radiation_constant
1157 
1158    INTERFACE radiation_control
1159       MODULE PROCEDURE radiation_control
1160    END INTERFACE radiation_control
1161
1162    INTERFACE radiation_3d_data_averaging
1163       MODULE PROCEDURE radiation_3d_data_averaging
1164    END INTERFACE radiation_3d_data_averaging
1165
1166    INTERFACE radiation_data_output_2d
1167       MODULE PROCEDURE radiation_data_output_2d
1168    END INTERFACE radiation_data_output_2d
1169
1170    INTERFACE radiation_data_output_3d
1171       MODULE PROCEDURE radiation_data_output_3d
1172    END INTERFACE radiation_data_output_3d
1173
1174    INTERFACE radiation_data_output_mask
1175       MODULE PROCEDURE radiation_data_output_mask
1176    END INTERFACE radiation_data_output_mask
1177
1178    INTERFACE radiation_define_netcdf_grid
1179       MODULE PROCEDURE radiation_define_netcdf_grid
1180    END INTERFACE radiation_define_netcdf_grid
1181
1182    INTERFACE radiation_header
1183       MODULE PROCEDURE radiation_header
1184    END INTERFACE radiation_header 
1185 
1186    INTERFACE radiation_init
1187       MODULE PROCEDURE radiation_init
1188    END INTERFACE radiation_init
1189
1190    INTERFACE radiation_parin
1191       MODULE PROCEDURE radiation_parin
1192    END INTERFACE radiation_parin
1193   
1194    INTERFACE radiation_rrtmg
1195       MODULE PROCEDURE radiation_rrtmg
1196    END INTERFACE radiation_rrtmg
1197
1198    INTERFACE radiation_tendency
1199       MODULE PROCEDURE radiation_tendency
1200       MODULE PROCEDURE radiation_tendency_ij
1201    END INTERFACE radiation_tendency
1202
1203    INTERFACE radiation_rrd_local
1204       MODULE PROCEDURE radiation_rrd_local
1205    END INTERFACE radiation_rrd_local
1206
1207    INTERFACE radiation_wrd_local
1208       MODULE PROCEDURE radiation_wrd_local
1209    END INTERFACE radiation_wrd_local
1210
1211    INTERFACE radiation_interaction
1212       MODULE PROCEDURE radiation_interaction
1213    END INTERFACE radiation_interaction
1214
1215    INTERFACE radiation_interaction_init
1216       MODULE PROCEDURE radiation_interaction_init
1217    END INTERFACE radiation_interaction_init
1218 
1219    INTERFACE radiation_presimulate_solar_pos
1220       MODULE PROCEDURE radiation_presimulate_solar_pos
1221    END INTERFACE radiation_presimulate_solar_pos
1222
1223    INTERFACE radiation_radflux_gridbox
1224       MODULE PROCEDURE radiation_radflux_gridbox
1225    END INTERFACE radiation_radflux_gridbox
1226
1227    INTERFACE radiation_calc_svf
1228       MODULE PROCEDURE radiation_calc_svf
1229    END INTERFACE radiation_calc_svf
1230
1231    INTERFACE radiation_write_svf
1232       MODULE PROCEDURE radiation_write_svf
1233    END INTERFACE radiation_write_svf
1234
1235    INTERFACE radiation_read_svf
1236       MODULE PROCEDURE radiation_read_svf
1237    END INTERFACE radiation_read_svf
1238
1239
1240    SAVE
1241
1242    PRIVATE
1243
1244!
1245!-- Public functions / NEEDS SORTING
1246    PUBLIC radiation_check_data_output, radiation_check_data_output_pr,        &
1247           radiation_check_data_output_ts,                                     &
1248           radiation_check_parameters, radiation_control,                      &
1249           radiation_header, radiation_init, radiation_parin,                  &
1250           radiation_3d_data_averaging, radiation_tendency,                    &
1251           radiation_data_output_2d, radiation_data_output_3d,                 &
1252           radiation_define_netcdf_grid, radiation_wrd_local,                  &
1253           radiation_rrd_local, radiation_data_output_mask,                    &
1254           radiation_radflux_gridbox, radiation_calc_svf, radiation_write_svf, &
1255           radiation_interaction, radiation_interaction_init,                  &
1256           radiation_read_svf, radiation_presimulate_solar_pos
1257           
1258
1259   
1260!
1261!-- Public variables and constants / NEEDS SORTING
1262    PUBLIC albedo, albedo_type, decl_1, decl_2, decl_3, dots_rad, dt_radiation,&
1263           emissivity, force_radiation_call, lat, lon, mrt_geom_human,         &
1264           mrt_include_sw, mrt_nlevels, mrtbl, mrtinsw, mrtinlw, nmrtbl,       &
1265           rad_net_av, radiation, radiation_scheme, rad_lw_in,                 &
1266           rad_lw_in_av, rad_lw_out, rad_lw_out_av,                            &
1267           rad_lw_cs_hr, rad_lw_cs_hr_av, rad_lw_hr, rad_lw_hr_av, rad_sw_in,  &
1268           rad_sw_in_av, rad_sw_out, rad_sw_out_av, rad_sw_cs_hr,              &
1269           rad_sw_cs_hr_av, rad_sw_hr, rad_sw_hr_av, sigma_sb, solar_constant, &
1270           skip_time_do_radiation, time_radiation, unscheduled_radiation_calls,&
1271           zenith, calc_zenith, sun_direction, sun_dir_lat, sun_dir_lon,       &
1272           idir, jdir, kdir, id, iz, iy, ix,                                   &
1273           iup_u, inorth_u, isouth_u, ieast_u, iwest_u,                        &
1274           iup_l, inorth_l, isouth_l, ieast_l, iwest_l,                        &
1275           nsurf_type, nzub, nzut, nzu, pch, nsurf,                            &
1276           idsvf, ndsvf, idcsf, ndcsf, kdcsf, pct,                             &
1277           radiation_interactions, startwall, startland, endland, endwall,     &
1278           skyvf, skyvft, radiation_interactions_on, average_radiation,        &
1279           rad_sw_in_diff, rad_sw_in_dir
1280
1281
1282#if defined ( __rrtmg )
1283    PUBLIC rrtm_aldif, rrtm_aldir, rrtm_asdif, rrtm_asdir
1284#endif
1285
1286 CONTAINS
1287
1288
1289!------------------------------------------------------------------------------!
1290! Description:
1291! ------------
1292!> This subroutine controls the calls of the radiation schemes
1293!------------------------------------------------------------------------------!
1294    SUBROUTINE radiation_control
1295 
1296 
1297       IMPLICIT NONE
1298
1299
1300       SELECT CASE ( TRIM( radiation_scheme ) )
1301
1302          CASE ( 'constant' )
1303             CALL radiation_constant
1304         
1305          CASE ( 'clear-sky' ) 
1306             CALL radiation_clearsky
1307       
1308          CASE ( 'rrtmg' )
1309             CALL radiation_rrtmg
1310
1311          CASE DEFAULT
1312
1313       END SELECT
1314
1315
1316    END SUBROUTINE radiation_control
1317
1318!------------------------------------------------------------------------------!
1319! Description:
1320! ------------
1321!> Check data output for radiation model
1322!------------------------------------------------------------------------------!
1323    SUBROUTINE radiation_check_data_output( variable, unit, i, ilen, k )
1324 
1325 
1326       USE control_parameters,                                                 &
1327           ONLY: data_output, message_string
1328
1329       IMPLICIT NONE
1330
1331       CHARACTER (LEN=*) ::  unit          !<
1332       CHARACTER (LEN=*) ::  variable      !<
1333
1334       INTEGER(iwp) :: i, j, k, l
1335       INTEGER(iwp) :: ilen
1336       CHARACTER(LEN=varnamelength) :: var          !< TRIM(variable)
1337
1338       var = TRIM(variable)
1339
1340!--    first process diractional variables
1341       IF ( var(1:12) == 'rtm_rad_net_'  .OR.  var(1:13) == 'rtm_rad_insw_'  .OR.        &
1342            var(1:13) == 'rtm_rad_inlw_'  .OR.  var(1:16) == 'rtm_rad_inswdir_'  .OR.    &
1343            var(1:16) == 'rtm_rad_inswdif_'  .OR.  var(1:16) == 'rtm_rad_inswref_'  .OR. &
1344            var(1:16) == 'rtm_rad_inlwdif_'  .OR.  var(1:16) == 'rtm_rad_inlwref_'  .OR. &
1345            var(1:14) == 'rtm_rad_outsw_'  .OR.  var(1:14) == 'rtm_rad_outlw_'  .OR.     &
1346            var(1:14) == 'rtm_rad_ressw_'  .OR.  var(1:14) == 'rtm_rad_reslw_'  ) THEN
1347          IF ( .NOT.  radiation ) THEN
1348                message_string = 'output of "' // TRIM( var ) // '" require'&
1349                                 // 's radiation = .TRUE.'
1350                CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1351          ENDIF
1352          unit = 'W/m2'
1353       ELSE IF ( var(1:7) == 'rtm_svf'  .OR.  var(1:7) == 'rtm_dif'  .OR.                &
1354                 var(1:9) == 'rtm_skyvf' .OR. var(1:9) == 'rtm_skyvft' )  THEN
1355          IF ( .NOT.  radiation ) THEN
1356                message_string = 'output of "' // TRIM( var ) // '" require'&
1357                                 // 's radiation = .TRUE.'
1358                CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1359          ENDIF
1360          unit = '1'
1361       ELSE
1362!--       non-directional variables
1363          SELECT CASE ( TRIM( var ) )
1364             CASE ( 'rad_lw_cs_hr', 'rad_lw_hr', 'rad_lw_in', 'rad_lw_out', &
1365                    'rad_sw_cs_hr', 'rad_sw_hr', 'rad_sw_in', 'rad_sw_out'  )
1366                IF (  .NOT.  radiation  .OR.  radiation_scheme /= 'rrtmg' )  THEN
1367                   message_string = '"output of "' // TRIM( var ) // '" requi' // &
1368                                    'res radiation = .TRUE. and ' //              &
1369                                    'radiation_scheme = "rrtmg"'
1370                   CALL message( 'check_parameters', 'PA0406', 1, 2, 0, 6, 0 )
1371                ENDIF
1372                unit = 'K/h'
1373
1374             CASE ( 'rad_net*', 'rrtm_aldif*', 'rrtm_aldir*', 'rrtm_asdif*',      &
1375                    'rrtm_asdir*', 'rad_lw_in*', 'rad_lw_out*', 'rad_sw_in*',     &
1376                    'rad_sw_out*')
1377                IF ( i == 0 .AND. ilen == 0 .AND. k == 0)  THEN
1378                   ! Workaround for masked output (calls with i=ilen=k=0)
1379                   unit = 'illegal'
1380                   RETURN
1381                ENDIF
1382                IF ( k == 0  .OR.  data_output(i)(ilen-2:ilen) /= '_xy' )  THEN
1383                   message_string = 'illegal value for data_output: "' //         &
1384                                    TRIM( var ) // '" & only 2d-horizontal ' //   &
1385                                    'cross sections are allowed for this value'
1386                   CALL message( 'check_parameters', 'PA0111', 1, 2, 0, 6, 0 )
1387                ENDIF
1388                IF (  .NOT.  radiation  .OR.  radiation_scheme /= "rrtmg" )  THEN
1389                   IF ( TRIM( var ) == 'rrtm_aldif*'  .OR.                        &
1390                        TRIM( var ) == 'rrtm_aldir*'  .OR.                        &
1391                        TRIM( var ) == 'rrtm_asdif*'  .OR.                        &
1392                        TRIM( var ) == 'rrtm_asdir*'      )                       &
1393                   THEN
1394                      message_string = 'output of "' // TRIM( var ) // '" require'&
1395                                       // 's radiation = .TRUE. and radiation_sch'&
1396                                       // 'eme = "rrtmg"'
1397                      CALL message( 'check_parameters', 'PA0409', 1, 2, 0, 6, 0 )
1398                   ENDIF
1399                ENDIF
1400
1401                IF ( TRIM( var ) == 'rad_net*'      ) unit = 'W/m2'
1402                IF ( TRIM( var ) == 'rad_lw_in*'    ) unit = 'W/m2'
1403                IF ( TRIM( var ) == 'rad_lw_out*'   ) unit = 'W/m2'
1404                IF ( TRIM( var ) == 'rad_sw_in*'    ) unit = 'W/m2'
1405                IF ( TRIM( var ) == 'rad_sw_out*'   ) unit = 'W/m2'
1406                IF ( TRIM( var ) == 'rad_sw_in'     ) unit = 'W/m2'
1407                IF ( TRIM( var ) == 'rrtm_aldif*'   ) unit = ''
1408                IF ( TRIM( var ) == 'rrtm_aldir*'   ) unit = ''
1409                IF ( TRIM( var ) == 'rrtm_asdif*'   ) unit = ''
1410                IF ( TRIM( var ) == 'rrtm_asdir*'   ) unit = ''
1411
1412             CASE ( 'rtm_rad_pc_inlw', 'rtm_rad_pc_insw', 'rtm_rad_pc_inswdir', &
1413                    'rtm_rad_pc_inswdif', 'rtm_rad_pc_inswref')
1414                IF ( .NOT.  radiation ) THEN
1415                   message_string = 'output of "' // TRIM( var ) // '" require'&
1416                                    // 's radiation = .TRUE.'
1417                   CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1418                ENDIF
1419                unit = 'W'
1420
1421             CASE ( 'rtm_mrt', 'rtm_mrt_sw', 'rtm_mrt_lw'  )
1422                IF ( i == 0 .AND. ilen == 0 .AND. k == 0)  THEN
1423                   ! Workaround for masked output (calls with i=ilen=k=0)
1424                   unit = 'illegal'
1425                   RETURN
1426                ENDIF
1427
1428                IF ( .NOT.  radiation ) THEN
1429                   message_string = 'output of "' // TRIM( var ) // '" require'&
1430                                    // 's radiation = .TRUE.'
1431                   CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1432                ENDIF
1433                IF ( mrt_nlevels == 0 ) THEN
1434                   message_string = 'output of "' // TRIM( var ) // '" require'&
1435                                    // 's mrt_nlevels > 0'
1436                   CALL message( 'check_parameters', 'PA0510', 1, 2, 0, 6, 0 )
1437                ENDIF
1438                IF ( TRIM( var ) == 'rtm_mrt_sw'  .AND.  .NOT. mrt_include_sw ) THEN
1439                   message_string = 'output of "' // TRIM( var ) // '" require'&
1440                                    // 's rtm_mrt_sw = .TRUE.'
1441                   CALL message( 'check_parameters', 'PA0511', 1, 2, 0, 6, 0 )
1442                ENDIF
1443                IF ( TRIM( var ) == 'rtm_mrt' ) THEN
1444                   unit = 'K'
1445                ELSE
1446                   unit = 'W m-2'
1447                ENDIF
1448
1449             CASE DEFAULT
1450                unit = 'illegal'
1451
1452          END SELECT
1453       ENDIF
1454
1455    END SUBROUTINE radiation_check_data_output
1456
1457
1458!------------------------------------------------------------------------------!
1459! Description:
1460! ------------
1461!> Set module-specific timeseries units and labels
1462!------------------------------------------------------------------------------!
1463 SUBROUTINE radiation_check_data_output_ts( dots_max, dots_num, dots_label, dots_unit )
1464
1465
1466   INTEGER(iwp),      INTENT(IN)     ::  dots_max
1467   INTEGER(iwp),      INTENT(INOUT)  ::  dots_num
1468   CHARACTER (LEN=*), DIMENSION(dots_max), INTENT(INOUT)  :: dots_label
1469   CHARACTER (LEN=*), DIMENSION(dots_max), INTENT(INOUT)  :: dots_unit
1470
1471!
1472!-- Temporary solution to add LSM and radiation time series to the default
1473!-- output
1474    IF ( land_surface  .OR.  radiation )  THEN
1475       IF ( TRIM( radiation_scheme ) == 'rrtmg' )  THEN
1476          dots_num = dots_num + 15
1477       ELSE
1478          dots_num = dots_num + 11
1479       ENDIF
1480    ENDIF
1481
1482
1483 END SUBROUTINE radiation_check_data_output_ts
1484
1485!------------------------------------------------------------------------------!
1486! Description:
1487! ------------
1488!> Check data output of profiles for radiation model
1489!------------------------------------------------------------------------------! 
1490    SUBROUTINE radiation_check_data_output_pr( variable, var_count, unit,      &
1491               dopr_unit )
1492 
1493       USE arrays_3d,                                                          &
1494           ONLY: zu
1495
1496       USE control_parameters,                                                 &
1497           ONLY: data_output_pr, message_string
1498
1499       USE indices
1500
1501       USE profil_parameter
1502
1503       USE statistics
1504
1505       IMPLICIT NONE
1506   
1507       CHARACTER (LEN=*) ::  unit      !<
1508       CHARACTER (LEN=*) ::  variable  !<
1509       CHARACTER (LEN=*) ::  dopr_unit !< local value of dopr_unit
1510 
1511       INTEGER(iwp) ::  var_count     !<
1512
1513       SELECT CASE ( TRIM( variable ) )
1514       
1515         CASE ( 'rad_net' )
1516             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme == 'constant' )&
1517             THEN
1518                message_string = 'data_output_pr = ' //                        &
1519                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1520                                 'not available for radiation = .FALSE. or ' //&
1521                                 'radiation_scheme = "constant"'
1522                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1523             ELSE
1524                dopr_index(var_count) = 99
1525                dopr_unit  = 'W/m2'
1526                hom(:,2,99,:)  = SPREAD( zw, 2, statistic_regions+1 )
1527                unit = dopr_unit
1528             ENDIF
1529
1530          CASE ( 'rad_lw_in' )
1531             IF ( (  .NOT.  radiation)  .OR.  radiation_scheme == 'constant' ) &
1532             THEN
1533                message_string = 'data_output_pr = ' //                        &
1534                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1535                                 'not available for radiation = .FALSE. or ' //&
1536                                 'radiation_scheme = "constant"'
1537                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1538             ELSE
1539                dopr_index(var_count) = 100
1540                dopr_unit  = 'W/m2'
1541                hom(:,2,100,:)  = SPREAD( zw, 2, statistic_regions+1 )
1542                unit = dopr_unit 
1543             ENDIF
1544
1545          CASE ( 'rad_lw_out' )
1546             IF ( (  .NOT. radiation )  .OR.  radiation_scheme == 'constant' ) &
1547             THEN
1548                message_string = 'data_output_pr = ' //                        &
1549                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1550                                 'not available for radiation = .FALSE. or ' //&
1551                                 'radiation_scheme = "constant"'
1552                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1553             ELSE
1554                dopr_index(var_count) = 101
1555                dopr_unit  = 'W/m2'
1556                hom(:,2,101,:)  = SPREAD( zw, 2, statistic_regions+1 )
1557                unit = dopr_unit   
1558             ENDIF
1559
1560          CASE ( 'rad_sw_in' )
1561             IF ( (  .NOT. radiation )  .OR.  radiation_scheme == 'constant' ) &
1562             THEN
1563                message_string = 'data_output_pr = ' //                        &
1564                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1565                                 'not available for radiation = .FALSE. or ' //&
1566                                 'radiation_scheme = "constant"'
1567                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1568             ELSE
1569                dopr_index(var_count) = 102
1570                dopr_unit  = 'W/m2'
1571                hom(:,2,102,:)  = SPREAD( zw, 2, statistic_regions+1 )
1572                unit = dopr_unit
1573             ENDIF
1574
1575          CASE ( 'rad_sw_out')
1576             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme == 'constant' )&
1577             THEN
1578                message_string = 'data_output_pr = ' //                        &
1579                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1580                                 'not available for radiation = .FALSE. or ' //&
1581                                 'radiation_scheme = "constant"'
1582                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1583             ELSE
1584                dopr_index(var_count) = 103
1585                dopr_unit  = 'W/m2'
1586                hom(:,2,103,:)  = SPREAD( zw, 2, statistic_regions+1 )
1587                unit = dopr_unit
1588             ENDIF
1589
1590          CASE ( 'rad_lw_cs_hr' )
1591             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1592             THEN
1593                message_string = 'data_output_pr = ' //                        &
1594                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1595                                 'not available for radiation = .FALSE. or ' //&
1596                                 'radiation_scheme /= "rrtmg"'
1597                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1598             ELSE
1599                dopr_index(var_count) = 104
1600                dopr_unit  = 'K/h'
1601                hom(:,2,104,:)  = SPREAD( zu, 2, statistic_regions+1 )
1602                unit = dopr_unit
1603             ENDIF
1604
1605          CASE ( 'rad_lw_hr' )
1606             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1607             THEN
1608                message_string = 'data_output_pr = ' //                        &
1609                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1610                                 'not available for radiation = .FALSE. or ' //&
1611                                 'radiation_scheme /= "rrtmg"'
1612                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1613             ELSE
1614                dopr_index(var_count) = 105
1615                dopr_unit  = 'K/h'
1616                hom(:,2,105,:)  = SPREAD( zu, 2, statistic_regions+1 )
1617                unit = dopr_unit
1618             ENDIF
1619
1620          CASE ( 'rad_sw_cs_hr' )
1621             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1622             THEN
1623                message_string = 'data_output_pr = ' //                        &
1624                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1625                                 'not available for radiation = .FALSE. or ' //&
1626                                 'radiation_scheme /= "rrtmg"'
1627                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1628             ELSE
1629                dopr_index(var_count) = 106
1630                dopr_unit  = 'K/h'
1631                hom(:,2,106,:)  = SPREAD( zu, 2, statistic_regions+1 )
1632                unit = dopr_unit
1633             ENDIF
1634
1635          CASE ( 'rad_sw_hr' )
1636             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1637             THEN
1638                message_string = 'data_output_pr = ' //                        &
1639                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1640                                 'not available for radiation = .FALSE. or ' //&
1641                                 'radiation_scheme /= "rrtmg"'
1642                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1643             ELSE
1644                dopr_index(var_count) = 107
1645                dopr_unit  = 'K/h'
1646                hom(:,2,107,:)  = SPREAD( zu, 2, statistic_regions+1 )
1647                unit = dopr_unit
1648             ENDIF
1649
1650
1651          CASE DEFAULT
1652             unit = 'illegal'
1653
1654       END SELECT
1655
1656
1657    END SUBROUTINE radiation_check_data_output_pr
1658 
1659 
1660!------------------------------------------------------------------------------!
1661! Description:
1662! ------------
1663!> Check parameters routine for radiation model
1664!------------------------------------------------------------------------------!
1665    SUBROUTINE radiation_check_parameters
1666
1667       USE control_parameters,                                                 &
1668           ONLY: land_surface, message_string, urban_surface
1669
1670       USE netcdf_data_input_mod,                                              &
1671           ONLY:  input_pids_static                 
1672   
1673       IMPLICIT NONE
1674       
1675!
1676!--    In case no urban-surface or land-surface model is applied, usage of
1677!--    a radiation model make no sense.         
1678       IF ( .NOT. land_surface  .AND.  .NOT. urban_surface )  THEN
1679          message_string = 'Usage of radiation module is only allowed if ' //  &
1680                           'land-surface and/or urban-surface model is applied.'
1681          CALL message( 'check_parameters', 'PA0486', 1, 2, 0, 6, 0 )
1682       ENDIF
1683
1684       IF ( radiation_scheme /= 'constant'   .AND.                             &
1685            radiation_scheme /= 'clear-sky'  .AND.                             &
1686            radiation_scheme /= 'rrtmg' )  THEN
1687          message_string = 'unknown radiation_scheme = '//                     &
1688                           TRIM( radiation_scheme )
1689          CALL message( 'check_parameters', 'PA0405', 1, 2, 0, 6, 0 )
1690       ELSEIF ( radiation_scheme == 'rrtmg' )  THEN
1691#if ! defined ( __rrtmg )
1692          message_string = 'radiation_scheme = "rrtmg" requires ' //           & 
1693                           'compilation of PALM with pre-processor ' //        &
1694                           'directive -D__rrtmg'
1695          CALL message( 'check_parameters', 'PA0407', 1, 2, 0, 6, 0 )
1696#endif
1697#if defined ( __rrtmg ) && ! defined( __netcdf )
1698          message_string = 'radiation_scheme = "rrtmg" requires ' //           & 
1699                           'the use of NetCDF (preprocessor directive ' //     &
1700                           '-D__netcdf'
1701          CALL message( 'check_parameters', 'PA0412', 1, 2, 0, 6, 0 )
1702#endif
1703
1704       ENDIF
1705!
1706!--    Checks performed only if data is given via namelist only.
1707       IF ( .NOT. input_pids_static )  THEN
1708          IF ( albedo_type == 0  .AND.  albedo == 9999999.9_wp  .AND.          &
1709               radiation_scheme == 'clear-sky')  THEN
1710             message_string = 'radiation_scheme = "clear-sky" in combination'//& 
1711                              'with albedo_type = 0 requires setting of'//     &
1712                              'albedo /= 9999999.9'
1713             CALL message( 'check_parameters', 'PA0410', 1, 2, 0, 6, 0 )
1714          ENDIF
1715
1716          IF ( albedo_type == 0  .AND.  radiation_scheme == 'rrtmg'  .AND.     &
1717             ( albedo_lw_dif == 9999999.9_wp .OR. albedo_lw_dir == 9999999.9_wp&
1718          .OR. albedo_sw_dif == 9999999.9_wp .OR. albedo_sw_dir == 9999999.9_wp& 
1719             ) ) THEN
1720             message_string = 'radiation_scheme = "rrtmg" in combination' //   & 
1721                              'with albedo_type = 0 requires setting of ' //   &
1722                              'albedo_lw_dif /= 9999999.9' //                  &
1723                              'albedo_lw_dir /= 9999999.9' //                  &
1724                              'albedo_sw_dif /= 9999999.9 and' //              &
1725                              'albedo_sw_dir /= 9999999.9'
1726             CALL message( 'check_parameters', 'PA0411', 1, 2, 0, 6, 0 )
1727          ENDIF
1728       ENDIF
1729!
1730!--    Parallel rad_angular_discretization without raytrace_mpi_rma is not implemented
1731#if defined( __parallel )     
1732       IF ( rad_angular_discretization  .AND.  .NOT. raytrace_mpi_rma )  THEN
1733          message_string = 'rad_angular_discretization can only be used ' //  &
1734                           'together with raytrace_mpi_rma or when ' //  &
1735                           'no parallelization is applied.'
1736          CALL message( 'check_parameters', 'PA0486', 1, 2, 0, 6, 0 )
1737       ENDIF
1738#endif
1739
1740       IF ( cloud_droplets  .AND.   radiation_scheme == 'rrtmg'  .AND.         &
1741            average_radiation ) THEN
1742          message_string = 'average_radiation = .T. with radiation_scheme'//   & 
1743                           '= "rrtmg" in combination cloud_droplets = .T.'//   &
1744                           'is not implementd'
1745          CALL message( 'check_parameters', 'PA0560', 1, 2, 0, 6, 0 )
1746       ENDIF
1747
1748!
1749!--    Incialize svf normalization reporting histogram
1750       svfnorm_report_num = 1
1751       DO WHILE ( svfnorm_report_thresh(svfnorm_report_num) < 1e20_wp          &
1752                   .AND. svfnorm_report_num <= 30 )
1753          svfnorm_report_num = svfnorm_report_num + 1
1754       ENDDO
1755       svfnorm_report_num = svfnorm_report_num - 1
1756
1757
1758 
1759    END SUBROUTINE radiation_check_parameters 
1760 
1761 
1762!------------------------------------------------------------------------------!
1763! Description:
1764! ------------
1765!> Initialization of the radiation model
1766!------------------------------------------------------------------------------!
1767    SUBROUTINE radiation_init
1768   
1769       IMPLICIT NONE
1770
1771       INTEGER(iwp) ::  i         !< running index x-direction
1772       INTEGER(iwp) ::  ioff      !< offset in x between surface element reference grid point in atmosphere and actual surface
1773       INTEGER(iwp) ::  j         !< running index y-direction
1774       INTEGER(iwp) ::  joff      !< offset in y between surface element reference grid point in atmosphere and actual surface
1775       INTEGER(iwp) ::  l         !< running index for orientation of vertical surfaces
1776       INTEGER(iwp) ::  m         !< running index for surface elements
1777#if defined( __rrtmg )
1778       INTEGER(iwp) ::  ind_type  !< running index for subgrid-surface tiles
1779#endif
1780
1781!
1782!--    Activate radiation_interactions according to the existence of vertical surfaces and/or trees.
1783!--    The namelist parameter radiation_interactions_on can override this behavior.
1784!--    (This check cannot be performed in check_parameters, because vertical_surfaces_exist is first set in
1785!--    init_surface_arrays.)
1786       IF ( radiation_interactions_on )  THEN
1787          IF ( vertical_surfaces_exist  .OR.  plant_canopy )  THEN
1788             radiation_interactions    = .TRUE.
1789             average_radiation         = .TRUE.
1790          ELSE
1791             radiation_interactions_on = .FALSE.   !< reset namelist parameter: no interactions
1792                                                   !< calculations necessary in case of flat surface
1793          ENDIF
1794       ELSEIF ( vertical_surfaces_exist  .OR.  plant_canopy )  THEN
1795          message_string = 'radiation_interactions_on is set to .FALSE. although '     // &
1796                           'vertical surfaces and/or trees exist. The model will run ' // &
1797                           'without RTM (no shadows, no radiation reflections)'
1798          CALL message( 'init_3d_model', 'PA0348', 0, 1, 0, 6, 0 )
1799       ENDIF
1800!
1801!--    If required, initialize radiation interactions between surfaces
1802!--    via sky-view factors. This must be done before radiation is initialized.
1803       IF ( radiation_interactions )  CALL radiation_interaction_init
1804
1805!
1806!--    Initialize radiation model
1807       CALL location_message( 'initializing radiation model', .FALSE. )
1808
1809!
1810!--    Allocate array for storing the surface net radiation
1811       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_net )  .AND.                      &
1812                  surf_lsm_h%ns > 0  )   THEN
1813          ALLOCATE( surf_lsm_h%rad_net(1:surf_lsm_h%ns) )
1814          surf_lsm_h%rad_net = 0.0_wp 
1815       ENDIF
1816       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_net )  .AND.                      &
1817                  surf_usm_h%ns > 0  )  THEN
1818          ALLOCATE( surf_usm_h%rad_net(1:surf_usm_h%ns) )
1819          surf_usm_h%rad_net = 0.0_wp 
1820       ENDIF
1821       DO  l = 0, 3
1822          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_net )  .AND.                &
1823                     surf_lsm_v(l)%ns > 0  )  THEN
1824             ALLOCATE( surf_lsm_v(l)%rad_net(1:surf_lsm_v(l)%ns) )
1825             surf_lsm_v(l)%rad_net = 0.0_wp 
1826          ENDIF
1827          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_net )  .AND.                &
1828                     surf_usm_v(l)%ns > 0  )  THEN
1829             ALLOCATE( surf_usm_v(l)%rad_net(1:surf_usm_v(l)%ns) )
1830             surf_usm_v(l)%rad_net = 0.0_wp 
1831          ENDIF
1832       ENDDO
1833
1834
1835!
1836!--    Allocate array for storing the surface longwave (out) radiation change
1837       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_lw_out_change_0 )  .AND.          &
1838                  surf_lsm_h%ns > 0  )   THEN
1839          ALLOCATE( surf_lsm_h%rad_lw_out_change_0(1:surf_lsm_h%ns) )
1840          surf_lsm_h%rad_lw_out_change_0 = 0.0_wp 
1841       ENDIF
1842       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_lw_out_change_0 )  .AND.          &
1843                  surf_usm_h%ns > 0  )  THEN
1844          ALLOCATE( surf_usm_h%rad_lw_out_change_0(1:surf_usm_h%ns) )
1845          surf_usm_h%rad_lw_out_change_0 = 0.0_wp 
1846       ENDIF
1847       DO  l = 0, 3
1848          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_lw_out_change_0 )  .AND.    &
1849                     surf_lsm_v(l)%ns > 0  )  THEN
1850             ALLOCATE( surf_lsm_v(l)%rad_lw_out_change_0(1:surf_lsm_v(l)%ns) )
1851             surf_lsm_v(l)%rad_lw_out_change_0 = 0.0_wp 
1852          ENDIF
1853          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_lw_out_change_0 )  .AND.    &
1854                     surf_usm_v(l)%ns > 0  )  THEN
1855             ALLOCATE( surf_usm_v(l)%rad_lw_out_change_0(1:surf_usm_v(l)%ns) )
1856             surf_usm_v(l)%rad_lw_out_change_0 = 0.0_wp 
1857          ENDIF
1858       ENDDO
1859
1860!
1861!--    Allocate surface arrays for incoming/outgoing short/longwave radiation
1862       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_sw_in )  .AND.                    &
1863                  surf_lsm_h%ns > 0  )   THEN
1864          ALLOCATE( surf_lsm_h%rad_sw_in(1:surf_lsm_h%ns)  )
1865          ALLOCATE( surf_lsm_h%rad_sw_out(1:surf_lsm_h%ns) )
1866          ALLOCATE( surf_lsm_h%rad_sw_dir(1:surf_lsm_h%ns) )
1867          ALLOCATE( surf_lsm_h%rad_sw_dif(1:surf_lsm_h%ns) )
1868          ALLOCATE( surf_lsm_h%rad_sw_ref(1:surf_lsm_h%ns) )
1869          ALLOCATE( surf_lsm_h%rad_sw_res(1:surf_lsm_h%ns) )
1870          ALLOCATE( surf_lsm_h%rad_lw_in(1:surf_lsm_h%ns)  )
1871          ALLOCATE( surf_lsm_h%rad_lw_out(1:surf_lsm_h%ns) )
1872          ALLOCATE( surf_lsm_h%rad_lw_dif(1:surf_lsm_h%ns) )
1873          ALLOCATE( surf_lsm_h%rad_lw_ref(1:surf_lsm_h%ns) )
1874          ALLOCATE( surf_lsm_h%rad_lw_res(1:surf_lsm_h%ns) )
1875          surf_lsm_h%rad_sw_in  = 0.0_wp 
1876          surf_lsm_h%rad_sw_out = 0.0_wp 
1877          surf_lsm_h%rad_sw_dir = 0.0_wp 
1878          surf_lsm_h%rad_sw_dif = 0.0_wp 
1879          surf_lsm_h%rad_sw_ref = 0.0_wp 
1880          surf_lsm_h%rad_sw_res = 0.0_wp 
1881          surf_lsm_h%rad_lw_in  = 0.0_wp 
1882          surf_lsm_h%rad_lw_out = 0.0_wp 
1883          surf_lsm_h%rad_lw_dif = 0.0_wp 
1884          surf_lsm_h%rad_lw_ref = 0.0_wp 
1885          surf_lsm_h%rad_lw_res = 0.0_wp 
1886       ENDIF
1887       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_sw_in )  .AND.                    &
1888                  surf_usm_h%ns > 0  )  THEN
1889          ALLOCATE( surf_usm_h%rad_sw_in(1:surf_usm_h%ns)  )
1890          ALLOCATE( surf_usm_h%rad_sw_out(1:surf_usm_h%ns) )
1891          ALLOCATE( surf_usm_h%rad_sw_dir(1:surf_usm_h%ns) )
1892          ALLOCATE( surf_usm_h%rad_sw_dif(1:surf_usm_h%ns) )
1893          ALLOCATE( surf_usm_h%rad_sw_ref(1:surf_usm_h%ns) )
1894          ALLOCATE( surf_usm_h%rad_sw_res(1:surf_usm_h%ns) )
1895          ALLOCATE( surf_usm_h%rad_lw_in(1:surf_usm_h%ns)  )
1896          ALLOCATE( surf_usm_h%rad_lw_out(1:surf_usm_h%ns) )
1897          ALLOCATE( surf_usm_h%rad_lw_dif(1:surf_usm_h%ns) )
1898          ALLOCATE( surf_usm_h%rad_lw_ref(1:surf_usm_h%ns) )
1899          ALLOCATE( surf_usm_h%rad_lw_res(1:surf_usm_h%ns) )
1900          surf_usm_h%rad_sw_in  = 0.0_wp 
1901          surf_usm_h%rad_sw_out = 0.0_wp 
1902          surf_usm_h%rad_sw_dir = 0.0_wp 
1903          surf_usm_h%rad_sw_dif = 0.0_wp 
1904          surf_usm_h%rad_sw_ref = 0.0_wp 
1905          surf_usm_h%rad_sw_res = 0.0_wp 
1906          surf_usm_h%rad_lw_in  = 0.0_wp 
1907          surf_usm_h%rad_lw_out = 0.0_wp 
1908          surf_usm_h%rad_lw_dif = 0.0_wp 
1909          surf_usm_h%rad_lw_ref = 0.0_wp 
1910          surf_usm_h%rad_lw_res = 0.0_wp 
1911       ENDIF
1912       DO  l = 0, 3
1913          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_sw_in )  .AND.              &
1914                     surf_lsm_v(l)%ns > 0  )  THEN
1915             ALLOCATE( surf_lsm_v(l)%rad_sw_in(1:surf_lsm_v(l)%ns)  )
1916             ALLOCATE( surf_lsm_v(l)%rad_sw_out(1:surf_lsm_v(l)%ns) )
1917             ALLOCATE( surf_lsm_v(l)%rad_sw_dir(1:surf_lsm_v(l)%ns) )
1918             ALLOCATE( surf_lsm_v(l)%rad_sw_dif(1:surf_lsm_v(l)%ns) )
1919             ALLOCATE( surf_lsm_v(l)%rad_sw_ref(1:surf_lsm_v(l)%ns) )
1920             ALLOCATE( surf_lsm_v(l)%rad_sw_res(1:surf_lsm_v(l)%ns) )
1921
1922             ALLOCATE( surf_lsm_v(l)%rad_lw_in(1:surf_lsm_v(l)%ns)  )
1923             ALLOCATE( surf_lsm_v(l)%rad_lw_out(1:surf_lsm_v(l)%ns) )
1924             ALLOCATE( surf_lsm_v(l)%rad_lw_dif(1:surf_lsm_v(l)%ns) )
1925             ALLOCATE( surf_lsm_v(l)%rad_lw_ref(1:surf_lsm_v(l)%ns) )
1926             ALLOCATE( surf_lsm_v(l)%rad_lw_res(1:surf_lsm_v(l)%ns) )
1927
1928             surf_lsm_v(l)%rad_sw_in  = 0.0_wp 
1929             surf_lsm_v(l)%rad_sw_out = 0.0_wp
1930             surf_lsm_v(l)%rad_sw_dir = 0.0_wp
1931             surf_lsm_v(l)%rad_sw_dif = 0.0_wp
1932             surf_lsm_v(l)%rad_sw_ref = 0.0_wp
1933             surf_lsm_v(l)%rad_sw_res = 0.0_wp
1934
1935             surf_lsm_v(l)%rad_lw_in  = 0.0_wp 
1936             surf_lsm_v(l)%rad_lw_out = 0.0_wp 
1937             surf_lsm_v(l)%rad_lw_dif = 0.0_wp 
1938             surf_lsm_v(l)%rad_lw_ref = 0.0_wp 
1939             surf_lsm_v(l)%rad_lw_res = 0.0_wp 
1940          ENDIF
1941          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_sw_in )  .AND.              &
1942                     surf_usm_v(l)%ns > 0  )  THEN
1943             ALLOCATE( surf_usm_v(l)%rad_sw_in(1:surf_usm_v(l)%ns)  )
1944             ALLOCATE( surf_usm_v(l)%rad_sw_out(1:surf_usm_v(l)%ns) )
1945             ALLOCATE( surf_usm_v(l)%rad_sw_dir(1:surf_usm_v(l)%ns) )
1946             ALLOCATE( surf_usm_v(l)%rad_sw_dif(1:surf_usm_v(l)%ns) )
1947             ALLOCATE( surf_usm_v(l)%rad_sw_ref(1:surf_usm_v(l)%ns) )
1948             ALLOCATE( surf_usm_v(l)%rad_sw_res(1:surf_usm_v(l)%ns) )
1949             ALLOCATE( surf_usm_v(l)%rad_lw_in(1:surf_usm_v(l)%ns)  )
1950             ALLOCATE( surf_usm_v(l)%rad_lw_out(1:surf_usm_v(l)%ns) )
1951             ALLOCATE( surf_usm_v(l)%rad_lw_dif(1:surf_usm_v(l)%ns) )
1952             ALLOCATE( surf_usm_v(l)%rad_lw_ref(1:surf_usm_v(l)%ns) )
1953             ALLOCATE( surf_usm_v(l)%rad_lw_res(1:surf_usm_v(l)%ns) )
1954             surf_usm_v(l)%rad_sw_in  = 0.0_wp 
1955             surf_usm_v(l)%rad_sw_out = 0.0_wp
1956             surf_usm_v(l)%rad_sw_dir = 0.0_wp
1957             surf_usm_v(l)%rad_sw_dif = 0.0_wp
1958             surf_usm_v(l)%rad_sw_ref = 0.0_wp
1959             surf_usm_v(l)%rad_sw_res = 0.0_wp
1960             surf_usm_v(l)%rad_lw_in  = 0.0_wp 
1961             surf_usm_v(l)%rad_lw_out = 0.0_wp 
1962             surf_usm_v(l)%rad_lw_dif = 0.0_wp 
1963             surf_usm_v(l)%rad_lw_ref = 0.0_wp 
1964             surf_usm_v(l)%rad_lw_res = 0.0_wp 
1965          ENDIF
1966       ENDDO
1967!
1968!--    Fix net radiation in case of radiation_scheme = 'constant'
1969       IF ( radiation_scheme == 'constant' )  THEN
1970          IF ( ALLOCATED( surf_lsm_h%rad_net ) )                               &
1971             surf_lsm_h%rad_net    = net_radiation
1972          IF ( ALLOCATED( surf_usm_h%rad_net ) )                               &
1973             surf_usm_h%rad_net    = net_radiation
1974!
1975!--       Todo: weight with inclination angle
1976          DO  l = 0, 3
1977             IF ( ALLOCATED( surf_lsm_v(l)%rad_net ) )                         &
1978                surf_lsm_v(l)%rad_net = net_radiation
1979             IF ( ALLOCATED( surf_usm_v(l)%rad_net ) )                         &
1980                surf_usm_v(l)%rad_net = net_radiation
1981          ENDDO
1982!          radiation = .FALSE.
1983!
1984!--    Calculate orbital constants
1985       ELSE
1986          decl_1 = SIN(23.45_wp * pi / 180.0_wp)
1987          decl_2 = 2.0_wp * pi / 365.0_wp
1988          decl_3 = decl_2 * 81.0_wp
1989          lat    = latitude * pi / 180.0_wp
1990          lon    = longitude * pi / 180.0_wp
1991       ENDIF
1992
1993       IF ( radiation_scheme == 'clear-sky'  .OR.                              &
1994            radiation_scheme == 'constant')  THEN
1995
1996
1997!
1998!--       Allocate arrays for incoming/outgoing short/longwave radiation
1999          IF ( .NOT. ALLOCATED ( rad_sw_in ) )  THEN
2000             ALLOCATE ( rad_sw_in(0:0,nysg:nyng,nxlg:nxrg) )
2001          ENDIF
2002          IF ( .NOT. ALLOCATED ( rad_sw_out ) )  THEN
2003             ALLOCATE ( rad_sw_out(0:0,nysg:nyng,nxlg:nxrg) )
2004          ENDIF
2005
2006          IF ( .NOT. ALLOCATED ( rad_lw_in ) )  THEN
2007             ALLOCATE ( rad_lw_in(0:0,nysg:nyng,nxlg:nxrg) )
2008          ENDIF
2009          IF ( .NOT. ALLOCATED ( rad_lw_out ) )  THEN
2010             ALLOCATE ( rad_lw_out(0:0,nysg:nyng,nxlg:nxrg) )
2011          ENDIF
2012
2013!
2014!--       Allocate average arrays for incoming/outgoing short/longwave radiation
2015          IF ( .NOT. ALLOCATED ( rad_sw_in_av ) )  THEN
2016             ALLOCATE ( rad_sw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
2017          ENDIF
2018          IF ( .NOT. ALLOCATED ( rad_sw_out_av ) )  THEN
2019             ALLOCATE ( rad_sw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
2020          ENDIF
2021
2022          IF ( .NOT. ALLOCATED ( rad_lw_in_av ) )  THEN
2023             ALLOCATE ( rad_lw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
2024          ENDIF
2025          IF ( .NOT. ALLOCATED ( rad_lw_out_av ) )  THEN
2026             ALLOCATE ( rad_lw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
2027          ENDIF
2028!
2029!--       Allocate arrays for broadband albedo, and level 1 initialization
2030!--       via namelist paramter, unless not already allocated.
2031          IF ( .NOT. ALLOCATED(surf_lsm_h%albedo) )  THEN
2032             ALLOCATE( surf_lsm_h%albedo(0:2,1:surf_lsm_h%ns)     )
2033             surf_lsm_h%albedo    = albedo
2034          ENDIF
2035          IF ( .NOT. ALLOCATED(surf_usm_h%albedo) )  THEN
2036             ALLOCATE( surf_usm_h%albedo(0:2,1:surf_usm_h%ns)     )
2037             surf_usm_h%albedo    = albedo
2038          ENDIF
2039
2040          DO  l = 0, 3
2041             IF ( .NOT. ALLOCATED( surf_lsm_v(l)%albedo ) )  THEN
2042                ALLOCATE( surf_lsm_v(l)%albedo(0:2,1:surf_lsm_v(l)%ns) )
2043                surf_lsm_v(l)%albedo = albedo
2044             ENDIF
2045             IF ( .NOT. ALLOCATED( surf_usm_v(l)%albedo ) )  THEN
2046                ALLOCATE( surf_usm_v(l)%albedo(0:2,1:surf_usm_v(l)%ns) )
2047                surf_usm_v(l)%albedo = albedo
2048             ENDIF
2049          ENDDO
2050!
2051!--       Level 2 initialization of broadband albedo via given albedo_type.
2052!--       Only if albedo_type is non-zero. In case of urban surface and
2053!--       input data is read from ASCII file, albedo_type will be zero, so that
2054!--       albedo won't be overwritten.
2055          DO  m = 1, surf_lsm_h%ns
2056             IF ( surf_lsm_h%albedo_type(ind_veg_wall,m) /= 0 )                &
2057                surf_lsm_h%albedo(ind_veg_wall,m) =                            &
2058                           albedo_pars(2,surf_lsm_h%albedo_type(ind_veg_wall,m))
2059             IF ( surf_lsm_h%albedo_type(ind_pav_green,m) /= 0 )               &
2060                surf_lsm_h%albedo(ind_pav_green,m) =                           &
2061                           albedo_pars(2,surf_lsm_h%albedo_type(ind_pav_green,m))
2062             IF ( surf_lsm_h%albedo_type(ind_wat_win,m) /= 0 )                 &
2063                surf_lsm_h%albedo(ind_wat_win,m) =                             &
2064                           albedo_pars(2,surf_lsm_h%albedo_type(ind_wat_win,m))
2065          ENDDO
2066          DO  m = 1, surf_usm_h%ns
2067             IF ( surf_usm_h%albedo_type(ind_veg_wall,m) /= 0 )                &
2068                surf_usm_h%albedo(ind_veg_wall,m) =                            &
2069                           albedo_pars(2,surf_usm_h%albedo_type(ind_veg_wall,m))
2070             IF ( surf_usm_h%albedo_type(ind_pav_green,m) /= 0 )               &
2071                surf_usm_h%albedo(ind_pav_green,m) =                           &
2072                           albedo_pars(2,surf_usm_h%albedo_type(ind_pav_green,m))
2073             IF ( surf_usm_h%albedo_type(ind_wat_win,m) /= 0 )                 &
2074                surf_usm_h%albedo(ind_wat_win,m) =                             &
2075                           albedo_pars(2,surf_usm_h%albedo_type(ind_wat_win,m))
2076          ENDDO
2077
2078          DO  l = 0, 3
2079             DO  m = 1, surf_lsm_v(l)%ns
2080                IF ( surf_lsm_v(l)%albedo_type(ind_veg_wall,m) /= 0 )          &
2081                   surf_lsm_v(l)%albedo(ind_veg_wall,m) =                      &
2082                        albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_veg_wall,m))
2083                IF ( surf_lsm_v(l)%albedo_type(ind_pav_green,m) /= 0 )         &
2084                   surf_lsm_v(l)%albedo(ind_pav_green,m) =                     &
2085                        albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_pav_green,m))
2086                IF ( surf_lsm_v(l)%albedo_type(ind_wat_win,m) /= 0 )           &
2087                   surf_lsm_v(l)%albedo(ind_wat_win,m) =                       &
2088                        albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_wat_win,m))
2089             ENDDO
2090             DO  m = 1, surf_usm_v(l)%ns
2091                IF ( surf_usm_v(l)%albedo_type(ind_veg_wall,m) /= 0 )          &
2092                   surf_usm_v(l)%albedo(ind_veg_wall,m) =                      &
2093                        albedo_pars(2,surf_usm_v(l)%albedo_type(ind_veg_wall,m))
2094                IF ( surf_usm_v(l)%albedo_type(ind_pav_green,m) /= 0 )         &
2095                   surf_usm_v(l)%albedo(ind_pav_green,m) =                     &
2096                        albedo_pars(2,surf_usm_v(l)%albedo_type(ind_pav_green,m))
2097                IF ( surf_usm_v(l)%albedo_type(ind_wat_win,m) /= 0 )           &
2098                   surf_usm_v(l)%albedo(ind_wat_win,m) =                       &
2099                        albedo_pars(2,surf_usm_v(l)%albedo_type(ind_wat_win,m))
2100             ENDDO
2101          ENDDO
2102
2103!
2104!--       Level 3 initialization at grid points where albedo type is zero.
2105!--       This case, albedo is taken from file. In case of constant radiation
2106!--       or clear sky, only broadband albedo is given.
2107          IF ( albedo_pars_f%from_file )  THEN
2108!
2109!--          Horizontal surfaces
2110             DO  m = 1, surf_lsm_h%ns
2111                i = surf_lsm_h%i(m)
2112                j = surf_lsm_h%j(m)
2113                IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2114                   IF ( surf_lsm_h%albedo_type(ind_veg_wall,m) == 0 )          &
2115                      surf_lsm_h%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2116                   IF ( surf_lsm_h%albedo_type(ind_pav_green,m) == 0 )         &
2117                      surf_lsm_h%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2118                   IF ( surf_lsm_h%albedo_type(ind_wat_win,m) == 0 )           &
2119                      surf_lsm_h%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2120                ENDIF
2121             ENDDO
2122             DO  m = 1, surf_usm_h%ns
2123                i = surf_usm_h%i(m)
2124                j = surf_usm_h%j(m)
2125                IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2126                   IF ( surf_usm_h%albedo_type(ind_veg_wall,m) == 0 )          &
2127                      surf_usm_h%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2128                   IF ( surf_usm_h%albedo_type(ind_pav_green,m) == 0 )         &
2129                      surf_usm_h%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2130                   IF ( surf_usm_h%albedo_type(ind_wat_win,m) == 0 )           &
2131                      surf_usm_h%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2132                ENDIF
2133             ENDDO 
2134!
2135!--          Vertical surfaces           
2136             DO  l = 0, 3
2137
2138                ioff = surf_lsm_v(l)%ioff
2139                joff = surf_lsm_v(l)%joff
2140                DO  m = 1, surf_lsm_v(l)%ns
2141                   i = surf_lsm_v(l)%i(m) + ioff
2142                   j = surf_lsm_v(l)%j(m) + joff
2143                   IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2144                      IF ( surf_lsm_v(l)%albedo_type(ind_veg_wall,m) == 0 )    &
2145                         surf_lsm_v(l)%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2146                      IF ( surf_lsm_v(l)%albedo_type(ind_pav_green,m) == 0 )   &
2147                         surf_lsm_v(l)%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2148                      IF ( surf_lsm_v(l)%albedo_type(ind_wat_win,m) == 0 )     &
2149                         surf_lsm_v(l)%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2150                   ENDIF
2151                ENDDO
2152
2153                ioff = surf_usm_v(l)%ioff
2154                joff = surf_usm_v(l)%joff
2155                DO  m = 1, surf_usm_h%ns
2156                   i = surf_usm_h%i(m) + joff
2157                   j = surf_usm_h%j(m) + joff
2158                   IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2159                      IF ( surf_usm_v(l)%albedo_type(ind_veg_wall,m) == 0 )    &
2160                         surf_usm_v(l)%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2161                      IF ( surf_usm_v(l)%albedo_type(ind_pav_green,m) == 0 )   &
2162                         surf_usm_v(l)%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2163                      IF ( surf_usm_v(l)%albedo_type(ind_wat_win,m) == 0 )     &
2164                         surf_lsm_v(l)%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2165                   ENDIF
2166                ENDDO
2167             ENDDO
2168
2169          ENDIF 
2170!
2171!--    Initialization actions for RRTMG
2172       ELSEIF ( radiation_scheme == 'rrtmg' )  THEN
2173#if defined ( __rrtmg )
2174!
2175!--       Allocate albedos for short/longwave radiation, horizontal surfaces
2176!--       for wall/green/window (USM) or vegetation/pavement/water surfaces
2177!--       (LSM).
2178          ALLOCATE ( surf_lsm_h%aldif(0:2,1:surf_lsm_h%ns)       )
2179          ALLOCATE ( surf_lsm_h%aldir(0:2,1:surf_lsm_h%ns)       )
2180          ALLOCATE ( surf_lsm_h%asdif(0:2,1:surf_lsm_h%ns)       )
2181          ALLOCATE ( surf_lsm_h%asdir(0:2,1:surf_lsm_h%ns)       )
2182          ALLOCATE ( surf_lsm_h%rrtm_aldif(0:2,1:surf_lsm_h%ns)  )
2183          ALLOCATE ( surf_lsm_h%rrtm_aldir(0:2,1:surf_lsm_h%ns)  )
2184          ALLOCATE ( surf_lsm_h%rrtm_asdif(0:2,1:surf_lsm_h%ns)  )
2185          ALLOCATE ( surf_lsm_h%rrtm_asdir(0:2,1:surf_lsm_h%ns)  )
2186
2187          ALLOCATE ( surf_usm_h%aldif(0:2,1:surf_usm_h%ns)       )
2188          ALLOCATE ( surf_usm_h%aldir(0:2,1:surf_usm_h%ns)       )
2189          ALLOCATE ( surf_usm_h%asdif(0:2,1:surf_usm_h%ns)       )
2190          ALLOCATE ( surf_usm_h%asdir(0:2,1:surf_usm_h%ns)       )
2191          ALLOCATE ( surf_usm_h%rrtm_aldif(0:2,1:surf_usm_h%ns)  )
2192          ALLOCATE ( surf_usm_h%rrtm_aldir(0:2,1:surf_usm_h%ns)  )
2193          ALLOCATE ( surf_usm_h%rrtm_asdif(0:2,1:surf_usm_h%ns)  )
2194          ALLOCATE ( surf_usm_h%rrtm_asdir(0:2,1:surf_usm_h%ns)  )
2195
2196!
2197!--       Allocate broadband albedo (temporary for the current radiation
2198!--       implementations)
2199          IF ( .NOT. ALLOCATED(surf_lsm_h%albedo) )                            &
2200             ALLOCATE( surf_lsm_h%albedo(0:2,1:surf_lsm_h%ns)     )
2201          IF ( .NOT. ALLOCATED(surf_usm_h%albedo) )                            &
2202             ALLOCATE( surf_usm_h%albedo(0:2,1:surf_usm_h%ns)     )
2203
2204!
2205!--       Allocate albedos for short/longwave radiation, vertical surfaces
2206          DO  l = 0, 3
2207
2208             ALLOCATE ( surf_lsm_v(l)%aldif(0:2,1:surf_lsm_v(l)%ns)      )
2209             ALLOCATE ( surf_lsm_v(l)%aldir(0:2,1:surf_lsm_v(l)%ns)      )
2210             ALLOCATE ( surf_lsm_v(l)%asdif(0:2,1:surf_lsm_v(l)%ns)      )
2211             ALLOCATE ( surf_lsm_v(l)%asdir(0:2,1:surf_lsm_v(l)%ns)      )
2212
2213             ALLOCATE ( surf_lsm_v(l)%rrtm_aldif(0:2,1:surf_lsm_v(l)%ns) )
2214             ALLOCATE ( surf_lsm_v(l)%rrtm_aldir(0:2,1:surf_lsm_v(l)%ns) )
2215             ALLOCATE ( surf_lsm_v(l)%rrtm_asdif(0:2,1:surf_lsm_v(l)%ns) )
2216             ALLOCATE ( surf_lsm_v(l)%rrtm_asdir(0:2,1:surf_lsm_v(l)%ns) )
2217
2218             ALLOCATE ( surf_usm_v(l)%aldif(0:2,1:surf_usm_v(l)%ns)      )
2219             ALLOCATE ( surf_usm_v(l)%aldir(0:2,1:surf_usm_v(l)%ns)      )
2220             ALLOCATE ( surf_usm_v(l)%asdif(0:2,1:surf_usm_v(l)%ns)      )
2221             ALLOCATE ( surf_usm_v(l)%asdir(0:2,1:surf_usm_v(l)%ns)      )
2222
2223             ALLOCATE ( surf_usm_v(l)%rrtm_aldif(0:2,1:surf_usm_v(l)%ns) )
2224             ALLOCATE ( surf_usm_v(l)%rrtm_aldir(0:2,1:surf_usm_v(l)%ns) )
2225             ALLOCATE ( surf_usm_v(l)%rrtm_asdif(0:2,1:surf_usm_v(l)%ns) )
2226             ALLOCATE ( surf_usm_v(l)%rrtm_asdir(0:2,1:surf_usm_v(l)%ns) )
2227!
2228!--          Allocate broadband albedo (temporary for the current radiation
2229!--          implementations)
2230             IF ( .NOT. ALLOCATED( surf_lsm_v(l)%albedo ) )                    &
2231                ALLOCATE( surf_lsm_v(l)%albedo(0:2,1:surf_lsm_v(l)%ns) )
2232             IF ( .NOT. ALLOCATED( surf_usm_v(l)%albedo ) )                    &
2233                ALLOCATE( surf_usm_v(l)%albedo(0:2,1:surf_usm_v(l)%ns) )
2234
2235          ENDDO
2236!
2237!--       Level 1 initialization of spectral albedos via namelist
2238!--       paramters. Please note, this case all surface tiles are initialized
2239!--       the same.
2240          IF ( surf_lsm_h%ns > 0 )  THEN
2241             surf_lsm_h%aldif  = albedo_lw_dif
2242             surf_lsm_h%aldir  = albedo_lw_dir
2243             surf_lsm_h%asdif  = albedo_sw_dif
2244             surf_lsm_h%asdir  = albedo_sw_dir
2245             surf_lsm_h%albedo = albedo_sw_dif
2246          ENDIF
2247          IF ( surf_usm_h%ns > 0 )  THEN
2248             IF ( surf_usm_h%albedo_from_ascii )  THEN
2249                surf_usm_h%aldif  = surf_usm_h%albedo
2250                surf_usm_h%aldir  = surf_usm_h%albedo
2251                surf_usm_h%asdif  = surf_usm_h%albedo
2252                surf_usm_h%asdir  = surf_usm_h%albedo
2253             ELSE
2254                surf_usm_h%aldif  = albedo_lw_dif
2255                surf_usm_h%aldir  = albedo_lw_dir
2256                surf_usm_h%asdif  = albedo_sw_dif
2257                surf_usm_h%asdir  = albedo_sw_dir
2258                surf_usm_h%albedo = albedo_sw_dif
2259             ENDIF
2260          ENDIF
2261
2262          DO  l = 0, 3
2263
2264             IF ( surf_lsm_v(l)%ns > 0 )  THEN
2265                surf_lsm_v(l)%aldif  = albedo_lw_dif
2266                surf_lsm_v(l)%aldir  = albedo_lw_dir
2267                surf_lsm_v(l)%asdif  = albedo_sw_dif
2268                surf_lsm_v(l)%asdir  = albedo_sw_dir
2269                surf_lsm_v(l)%albedo = albedo_sw_dif
2270             ENDIF
2271
2272             IF ( surf_usm_v(l)%ns > 0 )  THEN
2273                IF ( surf_usm_v(l)%albedo_from_ascii )  THEN
2274                   surf_usm_v(l)%aldif  = surf_usm_v(l)%albedo
2275                   surf_usm_v(l)%aldir  = surf_usm_v(l)%albedo
2276                   surf_usm_v(l)%asdif  = surf_usm_v(l)%albedo
2277                   surf_usm_v(l)%asdir  = surf_usm_v(l)%albedo
2278                ELSE
2279                   surf_usm_v(l)%aldif  = albedo_lw_dif
2280                   surf_usm_v(l)%aldir  = albedo_lw_dir
2281                   surf_usm_v(l)%asdif  = albedo_sw_dif
2282                   surf_usm_v(l)%asdir  = albedo_sw_dir
2283                ENDIF
2284             ENDIF
2285          ENDDO
2286
2287!
2288!--       Level 2 initialization of spectral albedos via albedo_type.
2289!--       Please note, for natural- and urban-type surfaces, a tile approach
2290!--       is applied so that the resulting albedo is calculated via the weighted
2291!--       average of respective surface fractions.
2292          DO  m = 1, surf_lsm_h%ns
2293!
2294!--          Spectral albedos for vegetation/pavement/water surfaces
2295             DO  ind_type = 0, 2
2296                IF ( surf_lsm_h%albedo_type(ind_type,m) /= 0 )  THEN
2297                   surf_lsm_h%aldif(ind_type,m) =                              &
2298                               albedo_pars(0,surf_lsm_h%albedo_type(ind_type,m))
2299                   surf_lsm_h%asdif(ind_type,m) =                              &
2300                               albedo_pars(1,surf_lsm_h%albedo_type(ind_type,m))
2301                   surf_lsm_h%aldir(ind_type,m) =                              &
2302                               albedo_pars(0,surf_lsm_h%albedo_type(ind_type,m))
2303                   surf_lsm_h%asdir(ind_type,m) =                              &
2304                               albedo_pars(1,surf_lsm_h%albedo_type(ind_type,m))
2305                   surf_lsm_h%albedo(ind_type,m) =                             &
2306                               albedo_pars(2,surf_lsm_h%albedo_type(ind_type,m))
2307                ENDIF
2308             ENDDO
2309
2310          ENDDO
2311!
2312!--       For urban surface only if albedo has not been already initialized
2313!--       in the urban-surface model via the ASCII file.
2314          IF ( .NOT. surf_usm_h%albedo_from_ascii )  THEN
2315             DO  m = 1, surf_usm_h%ns
2316!
2317!--             Spectral albedos for wall/green/window surfaces
2318                DO  ind_type = 0, 2
2319                   IF ( surf_usm_h%albedo_type(ind_type,m) /= 0 )  THEN
2320                      surf_usm_h%aldif(ind_type,m) =                           &
2321                               albedo_pars(0,surf_usm_h%albedo_type(ind_type,m))
2322                      surf_usm_h%asdif(ind_type,m) =                           &
2323                               albedo_pars(1,surf_usm_h%albedo_type(ind_type,m))
2324                      surf_usm_h%aldir(ind_type,m) =                           &
2325                               albedo_pars(0,surf_usm_h%albedo_type(ind_type,m))
2326                      surf_usm_h%asdir(ind_type,m) =                           &
2327                               albedo_pars(1,surf_usm_h%albedo_type(ind_type,m))
2328                      surf_usm_h%albedo(ind_type,m) =                          &
2329                               albedo_pars(2,surf_usm_h%albedo_type(ind_type,m))
2330                   ENDIF
2331                ENDDO
2332
2333             ENDDO
2334          ENDIF
2335
2336          DO l = 0, 3
2337
2338             DO  m = 1, surf_lsm_v(l)%ns
2339!
2340!--             Spectral albedos for vegetation/pavement/water surfaces
2341                DO  ind_type = 0, 2
2342                   IF ( surf_lsm_v(l)%albedo_type(ind_type,m) /= 0 )  THEN
2343                      surf_lsm_v(l)%aldif(ind_type,m) =                        &
2344                            albedo_pars(0,surf_lsm_v(l)%albedo_type(ind_type,m))
2345                      surf_lsm_v(l)%asdif(ind_type,m) =                        &
2346                            albedo_pars(1,surf_lsm_v(l)%albedo_type(ind_type,m))
2347                      surf_lsm_v(l)%aldir(ind_type,m) =                        &
2348                            albedo_pars(0,surf_lsm_v(l)%albedo_type(ind_type,m))
2349                      surf_lsm_v(l)%asdir(ind_type,m) =                        &
2350                            albedo_pars(1,surf_lsm_v(l)%albedo_type(ind_type,m))
2351                      surf_lsm_v(l)%albedo(ind_type,m) =                       &
2352                            albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_type,m))
2353                   ENDIF
2354                ENDDO
2355             ENDDO
2356!
2357!--          For urban surface only if albedo has not been already initialized
2358!--          in the urban-surface model via the ASCII file.
2359             IF ( .NOT. surf_usm_v(l)%albedo_from_ascii )  THEN
2360                DO  m = 1, surf_usm_v(l)%ns
2361!
2362!--                Spectral albedos for wall/green/window surfaces
2363                   DO  ind_type = 0, 2
2364                      IF ( surf_usm_v(l)%albedo_type(ind_type,m) /= 0 )  THEN
2365                         surf_usm_v(l)%aldif(ind_type,m) =                     &
2366                            albedo_pars(0,surf_usm_v(l)%albedo_type(ind_type,m))
2367                         surf_usm_v(l)%asdif(ind_type,m) =                     &
2368                            albedo_pars(1,surf_usm_v(l)%albedo_type(ind_type,m))
2369                         surf_usm_v(l)%aldir(ind_type,m) =                     &
2370                            albedo_pars(0,surf_usm_v(l)%albedo_type(ind_type,m))
2371                         surf_usm_v(l)%asdir(ind_type,m) =                     &
2372                            albedo_pars(1,surf_usm_v(l)%albedo_type(ind_type,m))
2373                         surf_usm_v(l)%albedo(ind_type,m) =                    &
2374                            albedo_pars(2,surf_usm_v(l)%albedo_type(ind_type,m))
2375                      ENDIF
2376                   ENDDO
2377
2378                ENDDO
2379             ENDIF
2380          ENDDO
2381!
2382!--       Level 3 initialization at grid points where albedo type is zero.
2383!--       This case, spectral albedos are taken from file if available
2384          IF ( albedo_pars_f%from_file )  THEN
2385!
2386!--          Horizontal
2387             DO  m = 1, surf_lsm_h%ns
2388                i = surf_lsm_h%i(m)
2389                j = surf_lsm_h%j(m)
2390!
2391!--             Spectral albedos for vegetation/pavement/water surfaces
2392                DO  ind_type = 0, 2
2393                   IF ( surf_lsm_h%albedo_type(ind_type,m) == 0 )  THEN
2394                      IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2395                         surf_lsm_h%albedo(ind_type,m) =                       &
2396                                                albedo_pars_f%pars_xy(1,j,i)
2397                      IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2398                         surf_lsm_h%aldir(ind_type,m) =                        &
2399                                                albedo_pars_f%pars_xy(1,j,i)
2400                      IF ( albedo_pars_f%pars_xy(2,j,i) /= albedo_pars_f%fill )&
2401                         surf_lsm_h%aldif(ind_type,m) =                        &
2402                                                albedo_pars_f%pars_xy(2,j,i)
2403                      IF ( albedo_pars_f%pars_xy(3,j,i) /= albedo_pars_f%fill )&
2404                         surf_lsm_h%asdir(ind_type,m) =                        &
2405                                                albedo_pars_f%pars_xy(3,j,i)
2406                      IF ( albedo_pars_f%pars_xy(4,j,i) /= albedo_pars_f%fill )&
2407                         surf_lsm_h%asdif(ind_type,m) =                        &
2408                                                albedo_pars_f%pars_xy(4,j,i)
2409                   ENDIF
2410                ENDDO
2411             ENDDO
2412!
2413!--          For urban surface only if albedo has not been already initialized
2414!--          in the urban-surface model via the ASCII file.
2415             IF ( .NOT. surf_usm_h%albedo_from_ascii )  THEN
2416                DO  m = 1, surf_usm_h%ns
2417                   i = surf_usm_h%i(m)
2418                   j = surf_usm_h%j(m)
2419!
2420!--                Spectral albedos for wall/green/window surfaces
2421                   DO  ind_type = 0, 2
2422                      IF ( surf_usm_h%albedo_type(ind_type,m) == 0 )  THEN
2423                         IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2424                            surf_usm_h%albedo(ind_type,m) =                       &
2425                                                albedo_pars_f%pars_xy(1,j,i)
2426                         IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2427                            surf_usm_h%aldir(ind_type,m) =                        &
2428                                                albedo_pars_f%pars_xy(1,j,i)
2429                         IF ( albedo_pars_f%pars_xy(2,j,i) /= albedo_pars_f%fill )&
2430                            surf_usm_h%aldif(ind_type,m) =                        &
2431                                                albedo_pars_f%pars_xy(2,j,i)
2432                         IF ( albedo_pars_f%pars_xy(3,j,i) /= albedo_pars_f%fill )&
2433                            surf_usm_h%asdir(ind_type,m) =                        &
2434                                                albedo_pars_f%pars_xy(3,j,i)
2435                         IF ( albedo_pars_f%pars_xy(4,j,i) /= albedo_pars_f%fill )&
2436                            surf_usm_h%asdif(ind_type,m) =                        &
2437                                                albedo_pars_f%pars_xy(4,j,i)
2438                      ENDIF
2439                   ENDDO
2440
2441                ENDDO
2442             ENDIF
2443!
2444!--          Vertical
2445             DO  l = 0, 3
2446                ioff = surf_lsm_v(l)%ioff
2447                joff = surf_lsm_v(l)%joff
2448
2449                DO  m = 1, surf_lsm_v(l)%ns
2450                   i = surf_lsm_v(l)%i(m)
2451                   j = surf_lsm_v(l)%j(m)
2452!
2453!--                Spectral albedos for vegetation/pavement/water surfaces
2454                   DO  ind_type = 0, 2
2455                      IF ( surf_lsm_v(l)%albedo_type(ind_type,m) == 0 )  THEN
2456                         IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2457                              albedo_pars_f%fill )                             &
2458                            surf_lsm_v(l)%albedo(ind_type,m) =                 &
2459                                          albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2460                         IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2461                              albedo_pars_f%fill )                             &
2462                            surf_lsm_v(l)%aldir(ind_type,m) =                  &
2463                                          albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2464                         IF ( albedo_pars_f%pars_xy(2,j+joff,i+ioff) /=        &
2465                              albedo_pars_f%fill )                             &
2466                            surf_lsm_v(l)%aldif(ind_type,m) =                  &
2467                                          albedo_pars_f%pars_xy(2,j+joff,i+ioff)
2468                         IF ( albedo_pars_f%pars_xy(3,j+joff,i+ioff) /=        &
2469                              albedo_pars_f%fill )                             &
2470                            surf_lsm_v(l)%asdir(ind_type,m) =                  &
2471                                          albedo_pars_f%pars_xy(3,j+joff,i+ioff)
2472                         IF ( albedo_pars_f%pars_xy(4,j+joff,i+ioff) /=        &
2473                              albedo_pars_f%fill )                             &
2474                            surf_lsm_v(l)%asdif(ind_type,m) =                  &
2475                                          albedo_pars_f%pars_xy(4,j+joff,i+ioff)
2476                      ENDIF
2477                   ENDDO
2478                ENDDO
2479!
2480!--             For urban surface only if albedo has not been already initialized
2481!--             in the urban-surface model via the ASCII file.
2482                IF ( .NOT. surf_usm_v(l)%albedo_from_ascii )  THEN
2483                   ioff = surf_usm_v(l)%ioff
2484                   joff = surf_usm_v(l)%joff
2485
2486                   DO  m = 1, surf_usm_v(l)%ns
2487                      i = surf_usm_v(l)%i(m)
2488                      j = surf_usm_v(l)%j(m)
2489!
2490!--                   Spectral albedos for wall/green/window surfaces
2491                      DO  ind_type = 0, 2
2492                         IF ( surf_usm_v(l)%albedo_type(ind_type,m) == 0 )  THEN
2493                            IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2494                                 albedo_pars_f%fill )                             &
2495                               surf_usm_v(l)%albedo(ind_type,m) =                 &
2496                                             albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2497                            IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2498                                 albedo_pars_f%fill )                             &
2499                               surf_usm_v(l)%aldir(ind_type,m) =                  &
2500                                             albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2501                            IF ( albedo_pars_f%pars_xy(2,j+joff,i+ioff) /=        &
2502                                 albedo_pars_f%fill )                             &
2503                               surf_usm_v(l)%aldif(ind_type,m) =                  &
2504                                             albedo_pars_f%pars_xy(2,j+joff,i+ioff)
2505                            IF ( albedo_pars_f%pars_xy(3,j+joff,i+ioff) /=        &
2506                                 albedo_pars_f%fill )                             &
2507                               surf_usm_v(l)%asdir(ind_type,m) =                  &
2508                                             albedo_pars_f%pars_xy(3,j+joff,i+ioff)
2509                            IF ( albedo_pars_f%pars_xy(4,j+joff,i+ioff) /=        &
2510                                 albedo_pars_f%fill )                             &
2511                               surf_usm_v(l)%asdif(ind_type,m) =                  &
2512                                             albedo_pars_f%pars_xy(4,j+joff,i+ioff)
2513                         ENDIF
2514                      ENDDO
2515
2516                   ENDDO
2517                ENDIF
2518             ENDDO
2519
2520          ENDIF
2521
2522!
2523!--       Calculate initial values of current (cosine of) the zenith angle and
2524!--       whether the sun is up
2525          CALL calc_zenith     
2526          ! readjust date and time to its initial value
2527          CALL init_date_and_time
2528!
2529!--       Calculate initial surface albedo for different surfaces
2530          IF ( .NOT. constant_albedo )  THEN
2531#if defined( __netcdf )
2532!
2533!--          Horizontally aligned natural and urban surfaces
2534             CALL calc_albedo( surf_lsm_h    )
2535             CALL calc_albedo( surf_usm_h    )
2536!
2537!--          Vertically aligned natural and urban surfaces
2538             DO  l = 0, 3
2539                CALL calc_albedo( surf_lsm_v(l) )
2540                CALL calc_albedo( surf_usm_v(l) )
2541             ENDDO
2542#endif
2543          ELSE
2544!
2545!--          Initialize sun-inclination independent spectral albedos
2546!--          Horizontal surfaces
2547             IF ( surf_lsm_h%ns > 0 )  THEN
2548                surf_lsm_h%rrtm_aldir = surf_lsm_h%aldir
2549                surf_lsm_h%rrtm_asdir = surf_lsm_h%asdir
2550                surf_lsm_h%rrtm_aldif = surf_lsm_h%aldif
2551                surf_lsm_h%rrtm_asdif = surf_lsm_h%asdif
2552             ENDIF
2553             IF ( surf_usm_h%ns > 0 )  THEN
2554                surf_usm_h%rrtm_aldir = surf_usm_h%aldir
2555                surf_usm_h%rrtm_asdir = surf_usm_h%asdir
2556                surf_usm_h%rrtm_aldif = surf_usm_h%aldif
2557                surf_usm_h%rrtm_asdif = surf_usm_h%asdif
2558             ENDIF
2559!
2560!--          Vertical surfaces
2561             DO  l = 0, 3
2562                IF ( surf_lsm_v(l)%ns > 0 )  THEN
2563                   surf_lsm_v(l)%rrtm_aldir = surf_lsm_v(l)%aldir
2564                   surf_lsm_v(l)%rrtm_asdir = surf_lsm_v(l)%asdir
2565                   surf_lsm_v(l)%rrtm_aldif = surf_lsm_v(l)%aldif
2566                   surf_lsm_v(l)%rrtm_asdif = surf_lsm_v(l)%asdif
2567                ENDIF
2568                IF ( surf_usm_v(l)%ns > 0 )  THEN
2569                   surf_usm_v(l)%rrtm_aldir = surf_usm_v(l)%aldir
2570                   surf_usm_v(l)%rrtm_asdir = surf_usm_v(l)%asdir
2571                   surf_usm_v(l)%rrtm_aldif = surf_usm_v(l)%aldif
2572                   surf_usm_v(l)%rrtm_asdif = surf_usm_v(l)%asdif
2573                ENDIF
2574             ENDDO
2575
2576          ENDIF
2577
2578!
2579!--       Allocate 3d arrays of radiative fluxes and heating rates
2580          IF ( .NOT. ALLOCATED ( rad_sw_in ) )  THEN
2581             ALLOCATE ( rad_sw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2582             rad_sw_in = 0.0_wp
2583          ENDIF
2584
2585          IF ( .NOT. ALLOCATED ( rad_sw_in_av ) )  THEN
2586             ALLOCATE ( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2587          ENDIF
2588
2589          IF ( .NOT. ALLOCATED ( rad_sw_out ) )  THEN
2590             ALLOCATE ( rad_sw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2591             rad_sw_out = 0.0_wp
2592          ENDIF
2593
2594          IF ( .NOT. ALLOCATED ( rad_sw_out_av ) )  THEN
2595             ALLOCATE ( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2596          ENDIF
2597
2598          IF ( .NOT. ALLOCATED ( rad_sw_hr ) )  THEN
2599             ALLOCATE ( rad_sw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2600             rad_sw_hr = 0.0_wp
2601          ENDIF
2602
2603          IF ( .NOT. ALLOCATED ( rad_sw_hr_av ) )  THEN
2604             ALLOCATE ( rad_sw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2605             rad_sw_hr_av = 0.0_wp
2606          ENDIF
2607
2608          IF ( .NOT. ALLOCATED ( rad_sw_cs_hr ) )  THEN
2609             ALLOCATE ( rad_sw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2610             rad_sw_cs_hr = 0.0_wp
2611          ENDIF
2612
2613          IF ( .NOT. ALLOCATED ( rad_sw_cs_hr_av ) )  THEN
2614             ALLOCATE ( rad_sw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2615             rad_sw_cs_hr_av = 0.0_wp
2616          ENDIF
2617
2618          IF ( .NOT. ALLOCATED ( rad_lw_in ) )  THEN
2619             ALLOCATE ( rad_lw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2620             rad_lw_in     = 0.0_wp
2621          ENDIF
2622
2623          IF ( .NOT. ALLOCATED ( rad_lw_in_av ) )  THEN
2624             ALLOCATE ( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2625          ENDIF
2626
2627          IF ( .NOT. ALLOCATED ( rad_lw_out ) )  THEN
2628             ALLOCATE ( rad_lw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2629            rad_lw_out    = 0.0_wp
2630          ENDIF
2631
2632          IF ( .NOT. ALLOCATED ( rad_lw_out_av ) )  THEN
2633             ALLOCATE ( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2634          ENDIF
2635
2636          IF ( .NOT. ALLOCATED ( rad_lw_hr ) )  THEN
2637             ALLOCATE ( rad_lw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2638             rad_lw_hr = 0.0_wp
2639          ENDIF
2640
2641          IF ( .NOT. ALLOCATED ( rad_lw_hr_av ) )  THEN
2642             ALLOCATE ( rad_lw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2643             rad_lw_hr_av = 0.0_wp
2644          ENDIF
2645
2646          IF ( .NOT. ALLOCATED ( rad_lw_cs_hr ) )  THEN
2647             ALLOCATE ( rad_lw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2648             rad_lw_cs_hr = 0.0_wp
2649          ENDIF
2650
2651          IF ( .NOT. ALLOCATED ( rad_lw_cs_hr_av ) )  THEN
2652             ALLOCATE ( rad_lw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2653             rad_lw_cs_hr_av = 0.0_wp
2654          ENDIF
2655
2656          ALLOCATE ( rad_sw_cs_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2657          ALLOCATE ( rad_sw_cs_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2658          rad_sw_cs_in  = 0.0_wp
2659          rad_sw_cs_out = 0.0_wp
2660
2661          ALLOCATE ( rad_lw_cs_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2662          ALLOCATE ( rad_lw_cs_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2663          rad_lw_cs_in  = 0.0_wp
2664          rad_lw_cs_out = 0.0_wp
2665
2666!
2667!--       Allocate 1-element array for surface temperature
2668!--       (RRTMG anticipates an array as passed argument).
2669          ALLOCATE ( rrtm_tsfc(1) )
2670!
2671!--       Allocate surface emissivity.
2672!--       Values will be given directly before calling rrtm_lw.
2673          ALLOCATE ( rrtm_emis(0:0,1:nbndlw+1) )
2674
2675!
2676!--       Initialize RRTMG, before check if files are existent
2677          INQUIRE( FILE='rrtmg_lw.nc', EXIST=lw_exists )
2678          IF ( .NOT. lw_exists )  THEN
2679             message_string = 'Input file rrtmg_lw.nc' //                &
2680                            '&for rrtmg missing. ' // &
2681                            '&Please provide <jobname>_lsw file in the INPUT directory.'
2682             CALL message( 'radiation_init', 'PA0583', 1, 2, 0, 6, 0 )
2683          ENDIF         
2684          INQUIRE( FILE='rrtmg_sw.nc', EXIST=sw_exists )
2685          IF ( .NOT. sw_exists )  THEN
2686             message_string = 'Input file rrtmg_sw.nc' //                &
2687                            '&for rrtmg missing. ' // &
2688                            '&Please provide <jobname>_rsw file in the INPUT directory.'
2689             CALL message( 'radiation_init', 'PA0584', 1, 2, 0, 6, 0 )
2690          ENDIF         
2691         
2692          IF ( lw_radiation )  CALL rrtmg_lw_ini ( c_p )
2693          IF ( sw_radiation )  CALL rrtmg_sw_ini ( c_p )
2694         
2695!
2696!--       Set input files for RRTMG
2697          INQUIRE(FILE="RAD_SND_DATA", EXIST=snd_exists) 
2698          IF ( .NOT. snd_exists )  THEN
2699             rrtm_input_file = "rrtmg_lw.nc"
2700          ENDIF
2701
2702!
2703!--       Read vertical layers for RRTMG from sounding data
2704!--       The routine provides nzt_rad, hyp_snd(1:nzt_rad),
2705!--       t_snd(nzt+2:nzt_rad), rrtm_play(1:nzt_rad), rrtm_plev(1_nzt_rad+1),
2706!--       rrtm_tlay(nzt+2:nzt_rad), rrtm_tlev(nzt+2:nzt_rad+1)
2707          CALL read_sounding_data
2708
2709!
2710!--       Read trace gas profiles from file. This routine provides
2711!--       the rrtm_ arrays (1:nzt_rad+1)
2712          CALL read_trace_gas_data
2713#endif
2714       ENDIF
2715
2716!
2717!--    Perform user actions if required
2718       CALL user_init_radiation
2719
2720!
2721!--    Calculate radiative fluxes at model start
2722       SELECT CASE ( TRIM( radiation_scheme ) )
2723
2724          CASE ( 'rrtmg' )
2725             CALL radiation_rrtmg
2726
2727          CASE ( 'clear-sky' )
2728             CALL radiation_clearsky
2729
2730          CASE ( 'constant' )
2731             CALL radiation_constant
2732
2733          CASE DEFAULT
2734
2735       END SELECT
2736
2737! readjust date and time to its initial value
2738       CALL init_date_and_time
2739
2740       CALL location_message( 'finished', .TRUE. )
2741
2742!
2743!--    Find all discretized apparent solar positions for radiation interaction.
2744       IF ( radiation_interactions )  CALL radiation_presimulate_solar_pos
2745
2746!
2747!--    If required, read or calculate and write out the SVF
2748       IF ( radiation_interactions .AND. read_svf)  THEN
2749!
2750!--       Read sky-view factors and further required data from file
2751          CALL location_message( '    Start reading SVF from file', .FALSE. )
2752          CALL radiation_read_svf()
2753          CALL location_message( '    Reading SVF from file has finished', .TRUE. )
2754
2755       ELSEIF ( radiation_interactions .AND. .NOT. read_svf)  THEN
2756!
2757!--       calculate SFV and CSF
2758          CALL location_message( '    Start calculation of SVF', .FALSE. )
2759          CALL radiation_calc_svf()
2760          CALL location_message( '    Calculation of SVF has finished', .TRUE. )
2761       ENDIF
2762
2763       IF ( radiation_interactions .AND. write_svf)  THEN
2764!
2765!--       Write svf, csf svfsurf and csfsurf data to file
2766          CALL location_message( '    Start writing SVF in file', .FALSE. )
2767          CALL radiation_write_svf()
2768          CALL location_message( '    Writing SVF in file has finished', .TRUE. )
2769       ENDIF
2770
2771!
2772!--    Adjust radiative fluxes. In case of urban and land surfaces, also
2773!--    call an initial interaction.
2774       IF ( radiation_interactions )  THEN
2775          CALL radiation_interaction
2776       ENDIF
2777
2778       RETURN
2779
2780    END SUBROUTINE radiation_init
2781
2782
2783!------------------------------------------------------------------------------!
2784! Description:
2785! ------------
2786!> A simple clear sky radiation model
2787!------------------------------------------------------------------------------!
2788    SUBROUTINE radiation_clearsky
2789
2790
2791       IMPLICIT NONE
2792
2793       INTEGER(iwp) ::  l         !< running index for surface orientation
2794       REAL(wp)     ::  pt1       !< potential temperature at first grid level or mean value at urban layer top
2795       REAL(wp)     ::  pt1_l     !< potential temperature at first grid level or mean value at urban layer top at local subdomain
2796       REAL(wp)     ::  ql1       !< liquid water mixing ratio at first grid level or mean value at urban layer top
2797       REAL(wp)     ::  ql1_l     !< liquid water mixing ratio at first grid level or mean value at urban layer top at local subdomain
2798
2799       TYPE(surf_type), POINTER ::  surf !< pointer on respective surface type, used to generalize routine   
2800
2801!
2802!--    Calculate current zenith angle
2803       CALL calc_zenith
2804
2805!
2806!--    Calculate sky transmissivity
2807       sky_trans = 0.6_wp + 0.2_wp * zenith(0)
2808
2809!
2810!--    Calculate value of the Exner function at model surface
2811!
2812!--    In case averaged radiation is used, calculate mean temperature and
2813!--    liquid water mixing ratio at the urban-layer top.
2814       IF ( average_radiation ) THEN
2815          pt1   = 0.0_wp
2816          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1   = 0.0_wp
2817
2818          pt1_l = SUM( pt(nzut,nys:nyn,nxl:nxr) )
2819          IF ( bulk_cloud_model  .OR.  cloud_droplets  )  ql1_l = SUM( ql(nzut,nys:nyn,nxl:nxr) )
2820
2821#if defined( __parallel )     
2822          IF ( collective_wait )  CALL MPI_BARRIER( comm2d, ierr )
2823          CALL MPI_ALLREDUCE( pt1_l, pt1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
2824          IF ( ierr /= 0 ) THEN
2825              WRITE(9,*) 'Error MPI_AllReduce1:', ierr, pt1_l, pt1
2826              FLUSH(9)
2827          ENDIF
2828
2829          IF ( bulk_cloud_model  .OR.  cloud_droplets ) THEN
2830              CALL MPI_ALLREDUCE( ql1_l, ql1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
2831              IF ( ierr /= 0 ) THEN
2832                  WRITE(9,*) 'Error MPI_AllReduce2:', ierr, ql1_l, ql1
2833                  FLUSH(9)
2834              ENDIF
2835          ENDIF
2836#else
2837          pt1 = pt1_l 
2838          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1 = ql1_l
2839#endif
2840
2841          IF ( bulk_cloud_model  .OR.  cloud_droplets  )  pt1 = pt1 + lv_d_cp / exner(nzut) * ql1
2842!
2843!--       Finally, divide by number of grid points
2844          pt1 = pt1 / REAL( ( nx + 1 ) * ( ny + 1 ), KIND=wp )
2845       ENDIF
2846!
2847!--    Call clear-sky calculation for each surface orientation.
2848!--    First, horizontal surfaces
2849       surf => surf_lsm_h
2850       CALL radiation_clearsky_surf
2851       surf => surf_usm_h
2852       CALL radiation_clearsky_surf
2853!
2854!--    Vertical surfaces
2855       DO  l = 0, 3
2856          surf => surf_lsm_v(l)
2857          CALL radiation_clearsky_surf
2858          surf => surf_usm_v(l)
2859          CALL radiation_clearsky_surf
2860       ENDDO
2861
2862       CONTAINS
2863
2864          SUBROUTINE radiation_clearsky_surf
2865
2866             IMPLICIT NONE
2867
2868             INTEGER(iwp) ::  i         !< index x-direction
2869             INTEGER(iwp) ::  j         !< index y-direction
2870             INTEGER(iwp) ::  k         !< index z-direction
2871             INTEGER(iwp) ::  m         !< running index for surface elements
2872
2873             IF ( surf%ns < 1 )  RETURN
2874
2875!
2876!--          Calculate radiation fluxes and net radiation (rad_net) assuming
2877!--          homogeneous urban radiation conditions.
2878             IF ( average_radiation ) THEN       
2879
2880                k = nzut
2881
2882                surf%rad_sw_in  = solar_constant * sky_trans * zenith(0)
2883                surf%rad_sw_out = albedo_urb * surf%rad_sw_in
2884               
2885                surf%rad_lw_in  = 0.8_wp * sigma_sb * (pt1 * exner(k+1))**4
2886
2887                surf%rad_lw_out = emissivity_urb * sigma_sb * (t_rad_urb)**4   &
2888                                    + (1.0_wp - emissivity_urb) * surf%rad_lw_in
2889
2890                surf%rad_net = surf%rad_sw_in - surf%rad_sw_out                &
2891                             + surf%rad_lw_in - surf%rad_lw_out
2892
2893                surf%rad_lw_out_change_0 = 3.0_wp * emissivity_urb * sigma_sb  &
2894                                           * (t_rad_urb)**3
2895
2896!
2897!--          Calculate radiation fluxes and net radiation (rad_net) for each surface
2898!--          element.
2899             ELSE
2900
2901                DO  m = 1, surf%ns
2902                   i = surf%i(m)
2903                   j = surf%j(m)
2904                   k = surf%k(m)
2905
2906                   surf%rad_sw_in(m) = solar_constant * sky_trans * zenith(0)
2907
2908!
2909!--                Weighted average according to surface fraction.
2910!--                ATTENTION: when radiation interactions are switched on the
2911!--                calculated fluxes below are not actually used as they are
2912!--                overwritten in radiation_interaction.
2913                   surf%rad_sw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
2914                                          surf%albedo(ind_veg_wall,m)          &
2915                                        + surf%frac(ind_pav_green,m) *         &
2916                                          surf%albedo(ind_pav_green,m)         &
2917                                        + surf%frac(ind_wat_win,m)   *         &
2918                                          surf%albedo(ind_wat_win,m) )         &
2919                                        * surf%rad_sw_in(m)
2920
2921                   surf%rad_lw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
2922                                          surf%emissivity(ind_veg_wall,m)      &
2923                                        + surf%frac(ind_pav_green,m) *         &
2924                                          surf%emissivity(ind_pav_green,m)     &
2925                                        + surf%frac(ind_wat_win,m)   *         &
2926                                          surf%emissivity(ind_wat_win,m)       &
2927                                        )                                      &
2928                                        * sigma_sb                             &
2929                                        * ( surf%pt_surface(m) * exner(nzb) )**4
2930
2931                   surf%rad_lw_out_change_0(m) =                               &
2932                                      ( surf%frac(ind_veg_wall,m)  *           &
2933                                        surf%emissivity(ind_veg_wall,m)        &
2934                                      + surf%frac(ind_pav_green,m) *           &
2935                                        surf%emissivity(ind_pav_green,m)       &
2936                                      + surf%frac(ind_wat_win,m)   *           &
2937                                        surf%emissivity(ind_wat_win,m)         &
2938                                      ) * 3.0_wp * sigma_sb                    &
2939                                      * ( surf%pt_surface(m) * exner(nzb) )** 3
2940
2941
2942                   IF ( bulk_cloud_model  .OR.  cloud_droplets  )  THEN
2943                      pt1 = pt(k,j,i) + lv_d_cp / exner(k) * ql(k,j,i)
2944                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb * (pt1 * exner(k))**4
2945                   ELSE
2946                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb * (pt(k,j,i) * exner(k))**4
2947                   ENDIF
2948
2949                   surf%rad_net(m) = surf%rad_sw_in(m) - surf%rad_sw_out(m)    &
2950                                   + surf%rad_lw_in(m) - surf%rad_lw_out(m)
2951
2952                ENDDO
2953
2954             ENDIF
2955
2956!
2957!--          Fill out values in radiation arrays
2958             DO  m = 1, surf%ns
2959                i = surf%i(m)
2960                j = surf%j(m)
2961                rad_sw_in(0,j,i) = surf%rad_sw_in(m)
2962                rad_sw_out(0,j,i) = surf%rad_sw_out(m)
2963                rad_lw_in(0,j,i) = surf%rad_lw_in(m)
2964                rad_lw_out(0,j,i) = surf%rad_lw_out(m)
2965             ENDDO
2966 
2967          END SUBROUTINE radiation_clearsky_surf
2968
2969    END SUBROUTINE radiation_clearsky
2970
2971
2972!------------------------------------------------------------------------------!
2973! Description:
2974! ------------
2975!> This scheme keeps the prescribed net radiation constant during the run
2976!------------------------------------------------------------------------------!
2977    SUBROUTINE radiation_constant
2978
2979
2980       IMPLICIT NONE
2981
2982       INTEGER(iwp) ::  l         !< running index for surface orientation
2983
2984       REAL(wp)     ::  pt1       !< potential temperature at first grid level or mean value at urban layer top
2985       REAL(wp)     ::  pt1_l     !< potential temperature at first grid level or mean value at urban layer top at local subdomain
2986       REAL(wp)     ::  ql1       !< liquid water mixing ratio at first grid level or mean value at urban layer top
2987       REAL(wp)     ::  ql1_l     !< liquid water mixing ratio at first grid level or mean value at urban layer top at local subdomain
2988
2989       TYPE(surf_type), POINTER ::  surf !< pointer on respective surface type, used to generalize routine
2990
2991!
2992!--    In case averaged radiation is used, calculate mean temperature and
2993!--    liquid water mixing ratio at the urban-layer top.
2994       IF ( average_radiation ) THEN   
2995          pt1   = 0.0_wp
2996          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1   = 0.0_wp
2997
2998          pt1_l = SUM( pt(nzut,nys:nyn,nxl:nxr) )
2999          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1_l = SUM( ql(nzut,nys:nyn,nxl:nxr) )
3000
3001#if defined( __parallel )     
3002          IF ( collective_wait )  CALL MPI_BARRIER( comm2d, ierr )
3003          CALL MPI_ALLREDUCE( pt1_l, pt1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
3004          IF ( ierr /= 0 ) THEN
3005              WRITE(9,*) 'Error MPI_AllReduce3:', ierr, pt1_l, pt1
3006              FLUSH(9)
3007          ENDIF
3008          IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
3009             CALL MPI_ALLREDUCE( ql1_l, ql1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
3010             IF ( ierr /= 0 ) THEN
3011                 WRITE(9,*) 'Error MPI_AllReduce4:', ierr, ql1_l, ql1
3012                 FLUSH(9)
3013             ENDIF
3014          ENDIF
3015#else
3016          pt1 = pt1_l
3017          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1 = ql1_l
3018#endif
3019          IF ( bulk_cloud_model  .OR.  cloud_droplets )  pt1 = pt1 + lv_d_cp / exner(nzut+1) * ql1
3020!
3021!--       Finally, divide by number of grid points
3022          pt1 = pt1 / REAL( ( nx + 1 ) * ( ny + 1 ), KIND=wp )
3023       ENDIF
3024
3025!
3026!--    First, horizontal surfaces
3027       surf => surf_lsm_h
3028       CALL radiation_constant_surf
3029       surf => surf_usm_h
3030       CALL radiation_constant_surf
3031!
3032!--    Vertical surfaces
3033       DO  l = 0, 3
3034          surf => surf_lsm_v(l)
3035          CALL radiation_constant_surf
3036          surf => surf_usm_v(l)
3037          CALL radiation_constant_surf
3038       ENDDO
3039
3040       CONTAINS
3041
3042          SUBROUTINE radiation_constant_surf
3043
3044             IMPLICIT NONE
3045
3046             INTEGER(iwp) ::  i         !< index x-direction
3047             INTEGER(iwp) ::  ioff      !< offset between surface element and adjacent grid point along x
3048             INTEGER(iwp) ::  j         !< index y-direction
3049             INTEGER(iwp) ::  joff      !< offset between surface element and adjacent grid point along y
3050             INTEGER(iwp) ::  k         !< index z-direction
3051             INTEGER(iwp) ::  koff      !< offset between surface element and adjacent grid point along z
3052             INTEGER(iwp) ::  m         !< running index for surface elements
3053
3054             IF ( surf%ns < 1 )  RETURN
3055
3056!--          Calculate homogenoeus urban radiation fluxes
3057             IF ( average_radiation ) THEN
3058
3059                surf%rad_net = net_radiation
3060
3061                surf%rad_lw_in  = 0.8_wp * sigma_sb * (pt1 * exner(nzut+1))**4
3062
3063                surf%rad_lw_out = emissivity_urb * sigma_sb * (t_rad_urb)**4   &
3064                                    + ( 1.0_wp - emissivity_urb )             & ! shouldn't be this a bulk value -- emissivity_urb?
3065                                    * surf%rad_lw_in
3066
3067                surf%rad_lw_out_change_0 = 3.0_wp * emissivity_urb * sigma_sb  &
3068                                           * t_rad_urb**3
3069
3070                surf%rad_sw_in = ( surf%rad_net - surf%rad_lw_in               &
3071                                     + surf%rad_lw_out )                       &
3072                                     / ( 1.0_wp - albedo_urb )
3073
3074                surf%rad_sw_out =  albedo_urb * surf%rad_sw_in
3075
3076!
3077!--          Calculate radiation fluxes for each surface element
3078             ELSE
3079!
3080!--             Determine index offset between surface element and adjacent
3081!--             atmospheric grid point
3082                ioff = surf%ioff
3083                joff = surf%joff
3084                koff = surf%koff
3085
3086!
3087!--             Prescribe net radiation and estimate the remaining radiative fluxes
3088                DO  m = 1, surf%ns
3089                   i = surf%i(m)
3090                   j = surf%j(m)
3091                   k = surf%k(m)
3092
3093                   surf%rad_net(m) = net_radiation
3094
3095                   IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
3096                      pt1 = pt(k,j,i) + lv_d_cp / exner(k) * ql(k,j,i)
3097                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb * (pt1 * exner(k))**4
3098                   ELSE
3099                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb *                 &
3100                                             ( pt(k,j,i) * exner(k) )**4
3101                   ENDIF
3102
3103!
3104!--                Weighted average according to surface fraction.
3105                   surf%rad_lw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
3106                                          surf%emissivity(ind_veg_wall,m)      &
3107                                        + surf%frac(ind_pav_green,m) *         &
3108                                          surf%emissivity(ind_pav_green,m)     &
3109                                        + surf%frac(ind_wat_win,m)   *         &
3110                                          surf%emissivity(ind_wat_win,m)       &
3111                                        )                                      &
3112                                      * sigma_sb                               &
3113                                      * ( surf%pt_surface(m) * exner(nzb) )**4
3114
3115                   surf%rad_sw_in(m) = ( surf%rad_net(m) - surf%rad_lw_in(m)   &
3116                                       + surf%rad_lw_out(m) )                  &
3117                                       / ( 1.0_wp -                            &
3118                                          ( surf%frac(ind_veg_wall,m)  *       &
3119                                            surf%albedo(ind_veg_wall,m)        &
3120                                         +  surf%frac(ind_pav_green,m) *       &
3121                                            surf%albedo(ind_pav_green,m)       &
3122                                         +  surf%frac(ind_wat_win,m)   *       &
3123                                            surf%albedo(ind_wat_win,m) )       &
3124                                         )
3125
3126                   surf%rad_sw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
3127                                          surf%albedo(ind_veg_wall,m)          &
3128                                        + surf%frac(ind_pav_green,m) *         &
3129                                          surf%albedo(ind_pav_green,m)         &
3130                                        + surf%frac(ind_wat_win,m)   *         &
3131                                          surf%albedo(ind_wat_win,m) )         &
3132                                      * surf%rad_sw_in(m)
3133
3134                ENDDO
3135
3136             ENDIF
3137
3138!
3139!--          Fill out values in radiation arrays
3140             DO  m = 1, surf%ns
3141                i = surf%i(m)
3142                j = surf%j(m)
3143                rad_sw_in(0,j,i) = surf%rad_sw_in(m)
3144                rad_sw_out(0,j,i) = surf%rad_sw_out(m)
3145                rad_lw_in(0,j,i) = surf%rad_lw_in(m)
3146                rad_lw_out(0,j,i) = surf%rad_lw_out(m)
3147             ENDDO
3148
3149          END SUBROUTINE radiation_constant_surf
3150         
3151
3152    END SUBROUTINE radiation_constant
3153
3154!------------------------------------------------------------------------------!
3155! Description:
3156! ------------
3157!> Header output for radiation model
3158!------------------------------------------------------------------------------!
3159    SUBROUTINE radiation_header ( io )
3160
3161
3162       IMPLICIT NONE
3163 
3164       INTEGER(iwp), INTENT(IN) ::  io            !< Unit of the output file
3165   
3166
3167       
3168!
3169!--    Write radiation model header
3170       WRITE( io, 3 )
3171
3172       IF ( radiation_scheme == "constant" )  THEN
3173          WRITE( io, 4 ) net_radiation
3174       ELSEIF ( radiation_scheme == "clear-sky" )  THEN
3175          WRITE( io, 5 )
3176       ELSEIF ( radiation_scheme == "rrtmg" )  THEN
3177          WRITE( io, 6 )
3178          IF ( .NOT. lw_radiation )  WRITE( io, 10 )
3179          IF ( .NOT. sw_radiation )  WRITE( io, 11 )
3180       ENDIF
3181
3182       IF ( albedo_type_f%from_file  .OR.  vegetation_type_f%from_file  .OR.   &
3183            pavement_type_f%from_file  .OR.  water_type_f%from_file  .OR.      &
3184            building_type_f%from_file )  THEN
3185             WRITE( io, 13 )
3186       ELSE 
3187          IF ( albedo_type == 0 )  THEN
3188             WRITE( io, 7 ) albedo
3189          ELSE
3190             WRITE( io, 8 ) TRIM( albedo_type_name(albedo_type) )
3191          ENDIF
3192       ENDIF
3193       IF ( constant_albedo )  THEN
3194          WRITE( io, 9 )
3195       ENDIF
3196       
3197       WRITE( io, 12 ) dt_radiation
3198 
3199
3200 3 FORMAT (//' Radiation model information:'/                                  &
3201              ' ----------------------------'/)
3202 4 FORMAT ('    --> Using constant net radiation: net_radiation = ', F6.2,     &
3203           // 'W/m**2')
3204 5 FORMAT ('    --> Simple radiation scheme for clear sky is used (no clouds,',&
3205                   ' default)')
3206 6 FORMAT ('    --> RRTMG scheme is used')
3207 7 FORMAT (/'    User-specific surface albedo: albedo =', F6.3)
3208 8 FORMAT (/'    Albedo is set for land surface type: ', A)
3209 9 FORMAT (/'    --> Albedo is fixed during the run')
321010 FORMAT (/'    --> Longwave radiation is disabled')
321111 FORMAT (/'    --> Shortwave radiation is disabled.')
321212 FORMAT  ('    Timestep: dt_radiation = ', F6.2, '  s')
321313 FORMAT (/'    Albedo is set individually for each xy-location, according ', &
3214                 'to given surface type.')
3215
3216
3217    END SUBROUTINE radiation_header
3218   
3219
3220!------------------------------------------------------------------------------!
3221! Description:
3222! ------------
3223!> Parin for &radiation_parameters for radiation model
3224!------------------------------------------------------------------------------!
3225    SUBROUTINE radiation_parin
3226
3227
3228       IMPLICIT NONE
3229
3230       CHARACTER (LEN=80) ::  line  !< dummy string that contains the current line of the parameter file
3231       
3232       NAMELIST /radiation_par/   albedo, albedo_lw_dif, albedo_lw_dir,         &
3233                                  albedo_sw_dif, albedo_sw_dir, albedo_type,    &
3234                                  constant_albedo, dt_radiation, emissivity,    &
3235                                  lw_radiation, max_raytracing_dist,            &
3236                                  min_irrf_value, mrt_geom_human,               &
3237                                  mrt_include_sw, mrt_nlevels,                  &
3238                                  mrt_skip_roof, net_radiation, nrefsteps,      &
3239                                  plant_lw_interact, rad_angular_discretization,&
3240                                  radiation_interactions_on, radiation_scheme,  &
3241                                  raytrace_discrete_azims,                      &
3242                                  raytrace_discrete_elevs, raytrace_mpi_rma,    &
3243                                  skip_time_do_radiation, surface_reflections,  &
3244                                  svfnorm_report_thresh, sw_radiation,          &
3245                                  unscheduled_radiation_calls
3246
3247   
3248       NAMELIST /radiation_parameters/ albedo, albedo_lw_dif, albedo_lw_dir,    &
3249                                  albedo_sw_dif, albedo_sw_dir, albedo_type,    &
3250                                  constant_albedo, dt_radiation, emissivity,    &
3251                                  lw_radiation, max_raytracing_dist,            &
3252                                  min_irrf_value, mrt_geom_human,               &
3253                                  mrt_include_sw, mrt_nlevels,                  &
3254                                  mrt_skip_roof, net_radiation, nrefsteps,      &
3255                                  plant_lw_interact, rad_angular_discretization,&
3256                                  radiation_interactions_on, radiation_scheme,  &
3257                                  raytrace_discrete_azims,                      &
3258                                  raytrace_discrete_elevs, raytrace_mpi_rma,    &
3259                                  skip_time_do_radiation, surface_reflections,  &
3260                                  svfnorm_report_thresh, sw_radiation,          &
3261                                  unscheduled_radiation_calls
3262   
3263       line = ' '
3264       
3265!
3266!--    Try to find radiation model namelist
3267       REWIND ( 11 )
3268       line = ' '
3269       DO WHILE ( INDEX( line, '&radiation_parameters' ) == 0 )
3270          READ ( 11, '(A)', END=12 )  line
3271       ENDDO
3272       BACKSPACE ( 11 )
3273
3274!
3275!--    Read user-defined namelist
3276       READ ( 11, radiation_parameters, ERR = 10 )
3277
3278!
3279!--    Set flag that indicates that the radiation model is switched on
3280       radiation = .TRUE.
3281
3282       GOTO 14
3283
3284 10    BACKSPACE( 11 )
3285       READ( 11 , '(A)') line
3286       CALL parin_fail_message( 'radiation_parameters', line )
3287!
3288!--    Try to find old namelist
3289 12    REWIND ( 11 )
3290       line = ' '
3291       DO WHILE ( INDEX( line, '&radiation_par' ) == 0 )
3292          READ ( 11, '(A)', END=14 )  line
3293       ENDDO
3294       BACKSPACE ( 11 )
3295
3296!
3297!--    Read user-defined namelist
3298       READ ( 11, radiation_par, ERR = 13, END = 14 )
3299
3300       message_string = 'namelist radiation_par is deprecated and will be ' // &
3301                     'removed in near future. Please use namelist ' //         &
3302                     'radiation_parameters instead'
3303       CALL message( 'radiation_parin', 'PA0487', 0, 1, 0, 6, 0 )
3304
3305!
3306!--    Set flag that indicates that the radiation model is switched on
3307       radiation = .TRUE.
3308
3309       IF ( .NOT.  radiation_interactions_on  .AND.  surface_reflections )  THEN
3310          message_string = 'surface_reflections is allowed only when '      // &
3311               'radiation_interactions_on is set to TRUE'
3312          CALL message( 'radiation_parin', 'PA0293',1, 2, 0, 6, 0 )
3313       ENDIF
3314
3315       GOTO 14
3316
3317 13    BACKSPACE( 11 )
3318       READ( 11 , '(A)') line
3319       CALL parin_fail_message( 'radiation_par', line )
3320
3321 14    CONTINUE
3322       
3323    END SUBROUTINE radiation_parin
3324
3325
3326!------------------------------------------------------------------------------!
3327! Description:
3328! ------------
3329!> Implementation of the RRTMG radiation_scheme
3330!------------------------------------------------------------------------------!
3331    SUBROUTINE radiation_rrtmg
3332
3333#if defined ( __rrtmg )
3334       USE indices,                                                            &
3335           ONLY:  nbgp
3336
3337       USE particle_attributes,                                                &
3338           ONLY:  grid_particles, number_of_particles, particles,              &
3339                  particle_advection_start, prt_count
3340
3341       IMPLICIT NONE
3342
3343
3344       INTEGER(iwp) ::  i, j, k, l, m, n !< loop indices
3345       INTEGER(iwp) ::  k_topo     !< topography top index
3346
3347       REAL(wp)     ::  nc_rad, &    !< number concentration of cloud droplets
3348                        s_r2,   &    !< weighted sum over all droplets with r^2
3349                        s_r3         !< weighted sum over all droplets with r^3
3350
3351       REAL(wp), DIMENSION(0:nzt+1) :: pt_av, q_av, ql_av
3352!
3353!--    Just dummy arguments
3354       REAL(wp), DIMENSION(:,:,:), ALLOCATABLE :: rrtm_lw_taucld_dum,          &
3355                                                  rrtm_lw_tauaer_dum,          &
3356                                                  rrtm_sw_taucld_dum,          &
3357                                                  rrtm_sw_ssacld_dum,          &
3358                                                  rrtm_sw_asmcld_dum,          &
3359                                                  rrtm_sw_fsfcld_dum,          &
3360                                                  rrtm_sw_tauaer_dum,          &
3361                                                  rrtm_sw_ssaaer_dum,          &
3362                                                  rrtm_sw_asmaer_dum,          &
3363                                                  rrtm_sw_ecaer_dum
3364
3365!
3366!--    Calculate current (cosine of) zenith angle and whether the sun is up
3367       CALL calc_zenith     
3368!
3369!--    Calculate surface albedo. In case average radiation is applied,
3370!--    this is not required.
3371#if defined( __netcdf )
3372       IF ( .NOT. constant_albedo )  THEN
3373!
3374!--       Horizontally aligned default, natural and urban surfaces
3375          CALL calc_albedo( surf_lsm_h    )
3376          CALL calc_albedo( surf_usm_h    )
3377!
3378!--       Vertically aligned default, natural and urban surfaces
3379          DO  l = 0, 3
3380             CALL calc_albedo( surf_lsm_v(l) )
3381             CALL calc_albedo( surf_usm_v(l) )
3382          ENDDO
3383       ENDIF
3384#endif
3385
3386!
3387!--    Prepare input data for RRTMG
3388
3389!
3390!--    In case of large scale forcing with surface data, calculate new pressure
3391!--    profile. nzt_rad might be modified by these calls and all required arrays
3392!--    will then be re-allocated
3393       IF ( large_scale_forcing  .AND.  lsf_surf )  THEN
3394          CALL read_sounding_data
3395          CALL read_trace_gas_data
3396       ENDIF
3397
3398
3399       IF ( average_radiation ) THEN
3400
3401          rrtm_asdir(1)  = albedo_urb
3402          rrtm_asdif(1)  = albedo_urb
3403          rrtm_aldir(1)  = albedo_urb
3404          rrtm_aldif(1)  = albedo_urb
3405
3406          rrtm_emis = emissivity_urb
3407!
3408!--       Calculate mean pt profile. Actually, only one height level is required.
3409          CALL calc_mean_profile( pt, 4 )
3410          pt_av = hom(:, 1, 4, 0)
3411         
3412          IF ( humidity )  THEN
3413             CALL calc_mean_profile( q, 41 )
3414             q_av  = hom(:, 1, 41, 0)
3415          ENDIF
3416!
3417!--       Prepare profiles of temperature and H2O volume mixing ratio
3418          rrtm_tlev(0,nzb+1) = t_rad_urb
3419
3420          IF ( bulk_cloud_model )  THEN
3421
3422             CALL calc_mean_profile( ql, 54 )
3423             ! average ql is now in hom(:, 1, 54, 0)
3424             ql_av = hom(:, 1, 54, 0)
3425             
3426             DO k = nzb+1, nzt+1
3427                rrtm_tlay(0,k) = pt_av(k) * ( (hyp(k) ) / 100000._wp       &
3428                                 )**.286_wp + lv_d_cp * ql_av(k)
3429                rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * (q_av(k) - ql_av(k))
3430             ENDDO
3431          ELSE
3432             DO k = nzb+1, nzt+1
3433                rrtm_tlay(0,k) = pt_av(k) * ( (hyp(k) ) / 100000._wp       &
3434                                 )**.286_wp
3435             ENDDO
3436
3437             IF ( humidity )  THEN
3438                DO k = nzb+1, nzt+1
3439                   rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * q_av(k)
3440                ENDDO
3441             ELSE
3442                rrtm_h2ovmr(0,nzb+1:nzt+1) = 0.0_wp
3443             ENDIF
3444          ENDIF
3445
3446!
3447!--       Avoid temperature/humidity jumps at the top of the LES domain by
3448!--       linear interpolation from nzt+2 to nzt+7
3449          DO k = nzt+2, nzt+7
3450             rrtm_tlay(0,k) = rrtm_tlay(0,nzt+1)                            &
3451                           + ( rrtm_tlay(0,nzt+8) - rrtm_tlay(0,nzt+1) )    &
3452                           / ( rrtm_play(0,nzt+8) - rrtm_play(0,nzt+1) )    &
3453                           * ( rrtm_play(0,k) - rrtm_play(0,nzt+1) )
3454
3455             rrtm_h2ovmr(0,k) = rrtm_h2ovmr(0,nzt+1)                        &
3456                           + ( rrtm_h2ovmr(0,nzt+8) - rrtm_h2ovmr(0,nzt+1) )&
3457                           / ( rrtm_play(0,nzt+8)   - rrtm_play(0,nzt+1)   )&
3458                           * ( rrtm_play(0,k) - rrtm_play(0,nzt+1) )
3459
3460          ENDDO
3461
3462!--       Linear interpolate to zw grid
3463          DO k = nzb+2, nzt+8
3464             rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k) -        &
3465                                rrtm_tlay(0,k-1))                           &
3466                                / ( rrtm_play(0,k) - rrtm_play(0,k-1) )     &
3467                                * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
3468          ENDDO
3469
3470
3471!
3472!--       Calculate liquid water path and cloud fraction for each column.
3473!--       Note that LWP is required in g/m2 instead of kg/kg m.
3474          rrtm_cldfr  = 0.0_wp
3475          rrtm_reliq  = 0.0_wp
3476          rrtm_cliqwp = 0.0_wp
3477          rrtm_icld   = 0
3478
3479          IF ( bulk_cloud_model )  THEN
3480             DO k = nzb+1, nzt+1
3481                rrtm_cliqwp(0,k) =  ql_av(k) * 1000._wp *                   &
3482                                    (rrtm_plev(0,k) - rrtm_plev(0,k+1))     &
3483                                    * 100._wp / g 
3484
3485                IF ( rrtm_cliqwp(0,k) > 0._wp )  THEN
3486                   rrtm_cldfr(0,k) = 1._wp
3487                   IF ( rrtm_icld == 0 )  rrtm_icld = 1
3488
3489!
3490!--                Calculate cloud droplet effective radius
3491                   rrtm_reliq(0,k) = 1.0E6_wp * ( 3.0_wp * ql_av(k)         &
3492                                     * rho_surface                          &
3493                                     / ( 4.0_wp * pi * nc_const * rho_l )   &
3494                                     )**0.33333333333333_wp                 &
3495                                     * EXP( LOG( sigma_gc )**2 )
3496!
3497!--                Limit effective radius
3498                   IF ( rrtm_reliq(0,k) > 0.0_wp )  THEN
3499                      rrtm_reliq(0,k) = MAX(rrtm_reliq(0,k),2.5_wp)
3500                      rrtm_reliq(0,k) = MIN(rrtm_reliq(0,k),60.0_wp)
3501                   ENDIF
3502                ENDIF
3503             ENDDO
3504          ENDIF
3505
3506!
3507!--       Set surface temperature
3508          rrtm_tsfc = t_rad_urb
3509         
3510          IF ( lw_radiation )  THEN       
3511         
3512             CALL rrtmg_lw( 1, nzt_rad      , rrtm_icld    , rrtm_idrv      ,&
3513             rrtm_play       , rrtm_plev    , rrtm_tlay    , rrtm_tlev      ,&
3514             rrtm_tsfc       , rrtm_h2ovmr  , rrtm_o3vmr   , rrtm_co2vmr    ,&
3515             rrtm_ch4vmr     , rrtm_n2ovmr  , rrtm_o2vmr   , rrtm_cfc11vmr  ,&
3516             rrtm_cfc12vmr   , rrtm_cfc22vmr, rrtm_ccl4vmr , rrtm_emis      ,&
3517             rrtm_inflglw    , rrtm_iceflglw, rrtm_liqflglw, rrtm_cldfr     ,&
3518             rrtm_lw_taucld  , rrtm_cicewp  , rrtm_cliqwp  , rrtm_reice     ,& 
3519             rrtm_reliq      , rrtm_lw_tauaer,                               &
3520             rrtm_lwuflx     , rrtm_lwdflx  , rrtm_lwhr  ,                   &
3521             rrtm_lwuflxc    , rrtm_lwdflxc , rrtm_lwhrc ,                   &
3522             rrtm_lwuflx_dt  ,  rrtm_lwuflxc_dt )
3523
3524!
3525!--          Save fluxes
3526             DO k = nzb, nzt+1
3527                rad_lw_in(k,:,:)  = rrtm_lwdflx(0,k)
3528                rad_lw_out(k,:,:) = rrtm_lwuflx(0,k)
3529             ENDDO
3530             rad_lw_in_diff(:,:) = rad_lw_in(0,:,:)
3531!
3532!--          Save heating rates (convert from K/d to K/h).
3533!--          Further, even though an aggregated radiation is computed, map
3534!--          signle-column profiles on top of any topography, in order to
3535!--          obtain correct near surface radiation heating/cooling rates.
3536             DO  i = nxl, nxr
3537                DO  j = nys, nyn
3538                   k_topo = get_topography_top_index_ji( j, i, 's' )
3539                   DO k = k_topo+1, nzt+1
3540                      rad_lw_hr(k,j,i)     = rrtm_lwhr(0,k-k_topo)  * d_hours_day
3541                      rad_lw_cs_hr(k,j,i)  = rrtm_lwhrc(0,k-k_topo) * d_hours_day
3542                   ENDDO
3543                ENDDO
3544             ENDDO
3545
3546          ENDIF
3547
3548          IF ( sw_radiation .AND. sun_up )  THEN
3549             CALL rrtmg_sw( 1, nzt_rad      , rrtm_icld     , rrtm_iaer      ,&
3550             rrtm_play      , rrtm_plev     , rrtm_tlay     , rrtm_tlev      ,&
3551             rrtm_tsfc      , rrtm_h2ovmr   , rrtm_o3vmr    , rrtm_co2vmr    ,&
3552             rrtm_ch4vmr    , rrtm_n2ovmr   , rrtm_o2vmr    , rrtm_asdir     ,&
3553             rrtm_asdif     , rrtm_aldir    , rrtm_aldif    , zenith         ,&
3554             0.0_wp         , day_of_year   , solar_constant, rrtm_inflgsw   ,&
3555             rrtm_iceflgsw  , rrtm_liqflgsw , rrtm_cldfr    , rrtm_sw_taucld ,&
3556             rrtm_sw_ssacld , rrtm_sw_asmcld, rrtm_sw_fsfcld, rrtm_cicewp    ,&
3557             rrtm_cliqwp    , rrtm_reice    , rrtm_reliq    , rrtm_sw_tauaer ,&
3558             rrtm_sw_ssaaer , rrtm_sw_asmaer, rrtm_sw_ecaer , rrtm_swuflx    ,&
3559             rrtm_swdflx    , rrtm_swhr     , rrtm_swuflxc  , rrtm_swdflxc   ,&
3560             rrtm_swhrc     , rrtm_dirdflux , rrtm_difdflux )
3561 
3562!
3563!--          Save fluxes:
3564!--          - whole domain
3565             DO k = nzb, nzt+1
3566                rad_sw_in(k,:,:)  = rrtm_swdflx(0,k)
3567                rad_sw_out(k,:,:) = rrtm_swuflx(0,k)
3568             ENDDO
3569!--          - direct and diffuse SW at urban-surface-layer (required by RTM)
3570             rad_sw_in_dir(:,:) = rrtm_dirdflux(0,nzb)
3571             rad_sw_in_diff(:,:) = rrtm_difdflux(0,nzb)
3572
3573!
3574!--          Save heating rates (convert from K/d to K/s)
3575             DO k = nzb+1, nzt+1
3576                rad_sw_hr(k,:,:)     = rrtm_swhr(0,k)  * d_hours_day
3577                rad_sw_cs_hr(k,:,:)  = rrtm_swhrc(0,k) * d_hours_day
3578             ENDDO
3579!
3580!--       Solar radiation is zero during night
3581          ELSE
3582             rad_sw_in  = 0.0_wp
3583             rad_sw_out = 0.0_wp
3584             rad_sw_in_dir(:,:) = 0.0_wp
3585             rad_sw_in_diff(:,:) = 0.0_wp
3586          ENDIF
3587!
3588!--    RRTMG is called for each (j,i) grid point separately, starting at the
3589!--    highest topography level. Here no RTM is used since average_radiation is false
3590       ELSE
3591!
3592!--       Loop over all grid points
3593          DO i = nxl, nxr
3594             DO j = nys, nyn
3595
3596!
3597!--             Prepare profiles of temperature and H2O volume mixing ratio
3598                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
3599                   rrtm_tlev(0,nzb+1) = surf_lsm_h%pt_surface(m) * exner(nzb)
3600                ENDDO
3601                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
3602                   rrtm_tlev(0,nzb+1) = surf_usm_h%pt_surface(m) * exner(nzb)
3603                ENDDO
3604
3605
3606                IF ( bulk_cloud_model )  THEN
3607                   DO k = nzb+1, nzt+1
3608                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)                    &
3609                                        + lv_d_cp * ql(k,j,i)
3610                      rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * (q(k,j,i) - ql(k,j,i))
3611                   ENDDO
3612                ELSEIF ( cloud_droplets )  THEN
3613                   DO k = nzb+1, nzt+1
3614                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)                     &
3615                                        + lv_d_cp * ql(k,j,i)
3616                      rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * q(k,j,i) 
3617                   ENDDO
3618                ELSE
3619                   DO k = nzb+1, nzt+1
3620                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)
3621                   ENDDO
3622
3623                   IF ( humidity )  THEN
3624                      DO k = nzb+1, nzt+1
3625                         rrtm_h2ovmr(0,k) =  mol_mass_air_d_wv * q(k,j,i)
3626                      ENDDO   
3627                   ELSE
3628                      rrtm_h2ovmr(0,nzb+1:nzt+1) = 0.0_wp
3629                   ENDIF
3630                ENDIF
3631
3632!
3633!--             Avoid temperature/humidity jumps at the top of the LES domain by
3634!--             linear interpolation from nzt+2 to nzt+7
3635                DO k = nzt+2, nzt+7
3636                   rrtm_tlay(0,k) = rrtm_tlay(0,nzt+1)                         &
3637                                 + ( rrtm_tlay(0,nzt+8) - rrtm_tlay(0,nzt+1) ) &
3638                                 / ( rrtm_play(0,nzt+8) - rrtm_play(0,nzt+1) ) &
3639                                 * ( rrtm_play(0,k)     - rrtm_play(0,nzt+1) )
3640
3641                   rrtm_h2ovmr(0,k) = rrtm_h2ovmr(0,nzt+1)                     &
3642                              + ( rrtm_h2ovmr(0,nzt+8) - rrtm_h2ovmr(0,nzt+1) )&
3643                              / ( rrtm_play(0,nzt+8)   - rrtm_play(0,nzt+1)   )&
3644                              * ( rrtm_play(0,k)       - rrtm_play(0,nzt+1) )
3645
3646                ENDDO
3647
3648!--             Linear interpolate to zw grid
3649                DO k = nzb+2, nzt+8
3650                   rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k) -     &
3651                                      rrtm_tlay(0,k-1))                        &
3652                                      / ( rrtm_play(0,k) - rrtm_play(0,k-1) )  &
3653                                      * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
3654                ENDDO
3655
3656
3657!
3658!--             Calculate liquid water path and cloud fraction for each column.
3659!--             Note that LWP is required in g/m2 instead of kg/kg m.
3660                rrtm_cldfr  = 0.0_wp
3661                rrtm_reliq  = 0.0_wp
3662                rrtm_cliqwp = 0.0_wp
3663                rrtm_icld   = 0
3664
3665                IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
3666                   DO k = nzb+1, nzt+1
3667                      rrtm_cliqwp(0,k) =  ql(k,j,i) * 1000.0_wp *              &
3668                                          (rrtm_plev(0,k) - rrtm_plev(0,k+1))  &
3669                                          * 100.0_wp / g 
3670
3671                      IF ( rrtm_cliqwp(0,k) > 0.0_wp )  THEN
3672                         rrtm_cldfr(0,k) = 1.0_wp
3673                         IF ( rrtm_icld == 0 )  rrtm_icld = 1
3674
3675!
3676!--                      Calculate cloud droplet effective radius
3677                         IF ( bulk_cloud_model )  THEN
3678!
3679!--                         Calculete effective droplet radius. In case of using
3680!--                         cloud_scheme = 'morrison' and a non reasonable number
3681!--                         of cloud droplets the inital aerosol number 
3682!--                         concentration is considered.
3683                            IF ( microphysics_morrison )  THEN
3684                               IF ( nc(k,j,i) > 1.0E-20_wp )  THEN
3685                                  nc_rad = nc(k,j,i)
3686                               ELSE
3687                                  nc_rad = na_init
3688                               ENDIF
3689                            ELSE
3690                               nc_rad = nc_const
3691                            ENDIF 
3692
3693                            rrtm_reliq(0,k) = 1.0E6_wp * ( 3.0_wp * ql(k,j,i)     &
3694                                              * rho_surface                       &
3695                                              / ( 4.0_wp * pi * nc_rad * rho_l )  &
3696                                              )**0.33333333333333_wp              &
3697                                              * EXP( LOG( sigma_gc )**2 )
3698
3699                         ELSEIF ( cloud_droplets )  THEN
3700                            number_of_particles = prt_count(k,j,i)
3701
3702                            IF (number_of_particles <= 0)  CYCLE
3703                            particles => grid_particles(k,j,i)%particles(1:number_of_particles)
3704                            s_r2 = 0.0_wp
3705                            s_r3 = 0.0_wp
3706
3707                            DO  n = 1, number_of_particles
3708                               IF ( particles(n)%particle_mask )  THEN
3709                                  s_r2 = s_r2 + particles(n)%radius**2 *       &
3710                                         particles(n)%weight_factor
3711                                  s_r3 = s_r3 + particles(n)%radius**3 *       &
3712                                         particles(n)%weight_factor
3713                               ENDIF
3714                            ENDDO
3715
3716                            IF ( s_r2 > 0.0_wp )  rrtm_reliq(0,k) = s_r3 / s_r2
3717
3718                         ENDIF
3719
3720!
3721!--                      Limit effective radius
3722                         IF ( rrtm_reliq(0,k) > 0.0_wp )  THEN
3723                            rrtm_reliq(0,k) = MAX(rrtm_reliq(0,k),2.5_wp)
3724                            rrtm_reliq(0,k) = MIN(rrtm_reliq(0,k),60.0_wp)
3725                        ENDIF
3726                      ENDIF
3727                   ENDDO
3728                ENDIF
3729
3730!
3731!--             Write surface emissivity and surface temperature at current
3732!--             surface element on RRTMG-shaped array.
3733!--             Please note, as RRTMG is a single column model, surface attributes
3734!--             are only obtained from horizontally aligned surfaces (for
3735!--             simplicity). Taking surface attributes from horizontal and
3736!--             vertical walls would lead to multiple solutions. 
3737!--             Moreover, for natural- and urban-type surfaces, several surface
3738!--             classes can exist at a surface element next to each other.
3739!--             To obtain bulk parameters, apply a weighted average for these
3740!--             surfaces.
3741                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
3742                   rrtm_emis = surf_lsm_h%frac(ind_veg_wall,m)  *              &
3743                               surf_lsm_h%emissivity(ind_veg_wall,m)  +        &
3744                               surf_lsm_h%frac(ind_pav_green,m) *              &
3745                               surf_lsm_h%emissivity(ind_pav_green,m) +        & 
3746                               surf_lsm_h%frac(ind_wat_win,m)   *              &
3747                               surf_lsm_h%emissivity(ind_wat_win,m)
3748                   rrtm_tsfc = surf_lsm_h%pt_surface(m) * exner(nzb)
3749                ENDDO             
3750                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
3751                   rrtm_emis = surf_usm_h%frac(ind_veg_wall,m)  *              &
3752                               surf_usm_h%emissivity(ind_veg_wall,m)  +        &
3753                               surf_usm_h%frac(ind_pav_green,m) *              &
3754                               surf_usm_h%emissivity(ind_pav_green,m) +        & 
3755                               surf_usm_h%frac(ind_wat_win,m)   *              &
3756                               surf_usm_h%emissivity(ind_wat_win,m)
3757                   rrtm_tsfc = surf_usm_h%pt_surface(m) * exner(nzb)
3758                ENDDO
3759!
3760!--             Obtain topography top index (lower bound of RRTMG)
3761                k_topo = get_topography_top_index_ji( j, i, 's' )
3762
3763                IF ( lw_radiation )  THEN
3764!
3765!--                Due to technical reasons, copy optical depth to dummy arguments
3766!--                which are allocated on the exact size as the rrtmg_lw is called.
3767!--                As one dimesion is allocated with zero size, compiler complains
3768!--                that rank of the array does not match that of the
3769!--                assumed-shaped arguments in the RRTMG library. In order to
3770!--                avoid this, write to dummy arguments and give pass the entire
3771!--                dummy array. Seems to be the only existing work-around. 
3772                   ALLOCATE( rrtm_lw_taucld_dum(1:nbndlw+1,0:0,k_topo+1:nzt_rad+1) )
3773                   ALLOCATE( rrtm_lw_tauaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndlw+1) )
3774
3775                   rrtm_lw_taucld_dum =                                        &
3776                               rrtm_lw_taucld(1:nbndlw+1,0:0,k_topo+1:nzt_rad+1)
3777                   rrtm_lw_tauaer_dum =                                        &
3778                               rrtm_lw_tauaer(0:0,k_topo+1:nzt_rad+1,1:nbndlw+1)
3779
3780                   CALL rrtmg_lw( 1,                                           &                                       
3781                                  nzt_rad-k_topo,                              &
3782                                  rrtm_icld,                                   &
3783                                  rrtm_idrv,                                   &
3784                                  rrtm_play(:,k_topo+1:nzt_rad+1),             &
3785                                  rrtm_plev(:,k_topo+1:nzt_rad+2),             &
3786                                  rrtm_tlay(:,k_topo+1:nzt_rad+1),             &
3787                                  rrtm_tlev(:,k_topo+1:nzt_rad+2),             &
3788                                  rrtm_tsfc,                                   &
3789                                  rrtm_h2ovmr(:,k_topo+1:nzt_rad+1),           &
3790                                  rrtm_o3vmr(:,k_topo+1:nzt_rad+1),            &
3791                                  rrtm_co2vmr(:,k_topo+1:nzt_rad+1),           &
3792                                  rrtm_ch4vmr(:,k_topo+1:nzt_rad+1),           &
3793                                  rrtm_n2ovmr(:,k_topo+1:nzt_rad+1),           &
3794                                  rrtm_o2vmr(:,k_topo+1:nzt_rad+1),            &
3795                                  rrtm_cfc11vmr(:,k_topo+1:nzt_rad+1),         &
3796                                  rrtm_cfc12vmr(:,k_topo+1:nzt_rad+1),         &
3797                                  rrtm_cfc22vmr(:,k_topo+1:nzt_rad+1),         &
3798                                  rrtm_ccl4vmr(:,k_topo+1:nzt_rad+1),          &
3799                                  rrtm_emis,                                   &
3800                                  rrtm_inflglw,                                &
3801                                  rrtm_iceflglw,                               &
3802                                  rrtm_liqflglw,                               &
3803                                  rrtm_cldfr(:,k_topo+1:nzt_rad+1),            &
3804                                  rrtm_lw_taucld_dum,                          &
3805                                  rrtm_cicewp(:,k_topo+1:nzt_rad+1),           &
3806                                  rrtm_cliqwp(:,k_topo+1:nzt_rad+1),           &
3807                                  rrtm_reice(:,k_topo+1:nzt_rad+1),            & 
3808                                  rrtm_reliq(:,k_topo+1:nzt_rad+1),            &
3809                                  rrtm_lw_tauaer_dum,                          &
3810                                  rrtm_lwuflx(:,k_topo:nzt_rad+1),             &
3811                                  rrtm_lwdflx(:,k_topo:nzt_rad+1),             &
3812                                  rrtm_lwhr(:,k_topo+1:nzt_rad+1),             &
3813                                  rrtm_lwuflxc(:,k_topo:nzt_rad+1),            &
3814                                  rrtm_lwdflxc(:,k_topo:nzt_rad+1),            &
3815                                  rrtm_lwhrc(:,k_topo+1:nzt_rad+1),            &
3816                                  rrtm_lwuflx_dt(:,k_topo:nzt_rad+1),          &
3817                                  rrtm_lwuflxc_dt(:,k_topo:nzt_rad+1) )
3818
3819                   DEALLOCATE ( rrtm_lw_taucld_dum )
3820                   DEALLOCATE ( rrtm_lw_tauaer_dum )
3821!
3822!--                Save fluxes
3823                   DO k = k_topo, nzt+1
3824                      rad_lw_in(k,j,i)  = rrtm_lwdflx(0,k)
3825                      rad_lw_out(k,j,i) = rrtm_lwuflx(0,k)
3826                   ENDDO
3827
3828!
3829!--                Save heating rates (convert from K/d to K/h)
3830                   DO k = k_topo+1, nzt+1
3831                      rad_lw_hr(k,j,i)     = rrtm_lwhr(0,k-k_topo)  * d_hours_day
3832                      rad_lw_cs_hr(k,j,i)  = rrtm_lwhrc(0,k-k_topo) * d_hours_day
3833                   ENDDO
3834
3835!
3836!--                Save surface radiative fluxes and change in LW heating rate
3837!--                onto respective surface elements
3838!--                Horizontal surfaces
3839                   DO  m = surf_lsm_h%start_index(j,i),                        &
3840                           surf_lsm_h%end_index(j,i)
3841                      surf_lsm_h%rad_lw_in(m)           = rrtm_lwdflx(0,k_topo)
3842                      surf_lsm_h%rad_lw_out(m)          = rrtm_lwuflx(0,k_topo)
3843                      surf_lsm_h%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k_topo)
3844                   ENDDO             
3845                   DO  m = surf_usm_h%start_index(j,i),                        &
3846                           surf_usm_h%end_index(j,i)
3847                      surf_usm_h%rad_lw_in(m)           = rrtm_lwdflx(0,k_topo)
3848                      surf_usm_h%rad_lw_out(m)          = rrtm_lwuflx(0,k_topo)
3849                      surf_usm_h%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k_topo)
3850                   ENDDO 
3851!
3852!--                Vertical surfaces. Fluxes are obtain at vertical level of the
3853!--                respective surface element
3854                   DO  l = 0, 3
3855                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
3856                              surf_lsm_v(l)%end_index(j,i)
3857                         k                                    = surf_lsm_v(l)%k(m)
3858                         surf_lsm_v(l)%rad_lw_in(m)           = rrtm_lwdflx(0,k)
3859                         surf_lsm_v(l)%rad_lw_out(m)          = rrtm_lwuflx(0,k)
3860                         surf_lsm_v(l)%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k)
3861                      ENDDO             
3862                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
3863                              surf_usm_v(l)%end_index(j,i)
3864                         k                                    = surf_usm_v(l)%k(m)
3865                         surf_usm_v(l)%rad_lw_in(m)           = rrtm_lwdflx(0,k)
3866                         surf_usm_v(l)%rad_lw_out(m)          = rrtm_lwuflx(0,k)
3867                         surf_usm_v(l)%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k)
3868                      ENDDO 
3869                   ENDDO
3870
3871                ENDIF
3872
3873                IF ( sw_radiation .AND. sun_up )  THEN
3874!
3875!--                Get albedo for direct/diffusive long/shortwave radiation at
3876!--                current (y,x)-location from surface variables.
3877!--                Only obtain it from horizontal surfaces, as RRTMG is a single
3878!--                column model
3879!--                (Please note, only one loop will entered, controlled by
3880!--                start-end index.)
3881                   DO  m = surf_lsm_h%start_index(j,i),                        &
3882                           surf_lsm_h%end_index(j,i)
3883                      rrtm_asdir(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3884                                            surf_lsm_h%rrtm_asdir(:,m) )
3885                      rrtm_asdif(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3886                                            surf_lsm_h%rrtm_asdif(:,m) )
3887                      rrtm_aldir(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3888                                            surf_lsm_h%rrtm_aldir(:,m) )
3889                      rrtm_aldif(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3890                                            surf_lsm_h%rrtm_aldif(:,m) )
3891                   ENDDO             
3892                   DO  m = surf_usm_h%start_index(j,i),                        &
3893                           surf_usm_h%end_index(j,i)
3894                      rrtm_asdir(1)  = SUM( surf_usm_h%frac(:,m) *             &
3895                                            surf_usm_h%rrtm_asdir(:,m) )
3896                      rrtm_asdif(1)  = SUM( surf_usm_h%frac(:,m) *             &
3897                                            surf_usm_h%rrtm_asdif(:,m) )
3898                      rrtm_aldir(1)  = SUM( surf_usm_h%frac(:,m) *             &
3899                                            surf_usm_h%rrtm_aldir(:,m) )
3900                      rrtm_aldif(1)  = SUM( surf_usm_h%frac(:,m) *             &
3901                                            surf_usm_h%rrtm_aldif(:,m) )
3902                   ENDDO
3903!
3904!--                Due to technical reasons, copy optical depths and other
3905!--                to dummy arguments which are allocated on the exact size as the
3906!--                rrtmg_sw is called.
3907!--                As one dimesion is allocated with zero size, compiler complains
3908!--                that rank of the array does not match that of the
3909!--                assumed-shaped arguments in the RRTMG library. In order to
3910!--                avoid this, write to dummy arguments and give pass the entire
3911!--                dummy array. Seems to be the only existing work-around. 
3912                   ALLOCATE( rrtm_sw_taucld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3913                   ALLOCATE( rrtm_sw_ssacld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3914                   ALLOCATE( rrtm_sw_asmcld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3915                   ALLOCATE( rrtm_sw_fsfcld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3916                   ALLOCATE( rrtm_sw_tauaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3917                   ALLOCATE( rrtm_sw_ssaaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3918                   ALLOCATE( rrtm_sw_asmaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3919                   ALLOCATE( rrtm_sw_ecaer_dum(0:0,k_topo+1:nzt_rad+1,1:naerec+1)  )
3920     
3921                   rrtm_sw_taucld_dum = rrtm_sw_taucld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3922                   rrtm_sw_ssacld_dum = rrtm_sw_ssacld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3923                   rrtm_sw_asmcld_dum = rrtm_sw_asmcld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3924                   rrtm_sw_fsfcld_dum = rrtm_sw_fsfcld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3925                   rrtm_sw_tauaer_dum = rrtm_sw_tauaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3926                   rrtm_sw_ssaaer_dum = rrtm_sw_ssaaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3927                   rrtm_sw_asmaer_dum = rrtm_sw_asmaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3928                   rrtm_sw_ecaer_dum  = rrtm_sw_ecaer(0:0,k_topo+1:nzt_rad+1,1:naerec+1)
3929
3930                   CALL rrtmg_sw( 1,                                           &
3931                                  nzt_rad-k_topo,                              &
3932                                  rrtm_icld,                                   &
3933                                  rrtm_iaer,                                   &
3934                                  rrtm_play(:,k_topo+1:nzt_rad+1),             &
3935                                  rrtm_plev(:,k_topo+1:nzt_rad+2),             &
3936                                  rrtm_tlay(:,k_topo+1:nzt_rad+1),             &
3937                                  rrtm_tlev(:,k_topo+1:nzt_rad+2),             &
3938                                  rrtm_tsfc,                                   &
3939                                  rrtm_h2ovmr(:,k_topo+1:nzt_rad+1),           &                               
3940                                  rrtm_o3vmr(:,k_topo+1:nzt_rad+1),            &       
3941                                  rrtm_co2vmr(:,k_topo+1:nzt_rad+1),           &
3942                                  rrtm_ch4vmr(:,k_topo+1:nzt_rad+1),           &
3943                                  rrtm_n2ovmr(:,k_topo+1:nzt_rad+1),           &
3944                                  rrtm_o2vmr(:,k_topo+1:nzt_rad+1),            &
3945                                  rrtm_asdir,                                  & 
3946                                  rrtm_asdif,                                  &
3947                                  rrtm_aldir,                                  &
3948                                  rrtm_aldif,                                  &
3949                                  zenith,                                      &
3950                                  0.0_wp,                                      &
3951                                  day_of_year,                                 &
3952                                  solar_constant,                              &
3953                                  rrtm_inflgsw,                                &
3954                                  rrtm_iceflgsw,                               &
3955                                  rrtm_liqflgsw,                               &
3956                                  rrtm_cldfr(:,k_topo+1:nzt_rad+1),            &
3957                                  rrtm_sw_taucld_dum,                          &
3958                                  rrtm_sw_ssacld_dum,                          &
3959                                  rrtm_sw_asmcld_dum,                          &
3960                                  rrtm_sw_fsfcld_dum,                          &
3961                                  rrtm_cicewp(:,k_topo+1:nzt_rad+1),           &
3962                                  rrtm_cliqwp(:,k_topo+1:nzt_rad+1),           &
3963                                  rrtm_reice(:,k_topo+1:nzt_rad+1),            &
3964                                  rrtm_reliq(:,k_topo+1:nzt_rad+1),            &
3965                                  rrtm_sw_tauaer_dum,                          &
3966                                  rrtm_sw_ssaaer_dum,                          &
3967                                  rrtm_sw_asmaer_dum,                          &
3968                                  rrtm_sw_ecaer_dum,                           &
3969                                  rrtm_swuflx(:,k_topo:nzt_rad+1),             & 
3970                                  rrtm_swdflx(:,k_topo:nzt_rad+1),             & 
3971                                  rrtm_swhr(:,k_topo+1:nzt_rad+1),             & 
3972                                  rrtm_swuflxc(:,k_topo:nzt_rad+1),            & 
3973                                  rrtm_swdflxc(:,k_topo:nzt_rad+1),            &
3974                                  rrtm_swhrc(:,k_topo+1:nzt_rad+1),            &
3975                                  rrtm_dirdflux(:,k_topo:nzt_rad+1),           &
3976                                  rrtm_difdflux(:,k_topo:nzt_rad+1) )
3977
3978                   DEALLOCATE( rrtm_sw_taucld_dum )
3979                   DEALLOCATE( rrtm_sw_ssacld_dum )
3980                   DEALLOCATE( rrtm_sw_asmcld_dum )
3981                   DEALLOCATE( rrtm_sw_fsfcld_dum )
3982                   DEALLOCATE( rrtm_sw_tauaer_dum )
3983                   DEALLOCATE( rrtm_sw_ssaaer_dum )
3984                   DEALLOCATE( rrtm_sw_asmaer_dum )
3985                   DEALLOCATE( rrtm_sw_ecaer_dum )
3986!
3987!--                Save fluxes
3988                   DO k = nzb, nzt+1
3989                      rad_sw_in(k,j,i)  = rrtm_swdflx(0,k)
3990                      rad_sw_out(k,j,i) = rrtm_swuflx(0,k)
3991                   ENDDO
3992!
3993!--                Save heating rates (convert from K/d to K/s)
3994                   DO k = nzb+1, nzt+1
3995                      rad_sw_hr(k,j,i)     = rrtm_swhr(0,k)  * d_hours_day
3996                      rad_sw_cs_hr(k,j,i)  = rrtm_swhrc(0,k) * d_hours_day
3997                   ENDDO
3998
3999!
4000!--                Save surface radiative fluxes onto respective surface elements
4001!--                Horizontal surfaces
4002                   DO  m = surf_lsm_h%start_index(j,i),                        &
4003                           surf_lsm_h%end_index(j,i)
4004                      surf_lsm_h%rad_sw_in(m)     = rrtm_swdflx(0,k_topo)
4005                      surf_lsm_h%rad_sw_out(m)    = rrtm_swuflx(0,k_topo)
4006                   ENDDO             
4007                   DO  m = surf_usm_h%start_index(j,i),                        &
4008                           surf_usm_h%end_index(j,i)
4009                      surf_usm_h%rad_sw_in(m)     = rrtm_swdflx(0,k_topo)
4010                      surf_usm_h%rad_sw_out(m)    = rrtm_swuflx(0,k_topo)
4011                   ENDDO 
4012!
4013!--                Vertical surfaces. Fluxes are obtain at respective vertical
4014!--                level of the surface element
4015                   DO  l = 0, 3
4016                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
4017                              surf_lsm_v(l)%end_index(j,i)
4018                         k                           = surf_lsm_v(l)%k(m)
4019                         surf_lsm_v(l)%rad_sw_in(m)  = rrtm_swdflx(0,k)
4020                         surf_lsm_v(l)%rad_sw_out(m) = rrtm_swuflx(0,k)
4021                      ENDDO             
4022                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
4023                              surf_usm_v(l)%end_index(j,i)
4024                         k                           = surf_usm_v(l)%k(m)
4025                         surf_usm_v(l)%rad_sw_in(m)  = rrtm_swdflx(0,k)
4026                         surf_usm_v(l)%rad_sw_out(m) = rrtm_swuflx(0,k)
4027                      ENDDO 
4028                   ENDDO
4029!
4030!--             Solar radiation is zero during night
4031                ELSE
4032                   rad_sw_in  = 0.0_wp
4033                   rad_sw_out = 0.0_wp
4034!--             !!!!!!!! ATTENSION !!!!!!!!!!!!!!!
4035!--             Surface radiative fluxes should be also set to zero here                 
4036!--                Save surface radiative fluxes onto respective surface elements
4037!--                Horizontal surfaces
4038                   DO  m = surf_lsm_h%start_index(j,i),                        &
4039                           surf_lsm_h%end_index(j,i)
4040                      surf_lsm_h%rad_sw_in(m)     = 0.0_wp
4041                      surf_lsm_h%rad_sw_out(m)    = 0.0_wp
4042                   ENDDO             
4043                   DO  m = surf_usm_h%start_index(j,i),                        &
4044                           surf_usm_h%end_index(j,i)
4045                      surf_usm_h%rad_sw_in(m)     = 0.0_wp
4046                      surf_usm_h%rad_sw_out(m)    = 0.0_wp
4047                   ENDDO 
4048!
4049!--                Vertical surfaces. Fluxes are obtain at respective vertical
4050!--                level of the surface element
4051                   DO  l = 0, 3
4052                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
4053                              surf_lsm_v(l)%end_index(j,i)
4054                         k                           = surf_lsm_v(l)%k(m)
4055                         surf_lsm_v(l)%rad_sw_in(m)  = 0.0_wp
4056                         surf_lsm_v(l)%rad_sw_out(m) = 0.0_wp
4057                      ENDDO             
4058                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
4059                              surf_usm_v(l)%end_index(j,i)
4060                         k                           = surf_usm_v(l)%k(m)
4061                         surf_usm_v(l)%rad_sw_in(m)  = 0.0_wp
4062                         surf_usm_v(l)%rad_sw_out(m) = 0.0_wp
4063                      ENDDO 
4064                   ENDDO
4065                ENDIF
4066
4067             ENDDO
4068          ENDDO
4069
4070       ENDIF
4071!
4072!--    Finally, calculate surface net radiation for surface elements.
4073       IF (  .NOT.  radiation_interactions  ) THEN
4074!--       First, for horizontal surfaces   
4075          DO  m = 1, surf_lsm_h%ns
4076             surf_lsm_h%rad_net(m) = surf_lsm_h%rad_sw_in(m)                   &
4077                                   - surf_lsm_h%rad_sw_out(m)                  &
4078                                   + surf_lsm_h%rad_lw_in(m)                   &
4079                                   - surf_lsm_h%rad_lw_out(m)
4080          ENDDO
4081          DO  m = 1, surf_usm_h%ns
4082             surf_usm_h%rad_net(m) = surf_usm_h%rad_sw_in(m)                   &
4083                                   - surf_usm_h%rad_sw_out(m)                  &
4084                                   + surf_usm_h%rad_lw_in(m)                   &
4085                                   - surf_usm_h%rad_lw_out(m)
4086          ENDDO
4087!
4088!--       Vertical surfaces.
4089!--       Todo: weight with azimuth and zenith angle according to their orientation!
4090          DO  l = 0, 3     
4091             DO  m = 1, surf_lsm_v(l)%ns
4092                surf_lsm_v(l)%rad_net(m) = surf_lsm_v(l)%rad_sw_in(m)          &
4093                                         - surf_lsm_v(l)%rad_sw_out(m)         &
4094                                         + surf_lsm_v(l)%rad_lw_in(m)          &
4095                                         - surf_lsm_v(l)%rad_lw_out(m)
4096             ENDDO
4097             DO  m = 1, surf_usm_v(l)%ns
4098                surf_usm_v(l)%rad_net(m) = surf_usm_v(l)%rad_sw_in(m)          &
4099                                         - surf_usm_v(l)%rad_sw_out(m)         &
4100                                         + surf_usm_v(l)%rad_lw_in(m)          &
4101                                         - surf_usm_v(l)%rad_lw_out(m)
4102             ENDDO
4103          ENDDO
4104       ENDIF
4105
4106
4107       CALL exchange_horiz( rad_lw_in,  nbgp )
4108       CALL exchange_horiz( rad_lw_out, nbgp )
4109       CALL exchange_horiz( rad_lw_hr,    nbgp )
4110       CALL exchange_horiz( rad_lw_cs_hr, nbgp )
4111
4112       CALL exchange_horiz( rad_sw_in,  nbgp )
4113       CALL exchange_horiz( rad_sw_out, nbgp ) 
4114       CALL exchange_horiz( rad_sw_hr,    nbgp )
4115       CALL exchange_horiz( rad_sw_cs_hr, nbgp )
4116
4117#endif
4118
4119    END SUBROUTINE radiation_rrtmg
4120
4121
4122!------------------------------------------------------------------------------!
4123! Description:
4124! ------------
4125!> Calculate the cosine of the zenith angle (variable is called zenith)
4126!------------------------------------------------------------------------------!
4127    SUBROUTINE calc_zenith
4128
4129       IMPLICIT NONE
4130
4131       REAL(wp) ::  declination,  & !< solar declination angle
4132                    hour_angle      !< solar hour angle
4133!
4134!--    Calculate current day and time based on the initial values and simulation
4135!--    time
4136       CALL calc_date_and_time
4137
4138!
4139!--    Calculate solar declination and hour angle   
4140       declination = ASIN( decl_1 * SIN(decl_2 * REAL(day_of_year, KIND=wp) - decl_3) )
4141       hour_angle  = 2.0_wp * pi * (time_utc / 86400.0_wp) + lon - pi
4142
4143!
4144!--    Calculate cosine of solar zenith angle
4145       zenith(0) = SIN(lat) * SIN(declination) + COS(lat) * COS(declination)   &
4146                                            * COS(hour_angle)
4147       zenith(0) = MAX(0.0_wp,zenith(0))
4148
4149!
4150!--    Calculate solar directional vector
4151       IF ( sun_direction )  THEN
4152
4153!
4154!--       Direction in longitudes equals to sin(solar_azimuth) * sin(zenith)
4155          sun_dir_lon(0) = -SIN(hour_angle) * COS(declination)
4156
4157!
4158!--       Direction in latitues equals to cos(solar_azimuth) * sin(zenith)
4159          sun_dir_lat(0) = SIN(declination) * COS(lat) - COS(hour_angle) &
4160                              * COS(declination) * SIN(lat)
4161       ENDIF
4162
4163!
4164!--    Check if the sun is up (otheriwse shortwave calculations can be skipped)
4165       IF ( zenith(0) > 0.0_wp )  THEN
4166          sun_up = .TRUE.
4167       ELSE
4168          sun_up = .FALSE.
4169       END IF
4170
4171    END SUBROUTINE calc_zenith
4172
4173#if defined ( __rrtmg ) && defined ( __netcdf )
4174!------------------------------------------------------------------------------!
4175! Description:
4176! ------------
4177!> Calculates surface albedo components based on Briegleb (1992) and
4178!> Briegleb et al. (1986)
4179!------------------------------------------------------------------------------!
4180    SUBROUTINE calc_albedo( surf )
4181
4182        IMPLICIT NONE
4183
4184        INTEGER(iwp)    ::  ind_type !< running index surface tiles
4185        INTEGER(iwp)    ::  m        !< running index surface elements
4186
4187        TYPE(surf_type) ::  surf !< treated surfaces
4188
4189        IF ( sun_up  .AND.  .NOT. average_radiation )  THEN
4190
4191           DO  m = 1, surf%ns
4192!
4193!--           Loop over surface elements
4194              DO  ind_type = 0, SIZE( surf%albedo_type, 1 ) - 1
4195           
4196!
4197!--              Ocean
4198                 IF ( surf%albedo_type(ind_type,m) == 1 )  THEN
4199                    surf%rrtm_aldir(ind_type,m) = 0.026_wp /                    &
4200                                                ( zenith(0)**1.7_wp + 0.065_wp )&
4201                                     + 0.15_wp * ( zenith(0) - 0.1_wp )         &
4202                                               * ( zenith(0) - 0.5_wp )         &
4203                                               * ( zenith(0) - 1.0_wp )
4204                    surf%rrtm_asdir(ind_type,m) = surf%rrtm_aldir(ind_type,m)
4205!
4206!--              Snow
4207                 ELSEIF ( surf%albedo_type(ind_type,m) == 16 )  THEN
4208                    IF ( zenith(0) < 0.5_wp )  THEN
4209                       surf%rrtm_aldir(ind_type,m) =                           &
4210                                 0.5_wp * ( 1.0_wp - surf%aldif(ind_type,m) )  &
4211                                        * ( 3.0_wp / ( 1.0_wp + 4.0_wp         &
4212                                        * zenith(0) ) ) - 1.0_wp
4213                       surf%rrtm_asdir(ind_type,m) =                           &
4214                                 0.5_wp * ( 1.0_wp - surf%asdif(ind_type,m) )  &
4215                                        * ( 3.0_wp / ( 1.0_wp + 4.0_wp         &
4216                                        * zenith(0) ) ) - 1.0_wp
4217
4218                       surf%rrtm_aldir(ind_type,m) =                           &
4219                                       MIN(0.98_wp, surf%rrtm_aldir(ind_type,m))
4220                       surf%rrtm_asdir(ind_type,m) =                           &
4221                                       MIN(0.98_wp, surf%rrtm_asdir(ind_type,m))
4222                    ELSE
4223                       surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4224                       surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4225                    ENDIF
4226!
4227!--              Sea ice
4228                 ELSEIF ( surf%albedo_type(ind_type,m) == 15 )  THEN
4229                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4230                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4231
4232!
4233!--              Asphalt
4234                 ELSEIF ( surf%albedo_type(ind_type,m) == 17 )  THEN
4235                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4236                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4237
4238
4239!
4240!--              Bare soil
4241                 ELSEIF ( surf%albedo_type(ind_type,m) == 18 )  THEN
4242                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4243                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4244
4245!
4246!--              Land surfaces
4247                 ELSE
4248                    SELECT CASE ( surf%albedo_type(ind_type,m) )
4249
4250!
4251!--                    Surface types with strong zenith dependence
4252                       CASE ( 1, 2, 3, 4, 11, 12, 13 )
4253                          surf%rrtm_aldir(ind_type,m) =                        &
4254                                surf%aldif(ind_type,m) * 1.4_wp /              &
4255                                           ( 1.0_wp + 0.8_wp * zenith(0) )
4256                          surf%rrtm_asdir(ind_type,m) =                        &
4257                                surf%asdif(ind_type,m) * 1.4_wp /              &
4258                                           ( 1.0_wp + 0.8_wp * zenith(0) )
4259!
4260!--                    Surface types with weak zenith dependence
4261                       CASE ( 5, 6, 7, 8, 9, 10, 14 )
4262                          surf%rrtm_aldir(ind_type,m) =                        &
4263                                surf%aldif(ind_type,m) * 1.1_wp /              &
4264                                           ( 1.0_wp + 0.2_wp * zenith(0) )
4265                          surf%rrtm_asdir(ind_type,m) =                        &
4266                                surf%asdif(ind_type,m) * 1.1_wp /              &
4267                                           ( 1.0_wp + 0.2_wp * zenith(0) )
4268
4269                       CASE DEFAULT
4270
4271                    END SELECT
4272                 ENDIF
4273!
4274!--              Diffusive albedo is taken from Table 2
4275                 surf%rrtm_aldif(ind_type,m) = surf%aldif(ind_type,m)
4276                 surf%rrtm_asdif(ind_type,m) = surf%asdif(ind_type,m)
4277              ENDDO
4278           ENDDO
4279!
4280!--     Set albedo in case of average radiation
4281        ELSEIF ( sun_up  .AND.  average_radiation )  THEN
4282           surf%rrtm_asdir = albedo_urb
4283           surf%rrtm_asdif = albedo_urb
4284           surf%rrtm_aldir = albedo_urb
4285           surf%rrtm_aldif = albedo_urb 
4286!
4287!--     Darkness
4288        ELSE
4289           surf%rrtm_aldir = 0.0_wp
4290           surf%rrtm_asdir = 0.0_wp
4291           surf%rrtm_aldif = 0.0_wp
4292           surf%rrtm_asdif = 0.0_wp
4293        ENDIF
4294
4295    END SUBROUTINE calc_albedo
4296
4297!------------------------------------------------------------------------------!
4298! Description:
4299! ------------
4300!> Read sounding data (pressure and temperature) from RADIATION_DATA.
4301!------------------------------------------------------------------------------!
4302    SUBROUTINE read_sounding_data
4303
4304       IMPLICIT NONE
4305
4306       INTEGER(iwp) :: id,           & !< NetCDF id of input file
4307                       id_dim_zrad,  & !< pressure level id in the NetCDF file
4308                       id_var,       & !< NetCDF variable id
4309                       k,            & !< loop index
4310                       nz_snd,       & !< number of vertical levels in the sounding data
4311                       nz_snd_start, & !< start vertical index for sounding data to be used
4312                       nz_snd_end      !< end vertical index for souding data to be used
4313
4314       REAL(wp) :: t_surface           !< actual surface temperature
4315
4316       REAL(wp), DIMENSION(:), ALLOCATABLE ::  hyp_snd_tmp, & !< temporary hydrostatic pressure profile (sounding)
4317                                               t_snd_tmp      !< temporary temperature profile (sounding)
4318
4319!
4320!--    In case of updates, deallocate arrays first (sufficient to check one
4321!--    array as the others are automatically allocated). This is required
4322!--    because nzt_rad might change during the update
4323       IF ( ALLOCATED ( hyp_snd ) )  THEN
4324          DEALLOCATE( hyp_snd )
4325          DEALLOCATE( t_snd )
4326          DEALLOCATE ( rrtm_play )
4327          DEALLOCATE ( rrtm_plev )
4328          DEALLOCATE ( rrtm_tlay )
4329          DEALLOCATE ( rrtm_tlev )
4330
4331          DEALLOCATE ( rrtm_cicewp )
4332          DEALLOCATE ( rrtm_cldfr )
4333          DEALLOCATE ( rrtm_cliqwp )
4334          DEALLOCATE ( rrtm_reice )
4335          DEALLOCATE ( rrtm_reliq )
4336          DEALLOCATE ( rrtm_lw_taucld )
4337          DEALLOCATE ( rrtm_lw_tauaer )
4338
4339          DEALLOCATE ( rrtm_lwdflx  )
4340          DEALLOCATE ( rrtm_lwdflxc )
4341          DEALLOCATE ( rrtm_lwuflx  )
4342          DEALLOCATE ( rrtm_lwuflxc )
4343          DEALLOCATE ( rrtm_lwuflx_dt )
4344          DEALLOCATE ( rrtm_lwuflxc_dt )
4345          DEALLOCATE ( rrtm_lwhr  )
4346          DEALLOCATE ( rrtm_lwhrc )
4347
4348          DEALLOCATE ( rrtm_sw_taucld )
4349          DEALLOCATE ( rrtm_sw_ssacld )
4350          DEALLOCATE ( rrtm_sw_asmcld )
4351          DEALLOCATE ( rrtm_sw_fsfcld )
4352          DEALLOCATE ( rrtm_sw_tauaer )
4353          DEALLOCATE ( rrtm_sw_ssaaer )
4354          DEALLOCATE ( rrtm_sw_asmaer ) 
4355          DEALLOCATE ( rrtm_sw_ecaer )   
4356 
4357          DEALLOCATE ( rrtm_swdflx  )
4358          DEALLOCATE ( rrtm_swdflxc )
4359          DEALLOCATE ( rrtm_swuflx  )
4360          DEALLOCATE ( rrtm_swuflxc )
4361          DEALLOCATE ( rrtm_swhr  )
4362          DEALLOCATE ( rrtm_swhrc )
4363          DEALLOCATE ( rrtm_dirdflux )
4364          DEALLOCATE ( rrtm_difdflux )
4365
4366       ENDIF
4367
4368!
4369!--    Open file for reading
4370       nc_stat = NF90_OPEN( rrtm_input_file, NF90_NOWRITE, id )
4371       CALL netcdf_handle_error_rad( 'read_sounding_data', 549 )
4372
4373!
4374!--    Inquire dimension of z axis and save in nz_snd
4375       nc_stat = NF90_INQ_DIMID( id, "Pressure", id_dim_zrad )
4376       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim_zrad, len = nz_snd )
4377       CALL netcdf_handle_error_rad( 'read_sounding_data', 551 )
4378
4379!
4380! !--    Allocate temporary array for storing pressure data
4381       ALLOCATE( hyp_snd_tmp(1:nz_snd) )
4382       hyp_snd_tmp = 0.0_wp
4383
4384
4385!--    Read pressure from file
4386       nc_stat = NF90_INQ_VARID( id, "Pressure", id_var )
4387       nc_stat = NF90_GET_VAR( id, id_var, hyp_snd_tmp(:), start = (/1/),      &
4388                               count = (/nz_snd/) )
4389       CALL netcdf_handle_error_rad( 'read_sounding_data', 552 )
4390
4391!
4392!--    Allocate temporary array for storing temperature data
4393       ALLOCATE( t_snd_tmp(1:nz_snd) )
4394       t_snd_tmp = 0.0_wp
4395
4396!
4397!--    Read temperature from file
4398       nc_stat = NF90_INQ_VARID( id, "ReferenceTemperature", id_var )
4399       nc_stat = NF90_GET_VAR( id, id_var, t_snd_tmp(:), start = (/1/),        &
4400                               count = (/nz_snd/) )
4401       CALL netcdf_handle_error_rad( 'read_sounding_data', 553 )
4402
4403!
4404!--    Calculate start of sounding data
4405       nz_snd_start = nz_snd + 1
4406       nz_snd_end   = nz_snd + 1
4407
4408!
4409!--    Start filling vertical dimension at 10hPa above the model domain (hyp is
4410!--    in Pa, hyp_snd in hPa).
4411       DO  k = 1, nz_snd
4412          IF ( hyp_snd_tmp(k) < ( hyp(nzt+1) - 1000.0_wp) * 0.01_wp )  THEN
4413             nz_snd_start = k
4414             EXIT
4415          END IF
4416       END DO
4417
4418       IF ( nz_snd_start <= nz_snd )  THEN
4419          nz_snd_end = nz_snd
4420       END IF
4421
4422
4423!
4424!--    Calculate of total grid points for RRTMG calculations
4425       nzt_rad = nzt + nz_snd_end - nz_snd_start + 1
4426
4427!
4428!--    Save data above LES domain in hyp_snd, t_snd
4429       ALLOCATE( hyp_snd(nzb+1:nzt_rad) )
4430       ALLOCATE( t_snd(nzb+1:nzt_rad)   )
4431       hyp_snd = 0.0_wp
4432       t_snd = 0.0_wp
4433
4434       hyp_snd(nzt+2:nzt_rad) = hyp_snd_tmp(nz_snd_start+1:nz_snd_end)
4435       t_snd(nzt+2:nzt_rad)   = t_snd_tmp(nz_snd_start+1:nz_snd_end)
4436
4437       nc_stat = NF90_CLOSE( id )
4438
4439!
4440!--    Calculate pressure levels on zu and zw grid. Sounding data is added at
4441!--    top of the LES domain. This routine does not consider horizontal or
4442!--    vertical variability of pressure and temperature
4443       ALLOCATE ( rrtm_play(0:0,nzb+1:nzt_rad+1)   )
4444       ALLOCATE ( rrtm_plev(0:0,nzb+1:nzt_rad+2)   )
4445
4446       t_surface = pt_surface * exner(nzb)
4447       DO k = nzb+1, nzt+1
4448          rrtm_play(0,k) = hyp(k) * 0.01_wp
4449          rrtm_plev(0,k) = barometric_formula(zw(k-1),                         &
4450                              pt_surface * exner(nzb), &
4451                              surface_pressure )
4452       ENDDO
4453
4454       DO k = nzt+2, nzt_rad
4455          rrtm_play(0,k) = hyp_snd(k)
4456          rrtm_plev(0,k) = 0.5_wp * ( rrtm_play(0,k) + rrtm_play(0,k-1) )
4457       ENDDO
4458       rrtm_plev(0,nzt_rad+1) = MAX( 0.5 * hyp_snd(nzt_rad),                   &
4459                                   1.5 * hyp_snd(nzt_rad)                      &
4460                                 - 0.5 * hyp_snd(nzt_rad-1) )
4461       rrtm_plev(0,nzt_rad+2)  = MIN( 1.0E-4_wp,                               &
4462                                      0.25_wp * rrtm_plev(0,nzt_rad+1) )
4463
4464       rrtm_play(0,nzt_rad+1) = 0.5 * rrtm_plev(0,nzt_rad+1)
4465
4466!
4467!--    Calculate temperature/humidity levels at top of the LES domain.
4468!--    Currently, the temperature is taken from sounding data (might lead to a
4469!--    temperature jump at interface. To do: Humidity is currently not
4470!--    calculated above the LES domain.
4471       ALLOCATE ( rrtm_tlay(0:0,nzb+1:nzt_rad+1)   )
4472       ALLOCATE ( rrtm_tlev(0:0,nzb+1:nzt_rad+2)   )
4473
4474       DO k = nzt+8, nzt_rad
4475          rrtm_tlay(0,k)   = t_snd(k)
4476       ENDDO
4477       rrtm_tlay(0,nzt_rad+1) = 2.0_wp * rrtm_tlay(0,nzt_rad)                  &
4478                                - rrtm_tlay(0,nzt_rad-1)
4479       DO k = nzt+9, nzt_rad+1
4480          rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k)                &
4481                             - rrtm_tlay(0,k-1))                               &
4482                             / ( rrtm_play(0,k) - rrtm_play(0,k-1) )           &
4483                             * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
4484       ENDDO
4485
4486       rrtm_tlev(0,nzt_rad+2)   = 2.0_wp * rrtm_tlay(0,nzt_rad+1)              &
4487                                  - rrtm_tlev(0,nzt_rad)
4488!
4489!--    Allocate remaining RRTMG arrays
4490       ALLOCATE ( rrtm_cicewp(0:0,nzb+1:nzt_rad+1) )
4491       ALLOCATE ( rrtm_cldfr(0:0,nzb+1:nzt_rad+1) )
4492       ALLOCATE ( rrtm_cliqwp(0:0,nzb+1:nzt_rad+1) )
4493       ALLOCATE ( rrtm_reice(0:0,nzb+1:nzt_rad+1) )
4494       ALLOCATE ( rrtm_reliq(0:0,nzb+1:nzt_rad+1) )
4495       ALLOCATE ( rrtm_lw_taucld(1:nbndlw+1,0:0,nzb+1:nzt_rad+1) )
4496       ALLOCATE ( rrtm_lw_tauaer(0:0,nzb+1:nzt_rad+1,1:nbndlw+1) )
4497       ALLOCATE ( rrtm_sw_taucld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4498       ALLOCATE ( rrtm_sw_ssacld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4499       ALLOCATE ( rrtm_sw_asmcld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4500       ALLOCATE ( rrtm_sw_fsfcld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4501       ALLOCATE ( rrtm_sw_tauaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) )
4502       ALLOCATE ( rrtm_sw_ssaaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) )
4503       ALLOCATE ( rrtm_sw_asmaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) ) 
4504       ALLOCATE ( rrtm_sw_ecaer(0:0,nzb+1:nzt_rad+1,1:naerec+1) )   
4505
4506!
4507!--    The ice phase is currently not considered in PALM
4508       rrtm_cicewp = 0.0_wp
4509       rrtm_reice  = 0.0_wp
4510
4511!
4512!--    Set other parameters (move to NAMELIST parameters in the future)
4513       rrtm_lw_tauaer = 0.0_wp
4514       rrtm_lw_taucld = 0.0_wp
4515       rrtm_sw_taucld = 0.0_wp
4516       rrtm_sw_ssacld = 0.0_wp
4517       rrtm_sw_asmcld = 0.0_wp
4518       rrtm_sw_fsfcld = 0.0_wp
4519       rrtm_sw_tauaer = 0.0_wp
4520       rrtm_sw_ssaaer = 0.0_wp
4521       rrtm_sw_asmaer = 0.0_wp
4522       rrtm_sw_ecaer  = 0.0_wp
4523
4524
4525       ALLOCATE ( rrtm_swdflx(0:0,nzb:nzt_rad+1)  )
4526       ALLOCATE ( rrtm_swuflx(0:0,nzb:nzt_rad+1)  )
4527       ALLOCATE ( rrtm_swhr(0:0,nzb+1:nzt_rad+1)  )
4528       ALLOCATE ( rrtm_swuflxc(0:0,nzb:nzt_rad+1) )
4529       ALLOCATE ( rrtm_swdflxc(0:0,nzb:nzt_rad+1) )
4530       ALLOCATE ( rrtm_swhrc(0:0,nzb+1:nzt_rad+1) )
4531       ALLOCATE ( rrtm_dirdflux(0:0,nzb:nzt_rad+1) )
4532       ALLOCATE ( rrtm_difdflux(0:0,nzb:nzt_rad+1) )
4533
4534       rrtm_swdflx  = 0.0_wp
4535       rrtm_swuflx  = 0.0_wp
4536       rrtm_swhr    = 0.0_wp 
4537       rrtm_swuflxc = 0.0_wp
4538       rrtm_swdflxc = 0.0_wp
4539       rrtm_swhrc   = 0.0_wp
4540       rrtm_dirdflux = 0.0_wp
4541       rrtm_difdflux = 0.0_wp
4542
4543       ALLOCATE ( rrtm_lwdflx(0:0,nzb:nzt_rad+1)  )
4544       ALLOCATE ( rrtm_lwuflx(0:0,nzb:nzt_rad+1)  )
4545       ALLOCATE ( rrtm_lwhr(0:0,nzb+1:nzt_rad+1)  )
4546       ALLOCATE ( rrtm_lwuflxc(0:0,nzb:nzt_rad+1) )
4547       ALLOCATE ( rrtm_lwdflxc(0:0,nzb:nzt_rad+1) )
4548       ALLOCATE ( rrtm_lwhrc(0:0,nzb+1:nzt_rad+1) )
4549
4550       rrtm_lwdflx  = 0.0_wp
4551       rrtm_lwuflx  = 0.0_wp
4552       rrtm_lwhr    = 0.0_wp 
4553       rrtm_lwuflxc = 0.0_wp
4554       rrtm_lwdflxc = 0.0_wp
4555       rrtm_lwhrc   = 0.0_wp
4556
4557       ALLOCATE ( rrtm_lwuflx_dt(0:0,nzb:nzt_rad+1) )
4558       ALLOCATE ( rrtm_lwuflxc_dt(0:0,nzb:nzt_rad+1) )
4559
4560       rrtm_lwuflx_dt = 0.0_wp
4561       rrtm_lwuflxc_dt = 0.0_wp
4562
4563    END SUBROUTINE read_sounding_data
4564
4565
4566!------------------------------------------------------------------------------!
4567! Description:
4568! ------------
4569!> Read trace gas data from file
4570!------------------------------------------------------------------------------!
4571    SUBROUTINE read_trace_gas_data
4572
4573       USE rrsw_ncpar
4574
4575       IMPLICIT NONE
4576
4577       INTEGER(iwp), PARAMETER :: num_trace_gases = 10 !< number of trace gases (absorbers)
4578
4579       CHARACTER(LEN=5), DIMENSION(num_trace_gases), PARAMETER ::              & !< trace gas names
4580           trace_names = (/'O3   ', 'CO2  ', 'CH4  ', 'N2O  ', 'O2   ',        &
4581                           'CFC11', 'CFC12', 'CFC22', 'CCL4 ', 'H2O  '/)
4582
4583       INTEGER(iwp) :: id,     & !< NetCDF id
4584                       k,      & !< loop index
4585                       m,      & !< loop index
4586                       n,      & !< loop index
4587                       nabs,   & !< number of absorbers
4588                       np,     & !< number of pressure levels
4589                       id_abs, & !< NetCDF id of the respective absorber
4590                       id_dim, & !< NetCDF id of asborber's dimension
4591                       id_var    !< NetCDf id ot the absorber
4592
4593       REAL(wp) :: p_mls_l, p_mls_u, p_wgt_l, p_wgt_u, p_mls_m
4594
4595
4596       REAL(wp), DIMENSION(:), ALLOCATABLE   ::  p_mls,          & !< pressure levels for the absorbers
4597                                                 rrtm_play_tmp,  & !< temporary array for pressure zu-levels
4598                                                 rrtm_plev_tmp,  & !< temporary array for pressure zw-levels
4599                                                 trace_path_tmp    !< temporary array for storing trace gas path data
4600
4601       REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  trace_mls,      & !< array for storing the absorber amounts
4602                                                 trace_mls_path, & !< array for storing trace gas path data
4603                                                 trace_mls_tmp     !< temporary array for storing trace gas data
4604
4605
4606!
4607!--    In case of updates, deallocate arrays first (sufficient to check one
4608!--    array as the others are automatically allocated)
4609       IF ( ALLOCATED ( rrtm_o3vmr ) )  THEN
4610          DEALLOCATE ( rrtm_o3vmr  )
4611          DEALLOCATE ( rrtm_co2vmr )
4612          DEALLOCATE ( rrtm_ch4vmr )
4613          DEALLOCATE ( rrtm_n2ovmr )
4614          DEALLOCATE ( rrtm_o2vmr  )
4615          DEALLOCATE ( rrtm_cfc11vmr )
4616          DEALLOCATE ( rrtm_cfc12vmr )
4617          DEALLOCATE ( rrtm_cfc22vmr )
4618          DEALLOCATE ( rrtm_ccl4vmr  )
4619          DEALLOCATE ( rrtm_h2ovmr  )     
4620       ENDIF
4621
4622!
4623!--    Allocate trace gas profiles
4624       ALLOCATE ( rrtm_o3vmr(0:0,1:nzt_rad+1)  )
4625       ALLOCATE ( rrtm_co2vmr(0:0,1:nzt_rad+1) )
4626       ALLOCATE ( rrtm_ch4vmr(0:0,1:nzt_rad+1) )
4627       ALLOCATE ( rrtm_n2ovmr(0:0,1:nzt_rad+1) )
4628       ALLOCATE ( rrtm_o2vmr(0:0,1:nzt_rad+1)  )
4629       ALLOCATE ( rrtm_cfc11vmr(0:0,1:nzt_rad+1) )
4630       ALLOCATE ( rrtm_cfc12vmr(0:0,1:nzt_rad+1) )
4631       ALLOCATE ( rrtm_cfc22vmr(0:0,1:nzt_rad+1) )
4632       ALLOCATE ( rrtm_ccl4vmr(0:0,1:nzt_rad+1)  )
4633       ALLOCATE ( rrtm_h2ovmr(0:0,1:nzt_rad+1)  )
4634
4635!
4636!--    Open file for reading
4637       nc_stat = NF90_OPEN( rrtm_input_file, NF90_NOWRITE, id )
4638       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 549 )
4639!
4640!--    Inquire dimension ids and dimensions
4641       nc_stat = NF90_INQ_DIMID( id, "Pressure", id_dim )
4642       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4643       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim, len = np) 
4644       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4645
4646       nc_stat = NF90_INQ_DIMID( id, "Absorber", id_dim )
4647       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4648       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim, len = nabs ) 
4649       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4650   
4651
4652!
4653!--    Allocate pressure, and trace gas arrays     
4654       ALLOCATE( p_mls(1:np) )
4655       ALLOCATE( trace_mls(1:num_trace_gases,1:np) ) 
4656       ALLOCATE( trace_mls_tmp(1:nabs,1:np) ) 
4657
4658
4659       nc_stat = NF90_INQ_VARID( id, "Pressure", id_var )
4660       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4661       nc_stat = NF90_GET_VAR( id, id_var, p_mls )
4662       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4663
4664       nc_stat = NF90_INQ_VARID( id, "AbsorberAmountMLS", id_var )
4665       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4666       nc_stat = NF90_GET_VAR( id, id_var, trace_mls_tmp )
4667       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4668
4669
4670!
4671!--    Write absorber amounts (mls) to trace_mls
4672       DO n = 1, num_trace_gases
4673          CALL getAbsorberIndex( TRIM( trace_names(n) ), id_abs )
4674
4675          trace_mls(n,1:np) = trace_mls_tmp(id_abs,1:np)
4676
4677!
4678!--       Replace missing values by zero
4679          WHERE ( trace_mls(n,:) > 2.0_wp ) 
4680             trace_mls(n,:) = 0.0_wp
4681          END WHERE
4682       END DO
4683
4684       DEALLOCATE ( trace_mls_tmp )
4685
4686       nc_stat = NF90_CLOSE( id )
4687       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 551 )
4688
4689!
4690!--    Add extra pressure level for calculations of the trace gas paths
4691       ALLOCATE ( rrtm_play_tmp(1:nzt_rad+1) )
4692       ALLOCATE ( rrtm_plev_tmp(1:nzt_rad+2) )
4693
4694       rrtm_play_tmp(1:nzt_rad)   = rrtm_play(0,1:nzt_rad) 
4695       rrtm_plev_tmp(1:nzt_rad+1) = rrtm_plev(0,1:nzt_rad+1)
4696       rrtm_play_tmp(nzt_rad+1)   = rrtm_plev(0,nzt_rad+1) * 0.5_wp
4697       rrtm_plev_tmp(nzt_rad+2)   = MIN( 1.0E-4_wp, 0.25_wp                    &
4698                                         * rrtm_plev(0,nzt_rad+1) )
4699 
4700!
4701!--    Calculate trace gas path (zero at surface) with interpolation to the
4702!--    sounding levels
4703       ALLOCATE ( trace_mls_path(1:nzt_rad+2,1:num_trace_gases) )
4704
4705       trace_mls_path(nzb+1,:) = 0.0_wp
4706       
4707       DO k = nzb+2, nzt_rad+2
4708          DO m = 1, num_trace_gases
4709             trace_mls_path(k,m) = trace_mls_path(k-1,m)
4710
4711!
4712!--          When the pressure level is higher than the trace gas pressure
4713!--          level, assume that
4714             IF ( rrtm_plev_tmp(k-1) > p_mls(1) )  THEN             
4715               
4716                trace_mls_path(k,m) = trace_mls_path(k,m) + trace_mls(m,1)     &
4717                                      * ( rrtm_plev_tmp(k-1)                   &
4718                                          - MAX( p_mls(1), rrtm_plev_tmp(k) )  &
4719                                        ) / g
4720             ENDIF
4721
4722!
4723!--          Integrate for each sounding level from the contributing p_mls
4724!--          levels
4725             DO n = 2, np
4726!
4727!--             Limit p_mls so that it is within the model level
4728                p_mls_u = MIN( rrtm_plev_tmp(k-1),                             &
4729                          MAX( rrtm_plev_tmp(k), p_mls(n) ) )
4730                p_mls_l = MIN( rrtm_plev_tmp(k-1),                             &
4731                          MAX( rrtm_plev_tmp(k), p_mls(n-1) ) )
4732
4733                IF ( p_mls_l > p_mls_u )  THEN
4734
4735!
4736!--                Calculate weights for interpolation
4737                   p_mls_m = 0.5_wp * (p_mls_l + p_mls_u)
4738                   p_wgt_u = (p_mls(n-1) - p_mls_m) / (p_mls(n-1) - p_mls(n))
4739                   p_wgt_l = (p_mls_m - p_mls(n))   / (p_mls(n-1) - p_mls(n))
4740
4741!
4742!--                Add level to trace gas path
4743                   trace_mls_path(k,m) = trace_mls_path(k,m)                   &
4744                                         +  ( p_wgt_u * trace_mls(m,n)         &
4745                                            + p_wgt_l * trace_mls(m,n-1) )     &
4746                                         * (p_mls_l - p_mls_u) / g
4747                ENDIF
4748             ENDDO
4749
4750             IF ( rrtm_plev_tmp(k) < p_mls(np) )  THEN
4751                trace_mls_path(k,m) = trace_mls_path(k,m) + trace_mls(m,np)    &
4752                                      * ( MIN( rrtm_plev_tmp(k-1), p_mls(np) ) &
4753                                          - rrtm_plev_tmp(k)                   &
4754                                        ) / g 
4755             ENDIF 
4756          ENDDO
4757       ENDDO
4758
4759
4760!
4761!--    Prepare trace gas path profiles
4762       ALLOCATE ( trace_path_tmp(1:nzt_rad+1) )
4763
4764       DO m = 1, num_trace_gases
4765
4766          trace_path_tmp(1:nzt_rad+1) = ( trace_mls_path(2:nzt_rad+2,m)        &
4767                                       - trace_mls_path(1:nzt_rad+1,m) ) * g   &
4768                                       / ( rrtm_plev_tmp(1:nzt_rad+1)          &
4769                                       - rrtm_plev_tmp(2:nzt_rad+2) )
4770
4771!
4772!--       Save trace gas paths to the respective arrays
4773          SELECT CASE ( TRIM( trace_names(m) ) )
4774
4775             CASE ( 'O3' )
4776
4777                rrtm_o3vmr(0,:) = trace_path_tmp(:)
4778
4779             CASE ( 'CO2' )
4780
4781                rrtm_co2vmr(0,:) = trace_path_tmp(:)
4782
4783             CASE ( 'CH4' )
4784
4785                rrtm_ch4vmr(0,:) = trace_path_tmp(:)
4786
4787             CASE ( 'N2O' )
4788
4789                rrtm_n2ovmr(0,:) = trace_path_tmp(:)
4790
4791             CASE ( 'O2' )
4792
4793                rrtm_o2vmr(0,:) = trace_path_tmp(:)
4794
4795             CASE ( 'CFC11' )
4796
4797                rrtm_cfc11vmr(0,:) = trace_path_tmp(:)
4798
4799             CASE ( 'CFC12' )
4800
4801                rrtm_cfc12vmr(0,:) = trace_path_tmp(:)
4802
4803             CASE ( 'CFC22' )
4804
4805                rrtm_cfc22vmr(0,:) = trace_path_tmp(:)
4806
4807             CASE ( 'CCL4' )
4808
4809                rrtm_ccl4vmr(0,:) = trace_path_tmp(:)
4810
4811             CASE ( 'H2O' )
4812
4813                rrtm_h2ovmr(0,:) = trace_path_tmp(:)
4814               
4815             CASE DEFAULT
4816
4817          END SELECT
4818
4819       ENDDO
4820
4821       DEALLOCATE ( trace_path_tmp )
4822       DEALLOCATE ( trace_mls_path )
4823       DEALLOCATE ( rrtm_play_tmp )
4824       DEALLOCATE ( rrtm_plev_tmp )
4825       DEALLOCATE ( trace_mls )
4826       DEALLOCATE ( p_mls )
4827
4828    END SUBROUTINE read_trace_gas_data
4829
4830
4831    SUBROUTINE netcdf_handle_error_rad( routine_name, errno )
4832
4833       USE control_parameters,                                                 &
4834           ONLY:  message_string
4835
4836       USE NETCDF
4837
4838       USE pegrid
4839
4840       IMPLICIT NONE
4841
4842       CHARACTER(LEN=6) ::  message_identifier
4843       CHARACTER(LEN=*) ::  routine_name
4844
4845       INTEGER(iwp) ::  errno
4846
4847       IF ( nc_stat /= NF90_NOERR )  THEN
4848
4849          WRITE( message_identifier, '(''NC'',I4.4)' )  errno
4850          message_string = TRIM( NF90_STRERROR( nc_stat ) )
4851
4852          CALL message( routine_name, message_identifier, 2, 2, 0, 6, 1 )
4853
4854       ENDIF
4855
4856    END SUBROUTINE netcdf_handle_error_rad
4857#endif
4858
4859
4860!------------------------------------------------------------------------------!
4861! Description:
4862! ------------
4863!> Calculate temperature tendency due to radiative cooling/heating.
4864!> Cache-optimized version.
4865!------------------------------------------------------------------------------!
4866 SUBROUTINE radiation_tendency_ij ( i, j, tend )
4867
4868    IMPLICIT NONE
4869
4870    INTEGER(iwp) :: i, j, k !< loop indices
4871
4872    REAL(wp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg) :: tend !< pt tendency term
4873
4874    IF ( radiation_scheme == 'rrtmg' )  THEN
4875#if defined  ( __rrtmg )
4876!
4877!--    Calculate tendency based on heating rate
4878       DO k = nzb+1, nzt+1
4879          tend(k,j,i) = tend(k,j,i) + (rad_lw_hr(k,j,i) + rad_sw_hr(k,j,i))    &
4880                                         * d_exner(k) * d_seconds_hour
4881       ENDDO
4882#endif
4883    ENDIF
4884
4885    END SUBROUTINE radiation_tendency_ij
4886
4887
4888!------------------------------------------------------------------------------!
4889! Description:
4890! ------------
4891!> Calculate temperature tendency due to radiative cooling/heating.
4892!> Vector-optimized version
4893!------------------------------------------------------------------------------!
4894 SUBROUTINE radiation_tendency ( tend )
4895
4896    USE indices,                                                               &
4897        ONLY:  nxl, nxr, nyn, nys
4898
4899    IMPLICIT NONE
4900
4901    INTEGER(iwp) :: i, j, k !< loop indices
4902
4903    REAL(wp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg) :: tend !< pt tendency term
4904
4905    IF ( radiation_scheme == 'rrtmg' )  THEN
4906#if defined  ( __rrtmg )
4907!
4908!--    Calculate tendency based on heating rate
4909       DO  i = nxl, nxr
4910          DO  j = nys, nyn
4911             DO k = nzb+1, nzt+1
4912                tend(k,j,i) = tend(k,j,i) + ( rad_lw_hr(k,j,i)                 &
4913                                          +  rad_sw_hr(k,j,i) ) * d_exner(k)   &
4914                                          * d_seconds_hour
4915             ENDDO
4916          ENDDO
4917       ENDDO
4918#endif
4919    ENDIF
4920
4921
4922 END SUBROUTINE radiation_tendency
4923
4924!------------------------------------------------------------------------------!
4925! Description:
4926! ------------
4927!> This subroutine calculates interaction of the solar radiation
4928!> with urban and land surfaces and updates all surface heatfluxes.
4929!> It calculates also the required parameters for RRTMG lower BC.
4930!>
4931!> For more info. see Resler et al. 2017
4932!>
4933!> The new version 2.0 was radically rewriten, the discretization scheme
4934!> has been changed. This new version significantly improves effectivity
4935!> of the paralelization and the scalability of the model.
4936!------------------------------------------------------------------------------!
4937
4938 SUBROUTINE radiation_interaction
4939
4940     IMPLICIT NONE
4941
4942     INTEGER(iwp)                      :: i, j, k, kk, is, js, d, ku, refstep, m, mm, l, ll
4943     INTEGER(iwp)                      :: isurf, isurfsrc, isvf, icsf, ipcgb
4944     INTEGER(iwp)                      :: imrt, imrtf
4945     INTEGER(iwp)                      :: isd                !< solar direction number
4946     INTEGER(iwp)                      :: pc_box_dimshift    !< transform for best accuracy
4947     INTEGER(iwp), DIMENSION(0:3)      :: reorder = (/ 1, 0, 3, 2 /)
4948     
4949     REAL(wp), DIMENSION(3,3)          :: mrot               !< grid rotation matrix (zyx)
4950     REAL(wp), DIMENSION(3,0:nsurf_type):: vnorm             !< face direction normal vectors (zyx)
4951     REAL(wp), DIMENSION(3)            :: sunorig            !< grid rotated solar direction unit vector (zyx)
4952     REAL(wp), DIMENSION(3)            :: sunorig_grid       !< grid squashed solar direction unit vector (zyx)
4953     REAL(wp), DIMENSION(0:nsurf_type) :: costheta           !< direct irradiance factor of solar angle
4954     REAL(wp), DIMENSION(nzub:nzut)    :: pchf_prep          !< precalculated factor for canopy temperature tendency
4955     REAL(wp), PARAMETER               :: alpha = 0._wp      !< grid rotation (TODO: add to namelist or remove)
4956     REAL(wp)                          :: pc_box_area, pc_abs_frac, pc_abs_eff
4957     REAL(wp)                          :: asrc               !< area of source face
4958     REAL(wp)                          :: pcrad              !< irradiance from plant canopy
4959     REAL(wp)                          :: pabsswl  = 0.0_wp  !< total absorbed SW radiation energy in local processor (W)
4960     REAL(wp)                          :: pabssw   = 0.0_wp  !< total absorbed SW radiation energy in all processors (W)
4961     REAL(wp)                          :: pabslwl  = 0.0_wp  !< total absorbed LW radiation energy in local processor (W)
4962     REAL(wp)                          :: pabslw   = 0.0_wp  !< total absorbed LW radiation energy in all processors (W)
4963     REAL(wp)                          :: pemitlwl = 0.0_wp  !< total emitted LW radiation energy in all processors (W)
4964     REAL(wp)                          :: pemitlw  = 0.0_wp  !< total emitted LW radiation energy in all processors (W)
4965     REAL(wp)                          :: pinswl   = 0.0_wp  !< total received SW radiation energy in local processor (W)
4966     REAL(wp)                          :: pinsw    = 0.0_wp  !< total received SW radiation energy in all processor (W)
4967     REAL(wp)                          :: pinlwl   = 0.0_wp  !< total received LW radiation energy in local processor (W)
4968     REAL(wp)                          :: pinlw    = 0.0_wp  !< total received LW radiation energy in all processor (W)
4969     REAL(wp)                          :: emiss_sum_surfl    !< sum of emissisivity of surfaces in local processor
4970     REAL(wp)                          :: emiss_sum_surf     !< sum of emissisivity of surfaces in all processor
4971     REAL(wp)                          :: area_surfl         !< total area of surfaces in local processor
4972     REAL(wp)                          :: area_surf          !< total area of surfaces in all processor
4973     REAL(wp)                          :: area_hor           !< total horizontal area of domain in all processor
4974
4975
4976     IF ( plant_canopy )  THEN
4977         pchf_prep(:) = r_d * exner(nzub:nzut)                                 &
4978                     / (c_p * hyp(nzub:nzut) * dx*dy*dz(1)) !< equals to 1 / (rho * c_p * Vbox * T)
4979     ENDIF
4980
4981     sun_direction = .TRUE.
4982     CALL calc_zenith  !< required also for diffusion radiation
4983
4984!--     prepare rotated normal vectors and irradiance factor
4985     vnorm(1,:) = kdir(:)
4986     vnorm(2,:) = jdir(:)
4987     vnorm(3,:) = idir(:)
4988     mrot(1, :) = (/ 1._wp,  0._wp,      0._wp      /)
4989     mrot(2, :) = (/ 0._wp,  COS(alpha), SIN(alpha) /)
4990     mrot(3, :) = (/ 0._wp, -SIN(alpha), COS(alpha) /)
4991     sunorig = (/ zenith(0), sun_dir_lat, sun_dir_lon /)
4992     sunorig = MATMUL(mrot, sunorig)
4993     DO d = 0, nsurf_type
4994         costheta(d) = DOT_PRODUCT(sunorig, vnorm(:,d))
4995     ENDDO
4996
4997     IF ( zenith(0) > 0 )  THEN
4998!--      now we will "squash" the sunorig vector by grid box size in
4999!--      each dimension, so that this new direction vector will allow us
5000!--      to traverse the ray path within grid coordinates directly
5001         sunorig_grid = (/ sunorig(1)/dz(1), sunorig(2)/dy, sunorig(3)/dx /)
5002!--      sunorig_grid = sunorig_grid / norm2(sunorig_grid)
5003         sunorig_grid = sunorig_grid / SQRT(SUM(sunorig_grid**2))
5004
5005         IF ( npcbl > 0 )  THEN
5006!--         precompute effective box depth with prototype Leaf Area Density
5007            pc_box_dimshift = MAXLOC(ABS(sunorig), 1) - 1
5008            CALL box_absorb(CSHIFT((/dz(1),dy,dx/), pc_box_dimshift),       &
5009                                60, prototype_lad,                          &
5010                                CSHIFT(ABS(sunorig), pc_box_dimshift),      &
5011                                pc_box_area, pc_abs_frac)
5012            pc_box_area = pc_box_area * ABS(sunorig(pc_box_dimshift+1)      &
5013                          / sunorig(1))
5014            pc_abs_eff = LOG(1._wp - pc_abs_frac) / prototype_lad
5015         ENDIF
5016     ENDIF
5017
5018!--  if radiation scheme is not RRTMG, split diffusion and direct part of the solar downward radiation
5019!--  comming from radiation model and store it in 2D arrays
5020     IF (  radiation_scheme /= 'rrtmg'  )  CALL calc_diffusion_radiation
5021
5022!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5023!--     First pass: direct + diffuse irradiance + thermal
5024!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5025     surfinswdir   = 0._wp !nsurfl
5026     surfins       = 0._wp !nsurfl
5027     surfinl       = 0._wp !nsurfl
5028     surfoutsl(:)  = 0.0_wp !start-end
5029     surfoutll(:)  = 0.0_wp !start-end
5030     IF ( nmrtbl > 0 )  THEN
5031        mrtinsw(:) = 0._wp
5032        mrtinlw(:) = 0._wp
5033     ENDIF
5034     surfinlg(:)  = 0._wp !global
5035
5036
5037!--  Set up thermal radiation from surfaces
5038!--  emiss_surf is defined only for surfaces for which energy balance is calculated
5039!--  Workaround: reorder surface data type back on 1D array including all surfaces,
5040!--  which implies to reorder horizontal and vertical surfaces
5041!
5042!--  Horizontal walls
5043     mm = 1
5044     DO  i = nxl, nxr
5045        DO  j = nys, nyn
5046!--           urban
5047           DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
5048              surfoutll(mm) = SUM ( surf_usm_h%frac(:,m) *                  &
5049                                    surf_usm_h%emissivity(:,m) )            &
5050                                  * sigma_sb                                &
5051                                  * surf_usm_h%pt_surface(m)**4
5052              albedo_surf(mm) = SUM ( surf_usm_h%frac(:,m) *                &
5053                                      surf_usm_h%albedo(:,m) )
5054              emiss_surf(mm)  = SUM ( surf_usm_h%frac(:,m) *                &
5055                                      surf_usm_h%emissivity(:,m) )
5056              mm = mm + 1
5057           ENDDO
5058!--           land
5059           DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
5060              surfoutll(mm) = SUM ( surf_lsm_h%frac(:,m) *                  &
5061                                    surf_lsm_h%emissivity(:,m) )            &
5062                                  * sigma_sb                                &
5063                                  * surf_lsm_h%pt_surface(m)**4
5064              albedo_surf(mm) = SUM ( surf_lsm_h%frac(:,m) *                &
5065                                      surf_lsm_h%albedo(:,m) )
5066              emiss_surf(mm)  = SUM ( surf_lsm_h%frac(:,m) *                &
5067                                      surf_lsm_h%emissivity(:,m) )
5068              mm = mm + 1
5069           ENDDO
5070        ENDDO
5071     ENDDO
5072!
5073!--     Vertical walls
5074     DO  i = nxl, nxr
5075        DO  j = nys, nyn
5076           DO  ll = 0, 3
5077              l = reorder(ll)
5078!--              urban
5079              DO  m = surf_usm_v(l)%start_index(j,i),                       &
5080                      surf_usm_v(l)%end_index(j,i)
5081                 surfoutll(mm) = SUM ( surf_usm_v(l)%frac(:,m) *            &
5082                                       surf_usm_v(l)%emissivity(:,m) )      &
5083                                  * sigma_sb                                &
5084                                  * surf_usm_v(l)%pt_surface(m)**4
5085                 albedo_surf(mm) = SUM ( surf_usm_v(l)%frac(:,m) *          &
5086                                         surf_usm_v(l)%albedo(:,m) )
5087                 emiss_surf(mm)  = SUM ( surf_usm_v(l)%frac(:,m) *          &
5088                                         surf_usm_v(l)%emissivity(:,m) )
5089                 mm = mm + 1
5090              ENDDO
5091!--              land
5092              DO  m = surf_lsm_v(l)%start_index(j,i),                       &
5093                      surf_lsm_v(l)%end_index(j,i)
5094                 surfoutll(mm) = SUM ( surf_lsm_v(l)%frac(:,m) *            &
5095                                       surf_lsm_v(l)%emissivity(:,m) )      &
5096                                  * sigma_sb                                &
5097                                  * surf_lsm_v(l)%pt_surface(m)**4
5098                 albedo_surf(mm) = SUM ( surf_lsm_v(l)%frac(:,m) *          &
5099                                         surf_lsm_v(l)%albedo(:,m) )
5100                 emiss_surf(mm)  = SUM ( surf_lsm_v(l)%frac(:,m) *          &
5101                                         surf_lsm_v(l)%emissivity(:,m) )
5102                 mm = mm + 1
5103              ENDDO
5104           ENDDO
5105        ENDDO
5106     ENDDO
5107
5108#if defined( __parallel )
5109!--     might be optimized and gather only values relevant for current processor
5110     CALL MPI_AllGatherv(surfoutll, nsurfl, MPI_REAL, &
5111                         surfoutl, nsurfs, surfstart, MPI_REAL, comm2d, ierr) !nsurf global
5112     IF ( ierr /= 0 ) THEN
5113         WRITE(9,*) 'Error MPI_AllGatherv1:', ierr, SIZE(surfoutll), nsurfl, &
5114                     SIZE(surfoutl), nsurfs, surfstart
5115         FLUSH(9)
5116     ENDIF
5117#else
5118     surfoutl(:) = surfoutll(:) !nsurf global
5119#endif
5120
5121     IF ( surface_reflections)  THEN
5122        DO  isvf = 1, nsvfl
5123           isurf = svfsurf(1, isvf)
5124           k     = surfl(iz, isurf)
5125           j     = surfl(iy, isurf)
5126           i     = surfl(ix, isurf)
5127           isurfsrc = svfsurf(2, isvf)
5128!
5129!--        For surface-to-surface factors we calculate thermal radiation in 1st pass
5130           IF ( plant_lw_interact )  THEN
5131              surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * svf(2,isvf) * surfoutl(isurfsrc)
5132           ELSE
5133              surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * surfoutl(isurfsrc)
5134           ENDIF
5135        ENDDO
5136     ENDIF
5137!
5138!--  diffuse radiation using sky view factor
5139     DO isurf = 1, nsurfl
5140        j = surfl(iy, isurf)
5141        i = surfl(ix, isurf)
5142        surfinswdif(isurf) = rad_sw_in_diff(j,i) * skyvft(isurf)
5143        IF ( plant_lw_interact )  THEN
5144           surfinlwdif(isurf) = rad_lw_in_diff(j,i) * skyvft(isurf)
5145        ELSE
5146           surfinlwdif(isurf) = rad_lw_in_diff(j,i) * skyvf(isurf)
5147        ENDIF
5148     ENDDO
5149!
5150!--  MRT diffuse irradiance
5151     DO  imrt = 1, nmrtbl
5152        j = mrtbl(iy, imrt)
5153        i = mrtbl(ix, imrt)
5154        mrtinsw(imrt) = mrtskyt(imrt) * rad_sw_in_diff(j,i)
5155        mrtinlw(imrt) = mrtsky(imrt) * rad_lw_in_diff(j,i)
5156     ENDDO
5157
5158     !-- direct radiation
5159     IF ( zenith(0) > 0 )  THEN
5160        !--Identify solar direction vector (discretized number) 1)
5161        !--
5162        j = FLOOR(ACOS(zenith(0)) / pi * raytrace_discrete_elevs)
5163        i = MODULO(NINT(ATAN2(sun_dir_lon(0), sun_dir_lat(0))               &
5164                        / (2._wp*pi) * raytrace_discrete_azims-.5_wp, iwp), &
5165                   raytrace_discrete_azims)
5166        isd = dsidir_rev(j, i)
5167!-- TODO: check if isd = -1 to report that this solar position is not precalculated
5168        DO isurf = 1, nsurfl
5169           j = surfl(iy, isurf)
5170           i = surfl(ix, isurf)
5171           surfinswdir(isurf) = rad_sw_in_dir(j,i) *                        &
5172                costheta(surfl(id, isurf)) * dsitrans(isurf, isd) / zenith(0)
5173        ENDDO
5174!
5175!--     MRT direct irradiance
5176        DO  imrt = 1, nmrtbl
5177           j = mrtbl(iy, imrt)
5178           i = mrtbl(ix, imrt)
5179           mrtinsw(imrt) = mrtinsw(imrt) + mrtdsit(imrt, isd) * rad_sw_in_dir(j,i) &
5180                                     / zenith(0) / 4._wp ! normal to sphere
5181        ENDDO
5182     ENDIF
5183!
5184!--  MRT first pass thermal
5185     DO  imrtf = 1, nmrtf
5186        imrt = mrtfsurf(1, imrtf)
5187        isurfsrc = mrtfsurf(2, imrtf)
5188        mrtinlw(imrt) = mrtinlw(imrt) + mrtf(imrtf) * surfoutl(isurfsrc)
5189     ENDDO
5190
5191     IF ( npcbl > 0 )  THEN
5192
5193         pcbinswdir(:) = 0._wp
5194         pcbinswdif(:) = 0._wp
5195         pcbinlw(:) = 0._wp
5196!
5197!--      pcsf first pass
5198         DO icsf = 1, ncsfl
5199             ipcgb = csfsurf(1, icsf)
5200             i = pcbl(ix,ipcgb)
5201             j = pcbl(iy,ipcgb)
5202             k = pcbl(iz,ipcgb)
5203             isurfsrc = csfsurf(2, icsf)
5204
5205             IF ( isurfsrc == -1 )  THEN
5206!
5207!--             Diffuse rad from sky.
5208                pcbinswdif(ipcgb) = csf(1,icsf) * rad_sw_in_diff(j,i)
5209!
5210!--             Absorbed diffuse LW from sky minus emitted to sky
5211                IF ( plant_lw_interact )  THEN
5212                   pcbinlw(ipcgb) = csf(1,icsf)                                  &
5213                                       * (rad_lw_in_diff(j, i)                   &
5214                                          - sigma_sb * (pt(k,j,i)*exner(k))**4)
5215                ENDIF
5216!
5217!--             Direct rad
5218                IF ( zenith(0) > 0 )  THEN
5219!--                Estimate directed box absorption
5220                   pc_abs_frac = 1._wp - exp(pc_abs_eff * lad_s(k,j,i))
5221!
5222!--                isd has already been established, see 1)
5223                   pcbinswdir(ipcgb) = rad_sw_in_dir(j, i) * pc_box_area &
5224                                       * pc_abs_frac * dsitransc(ipcgb, isd)
5225                ENDIF
5226             ELSE
5227                IF ( plant_lw_interact )  THEN
5228!
5229!--                Thermal emission from plan canopy towards respective face
5230                   pcrad = sigma_sb * (pt(k,j,i) * exner(k))**4 * csf(1,icsf)
5231                   surfinlg(isurfsrc) = surfinlg(isurfsrc) + pcrad
5232!
5233!--                Remove the flux above + absorb LW from first pass from surfaces
5234                   asrc = facearea(surf(id, isurfsrc))
5235                   pcbinlw(ipcgb) = pcbinlw(ipcgb)                      &
5236                                    + (csf(1,icsf) * surfoutl(isurfsrc) & ! Absorb from first pass surf emit
5237                                       - pcrad)                         & ! Remove emitted heatflux
5238                                    * asrc
5239                ENDIF
5240             ENDIF
5241         ENDDO
5242
5243         pcbinsw(:) = pcbinswdir(:) + pcbinswdif(:)
5244     ENDIF
5245
5246     IF ( plant_lw_interact )  THEN
5247!
5248!--     Exchange incoming lw radiation from plant canopy
5249#if defined( __parallel )
5250        CALL MPI_Allreduce(MPI_IN_PLACE, surfinlg, nsurf, MPI_REAL, MPI_SUM, comm2d, ierr)
5251        IF ( ierr /= 0 )  THEN
5252           WRITE (9,*) 'Error MPI_Allreduce:', ierr
5253           FLUSH(9)
5254        ENDIF
5255        surfinl(:) = surfinl(:) + surfinlg(surfstart(myid)+1:surfstart(myid+1))
5256#else
5257        surfinl(:) = surfinl(:) + surfinlg(:)
5258#endif
5259     ENDIF
5260
5261     surfins = surfinswdir + surfinswdif
5262     surfinl = surfinl + surfinlwdif
5263     surfinsw = surfins
5264     surfinlw = surfinl
5265     surfoutsw = 0.0_wp
5266     surfoutlw = surfoutll
5267     surfemitlwl = surfoutll
5268
5269     IF ( .NOT.  surface_reflections )  THEN
5270!
5271!--     Set nrefsteps to 0 to disable reflections       
5272        nrefsteps = 0
5273        surfoutsl = albedo_surf * surfins
5274        surfoutll = (1._wp - emiss_surf) * surfinl
5275        surfoutsw = surfoutsw + surfoutsl
5276        surfoutlw = surfoutlw + surfoutll
5277     ENDIF
5278
5279!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5280!--     Next passes - reflections
5281!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5282     DO refstep = 1, nrefsteps
5283
5284         surfoutsl = albedo_surf * surfins
5285!--         for non-transparent surfaces, longwave albedo is 1 - emissivity
5286         surfoutll = (1._wp - emiss_surf) * surfinl
5287
5288#if defined( __parallel )
5289         CALL MPI_AllGatherv(surfoutsl, nsurfl, MPI_REAL, &
5290             surfouts, nsurfs, surfstart, MPI_REAL, comm2d, ierr)
5291         IF ( ierr /= 0 ) THEN
5292             WRITE(9,*) 'Error MPI_AllGatherv2:', ierr, SIZE(surfoutsl), nsurfl, &
5293                        SIZE(surfouts), nsurfs, surfstart
5294             FLUSH(9)
5295         ENDIF
5296
5297         CALL MPI_AllGatherv(surfoutll, nsurfl, MPI_REAL, &
5298             surfoutl, nsurfs, surfstart, MPI_REAL, comm2d, ierr)
5299         IF ( ierr /= 0 ) THEN
5300             WRITE(9,*) 'Error MPI_AllGatherv3:', ierr, SIZE(surfoutll), nsurfl, &
5301                        SIZE(surfoutl), nsurfs, surfstart
5302             FLUSH(9)
5303         ENDIF
5304
5305#else
5306         surfouts = surfoutsl
5307         surfoutl = surfoutll
5308#endif
5309
5310!--         reset for next pass input
5311         surfins = 0._wp
5312         surfinl = 0._wp
5313
5314!--         reflected radiation
5315         DO isvf = 1, nsvfl
5316             isurf = svfsurf(1, isvf)
5317             isurfsrc = svfsurf(2, isvf)
5318             surfins(isurf) = surfins(isurf) + svf(1,isvf) * svf(2,isvf) * surfouts(isurfsrc)
5319             IF ( plant_lw_interact )  THEN
5320                surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * svf(2,isvf) * surfoutl(isurfsrc)
5321             ELSE
5322                surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * surfoutl(isurfsrc)
5323             ENDIF
5324         ENDDO
5325!
5326!--      NOTE: PC absorbtion and MRT from reflected can both be done at once
5327!--      after all reflections if we do one more MPI_ALLGATHERV on surfout.
5328!--      Advantage: less local computation. Disadvantage: one more collective
5329!--      MPI call.
5330!
5331!--      Radiation absorbed by plant canopy
5332         DO  icsf = 1, ncsfl
5333             ipcgb = csfsurf(1, icsf)
5334             isurfsrc = csfsurf(2, icsf)
5335             IF ( isurfsrc == -1 )  CYCLE ! sky->face only in 1st pass, not here
5336!
5337!--          Calculate source surface area. If the `surf' array is removed
5338!--          before timestepping starts (future version), then asrc must be
5339!--          stored within `csf'
5340             asrc = facearea(surf(id, isurfsrc))
5341             pcbinsw(ipcgb) = pcbinsw(ipcgb) + csf(1,icsf) * surfouts(isurfsrc) * asrc
5342             IF ( plant_lw_interact )  THEN
5343                pcbinlw(ipcgb) = pcbinlw(ipcgb) + csf(1,icsf) * surfoutl(isurfsrc) * asrc
5344             ENDIF
5345         ENDDO
5346!
5347!--      MRT reflected
5348         DO  imrtf = 1, nmrtf
5349            imrt = mrtfsurf(1, imrtf)
5350            isurfsrc = mrtfsurf(2, imrtf)
5351            mrtinsw(imrt) = mrtinsw(imrt) + mrtft(imrtf) * surfouts(isurfsrc)
5352            mrtinlw(imrt) = mrtinlw(imrt) + mrtf(imrtf) * surfoutl(isurfsrc)
5353         ENDDO
5354
5355         surfinsw = surfinsw  + surfins
5356         surfinlw = surfinlw  + surfinl
5357         surfoutsw = surfoutsw + surfoutsl
5358         surfoutlw = surfoutlw + surfoutll
5359
5360     ENDDO ! refstep
5361
5362!--  push heat flux absorbed by plant canopy to respective 3D arrays
5363     IF ( npcbl > 0 )  THEN
5364         pc_heating_rate(:,:,:) = 0.0_wp
5365         DO ipcgb = 1, npcbl
5366             j = pcbl(iy, ipcgb)
5367             i = pcbl(ix, ipcgb)
5368             k = pcbl(iz, ipcgb)
5369!
5370!--          Following expression equals former kk = k - nzb_s_inner(j,i)
5371             kk = k - get_topography_top_index_ji( j, i, 's' )  !- lad arrays are defined flat
5372             pc_heating_rate(kk, j, i) = (pcbinsw(ipcgb) + pcbinlw(ipcgb)) &
5373                 * pchf_prep(k) * pt(k, j, i) !-- = dT/dt
5374         ENDDO
5375
5376         IF ( humidity .AND. plant_canopy_transpiration ) THEN
5377!--          Calculation of plant canopy transpiration rate and correspondidng latent heat rate
5378             pc_transpiration_rate(:,:,:) = 0.0_wp
5379             pc_latent_rate(:,:,:) = 0.0_wp
5380             DO ipcgb = 1, npcbl
5381                 i = pcbl(ix, ipcgb)
5382                 j = pcbl(iy, ipcgb)
5383                 k = pcbl(iz, ipcgb)
5384                 kk = k - get_topography_top_index_ji( j, i, 's' )  !- lad arrays are defined flat
5385                 CALL pcm_calc_transpiration_rate( i, j, k, kk, pcbinsw(ipcgb), pcbinlw(ipcgb), &
5386                                                   pc_transpiration_rate(kk,j,i), pc_latent_rate(kk,j,i) )
5387              ENDDO
5388         ENDIF
5389     ENDIF
5390!
5391!--  Calculate black body MRT (after all reflections)
5392     IF ( nmrtbl > 0 )  THEN
5393        IF ( mrt_include_sw )  THEN
5394           mrt(:) = ((mrtinsw(:) + mrtinlw(:)) / sigma_sb) ** .25_wp
5395        ELSE
5396           mrt(:) = (mrtinlw(:) / sigma_sb) ** .25_wp
5397        ENDIF
5398     ENDIF
5399!
5400!--     Transfer radiation arrays required for energy balance to the respective data types
5401     DO  i = 1, nsurfl
5402        m  = surfl(5,i)
5403!
5404!--     (1) Urban surfaces
5405!--     upward-facing
5406        IF ( surfl(1,i) == iup_u )  THEN
5407           surf_usm_h%rad_sw_in(m)  = surfinsw(i)
5408           surf_usm_h%rad_sw_out(m) = surfoutsw(i)
5409           surf_usm_h%rad_sw_dir(m) = surfinswdir(i)
5410           surf_usm_h%rad_sw_dif(m) = surfinswdif(i)
5411           surf_usm_h%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -        &
5412                                      surfinswdif(i)
5413           surf_usm_h%rad_sw_res(m) = surfins(i)
5414           surf_usm_h%rad_lw_in(m)  = surfinlw(i)
5415           surf_usm_h%rad_lw_out(m) = surfoutlw(i)
5416           surf_usm_h%rad_net(m)    = surfinsw(i) - surfoutsw(i) +          &
5417                                      surfinlw(i) - surfoutlw(i)
5418           surf_usm_h%rad_net_l(m)  = surf_usm_h%rad_net(m)
5419           surf_usm_h%rad_lw_dif(m) = surfinlwdif(i)
5420           surf_usm_h%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5421           surf_usm_h%rad_lw_res(m) = surfinl(i)
5422!
5423!--     northward-facding
5424        ELSEIF ( surfl(1,i) == inorth_u )  THEN
5425           surf_usm_v(0)%rad_sw_in(m)  = surfinsw(i)
5426           surf_usm_v(0)%rad_sw_out(m) = surfoutsw(i)
5427           surf_usm_v(0)%rad_sw_dir(m) = surfinswdir(i)
5428           surf_usm_v(0)%rad_sw_dif(m) = surfinswdif(i)
5429           surf_usm_v(0)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5430                                         surfinswdif(i)
5431           surf_usm_v(0)%rad_sw_res(m) = surfins(i)
5432           surf_usm_v(0)%rad_lw_in(m)  = surfinlw(i)
5433           surf_usm_v(0)%rad_lw_out(m) = surfoutlw(i)
5434           surf_usm_v(0)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5435                                         surfinlw(i) - surfoutlw(i)
5436           surf_usm_v(0)%rad_net_l(m)  = surf_usm_v(0)%rad_net(m)
5437           surf_usm_v(0)%rad_lw_dif(m) = surfinlwdif(i)
5438           surf_usm_v(0)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5439           surf_usm_v(0)%rad_lw_res(m) = surfinl(i)
5440!
5441!--     southward-facding
5442        ELSEIF ( surfl(1,i) == isouth_u )  THEN
5443           surf_usm_v(1)%rad_sw_in(m)  = surfinsw(i)
5444           surf_usm_v(1)%rad_sw_out(m) = surfoutsw(i)
5445           surf_usm_v(1)%rad_sw_dir(m) = surfinswdir(i)
5446           surf_usm_v(1)%rad_sw_dif(m) = surfinswdif(i)
5447           surf_usm_v(1)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5448                                         surfinswdif(i)
5449           surf_usm_v(1)%rad_sw_res(m) = surfins(i)
5450           surf_usm_v(1)%rad_lw_in(m)  = surfinlw(i)
5451           surf_usm_v(1)%rad_lw_out(m) = surfoutlw(i)
5452           surf_usm_v(1)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5453                                         surfinlw(i) - surfoutlw(i)
5454           surf_usm_v(1)%rad_net_l(m)  = surf_usm_v(1)%rad_net(m)
5455           surf_usm_v(1)%rad_lw_dif(m) = surfinlwdif(i)
5456           surf_usm_v(1)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5457           surf_usm_v(1)%rad_lw_res(m) = surfinl(i)
5458!
5459!--     eastward-facing
5460        ELSEIF ( surfl(1,i) == ieast_u )  THEN
5461           surf_usm_v(2)%rad_sw_in(m)  = surfinsw(i)
5462           surf_usm_v(2)%rad_sw_out(m) = surfoutsw(i)
5463           surf_usm_v(2)%rad_sw_dir(m) = surfinswdir(i)
5464           surf_usm_v(2)%rad_sw_dif(m) = surfinswdif(i)
5465           surf_usm_v(2)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5466                                         surfinswdif(i)
5467           surf_usm_v(2)%rad_sw_res(m) = surfins(i)
5468           surf_usm_v(2)%rad_lw_in(m)  = surfinlw(i)
5469           surf_usm_v(2)%rad_lw_out(m) = surfoutlw(i)
5470           surf_usm_v(2)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5471                                         surfinlw(i) - surfoutlw(i)
5472           surf_usm_v(2)%rad_net_l(m)  = surf_usm_v(2)%rad_net(m)
5473           surf_usm_v(2)%rad_lw_dif(m) = surfinlwdif(i)
5474           surf_usm_v(2)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5475           surf_usm_v(2)%rad_lw_res(m) = surfinl(i)
5476!
5477!--     westward-facding
5478        ELSEIF ( surfl(1,i) == iwest_u )  THEN
5479           surf_usm_v(3)%rad_sw_in(m)  = surfinsw(i)
5480           surf_usm_v(3)%rad_sw_out(m) = surfoutsw(i)
5481           surf_usm_v(3)%rad_sw_dir(m) = surfinswdir(i)
5482           surf_usm_v(3)%rad_sw_dif(m) = surfinswdif(i)
5483           surf_usm_v(3)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5484                                         surfinswdif(i)
5485           surf_usm_v(3)%rad_sw_res(m) = surfins(i)
5486           surf_usm_v(3)%rad_lw_in(m)  = surfinlw(i)
5487           surf_usm_v(3)%rad_lw_out(m) = surfoutlw(i)
5488           surf_usm_v(3)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5489                                         surfinlw(i) - surfoutlw(i)
5490           surf_usm_v(3)%rad_net_l(m)  = surf_usm_v(3)%rad_net(m)
5491           surf_usm_v(3)%rad_lw_dif(m) = surfinlwdif(i)
5492           surf_usm_v(3)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5493           surf_usm_v(3)%rad_lw_res(m) = surfinl(i)
5494!
5495!--     (2) land surfaces
5496!--     upward-facing
5497        ELSEIF ( surfl(1,i) == iup_l )  THEN
5498           surf_lsm_h%rad_sw_in(m)  = surfinsw(i)
5499           surf_lsm_h%rad_sw_out(m) = surfoutsw(i)
5500           surf_lsm_h%rad_sw_dir(m) = surfinswdir(i)
5501           surf_lsm_h%rad_sw_dif(m) = surfinswdif(i)
5502           surf_lsm_h%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -        &
5503                                         surfinswdif(i)
5504           surf_lsm_h%rad_sw_res(m) = surfins(i)
5505           surf_lsm_h%rad_lw_in(m)  = surfinlw(i)
5506           surf_lsm_h%rad_lw_out(m) = surfoutlw(i)
5507           surf_lsm_h%rad_net(m)    = surfinsw(i) - surfoutsw(i) +          &
5508                                      surfinlw(i) - surfoutlw(i)
5509           surf_lsm_h%rad_lw_dif(m) = surfinlwdif(i)
5510           surf_lsm_h%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5511           surf_lsm_h%rad_lw_res(m) = surfinl(i)
5512!
5513!--     northward-facding
5514        ELSEIF ( surfl(1,i) == inorth_l )  THEN
5515           surf_lsm_v(0)%rad_sw_in(m)  = surfinsw(i)
5516           surf_lsm_v(0)%rad_sw_out(m) = surfoutsw(i)
5517           surf_lsm_v(0)%rad_sw_dir(m) = surfinswdir(i)
5518           surf_lsm_v(0)%rad_sw_dif(m) = surfinswdif(i)
5519           surf_lsm_v(0)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5520                                         surfinswdif(i)
5521           surf_lsm_v(0)%rad_sw_res(m) = surfins(i)
5522           surf_lsm_v(0)%rad_lw_in(m)  = surfinlw(i)
5523           surf_lsm_v(0)%rad_lw_out(m) = surfoutlw(i)
5524           surf_lsm_v(0)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5525                                         surfinlw(i) - surfoutlw(i)
5526           surf_lsm_v(0)%rad_lw_dif(m) = surfinlwdif(i)
5527           surf_lsm_v(0)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5528           surf_lsm_v(0)%rad_lw_res(m) = surfinl(i)
5529!
5530!--     southward-facding
5531        ELSEIF ( surfl(1,i) == isouth_l )  THEN
5532           surf_lsm_v(1)%rad_sw_in(m)  = surfinsw(i)
5533           surf_lsm_v(1)%rad_sw_out(m) = surfoutsw(i)
5534           surf_lsm_v(1)%rad_sw_dir(m) = surfinswdir(i)
5535           surf_lsm_v(1)%rad_sw_dif(m) = surfinswdif(i)
5536           surf_lsm_v(1)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5537                                         surfinswdif(i)
5538           surf_lsm_v(1)%rad_sw_res(m) = surfins(i)
5539           surf_lsm_v(1)%rad_lw_in(m)  = surfinlw(i)
5540           surf_lsm_v(1)%rad_lw_out(m) = surfoutlw(i)
5541           surf_lsm_v(1)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5542                                         surfinlw(i) - surfoutlw(i)
5543           surf_lsm_v(1)%rad_lw_dif(m) = surfinlwdif(i)
5544           surf_lsm_v(1)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5545           surf_lsm_v(1)%rad_lw_res(m) = surfinl(i)
5546!
5547!--     eastward-facing
5548        ELSEIF ( surfl(1,i) == ieast_l )  THEN
5549           surf_lsm_v(2)%rad_sw_in(m)  = surfinsw(i)
5550           surf_lsm_v(2)%rad_sw_out(m) = surfoutsw(i)
5551           surf_lsm_v(2)%rad_sw_dir(m) = surfinswdir(i)
5552           surf_lsm_v(2)%rad_sw_dif(m) = surfinswdif(i)
5553           surf_lsm_v(2)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5554                                         surfinswdif(i)
5555           surf_lsm_v(2)%rad_sw_res(m) = surfins(i)
5556           surf_lsm_v(2)%rad_lw_in(m)  = surfinlw(i)
5557           surf_lsm_v(2)%rad_lw_out(m) = surfoutlw(i)
5558           surf_lsm_v(2)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5559                                         surfinlw(i) - surfoutlw(i)
5560           surf_lsm_v(2)%rad_lw_dif(m) = surfinlwdif(i)
5561           surf_lsm_v(2)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5562           surf_lsm_v(2)%rad_lw_res(m) = surfinl(i)
5563!
5564!--     westward-facing
5565        ELSEIF ( surfl(1,i) == iwest_l )  THEN
5566           surf_lsm_v(3)%rad_sw_in(m)  = surfinsw(i)
5567           surf_lsm_v(3)%rad_sw_out(m) = surfoutsw(i)
5568           surf_lsm_v(3)%rad_sw_dir(m) = surfinswdir(i)
5569           surf_lsm_v(3)%rad_sw_dif(m) = surfinswdif(i)
5570           surf_lsm_v(3)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5571                                         surfinswdif(i)
5572           surf_lsm_v(3)%rad_sw_res(m) = surfins(i)
5573           surf_lsm_v(3)%rad_lw_in(m)  = surfinlw(i)
5574           surf_lsm_v(3)%rad_lw_out(m) = surfoutlw(i)
5575           surf_lsm_v(3)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5576                                         surfinlw(i) - surfoutlw(i)
5577           surf_lsm_v(3)%rad_lw_dif(m) = surfinlwdif(i)
5578           surf_lsm_v(3)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5579           surf_lsm_v(3)%rad_lw_res(m) = surfinl(i)
5580        ENDIF
5581
5582     ENDDO
5583
5584     DO  m = 1, surf_usm_h%ns
5585        surf_usm_h%surfhf(m) = surf_usm_h%rad_sw_in(m)  +                   &
5586                               surf_usm_h%rad_lw_in(m)  -                   &
5587                               surf_usm_h%rad_sw_out(m) -                   &
5588                               surf_usm_h%rad_lw_out(m)
5589     ENDDO
5590     DO  m = 1, surf_lsm_h%ns
5591        surf_lsm_h%surfhf(m) = surf_lsm_h%rad_sw_in(m)  +                   &
5592                               surf_lsm_h%rad_lw_in(m)  -                   &
5593                               surf_lsm_h%rad_sw_out(m) -                   &
5594                               surf_lsm_h%rad_lw_out(m)
5595     ENDDO
5596
5597     DO  l = 0, 3
5598!--     urban
5599        DO  m = 1, surf_usm_v(l)%ns
5600           surf_usm_v(l)%surfhf(m) = surf_usm_v(l)%rad_sw_in(m)  +          &
5601                                     surf_usm_v(l)%rad_lw_in(m)  -          &
5602                                     surf_usm_v(l)%rad_sw_out(m) -          &
5603                                     surf_usm_v(l)%rad_lw_out(m)
5604        ENDDO
5605!--     land
5606        DO  m = 1, surf_lsm_v(l)%ns
5607           surf_lsm_v(l)%surfhf(m) = surf_lsm_v(l)%rad_sw_in(m)  +          &
5608                                     surf_lsm_v(l)%rad_lw_in(m)  -          &
5609                                     surf_lsm_v(l)%rad_sw_out(m) -          &
5610                                     surf_lsm_v(l)%rad_lw_out(m)
5611
5612        ENDDO
5613     ENDDO
5614!
5615!--  Calculate the average temperature, albedo, and emissivity for urban/land
5616!--  domain when using average_radiation in the respective radiation model
5617
5618!--  calculate horizontal area
5619! !!! ATTENTION!!! uniform grid is assumed here
5620     area_hor = (nx+1) * (ny+1) * dx * dy
5621!
5622!--  absorbed/received SW & LW and emitted LW energy of all physical
5623!--  surfaces (land and urban) in local processor
5624     pinswl = 0._wp
5625     pinlwl = 0._wp
5626     pabsswl = 0._wp
5627     pabslwl = 0._wp
5628     pemitlwl = 0._wp
5629     emiss_sum_surfl = 0._wp
5630     area_surfl = 0._wp
5631     DO  i = 1, nsurfl
5632        d = surfl(id, i)
5633!--  received SW & LW
5634        pinswl = pinswl + (surfinswdir(i) + surfinswdif(i)) * facearea(d)
5635        pinlwl = pinlwl + surfinlwdif(i) * facearea(d)
5636!--   absorbed SW & LW
5637        pabsswl = pabsswl + (1._wp - albedo_surf(i)) *                   &
5638                                                surfinsw(i) * facearea(d)
5639        pabslwl = pabslwl + emiss_surf(i) * surfinlw(i) * facearea(d)
5640!--   emitted LW
5641        pemitlwl = pemitlwl + surfemitlwl(i) * facearea(d)
5642!--   emissivity and area sum
5643        emiss_sum_surfl = emiss_sum_surfl + emiss_surf(i) * facearea(d)
5644        area_surfl = area_surfl + facearea(d)
5645     END DO
5646!
5647!--  add the absorbed SW energy by plant canopy
5648     IF ( npcbl > 0 )  THEN
5649        pabsswl = pabsswl + SUM(pcbinsw)
5650        pabslwl = pabslwl + SUM(pcbinlw)
5651        pinswl = pinswl + SUM(pcbinswdir) + SUM(pcbinswdif)
5652     ENDIF
5653!
5654!--  gather all rad flux energy in all processors
5655#if defined( __parallel )
5656     CALL MPI_ALLREDUCE( pinswl, pinsw, 1, MPI_REAL, MPI_SUM, comm2d, ierr)
5657     IF ( ierr /= 0 ) THEN
5658         WRITE(9,*) 'Error MPI_AllReduce5:', ierr, pinswl, pinsw
5659         FLUSH(9)
5660     ENDIF
5661     CALL MPI_ALLREDUCE( pinlwl, pinlw, 1, MPI_REAL, MPI_SUM, comm2d, ierr)
5662     IF ( ierr /= 0 ) THEN
5663         WRITE(9,*) 'Error MPI_AllReduce6:', ierr, pinlwl, pinlw
5664         FLUSH(9)
5665     ENDIF
5666     CALL MPI_ALLREDUCE( pabsswl, pabssw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5667     IF ( ierr /= 0 ) THEN
5668         WRITE(9,*) 'Error MPI_AllReduce7:', ierr, pabsswl, pabssw
5669         FLUSH(9)
5670     ENDIF
5671     CALL MPI_ALLREDUCE( pabslwl, pabslw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5672     IF ( ierr /= 0 ) THEN
5673         WRITE(9,*) 'Error MPI_AllReduce8:', ierr, pabslwl, pabslw
5674         FLUSH(9)
5675     ENDIF
5676     CALL MPI_ALLREDUCE( pemitlwl, pemitlw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5677     IF ( ierr /= 0 ) THEN
5678         WRITE(9,*) 'Error MPI_AllReduce8:', ierr, pemitlwl, pemitlw
5679         FLUSH(9)
5680     ENDIF
5681     CALL MPI_ALLREDUCE( emiss_sum_surfl, emiss_sum_surf, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5682     IF ( ierr /= 0 ) THEN
5683         WRITE(9,*) 'Error MPI_AllReduce9:', ierr, emiss_sum_surfl, emiss_sum_surf
5684         FLUSH(9)
5685     ENDIF
5686     CALL MPI_ALLREDUCE( area_surfl, area_surf, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5687     IF ( ierr /= 0 ) THEN
5688         WRITE(9,*) 'Error MPI_AllReduce10:', ierr, area_surfl, area_surf
5689         FLUSH(9)
5690     ENDIF
5691#else
5692     pinsw = pinswl
5693     pinlw = pinlwl
5694     pabssw = pabsswl
5695     pabslw = pabslwl
5696     pemitlw = pemitlwl
5697     emiss_sum_surf = emiss_sum_surfl
5698     area_surf = area_surfl
5699#endif
5700
5701!--  (1) albedo
5702     IF ( pinsw /= 0.0_wp )  &
5703          albedo_urb = (pinsw - pabssw) / pinsw
5704!--  (2) average emmsivity
5705     IF ( area_surf /= 0.0_wp ) &
5706          emissivity_urb = emiss_sum_surf / area_surf
5707!
5708!--  Temporally comment out calculation of effective radiative temperature.
5709!--  See below for more explanation.
5710!--  (3) temperature
5711!--   first we calculate an effective horizontal area to account for
5712!--   the effect of vertical surfaces (which contributes to LW emission)
5713!--   We simply use the ratio of the total LW to the incoming LW flux
5714      area_hor = pinlw/rad_lw_in_diff(nyn,nxl)
5715      t_rad_urb = ( (pemitlw - pabslw + emissivity_urb*pinlw) / &
5716           (emissivity_urb*sigma_sb * area_hor) )**0.25_wp
5717
5718    CONTAINS
5719
5720!------------------------------------------------------------------------------!
5721!> Calculates radiation absorbed by box with given size and LAD.
5722!>
5723!> Simulates resol**2 rays (by equally spacing a bounding horizontal square
5724!> conatining all possible rays that would cross the box) and calculates
5725!> average transparency per ray. Returns fraction of absorbed radiation flux
5726!> and area for which this fraction is effective.
5727!------------------------------------------------------------------------------!
5728    PURE SUBROUTINE box_absorb(boxsize, resol, dens, uvec, area, absorb)
5729       IMPLICIT NONE
5730
5731       REAL(wp), DIMENSION(3), INTENT(in) :: &
5732            boxsize, &      !< z, y, x size of box in m
5733            uvec            !< z, y, x unit vector of incoming flux
5734       INTEGER(iwp), INTENT(in) :: &
5735            resol           !< No. of rays in x and y dimensions
5736       REAL(wp), INTENT(in) :: &
5737            dens            !< box density (e.g. Leaf Area Density)
5738       REAL(wp), INTENT(out) :: &
5739            area, &         !< horizontal area for flux absorbtion
5740            absorb          !< fraction of absorbed flux
5741       REAL(wp) :: &
5742            xshift, yshift, &
5743            xmin, xmax, ymin, ymax, &
5744            xorig, yorig, &
5745            dx1, dy1, dz1, dx2, dy2, dz2, &
5746            crdist, &
5747            transp
5748       INTEGER(iwp) :: &
5749            i, j
5750
5751       xshift = uvec(3) / uvec(1) * boxsize(1)
5752       xmin = min(0._wp, -xshift)
5753       xmax = boxsize(3) + max(0._wp, -xshift)
5754       yshift = uvec(2) / uvec(1) * boxsize(1)
5755       ymin = min(0._wp, -yshift)
5756       ymax = boxsize(2) + max(0._wp, -yshift)
5757
5758       transp = 0._wp
5759       DO i = 1, resol
5760          xorig = xmin + (xmax-xmin) * (i-.5_wp) / resol
5761          DO j = 1, resol
5762             yorig = ymin + (ymax-ymin) * (j-.5_wp) / resol
5763
5764             dz1 = 0._wp
5765             dz2 = boxsize(1)/uvec(1)
5766
5767             IF ( uvec(2) > 0._wp )  THEN
5768                dy1 = -yorig             / uvec(2) !< crossing with y=0
5769                dy2 = (boxsize(2)-yorig) / uvec(2) !< crossing with y=boxsize(2)
5770             ELSE !uvec(2)==0
5771                dy1 = -huge(1._wp)
5772                dy2 = huge(1._wp)
5773             ENDIF
5774
5775             IF ( uvec(3) > 0._wp )  THEN
5776                dx1 = -xorig             / uvec(3) !< crossing with x=0
5777                dx2 = (boxsize(3)-xorig) / uvec(3) !< crossing with x=boxsize(3)
5778             ELSE !uvec(3)==0
5779                dx1 = -huge(1._wp)
5780                dx2 = huge(1._wp)
5781             ENDIF
5782
5783             crdist = max(0._wp, (min(dz2, dy2, dx2) - max(dz1, dy1, dx1)))
5784             transp = transp + exp(-ext_coef * dens * crdist)
5785          ENDDO
5786       ENDDO
5787       transp = transp / resol**2
5788       area = (boxsize(3)+xshift)*(boxsize(2)+yshift)
5789       absorb = 1._wp - transp
5790
5791    END SUBROUTINE box_absorb
5792
5793!------------------------------------------------------------------------------!
5794! Description:
5795! ------------
5796!> This subroutine splits direct and diffusion dw radiation
5797!> It sould not be called in case the radiation model already does it
5798!> It follows <CITATION>
5799!------------------------------------------------------------------------------!
5800    SUBROUTINE calc_diffusion_radiation 
5801   
5802        REAL(wp), PARAMETER                          :: lowest_solarUp = 0.1_wp  !< limit the sun elevation to protect stability of the calculation
5803        INTEGER(iwp)                                 :: i, j
5804        REAL(wp)                                     ::  year_angle              !< angle
5805        REAL(wp)                                     ::  etr                     !< extraterestrial radiation
5806        REAL(wp)                                     ::  corrected_solarUp       !< corrected solar up radiation
5807        REAL(wp)                                     ::  horizontalETR           !< horizontal extraterestrial radiation
5808        REAL(wp)                                     ::  clearnessIndex          !< clearness index
5809        REAL(wp)                                     ::  diff_frac               !< diffusion fraction of the radiation
5810
5811       
5812!--     Calculate current day and time based on the initial values and simulation time
5813        year_angle = ( (day_of_year_init * 86400) + time_utc_init              &
5814                        + time_since_reference_point )  * d_seconds_year       &
5815                        * 2.0_wp * pi
5816       
5817        etr = solar_constant * (1.00011_wp +                                   &
5818                          0.034221_wp * cos(year_angle) +                      &
5819                          0.001280_wp * sin(year_angle) +                      &
5820                          0.000719_wp * cos(2.0_wp * year_angle) +             &
5821                          0.000077_wp * sin(2.0_wp * year_angle))
5822       
5823!--   
5824!--     Under a very low angle, we keep extraterestrial radiation at
5825!--     the last small value, therefore the clearness index will be pushed
5826!--     towards 0 while keeping full continuity.
5827!--   
5828        IF ( zenith(0) <= lowest_solarUp )  THEN
5829            corrected_solarUp = lowest_solarUp
5830        ELSE
5831            corrected_solarUp = zenith(0)
5832        ENDIF
5833       
5834        horizontalETR = etr * corrected_solarUp
5835       
5836        DO i = nxl, nxr
5837            DO j = nys, nyn
5838                clearnessIndex = rad_sw_in(0,j,i) / horizontalETR
5839                diff_frac = 1.0_wp / (1.0_wp + exp(-5.0033_wp + 8.6025_wp * clearnessIndex))
5840                rad_sw_in_diff(j,i) = rad_sw_in(0,j,i) * diff_frac
5841                rad_sw_in_dir(j,i)  = rad_sw_in(0,j,i) * (1.0_wp - diff_frac)
5842                rad_lw_in_diff(j,i) = rad_lw_in(0,j,i)
5843            ENDDO
5844        ENDDO
5845       
5846    END SUBROUTINE calc_diffusion_radiation
5847
5848
5849 END SUBROUTINE radiation_interaction
5850   
5851!------------------------------------------------------------------------------!
5852! Description:
5853! ------------
5854!> This subroutine initializes structures needed for radiative transfer
5855!> model. This model calculates transformation processes of the
5856!> radiation inside urban and land canopy layer. The module includes also
5857!> the interaction of the radiation with the resolved plant canopy.
5858!>
5859!> For more info. see Resler et al. 2017
5860!>
5861!> The new version 2.0 was radically rewriten, the discretization scheme
5862!> has been changed. This new version significantly improves effectivity
5863!> of the paralelization and the scalability of the model.
5864!>
5865!------------------------------------------------------------------------------!
5866    SUBROUTINE radiation_interaction_init
5867
5868       USE control_parameters,                                                 &
5869           ONLY:  dz_stretch_level_start
5870           
5871       USE netcdf_data_input_mod,                                              &
5872           ONLY:  leaf_area_density_f
5873
5874       USE plant_canopy_model_mod,                                             &
5875           ONLY:  pch_index, lad_s
5876
5877       IMPLICIT NONE
5878
5879       INTEGER(iwp) :: i, j, k, l, m, d
5880       INTEGER(iwp) :: k_topo     !< vertical index indicating topography top for given (j,i)
5881       INTEGER(iwp) :: nzptl, nzubl, nzutl, isurf, ipcgb, imrt
5882       REAL(wp)     :: mrl
5883#if defined( __parallel )
5884       INTEGER(iwp), DIMENSION(:), POINTER       ::  gridsurf_rma   !< fortran pointer, but lower bounds are 1
5885       TYPE(c_ptr)                               ::  gridsurf_rma_p !< allocated c pointer
5886       INTEGER(iwp)                              ::  minfo          !< MPI RMA window info handle
5887#endif
5888
5889!
5890!--     precalculate face areas for different face directions using normal vector
5891        DO d = 0, nsurf_type
5892            facearea(d) = 1._wp
5893            IF ( idir(d) == 0 ) facearea(d) = facearea(d) * dx
5894            IF ( jdir(d) == 0 ) facearea(d) = facearea(d) * dy
5895            IF ( kdir(d) == 0 ) facearea(d) = facearea(d) * dz(1)
5896        ENDDO
5897!
5898!--    Find nzub, nzut, nzu via wall_flag_0 array (nzb_s_inner will be
5899!--    removed later). The following contruct finds the lowest / largest index
5900!--    for any upward-facing wall (see bit 12).
5901       nzubl = MINVAL( get_topography_top_index( 's' ) )
5902       nzutl = MAXVAL( get_topography_top_index( 's' ) )
5903
5904       nzubl = MAX( nzubl, nzb )
5905
5906       IF ( plant_canopy )  THEN
5907!--        allocate needed arrays
5908           ALLOCATE( pct(nys:nyn,nxl:nxr) )
5909           ALLOCATE( pch(nys:nyn,nxl:nxr) )
5910
5911!--        calculate plant canopy height
5912           npcbl = 0
5913           pct   = 0
5914           pch   = 0
5915           DO i = nxl, nxr
5916               DO j = nys, nyn
5917!
5918!--                Find topography top index
5919                   k_topo = get_topography_top_index_ji( j, i, 's' )
5920
5921                   DO k = nzt+1, 0, -1
5922                       IF ( lad_s(k,j,i) /= 0.0_wp )  THEN
5923!--                        we are at the top of the pcs
5924                           pct(j,i) = k + k_topo
5925                           pch(j,i) = k
5926                           npcbl = npcbl + pch(j,i)
5927                           EXIT
5928                       ENDIF
5929                   ENDDO
5930               ENDDO
5931           ENDDO
5932
5933           nzutl = MAX( nzutl, MAXVAL( pct ) )
5934           nzptl = MAXVAL( pct )
5935!--        code of plant canopy model uses parameter pch_index
5936!--        we need to setup it here to right value
5937!--        (pch_index, lad_s and other arrays in PCM are defined flat)
5938           pch_index = MERGE( leaf_area_density_f%nz - 1, MAXVAL( pch ),       &
5939                              leaf_area_density_f%from_file )
5940
5941           prototype_lad = MAXVAL( lad_s ) * .9_wp  !< better be *1.0 if lad is either 0 or maxval(lad) everywhere
5942           IF ( prototype_lad <= 0._wp ) prototype_lad = .3_wp
5943           !WRITE(message_string, '(a,f6.3)') 'Precomputing effective box optical ' &
5944           !    // 'depth using prototype leaf area density = ', prototype_lad
5945           !CALL message('radiation_interaction_init', 'PA0520', 0, 0, -1, 6, 0)
5946       ENDIF
5947
5948       nzutl = MIN( nzutl + nzut_free, nzt )
5949
5950#if defined( __parallel )
5951       CALL MPI_AllReduce(nzubl, nzub, 1, MPI_INTEGER, MPI_MIN, comm2d, ierr )
5952       IF ( ierr /= 0 ) THEN
5953           WRITE(9,*) 'Error MPI_AllReduce11:', ierr, nzubl, nzub
5954           FLUSH(9)
5955       ENDIF
5956       CALL MPI_AllReduce(nzutl, nzut, 1, MPI_INTEGER, MPI_MAX, comm2d, ierr )
5957       IF ( ierr /= 0 ) THEN
5958           WRITE(9,*) 'Error MPI_AllReduce12:', ierr, nzutl, nzut
5959           FLUSH(9)
5960       ENDIF
5961       CALL MPI_AllReduce(nzptl, nzpt, 1, MPI_INTEGER, MPI_MAX, comm2d, ierr )
5962       IF ( ierr /= 0 ) THEN
5963           WRITE(9,*) 'Error MPI_AllReduce13:', ierr, nzptl, nzpt
5964           FLUSH(9)
5965       ENDIF
5966#else
5967       nzub = nzubl
5968       nzut = nzutl
5969       nzpt = nzptl
5970#endif
5971!
5972!--    Stretching (non-uniform grid spacing) is not considered in the radiation
5973!--    model. Therefore, vertical stretching has to be applied above the area
5974!--    where the parts of the radiation model which assume constant grid spacing
5975!--    are active. ABS (...) is required because the default value of
5976!--    dz_stretch_level_start is -9999999.9_wp (negative).
5977       IF ( ABS( dz_stretch_level_start(1) ) <= zw(nzut) ) THEN
5978          WRITE( message_string, * ) 'The lowest level where vertical ',       &
5979                                     'stretching is applied have to be ',      &
5980                                     'greater than ', zw(nzut)
5981          CALL message( 'radiation_interaction_init', 'PA0496', 1, 2, 0, 6, 0 )
5982       ENDIF 
5983!
5984!--    global number of urban and plant layers
5985       nzu = nzut - nzub + 1
5986       nzp = nzpt - nzub + 1
5987!
5988!--    check max_raytracing_dist relative to urban surface layer height
5989       mrl = 2.0_wp * nzu * dz(1)
5990!--    set max_raytracing_dist to double the urban surface layer height, if not set
5991       IF ( max_raytracing_dist == -999.0_wp ) THEN
5992          max_raytracing_dist = mrl
5993       ENDIF
5994!--    check if max_raytracing_dist set too low (here we only warn the user. Other
5995!      option is to correct the value again to double the urban surface layer height)
5996       IF ( max_raytracing_dist  <  mrl ) THEN
5997          WRITE(message_string, '(a,f6.1)') 'Max_raytracing_dist is set less than ', &
5998               'double the urban surface layer height, i.e. ', mrl
5999          CALL message('radiation_interaction_init', 'PA0521', 0, 0, -1, 6, 0)
6000       ENDIF
6001!        IF ( max_raytracing_dist <= mrl ) THEN
6002!           IF ( max_raytracing_dist /= -999.0_wp ) THEN
6003! !--          max_raytracing_dist too low
6004!              WRITE(message_string, '(a,f6.1)') 'Max_raytracing_dist too low, ' &
6005!                    // 'override to value ', mrl
6006!              CALL message('radiation_interaction_init', 'PA0521', 0, 0, -1, 6, 0)
6007!           ENDIF
6008!           max_raytracing_dist = mrl
6009!        ENDIF
6010!
6011!--    allocate urban surfaces grid
6012!--    calc number of surfaces in local proc
6013       CALL location_message( '    calculation of indices for surfaces', .TRUE. )
6014       nsurfl = 0
6015!
6016!--    Number of horizontal surfaces including land- and roof surfaces in both USM and LSM. Note that
6017!--    All horizontal surface elements are already counted in surface_mod.
6018       startland = 1
6019       nsurfl    = surf_usm_h%ns + surf_lsm_h%ns
6020       endland   = nsurfl
6021       nlands    = endland - startland + 1
6022
6023!
6024!--    Number of vertical surfaces in both USM and LSM. Note that all vertical surface elements are
6025!--    already counted in surface_mod.
6026       startwall = nsurfl+1
6027       DO  i = 0,3
6028          nsurfl = nsurfl + surf_usm_v(i)%ns + surf_lsm_v(i)%ns
6029       ENDDO
6030       endwall = nsurfl
6031       nwalls  = endwall - startwall + 1
6032       dirstart = (/ startland, startwall, startwall, startwall, startwall /)
6033       dirend = (/ endland, endwall, endwall, endwall, endwall /)
6034
6035!--    fill gridpcbl and pcbl
6036       IF ( npcbl > 0 )  THEN
6037           ALLOCATE( pcbl(iz:ix, 1:npcbl) )
6038           ALLOCATE( gridpcbl(nzub:nzpt,nys:nyn,nxl:nxr) )
6039           pcbl = -1
6040           gridpcbl(:,:,:) = 0
6041           ipcgb = 0
6042           DO i = nxl, nxr
6043               DO j = nys, nyn
6044!
6045!--                Find topography top index
6046                   k_topo = get_topography_top_index_ji( j, i, 's' )
6047
6048                   DO k = k_topo + 1, pct(j,i)
6049                       ipcgb = ipcgb + 1
6050                       gridpcbl(k,j,i) = ipcgb
6051                       pcbl(:,ipcgb) = (/ k, j, i /)
6052                   ENDDO
6053               ENDDO
6054           ENDDO
6055           ALLOCATE( pcbinsw( 1:npcbl ) )
6056           ALLOCATE( pcbinswdir( 1:npcbl ) )
6057           ALLOCATE( pcbinswdif( 1:npcbl ) )
6058           ALLOCATE( pcbinlw( 1:npcbl ) )
6059       ENDIF
6060
6061!--    fill surfl (the ordering of local surfaces given by the following
6062!--    cycles must not be altered, certain file input routines may depend
6063!--    on it)
6064       ALLOCATE(surfl_l(5*nsurfl))  ! is it necessary to allocate it with (5,nsurfl)?
6065       surfl(1:5,1:nsurfl) => surfl_l(1:5*nsurfl)
6066       isurf = 0
6067       IF ( rad_angular_discretization )  THEN
6068!
6069!--       Allocate and fill the reverse indexing array gridsurf
6070#if defined( __parallel )
6071!
6072!--       raytrace_mpi_rma is asserted
6073
6074          CALL MPI_Info_create(minfo, ierr)
6075          IF ( ierr /= 0 ) THEN
6076              WRITE(9,*) 'Error MPI_Info_create1:', ierr
6077              FLUSH(9)
6078          ENDIF
6079          CALL MPI_Info_set(minfo, 'accumulate_ordering', '', ierr)
6080          IF ( ierr /= 0 ) THEN
6081              WRITE(9,*) 'Error MPI_Info_set1:', ierr
6082              FLUSH(9)
6083          ENDIF
6084          CALL MPI_Info_set(minfo, 'accumulate_ops', 'same_op', ierr)
6085          IF ( ierr /= 0 ) THEN
6086              WRITE(9,*) 'Error MPI_Info_set2:', ierr
6087              FLUSH(9)
6088          ENDIF
6089          CALL MPI_Info_set(minfo, 'same_size', 'true', ierr)
6090          IF ( ierr /= 0 ) THEN
6091              WRITE(9,*) 'Error MPI_Info_set3:', ierr
6092              FLUSH(9)
6093          ENDIF
6094          CALL MPI_Info_set(minfo, 'same_disp_unit', 'true', ierr)
6095          IF ( ierr /= 0 ) THEN
6096              WRITE(9,*) 'Error MPI_Info_set4:', ierr
6097              FLUSH(9)
6098          ENDIF
6099
6100          CALL MPI_Win_allocate(INT(STORAGE_SIZE(1_iwp)/8*nsurf_type_u*nzu*nny*nnx, &
6101                                    kind=MPI_ADDRESS_KIND), STORAGE_SIZE(1_iwp)/8,  &
6102                                minfo, comm2d, gridsurf_rma_p, win_gridsurf, ierr)
6103          IF ( ierr /= 0 ) THEN
6104              WRITE(9,*) 'Error MPI_Win_allocate1:', ierr, &
6105                 INT(STORAGE_SIZE(1_iwp)/8*nsurf_type_u*nzu*nny*nnx,kind=MPI_ADDRESS_KIND), &
6106                 STORAGE_SIZE(1_iwp)/8, win_gridsurf
6107              FLUSH(9)
6108          ENDIF
6109
6110          CALL MPI_Info_free(minfo, ierr)
6111          IF ( ierr /= 0 ) THEN
6112              WRITE(9,*) 'Error MPI_Info_free1:', ierr
6113              FLUSH(9)
6114          ENDIF
6115
6116!
6117!--       On Intel compilers, calling c_f_pointer to transform a C pointer
6118!--       directly to a multi-dimensional Fotran pointer leads to strange
6119!--       errors on dimension boundaries. However, transforming to a 1D
6120!--       pointer and then redirecting a multidimensional pointer to it works
6121!--       fine.
6122          CALL c_f_pointer(gridsurf_rma_p, gridsurf_rma, (/ nsurf_type_u*nzu*nny*nnx /))
6123          gridsurf(0:nsurf_type_u-1, nzub:nzut, nys:nyn, nxl:nxr) =>                &
6124                     gridsurf_rma(1:nsurf_type_u*nzu*nny*nnx)
6125#else
6126          ALLOCATE(gridsurf(0:nsurf_type_u-1,nzub:nzut,nys:nyn,nxl:nxr) )
6127#endif
6128          gridsurf(:,:,:,:) = -999
6129       ENDIF
6130
6131!--    add horizontal surface elements (land and urban surfaces)
6132!--    TODO: add urban overhanging surfaces (idown_u)
6133       DO i = nxl, nxr
6134           DO j = nys, nyn
6135              DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
6136                 k = surf_usm_h%k(m)
6137                 isurf = isurf + 1
6138                 surfl(:,isurf) = (/iup_u,k,j,i,m/)
6139                 IF ( rad_angular_discretization ) THEN
6140                    gridsurf(iup_u,k,j,i) = isurf
6141                 ENDIF
6142              ENDDO
6143
6144              DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6145                 k = surf_lsm_h%k(m)
6146                 isurf = isurf + 1
6147                 surfl(:,isurf) = (/iup_l,k,j,i,m/)
6148                 IF ( rad_angular_discretization ) THEN
6149                    gridsurf(iup_u,k,j,i) = isurf
6150                 ENDIF
6151              ENDDO
6152
6153           ENDDO
6154       ENDDO
6155
6156!--    add vertical surface elements (land and urban surfaces)
6157!--    TODO: remove the hard coding of l = 0 to l = idirection
6158       DO i = nxl, nxr
6159           DO j = nys, nyn
6160              l = 0
6161              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6162                 k = surf_usm_v(l)%k(m)
6163                 isurf = isurf + 1
6164                 surfl(:,isurf) = (/inorth_u,k,j,i,m/)
6165                 IF ( rad_angular_discretization ) THEN
6166                    gridsurf(inorth_u,k,j,i) = isurf
6167                 ENDIF
6168              ENDDO
6169              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6170                 k = surf_lsm_v(l)%k(m)
6171                 isurf = isurf + 1
6172                 surfl(:,isurf) = (/inorth_l,k,j,i,m/)
6173                 IF ( rad_angular_discretization ) THEN
6174                    gridsurf(inorth_u,k,j,i) = isurf
6175                 ENDIF
6176              ENDDO
6177
6178              l = 1
6179              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6180                 k = surf_usm_v(l)%k(m)
6181                 isurf = isurf + 1
6182                 surfl(:,isurf) = (/isouth_u,k,j,i,m/)
6183                 IF ( rad_angular_discretization ) THEN
6184                    gridsurf(isouth_u,k,j,i) = isurf
6185                 ENDIF
6186              ENDDO
6187              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6188                 k = surf_lsm_v(l)%k(m)
6189                 isurf = isurf + 1
6190                 surfl(:,isurf) = (/isouth_l,k,j,i,m/)
6191                 IF ( rad_angular_discretization ) THEN
6192                    gridsurf(isouth_u,k,j,i) = isurf
6193                 ENDIF
6194              ENDDO
6195
6196              l = 2
6197              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6198                 k = surf_usm_v(l)%k(m)
6199                 isurf = isurf + 1
6200                 surfl(:,isurf) = (/ieast_u,k,j,i,m/)
6201                 IF ( rad_angular_discretization ) THEN
6202                    gridsurf(ieast_u,k,j,i) = isurf
6203                 ENDIF
6204              ENDDO
6205              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6206                 k = surf_lsm_v(l)%k(m)
6207                 isurf = isurf + 1
6208                 surfl(:,isurf) = (/ieast_l,k,j,i,m/)
6209                 IF ( rad_angular_discretization ) THEN
6210                    gridsurf(ieast_u,k,j,i) = isurf
6211                 ENDIF
6212              ENDDO
6213
6214              l = 3
6215              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6216                 k = surf_usm_v(l)%k(m)
6217                 isurf = isurf + 1
6218                 surfl(:,isurf) = (/iwest_u,k,j,i,m/)
6219                 IF ( rad_angular_discretization ) THEN
6220                    gridsurf(iwest_u,k,j,i) = isurf
6221                 ENDIF
6222              ENDDO
6223              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6224                 k = surf_lsm_v(l)%k(m)
6225                 isurf = isurf + 1
6226                 surfl(:,isurf) = (/iwest_l,k,j,i,m/)
6227                 IF ( rad_angular_discretization ) THEN
6228                    gridsurf(iwest_u,k,j,i) = isurf
6229                 ENDIF
6230              ENDDO
6231           ENDDO
6232       ENDDO
6233!
6234!--    Add local MRT boxes for specified number of levels
6235       nmrtbl = 0
6236       IF ( mrt_nlevels > 0 )  THEN
6237          DO  i = nxl, nxr
6238             DO  j = nys, nyn
6239                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
6240!
6241!--                Skip roof if requested
6242                   IF ( mrt_skip_roof  .AND.  surf_usm_h%isroof_surf(m) )  CYCLE
6243!
6244!--                Cycle over specified no of levels
6245                   nmrtbl = nmrtbl + mrt_nlevels
6246                ENDDO
6247!
6248!--             Dtto for LSM
6249                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6250                   nmrtbl = nmrtbl + mrt_nlevels
6251                ENDDO
6252             ENDDO
6253          ENDDO
6254
6255          ALLOCATE( mrtbl(iz:ix,nmrtbl), mrtsky(nmrtbl), mrtskyt(nmrtbl), &
6256                    mrtinsw(nmrtbl), mrtinlw(nmrtbl), mrt(nmrtbl) )
6257
6258          imrt = 0
6259          DO  i = nxl, nxr
6260             DO  j = nys, nyn
6261                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
6262!
6263!--                Skip roof if requested
6264                   IF ( mrt_skip_roof  .AND.  surf_usm_h%isroof_surf(m) )  CYCLE
6265!
6266!--                Cycle over specified no of levels
6267                   l = surf_usm_h%k(m)
6268                   DO  k = l, l + mrt_nlevels - 1
6269                      imrt = imrt + 1
6270                      mrtbl(:,imrt) = (/k,j,i/)
6271                   ENDDO
6272                ENDDO
6273!
6274!--             Dtto for LSM
6275                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6276                   l = surf_lsm_h%k(m)
6277                   DO  k = l, l + mrt_nlevels - 1
6278                      imrt = imrt + 1
6279                      mrtbl(:,imrt) = (/k,j,i/)
6280                   ENDDO
6281                ENDDO
6282             ENDDO
6283          ENDDO
6284       ENDIF
6285
6286!
6287!--    broadband albedo of the land, roof and wall surface
6288!--    for domain border and sky set artifically to 1.0
6289!--    what allows us to calculate heat flux leaving over
6290!--    side and top borders of the domain
6291       ALLOCATE ( albedo_surf(nsurfl) )
6292       albedo_surf = 1.0_wp
6293!
6294!--    Also allocate further array for emissivity with identical order of
6295!--    surface elements as radiation arrays.
6296       ALLOCATE ( emiss_surf(nsurfl)  )
6297
6298
6299!
6300!--    global array surf of indices of surfaces and displacement index array surfstart
6301       ALLOCATE(nsurfs(0:numprocs-1))
6302
6303#if defined( __parallel )
6304       CALL MPI_Allgather(nsurfl,1,MPI_INTEGER,nsurfs,1,MPI_INTEGER,comm2d,ierr)
6305       IF ( ierr /= 0 ) THEN
6306         WRITE(9,*) 'Error MPI_AllGather1:', ierr, nsurfl, nsurfs
6307         FLUSH(9)
6308     ENDIF
6309
6310#else
6311       nsurfs(0) = nsurfl
6312#endif
6313       ALLOCATE(surfstart(0:numprocs))
6314       k = 0
6315       DO i=0,numprocs-1
6316           surfstart(i) = k
6317           k = k+nsurfs(i)
6318       ENDDO
6319       surfstart(numprocs) = k
6320       nsurf = k
6321       ALLOCATE(surf_l(5*nsurf))
6322       surf(1:5,1:nsurf) => surf_l(1:5*nsurf)
6323
6324#if defined( __parallel )
6325       CALL MPI_AllGatherv(surfl_l, nsurfl*5, MPI_INTEGER, surf_l, nsurfs*5, &
6326           surfstart(0:numprocs-1)*5, MPI_INTEGER, comm2d, ierr)
6327       IF ( ierr /= 0 ) THEN
6328           WRITE(9,*) 'Error MPI_AllGatherv4:', ierr, SIZE(surfl_l), nsurfl*5, &
6329                      SIZE(surf_l), nsurfs*5, surfstart(0:numprocs-1)*5
6330           FLUSH(9)
6331       ENDIF
6332#else
6333       surf = surfl
6334#endif
6335
6336!--
6337!--    allocation of the arrays for direct and diffusion radiation
6338       CALL location_message( '    allocation of radiation arrays', .TRUE. )
6339!--    rad_sw_in, rad_lw_in are computed in radiation model,
6340!--    splitting of direct and diffusion part is done
6341!--    in calc_diffusion_radiation for now
6342
6343       ALLOCATE( rad_sw_in_dir(nysg:nyng,nxlg:nxrg) )
6344       ALLOCATE( rad_sw_in_diff(nysg:nyng,nxlg:nxrg) )
6345       ALLOCATE( rad_lw_in_diff(nysg:nyng,nxlg:nxrg) )
6346       rad_sw_in_dir  = 0.0_wp
6347       rad_sw_in_diff = 0.0_wp
6348       rad_lw_in_diff = 0.0_wp
6349
6350!--    allocate radiation arrays
6351       ALLOCATE( surfins(nsurfl) )
6352       ALLOCATE( surfinl(nsurfl) )
6353       ALLOCATE( surfinsw(nsurfl) )
6354       ALLOCATE( surfinlw(nsurfl) )
6355       ALLOCATE( surfinswdir(nsurfl) )
6356       ALLOCATE( surfinswdif(nsurfl) )
6357       ALLOCATE( surfinlwdif(nsurfl) )
6358       ALLOCATE( surfoutsl(nsurfl) )
6359       ALLOCATE( surfoutll(nsurfl) )
6360       ALLOCATE( surfoutsw(nsurfl) )
6361       ALLOCATE( surfoutlw(nsurfl) )
6362       ALLOCATE( surfouts(nsurf) )
6363       ALLOCATE( surfoutl(nsurf) )
6364       ALLOCATE( surfinlg(nsurf) )
6365       ALLOCATE( skyvf(nsurfl) )
6366       ALLOCATE( skyvft(nsurfl) )
6367       ALLOCATE( surfemitlwl(nsurfl) )
6368
6369!
6370!--    In case of average_radiation, aggregated surface albedo and emissivity,
6371!--    also set initial value for t_rad_urb.
6372!--    For now set an arbitrary initial value.
6373       IF ( average_radiation )  THEN
6374          albedo_urb = 0.1_wp
6375          emissivity_urb = 0.9_wp
6376          t_rad_urb = pt_surface
6377       ENDIF
6378
6379    END SUBROUTINE radiation_interaction_init
6380
6381!------------------------------------------------------------------------------!
6382! Description:
6383! ------------
6384!> Calculates shape view factors (SVF), plant sink canopy factors (PCSF),
6385!> sky-view factors, discretized path for direct solar radiation, MRT factors
6386!> and other preprocessed data needed for radiation_interaction.
6387!------------------------------------------------------------------------------!
6388    SUBROUTINE radiation_calc_svf
6389   
6390        IMPLICIT NONE
6391       
6392        INTEGER(iwp)                                  :: i, j, k, d, ip, jp
6393        INTEGER(iwp)                                  :: isvf, ksvf, icsf, kcsf, npcsfl, isvf_surflt, imrt, imrtf, ipcgb
6394        INTEGER(iwp)                                  :: sd, td
6395        INTEGER(iwp)                                  :: iaz, izn      !< azimuth, zenith counters
6396        INTEGER(iwp)                                  :: naz, nzn      !< azimuth, zenith num of steps
6397        REAL(wp)                                      :: az0, zn0      !< starting azimuth/zenith
6398        REAL(wp)                                      :: azs, zns      !< azimuth/zenith cycle step
6399        REAL(wp)                                      :: az1, az2      !< relative azimuth of section borders
6400        REAL(wp)                                      :: azmid         !< ray (center) azimuth
6401        REAL(wp)                                      :: yxlen         !< |yxdir|
6402        REAL(wp), DIMENSION(2)                        :: yxdir         !< y,x *unit* vector of ray direction (in grid units)
6403        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zdirs         !< directions in z (tangent of elevation)
6404        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zcent         !< zenith angle centers
6405        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zbdry         !< zenith angle boundaries
6406        REAL(wp), DIMENSION(:), ALLOCATABLE           :: vffrac        !< view factor fractions for individual rays
6407        REAL(wp), DIMENSION(:), ALLOCATABLE           :: vffrac0       !< dtto (original values)
6408        REAL(wp), DIMENSION(:), ALLOCATABLE           :: ztransp       !< array of transparency in z steps
6409        INTEGER(iwp)                                  :: lowest_free_ray !< index into zdirs
6410        INTEGER(iwp), DIMENSION(:), ALLOCATABLE       :: itarget       !< face indices of detected obstacles
6411        INTEGER(iwp)                                  :: itarg0, itarg1
6412
6413        INTEGER(iwp)                                  :: udim
6414        INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET:: nzterrl_l
6415        INTEGER(iwp), DIMENSION(:,:), POINTER         :: nzterrl
6416        REAL(wp),     DIMENSION(:), ALLOCATABLE,TARGET:: csflt_l, pcsflt_l
6417        REAL(wp),     DIMENSION(:,:), POINTER         :: csflt, pcsflt
6418        INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET:: kcsflt_l,kpcsflt_l
6419        INTEGER(iwp), DIMENSION(:,:), POINTER         :: kcsflt,kpcsflt
6420        INTEGER(iwp), DIMENSION(:), ALLOCATABLE       :: icsflt,dcsflt,ipcsflt,dpcsflt
6421        REAL(wp), DIMENSION(3)                        :: uv
6422        LOGICAL                                       :: visible
6423        REAL(wp), DIMENSION(3)                        :: sa, ta          !< real coordinates z,y,x of source and target
6424        REAL(wp)                                      :: difvf           !< differential view factor
6425        REAL(wp)                                      :: transparency, rirrf, sqdist, svfsum
6426        INTEGER(iwp)                                  :: isurflt, isurfs, isurflt_prev
6427        INTEGER(idp)                                  :: ray_skip_maxdist, ray_skip_minval !< skipped raytracing counts
6428        INTEGER(iwp)                                  :: max_track_len !< maximum 2d track length
6429        INTEGER(iwp)                                  :: minfo
6430        REAL(wp), DIMENSION(:), POINTER               :: lad_s_rma       !< fortran 1D pointer
6431        TYPE(c_ptr)                                   :: lad_s_rma_p     !< allocated c pointer
6432#if defined( __parallel )
6433        INTEGER(kind=MPI_ADDRESS_KIND)                :: size_lad_rma
6434#endif
6435!   
6436        INTEGER(iwp), DIMENSION(0:svfnorm_report_num) :: svfnorm_counts
6437        CHARACTER(200)                                :: msg
6438
6439!--     calculation of the SVF
6440        CALL location_message( '    calculation of SVF and CSF', .TRUE. )
6441        CALL radiation_write_debug_log('Start calculation of SVF and CSF')
6442
6443!--     initialize variables and temporary arrays for calculation of svf and csf
6444        nsvfl  = 0
6445        ncsfl  = 0
6446        nsvfla = gasize
6447        msvf   = 1
6448        ALLOCATE( asvf1(nsvfla) )
6449        asvf => asvf1
6450        IF ( plant_canopy )  THEN
6451            ncsfla = gasize
6452            mcsf   = 1
6453            ALLOCATE( acsf1(ncsfla) )
6454            acsf => acsf1
6455        ENDIF
6456        nmrtf = 0
6457        IF ( mrt_nlevels > 0 )  THEN
6458           nmrtfa = gasize
6459           mmrtf = 1
6460           ALLOCATE ( amrtf1(nmrtfa) )
6461           amrtf => amrtf1
6462        ENDIF
6463        ray_skip_maxdist = 0
6464        ray_skip_minval = 0
6465       
6466!--     initialize temporary terrain and plant canopy height arrays (global 2D array!)
6467        ALLOCATE( nzterr(0:(nx+1)*(ny+1)-1) )
6468#if defined( __parallel )
6469        !ALLOCATE( nzterrl(nys:nyn,nxl:nxr) )
6470        ALLOCATE( nzterrl_l((nyn-nys+1)*(nxr-nxl+1)) )
6471        nzterrl(nys:nyn,nxl:nxr) => nzterrl_l(1:(nyn-nys+1)*(nxr-nxl+1))
6472        nzterrl = get_topography_top_index( 's' )
6473        CALL MPI_AllGather( nzterrl_l, nnx*nny, MPI_INTEGER, &
6474                            nzterr, nnx*nny, MPI_INTEGER, comm2d, ierr )
6475        IF ( ierr /= 0 ) THEN
6476            WRITE(9,*) 'Error MPI_AllGather1:', ierr, SIZE(nzterrl_l), nnx*nny, &
6477                       SIZE(nzterr), nnx*nny
6478            FLUSH(9)
6479        ENDIF
6480        DEALLOCATE(nzterrl_l)
6481#else
6482        nzterr = RESHAPE( get_topography_top_index( 's' ), (/(nx+1)*(ny+1)/) )
6483#endif
6484        IF ( plant_canopy )  THEN
6485            ALLOCATE( plantt(0:(nx+1)*(ny+1)-1) )
6486            maxboxesg = nx + ny + nzp + 1
6487            max_track_len = nx + ny + 1
6488!--         temporary arrays storing values for csf calculation during raytracing
6489            ALLOCATE( boxes(3, maxboxesg) )
6490            ALLOCATE( crlens(maxboxesg) )
6491
6492#if defined( __parallel )
6493            CALL MPI_AllGather( pct, nnx*nny, MPI_INTEGER, &
6494                                plantt, nnx*nny, MPI_INTEGER, comm2d, ierr )
6495            IF ( ierr /= 0 ) THEN
6496                WRITE(9,*) 'Error MPI_AllGather2:', ierr, SIZE(pct), nnx*nny, &
6497                           SIZE(plantt), nnx*nny
6498                FLUSH(9)
6499            ENDIF
6500
6501!--         temporary arrays storing values for csf calculation during raytracing
6502            ALLOCATE( lad_ip(maxboxesg) )
6503            ALLOCATE( lad_disp(maxboxesg) )
6504
6505            IF ( raytrace_mpi_rma )  THEN
6506                ALLOCATE( lad_s_ray(maxboxesg) )
6507               
6508                ! set conditions for RMA communication
6509                CALL MPI_Info_create(minfo, ierr)
6510                IF ( ierr /= 0 ) THEN
6511                    WRITE(9,*) 'Error MPI_Info_create2:', ierr
6512                    FLUSH(9)
6513                ENDIF
6514                CALL MPI_Info_set(minfo, 'accumulate_ordering', '', ierr)
6515                IF ( ierr /= 0 ) THEN
6516                    WRITE(9,*) 'Error MPI_Info_set5:', ierr
6517                    FLUSH(9)
6518                ENDIF
6519                CALL MPI_Info_set(minfo, 'accumulate_ops', 'same_op', ierr)
6520                IF ( ierr /= 0 ) THEN
6521                    WRITE(9,*) 'Error MPI_Info_set6:', ierr
6522                    FLUSH(9)
6523                ENDIF
6524                CALL MPI_Info_set(minfo, 'same_size', 'true', ierr)
6525                IF ( ierr /= 0 ) THEN
6526                    WRITE(9,*) 'Error MPI_Info_set7:', ierr
6527                    FLUSH(9)
6528                ENDIF
6529                CALL MPI_Info_set(minfo, 'same_disp_unit', 'true', ierr)
6530                IF ( ierr /= 0 ) THEN
6531                    WRITE(9,*) 'Error MPI_Info_set8:', ierr
6532                    FLUSH(9)
6533                ENDIF
6534
6535!--             Allocate and initialize the MPI RMA window
6536!--             must be in accordance with allocation of lad_s in plant_canopy_model
6537!--             optimization of memory should be done
6538!--             Argument X of function STORAGE_SIZE(X) needs arbitrary REAL(wp) value, set to 1.0_wp for now
6539                size_lad_rma = STORAGE_SIZE(1.0_wp)/8*nnx*nny*nzp
6540                CALL MPI_Win_allocate(size_lad_rma, STORAGE_SIZE(1.0_wp)/8, minfo, comm2d, &
6541                                        lad_s_rma_p, win_lad, ierr)
6542                IF ( ierr /= 0 ) THEN
6543                    WRITE(9,*) 'Error MPI_Win_allocate2:', ierr, size_lad_rma, &
6544                                STORAGE_SIZE(1.0_wp)/8, win_lad
6545                    FLUSH(9)
6546                ENDIF
6547                CALL c_f_pointer(lad_s_rma_p, lad_s_rma, (/ nzp*nny*nnx /))
6548                sub_lad(nzub:nzpt, nys:nyn, nxl:nxr) => lad_s_rma(1:nzp*nny*nnx)
6549            ELSE
6550                ALLOCATE(sub_lad(nzub:nzpt, nys:nyn, nxl:nxr))
6551            ENDIF
6552#else
6553            plantt = RESHAPE( pct(nys:nyn,nxl:nxr), (/(nx+1)*(ny+1)/) )
6554            ALLOCATE(sub_lad(nzub:nzpt, nys:nyn, nxl:nxr))
6555#endif
6556            plantt_max = MAXVAL(plantt)
6557            ALLOCATE( rt2_track(2, max_track_len), rt2_track_lad(nzub:plantt_max, max_track_len), &
6558                      rt2_track_dist(0:max_track_len), rt2_dist(plantt_max-nzub+2) )
6559
6560            sub_lad(:,:,:) = 0._wp
6561            DO i = nxl, nxr
6562                DO j = nys, nyn
6563                    k = get_topography_top_index_ji( j, i, 's' )
6564
6565                    sub_lad(k:nzpt, j, i) = lad_s(0:nzpt-k, j, i)
6566                ENDDO
6567            ENDDO
6568
6569#if defined( __parallel )
6570            IF ( raytrace_mpi_rma )  THEN
6571                CALL MPI_Info_free(minfo, ierr)
6572                IF ( ierr /= 0 ) THEN
6573                    WRITE(9,*) 'Error MPI_Info_free2:', ierr
6574                    FLUSH(9)
6575                ENDIF
6576                CALL MPI_Win_lock_all(0, win_lad, ierr)
6577                IF ( ierr /= 0 ) THEN
6578                    WRITE(9,*) 'Error MPI_Win_lock_all1:', ierr, win_lad
6579                    FLUSH(9)
6580                ENDIF
6581               
6582            ELSE
6583                ALLOCATE( sub_lad_g(0:(nx+1)*(ny+1)*nzp-1) )
6584                CALL MPI_AllGather( sub_lad, nnx*nny*nzp, MPI_REAL, &
6585                                    sub_lad_g, nnx*nny*nzp, MPI_REAL, comm2d, ierr )
6586                IF ( ierr /= 0 ) THEN
6587                    WRITE(9,*) 'Error MPI_AllGather3:', ierr, SIZE(sub_lad), &
6588                                nnx*nny*nzp, SIZE(sub_lad_g), nnx*nny*nzp
6589                    FLUSH(9)
6590                ENDIF
6591            ENDIF
6592#endif
6593        ENDIF
6594
6595!--     prepare the MPI_Win for collecting the surface indices
6596!--     from the reverse index arrays gridsurf from processors of target surfaces
6597#if defined( __parallel )
6598        IF ( rad_angular_discretization )  THEN
6599!
6600!--         raytrace_mpi_rma is asserted
6601            CALL MPI_Win_lock_all(0, win_gridsurf, ierr)
6602            IF ( ierr /= 0 ) THEN
6603                WRITE(9,*) 'Error MPI_Win_lock_all2:', ierr, win_gridsurf
6604                FLUSH(9)
6605            ENDIF
6606        ENDIF
6607#endif
6608
6609
6610        !--Directions opposite to face normals are not even calculated,
6611        !--they must be preset to 0
6612        !--
6613        dsitrans(:,:) = 0._wp
6614       
6615        DO isurflt = 1, nsurfl
6616!--         determine face centers
6617            td = surfl(id, isurflt)
6618            ta = (/ REAL(surfl(iz, isurflt), wp) - 0.5_wp * kdir(td),  &
6619                      REAL(surfl(iy, isurflt), wp) - 0.5_wp * jdir(td),  &
6620                      REAL(surfl(ix, isurflt), wp) - 0.5_wp * idir(td)  /)
6621
6622            !--Calculate sky view factor and raytrace DSI paths
6623            skyvf(isurflt) = 0._wp
6624            skyvft(isurflt) = 0._wp
6625
6626            !--Select a proper half-sphere for 2D raytracing
6627            SELECT CASE ( td )
6628               CASE ( iup_u, iup_l )
6629                  az0 = 0._wp
6630                  naz = raytrace_discrete_azims
6631                  azs = 2._wp * pi / REAL(naz, wp)
6632                  zn0 = 0._wp
6633                  nzn = raytrace_discrete_elevs / 2
6634                  zns = pi / 2._wp / REAL(nzn, wp)
6635               CASE ( isouth_u, isouth_l )
6636                  az0 = pi / 2._wp
6637                  naz = raytrace_discrete_azims / 2
6638                  azs = pi / REAL(naz, wp)
6639                  zn0 = 0._wp
6640                  nzn = raytrace_discrete_elevs
6641                  zns = pi / REAL(nzn, wp)
6642               CASE ( inorth_u, inorth_l )
6643                  az0 = - pi / 2._wp
6644                  naz = raytrace_discrete_azims / 2
6645                  azs = pi / REAL(naz, wp)
6646                  zn0 = 0._wp
6647                  nzn = raytrace_discrete_elevs
6648                  zns = pi / REAL(nzn, wp)
6649               CASE ( iwest_u, iwest_l )
6650                  az0 = pi
6651                  naz = raytrace_discrete_azims / 2
6652                  azs = pi / REAL(naz, wp)
6653                  zn0 = 0._wp
6654                  nzn = raytrace_discrete_elevs
6655                  zns = pi / REAL(nzn, wp)
6656               CASE ( ieast_u, ieast_l )
6657                  az0 = 0._wp
6658                  naz = raytrace_discrete_azims / 2
6659                  azs = pi / REAL(naz, wp)
6660                  zn0 = 0._wp
6661                  nzn = raytrace_discrete_elevs
6662                  zns = pi / REAL(nzn, wp)
6663               CASE DEFAULT
6664                  WRITE(message_string, *) 'ERROR: the surface type ', td,     &
6665                                           ' is not supported for calculating',&
6666                                           ' SVF'
6667                  CALL message( 'radiation_calc_svf', 'PA0488', 1, 2, 0, 6, 0 )
6668            END SELECT
6669
6670            ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), zbdry(0:nzn), vffrac(1:nzn*naz), &
6671                       ztransp(1:nzn*naz), itarget(1:nzn*naz) )   !FIXME allocate itarget only
6672                                                                  !in case of rad_angular_discretization
6673
6674            itarg0 = 1
6675            itarg1 = nzn
6676            zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
6677            zbdry(:) = (/( zn0+REAL(izn,wp)*zns, izn=0, nzn )/)
6678            IF ( td == iup_u  .OR.  td == iup_l )  THEN
6679               vffrac(1:nzn) = (COS(2 * zbdry(0:nzn-1)) - COS(2 * zbdry(1:nzn))) / 2._wp / REAL(naz, wp)
6680!
6681!--            For horizontal target, vf fractions are constant per azimuth
6682               DO iaz = 1, naz-1
6683                  vffrac(iaz*nzn+1:(iaz+1)*nzn) = vffrac(1:nzn)
6684               ENDDO
6685!--            sum of whole vffrac equals 1, verified
6686            ENDIF
6687!
6688!--         Calculate sky-view factor and direct solar visibility using 2D raytracing
6689            DO iaz = 1, naz
6690               azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
6691               IF ( td /= iup_u  .AND.  td /= iup_l )  THEN
6692                  az2 = REAL(iaz, wp) * azs - pi/2._wp
6693                  az1 = az2 - azs
6694                  !TODO precalculate after 1st line
6695                  vffrac(itarg0:itarg1) = (SIN(az2) - SIN(az1))               &
6696                              * (zbdry(1:nzn) - zbdry(0:nzn-1)                &
6697                                 + SIN(zbdry(0:nzn-1))*COS(zbdry(0:nzn-1))    &
6698                                 - SIN(zbdry(1:nzn))*COS(zbdry(1:nzn)))       &
6699                              / (2._wp * pi)
6700!--               sum of whole vffrac equals 1, verified
6701               ENDIF
6702               yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
6703               yxlen = SQRT(SUM(yxdir(:)**2))
6704               zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
6705               yxdir(:) = yxdir(:) / yxlen
6706
6707               CALL raytrace_2d(ta, yxdir, nzn, zdirs,                        &
6708                                    surfstart(myid) + isurflt, facearea(td),  &
6709                                    vffrac(itarg0:itarg1), .TRUE., .TRUE.,    &
6710                                    .FALSE., lowest_free_ray,                 &
6711                                    ztransp(itarg0:itarg1),                   &
6712                                    itarget(itarg0:itarg1))
6713
6714               skyvf(isurflt) = skyvf(isurflt) + &
6715                                SUM(vffrac(itarg0:itarg0+lowest_free_ray-1))
6716               skyvft(isurflt) = skyvft(isurflt) + &
6717                                 SUM(ztransp(itarg0:itarg0+lowest_free_ray-1) &
6718                                             * vffrac(itarg0:itarg0+lowest_free_ray-1))
6719 
6720!--            Save direct solar transparency
6721               j = MODULO(NINT(azmid/                                          &
6722                               (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
6723                          raytrace_discrete_azims)
6724
6725               DO k = 1, raytrace_discrete_elevs/2
6726                  i = dsidir_rev(k-1, j)
6727                  IF ( i /= -1  .AND.  k <= lowest_free_ray )  &
6728                     dsitrans(isurflt, i) = ztransp(itarg0+k-1)
6729               ENDDO
6730
6731!
6732!--            Advance itarget indices
6733               itarg0 = itarg1 + 1
6734               itarg1 = itarg1 + nzn
6735            ENDDO
6736
6737            IF ( rad_angular_discretization )  THEN
6738!--            sort itarget by face id
6739               CALL quicksort_itarget(itarget,vffrac,ztransp,1,nzn*naz)
6740!
6741!--            find the first valid position
6742               itarg0 = 1
6743               DO WHILE ( itarg0 <= nzn*naz )
6744                  IF ( itarget(itarg0) /= -1 )  EXIT
6745                  itarg0 = itarg0 + 1
6746               ENDDO
6747
6748               DO  i = itarg0, nzn*naz
6749!
6750!--               For duplicate values, only sum up vf fraction value
6751                  IF ( i < nzn*naz )  THEN
6752                     IF ( itarget(i+1) == itarget(i) )  THEN
6753                        vffrac(i+1) = vffrac(i+1) + vffrac(i)
6754                        CYCLE
6755                     ENDIF
6756                  ENDIF
6757!
6758!--               write to the svf array
6759                  nsvfl = nsvfl + 1
6760!--               check dimmension of asvf array and enlarge it if needed
6761                  IF ( nsvfla < nsvfl )  THEN
6762                     k = CEILING(REAL(nsvfla, kind=wp) * grow_factor)
6763                     IF ( msvf == 0 )  THEN
6764                        msvf = 1
6765                        ALLOCATE( asvf1(k) )
6766                        asvf => asvf1
6767                        asvf1(1:nsvfla) = asvf2
6768                        DEALLOCATE( asvf2 )
6769                     ELSE
6770                        msvf = 0
6771                        ALLOCATE( asvf2(k) )
6772                        asvf => asvf2
6773                        asvf2(1:nsvfla) = asvf1
6774                        DEALLOCATE( asvf1 )
6775                     ENDIF
6776
6777                     WRITE (msg,'(A,3I12)') 'Grow asvf:',nsvfl,nsvfla,k
6778                     CALL radiation_write_debug_log( msg )
6779                     
6780                     nsvfla = k
6781                  ENDIF
6782!--               write svf values into the array
6783                  asvf(nsvfl)%isurflt = isurflt
6784                  asvf(nsvfl)%isurfs = itarget(i)
6785                  asvf(nsvfl)%rsvf = vffrac(i)
6786                  asvf(nsvfl)%rtransp = ztransp(i)
6787               END DO
6788
6789            ENDIF ! rad_angular_discretization
6790
6791            DEALLOCATE ( zdirs, zcent, zbdry, vffrac, ztransp, itarget ) !FIXME itarget shall be allocated only
6792                                                                  !in case of rad_angular_discretization
6793!
6794!--         Following calculations only required for surface_reflections
6795            IF ( surface_reflections  .AND.  .NOT. rad_angular_discretization )  THEN
6796
6797               DO  isurfs = 1, nsurf
6798                  IF ( .NOT.  surface_facing(surfl(ix, isurflt), surfl(iy, isurflt), &
6799                     surfl(iz, isurflt), surfl(id, isurflt), &
6800                     surf(ix, isurfs), surf(iy, isurfs), &
6801                     surf(iz, isurfs), surf(id, isurfs)) )  THEN
6802                     CYCLE
6803                  ENDIF
6804                 
6805                  sd = surf(id, isurfs)
6806                  sa = (/ REAL(surf(iz, isurfs), wp) - 0.5_wp * kdir(sd),  &
6807                          REAL(surf(iy, isurfs), wp) - 0.5_wp * jdir(sd),  &
6808                          REAL(surf(ix, isurfs), wp) - 0.5_wp * idir(sd)  /)
6809
6810!--               unit vector source -> target
6811                  uv = (/ (ta(1)-sa(1))*dz(1), (ta(2)-sa(2))*dy, (ta(3)-sa(3))*dx /)
6812                  sqdist = SUM(uv(:)**2)
6813                  uv = uv / SQRT(sqdist)
6814
6815!--               reject raytracing above max distance
6816                  IF ( SQRT(sqdist) > max_raytracing_dist ) THEN
6817                     ray_skip_maxdist = ray_skip_maxdist + 1
6818                     CYCLE
6819                  ENDIF
6820                 
6821                  difvf = dot_product((/ kdir(sd), jdir(sd), idir(sd) /), uv) & ! cosine of source normal and direction
6822                      * dot_product((/ kdir(td), jdir(td), idir(td) /), -uv) &  ! cosine of target normal and reverse direction
6823                      / (pi * sqdist) ! square of distance between centers
6824!
6825!--               irradiance factor (our unshaded shape view factor) = view factor per differential target area * source area
6826                  rirrf = difvf * facearea(sd)
6827
6828!--               reject raytracing for potentially too small view factor values
6829                  IF ( rirrf < min_irrf_value ) THEN
6830                      ray_skip_minval = ray_skip_minval + 1
6831                      CYCLE
6832                  ENDIF
6833
6834!--               raytrace + process plant canopy sinks within
6835                  CALL raytrace(sa, ta, isurfs, difvf, facearea(td), .TRUE., &
6836                                visible, transparency)
6837
6838                  IF ( .NOT.  visible ) CYCLE
6839                 ! rsvf = rirrf * transparency
6840
6841!--               write to the svf array
6842                  nsvfl = nsvfl + 1
6843!--               check dimmension of asvf array and enlarge it if needed
6844                  IF ( nsvfla < nsvfl )  THEN
6845                     k = CEILING(REAL(nsvfla, kind=wp) * grow_factor)
6846                     IF ( msvf == 0 )  THEN
6847                        msvf = 1
6848                        ALLOCATE( asvf1(k) )
6849                        asvf => asvf1
6850                        asvf1(1:nsvfla) = asvf2
6851                        DEALLOCATE( asvf2 )
6852                     ELSE
6853                        msvf = 0
6854                        ALLOCATE( asvf2(k) )
6855                        asvf => asvf2
6856                        asvf2(1:nsvfla) = asvf1
6857                        DEALLOCATE( asvf1 )
6858                     ENDIF
6859
6860                     WRITE(msg,'(A,3I12)') 'Grow asvf:',nsvfl,nsvfla,k
6861                     CALL radiation_write_debug_log( msg )
6862                     
6863                     nsvfla = k
6864                  ENDIF
6865!--               write svf values into the array
6866                  asvf(nsvfl)%isurflt = isurflt
6867                  asvf(nsvfl)%isurfs = isurfs
6868                  asvf(nsvfl)%rsvf = rirrf !we postopne multiplication by transparency
6869                  asvf(nsvfl)%rtransp = transparency !a.k.a. Direct Irradiance Factor
6870               ENDDO
6871            ENDIF
6872        ENDDO
6873
6874!--
6875!--     Raytrace to canopy boxes to fill dsitransc TODO optimize
6876        dsitransc(:,:) = 0._wp
6877        az0 = 0._wp
6878        naz = raytrace_discrete_azims
6879        azs = 2._wp * pi / REAL(naz, wp)
6880        zn0 = 0._wp
6881        nzn = raytrace_discrete_elevs / 2
6882        zns = pi / 2._wp / REAL(nzn, wp)
6883        ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), vffrac(1:nzn), ztransp(1:nzn), &
6884               itarget(1:nzn) )
6885        zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
6886        vffrac(:) = 0._wp
6887
6888        DO  ipcgb = 1, npcbl
6889           ta = (/ REAL(pcbl(iz, ipcgb), wp),  &
6890                   REAL(pcbl(iy, ipcgb), wp),  &
6891                   REAL(pcbl(ix, ipcgb), wp) /)
6892!--        Calculate direct solar visibility using 2D raytracing
6893           DO  iaz = 1, naz
6894              azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
6895              yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
6896              yxlen = SQRT(SUM(yxdir(:)**2))
6897              zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
6898              yxdir(:) = yxdir(:) / yxlen
6899              CALL raytrace_2d(ta, yxdir, nzn, zdirs,                                &
6900                                   -999, -999._wp, vffrac, .FALSE., .FALSE., .TRUE., &
6901                                   lowest_free_ray, ztransp, itarget)
6902
6903!--           Save direct solar transparency
6904              j = MODULO(NINT(azmid/                                         &
6905                             (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
6906                         raytrace_discrete_azims)
6907              DO  k = 1, raytrace_discrete_elevs/2
6908                 i = dsidir_rev(k-1, j)
6909                 IF ( i /= -1  .AND.  k <= lowest_free_ray ) &
6910                    dsitransc(ipcgb, i) = ztransp(k)
6911              ENDDO
6912           ENDDO
6913        ENDDO
6914        DEALLOCATE ( zdirs, zcent, vffrac, ztransp, itarget )
6915!--
6916!--     Raytrace to MRT boxes
6917        IF ( nmrtbl > 0 )  THEN
6918           mrtdsit(:,:) = 0._wp
6919           mrtsky(:) = 0._wp
6920           mrtskyt(:) = 0._wp
6921           az0 = 0._wp
6922           naz = raytrace_discrete_azims
6923           azs = 2._wp * pi / REAL(naz, wp)
6924           zn0 = 0._wp
6925           nzn = raytrace_discrete_elevs
6926           zns = pi / REAL(nzn, wp)
6927           ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), zbdry(0:nzn), vffrac(1:nzn*naz), vffrac0(1:nzn), &
6928                      ztransp(1:nzn*naz), itarget(1:nzn*naz) )   !FIXME allocate itarget only
6929                                                                 !in case of rad_angular_discretization
6930
6931           zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
6932           zbdry(:) = (/( zn0+REAL(izn,wp)*zns, izn=0, nzn )/)
6933           vffrac0(:) = (COS(zbdry(0:nzn-1)) - COS(zbdry(1:nzn))) / 2._wp / REAL(naz, wp)
6934           !
6935           !--Modify direction weights to simulate human body (lower weight for top-down)
6936           IF ( mrt_geom_human )  THEN
6937              vffrac0(:) = vffrac0(:) * MAX(0._wp, SIN(zcent(:))*0.88_wp + COS(zcent(:))*0.12_wp)
6938              vffrac0(:) = vffrac0(:) / (SUM(vffrac0) * REAL(naz, wp))
6939           ENDIF
6940
6941           DO  imrt = 1, nmrtbl
6942              ta = (/ REAL(mrtbl(iz, imrt), wp),  &
6943                      REAL(mrtbl(iy, imrt), wp),  &
6944                      REAL(mrtbl(ix, imrt), wp) /)
6945!
6946!--           vf fractions are constant per azimuth
6947              DO iaz = 0, naz-1
6948                 vffrac(iaz*nzn+1:(iaz+1)*nzn) = vffrac0(:)
6949              ENDDO
6950!--           sum of whole vffrac equals 1, verified
6951              itarg0 = 1
6952              itarg1 = nzn
6953!
6954!--           Calculate sky-view factor and direct solar visibility using 2D raytracing
6955              DO  iaz = 1, naz
6956                 azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
6957                 yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
6958                 yxlen = SQRT(SUM(yxdir(:)**2))
6959                 zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
6960                 yxdir(:) = yxdir(:) / yxlen
6961
6962                 CALL raytrace_2d(ta, yxdir, nzn, zdirs,                         &
6963                                  -999, -999._wp, vffrac(itarg0:itarg1), .TRUE., &
6964                                  .FALSE., .TRUE., lowest_free_ray,              &
6965                                  ztransp(itarg0:itarg1),                        &
6966                                  itarget(itarg0:itarg1))
6967
6968!--              Sky view factors for MRT
6969                 mrtsky(imrt) = mrtsky(imrt) + &
6970                                  SUM(vffrac(itarg0:itarg0+lowest_free_ray-1))
6971                 mrtskyt(imrt) = mrtskyt(imrt) + &
6972                                   SUM(ztransp(itarg0:itarg0+lowest_free_ray-1) &
6973                                               * vffrac(itarg0:itarg0+lowest_free_ray-1))
6974!--              Direct solar transparency for MRT
6975                 j = MODULO(NINT(azmid/                                         &
6976                                (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
6977                            raytrace_discrete_azims)
6978                 DO  k = 1, raytrace_discrete_elevs/2
6979                    i = dsidir_rev(k-1, j)
6980                    IF ( i /= -1  .AND.  k <= lowest_free_ray ) &
6981                       mrtdsit(imrt, i) = ztransp(itarg0+k-1)
6982                 ENDDO
6983!
6984!--              Advance itarget indices
6985                 itarg0 = itarg1 + 1
6986                 itarg1 = itarg1 + nzn
6987              ENDDO
6988
6989!--           sort itarget by face id
6990              CALL quicksort_itarget(itarget,vffrac,ztransp,1,nzn*naz)
6991!
6992!--           find the first valid position
6993              itarg0 = 1
6994              DO WHILE ( itarg0 <= nzn*naz )
6995                 IF ( itarget(itarg0) /= -1 )  EXIT
6996                 itarg0 = itarg0 + 1
6997              ENDDO
6998
6999              DO  i = itarg0, nzn*naz
7000!
7001!--              For duplicate values, only sum up vf fraction value
7002                 IF ( i < nzn*naz )  THEN
7003                    IF ( itarget(i+1) == itarget(i) )  THEN
7004                       vffrac(i+1) = vffrac(i+1) + vffrac(i)
7005                       CYCLE
7006                    ENDIF
7007                 ENDIF
7008!
7009!--              write to the mrtf array
7010                 nmrtf = nmrtf + 1
7011!--              check dimmension of mrtf array and enlarge it if needed
7012                 IF ( nmrtfa < nmrtf )  THEN
7013                    k = CEILING(REAL(nmrtfa, kind=wp) * grow_factor)
7014                    IF ( mmrtf == 0 )  THEN
7015                       mmrtf = 1
7016                       ALLOCATE( amrtf1(k) )
7017                       amrtf => amrtf1
7018                       amrtf1(1:nmrtfa) = amrtf2
7019                       DEALLOCATE( amrtf2 )
7020                    ELSE
7021                       mmrtf = 0
7022                       ALLOCATE( amrtf2(k) )
7023                       amrtf => amrtf2
7024                       amrtf2(1:nmrtfa) = amrtf1
7025                       DEALLOCATE( amrtf1 )
7026                    ENDIF
7027
7028                    WRITE (msg,'(A,3I12)') 'Grow amrtf:', nmrtf, nmrtfa, k
7029                    CALL radiation_write_debug_log( msg )
7030
7031                    nmrtfa = k
7032                 ENDIF
7033!--              write mrtf values into the array
7034                 amrtf(nmrtf)%isurflt = imrt
7035                 amrtf(nmrtf)%isurfs = itarget(i)
7036                 amrtf(nmrtf)%rsvf = vffrac(i)
7037                 amrtf(nmrtf)%rtransp = ztransp(i)
7038              ENDDO ! itarg
7039
7040           ENDDO ! imrt
7041           DEALLOCATE ( zdirs, zcent, zbdry, vffrac, vffrac0, ztransp, itarget )
7042!
7043!--        Move MRT factors to final arrays
7044           ALLOCATE ( mrtf(nmrtf), mrtft(nmrtf), mrtfsurf(2,nmrtf) )
7045           DO  imrtf = 1, nmrtf
7046              mrtf(imrtf) = amrtf(imrtf)%rsvf
7047              mrtft(imrtf) = amrtf(imrtf)%rsvf * amrtf(imrtf)%rtransp
7048              mrtfsurf(:,imrtf) = (/amrtf(imrtf)%isurflt, amrtf(imrtf)%isurfs /)
7049           ENDDO
7050           IF ( ALLOCATED(amrtf1) )  DEALLOCATE( amrtf1 )
7051           IF ( ALLOCATED(amrtf2) )  DEALLOCATE( amrtf2 )
7052        ENDIF ! nmrtbl > 0
7053
7054        IF ( rad_angular_discretization )  THEN
7055#if defined( __parallel )
7056!--        finalize MPI_RMA communication established to get global index of the surface from grid indices
7057!--        flush all MPI window pending requests
7058           CALL MPI_Win_flush_all(win_gridsurf, ierr)
7059           IF ( ierr /= 0 ) THEN
7060               WRITE(9,*) 'Error MPI_Win_flush_all1:', ierr, win_gridsurf
7061               FLUSH(9)
7062           ENDIF
7063!--        unlock MPI window
7064           CALL MPI_Win_unlock_all(win_gridsurf, ierr)
7065           IF ( ierr /= 0 ) THEN
7066               WRITE(9,*) 'Error MPI_Win_unlock_all1:', ierr, win_gridsurf
7067               FLUSH(9)
7068           ENDIF
7069!--        free MPI window
7070           CALL MPI_Win_free(win_gridsurf, ierr)
7071           IF ( ierr /= 0 ) THEN
7072               WRITE(9,*) 'Error MPI_Win_free1:', ierr, win_gridsurf
7073               FLUSH(9)
7074           ENDIF
7075#else
7076           DEALLOCATE ( gridsurf )
7077#endif
7078        ENDIF
7079
7080        CALL radiation_write_debug_log( 'End of calculation SVF' )
7081        WRITE(msg, *) 'Raytracing skipped for maximum distance of ', &
7082           max_raytracing_dist, ' m on ', ray_skip_maxdist, ' pairs.'
7083        CALL radiation_write_debug_log( msg )
7084        WRITE(msg, *) 'Raytracing skipped for minimum potential value of ', &
7085           min_irrf_value , ' on ', ray_skip_minval, ' pairs.'
7086        CALL radiation_write_debug_log( msg )
7087
7088        CALL location_message( '    waiting for completion of SVF and CSF calculation in all processes', .TRUE. )
7089!--     deallocate temporary global arrays
7090        DEALLOCATE(nzterr)
7091       
7092        IF ( plant_canopy )  THEN
7093!--         finalize mpi_rma communication and deallocate temporary arrays
7094#if defined( __parallel )
7095            IF ( raytrace_mpi_rma )  THEN
7096                CALL MPI_Win_flush_all(win_lad, ierr)
7097                IF ( ierr /= 0 ) THEN
7098                    WRITE(9,*) 'Error MPI_Win_flush_all2:', ierr, win_lad
7099                    FLUSH(9)
7100                ENDIF
7101!--             unlock MPI window
7102                CALL MPI_Win_unlock_all(win_lad, ierr)
7103                IF ( ierr /= 0 ) THEN
7104                    WRITE(9,*) 'Error MPI_Win_unlock_all2:', ierr, win_lad
7105                    FLUSH(9)
7106                ENDIF
7107!--             free MPI window
7108                CALL MPI_Win_free(win_lad, ierr)
7109                IF ( ierr /= 0 ) THEN
7110                    WRITE(9,*) 'Error MPI_Win_free2:', ierr, win_lad
7111                    FLUSH(9)
7112                ENDIF
7113!--             deallocate temporary arrays storing values for csf calculation during raytracing
7114                DEALLOCATE( lad_s_ray )
7115!--             sub_lad is the pointer to lad_s_rma in case of raytrace_mpi_rma
7116!--             and must not be deallocated here
7117            ELSE
7118                DEALLOCATE(sub_lad)
7119                DEALLOCATE(sub_lad_g)
7120            ENDIF
7121#else
7122            DEALLOCATE(sub_lad)
7123#endif
7124            DEALLOCATE( boxes )
7125            DEALLOCATE( crlens )
7126            DEALLOCATE( plantt )
7127            DEALLOCATE( rt2_track, rt2_track_lad, rt2_track_dist, rt2_dist )
7128        ENDIF
7129
7130        CALL location_message( '    calculation of the complete SVF array', .TRUE. )
7131
7132        IF ( rad_angular_discretization )  THEN
7133           CALL radiation_write_debug_log( 'Load svf from the structure array to plain arrays' )
7134           ALLOCATE( svf(ndsvf,nsvfl) )
7135           ALLOCATE( svfsurf(idsvf,nsvfl) )
7136
7137           DO isvf = 1, nsvfl
7138               svf(:, isvf) = (/ asvf(isvf)%rsvf, asvf(isvf)%rtransp /)
7139               svfsurf(:, isvf) = (/ asvf(isvf)%isurflt, asvf(isvf)%isurfs /)
7140           ENDDO
7141        ELSE
7142           CALL radiation_write_debug_log( 'Start SVF sort' )
7143!--        sort svf ( a version of quicksort )
7144           CALL quicksort_svf(asvf,1,nsvfl)
7145
7146           !< load svf from the structure array to plain arrays
7147           CALL radiation_write_debug_log( 'Load svf from the structure array to plain arrays' )
7148           ALLOCATE( svf(ndsvf,nsvfl) )
7149           ALLOCATE( svfsurf(idsvf,nsvfl) )
7150           svfnorm_counts(:) = 0._wp
7151           isurflt_prev = -1
7152           ksvf = 1
7153           svfsum = 0._wp
7154           DO isvf = 1, nsvfl
7155!--            normalize svf per target face
7156               IF ( asvf(ksvf)%isurflt /= isurflt_prev )  THEN
7157                   IF ( isurflt_prev /= -1  .AND.  svfsum /= 0._wp )  THEN
7158                       !< update histogram of logged svf normalization values
7159                       i = searchsorted(svfnorm_report_thresh, svfsum / (1._wp-skyvf(isurflt_prev)))
7160                       svfnorm_counts(i) = svfnorm_counts(i) + 1
7161
7162                       svf(1, isvf_surflt:isvf-1) = svf(1, isvf_surflt:isvf-1) / svfsum * (1._wp-skyvf(isurflt_prev))
7163                   ENDIF
7164                   isurflt_prev = asvf(ksvf)%isurflt
7165                   isvf_surflt = isvf
7166                   svfsum = asvf(ksvf)%rsvf !?? / asvf(ksvf)%rtransp
7167               ELSE
7168                   svfsum = svfsum + asvf(ksvf)%rsvf !?? / asvf(ksvf)%rtransp
7169               ENDIF
7170
7171               svf(:, isvf) = (/ asvf(ksvf)%rsvf, asvf(ksvf)%rtransp /)
7172               svfsurf(:, isvf) = (/ asvf(ksvf)%isurflt, asvf(ksvf)%isurfs /)
7173
7174!--            next element
7175               ksvf = ksvf + 1
7176           ENDDO
7177
7178           IF ( isurflt_prev /= -1  .AND.  svfsum /= 0._wp )  THEN
7179               i = searchsorted(svfnorm_report_thresh, svfsum / (1._wp-skyvf(isurflt_prev)))
7180               svfnorm_counts(i) = svfnorm_counts(i) + 1
7181
7182               svf(1, isvf_surflt:nsvfl) = svf(1, isvf_surflt:nsvfl) / svfsum * (1._wp-skyvf(isurflt_prev))
7183           ENDIF
7184           WRITE(9, *) 'SVF normalization histogram:', svfnorm_counts,  &
7185                       'on thresholds:', svfnorm_report_thresh(1:svfnorm_report_num), '(val < thresh <= val)'
7186           !TODO we should be able to deallocate skyvf, from now on we only need skyvft
7187        ENDIF ! rad_angular_discretization
7188
7189!--     deallocate temporary asvf array
7190!--     DEALLOCATE(asvf) - ifort has a problem with deallocation of allocatable target
7191!--     via pointing pointer - we need to test original targets
7192        IF ( ALLOCATED(asvf1) )  THEN
7193            DEALLOCATE(asvf1)
7194        ENDIF
7195        IF ( ALLOCATED(asvf2) )  THEN
7196            DEALLOCATE(asvf2)
7197        ENDIF
7198
7199        npcsfl = 0
7200        IF ( plant_canopy )  THEN
7201
7202            CALL location_message( '    calculation of the complete CSF array', .TRUE. )
7203            CALL radiation_write_debug_log( 'Calculation of the complete CSF array' )
7204!--         sort and merge csf for the last time, keeping the array size to minimum
7205            CALL merge_and_grow_csf(-1)
7206           
7207!--         aggregate csb among processors
7208!--         allocate necessary arrays
7209            udim = max(ncsfl,1)
7210            ALLOCATE( csflt_l(ndcsf*udim) )
7211            csflt(1:ndcsf,1:udim) => csflt_l(1:ndcsf*udim)
7212            ALLOCATE( kcsflt_l(kdcsf*udim) )
7213            kcsflt(1:kdcsf,1:udim) => kcsflt_l(1:kdcsf*udim)
7214            ALLOCATE( icsflt(0:numprocs-1) )
7215            ALLOCATE( dcsflt(0:numprocs-1) )
7216            ALLOCATE( ipcsflt(0:numprocs-1) )
7217            ALLOCATE( dpcsflt(0:numprocs-1) )
7218           
7219!--         fill out arrays of csf values and
7220!--         arrays of number of elements and displacements
7221!--         for particular precessors
7222            icsflt = 0
7223            dcsflt = 0
7224            ip = -1
7225            j = -1
7226            d = 0
7227            DO kcsf = 1, ncsfl
7228                j = j+1
7229                IF ( acsf(kcsf)%ip /= ip )  THEN
7230!--                 new block of the processor
7231!--                 number of elements of previous block
7232                    IF ( ip>=0) icsflt(ip) = j
7233                    d = d+j
7234!--                 blank blocks
7235                    DO jp = ip+1, acsf(kcsf)%ip-1
7236!--                     number of elements is zero, displacement is equal to previous
7237                        icsflt(jp) = 0
7238                        dcsflt(jp) = d
7239                    ENDDO
7240!--                 the actual block
7241                    ip = acsf(kcsf)%ip
7242                    dcsflt(ip) = d
7243                    j = 0
7244                ENDIF
7245                csflt(1,kcsf) = acsf(kcsf)%rcvf
7246!--             fill out integer values of itz,ity,itx,isurfs
7247                kcsflt(1,kcsf) = acsf(kcsf)%itz
7248                kcsflt(2,kcsf) = acsf(kcsf)%ity
7249                kcsflt(3,kcsf) = acsf(kcsf)%itx
7250                kcsflt(4,kcsf) = acsf(kcsf)%isurfs
7251            ENDDO
7252!--         last blank blocks at the end of array
7253            j = j+1
7254            IF ( ip>=0 ) icsflt(ip) = j
7255            d = d+j
7256            DO jp = ip+1, numprocs-1
7257!--             number of elements is zero, displacement is equal to previous
7258                icsflt(jp) = 0
7259                dcsflt(jp) = d
7260            ENDDO
7261           
7262!--         deallocate temporary acsf array
7263!--         DEALLOCATE(acsf) - ifort has a problem with deallocation of allocatable target
7264!--         via pointing pointer - we need to test original targets
7265            IF ( ALLOCATED(acsf1) )  THEN
7266                DEALLOCATE(acsf1)
7267            ENDIF
7268            IF ( ALLOCATED(acsf2) )  THEN
7269                DEALLOCATE(acsf2)
7270            ENDIF
7271                   
7272#if defined( __parallel )
7273!--         scatter and gather the number of elements to and from all processor
7274!--         and calculate displacements
7275            CALL radiation_write_debug_log( 'Scatter and gather the number of elements to and from all processor' )
7276            CALL MPI_AlltoAll(icsflt,1,MPI_INTEGER,ipcsflt,1,MPI_INTEGER,comm2d, ierr)
7277            IF ( ierr /= 0 ) THEN
7278                WRITE(9,*) 'Error MPI_AlltoAll1:', ierr, SIZE(icsflt), SIZE(ipcsflt)
7279                FLUSH(9)
7280            ENDIF
7281
7282            npcsfl = SUM(ipcsflt)
7283            d = 0
7284            DO i = 0, numprocs-1
7285                dpcsflt(i) = d
7286                d = d + ipcsflt(i)
7287            ENDDO
7288
7289!--         exchange csf fields between processors
7290            CALL radiation_write_debug_log( 'Exchange csf fields between processors' )
7291            udim = max(npcsfl,1)
7292            ALLOCATE( pcsflt_l(ndcsf*udim) )
7293            pcsflt(1:ndcsf,1:udim) => pcsflt_l(1:ndcsf*udim)
7294            ALLOCATE( kpcsflt_l(kdcsf*udim) )
7295            kpcsflt(1:kdcsf,1:udim) => kpcsflt_l(1:kdcsf*udim)
7296            CALL MPI_AlltoAllv(csflt_l, ndcsf*icsflt, ndcsf*dcsflt, MPI_REAL, &
7297                pcsflt_l, ndcsf*ipcsflt, ndcsf*dpcsflt, MPI_REAL, comm2d, ierr)
7298            IF ( ierr /= 0 ) THEN
7299                WRITE(9,*) 'Error MPI_AlltoAllv1:', ierr, SIZE(ipcsflt), ndcsf*icsflt, &
7300                            ndcsf*dcsflt, SIZE(pcsflt_l),ndcsf*ipcsflt, ndcsf*dpcsflt
7301                FLUSH(9)
7302            ENDIF
7303
7304            CALL MPI_AlltoAllv(kcsflt_l, kdcsf*icsflt, kdcsf*dcsflt, MPI_INTEGER, &
7305                kpcsflt_l, kdcsf*ipcsflt, kdcsf*dpcsflt, MPI_INTEGER, comm2d, ierr)
7306            IF ( ierr /= 0 ) THEN
7307                WRITE(9,*) 'Error MPI_AlltoAllv2:', ierr, SIZE(kcsflt_l),kdcsf*icsflt, &
7308                           kdcsf*dcsflt, SIZE(kpcsflt_l), kdcsf*ipcsflt, kdcsf*dpcsflt
7309                FLUSH(9)
7310            ENDIF
7311           
7312#else
7313            npcsfl = ncsfl
7314            ALLOCATE( pcsflt(ndcsf,max(npcsfl,ndcsf)) )
7315            ALLOCATE( kpcsflt(kdcsf,max(npcsfl,kdcsf)) )
7316            pcsflt = csflt
7317            kpcsflt = kcsflt
7318#endif
7319
7320!--         deallocate temporary arrays
7321            DEALLOCATE( csflt_l )
7322            DEALLOCATE( kcsflt_l )
7323            DEALLOCATE( icsflt )
7324            DEALLOCATE( dcsflt )
7325            DEALLOCATE( ipcsflt )
7326            DEALLOCATE( dpcsflt )
7327
7328!--         sort csf ( a version of quicksort )
7329            CALL radiation_write_debug_log( 'Sort csf' )
7330            CALL quicksort_csf2(kpcsflt, pcsflt, 1, npcsfl)
7331
7332!--         aggregate canopy sink factor records with identical box & source
7333!--         againg across all values from all processors
7334            CALL radiation_write_debug_log( 'Aggregate canopy sink factor records with identical box' )
7335
7336            IF ( npcsfl > 0 )  THEN
7337                icsf = 1 !< reading index
7338                kcsf = 1 !< writing index
7339                DO while (icsf < npcsfl)
7340!--                 here kpcsf(kcsf) already has values from kpcsf(icsf)
7341                    IF ( kpcsflt(3,icsf) == kpcsflt(3,icsf+1)  .AND.  &
7342                         kpcsflt(2,icsf) == kpcsflt(2,icsf+1)  .AND.  &
7343                         kpcsflt(1,icsf) == kpcsflt(1,icsf+1)  .AND.  &
7344                         kpcsflt(4,icsf) == kpcsflt(4,icsf+1) )  THEN
7345
7346                        pcsflt(1,kcsf) = pcsflt(1,kcsf) + pcsflt(1,icsf+1)
7347
7348!--                     advance reading index, keep writing index
7349                        icsf = icsf + 1
7350                    ELSE
7351!--                     not identical, just advance and copy
7352                        icsf = icsf + 1
7353                        kcsf = kcsf + 1
7354                        kpcsflt(:,kcsf) = kpcsflt(:,icsf)
7355                        pcsflt(:,kcsf) = pcsflt(:,icsf)
7356                    ENDIF
7357                ENDDO
7358!--             last written item is now also the last item in valid part of array
7359                npcsfl = kcsf
7360            ENDIF
7361
7362            ncsfl = npcsfl
7363            IF ( ncsfl > 0 )  THEN
7364                ALLOCATE( csf(ndcsf,ncsfl) )
7365                ALLOCATE( csfsurf(idcsf,ncsfl) )
7366                DO icsf = 1, ncsfl
7367                    csf(:,icsf) = pcsflt(:,icsf)
7368                    csfsurf(1,icsf) =  gridpcbl(kpcsflt(1,icsf),kpcsflt(2,icsf),kpcsflt(3,icsf))
7369                    csfsurf(2,icsf) =  kpcsflt(4,icsf)
7370                ENDDO
7371            ENDIF
7372           
7373!--         deallocation of temporary arrays
7374            IF ( npcbl > 0 )  DEALLOCATE( gridpcbl )
7375            DEALLOCATE( pcsflt_l )
7376            DEALLOCATE( kpcsflt_l )
7377            CALL radiation_write_debug_log( 'End of aggregate csf' )
7378           
7379        ENDIF
7380
7381#if defined( __parallel )
7382        CALL MPI_BARRIER( comm2d, ierr )
7383#endif
7384        CALL radiation_write_debug_log( 'End of radiation_calc_svf (after mpi_barrier)' )
7385
7386        RETURN
7387       
7388!        WRITE( message_string, * )  &
7389!            'I/O error when processing shape view factors / ',  &
7390!            'plant canopy sink factors / direct irradiance factors.'
7391!        CALL message( 'init_urban_surface', 'PA0502', 2, 2, 0, 6, 0 )
7392       
7393    END SUBROUTINE radiation_calc_svf
7394
7395   
7396!------------------------------------------------------------------------------!
7397! Description:
7398! ------------
7399!> Raytracing for detecting obstacles and calculating compound canopy sink
7400!> factors. (A simple obstacle detection would only need to process faces in
7401!> 3 dimensions without any ordering.)
7402!> Assumtions:
7403!> -----------
7404!> 1. The ray always originates from a face midpoint (only one coordinate equals
7405!>    *.5, i.e. wall) and doesn't travel parallel to the surface (that would mean
7406!>    shape factor=0). Therefore, the ray may never travel exactly along a face
7407!>    or an edge.
7408!> 2. From grid bottom to urban surface top the grid has to be *equidistant*
7409!>    within each of the dimensions, including vertical (but the resolution
7410!>    doesn't need to be the same in all three dimensions).
7411!------------------------------------------------------------------------------!
7412    SUBROUTINE raytrace(src, targ, isrc, difvf, atarg, create_csf, visible, transparency)
7413        IMPLICIT NONE
7414
7415        REAL(wp), DIMENSION(3), INTENT(in)     :: src, targ    !< real coordinates z,y,x
7416        INTEGER(iwp), INTENT(in)               :: isrc         !< index of source face for csf
7417        REAL(wp), INTENT(in)                   :: difvf        !< differential view factor for csf
7418        REAL(wp), INTENT(in)                   :: atarg        !< target surface area for csf
7419        LOGICAL, INTENT(in)                    :: create_csf   !< whether to generate new CSFs during raytracing
7420        LOGICAL, INTENT(out)                   :: visible
7421        REAL(wp), INTENT(out)                  :: transparency !< along whole path
7422        INTEGER(iwp)                           :: i, k, d
7423        INTEGER(iwp)                           :: seldim       !< dimension to be incremented
7424        INTEGER(iwp)                           :: ncsb         !< no of written plant canopy sinkboxes
7425        INTEGER(iwp)                           :: maxboxes     !< max no of gridboxes visited
7426        REAL(wp)                               :: distance     !< euclidean along path
7427        REAL(wp)                               :: crlen        !< length of gridbox crossing
7428        REAL(wp)                               :: lastdist     !< beginning of current crossing
7429        REAL(wp)                               :: nextdist     !< end of current crossing
7430        REAL(wp)                               :: realdist     !< distance in meters per unit distance
7431        REAL(wp)                               :: crmid        !< midpoint of crossing
7432        REAL(wp)                               :: cursink      !< sink factor for current canopy box
7433        REAL(wp), DIMENSION(3)                 :: delta        !< path vector
7434        REAL(wp), DIMENSION(3)                 :: uvect        !< unit vector
7435        REAL(wp), DIMENSION(3)                 :: dimnextdist  !< distance for each dimension increments
7436        INTEGER(iwp), DIMENSION(3)             :: box          !< gridbox being crossed
7437        INTEGER(iwp), DIMENSION(3)             :: dimnext      !< next dimension increments along path
7438        INTEGER(iwp), DIMENSION(3)             :: dimdelta     !< dimension direction = +- 1
7439        INTEGER(iwp)                           :: px, py       !< number of processors in x and y dir before
7440                                                               !< the processor in the question
7441        INTEGER(iwp)                           :: ip           !< number of processor where gridbox reside
7442        INTEGER(iwp)                           :: ig           !< 1D index of gridbox in global 2D array
7443       
7444        REAL(wp)                               :: eps = 1E-10_wp !< epsilon for value comparison
7445        REAL(wp)                               :: lad_s_target   !< recieved lad_s of particular grid box
7446
7447!
7448!--     Maximum number of gridboxes visited equals to maximum number of boundaries crossed in each dimension plus one. That's also
7449!--     the maximum number of plant canopy boxes written. We grow the acsf array accordingly using exponential factor.
7450        maxboxes = SUM(ABS(NINT(targ, iwp) - NINT(src, iwp))) + 1
7451        IF ( plant_canopy  .AND.  ncsfl + maxboxes > ncsfla )  THEN
7452!--         use this code for growing by fixed exponential increments (equivalent to case where ncsfl always increases by 1)
7453!--         k = CEILING(grow_factor ** real(CEILING(log(real(ncsfl + maxboxes, kind=wp)) &
7454!--                                                / log(grow_factor)), kind=wp))
7455!--         or use this code to simply always keep some extra space after growing
7456            k = CEILING(REAL(ncsfl + maxboxes, kind=wp) * grow_factor)
7457
7458            CALL merge_and_grow_csf(k)
7459        ENDIF
7460       
7461        transparency = 1._wp
7462        ncsb = 0
7463
7464        delta(:) = targ(:) - src(:)
7465        distance = SQRT(SUM(delta(:)**2))
7466        IF ( distance == 0._wp )  THEN
7467            visible = .TRUE.
7468            RETURN
7469        ENDIF
7470        uvect(:) = delta(:) / distance
7471        realdist = SQRT(SUM( (uvect(:)*(/dz(1),dy,dx/))**2 ))
7472
7473        lastdist = 0._wp
7474
7475!--     Since all face coordinates have values *.5 and we'd like to use
7476!--     integers, all these have .5 added
7477        DO d = 1, 3
7478            IF ( uvect(d) == 0._wp )  THEN
7479                dimnext(d) = 999999999
7480                dimdelta(d) = 999999999
7481                dimnextdist(d) = 1.0E20_wp
7482            ELSE IF ( uvect(d) > 0._wp )  THEN
7483                dimnext(d) = CEILING(src(d) + .5_wp)
7484                dimdelta(d) = 1
7485                dimnextdist(d) = (dimnext(d) - .5_wp - src(d)) / uvect(d)
7486            ELSE
7487                dimnext(d) = FLOOR(src(d) + .5_wp)
7488                dimdelta(d) = -1
7489                dimnextdist(d) = (dimnext(d) - .5_wp - src(d)) / uvect(d)
7490            ENDIF
7491        ENDDO
7492
7493        DO
7494!--         along what dimension will the next wall crossing be?
7495            seldim = minloc(dimnextdist, 1)
7496            nextdist = dimnextdist(seldim)
7497            IF ( nextdist > distance ) nextdist = distance
7498
7499            crlen = nextdist - lastdist
7500            IF ( crlen > .001_wp )  THEN
7501                crmid = (lastdist + nextdist) * .5_wp
7502                box = NINT(src(:) + uvect(:) * crmid, iwp)
7503
7504!--             calculate index of the grid with global indices (box(2),box(3))
7505!--             in the array nzterr and plantt and id of the coresponding processor
7506                px = box(3)/nnx
7507                py = box(2)/nny
7508                ip = px*pdims(2)+py
7509                ig = ip*nnx*nny + (box(3)-px*nnx)*nny + box(2)-py*nny
7510                IF ( box(1) <= nzterr(ig) )  THEN
7511                    visible = .FALSE.
7512                    RETURN
7513                ENDIF
7514
7515                IF ( plant_canopy )  THEN
7516                    IF ( box(1) <= plantt(ig) )  THEN
7517                        ncsb = ncsb + 1
7518                        boxes(:,ncsb) = box
7519                        crlens(ncsb) = crlen
7520#if defined( __parallel )
7521                        lad_ip(ncsb) = ip
7522                        lad_disp(ncsb) = (box(3)-px*nnx)*(nny*nzp) + (box(2)-py*nny)*nzp + box(1)-nzub
7523#endif
7524                    ENDIF
7525                ENDIF
7526            ENDIF
7527
7528            IF ( ABS(distance - nextdist) < eps )  EXIT
7529            lastdist = nextdist
7530            dimnext(seldim) = dimnext(seldim) + dimdelta(seldim)
7531            dimnextdist(seldim) = (dimnext(seldim) - .5_wp - src(seldim)) / uvect(seldim)
7532        ENDDO
7533       
7534        IF ( plant_canopy )  THEN
7535#if defined( __parallel )
7536            IF ( raytrace_mpi_rma )  THEN
7537!--             send requests for lad_s to appropriate processor
7538                CALL cpu_log( log_point_s(77), 'rad_rma_lad', 'start' )
7539                DO i = 1, ncsb
7540                    CALL MPI_Get(lad_s_ray(i), 1, MPI_REAL, lad_ip(i), lad_disp(i), &
7541                                 1, MPI_REAL, win_lad, ierr)
7542                    IF ( ierr /= 0 )  THEN
7543                        WRITE(9,*) 'Error MPI_Get1:', ierr, lad_s_ray(i), &
7544                                   lad_ip(i), lad_disp(i), win_lad
7545                        FLUSH(9)
7546                    ENDIF
7547                ENDDO
7548               
7549!--             wait for all pending local requests complete
7550                CALL MPI_Win_flush_local_all(win_lad, ierr)
7551                IF ( ierr /= 0 )  THEN
7552                    WRITE(9,*) 'Error MPI_Win_flush_local_all1:', ierr, win_lad
7553                    FLUSH(9)
7554                ENDIF
7555                CALL cpu_log( log_point_s(77), 'rad_rma_lad', 'stop' )
7556               
7557            ENDIF
7558#endif
7559
7560!--         calculate csf and transparency
7561            DO i = 1, ncsb
7562#if defined( __parallel )
7563                IF ( raytrace_mpi_rma )  THEN
7564                    lad_s_target = lad_s_ray(i)
7565                ELSE
7566                    lad_s_target = sub_lad_g(lad_ip(i)*nnx*nny*nzp + lad_disp(i))
7567                ENDIF
7568#else
7569                lad_s_target = sub_lad(boxes(1,i),boxes(2,i),boxes(3,i))
7570#endif
7571                cursink = 1._wp - exp(-ext_coef * lad_s_target * crlens(i)*realdist)
7572
7573                IF ( create_csf )  THEN
7574!--                 write svf values into the array
7575                    ncsfl = ncsfl + 1
7576                    acsf(ncsfl)%ip = lad_ip(i)
7577                    acsf(ncsfl)%itx = boxes(3,i)
7578                    acsf(ncsfl)%ity = boxes(2,i)
7579                    acsf(ncsfl)%itz = boxes(1,i)
7580                    acsf(ncsfl)%isurfs = isrc
7581                    acsf(ncsfl)%rcvf = cursink*transparency*difvf*atarg
7582                ENDIF  !< create_csf
7583
7584                transparency = transparency * (1._wp - cursink)
7585               
7586            ENDDO
7587        ENDIF
7588       
7589        visible = .TRUE.
7590
7591    END SUBROUTINE raytrace
7592   
7593 
7594!------------------------------------------------------------------------------!
7595! Description:
7596! ------------
7597!> A new, more efficient version of ray tracing algorithm that processes a whole
7598!> arc instead of a single ray.
7599!>
7600!> In all comments, horizon means tangent of horizon angle, i.e.
7601!> vertical_delta / horizontal_distance
7602!------------------------------------------------------------------------------!
7603   SUBROUTINE raytrace_2d(origin, yxdir, nrays, zdirs, iorig, aorig, vffrac,  &
7604                              calc_svf, create_csf, skip_1st_pcb,             &
7605                              lowest_free_ray, transparency, itarget)
7606      IMPLICIT NONE
7607
7608      REAL(wp), DIMENSION(3), INTENT(IN)     ::  origin        !< z,y,x coordinates of ray origin
7609      REAL(wp), DIMENSION(2), INTENT(IN)     ::  yxdir         !< y,x *unit* vector of ray direction (in grid units)
7610      INTEGER(iwp)                           ::  nrays         !< number of rays (z directions) to raytrace
7611      REAL(wp), DIMENSION(nrays), INTENT(IN) ::  zdirs         !< list of z directions to raytrace (z/hdist, grid, zenith->nadir)
7612      INTEGER(iwp), INTENT(in)               ::  iorig         !< index of origin face for csf
7613      REAL(wp), INTENT(in)                   ::  aorig         !< origin face area for csf
7614      REAL(wp), DIMENSION(nrays), INTENT(in) ::  vffrac        !< view factor fractions of each ray for csf
7615      LOGICAL, INTENT(in)                    ::  calc_svf      !< whether to calculate SFV (identify obstacle surfaces)
7616      LOGICAL, INTENT(in)                    ::  create_csf    !< whether to create canopy sink factors
7617      LOGICAL, INTENT(in)                    ::  skip_1st_pcb  !< whether to skip first plant canopy box during raytracing
7618      INTEGER(iwp), INTENT(out)              ::  lowest_free_ray !< index into zdirs
7619      REAL(wp), DIMENSION(nrays), INTENT(OUT) ::  transparency !< transparencies of zdirs paths
7620      INTEGER(iwp), DIMENSION(nrays), INTENT(OUT) ::  itarget  !< global indices of target faces for zdirs
7621
7622      INTEGER(iwp), DIMENSION(nrays)         ::  target_procs
7623      REAL(wp)                               ::  horizon       !< highest horizon found after raytracing (z/hdist)
7624      INTEGER(iwp)                           ::  i, k, l, d
7625      INTEGER(iwp)                           ::  seldim       !< dimension to be incremented
7626      REAL(wp), DIMENSION(2)                 ::  yxorigin     !< horizontal copy of origin (y,x)
7627      REAL(wp)                               ::  distance     !< euclidean along path
7628      REAL(wp)                               ::  lastdist     !< beginning of current crossing
7629      REAL(wp)                               ::  nextdist     !< end of current crossing
7630      REAL(wp)                               ::  crmid        !< midpoint of crossing
7631      REAL(wp)                               ::  horz_entry   !< horizon at entry to column
7632      REAL(wp)                               ::  horz_exit    !< horizon at exit from column
7633      REAL(wp)                               ::  bdydim       !< boundary for current dimension
7634      REAL(wp), DIMENSION(2)                 ::  crossdist    !< distances to boundary for dimensions
7635      REAL(wp), DIMENSION(2)                 ::  dimnextdist  !< distance for each dimension increments
7636      INTEGER(iwp), DIMENSION(2)             ::  column       !< grid column being crossed
7637      INTEGER(iwp), DIMENSION(2)             ::  dimnext      !< next dimension increments along path
7638      INTEGER(iwp), DIMENSION(2)             ::  dimdelta     !< dimension direction = +- 1
7639      INTEGER(iwp)                           ::  px, py       !< number of processors in x and y dir before
7640                                                              !< the processor in the question
7641      INTEGER(iwp)                           ::  ip           !< number of processor where gridbox reside
7642      INTEGER(iwp)                           ::  ig           !< 1D index of gridbox in global 2D array
7643      INTEGER(iwp)                           ::  wcount       !< RMA window item count
7644      INTEGER(iwp)                           ::  maxboxes     !< max no of CSF created
7645      INTEGER(iwp)                           ::  nly          !< maximum  plant canopy height
7646      INTEGER(iwp)                           ::  ntrack
7647     
7648      INTEGER(iwp)                           ::  zb0
7649      INTEGER(iwp)                           ::  zb1
7650      INTEGER(iwp)                           ::  nz
7651      INTEGER(iwp)                           ::  iz
7652      INTEGER(iwp)                           ::  zsgn
7653      INTEGER(iwp)                           ::  lowest_lad   !< lowest column cell for which we need LAD
7654      INTEGER(iwp)                           ::  lastdir      !< wall direction before hitting this column
7655      INTEGER(iwp), DIMENSION(2)             ::  lastcolumn
7656
7657#if defined( __parallel )
7658      INTEGER(MPI_ADDRESS_KIND)              ::  wdisp        !< RMA window displacement
7659#endif
7660     
7661      REAL(wp)                               ::  eps = 1E-10_wp !< epsilon for value comparison
7662      REAL(wp)                               ::  zbottom, ztop !< urban surface boundary in real numbers
7663      REAL(wp)                               ::  zorig         !< z coordinate of ray column entry
7664      REAL(wp)                               ::  zexit         !< z coordinate of ray column exit
7665      REAL(wp)                               ::  qdist         !< ratio of real distance to z coord difference
7666      REAL(wp)                               ::  dxxyy         !< square of real horizontal distance
7667      REAL(wp)                               ::  curtrans      !< transparency of current PC box crossing
7668     
7669
7670     
7671      yxorigin(:) = origin(2:3)
7672      transparency(:) = 1._wp !-- Pre-set the all rays to transparent before reducing
7673      horizon = -HUGE(1._wp)
7674      lowest_free_ray = nrays
7675      IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7676         ALLOCATE(target_surfl(nrays))
7677         target_surfl(:) = -1
7678         lastdir = -999
7679         lastcolumn(:) = -999
7680      ENDIF
7681
7682!--   Determine distance to boundary (in 2D xy)
7683      IF ( yxdir(1) > 0._wp )  THEN
7684         bdydim = ny + .5_wp !< north global boundary
7685         crossdist(1) = (bdydim - yxorigin(1)) / yxdir(1)
7686      ELSEIF ( yxdir(1) == 0._wp )  THEN
7687         crossdist(1) = HUGE(1._wp)
7688      ELSE
7689          bdydim = -.5_wp !< south global boundary
7690          crossdist(1) = (bdydim - yxorigin(1)) / yxdir(1)
7691      ENDIF
7692
7693      IF ( yxdir(2) >= 0._wp )  THEN
7694          bdydim = nx + .5_wp !< east global boundary
7695          crossdist(2) = (bdydim - yxorigin(2)) / yxdir(2)
7696      ELSEIF ( yxdir(2) == 0._wp )  THEN
7697         crossdist(2) = HUGE(1._wp)
7698      ELSE
7699          bdydim = -.5_wp !< west global boundary
7700          crossdist(2) = (bdydim - yxorigin(2)) / yxdir(2)
7701      ENDIF
7702      distance = minval(crossdist, 1)
7703
7704      IF ( plant_canopy )  THEN
7705         rt2_track_dist(0) = 0._wp
7706         rt2_track_lad(:,:) = 0._wp
7707         nly = plantt_max - nzub + 1
7708      ENDIF
7709
7710      lastdist = 0._wp
7711
7712!--   Since all face coordinates have values *.5 and we'd like to use
7713!--   integers, all these have .5 added
7714      DO  d = 1, 2
7715          IF ( yxdir(d) == 0._wp )  THEN
7716              dimnext(d) = HUGE(1_iwp)
7717              dimdelta(d) = HUGE(1_iwp)
7718              dimnextdist(d) = HUGE(1._wp)
7719          ELSE IF ( yxdir(d) > 0._wp )  THEN
7720              dimnext(d) = FLOOR(yxorigin(d) + .5_wp) + 1
7721              dimdelta(d) = 1
7722              dimnextdist(d) = (dimnext(d) - .5_wp - yxorigin(d)) / yxdir(d)
7723          ELSE
7724              dimnext(d) = CEILING(yxorigin(d) + .5_wp) - 1
7725              dimdelta(d) = -1
7726              dimnextdist(d) = (dimnext(d) - .5_wp - yxorigin(d)) / yxdir(d)
7727          ENDIF
7728      ENDDO
7729
7730      ntrack = 0
7731      DO
7732!--      along what dimension will the next wall crossing be?
7733         seldim = minloc(dimnextdist, 1)
7734         nextdist = dimnextdist(seldim)
7735         IF ( nextdist > distance )  nextdist = distance
7736
7737         IF ( nextdist > lastdist )  THEN
7738            ntrack = ntrack + 1
7739            crmid = (lastdist + nextdist) * .5_wp
7740            column = NINT(yxorigin(:) + yxdir(:) * crmid, iwp)
7741
7742!--         calculate index of the grid with global indices (column(1),column(2))
7743!--         in the array nzterr and plantt and id of the coresponding processor
7744            px = column(2)/nnx
7745            py = column(1)/nny
7746            ip = px*pdims(2)+py
7747            ig = ip*nnx*nny + (column(2)-px*nnx)*nny + column(1)-py*nny
7748
7749            IF ( lastdist == 0._wp )  THEN
7750               horz_entry = -HUGE(1._wp)
7751            ELSE
7752               horz_entry = (REAL(nzterr(ig), wp) + .5_wp - origin(1)) / lastdist
7753            ENDIF
7754            horz_exit = (REAL(nzterr(ig), wp) + .5_wp - origin(1)) / nextdist
7755
7756            IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7757!
7758!--            Identify vertical obstacles hit by rays in current column
7759               DO WHILE ( lowest_free_ray > 0 )
7760                  IF ( zdirs(lowest_free_ray) > horz_entry )  EXIT
7761!
7762!--               This may only happen after 1st column, so lastdir and lastcolumn are valid
7763                  CALL request_itarget(lastdir,                                         &
7764                        CEILING(-0.5_wp + origin(1) + zdirs(lowest_free_ray)*lastdist), &
7765                        lastcolumn(1), lastcolumn(2),                                   &
7766                        target_surfl(lowest_free_ray), target_procs(lowest_free_ray))
7767                  lowest_free_ray = lowest_free_ray - 1
7768               ENDDO
7769!
7770!--            Identify horizontal obstacles hit by rays in current column
7771               DO WHILE ( lowest_free_ray > 0 )
7772                  IF ( zdirs(lowest_free_ray) > horz_exit )  EXIT
7773                  CALL request_itarget(iup_u, nzterr(ig)+1, column(1), column(2), &
7774                                       target_surfl(lowest_free_ray),           &
7775                                       target_procs(lowest_free_ray))
7776                  lowest_free_ray = lowest_free_ray - 1
7777               ENDDO
7778            ENDIF
7779
7780            horizon = MAX(horizon, horz_entry, horz_exit)
7781
7782            IF ( plant_canopy )  THEN
7783               rt2_track(:, ntrack) = column(:)
7784               rt2_track_dist(ntrack) = nextdist
7785            ENDIF
7786         ENDIF
7787
7788         IF ( ABS(distance - nextdist) < eps )  EXIT
7789
7790         IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7791!
7792!--         Save wall direction of coming building column (= this air column)
7793            IF ( seldim == 1 )  THEN
7794               IF ( dimdelta(seldim) == 1 )  THEN
7795                  lastdir = isouth_u
7796               ELSE
7797                  lastdir = inorth_u
7798               ENDIF
7799            ELSE
7800               IF ( dimdelta(seldim) == 1 )  THEN
7801                  lastdir = iwest_u
7802               ELSE
7803                  lastdir = ieast_u
7804               ENDIF
7805            ENDIF
7806            lastcolumn = column
7807         ENDIF
7808         lastdist = nextdist
7809         dimnext(seldim) = dimnext(seldim) + dimdelta(seldim)
7810         dimnextdist(seldim) = (dimnext(seldim) - .5_wp - yxorigin(seldim)) / yxdir(seldim)
7811      ENDDO
7812
7813      IF ( plant_canopy )  THEN
7814!--      Request LAD WHERE applicable
7815!--     
7816#if defined( __parallel )
7817         IF ( raytrace_mpi_rma )  THEN
7818!--         send requests for lad_s to appropriate processor
7819            !CALL cpu_log( log_point_s(77), 'usm_init_rma', 'start' )
7820            DO  i = 1, ntrack
7821               px = rt2_track(2,i)/nnx
7822               py = rt2_track(1,i)/nny
7823               ip = px*pdims(2)+py
7824               ig = ip*nnx*nny + (rt2_track(2,i)-px*nnx)*nny + rt2_track(1,i)-py*nny
7825
7826               IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7827!
7828!--               For fixed view resolution, we need plant canopy even for rays
7829!--               to opposing surfaces
7830                  lowest_lad = nzterr(ig) + 1
7831               ELSE
7832!
7833!--               We only need LAD for rays directed above horizon (to sky)
7834                  lowest_lad = CEILING( -0.5_wp + origin(1) +            &
7835                                    MIN( horizon * rt2_track_dist(i-1),  & ! entry
7836                                         horizon * rt2_track_dist(i)   ) ) ! exit
7837               ENDIF
7838!
7839!--            Skip asking for LAD where all plant canopy is under requested level
7840               IF ( plantt(ig) < lowest_lad )  CYCLE
7841
7842               wdisp = (rt2_track(2,i)-px*nnx)*(nny*nzp) + (rt2_track(1,i)-py*nny)*nzp + lowest_lad-nzub
7843               wcount = plantt(ig)-lowest_lad+1
7844               ! TODO send request ASAP - even during raytracing
7845               CALL MPI_Get(rt2_track_lad(lowest_lad:plantt(ig), i), wcount, MPI_REAL, ip,    &
7846                            wdisp, wcount, MPI_REAL, win_lad, ierr)
7847               IF ( ierr /= 0 )  THEN
7848                  WRITE(9,*) 'Error MPI_Get2:', ierr, rt2_track_lad(lowest_lad:plantt(ig), i), &
7849                             wcount, ip, wdisp, win_lad
7850                  FLUSH(9)
7851               ENDIF
7852            ENDDO
7853
7854!--         wait for all pending local requests complete
7855            ! TODO WAIT selectively for each column later when needed
7856            CALL MPI_Win_flush_local_all(win_lad, ierr)
7857            IF ( ierr /= 0 )  THEN
7858               WRITE(9,*) 'Error MPI_Win_flush_local_all2:', ierr, win_lad
7859               FLUSH(9)
7860            ENDIF
7861            !CALL cpu_log( log_point_s(77), 'usm_init_rma', 'stop' )
7862
7863         ELSE ! raytrace_mpi_rma = .F.
7864            DO  i = 1, ntrack
7865               px = rt2_track(2,i)/nnx
7866               py = rt2_track(1,i)/nny
7867               ip = px*pdims(2)+py
7868               ig = ip*nnx*nny*nzp + (rt2_track(2,i)-px*nnx)*(nny*nzp) + (rt2_track(1,i)-py*nny)*nzp
7869               rt2_track_lad(nzub:plantt_max, i) = sub_lad_g(ig:ig+nly-1)
7870            ENDDO
7871         ENDIF
7872#else
7873         DO  i = 1, ntrack
7874            rt2_track_lad(nzub:plantt_max, i) = sub_lad(rt2_track(1,i), rt2_track(2,i), nzub:plantt_max)
7875         ENDDO
7876#endif
7877      ENDIF ! plant_canopy
7878
7879      IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7880#if defined( __parallel )
7881!--      wait for all gridsurf requests to complete
7882         CALL MPI_Win_flush_local_all(win_gridsurf, ierr)
7883         IF ( ierr /= 0 )  THEN
7884            WRITE(9,*) 'Error MPI_Win_flush_local_all3:', ierr, win_gridsurf
7885            FLUSH(9)
7886         ENDIF
7887#endif
7888!
7889!--      recalculate local surf indices into global ones
7890         DO i = 1, nrays
7891            IF ( target_surfl(i) == -1 )  THEN
7892               itarget(i) = -1
7893            ELSE
7894               itarget(i) = target_surfl(i) + surfstart(target_procs(i))
7895            ENDIF
7896         ENDDO
7897         
7898         DEALLOCATE( target_surfl )
7899         
7900      ELSE
7901         itarget(:) = -1
7902      ENDIF ! rad_angular_discretization
7903
7904      IF ( plant_canopy )  THEN
7905!--      Skip the PCB around origin if requested (for MRT, the PCB might not be there)
7906!--     
7907         IF ( skip_1st_pcb  .AND.  NINT(origin(1)) <= plantt_max )  THEN
7908            rt2_track_lad(NINT(origin(1), iwp), 1) = 0._wp
7909         ENDIF
7910
7911!--      Assert that we have space allocated for CSFs
7912!--     
7913         maxboxes = (ntrack + MAX(CEILING(origin(1)-.5_wp) - nzub,          &
7914                                  nzut - CEILING(origin(1)-.5_wp))) * nrays
7915         IF ( ncsfl + maxboxes > ncsfla )  THEN
7916!--         use this code for growing by fixed exponential increments (equivalent to case where ncsfl always increases by 1)
7917!--         k = CEILING(grow_factor ** real(CEILING(log(real(ncsfl + maxboxes, kind=wp)) &
7918!--                                                / log(grow_factor)), kind=wp))
7919!--         or use this code to simply always keep some extra space after growing
7920            k = CEILING(REAL(ncsfl + maxboxes, kind=wp) * grow_factor)
7921            CALL merge_and_grow_csf(k)
7922         ENDIF
7923
7924!--      Calculate transparencies and store new CSFs
7925!--     
7926         zbottom = REAL(nzub, wp) - .5_wp
7927         ztop = REAL(plantt_max, wp) + .5_wp
7928
7929!--      Reverse direction of radiation (face->sky), only when calc_svf
7930!--     
7931         IF ( calc_svf )  THEN
7932            DO  i = 1, ntrack ! for each column
7933               dxxyy = ((dy*yxdir(1))**2 + (dx*yxdir(2))**2) * (rt2_track_dist(i)-rt2_track_dist(i-1))**2
7934               px = rt2_track(2,i)/nnx
7935               py = rt2_track(1,i)/nny
7936               ip = px*pdims(2)+py
7937
7938               DO  k = 1, nrays ! for each ray
7939!
7940!--               NOTE 6778:
7941!--               With traditional svf discretization, CSFs under the horizon
7942!--               (i.e. for surface to surface radiation)  are created in
7943!--               raytrace(). With rad_angular_discretization, we must create
7944!--               CSFs under horizon only for one direction, otherwise we would
7945!--               have duplicate amount of energy. Although we could choose
7946!--               either of the two directions (they differ only by
7947!--               discretization error with no bias), we choose the the backward
7948!--               direction, because it tends to cumulate high canopy sink
7949!--               factors closer to raytrace origin, i.e. it should potentially
7950!--               cause less moiree.
7951                  IF ( .NOT. rad_angular_discretization )  THEN
7952                     IF ( zdirs(k) <= horizon )  CYCLE
7953                  ENDIF
7954
7955                  zorig = origin(1) + zdirs(k) * rt2_track_dist(i-1)
7956                  IF ( zorig <= zbottom  .OR.  zorig >= ztop )  CYCLE
7957
7958                  zsgn = INT(SIGN(1._wp, zdirs(k)), iwp)
7959                  rt2_dist(1) = 0._wp
7960                  IF ( zdirs(k) == 0._wp )  THEN ! ray is exactly horizontal
7961                     nz = 2
7962                     rt2_dist(nz) = SQRT(dxxyy)
7963                     iz = CEILING(-.5_wp + zorig, iwp)
7964                  ELSE
7965                     zexit = MIN(MAX(origin(1) + zdirs(k) * rt2_track_dist(i), zbottom), ztop)
7966
7967                     zb0 = FLOOR(  zorig * zsgn - .5_wp) + 1  ! because it must be greater than orig
7968                     zb1 = CEILING(zexit * zsgn - .5_wp) - 1  ! because it must be smaller than exit
7969                     nz = MAX(zb1 - zb0 + 3, 2)
7970                     rt2_dist(nz) = SQRT(((zexit-zorig)*dz(1))**2 + dxxyy)
7971                     qdist = rt2_dist(nz) / (zexit-zorig)
7972                     rt2_dist(2:nz-1) = (/( ((REAL(l, wp) + .5_wp) * zsgn - zorig) * qdist , l = zb0, zb1 )/)
7973                     iz = zb0 * zsgn
7974                  ENDIF
7975
7976                  DO  l = 2, nz
7977                     IF ( rt2_track_lad(iz, i) > 0._wp )  THEN
7978                        curtrans = exp(-ext_coef * rt2_track_lad(iz, i) * (rt2_dist(l)-rt2_dist(l-1)))
7979
7980                        IF ( create_csf )  THEN
7981                           ncsfl = ncsfl + 1
7982                           acsf(ncsfl)%ip = ip
7983                           acsf(ncsfl)%itx = rt2_track(2,i)
7984                           acsf(ncsfl)%ity = rt2_track(1,i)
7985                           acsf(ncsfl)%itz = iz
7986                           acsf(ncsfl)%isurfs = iorig
7987                           acsf(ncsfl)%rcvf = (1._wp - curtrans)*transparency(k)*vffrac(k)
7988                        ENDIF
7989
7990                        transparency(k) = transparency(k) * curtrans
7991                     ENDIF
7992                     iz = iz + zsgn
7993                  ENDDO ! l = 1, nz - 1
7994               ENDDO ! k = 1, nrays
7995            ENDDO ! i = 1, ntrack
7996
7997            transparency(1:lowest_free_ray) = 1._wp !-- Reset rays above horizon to transparent (see NOTE 6778)
7998         ENDIF
7999
8000!--      Forward direction of radiation (sky->face), always
8001!--     
8002         DO  i = ntrack, 1, -1 ! for each column backwards
8003            dxxyy = ((dy*yxdir(1))**2 + (dx*yxdir(2))**2) * (rt2_track_dist(i)-rt2_track_dist(i-1))**2
8004            px = rt2_track(2,i)/nnx
8005            py = rt2_track(1,i)/nny
8006            ip = px*pdims(2)+py
8007
8008            DO  k = 1, nrays ! for each ray
8009!
8010!--            See NOTE 6778 above
8011               IF ( zdirs(k) <= horizon )  CYCLE
8012
8013               zexit = origin(1) + zdirs(k) * rt2_track_dist(i-1)
8014               IF ( zexit <= zbottom  .OR.  zexit >= ztop )  CYCLE
8015
8016               zsgn = -INT(SIGN(1._wp, zdirs(k)), iwp)
8017               rt2_dist(1) = 0._wp
8018               IF ( zdirs(k) == 0._wp )  THEN ! ray is exactly horizontal
8019                  nz = 2
8020                  rt2_dist(nz) = SQRT(dxxyy)
8021                  iz = NINT(zexit, iwp)
8022               ELSE
8023                  zorig = MIN(MAX(origin(1) + zdirs(k) * rt2_track_dist(i), zbottom), ztop)
8024
8025                  zb0 = FLOOR(  zorig * zsgn - .5_wp) + 1  ! because it must be greater than orig
8026                  zb1 = CEILING(zexit * zsgn - .5_wp) - 1  ! because it must be smaller than exit
8027                  nz = MAX(zb1 - zb0 + 3, 2)
8028                  rt2_dist(nz) = SQRT(((zexit-zorig)*dz(1))**2 + dxxyy)
8029                  qdist = rt2_dist(nz) / (zexit-zorig)
8030                  rt2_dist(2:nz-1) = (/( ((REAL(l, wp) + .5_wp) * zsgn - zorig) * qdist , l = zb0, zb1 )/)
8031                  iz = zb0 * zsgn
8032               ENDIF
8033
8034               DO  l = 2, nz
8035                  IF ( rt2_track_lad(iz, i) > 0._wp )  THEN
8036                     curtrans = exp(-ext_coef * rt2_track_lad(iz, i) * (rt2_dist(l)-rt2_dist(l-1)))
8037
8038                     IF ( create_csf )  THEN
8039                        ncsfl = ncsfl + 1
8040                        acsf(ncsfl)%ip = ip
8041                        acsf(ncsfl)%itx = rt2_track(2,i)
8042                        acsf(ncsfl)%ity = rt2_track(1,i)
8043                        acsf(ncsfl)%itz = iz
8044                        IF ( itarget(k) /= -1 ) STOP 1 !FIXME remove after test
8045                        acsf(ncsfl)%isurfs = -1
8046                        acsf(ncsfl)%rcvf = (1._wp - curtrans)*transparency(k)*aorig*vffrac(k)
8047                     ENDIF  ! create_csf
8048
8049                     transparency(k) = transparency(k) * curtrans
8050                  ENDIF
8051                  iz = iz + zsgn
8052               ENDDO ! l = 1, nz - 1
8053            ENDDO ! k = 1, nrays
8054         ENDDO ! i = 1, ntrack
8055      ENDIF ! plant_canopy
8056
8057      IF ( .NOT. (rad_angular_discretization  .AND.  calc_svf) )  THEN
8058!
8059!--      Just update lowest_free_ray according to horizon
8060         DO WHILE ( lowest_free_ray > 0 )
8061            IF ( zdirs(lowest_free_ray) > horizon )  EXIT
8062            lowest_free_ray = lowest_free_ray - 1
8063         ENDDO
8064      ENDIF
8065
8066   CONTAINS
8067
8068      SUBROUTINE request_itarget( d, z, y, x, isurfl, iproc )
8069
8070         INTEGER(iwp), INTENT(in)            ::  d, z, y, x
8071         INTEGER(iwp), TARGET, INTENT(out)   ::  isurfl
8072         INTEGER(iwp), INTENT(out)           ::  iproc
8073#if defined( __parallel )
8074#else
8075         INTEGER(iwp)                        ::  target_displ  !< index of the grid in the local gridsurf array
8076#endif
8077         INTEGER(iwp)                        ::  px, py        !< number of processors in x and y direction
8078                                                               !< before the processor in the question
8079#if defined( __parallel )
8080         INTEGER(KIND=MPI_ADDRESS_KIND)      ::  target_displ  !< index of the grid in the local gridsurf array
8081
8082!
8083!--      Calculate target processor and index in the remote local target gridsurf array
8084         px = x / nnx
8085         py = y / nny
8086         iproc = px * pdims(2) + py
8087         target_displ = ((x-px*nnx) * nny + y - py*nny ) * nzu * nsurf_type_u +&
8088                        ( z-nzub ) * nsurf_type_u + d
8089!
8090!--      Send MPI_Get request to obtain index target_surfl(i)
8091         CALL MPI_GET( isurfl, 1, MPI_INTEGER, iproc, target_displ,            &
8092                       1, MPI_INTEGER, win_gridsurf, ierr)
8093         IF ( ierr /= 0 )  THEN
8094            WRITE( 9,* ) 'Error MPI_Get3:', ierr, isurfl, iproc, target_displ, &
8095                         win_gridsurf
8096            FLUSH( 9 )
8097         ENDIF
8098#else
8099!--      set index target_surfl(i)
8100         isurfl = gridsurf(d,z,y,x)
8101#endif
8102
8103      END SUBROUTINE request_itarget
8104
8105   END SUBROUTINE raytrace_2d
8106 
8107
8108!------------------------------------------------------------------------------!
8109!
8110! Description:
8111! ------------
8112!> Calculates apparent solar positions for all timesteps and stores discretized
8113!> positions.
8114!------------------------------------------------------------------------------!
8115   SUBROUTINE radiation_presimulate_solar_pos
8116
8117      IMPLICIT NONE
8118
8119      INTEGER(iwp)                              ::  it, i, j
8120      INTEGER(iwp)                              ::  day_of_month_prev,month_of_year_prev
8121      REAL(wp)                                  ::  tsrp_prev
8122      REAL(wp)                                  ::  simulated_time_prev
8123      REAL(wp), DIMENSION(:,:), ALLOCATABLE     ::  dsidir_tmp       !< dsidir_tmp[:,i] = unit vector of i-th
8124                                                                     !< appreant solar direction
8125
8126      ALLOCATE ( dsidir_rev(0:raytrace_discrete_elevs/2-1,                 &
8127                            0:raytrace_discrete_azims-1) )
8128      dsidir_rev(:,:) = -1
8129      ALLOCATE ( dsidir_tmp(3,                                             &
8130                     raytrace_discrete_elevs/2*raytrace_discrete_azims) )
8131      ndsidir = 0
8132
8133!
8134!--   We will artificialy update time_since_reference_point and return to
8135!--   true value later
8136      tsrp_prev = time_since_reference_point
8137      simulated_time_prev = simulated_time
8138      day_of_month_prev = day_of_month
8139      month_of_year_prev = month_of_year
8140      sun_direction = .TRUE.
8141
8142!
8143!--   Process spinup time if configured
8144      IF ( spinup_time > 0._wp )  THEN
8145         DO  it = 0, CEILING(spinup_time / dt_spinup)
8146            time_since_reference_point = -spinup_time + REAL(it, wp) * dt_spinup
8147            simulated_time = simulated_time + dt_spinup
8148            CALL simulate_pos
8149         ENDDO
8150      ENDIF
8151!
8152!--   Process simulation time
8153      DO  it = 0, CEILING(( end_time - spinup_time ) / dt_radiation)
8154         time_since_reference_point = REAL(it, wp) * dt_radiation
8155         simulated_time = simulated_time + dt_radiation
8156         CALL simulate_pos
8157      ENDDO
8158!
8159!--   Return date and time to its original values
8160      time_since_reference_point = tsrp_prev
8161      simulated_time = simulated_time_prev
8162      day_of_month = day_of_month_prev
8163      month_of_year = month_of_year_prev
8164      CALL init_date_and_time
8165
8166!--   Allocate global vars which depend on ndsidir
8167      ALLOCATE ( dsidir ( 3, ndsidir ) )
8168      dsidir(:,:) = dsidir_tmp(:, 1:ndsidir)
8169      DEALLOCATE ( dsidir_tmp )
8170
8171      ALLOCATE ( dsitrans(nsurfl, ndsidir) )
8172      ALLOCATE ( dsitransc(npcbl, ndsidir) )
8173      IF ( nmrtbl > 0 )  ALLOCATE ( mrtdsit(nmrtbl, ndsidir) )
8174
8175      WRITE ( message_string, * ) 'Precalculated', ndsidir, ' solar positions', &
8176                                  'from', it, ' timesteps.'
8177      CALL message( 'radiation_presimulate_solar_pos', 'UI0013', 0, 0, 0, 6, 0 )
8178
8179      CONTAINS
8180
8181      !------------------------------------------------------------------------!
8182      ! Description:
8183      ! ------------
8184      !> Simuates a single position
8185      !------------------------------------------------------------------------!
8186      SUBROUTINE simulate_pos
8187         IMPLICIT NONE
8188!
8189!--      Update apparent solar position based on modified t_s_r_p
8190         CALL calc_zenith
8191         IF ( zenith(0) > 0 )  THEN
8192!--         
8193!--         Identify solar direction vector (discretized number) 1)
8194            i = MODULO(NINT(ATAN2(sun_dir_lon(0), sun_dir_lat(0))               &
8195                            / (2._wp*pi) * raytrace_discrete_azims-.5_wp, iwp), &
8196                       raytrace_discrete_azims)
8197            j = FLOOR(ACOS(zenith(0)) / pi * raytrace_discrete_elevs)
8198            IF ( dsidir_rev(j, i) == -1 )  THEN
8199               ndsidir = ndsidir + 1
8200               dsidir_tmp(:, ndsidir) =                                              &
8201                     (/ COS((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs), &
8202                        SIN((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs)  &
8203                      * COS((REAL(i,wp)+.5_wp) * 2_wp*pi / raytrace_discrete_azims), &
8204                        SIN((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs)  &
8205                      * SIN((REAL(i,wp)+.5_wp) * 2_wp*pi / raytrace_discrete_azims) /)
8206               dsidir_rev(j, i) = ndsidir
8207            ENDIF
8208         ENDIF
8209      END SUBROUTINE simulate_pos
8210
8211   END SUBROUTINE radiation_presimulate_solar_pos
8212
8213
8214
8215!------------------------------------------------------------------------------!
8216! Description:
8217! ------------
8218!> Determines whether two faces are oriented towards each other. Since the
8219!> surfaces follow the gird box surfaces, it checks first whether the two surfaces
8220!> are directed in the same direction, then it checks if the two surfaces are
8221!> located in confronted direction but facing away from each other, e.g. <--| |-->
8222!------------------------------------------------------------------------------!
8223    PURE LOGICAL FUNCTION surface_facing(x, y, z, d, x2, y2, z2, d2)
8224        IMPLICIT NONE
8225        INTEGER(iwp),   INTENT(in)  :: x, y, z, d, x2, y2, z2, d2
8226     
8227        surface_facing = .FALSE.
8228
8229!-- first check: are the two surfaces directed in the same direction
8230        IF ( (d==iup_u  .OR.  d==iup_l )                             &
8231             .AND. (d2==iup_u  .OR. d2==iup_l) ) RETURN
8232        IF ( (d==isouth_u  .OR.  d==isouth_l ) &
8233             .AND.  (d2==isouth_u  .OR.  d2==isouth_l) ) RETURN
8234        IF ( (d==inorth_u  .OR.  d==inorth_l ) &
8235             .AND.  (d2==inorth_u  .OR.  d2==inorth_l) ) RETURN
8236        IF ( (d==iwest_u  .OR.  d==iwest_l )     &
8237             .AND.  (d2==iwest_u  .OR.  d2==iwest_l ) ) RETURN
8238        IF ( (d==ieast_u  .OR.  d==ieast_l )     &
8239             .AND.  (d2==ieast_u  .OR.  d2==ieast_l ) ) RETURN
8240
8241!-- second check: are surfaces facing away from each other
8242        SELECT CASE (d)
8243            CASE (iup_u, iup_l)                     !< upward facing surfaces
8244                IF ( z2 < z ) RETURN
8245            CASE (isouth_u, isouth_l)               !< southward facing surfaces
8246                IF ( y2 > y ) RETURN
8247            CASE (inorth_u, inorth_l)               !< northward facing surfaces
8248                IF ( y2 < y ) RETURN
8249            CASE (iwest_u, iwest_l)                 !< westward facing surfaces
8250                IF ( x2 > x ) RETURN
8251            CASE (ieast_u, ieast_l)                 !< eastward facing surfaces
8252                IF ( x2 < x ) RETURN
8253        END SELECT
8254
8255        SELECT CASE (d2)
8256            CASE (iup_u)                            !< ground, roof
8257                IF ( z < z2 ) RETURN
8258            CASE (isouth_u, isouth_l)               !< south facing
8259                IF ( y > y2 ) RETURN
8260            CASE (inorth_u, inorth_l)               !< north facing
8261                IF ( y < y2 ) RETURN
8262            CASE (iwest_u, iwest_l)                 !< west facing
8263                IF ( x > x2 ) RETURN
8264            CASE (ieast_u, ieast_l)                 !< east facing
8265                IF ( x < x2 ) RETURN
8266            CASE (-1)
8267                CONTINUE
8268        END SELECT
8269
8270        surface_facing = .TRUE.
8271       
8272    END FUNCTION surface_facing
8273
8274
8275!------------------------------------------------------------------------------!
8276!
8277! Description:
8278! ------------
8279!> Soubroutine reads svf and svfsurf data from saved file
8280!> SVF means sky view factors and CSF means canopy sink factors
8281!------------------------------------------------------------------------------!
8282    SUBROUTINE radiation_read_svf
8283
8284       IMPLICIT NONE
8285       
8286       CHARACTER(rad_version_len)   :: rad_version_field
8287       
8288       INTEGER(iwp)                 :: i
8289       INTEGER(iwp)                 :: ndsidir_from_file = 0
8290       INTEGER(iwp)                 :: npcbl_from_file = 0
8291       INTEGER(iwp)                 :: nsurfl_from_file = 0
8292       
8293       DO  i = 0, io_blocks-1
8294          IF ( i == io_group )  THEN
8295
8296!
8297!--          numprocs_previous_run is only known in case of reading restart
8298!--          data. If a new initial run which reads svf data is started the
8299!--          following query will be skipped
8300             IF ( initializing_actions == 'read_restart_data' ) THEN
8301
8302                IF ( numprocs_previous_run /= numprocs ) THEN
8303                   WRITE( message_string, * ) 'A different number of ',        &
8304                                              'processors between the run ',   &
8305                                              'that has written the svf data ',&
8306                                              'and the one that will read it ',&
8307                                              'is not allowed' 
8308                   CALL message( 'check_open', 'PA0491', 1, 2, 0, 6, 0 )
8309                ENDIF
8310
8311             ENDIF
8312             
8313!
8314!--          Open binary file
8315             CALL check_open( 88 )
8316
8317!
8318!--          read and check version
8319             READ ( 88 ) rad_version_field
8320             IF ( TRIM(rad_version_field) /= TRIM(rad_version) )  THEN
8321                 WRITE( message_string, * ) 'Version of binary SVF file "',    &
8322                             TRIM(rad_version_field), '" does not match ',     &
8323                             'the version of model "', TRIM(rad_version), '"'
8324                 CALL message( 'radiation_read_svf', 'PA0482', 1, 2, 0, 6, 0 )
8325             ENDIF
8326             
8327!
8328!--          read nsvfl, ncsfl, nsurfl
8329             READ ( 88 ) nsvfl, ncsfl, nsurfl_from_file, npcbl_from_file,      &
8330                         ndsidir_from_file
8331             
8332             IF ( nsvfl < 0  .OR.  ncsfl < 0 )  THEN
8333                 WRITE( message_string, * ) 'Wrong number of SVF or CSF'
8334                 CALL message( 'radiation_read_svf', 'PA0483', 1, 2, 0, 6, 0 )
8335             ELSE
8336                 WRITE(message_string,*) '    Number of SVF, CSF, and nsurfl ',&
8337                                         'to read', nsvfl, ncsfl,              &
8338                                         nsurfl_from_file
8339                 CALL location_message( message_string, .TRUE. )
8340             ENDIF
8341             
8342             IF ( nsurfl_from_file /= nsurfl )  THEN
8343                 WRITE( message_string, * ) 'nsurfl from SVF file does not ',  &
8344                                            'match calculated nsurfl from ',   &
8345                                            'radiation_interaction_init'
8346                 CALL message( 'radiation_read_svf', 'PA0490', 1, 2, 0, 6, 0 )
8347             ENDIF
8348             
8349             IF ( npcbl_from_file /= npcbl )  THEN
8350                 WRITE( message_string, * ) 'npcbl from SVF file does not ',   &
8351                                            'match calculated npcbl from ',    &
8352                                            'radiation_interaction_init'
8353                 CALL message( 'radiation_read_svf', 'PA0493', 1, 2, 0, 6, 0 )
8354             ENDIF
8355             
8356             IF ( ndsidir_from_file /= ndsidir )  THEN
8357                 WRITE( message_string, * ) 'ndsidir from SVF file does not ', &
8358                                            'match calculated ndsidir from ',  &
8359                                            'radiation_presimulate_solar_pos'
8360                 CALL message( 'radiation_read_svf', 'PA0494', 1, 2, 0, 6, 0 )
8361             ENDIF
8362             
8363!
8364!--          Arrays skyvf, skyvft, dsitrans and dsitransc are allready
8365!--          allocated in radiation_interaction_init and
8366!--          radiation_presimulate_solar_pos
8367             IF ( nsurfl > 0 )  THEN
8368                READ(88) skyvf
8369                READ(88) skyvft
8370                READ(88) dsitrans 
8371             ENDIF
8372             
8373             IF ( plant_canopy  .AND.  npcbl > 0 ) THEN
8374                READ ( 88 )  dsitransc
8375             ENDIF
8376             
8377!
8378!--          The allocation of svf, svfsurf, csf and csfsurf happens in routine
8379!--          radiation_calc_svf which is not called if the program enters
8380!--          radiation_read_svf. Therefore these arrays has to allocate in the
8381!--          following
8382             IF ( nsvfl > 0 )  THEN
8383                ALLOCATE( svf(ndsvf,nsvfl) )
8384                ALLOCATE( svfsurf(idsvf,nsvfl) )
8385                READ(88) svf
8386                READ(88) svfsurf
8387             ENDIF
8388
8389             IF ( plant_canopy  .AND.  ncsfl > 0 )  THEN
8390                ALLOCATE( csf(ndcsf,ncsfl) )
8391                ALLOCATE( csfsurf(idcsf,ncsfl) )
8392                READ(88) csf
8393                READ(88) csfsurf
8394             ENDIF
8395             
8396!
8397!--          Close binary file                 
8398             CALL close_file( 88 )
8399               
8400          ENDIF
8401#if defined( __parallel )
8402          CALL MPI_BARRIER( comm2d, ierr )
8403#endif
8404       ENDDO
8405
8406    END SUBROUTINE radiation_read_svf
8407
8408
8409!------------------------------------------------------------------------------!
8410!
8411! Description:
8412! ------------
8413!> Subroutine stores svf, svfsurf, csf and csfsurf data to a file.
8414!------------------------------------------------------------------------------!
8415    SUBROUTINE radiation_write_svf
8416
8417       IMPLICIT NONE
8418       
8419       INTEGER(iwp)        :: i
8420
8421       DO  i = 0, io_blocks-1
8422          IF ( i == io_group )  THEN
8423!
8424!--          Open binary file
8425             CALL check_open( 89 )
8426
8427             WRITE ( 89 )  rad_version
8428             WRITE ( 89 )  nsvfl, ncsfl, nsurfl, npcbl, ndsidir
8429             IF ( nsurfl > 0 ) THEN
8430                WRITE ( 89 )  skyvf
8431                WRITE ( 89 )  skyvft
8432                WRITE ( 89 )  dsitrans
8433             ENDIF
8434             IF ( npcbl > 0 ) THEN
8435                WRITE ( 89 )  dsitransc
8436             ENDIF
8437             IF ( nsvfl > 0 ) THEN
8438                WRITE ( 89 )  svf
8439                WRITE ( 89 )  svfsurf
8440             ENDIF
8441             IF ( plant_canopy  .AND.  ncsfl > 0 )  THEN
8442                 WRITE ( 89 )  csf
8443                 WRITE ( 89 )  csfsurf
8444             ENDIF
8445
8446!
8447!--          Close binary file                 
8448             CALL close_file( 89 )
8449
8450          ENDIF
8451#if defined( __parallel )
8452          CALL MPI_BARRIER( comm2d, ierr )
8453#endif
8454       ENDDO
8455    END SUBROUTINE radiation_write_svf
8456
8457!------------------------------------------------------------------------------!
8458!
8459! Description:
8460! ------------
8461!> Block of auxiliary subroutines:
8462!> 1. quicksort and corresponding comparison
8463!> 2. merge_and_grow_csf for implementation of "dynamical growing"
8464!>    array for csf
8465!------------------------------------------------------------------------------!
8466!-- quicksort.f -*-f90-*-
8467!-- Author: t-nissie, adaptation J.Resler
8468!-- License: GPLv3
8469!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8470    RECURSIVE SUBROUTINE quicksort_itarget(itarget, vffrac, ztransp, first, last)
8471        IMPLICIT NONE
8472        INTEGER(iwp), DIMENSION(:), INTENT(INOUT)   :: itarget
8473        REAL(wp), DIMENSION(:), INTENT(INOUT)       :: vffrac, ztransp
8474        INTEGER(iwp), INTENT(IN)                    :: first, last
8475        INTEGER(iwp)                                :: x, t
8476        INTEGER(iwp)                                :: i, j
8477        REAL(wp)                                    :: tr
8478
8479        IF ( first>=last ) RETURN
8480        x = itarget((first+last)/2)
8481        i = first
8482        j = last
8483        DO
8484            DO WHILE ( itarget(i) < x )
8485               i=i+1
8486            ENDDO
8487            DO WHILE ( x < itarget(j) )
8488                j=j-1
8489            ENDDO
8490            IF ( i >= j ) EXIT
8491            t = itarget(i);  itarget(i) = itarget(j);  itarget(j) = t
8492            tr = vffrac(i);  vffrac(i) = vffrac(j);  vffrac(j) = tr
8493            tr = ztransp(i);  ztransp(i) = ztransp(j);  ztransp(j) = tr
8494            i=i+1
8495            j=j-1
8496        ENDDO
8497        IF ( first < i-1 ) CALL quicksort_itarget(itarget, vffrac, ztransp, first, i-1)
8498        IF ( j+1 < last )  CALL quicksort_itarget(itarget, vffrac, ztransp, j+1, last)
8499    END SUBROUTINE quicksort_itarget
8500
8501    PURE FUNCTION svf_lt(svf1,svf2) result (res)
8502      TYPE (t_svf), INTENT(in) :: svf1,svf2
8503      LOGICAL                  :: res
8504      IF ( svf1%isurflt < svf2%isurflt  .OR.    &
8505          (svf1%isurflt == svf2%isurflt  .AND.  svf1%isurfs < svf2%isurfs) )  THEN
8506          res = .TRUE.
8507      ELSE
8508          res = .FALSE.
8509      ENDIF
8510    END FUNCTION svf_lt
8511
8512
8513!-- quicksort.f -*-f90-*-
8514!-- Author: t-nissie, adaptation J.Resler
8515!-- License: GPLv3
8516!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8517    RECURSIVE SUBROUTINE quicksort_svf(svfl, first, last)
8518        IMPLICIT NONE
8519        TYPE(t_svf), DIMENSION(:), INTENT(INOUT)  :: svfl
8520        INTEGER(iwp), INTENT(IN)                  :: first, last
8521        TYPE(t_svf)                               :: x, t
8522        INTEGER(iwp)                              :: i, j
8523
8524        IF ( first>=last ) RETURN
8525        x = svfl( (first+last) / 2 )
8526        i = first
8527        j = last
8528        DO
8529            DO while ( svf_lt(svfl(i),x) )
8530               i=i+1
8531            ENDDO
8532            DO while ( svf_lt(x,svfl(j)) )
8533                j=j-1
8534            ENDDO
8535            IF ( i >= j ) EXIT
8536            t = svfl(i);  svfl(i) = svfl(j);  svfl(j) = t
8537            i=i+1
8538            j=j-1
8539        ENDDO
8540        IF ( first < i-1 ) CALL quicksort_svf(svfl, first, i-1)
8541        IF ( j+1 < last )  CALL quicksort_svf(svfl, j+1, last)
8542    END SUBROUTINE quicksort_svf
8543
8544    PURE FUNCTION csf_lt(csf1,csf2) result (res)
8545      TYPE (t_csf), INTENT(in) :: csf1,csf2
8546      LOGICAL                  :: res
8547      IF ( csf1%ip < csf2%ip  .OR.    &
8548           (csf1%ip == csf2%ip  .AND.  csf1%itx < csf2%itx)  .OR.  &
8549           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity < csf2%ity)  .OR.  &
8550           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity == csf2%ity  .AND.   &
8551            csf1%itz < csf2%itz)  .OR.  &
8552           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity == csf2%ity  .AND.   &
8553            csf1%itz == csf2%itz  .AND.  csf1%isurfs < csf2%isurfs) )  THEN
8554          res = .TRUE.
8555      ELSE
8556          res = .FALSE.
8557      ENDIF
8558    END FUNCTION csf_lt
8559
8560
8561!-- quicksort.f -*-f90-*-
8562!-- Author: t-nissie, adaptation J.Resler
8563!-- License: GPLv3
8564!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8565    RECURSIVE SUBROUTINE quicksort_csf(csfl, first, last)
8566        IMPLICIT NONE
8567        TYPE(t_csf), DIMENSION(:), INTENT(INOUT)  :: csfl
8568        INTEGER(iwp), INTENT(IN)                  :: first, last
8569        TYPE(t_csf)                               :: x, t
8570        INTEGER(iwp)                              :: i, j
8571
8572        IF ( first>=last ) RETURN
8573        x = csfl( (first+last)/2 )
8574        i = first
8575        j = last
8576        DO
8577            DO while ( csf_lt(csfl(i),x) )
8578                i=i+1
8579            ENDDO
8580            DO while ( csf_lt(x,csfl(j)) )
8581                j=j-1
8582            ENDDO
8583            IF ( i >= j ) EXIT
8584            t = csfl(i);  csfl(i) = csfl(j);  csfl(j) = t
8585            i=i+1
8586            j=j-1
8587        ENDDO
8588        IF ( first < i-1 ) CALL quicksort_csf(csfl, first, i-1)
8589        IF ( j+1 < last )  CALL quicksort_csf(csfl, j+1, last)
8590    END SUBROUTINE quicksort_csf
8591
8592   
8593    SUBROUTINE merge_and_grow_csf(newsize)
8594        INTEGER(iwp), INTENT(in)                :: newsize  !< new array size after grow, must be >= ncsfl
8595                                                            !< or -1 to shrink to minimum
8596        INTEGER(iwp)                            :: iread, iwrite
8597        TYPE(t_csf), DIMENSION(:), POINTER      :: acsfnew
8598        CHARACTER(100)                          :: msg
8599
8600        IF ( newsize == -1 )  THEN
8601!--         merge in-place
8602            acsfnew => acsf
8603        ELSE
8604!--         allocate new array
8605            IF ( mcsf == 0 )  THEN
8606                ALLOCATE( acsf1(newsize) )
8607                acsfnew => acsf1
8608            ELSE
8609                ALLOCATE( acsf2(newsize) )
8610                acsfnew => acsf2
8611            ENDIF
8612        ENDIF
8613
8614        IF ( ncsfl >= 1 )  THEN
8615!--         sort csf in place (quicksort)
8616            CALL quicksort_csf(acsf,1,ncsfl)
8617
8618!--         while moving to a new array, aggregate canopy sink factor records with identical box & source
8619            acsfnew(1) = acsf(1)
8620            iwrite = 1
8621            DO iread = 2, ncsfl
8622!--             here acsf(kcsf) already has values from acsf(icsf)
8623                IF ( acsfnew(iwrite)%itx == acsf(iread)%itx &
8624                         .AND.  acsfnew(iwrite)%ity == acsf(iread)%ity &
8625                         .AND.  acsfnew(iwrite)%itz == acsf(iread)%itz &
8626                         .AND.  acsfnew(iwrite)%isurfs == acsf(iread)%isurfs )  THEN
8627
8628                    acsfnew(iwrite)%rcvf = acsfnew(iwrite)%rcvf + acsf(iread)%rcvf
8629!--                 advance reading index, keep writing index
8630                ELSE
8631!--                 not identical, just advance and copy
8632                    iwrite = iwrite + 1
8633                    acsfnew(iwrite) = acsf(iread)
8634                ENDIF
8635            ENDDO
8636            ncsfl = iwrite
8637        ENDIF
8638
8639        IF ( newsize == -1 )  THEN
8640!--         allocate new array and copy shrinked data
8641            IF ( mcsf == 0 )  THEN
8642                ALLOCATE( acsf1(ncsfl) )
8643                acsf1(1:ncsfl) = acsf2(1:ncsfl)
8644            ELSE
8645                ALLOCATE( acsf2(ncsfl) )
8646                acsf2(1:ncsfl) = acsf1(1:ncsfl)
8647            ENDIF
8648        ENDIF
8649
8650!--     deallocate old array
8651        IF ( mcsf == 0 )  THEN
8652            mcsf = 1
8653            acsf => acsf1
8654            DEALLOCATE( acsf2 )
8655        ELSE
8656            mcsf = 0
8657            acsf => acsf2
8658            DEALLOCATE( acsf1 )
8659        ENDIF
8660        ncsfla = newsize
8661
8662        WRITE(msg,'(A,2I12)') 'Grow acsf2:',ncsfl,ncsfla
8663        CALL radiation_write_debug_log( msg )
8664
8665    END SUBROUTINE merge_and_grow_csf
8666
8667   
8668!-- quicksort.f -*-f90-*-
8669!-- Author: t-nissie, adaptation J.Resler
8670!-- License: GPLv3
8671!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8672    RECURSIVE SUBROUTINE quicksort_csf2(kpcsflt, pcsflt, first, last)
8673        IMPLICIT NONE
8674        INTEGER(iwp), DIMENSION(:,:), INTENT(INOUT)  :: kpcsflt
8675        REAL(wp), DIMENSION(:,:), INTENT(INOUT)      :: pcsflt
8676        INTEGER(iwp), INTENT(IN)                     :: first, last
8677        REAL(wp), DIMENSION(ndcsf)                   :: t2
8678        INTEGER(iwp), DIMENSION(kdcsf)               :: x, t1
8679        INTEGER(iwp)                                 :: i, j
8680
8681        IF ( first>=last ) RETURN
8682        x = kpcsflt(:, (first+last)/2 )
8683        i = first
8684        j = last
8685        DO
8686            DO while ( csf_lt2(kpcsflt(:,i),x) )
8687                i=i+1
8688            ENDDO
8689            DO while ( csf_lt2(x,kpcsflt(:,j)) )
8690                j=j-1
8691            ENDDO
8692            IF ( i >= j ) EXIT
8693            t1 = kpcsflt(:,i);  kpcsflt(:,i) = kpcsflt(:,j);  kpcsflt(:,j) = t1
8694            t2 = pcsflt(:,i);  pcsflt(:,i) = pcsflt(:,j);  pcsflt(:,j) = t2
8695            i=i+1
8696            j=j-1
8697        ENDDO
8698        IF ( first < i-1 ) CALL quicksort_csf2(kpcsflt, pcsflt, first, i-1)
8699        IF ( j+1 < last )  CALL quicksort_csf2(kpcsflt, pcsflt, j+1, last)
8700    END SUBROUTINE quicksort_csf2
8701   
8702
8703    PURE FUNCTION csf_lt2(item1, item2) result(res)
8704        INTEGER(iwp), DIMENSION(kdcsf), INTENT(in)  :: item1, item2
8705        LOGICAL                                     :: res
8706        res = ( (item1(3) < item2(3))                                                        &
8707             .OR.  (item1(3) == item2(3)  .AND.  item1(2) < item2(2))                            &
8708             .OR.  (item1(3) == item2(3)  .AND.  item1(2) == item2(2)  .AND.  item1(1) < item2(1)) &
8709             .OR.  (item1(3) == item2(3)  .AND.  item1(2) == item2(2)  .AND.  item1(1) == item2(1) &
8710                 .AND.  item1(4) < item2(4)) )
8711    END FUNCTION csf_lt2
8712
8713    PURE FUNCTION searchsorted(athresh, val) result(ind)
8714        REAL(wp), DIMENSION(:), INTENT(IN)  :: athresh
8715        REAL(wp), INTENT(IN)                :: val
8716        INTEGER(iwp)                        :: ind
8717        INTEGER(iwp)                        :: i
8718
8719        DO i = LBOUND(athresh, 1), UBOUND(athresh, 1)
8720            IF ( val < athresh(i) ) THEN
8721                ind = i - 1
8722                RETURN
8723            ENDIF
8724        ENDDO
8725        ind = UBOUND(athresh, 1)
8726    END FUNCTION searchsorted
8727
8728!------------------------------------------------------------------------------!
8729! Description:
8730! ------------
8731!
8732!> radiation_radflux_gridbox subroutine gives the sw and lw radiation fluxes at the
8733!> faces of a gridbox defined at i,j,k and located in the urban layer.
8734!> The total sw and the diffuse sw radiation as well as the lw radiation fluxes at
8735!> the gridbox 6 faces are stored in sw_gridbox, swd_gridbox, and lw_gridbox arrays,
8736!> respectively, in the following order:
8737!>  up_face, down_face, north_face, south_face, east_face, west_face
8738!>
8739!> The subroutine reports also how successful was the search process via the parameter
8740!> i_feedback as follow:
8741!> - i_feedback =  1 : successful
8742!> - i_feedback = -1 : unsuccessful; the requisted point is outside the urban domain
8743!> - i_feedback =  0 : uncomplete; some gridbox faces fluxes are missing
8744!>
8745!>
8746!> It is called outside from usm_urban_surface_mod whenever the radiation fluxes
8747!> are needed.
8748!>
8749!> This routine is not used so far. However, it may serve as an interface for radiation
8750!> fluxes of urban and land surfaces
8751!>
8752!> TODO:
8753!>    - Compare performance when using some combination of the Fortran intrinsic
8754!>      functions, e.g. MINLOC, MAXLOC, ALL, ANY and COUNT functions, which search
8755!>      surfl array for elements meeting user-specified criterion, i.e. i,j,k
8756!>    - Report non-found or incomplete radiation fluxes arrays , if any, at the
8757!>      gridbox faces in an error message form
8758!>
8759!------------------------------------------------------------------------------!
8760    SUBROUTINE radiation_radflux_gridbox(i,j,k,sw_gridbox,swd_gridbox,lw_gridbox,i_feedback)
8761       
8762        IMPLICIT NONE
8763
8764        INTEGER(iwp),                 INTENT(in)  :: i,j,k                 !< gridbox indices at which fluxes are required
8765        INTEGER(iwp)                              :: ii,jj,kk,d            !< surface indices and type
8766        INTEGER(iwp)                              :: l                     !< surface id
8767        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
8768        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
8769        INTEGER(iwp),                 INTENT(out) :: i_feedback            !< feedback to report how the search was successful
8770
8771
8772!-- initialize variables
8773        i_feedback  = -999999
8774        sw_gridbox  = -999999.9_wp
8775        lw_gridbox  = -999999.9_wp
8776        swd_gridbox = -999999.9_wp
8777       
8778!-- check the requisted grid indices
8779        IF ( k < nzb   .OR.  k > nzut  .OR.   &
8780             j < nysg  .OR.  j > nyng  .OR.   &
8781             i < nxlg  .OR.  i > nxrg         &
8782             ) THEN
8783           i_feedback = -1
8784           RETURN
8785        ENDIF
8786
8787!-- search for the required grid and formulate the fluxes at the 6 gridbox faces
8788        DO l = 1, nsurfl
8789            ii = surfl(ix,l)
8790            jj = surfl(iy,l)
8791            kk = surfl(iz,l)
8792
8793            IF ( ii == i  .AND.  jj == j  .AND.  kk == k ) THEN
8794               d = surfl(id,l)
8795
8796               SELECT CASE ( d )
8797
8798               CASE (iup_u,iup_l)                          !- gridbox up_facing face
8799                  sw_gridbox(1) = surfinsw(l)
8800                  lw_gridbox(1) = surfinlw(l)
8801                  swd_gridbox(1) = surfinswdif(l)
8802
8803               CASE (inorth_u,inorth_l)                    !- gridbox north_facing face
8804                  sw_gridbox(3) = surfinsw(l)
8805                  lw_gridbox(3) = surfinlw(l)
8806                  swd_gridbox(3) = surfinswdif(l)
8807
8808               CASE (isouth_u,isouth_l)                    !- gridbox south_facing face
8809                  sw_gridbox(4) = surfinsw(l)
8810                  lw_gridbox(4) = surfinlw(l)
8811                  swd_gridbox(4) = surfinswdif(l)
8812
8813               CASE (ieast_u,ieast_l)                      !- gridbox east_facing face
8814                  sw_gridbox(5) = surfinsw(l)
8815                  lw_gridbox(5) = surfinlw(l)
8816                  swd_gridbox(5) = surfinswdif(l)
8817
8818               CASE (iwest_u,iwest_l)                      !- gridbox west_facing face
8819                  sw_gridbox(6) = surfinsw(l)
8820                  lw_gridbox(6) = surfinlw(l)
8821                  swd_gridbox(6) = surfinswdif(l)
8822
8823               END SELECT
8824
8825            ENDIF
8826
8827        IF ( ALL( sw_gridbox(:)  /= -999999.9_wp )  ) EXIT
8828        ENDDO
8829
8830!-- check the completeness of the fluxes at all gidbox faces       
8831!-- TODO: report non-found or incomplete rad fluxes arrays in an error message form
8832        IF ( ANY( sw_gridbox(:)  <= -999999.9_wp )  .OR.   &
8833             ANY( swd_gridbox(:) <= -999999.9_wp )  .OR.   &
8834             ANY( lw_gridbox(:)  <= -999999.9_wp ) ) THEN
8835           i_feedback = 0
8836        ELSE
8837           i_feedback = 1
8838        ENDIF
8839       
8840        RETURN
8841       
8842    END SUBROUTINE radiation_radflux_gridbox
8843
8844!------------------------------------------------------------------------------!
8845!
8846! Description:
8847! ------------
8848!> Subroutine for averaging 3D data
8849!------------------------------------------------------------------------------!
8850SUBROUTINE radiation_3d_data_averaging( mode, variable )
8851 
8852
8853    USE control_parameters
8854
8855    USE indices
8856
8857    USE kinds
8858
8859    IMPLICIT NONE
8860
8861    CHARACTER (LEN=*) ::  mode    !<
8862    CHARACTER (LEN=*) :: variable !<
8863
8864    LOGICAL      ::  match_lsm !< flag indicating natural-type surface
8865    LOGICAL      ::  match_usm !< flag indicating urban-type surface
8866   
8867    INTEGER(iwp) ::  i !<
8868    INTEGER(iwp) ::  j !<
8869    INTEGER(iwp) ::  k !<
8870    INTEGER(iwp) ::  l, m !< index of current surface element
8871
8872    INTEGER(iwp)                                       :: ids, idsint_u, idsint_l, isurf
8873    CHARACTER(LEN=varnamelength)                       :: var
8874
8875!-- find the real name of the variable
8876    ids = -1
8877    l = -1
8878    var = TRIM(variable)
8879    DO i = 0, nd-1
8880        k = len(TRIM(var))
8881        j = len(TRIM(dirname(i)))
8882        IF ( k-j+1 >= 1_iwp ) THEN
8883           IF ( TRIM(var(k-j+1:k)) == TRIM(dirname(i)) )  THEN
8884               ids = i
8885               idsint_u = dirint_u(ids)
8886               idsint_l = dirint_l(ids)
8887               var = var(:k-j)
8888               EXIT
8889           ENDIF
8890        ENDIF
8891    ENDDO
8892    IF ( ids == -1 )  THEN
8893        var = TRIM(variable)
8894    ENDIF
8895
8896    IF ( mode == 'allocate' )  THEN
8897
8898       SELECT CASE ( TRIM( var ) )
8899!--          block of large scale (e.g. RRTMG) radiation output variables
8900             CASE ( 'rad_net*' )
8901                IF ( .NOT. ALLOCATED( rad_net_av ) )  THEN
8902                   ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
8903                ENDIF
8904                rad_net_av = 0.0_wp
8905             
8906             CASE ( 'rad_lw_in*' )
8907                IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) )  THEN
8908                   ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
8909                ENDIF
8910                rad_lw_in_xy_av = 0.0_wp
8911               
8912             CASE ( 'rad_lw_out*' )
8913                IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) )  THEN
8914                   ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
8915                ENDIF
8916                rad_lw_out_xy_av = 0.0_wp
8917               
8918             CASE ( 'rad_sw_in*' )
8919                IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) )  THEN
8920                   ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
8921                ENDIF
8922                rad_sw_in_xy_av = 0.0_wp
8923               
8924             CASE ( 'rad_sw_out*' )
8925                IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) )  THEN
8926                   ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
8927                ENDIF
8928                rad_sw_out_xy_av = 0.0_wp               
8929
8930             CASE ( 'rad_lw_in' )
8931                IF ( .NOT. ALLOCATED( rad_lw_in_av ) )  THEN
8932                   ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8933                ENDIF
8934                rad_lw_in_av = 0.0_wp
8935
8936             CASE ( 'rad_lw_out' )
8937                IF ( .NOT. ALLOCATED( rad_lw_out_av ) )  THEN
8938                   ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8939                ENDIF
8940                rad_lw_out_av = 0.0_wp
8941
8942             CASE ( 'rad_lw_cs_hr' )
8943                IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) )  THEN
8944                   ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8945                ENDIF
8946                rad_lw_cs_hr_av = 0.0_wp
8947
8948             CASE ( 'rad_lw_hr' )
8949                IF ( .NOT. ALLOCATED( rad_lw_hr_av ) )  THEN
8950                   ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8951                ENDIF
8952                rad_lw_hr_av = 0.0_wp
8953
8954             CASE ( 'rad_sw_in' )
8955                IF ( .NOT. ALLOCATED( rad_sw_in_av ) )  THEN
8956                   ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8957                ENDIF
8958                rad_sw_in_av = 0.0_wp
8959
8960             CASE ( 'rad_sw_out' )
8961                IF ( .NOT. ALLOCATED( rad_sw_out_av ) )  THEN
8962                   ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8963                ENDIF
8964                rad_sw_out_av = 0.0_wp
8965
8966             CASE ( 'rad_sw_cs_hr' )
8967                IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) )  THEN
8968                   ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8969                ENDIF
8970                rad_sw_cs_hr_av = 0.0_wp
8971
8972             CASE ( 'rad_sw_hr' )
8973                IF ( .NOT. ALLOCATED( rad_sw_hr_av ) )  THEN
8974                   ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8975                ENDIF
8976                rad_sw_hr_av = 0.0_wp
8977
8978!--          block of RTM output variables
8979             CASE ( 'rtm_rad_net' )
8980!--              array of complete radiation balance
8981                 IF ( .NOT.  ALLOCATED(surfradnet_av) )  THEN
8982                     ALLOCATE( surfradnet_av(nsurfl) )
8983                     surfradnet_av = 0.0_wp
8984                 ENDIF
8985
8986             CASE ( 'rtm_rad_insw' )
8987!--                 array of sw radiation falling to surface after i-th reflection
8988                 IF ( .NOT.  ALLOCATED(surfinsw_av) )  THEN
8989                     ALLOCATE( surfinsw_av(nsurfl) )
8990                     surfinsw_av = 0.0_wp
8991                 ENDIF
8992
8993             CASE ( 'rtm_rad_inlw' )
8994!--                 array of lw radiation falling to surface after i-th reflection
8995                 IF ( .NOT.  ALLOCATED(surfinlw_av) )  THEN
8996                     ALLOCATE( surfinlw_av(nsurfl) )
8997                     surfinlw_av = 0.0_wp
8998                 ENDIF
8999
9000             CASE ( 'rtm_rad_inswdir' )
9001!--                 array of direct sw radiation falling to surface from sun
9002                 IF ( .NOT.  ALLOCATED(surfinswdir_av) )  THEN
9003                     ALLOCATE( surfinswdir_av(nsurfl) )
9004                     surfinswdir_av = 0.0_wp
9005                 ENDIF
9006
9007             CASE ( 'rtm_rad_inswdif' )
9008!--                 array of difusion sw radiation falling to surface from sky and borders of the domain
9009                 IF ( .NOT.  ALLOCATED(surfinswdif_av) )  THEN
9010                     ALLOCATE( surfinswdif_av(nsurfl) )
9011                     surfinswdif_av = 0.0_wp
9012                 ENDIF
9013
9014             CASE ( 'rtm_rad_inswref' )
9015!--                 array of sw radiation falling to surface from reflections
9016                 IF ( .NOT.  ALLOCATED(surfinswref_av) )  THEN
9017                     ALLOCATE( surfinswref_av(nsurfl) )
9018                     surfinswref_av = 0.0_wp
9019                 ENDIF
9020
9021             CASE ( 'rtm_rad_inlwdif' )
9022!--                 array of sw radiation falling to surface after i-th reflection
9023                IF ( .NOT.  ALLOCATED(surfinlwdif_av) )  THEN
9024                     ALLOCATE( surfinlwdif_av(nsurfl) )
9025                     surfinlwdif_av = 0.0_wp
9026                 ENDIF
9027
9028             CASE ( 'rtm_rad_inlwref' )
9029!--                 array of lw radiation falling to surface from reflections
9030                 IF ( .NOT.  ALLOCATED(surfinlwref_av) )  THEN
9031                     ALLOCATE( surfinlwref_av(nsurfl) )
9032                     surfinlwref_av = 0.0_wp
9033                 ENDIF
9034
9035             CASE ( 'rtm_rad_outsw' )
9036!--                 array of sw radiation emitted from surface after i-th reflection
9037                 IF ( .NOT.  ALLOCATED(surfoutsw_av) )  THEN
9038                     ALLOCATE( surfoutsw_av(nsurfl) )
9039                     surfoutsw_av = 0.0_wp
9040                 ENDIF
9041
9042             CASE ( 'rtm_rad_outlw' )
9043!--                 array of lw radiation emitted from surface after i-th reflection
9044                 IF ( .NOT.  ALLOCATED(surfoutlw_av) )  THEN
9045                     ALLOCATE( surfoutlw_av(nsurfl) )
9046                     surfoutlw_av = 0.0_wp
9047                 ENDIF
9048             CASE ( 'rtm_rad_ressw' )
9049!--                 array of residua of sw radiation absorbed in surface after last reflection
9050                 IF ( .NOT.  ALLOCATED(surfins_av) )  THEN
9051                     ALLOCATE( surfins_av(nsurfl) )
9052                     surfins_av = 0.0_wp
9053                 ENDIF
9054
9055             CASE ( 'rtm_rad_reslw' )
9056!--                 array of residua of lw radiation absorbed in surface after last reflection
9057                 IF ( .NOT.  ALLOCATED(surfinl_av) )  THEN
9058                     ALLOCATE( surfinl_av(nsurfl) )
9059                     surfinl_av = 0.0_wp
9060                 ENDIF
9061
9062             CASE ( 'rtm_rad_pc_inlw' )
9063!--                 array of of lw radiation absorbed in plant canopy
9064                 IF ( .NOT.  ALLOCATED(pcbinlw_av) )  THEN
9065                     ALLOCATE( pcbinlw_av(1:npcbl) )
9066                     pcbinlw_av = 0.0_wp
9067                 ENDIF
9068
9069             CASE ( 'rtm_rad_pc_insw' )
9070!--                 array of of sw radiation absorbed in plant canopy
9071                 IF ( .NOT.  ALLOCATED(pcbinsw_av) )  THEN
9072                     ALLOCATE( pcbinsw_av(1:npcbl) )
9073                     pcbinsw_av = 0.0_wp
9074                 ENDIF
9075
9076             CASE ( 'rtm_rad_pc_inswdir' )
9077!--                 array of of direct sw radiation absorbed in plant canopy
9078                 IF ( .NOT.  ALLOCATED(pcbinswdir_av) )  THEN
9079                     ALLOCATE( pcbinswdir_av(1:npcbl) )
9080                     pcbinswdir_av = 0.0_wp
9081                 ENDIF
9082
9083             CASE ( 'rtm_rad_pc_inswdif' )
9084!--                 array of of diffuse sw radiation absorbed in plant canopy
9085                 IF ( .NOT.  ALLOCATED(pcbinswdif_av) )  THEN
9086                     ALLOCATE( pcbinswdif_av(1:npcbl) )
9087                     pcbinswdif_av = 0.0_wp
9088                 ENDIF
9089
9090             CASE ( 'rtm_rad_pc_inswref' )
9091!--                 array of of reflected sw radiation absorbed in plant canopy
9092                 IF ( .NOT.  ALLOCATED(pcbinswref_av) )  THEN
9093                     ALLOCATE( pcbinswref_av(1:npcbl) )
9094                     pcbinswref_av = 0.0_wp
9095                 ENDIF
9096
9097             CASE ( 'rtm_mrt_sw' )
9098                IF ( .NOT. ALLOCATED( mrtinsw_av ) )  THEN
9099                   ALLOCATE( mrtinsw_av(nmrtbl) )
9100                ENDIF
9101                mrtinsw_av = 0.0_wp
9102
9103             CASE ( 'rtm_mrt_lw' )
9104                IF ( .NOT. ALLOCATED( mrtinlw_av ) )  THEN
9105                   ALLOCATE( mrtinlw_av(nmrtbl) )
9106                ENDIF
9107                mrtinlw_av = 0.0_wp
9108
9109             CASE ( 'rtm_mrt' )
9110                IF ( .NOT. ALLOCATED( mrt_av ) )  THEN
9111                   ALLOCATE( mrt_av(nmrtbl) )
9112                ENDIF
9113                mrt_av = 0.0_wp
9114
9115          CASE DEFAULT
9116             CONTINUE
9117
9118       END SELECT
9119
9120    ELSEIF ( mode == 'sum' )  THEN
9121
9122       SELECT CASE ( TRIM( var ) )
9123!--       block of large scale (e.g. RRTMG) radiation output variables
9124          CASE ( 'rad_net*' )
9125             IF ( ALLOCATED( rad_net_av ) ) THEN
9126                DO  i = nxl, nxr
9127                   DO  j = nys, nyn
9128                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9129                                  surf_lsm_h%end_index(j,i)
9130                      match_usm = surf_usm_h%start_index(j,i) <=               &
9131                                  surf_usm_h%end_index(j,i)
9132
9133                     IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9134                         m = surf_lsm_h%end_index(j,i)
9135                         rad_net_av(j,i) = rad_net_av(j,i) +                   &
9136                                         surf_lsm_h%rad_net(m)
9137                      ELSEIF ( match_usm )  THEN
9138                         m = surf_usm_h%end_index(j,i)
9139                         rad_net_av(j,i) = rad_net_av(j,i) +                   &
9140                                         surf_usm_h%rad_net(m)
9141                      ENDIF
9142                   ENDDO
9143                ENDDO
9144             ENDIF
9145
9146          CASE ( 'rad_lw_in*' )
9147             IF ( ALLOCATED( rad_lw_in_xy_av ) ) THEN
9148                DO  i = nxl, nxr
9149                   DO  j = nys, nyn
9150                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9151                                  surf_lsm_h%end_index(j,i)
9152                      match_usm = surf_usm_h%start_index(j,i) <=               &
9153                                  surf_usm_h%end_index(j,i)
9154
9155                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9156                         m = surf_lsm_h%end_index(j,i)
9157                         rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i) +         &
9158                                         surf_lsm_h%rad_lw_in(m)
9159                      ELSEIF ( match_usm )  THEN
9160                         m = surf_usm_h%end_index(j,i)
9161                         rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i) +         &
9162                                         surf_usm_h%rad_lw_in(m)
9163                      ENDIF
9164                   ENDDO
9165                ENDDO
9166             ENDIF
9167             
9168          CASE ( 'rad_lw_out*' )
9169             IF ( ALLOCATED( rad_lw_out_xy_av ) ) THEN
9170                DO  i = nxl, nxr
9171                   DO  j = nys, nyn
9172                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9173                                  surf_lsm_h%end_index(j,i)
9174                      match_usm = surf_usm_h%start_index(j,i) <=               &
9175                                  surf_usm_h%end_index(j,i)
9176
9177                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9178                         m = surf_lsm_h%end_index(j,i)
9179                         rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i) +       &
9180                                                 surf_lsm_h%rad_lw_out(m)
9181                      ELSEIF ( match_usm )  THEN
9182                         m = surf_usm_h%end_index(j,i)
9183                         rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i) +       &
9184                                                 surf_usm_h%rad_lw_out(m)
9185                      ENDIF
9186                   ENDDO
9187                ENDDO
9188             ENDIF
9189             
9190          CASE ( 'rad_sw_in*' )
9191             IF ( ALLOCATED( rad_sw_in_xy_av ) ) THEN
9192                DO  i = nxl, nxr
9193                   DO  j = nys, nyn
9194                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9195                                  surf_lsm_h%end_index(j,i)
9196                      match_usm = surf_usm_h%start_index(j,i) <=               &
9197                                  surf_usm_h%end_index(j,i)
9198
9199                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9200                         m = surf_lsm_h%end_index(j,i)
9201                         rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i) +         &
9202                                                surf_lsm_h%rad_sw_in(m)
9203                      ELSEIF ( match_usm )  THEN
9204                         m = surf_usm_h%end_index(j,i)
9205                         rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i) +         &
9206                                                surf_usm_h%rad_sw_in(m)
9207                      ENDIF
9208                   ENDDO
9209                ENDDO
9210             ENDIF
9211             
9212          CASE ( 'rad_sw_out*' )
9213             IF ( ALLOCATED( rad_sw_out_xy_av ) ) THEN
9214                DO  i = nxl, nxr
9215                   DO  j = nys, nyn
9216                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9217                                  surf_lsm_h%end_index(j,i)
9218                      match_usm = surf_usm_h%start_index(j,i) <=               &
9219                                  surf_usm_h%end_index(j,i)
9220
9221                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9222                         m = surf_lsm_h%end_index(j,i)
9223                         rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i) +       &
9224                                                 surf_lsm_h%rad_sw_out(m)
9225                      ELSEIF ( match_usm )  THEN
9226                         m = surf_usm_h%end_index(j,i)
9227                         rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i) +       &
9228                                                 surf_usm_h%rad_sw_out(m)
9229                      ENDIF
9230                   ENDDO
9231                ENDDO
9232             ENDIF
9233             
9234          CASE ( 'rad_lw_in' )
9235             IF ( ALLOCATED( rad_lw_in_av ) ) THEN
9236                DO  i = nxlg, nxrg
9237                   DO  j = nysg, nyng
9238                      DO  k = nzb, nzt+1
9239                         rad_lw_in_av(k,j,i) = rad_lw_in_av(k,j,i)             &
9240                                               + rad_lw_in(k,j,i)
9241                      ENDDO
9242                   ENDDO
9243                ENDDO
9244             ENDIF
9245
9246          CASE ( 'rad_lw_out' )
9247             IF ( ALLOCATED( rad_lw_out_av ) ) THEN
9248                DO  i = nxlg, nxrg
9249                   DO  j = nysg, nyng
9250                      DO  k = nzb, nzt+1
9251                         rad_lw_out_av(k,j,i) = rad_lw_out_av(k,j,i)           &
9252                                                + rad_lw_out(k,j,i)
9253                      ENDDO
9254                   ENDDO
9255                ENDDO
9256             ENDIF
9257
9258          CASE ( 'rad_lw_cs_hr' )
9259             IF ( ALLOCATED( rad_lw_cs_hr_av ) ) THEN
9260                DO  i = nxlg, nxrg
9261                   DO  j = nysg, nyng
9262                      DO  k = nzb, nzt+1
9263                         rad_lw_cs_hr_av(k,j,i) = rad_lw_cs_hr_av(k,j,i)       &
9264                                                  + rad_lw_cs_hr(k,j,i)
9265                      ENDDO
9266                   ENDDO
9267                ENDDO
9268             ENDIF
9269
9270          CASE ( 'rad_lw_hr' )
9271             IF ( ALLOCATED( rad_lw_hr_av ) ) THEN
9272                DO  i = nxlg, nxrg
9273                   DO  j = nysg, nyng
9274                      DO  k = nzb, nzt+1
9275                         rad_lw_hr_av(k,j,i) = rad_lw_hr_av(k,j,i)             &
9276                                               + rad_lw_hr(k,j,i)
9277                      ENDDO
9278                   ENDDO
9279                ENDDO
9280             ENDIF
9281
9282          CASE ( 'rad_sw_in' )
9283             IF ( ALLOCATED( rad_sw_in_av ) ) THEN
9284                DO  i = nxlg, nxrg
9285                   DO  j = nysg, nyng
9286                      DO  k = nzb, nzt+1
9287                         rad_sw_in_av(k,j,i) = rad_sw_in_av(k,j,i)             &
9288                                               + rad_sw_in(k,j,i)
9289                      ENDDO
9290                   ENDDO
9291                ENDDO
9292             ENDIF
9293
9294          CASE ( 'rad_sw_out' )
9295             IF ( ALLOCATED( rad_sw_out_av ) ) THEN
9296                DO  i = nxlg, nxrg
9297                   DO  j = nysg, nyng
9298                      DO  k = nzb, nzt+1
9299                         rad_sw_out_av(k,j,i) = rad_sw_out_av(k,j,i)           &
9300                                                + rad_sw_out(k,j,i)
9301                      ENDDO
9302                   ENDDO
9303                ENDDO
9304             ENDIF
9305
9306          CASE ( 'rad_sw_cs_hr' )
9307             IF ( ALLOCATED( rad_sw_cs_hr_av ) ) THEN
9308                DO  i = nxlg, nxrg
9309                   DO  j = nysg, nyng
9310                      DO  k = nzb, nzt+1
9311                         rad_sw_cs_hr_av(k,j,i) = rad_sw_cs_hr_av(k,j,i)       &
9312                                                  + rad_sw_cs_hr(k,j,i)
9313                      ENDDO
9314                   ENDDO
9315                ENDDO
9316             ENDIF
9317
9318          CASE ( 'rad_sw_hr' )
9319             IF ( ALLOCATED( rad_sw_hr_av ) ) THEN
9320                DO  i = nxlg, nxrg
9321                   DO  j = nysg, nyng
9322                      DO  k = nzb, nzt+1
9323                         rad_sw_hr_av(k,j,i) = rad_sw_hr_av(k,j,i)             &
9324                                               + rad_sw_hr(k,j,i)
9325                      ENDDO
9326                   ENDDO
9327                ENDDO
9328             ENDIF
9329
9330!--       block of RTM output variables
9331          CASE ( 'rtm_rad_net' )
9332!--           array of complete radiation balance
9333              DO isurf = dirstart(ids), dirend(ids)
9334                 IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9335                    surfradnet_av(isurf) = surfinsw(isurf) - surfoutsw(isurf) +  surfinlw(isurf) - surfoutlw(isurf)
9336                 ENDIF
9337              ENDDO
9338
9339          CASE ( 'rtm_rad_insw' )
9340!--           array of sw radiation falling to surface after i-th reflection
9341              DO isurf = dirstart(ids), dirend(ids)
9342                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9343                      surfinsw_av(isurf) = surfinsw_av(isurf) + surfinsw(isurf)
9344                  ENDIF
9345              ENDDO
9346
9347          CASE ( 'rtm_rad_inlw' )
9348!--           array of lw radiation falling to surface after i-th reflection
9349              DO isurf = dirstart(ids), dirend(ids)
9350                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9351                      surfinlw_av(isurf) = surfinlw_av(isurf) + surfinlw(isurf)
9352                  ENDIF
9353              ENDDO
9354
9355          CASE ( 'rtm_rad_inswdir' )
9356!--           array of direct sw radiation falling to surface from sun
9357              DO isurf = dirstart(ids), dirend(ids)
9358                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9359                      surfinswdir_av(isurf) = surfinswdir_av(isurf) + surfinswdir(isurf)
9360                  ENDIF
9361              ENDDO
9362
9363          CASE ( 'rtm_rad_inswdif' )
9364!--           array of difusion sw radiation falling to surface from sky and borders of the domain
9365              DO isurf = dirstart(ids), dirend(ids)
9366                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9367                      surfinswdif_av(isurf) = surfinswdif_av(isurf) + surfinswdif(isurf)
9368                  ENDIF
9369              ENDDO
9370
9371          CASE ( 'rtm_rad_inswref' )
9372!--           array of sw radiation falling to surface from reflections
9373              DO isurf = dirstart(ids), dirend(ids)
9374                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9375                      surfinswref_av(isurf) = surfinswref_av(isurf) + surfinsw(isurf) - &
9376                                          surfinswdir(isurf) - surfinswdif(isurf)
9377                  ENDIF
9378              ENDDO
9379
9380
9381          CASE ( 'rtm_rad_inlwdif' )
9382!--           array of sw radiation falling to surface after i-th reflection
9383              DO isurf = dirstart(ids), dirend(ids)
9384                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9385                      surfinlwdif_av(isurf) = surfinlwdif_av(isurf) + surfinlwdif(isurf)
9386                  ENDIF
9387              ENDDO
9388!
9389          CASE ( 'rtm_rad_inlwref' )
9390!--           array of lw radiation falling to surface from reflections
9391              DO isurf = dirstart(ids), dirend(ids)
9392                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9393                      surfinlwref_av(isurf) = surfinlwref_av(isurf) + &
9394                                          surfinlw(isurf) - surfinlwdif(isurf)
9395                  ENDIF
9396              ENDDO
9397
9398          CASE ( 'rtm_rad_outsw' )
9399!--           array of sw radiation emitted from surface after i-th reflection
9400              DO isurf = dirstart(ids), dirend(ids)
9401                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9402                      surfoutsw_av(isurf) = surfoutsw_av(isurf) + surfoutsw(isurf)
9403                  ENDIF
9404              ENDDO
9405
9406          CASE ( 'rtm_rad_outlw' )
9407!--           array of lw radiation emitted from surface after i-th reflection
9408              DO isurf = dirstart(ids), dirend(ids)
9409                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9410                      surfoutlw_av(isurf) = surfoutlw_av(isurf) + surfoutlw(isurf)
9411                  ENDIF
9412              ENDDO
9413
9414          CASE ( 'rtm_rad_ressw' )
9415!--           array of residua of sw radiation absorbed in surface after last reflection
9416              DO isurf = dirstart(ids), dirend(ids)
9417                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9418                      surfins_av(isurf) = surfins_av(isurf) + surfins(isurf)
9419                  ENDIF
9420              ENDDO
9421
9422          CASE ( 'rtm_rad_reslw' )
9423!--           array of residua of lw radiation absorbed in surface after last reflection
9424              DO isurf = dirstart(ids), dirend(ids)
9425                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9426                      surfinl_av(isurf) = surfinl_av(isurf) + surfinl(isurf)
9427                  ENDIF
9428              ENDDO
9429
9430          CASE ( 'rtm_rad_pc_inlw' )
9431              DO l = 1, npcbl
9432                 pcbinlw_av(l) = pcbinlw_av(l) + pcbinlw(l)
9433              ENDDO
9434
9435          CASE ( 'rtm_rad_pc_insw' )
9436              DO l = 1, npcbl
9437                 pcbinsw_av(l) = pcbinsw_av(l) + pcbinsw(l)
9438              ENDDO
9439
9440          CASE ( 'rtm_rad_pc_inswdir' )
9441              DO l = 1, npcbl
9442                 pcbinswdir_av(l) = pcbinswdir_av(l) + pcbinswdir(l)
9443              ENDDO
9444
9445          CASE ( 'rtm_rad_pc_inswdif' )
9446              DO l = 1, npcbl
9447                 pcbinswdif_av(l) = pcbinswdif_av(l) + pcbinswdif(l)
9448              ENDDO
9449
9450          CASE ( 'rtm_rad_pc_inswref' )
9451              DO l = 1, npcbl
9452                 pcbinswref_av(l) = pcbinswref_av(l) + pcbinsw(l) - pcbinswdir(l) - pcbinswdif(l)
9453              ENDDO
9454
9455          CASE ( 'rad_mrt_sw' )
9456             IF ( ALLOCATED( mrtinsw_av ) )  THEN
9457                mrtinsw_av(:) = mrtinsw_av(:) + mrtinsw(:)
9458             ENDIF
9459
9460          CASE ( 'rad_mrt_lw' )
9461             IF ( ALLOCATED( mrtinlw_av ) )  THEN
9462                mrtinlw_av(:) = mrtinlw_av(:) + mrtinlw(:)
9463             ENDIF
9464
9465          CASE ( 'rad_mrt' )
9466             IF ( ALLOCATED( mrt_av ) )  THEN
9467                mrt_av(:) = mrt_av(:) + mrt(:)
9468             ENDIF
9469
9470          CASE DEFAULT
9471             CONTINUE
9472
9473       END SELECT
9474
9475    ELSEIF ( mode == 'average' )  THEN
9476
9477       SELECT CASE ( TRIM( var ) )
9478!--       block of large scale (e.g. RRTMG) radiation output variables
9479          CASE ( 'rad_net*' )
9480             IF ( ALLOCATED( rad_net_av ) ) THEN
9481                DO  i = nxlg, nxrg
9482                   DO  j = nysg, nyng
9483                      rad_net_av(j,i) = rad_net_av(j,i)                        &
9484                                        / REAL( average_count_3d, KIND=wp )
9485                   ENDDO
9486                ENDDO
9487             ENDIF
9488             
9489          CASE ( 'rad_lw_in*' )
9490             IF ( ALLOCATED( rad_lw_in_xy_av ) ) THEN
9491                DO  i = nxlg, nxrg
9492                   DO  j = nysg, nyng
9493                      rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i)              &
9494                                        / REAL( average_count_3d, KIND=wp )
9495                   ENDDO
9496                ENDDO
9497             ENDIF
9498             
9499          CASE ( 'rad_lw_out*' )
9500             IF ( ALLOCATED( rad_lw_out_xy_av ) ) THEN
9501                DO  i = nxlg, nxrg
9502                   DO  j = nysg, nyng
9503                      rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i)            &
9504                                        / REAL( average_count_3d, KIND=wp )
9505                   ENDDO
9506                ENDDO
9507             ENDIF
9508             
9509          CASE ( 'rad_sw_in*' )
9510             IF ( ALLOCATED( rad_sw_in_xy_av ) ) THEN
9511                DO  i = nxlg, nxrg
9512                   DO  j = nysg, nyng
9513                      rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i)              &
9514                                        / REAL( average_count_3d, KIND=wp )
9515                   ENDDO
9516                ENDDO
9517             ENDIF
9518             
9519          CASE ( 'rad_sw_out*' )
9520             IF ( ALLOCATED( rad_sw_out_xy_av ) ) THEN
9521                DO  i = nxlg, nxrg
9522                   DO  j = nysg, nyng
9523                      rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i)             &
9524                                        / REAL( average_count_3d, KIND=wp )
9525                   ENDDO
9526                ENDDO
9527             ENDIF
9528
9529          CASE ( 'rad_lw_in' )
9530             IF ( ALLOCATED( rad_lw_in_av ) ) THEN
9531                DO  i = nxlg, nxrg
9532                   DO  j = nysg, nyng
9533                      DO  k = nzb, nzt+1
9534                         rad_lw_in_av(k,j,i) = rad_lw_in_av(k,j,i)             &
9535                                               / REAL( average_count_3d, KIND=wp )
9536                      ENDDO
9537                   ENDDO
9538                ENDDO
9539             ENDIF
9540
9541          CASE ( 'rad_lw_out' )
9542             IF ( ALLOCATED( rad_lw_out_av ) ) THEN
9543                DO  i = nxlg, nxrg
9544                   DO  j = nysg, nyng
9545                      DO  k = nzb, nzt+1
9546                         rad_lw_out_av(k,j,i) = rad_lw_out_av(k,j,i)           &
9547                                                / REAL( average_count_3d, KIND=wp )
9548                      ENDDO
9549                   ENDDO
9550                ENDDO
9551             ENDIF
9552
9553          CASE ( 'rad_lw_cs_hr' )
9554             IF ( ALLOCATED( rad_lw_cs_hr_av ) ) THEN
9555                DO  i = nxlg, nxrg
9556                   DO  j = nysg, nyng
9557                      DO  k = nzb, nzt+1
9558                         rad_lw_cs_hr_av(k,j,i) = rad_lw_cs_hr_av(k,j,i)       &
9559                                                / REAL( average_count_3d, KIND=wp )
9560                      ENDDO
9561                   ENDDO
9562                ENDDO
9563             ENDIF
9564
9565          CASE ( 'rad_lw_hr' )
9566             IF ( ALLOCATED( rad_lw_hr_av ) ) THEN
9567                DO  i = nxlg, nxrg
9568                   DO  j = nysg, nyng
9569                      DO  k = nzb, nzt+1
9570                         rad_lw_hr_av(k,j,i) = rad_lw_hr_av(k,j,i)             &
9571                                               / REAL( average_count_3d, KIND=wp )
9572                      ENDDO
9573                   ENDDO
9574                ENDDO
9575             ENDIF
9576
9577          CASE ( 'rad_sw_in' )
9578             IF ( ALLOCATED( rad_sw_in_av ) ) THEN
9579                DO  i = nxlg, nxrg
9580                   DO  j = nysg, nyng
9581                      DO  k = nzb, nzt+1
9582                         rad_sw_in_av(k,j,i) = rad_sw_in_av(k,j,i)             &
9583                                               / REAL( average_count_3d, KIND=wp )
9584                      ENDDO
9585                   ENDDO
9586                ENDDO
9587             ENDIF
9588
9589          CASE ( 'rad_sw_out' )
9590             IF ( ALLOCATED( rad_sw_out_av ) ) THEN
9591                DO  i = nxlg, nxrg
9592                   DO  j = nysg, nyng
9593                      DO  k = nzb, nzt+1
9594                         rad_sw_out_av(k,j,i) = rad_sw_out_av(k,j,i)           &
9595                                                / REAL( average_count_3d, KIND=wp )
9596                      ENDDO
9597                   ENDDO
9598                ENDDO
9599             ENDIF
9600
9601          CASE ( 'rad_sw_cs_hr' )
9602             IF ( ALLOCATED( rad_sw_cs_hr_av ) ) THEN
9603                DO  i = nxlg, nxrg
9604                   DO  j = nysg, nyng
9605                      DO  k = nzb, nzt+1
9606                         rad_sw_cs_hr_av(k,j,i) = rad_sw_cs_hr_av(k,j,i)       &
9607                                                / REAL( average_count_3d, KIND=wp )
9608                      ENDDO
9609                   ENDDO
9610                ENDDO
9611             ENDIF
9612
9613          CASE ( 'rad_sw_hr' )
9614             IF ( ALLOCATED( rad_sw_hr_av ) ) THEN
9615                DO  i = nxlg, nxrg
9616                   DO  j = nysg, nyng
9617                      DO  k = nzb, nzt+1
9618                         rad_sw_hr_av(k,j,i) = rad_sw_hr_av(k,j,i)             &
9619                                               / REAL( average_count_3d, KIND=wp )
9620                      ENDDO
9621                   ENDDO
9622                ENDDO
9623             ENDIF
9624
9625!--       block of RTM output variables
9626          CASE ( 'rtm_rad_net' )
9627!--           array of complete radiation balance
9628              DO isurf = dirstart(ids), dirend(ids)
9629                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9630                      surfradnet_av(isurf) = surfinsw_av(isurf) / REAL( average_count_3d, kind=wp )
9631                  ENDIF
9632              ENDDO
9633
9634          CASE ( 'rtm_rad_insw' )
9635!--           array of sw radiation falling to surface after i-th reflection
9636              DO isurf = dirstart(ids), dirend(ids)
9637                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9638                      surfinsw_av(isurf) = surfinsw_av(isurf) / REAL( average_count_3d, kind=wp )
9639                  ENDIF
9640              ENDDO
9641
9642          CASE ( 'rtm_rad_inlw' )
9643!--           array of lw radiation falling to surface after i-th reflection
9644              DO isurf = dirstart(ids), dirend(ids)
9645                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9646                      surfinlw_av(isurf) = surfinlw_av(isurf) / REAL( average_count_3d, kind=wp )
9647                  ENDIF
9648              ENDDO
9649
9650          CASE ( 'rtm_rad_inswdir' )
9651!--           array of direct sw radiation falling to surface from sun
9652              DO isurf = dirstart(ids), dirend(ids)
9653                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9654                      surfinswdir_av(isurf) = surfinswdir_av(isurf) / REAL( average_count_3d, kind=wp )
9655                  ENDIF
9656              ENDDO
9657
9658          CASE ( 'rtm_rad_inswdif' )
9659!--           array of difusion sw radiation falling to surface from sky and borders of the domain
9660              DO isurf = dirstart(ids), dirend(ids)
9661                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9662                      surfinswdif_av(isurf) = surfinswdif_av(isurf) / REAL( average_count_3d, kind=wp )
9663                  ENDIF
9664              ENDDO
9665
9666          CASE ( 'rtm_rad_inswref' )
9667!--           array of sw radiation falling to surface from reflections
9668              DO isurf = dirstart(ids), dirend(ids)
9669                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9670                      surfinswref_av(isurf) = surfinswref_av(isurf) / REAL( average_count_3d, kind=wp )
9671                  ENDIF
9672              ENDDO
9673
9674          CASE ( 'rtm_rad_inlwdif' )
9675!--           array of sw radiation falling to surface after i-th reflection
9676              DO isurf = dirstart(ids), dirend(ids)
9677                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9678                      surfinlwdif_av(isurf) = surfinlwdif_av(isurf) / REAL( average_count_3d, kind=wp )
9679                  ENDIF
9680              ENDDO
9681
9682          CASE ( 'rtm_rad_inlwref' )
9683!--           array of lw radiation falling to surface from reflections
9684              DO isurf = dirstart(ids), dirend(ids)
9685                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9686                      surfinlwref_av(isurf) = surfinlwref_av(isurf) / REAL( average_count_3d, kind=wp )
9687                  ENDIF
9688              ENDDO
9689
9690          CASE ( 'rtm_rad_outsw' )
9691!--           array of sw radiation emitted from surface after i-th reflection
9692              DO isurf = dirstart(ids), dirend(ids)
9693                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9694                      surfoutsw_av(isurf) = surfoutsw_av(isurf) / REAL( average_count_3d, kind=wp )
9695                  ENDIF
9696              ENDDO
9697
9698          CASE ( 'rtm_rad_outlw' )
9699!--           array of lw radiation emitted from surface after i-th reflection
9700              DO isurf = dirstart(ids), dirend(ids)
9701                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9702                      surfoutlw_av(isurf) = surfoutlw_av(isurf) / REAL( average_count_3d, kind=wp )
9703                  ENDIF
9704              ENDDO
9705
9706          CASE ( 'rtm_rad_ressw' )
9707!--           array of residua of sw radiation absorbed in surface after last reflection
9708              DO isurf = dirstart(ids), dirend(ids)
9709                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9710                      surfins_av(isurf) = surfins_av(isurf) / REAL( average_count_3d, kind=wp )
9711                  ENDIF
9712              ENDDO
9713
9714          CASE ( 'rtm_rad_reslw' )
9715!--           array of residua of lw radiation absorbed in surface after last reflection
9716              DO isurf = dirstart(ids), dirend(ids)
9717                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9718                      surfinl_av(isurf) = surfinl_av(isurf) / REAL( average_count_3d, kind=wp )
9719                  ENDIF
9720              ENDDO
9721
9722          CASE ( 'rtm_rad_pc_inlw' )
9723              DO l = 1, npcbl
9724                 pcbinlw_av(:) = pcbinlw_av(:) / REAL( average_count_3d, kind=wp )
9725              ENDDO
9726
9727          CASE ( 'rtm_rad_pc_insw' )
9728              DO l = 1, npcbl
9729                 pcbinsw_av(:) = pcbinsw_av(:) / REAL( average_count_3d, kind=wp )
9730              ENDDO
9731
9732          CASE ( 'rtm_rad_pc_inswdir' )
9733              DO l = 1, npcbl
9734                 pcbinswdir_av(:) = pcbinswdir_av(:) / REAL( average_count_3d, kind=wp )
9735              ENDDO
9736
9737          CASE ( 'rtm_rad_pc_inswdif' )
9738              DO l = 1, npcbl
9739                 pcbinswdif_av(:) = pcbinswdif_av(:) / REAL( average_count_3d, kind=wp )
9740              ENDDO
9741
9742          CASE ( 'rtm_rad_pc_inswref' )
9743              DO l = 1, npcbl
9744                 pcbinswref_av(:) = pcbinswref_av(:) / REAL( average_count_3d, kind=wp )
9745              ENDDO
9746
9747          CASE ( 'rad_mrt_lw' )
9748             IF ( ALLOCATED( mrtinlw_av ) )  THEN
9749                mrtinlw_av(:) = mrtinlw_av(:) / REAL( average_count_3d, KIND=wp )
9750             ENDIF
9751
9752          CASE ( 'rad_mrt' )
9753             IF ( ALLOCATED( mrt_av ) )  THEN
9754                mrt_av(:) = mrt_av(:) / REAL( average_count_3d, KIND=wp )
9755             ENDIF
9756
9757       END SELECT
9758
9759    ENDIF
9760
9761END SUBROUTINE radiation_3d_data_averaging
9762
9763
9764!------------------------------------------------------------------------------!
9765!
9766! Description:
9767! ------------
9768!> Subroutine defining appropriate grid for netcdf variables.
9769!> It is called out from subroutine netcdf.
9770!------------------------------------------------------------------------------!
9771SUBROUTINE radiation_define_netcdf_grid( variable, found, grid_x, grid_y, grid_z )
9772   
9773    IMPLICIT NONE
9774
9775    CHARACTER (LEN=*), INTENT(IN)  ::  variable    !<
9776    LOGICAL, INTENT(OUT)           ::  found       !<
9777    CHARACTER (LEN=*), INTENT(OUT) ::  grid_x      !<
9778    CHARACTER (LEN=*), INTENT(OUT) ::  grid_y      !<
9779    CHARACTER (LEN=*), INTENT(OUT) ::  grid_z      !<
9780
9781    CHARACTER (len=varnamelength)  :: var
9782
9783    found  = .TRUE.
9784
9785!
9786!-- Check for the grid
9787    var = TRIM(variable)
9788!-- RTM directional variables
9789    IF ( var(1:12) == 'rtm_rad_net_'  .OR.  var(1:13) == 'rtm_rad_insw_'  .OR.          &
9790         var(1:13) == 'rtm_rad_inlw_'  .OR.  var(1:16) == 'rtm_rad_inswdir_'  .OR.      &
9791         var(1:16) == 'rtm_rad_inswdif_'  .OR.  var(1:16) == 'rtm_rad_inswref_'  .OR.   &
9792         var(1:16) == 'rtm_rad_inlwdif_'  .OR.  var(1:16) == 'rtm_rad_inlwref_'  .OR.   &
9793         var(1:14) == 'rtm_rad_outsw_'  .OR.  var(1:14) == 'rtm_rad_outlw_'  .OR.       &
9794         var(1:14) == 'rtm_rad_ressw_'  .OR.  var(1:14) == 'rtm_rad_reslw_'  .OR.       &
9795         var == 'rtm_rad_pc_inlw'  .OR.                                                 &
9796         var == 'rtm_rad_pc_insw'  .OR.  var == 'rtm_rad_pc_inswdir'  .OR.              &
9797         var == 'rtm_rad_pc_inswdif'  .OR.  var == 'rtm_rad_pc_inswref'  .OR.           &
9798         var(1:7) == 'rtm_svf'  .OR.  var(1:7) == 'rtm_dif'  .OR.                       &
9799         var(1:9) == 'rtm_skyvf' .OR. var(1:10) == 'rtm_skyvft'  .OR.                   &
9800         var == 'rtm_mrt'  .OR.  var ==  'rtm_mrt_sw'  .OR.  var == 'rtm_mrt_lw' )  THEN
9801
9802         found = .TRUE.
9803         grid_x = 'x'
9804         grid_y = 'y'
9805         grid_z = 'zu'
9806    ELSE
9807
9808       SELECT CASE ( TRIM( var ) )
9809
9810          CASE ( 'rad_lw_cs_hr', 'rad_lw_hr', 'rad_sw_cs_hr', 'rad_sw_hr',        &
9811                 'rad_lw_cs_hr_xy', 'rad_lw_hr_xy', 'rad_sw_cs_hr_xy',            &
9812                 'rad_sw_hr_xy', 'rad_lw_cs_hr_xz', 'rad_lw_hr_xz',               &
9813                 'rad_sw_cs_hr_xz', 'rad_sw_hr_xz', 'rad_lw_cs_hr_yz',            &
9814                 'rad_lw_hr_yz', 'rad_sw_cs_hr_yz', 'rad_sw_hr_yz',               &
9815                 'rad_mrt', 'rad_mrt_sw', 'rad_mrt_lw' )
9816             grid_x = 'x'
9817             grid_y = 'y'
9818             grid_z = 'zu'
9819
9820          CASE ( 'rad_lw_in', 'rad_lw_out', 'rad_sw_in', 'rad_sw_out',            &
9821                 'rad_lw_in_xy', 'rad_lw_out_xy', 'rad_sw_in_xy','rad_sw_out_xy', &
9822                 'rad_lw_in_xz', 'rad_lw_out_xz', 'rad_sw_in_xz','rad_sw_out_xz', &
9823                 'rad_lw_in_yz', 'rad_lw_out_yz', 'rad_sw_in_yz','rad_sw_out_yz' )
9824             grid_x = 'x'
9825             grid_y = 'y'
9826             grid_z = 'zw'
9827
9828
9829          CASE DEFAULT
9830             found  = .FALSE.
9831             grid_x = 'none'
9832             grid_y = 'none'
9833             grid_z = 'none'
9834
9835           END SELECT
9836       ENDIF
9837
9838    END SUBROUTINE radiation_define_netcdf_grid
9839
9840!------------------------------------------------------------------------------!
9841!
9842! Description:
9843! ------------
9844!> Subroutine defining 2D output variables
9845!------------------------------------------------------------------------------!
9846 SUBROUTINE radiation_data_output_2d( av, variable, found, grid, mode,         &
9847                                      local_pf, two_d, nzb_do, nzt_do )
9848 
9849    USE indices
9850
9851    USE kinds
9852
9853
9854    IMPLICIT NONE
9855
9856    CHARACTER (LEN=*) ::  grid     !<
9857    CHARACTER (LEN=*) ::  mode     !<
9858    CHARACTER (LEN=*) ::  variable !<
9859
9860    INTEGER(iwp) ::  av !<
9861    INTEGER(iwp) ::  i  !<
9862    INTEGER(iwp) ::  j  !<
9863    INTEGER(iwp) ::  k  !<
9864    INTEGER(iwp) ::  m  !< index of surface element at grid point (j,i)
9865    INTEGER(iwp) ::  nzb_do   !<
9866    INTEGER(iwp) ::  nzt_do   !<
9867
9868    LOGICAL      ::  found !<
9869    LOGICAL      ::  two_d !< flag parameter that indicates 2D variables (horizontal cross sections)
9870
9871    REAL(wp) ::  fill_value = -999.0_wp    !< value for the _FillValue attribute
9872
9873    REAL(wp), DIMENSION(nxl:nxr,nys:nyn,nzb_do:nzt_do) ::  local_pf !<
9874
9875    found = .TRUE.
9876
9877    SELECT CASE ( TRIM( variable ) )
9878
9879       CASE ( 'rad_net*_xy' )        ! 2d-array
9880          IF ( av == 0 ) THEN
9881             DO  i = nxl, nxr
9882                DO  j = nys, nyn
9883!
9884!--                Obtain rad_net from its respective surface type
9885!--                Natural-type surfaces
9886                   DO  m = surf_lsm_h%start_index(j,i),                        &
9887                           surf_lsm_h%end_index(j,i) 
9888                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_net(m)
9889                   ENDDO
9890!
9891!--                Urban-type surfaces
9892                   DO  m = surf_usm_h%start_index(j,i),                        &
9893                           surf_usm_h%end_index(j,i) 
9894                      local_pf(i,j,nzb+1) = surf_usm_h%rad_net(m)
9895                   ENDDO
9896                ENDDO
9897             ENDDO
9898          ELSE
9899             IF ( .NOT. ALLOCATED( rad_net_av ) ) THEN
9900                ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
9901                rad_net_av = REAL( fill_value, KIND = wp )
9902             ENDIF
9903             DO  i = nxl, nxr
9904                DO  j = nys, nyn 
9905                   local_pf(i,j,nzb+1) = rad_net_av(j,i)
9906                ENDDO
9907             ENDDO
9908          ENDIF
9909          two_d = .TRUE.
9910          grid = 'zu1'
9911         
9912       CASE ( 'rad_lw_in*_xy' )        ! 2d-array
9913          IF ( av == 0 ) THEN
9914             DO  i = nxl, nxr
9915                DO  j = nys, nyn
9916!
9917!--                Obtain rad_net from its respective surface type
9918!--                Natural-type surfaces
9919                   DO  m = surf_lsm_h%start_index(j,i),                        &
9920                           surf_lsm_h%end_index(j,i) 
9921                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_lw_in(m)
9922                   ENDDO
9923!
9924!--                Urban-type surfaces
9925                   DO  m = surf_usm_h%start_index(j,i),                        &
9926                           surf_usm_h%end_index(j,i) 
9927                      local_pf(i,j,nzb+1) = surf_usm_h%rad_lw_in(m)
9928                   ENDDO
9929                ENDDO
9930             ENDDO
9931          ELSE
9932             IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) ) THEN
9933                ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
9934                rad_lw_in_xy_av = REAL( fill_value, KIND = wp )
9935             ENDIF
9936             DO  i = nxl, nxr
9937                DO  j = nys, nyn 
9938                   local_pf(i,j,nzb+1) = rad_lw_in_xy_av(j,i)
9939                ENDDO
9940             ENDDO
9941          ENDIF
9942          two_d = .TRUE.
9943          grid = 'zu1'
9944         
9945       CASE ( 'rad_lw_out*_xy' )        ! 2d-array
9946          IF ( av == 0 ) THEN
9947             DO  i = nxl, nxr
9948                DO  j = nys, nyn
9949!
9950!--                Obtain rad_net from its respective surface type
9951!--                Natural-type surfaces
9952                   DO  m = surf_lsm_h%start_index(j,i),                        &
9953                           surf_lsm_h%end_index(j,i) 
9954                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_lw_out(m)
9955                   ENDDO
9956!
9957!--                Urban-type surfaces
9958                   DO  m = surf_usm_h%start_index(j,i),                        &
9959                           surf_usm_h%end_index(j,i) 
9960                      local_pf(i,j,nzb+1) = surf_usm_h%rad_lw_out(m)
9961                   ENDDO
9962                ENDDO
9963             ENDDO
9964          ELSE
9965             IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) ) THEN
9966                ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
9967                rad_lw_out_xy_av = REAL( fill_value, KIND = wp )
9968             ENDIF
9969             DO  i = nxl, nxr
9970                DO  j = nys, nyn 
9971                   local_pf(i,j,nzb+1) = rad_lw_out_xy_av(j,i)
9972                ENDDO
9973             ENDDO
9974          ENDIF
9975          two_d = .TRUE.
9976          grid = 'zu1'
9977         
9978       CASE ( 'rad_sw_in*_xy' )        ! 2d-array
9979          IF ( av == 0 ) THEN
9980             DO  i = nxl, nxr
9981                DO  j = nys, nyn
9982!
9983!--                Obtain rad_net from its respective surface type
9984!--                Natural-type surfaces
9985                   DO  m = surf_lsm_h%start_index(j,i),                        &
9986                           surf_lsm_h%end_index(j,i) 
9987                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_sw_in(m)
9988                   ENDDO
9989!
9990!--                Urban-type surfaces
9991                   DO  m = surf_usm_h%start_index(j,i),                        &
9992                           surf_usm_h%end_index(j,i) 
9993                      local_pf(i,j,nzb+1) = surf_usm_h%rad_sw_in(m)
9994                   ENDDO
9995                ENDDO
9996             ENDDO
9997          ELSE
9998             IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) ) THEN
9999                ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
10000                rad_sw_in_xy_av = REAL( fill_value, KIND = wp )
10001             ENDIF
10002             DO  i = nxl, nxr
10003                DO  j = nys, nyn 
10004                   local_pf(i,j,nzb+1) = rad_sw_in_xy_av(j,i)
10005                ENDDO
10006             ENDDO
10007          ENDIF
10008          two_d = .TRUE.
10009          grid = 'zu1'
10010         
10011       CASE ( 'rad_sw_out*_xy' )        ! 2d-array
10012          IF ( av == 0 ) THEN
10013             DO  i = nxl, nxr
10014                DO  j = nys, nyn
10015!
10016!--                Obtain rad_net from its respective surface type
10017!--                Natural-type surfaces
10018                   DO  m = surf_lsm_h%start_index(j,i),                        &
10019                           surf_lsm_h%end_index(j,i) 
10020                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_sw_out(m)
10021                   ENDDO
10022!
10023!--                Urban-type surfaces
10024                   DO  m = surf_usm_h%start_index(j,i),                        &
10025                           surf_usm_h%end_index(j,i) 
10026                      local_pf(i,j,nzb+1) = surf_usm_h%rad_sw_out(m)
10027                   ENDDO
10028                ENDDO
10029             ENDDO
10030          ELSE
10031             IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) ) THEN
10032                ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
10033                rad_sw_out_xy_av = REAL( fill_value, KIND = wp )
10034             ENDIF
10035             DO  i = nxl, nxr
10036                DO  j = nys, nyn 
10037                   local_pf(i,j,nzb+1) = rad_sw_out_xy_av(j,i)
10038                ENDDO
10039             ENDDO
10040          ENDIF
10041          two_d = .TRUE.
10042          grid = 'zu1'         
10043         
10044       CASE ( 'rad_lw_in_xy', 'rad_lw_in_xz', 'rad_lw_in_yz' )
10045          IF ( av == 0 ) THEN
10046             DO  i = nxl, nxr
10047                DO  j = nys, nyn
10048                   DO  k = nzb_do, nzt_do
10049                      local_pf(i,j,k) = rad_lw_in(k,j,i)
10050                   ENDDO
10051                ENDDO
10052             ENDDO
10053          ELSE
10054            IF ( .NOT. ALLOCATED( rad_lw_in_av ) ) THEN
10055               ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10056               rad_lw_in_av = REAL( fill_value, KIND = wp )
10057            ENDIF
10058             DO  i = nxl, nxr
10059                DO  j = nys, nyn 
10060                   DO  k = nzb_do, nzt_do
10061                      local_pf(i,j,k) = rad_lw_in_av(k,j,i)
10062                   ENDDO
10063                ENDDO
10064             ENDDO
10065          ENDIF
10066          IF ( mode == 'xy' )  grid = 'zu'
10067
10068       CASE ( 'rad_lw_out_xy', 'rad_lw_out_xz', 'rad_lw_out_yz' )
10069          IF ( av == 0 ) THEN
10070             DO  i = nxl, nxr
10071                DO  j = nys, nyn
10072                   DO  k = nzb_do, nzt_do
10073                      local_pf(i,j,k) = rad_lw_out(k,j,i)
10074                   ENDDO
10075                ENDDO
10076             ENDDO
10077          ELSE
10078            IF ( .NOT. ALLOCATED( rad_lw_out_av ) ) THEN
10079               ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10080               rad_lw_out_av = REAL( fill_value, KIND = wp )
10081            ENDIF
10082             DO  i = nxl, nxr
10083                DO  j = nys, nyn 
10084                   DO  k = nzb_do, nzt_do
10085                      local_pf(i,j,k) = rad_lw_out_av(k,j,i)
10086                   ENDDO
10087                ENDDO
10088             ENDDO
10089          ENDIF   
10090          IF ( mode == 'xy' )  grid = 'zu'
10091
10092       CASE ( 'rad_lw_cs_hr_xy', 'rad_lw_cs_hr_xz', 'rad_lw_cs_hr_yz' )
10093          IF ( av == 0 ) THEN
10094             DO  i = nxl, nxr
10095                DO  j = nys, nyn
10096                   DO  k = nzb_do, nzt_do
10097                      local_pf(i,j,k) = rad_lw_cs_hr(k,j,i)
10098                   ENDDO
10099                ENDDO
10100             ENDDO
10101          ELSE
10102            IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) ) THEN
10103               ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10104               rad_lw_cs_hr_av = REAL( fill_value, KIND = wp )
10105            ENDIF
10106             DO  i = nxl, nxr
10107                DO  j = nys, nyn 
10108                   DO  k = nzb_do, nzt_do
10109                      local_pf(i,j,k) = rad_lw_cs_hr_av(k,j,i)
10110                   ENDDO
10111                ENDDO
10112             ENDDO
10113          ENDIF
10114          IF ( mode == 'xy' )  grid = 'zw'
10115
10116       CASE ( 'rad_lw_hr_xy', 'rad_lw_hr_xz', 'rad_lw_hr_yz' )
10117          IF ( av == 0 ) THEN
10118             DO  i = nxl, nxr
10119                DO  j = nys, nyn
10120                   DO  k = nzb_do, nzt_do
10121                      local_pf(i,j,k) = rad_lw_hr(k,j,i)
10122                   ENDDO
10123                ENDDO
10124             ENDDO
10125          ELSE
10126            IF ( .NOT. ALLOCATED( rad_lw_hr_av ) ) THEN
10127               ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10128               rad_lw_hr_av= REAL( fill_value, KIND = wp )
10129            ENDIF
10130             DO  i = nxl, nxr
10131                DO  j = nys, nyn 
10132                   DO  k = nzb_do, nzt_do
10133                      local_pf(i,j,k) = rad_lw_hr_av(k,j,i)
10134                   ENDDO
10135                ENDDO
10136             ENDDO
10137          ENDIF
10138          IF ( mode == 'xy' )  grid = 'zw'
10139
10140       CASE ( 'rad_sw_in_xy', 'rad_sw_in_xz', 'rad_sw_in_yz' )
10141          IF ( av == 0 ) THEN
10142             DO  i = nxl, nxr
10143                DO  j = nys, nyn
10144                   DO  k = nzb_do, nzt_do
10145                      local_pf(i,j,k) = rad_sw_in(k,j,i)
10146                   ENDDO
10147                ENDDO
10148             ENDDO
10149          ELSE
10150            IF ( .NOT. ALLOCATED( rad_sw_in_av ) ) THEN
10151               ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10152               rad_sw_in_av = REAL( fill_value, KIND = wp )
10153            ENDIF
10154             DO  i = nxl, nxr
10155                DO  j = nys, nyn 
10156                   DO  k = nzb_do, nzt_do
10157                      local_pf(i,j,k) = rad_sw_in_av(k,j,i)
10158                   ENDDO
10159                ENDDO
10160             ENDDO
10161          ENDIF
10162          IF ( mode == 'xy' )  grid = 'zu'
10163
10164       CASE ( 'rad_sw_out_xy', 'rad_sw_out_xz', 'rad_sw_out_yz' )
10165          IF ( av == 0 ) THEN
10166             DO  i = nxl, nxr
10167                DO  j = nys, nyn
10168                   DO  k = nzb_do, nzt_do
10169                      local_pf(i,j,k) = rad_sw_out(k,j,i)
10170                   ENDDO
10171                ENDDO
10172             ENDDO
10173          ELSE
10174            IF ( .NOT. ALLOCATED( rad_sw_out_av ) ) THEN
10175               ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10176               rad_sw_out_av = REAL( fill_value, KIND = wp )
10177            ENDIF
10178             DO  i = nxl, nxr
10179                DO  j = nys, nyn 
10180                   DO  k = nzb, nzt+1
10181                      local_pf(i,j,k) = rad_sw_out_av(k,j,i)
10182                   ENDDO
10183                ENDDO
10184             ENDDO
10185          ENDIF
10186          IF ( mode == 'xy' )  grid = 'zu'
10187
10188       CASE ( 'rad_sw_cs_hr_xy', 'rad_sw_cs_hr_xz', 'rad_sw_cs_hr_yz' )
10189          IF ( av == 0 ) THEN
10190             DO  i = nxl, nxr
10191                DO  j = nys, nyn
10192                   DO  k = nzb_do, nzt_do
10193                      local_pf(i,j,k) = rad_sw_cs_hr(k,j,i)
10194                   ENDDO
10195                ENDDO
10196             ENDDO
10197          ELSE
10198            IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) ) THEN
10199               ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10200               rad_sw_cs_hr_av = REAL( fill_value, KIND = wp )
10201            ENDIF
10202             DO  i = nxl, nxr
10203                DO  j = nys, nyn 
10204                   DO  k = nzb_do, nzt_do
10205                      local_pf(i,j,k) = rad_sw_cs_hr_av(k,j,i)
10206                   ENDDO
10207                ENDDO
10208             ENDDO
10209          ENDIF
10210          IF ( mode == 'xy' )  grid = 'zw'
10211
10212       CASE ( 'rad_sw_hr_xy', 'rad_sw_hr_xz', 'rad_sw_hr_yz' )
10213          IF ( av == 0 ) THEN
10214             DO  i = nxl, nxr
10215                DO  j = nys, nyn
10216                   DO  k = nzb_do, nzt_do
10217                      local_pf(i,j,k) = rad_sw_hr(k,j,i)
10218                   ENDDO
10219                ENDDO
10220             ENDDO
10221          ELSE
10222            IF ( .NOT. ALLOCATED( rad_sw_hr_av ) ) THEN
10223               ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10224               rad_sw_hr_av = REAL( fill_value, KIND = wp )
10225            ENDIF
10226             DO  i = nxl, nxr
10227                DO  j = nys, nyn 
10228                   DO  k = nzb_do, nzt_do
10229                      local_pf(i,j,k) = rad_sw_hr_av(k,j,i)
10230                   ENDDO
10231                ENDDO
10232             ENDDO
10233          ENDIF
10234          IF ( mode == 'xy' )  grid = 'zw'
10235
10236       CASE DEFAULT
10237          found = .FALSE.
10238          grid  = 'none'
10239
10240    END SELECT
10241 
10242 END SUBROUTINE radiation_data_output_2d
10243
10244
10245!------------------------------------------------------------------------------!
10246!
10247! Description:
10248! ------------
10249!> Subroutine defining 3D output variables
10250!------------------------------------------------------------------------------!
10251 SUBROUTINE radiation_data_output_3d( av, variable, found, local_pf, nzb_do, nzt_do )
10252 
10253
10254    USE indices
10255
10256    USE kinds
10257
10258
10259    IMPLICIT NONE
10260
10261    CHARACTER (LEN=*) ::  variable !<
10262
10263    INTEGER(iwp) ::  av          !<
10264    INTEGER(iwp) ::  i, j, k, l  !<
10265    INTEGER(iwp) ::  nzb_do      !<
10266    INTEGER(iwp) ::  nzt_do      !<
10267
10268    LOGICAL      ::  found       !<
10269
10270    REAL(wp)     ::  fill_value = -999.0_wp    !< value for the _FillValue attribute
10271
10272    REAL(sp), DIMENSION(nxl:nxr,nys:nyn,nzb_do:nzt_do) ::  local_pf !<
10273
10274    CHARACTER (len=varnamelength)                   :: var, surfid
10275    INTEGER(iwp)                                    :: ids,idsint_u,idsint_l,isurf,isvf,isurfs,isurflt,ipcgb
10276    INTEGER(iwp)                                    :: is, js, ks, istat
10277
10278    found = .TRUE.
10279
10280    ids = -1
10281    var = TRIM(variable)
10282    DO i = 0, nd-1
10283        k = len(TRIM(var))
10284        j = len(TRIM(dirname(i)))
10285        IF ( TRIM(var(k-j+1:k)) == TRIM(dirname(i)) )  THEN
10286            ids = i
10287            idsint_u = dirint_u(ids)
10288            idsint_l = dirint_l(ids)
10289            var = var(:k-j)
10290            EXIT
10291        ENDIF
10292    ENDDO
10293    IF ( ids == -1 )  THEN
10294        var = TRIM(variable)
10295    ENDIF
10296
10297    IF ( (var(1:8) == 'rtm_svf_'  .OR.  var(1:8) == 'rtm_dif_')  .AND.  len(TRIM(var)) >= 13 )  THEN
10298!--     svf values to particular surface
10299        surfid = var(9:)
10300        i = index(surfid,'_')
10301        j = index(surfid(i+1:),'_')
10302        READ(surfid(1:i-1),*, iostat=istat ) is
10303        IF ( istat == 0 )  THEN
10304            READ(surfid(i+1:i+j-1),*, iostat=istat ) js
10305        ENDIF
10306        IF ( istat == 0 )  THEN
10307            READ(surfid(i+j+1:),*, iostat=istat ) ks
10308        ENDIF
10309        IF ( istat == 0 )  THEN
10310            var = var(1:7)
10311        ENDIF
10312    ENDIF
10313
10314    local_pf = fill_value
10315
10316    SELECT CASE ( TRIM( var ) )
10317!--   block of large scale radiation model (e.g. RRTMG) output variables
10318      CASE ( 'rad_sw_in' )
10319         IF ( av == 0 )  THEN
10320            DO  i = nxl, nxr
10321               DO  j = nys, nyn
10322                  DO  k = nzb_do, nzt_do
10323                     local_pf(i,j,k) = rad_sw_in(k,j,i)
10324                  ENDDO
10325               ENDDO
10326            ENDDO
10327         ELSE
10328            IF ( .NOT. ALLOCATED( rad_sw_in_av ) ) THEN
10329               ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10330               rad_sw_in_av = REAL( fill_value, KIND = wp )
10331            ENDIF
10332            DO  i = nxl, nxr
10333               DO  j = nys, nyn
10334                  DO  k = nzb_do, nzt_do
10335                     local_pf(i,j,k) = rad_sw_in_av(k,j,i)
10336                  ENDDO
10337               ENDDO
10338            ENDDO
10339         ENDIF
10340
10341      CASE ( 'rad_sw_out' )
10342         IF ( av == 0 )  THEN
10343            DO  i = nxl, nxr
10344               DO  j = nys, nyn
10345                  DO  k = nzb_do, nzt_do
10346                     local_pf(i,j,k) = rad_sw_out(k,j,i)
10347                  ENDDO
10348               ENDDO
10349            ENDDO
10350         ELSE
10351            IF ( .NOT. ALLOCATED( rad_sw_out_av ) ) THEN
10352               ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10353               rad_sw_out_av = REAL( fill_value, KIND = wp )
10354            ENDIF
10355            DO  i = nxl, nxr
10356               DO  j = nys, nyn
10357                  DO  k = nzb_do, nzt_do
10358                     local_pf(i,j,k) = rad_sw_out_av(k,j,i)
10359                  ENDDO
10360               ENDDO
10361            ENDDO
10362         ENDIF
10363
10364      CASE ( 'rad_sw_cs_hr' )
10365         IF ( av == 0 )  THEN
10366            DO  i = nxl, nxr
10367               DO  j = nys, nyn
10368                  DO  k = nzb_do, nzt_do
10369                     local_pf(i,j,k) = rad_sw_cs_hr(k,j,i)
10370                  ENDDO
10371               ENDDO
10372            ENDDO
10373         ELSE
10374            IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) ) THEN
10375               ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10376               rad_sw_cs_hr_av = REAL( fill_value, KIND = wp )
10377            ENDIF
10378            DO  i = nxl, nxr
10379               DO  j = nys, nyn
10380                  DO  k = nzb_do, nzt_do
10381                     local_pf(i,j,k) = rad_sw_cs_hr_av(k,j,i)
10382                  ENDDO
10383               ENDDO
10384            ENDDO
10385         ENDIF
10386
10387      CASE ( 'rad_sw_hr' )
10388         IF ( av == 0 )  THEN
10389            DO  i = nxl, nxr
10390               DO  j = nys, nyn
10391                  DO  k = nzb_do, nzt_do
10392                     local_pf(i,j,k) = rad_sw_hr(k,j,i)
10393                  ENDDO
10394               ENDDO
10395            ENDDO
10396         ELSE
10397            IF ( .NOT. ALLOCATED( rad_sw_hr_av ) ) THEN
10398               ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10399               rad_sw_hr_av = REAL( fill_value, KIND = wp )
10400            ENDIF
10401            DO  i = nxl, nxr
10402               DO  j = nys, nyn
10403                  DO  k = nzb_do, nzt_do
10404                     local_pf(i,j,k) = rad_sw_hr_av(k,j,i)
10405                  ENDDO
10406               ENDDO
10407            ENDDO
10408         ENDIF
10409
10410      CASE ( 'rad_lw_in' )
10411         IF ( av == 0 )  THEN
10412            DO  i = nxl, nxr
10413               DO  j = nys, nyn
10414                  DO  k = nzb_do, nzt_do
10415                     local_pf(i,j,k) = rad_lw_in(k,j,i)
10416                  ENDDO
10417               ENDDO
10418            ENDDO
10419         ELSE
10420            IF ( .NOT. ALLOCATED( rad_lw_in_av ) ) THEN
10421               ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10422               rad_lw_in_av = REAL( fill_value, KIND = wp )
10423            ENDIF
10424            DO  i = nxl, nxr
10425               DO  j = nys, nyn
10426                  DO  k = nzb_do, nzt_do
10427                     local_pf(i,j,k) = rad_lw_in_av(k,j,i)
10428                  ENDDO
10429               ENDDO
10430            ENDDO
10431         ENDIF
10432
10433      CASE ( 'rad_lw_out' )
10434         IF ( av == 0 )  THEN
10435            DO  i = nxl, nxr
10436               DO  j = nys, nyn
10437                  DO  k = nzb_do, nzt_do
10438                     local_pf(i,j,k) = rad_lw_out(k,j,i)
10439                  ENDDO
10440               ENDDO
10441            ENDDO
10442         ELSE
10443            IF ( .NOT. ALLOCATED( rad_lw_out_av ) ) THEN
10444               ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10445               rad_lw_out_av = REAL( fill_value, KIND = wp )
10446            ENDIF
10447            DO  i = nxl, nxr
10448               DO  j = nys, nyn
10449                  DO  k = nzb_do, nzt_do
10450                     local_pf(i,j,k) = rad_lw_out_av(k,j,i)
10451                  ENDDO
10452               ENDDO
10453            ENDDO
10454         ENDIF
10455
10456      CASE ( 'rad_lw_cs_hr' )
10457         IF ( av == 0 )  THEN
10458            DO  i = nxl, nxr
10459               DO  j = nys, nyn
10460                  DO  k = nzb_do, nzt_do
10461                     local_pf(i,j,k) = rad_lw_cs_hr(k,j,i)
10462                  ENDDO
10463               ENDDO
10464            ENDDO
10465         ELSE
10466            IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) ) THEN
10467               ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10468               rad_lw_cs_hr_av = REAL( fill_value, KIND = wp )
10469            ENDIF
10470            DO  i = nxl, nxr
10471               DO  j = nys, nyn
10472                  DO  k = nzb_do, nzt_do
10473                     local_pf(i,j,k) = rad_lw_cs_hr_av(k,j,i)
10474                  ENDDO
10475               ENDDO
10476            ENDDO
10477         ENDIF
10478
10479      CASE ( 'rad_lw_hr' )
10480         IF ( av == 0 )  THEN
10481            DO  i = nxl, nxr
10482               DO  j = nys, nyn
10483                  DO  k = nzb_do, nzt_do
10484                     local_pf(i,j,k) = rad_lw_hr(k,j,i)
10485                  ENDDO
10486               ENDDO
10487            ENDDO
10488         ELSE
10489            IF ( .NOT. ALLOCATED( rad_lw_hr_av ) ) THEN
10490               ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10491              rad_lw_hr_av = REAL( fill_value, KIND = wp )
10492            ENDIF
10493            DO  i = nxl, nxr
10494               DO  j = nys, nyn
10495                  DO  k = nzb_do, nzt_do
10496                     local_pf(i,j,k) = rad_lw_hr_av(k,j,i)
10497                  ENDDO
10498               ENDDO
10499            ENDDO
10500         ENDIF
10501
10502!--   block of RTM output variables
10503!--   variables are intended mainly for debugging and detailed analyse purposes
10504      CASE ( 'rtm_skyvf' )
10505!--        sky view factor
10506         DO isurf = dirstart(ids), dirend(ids)
10507            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10508               local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = skyvf(isurf)
10509            ENDIF
10510         ENDDO
10511
10512      CASE ( 'rtm_skyvft' )
10513!--      sky view factor
10514         DO isurf = dirstart(ids), dirend(ids)
10515            IF ( surfl(id,isurf) == ids )  THEN
10516               local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = skyvft(isurf)
10517            ENDIF
10518         ENDDO
10519
10520      CASE ( 'rtm_svf', 'rtm_dif' )
10521!--      shape view factors or iradiance factors to selected surface
10522         IF ( TRIM(var)=='rtm_svf' )  THEN
10523             k = 1
10524         ELSE
10525             k = 2
10526         ENDIF
10527         DO isvf = 1, nsvfl
10528            isurflt = svfsurf(1, isvf)
10529            isurfs = svfsurf(2, isvf)
10530
10531            IF ( surf(ix,isurfs) == is  .AND.  surf(iy,isurfs) == js  .AND. surf(iz,isurfs) == ks  .AND. &
10532                 (surf(id,isurfs) == idsint_u .OR. surfl(id,isurfs) == idsint_l ) ) THEN
10533!--            correct source surface
10534               local_pf(surfl(ix,isurflt),surfl(iy,isurflt),surfl(iz,isurflt)) = svf(k,isvf)
10535            ENDIF
10536         ENDDO
10537
10538      CASE ( 'rtm_rad_net' )
10539!--     array of complete radiation balance
10540         DO isurf = dirstart(ids), dirend(ids)
10541            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10542               IF ( av == 0 )  THEN
10543                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = &
10544                         surfinsw(isurf) - surfoutsw(isurf) +  surfinlw(isurf) - surfoutlw(isurf)
10545               ELSE
10546                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfradnet_av(isurf)
10547               ENDIF
10548            ENDIF
10549         ENDDO
10550
10551      CASE ( 'rtm_rad_insw' )
10552!--      array of sw radiation falling to surface after i-th reflection
10553         DO isurf = dirstart(ids), dirend(ids)
10554            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10555               IF ( av == 0 )  THEN
10556                 local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinsw(isurf)
10557               ELSE
10558                 local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinsw_av(isurf)
10559               ENDIF
10560            ENDIF
10561         ENDDO
10562
10563      CASE ( 'rtm_rad_inlw' )
10564!--      array of lw radiation falling to surface after i-th reflection
10565         DO isurf = dirstart(ids), dirend(ids)
10566            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10567               IF ( av == 0 )  THEN
10568                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlw(isurf)
10569               ELSE
10570                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlw_av(isurf)
10571               ENDIF
10572             ENDIF
10573         ENDDO
10574
10575      CASE ( 'rtm_rad_inswdir' )
10576!--      array of direct sw radiation falling to surface from sun
10577         DO isurf = dirstart(ids), dirend(ids)
10578            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10579               IF ( av == 0 )  THEN
10580                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdir(isurf)
10581               ELSE
10582                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdir_av(isurf)
10583               ENDIF
10584            ENDIF
10585         ENDDO
10586
10587      CASE ( 'rtm_rad_inswdif' )
10588!--      array of difusion sw radiation falling to surface from sky and borders of the domain
10589         DO isurf = dirstart(ids), dirend(ids)
10590            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10591               IF ( av == 0 )  THEN
10592                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdif(isurf)
10593               ELSE
10594                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdif_av(isurf)
10595               ENDIF
10596            ENDIF
10597         ENDDO
10598
10599      CASE ( 'rtm_rad_inswref' )
10600!--      array of sw radiation falling to surface from reflections
10601         DO isurf = dirstart(ids), dirend(ids)
10602            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10603               IF ( av == 0 )  THEN
10604                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = &
10605                    surfinsw(isurf) - surfinswdir(isurf) - surfinswdif(isurf)
10606               ELSE
10607                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswref_av(isurf)
10608               ENDIF
10609            ENDIF
10610         ENDDO
10611
10612      CASE ( 'rtm_rad_inlwdif' )
10613!--      array of difusion lw radiation falling to surface from sky and borders of the domain
10614         DO isurf = dirstart(ids), dirend(ids)
10615            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10616               IF ( av == 0 )  THEN
10617                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlwdif(isurf)
10618               ELSE
10619                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlwdif_av(isurf)
10620               ENDIF
10621            ENDIF
10622         ENDDO
10623
10624      CASE ( 'rtm_rad_inlwref' )
10625!--      array of lw radiation falling to surface from reflections
10626         DO isurf = dirstart(ids), dirend(ids)
10627            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10628               IF ( av == 0 )  THEN
10629                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlw(isurf) - surfinlwdif(isurf)
10630               ELSE
10631                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlwref_av(isurf)
10632               ENDIF
10633            ENDIF
10634         ENDDO
10635
10636      CASE ( 'rtm_rad_outsw' )
10637!--      array of sw radiation emitted from surface after i-th reflection
10638         DO isurf = dirstart(ids), dirend(ids)
10639            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10640               IF ( av == 0 )  THEN
10641                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutsw(isurf)
10642               ELSE
10643                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutsw_av(isurf)
10644               ENDIF
10645            ENDIF
10646         ENDDO
10647
10648      CASE ( 'rtm_rad_outlw' )
10649!--      array of lw radiation emitted from surface after i-th reflection
10650         DO isurf = dirstart(ids), dirend(ids)
10651            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10652               IF ( av == 0 )  THEN
10653                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutlw(isurf)
10654               ELSE
10655                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutlw_av(isurf)
10656               ENDIF
10657            ENDIF
10658         ENDDO
10659
10660      CASE ( 'rtm_rad_ressw' )
10661!--      average of array of residua of sw radiation absorbed in surface after last reflection
10662         DO isurf = dirstart(ids), dirend(ids)
10663            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10664               IF ( av == 0 )  THEN
10665                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfins(isurf)
10666               ELSE
10667                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfins_av(isurf)
10668               ENDIF
10669            ENDIF
10670         ENDDO
10671
10672      CASE ( 'rtm_rad_reslw' )
10673!--      average of array of residua of lw radiation absorbed in surface after last reflection
10674         DO isurf = dirstart(ids), dirend(ids)
10675            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10676               IF ( av == 0 )  THEN
10677                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinl(isurf)
10678               ELSE
10679                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinl_av(isurf)
10680               ENDIF
10681            ENDIF
10682         ENDDO
10683
10684      CASE ( 'rtm_rad_pc_inlw' )
10685!--      array of lw radiation absorbed by plant canopy
10686         DO ipcgb = 1, npcbl
10687            IF ( av == 0 )  THEN
10688               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinlw(ipcgb)
10689            ELSE
10690               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinlw_av(ipcgb)
10691            ENDIF
10692         ENDDO
10693
10694      CASE ( 'rtm_rad_pc_insw' )
10695!--      array of sw radiation absorbed by plant canopy
10696         DO ipcgb = 1, npcbl
10697            IF ( av == 0 )  THEN
10698              local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinsw(ipcgb)
10699            ELSE
10700              local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinsw_av(ipcgb)
10701            ENDIF
10702         ENDDO
10703
10704      CASE ( 'rtm_rad_pc_inswdir' )
10705!--      array of direct sw radiation absorbed by plant canopy
10706         DO ipcgb = 1, npcbl
10707            IF ( av == 0 )  THEN
10708               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdir(ipcgb)
10709            ELSE
10710               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdir_av(ipcgb)
10711            ENDIF
10712         ENDDO
10713
10714      CASE ( 'rtm_rad_pc_inswdif' )
10715!--      array of diffuse sw radiation absorbed by plant canopy
10716         DO ipcgb = 1, npcbl
10717            IF ( av == 0 )  THEN
10718               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdif(ipcgb)
10719            ELSE
10720               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdif_av(ipcgb)
10721            ENDIF
10722         ENDDO
10723
10724      CASE ( 'rtm_rad_pc_inswref' )
10725!--      array of reflected sw radiation absorbed by plant canopy
10726         DO ipcgb = 1, npcbl
10727            IF ( av == 0 )  THEN
10728               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = &
10729                                    pcbinsw(ipcgb) - pcbinswdir(ipcgb) - pcbinswdif(ipcgb)
10730            ELSE
10731               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswref_av(ipcgb)
10732            ENDIF
10733         ENDDO
10734
10735      CASE ( 'rtm_mrt_sw' )
10736         local_pf = REAL( fill_value, KIND = wp )
10737         IF ( av == 0 )  THEN
10738            DO  l = 1, nmrtbl
10739               local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinsw(l)
10740            ENDDO
10741         ELSE
10742            IF ( ALLOCATED( mrtinsw_av ) ) THEN
10743               DO  l = 1, nmrtbl
10744                  local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinsw_av(l)
10745               ENDDO
10746            ENDIF
10747         ENDIF
10748
10749      CASE ( 'rtm_mrt_lw' )
10750         local_pf = REAL( fill_value, KIND = wp )
10751         IF ( av == 0 )  THEN
10752            DO  l = 1, nmrtbl
10753               local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinlw(l)
10754            ENDDO
10755         ELSE
10756            IF ( ALLOCATED( mrtinlw_av ) ) THEN
10757               DO  l = 1, nmrtbl
10758                  local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinlw_av(l)
10759               ENDDO
10760            ENDIF
10761         ENDIF
10762
10763      CASE ( 'rtm_mrt' )
10764         local_pf = REAL( fill_value, KIND = wp )
10765         IF ( av == 0 )  THEN
10766            DO  l = 1, nmrtbl
10767               local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrt(l)
10768            ENDDO
10769         ELSE
10770            IF ( ALLOCATED( mrt_av ) ) THEN
10771               DO  l = 1, nmrtbl
10772                  local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrt_av(l)
10773               ENDDO
10774            ENDIF
10775         ENDIF
10776
10777       CASE DEFAULT
10778          found = .FALSE.
10779
10780    END SELECT
10781
10782
10783 END SUBROUTINE radiation_data_output_3d
10784
10785!------------------------------------------------------------------------------!
10786!
10787! Description:
10788! ------------
10789!> Subroutine defining masked data output
10790!------------------------------------------------------------------------------!
10791 SUBROUTINE radiation_data_output_mask( av, variable, found, local_pf )
10792 
10793    USE control_parameters
10794       
10795    USE indices
10796   
10797    USE kinds
10798   
10799
10800    IMPLICIT NONE
10801
10802    CHARACTER (LEN=*) ::  variable   !<
10803
10804    CHARACTER(LEN=5) ::  grid        !< flag to distinquish between staggered grids
10805
10806    INTEGER(iwp) ::  av              !<
10807    INTEGER(iwp) ::  i               !<
10808    INTEGER(iwp) ::  j               !<
10809    INTEGER(iwp) ::  k               !<
10810    INTEGER(iwp) ::  topo_top_ind    !< k index of highest horizontal surface
10811
10812    LOGICAL ::  found                !< true if output array was found
10813    LOGICAL ::  resorted             !< true if array is resorted
10814
10815
10816    REAL(wp),                                                                  &
10817       DIMENSION(mask_size_l(mid,1),mask_size_l(mid,2),mask_size_l(mid,3)) ::  &
10818          local_pf   !<
10819
10820    REAL(wp), DIMENSION(:,:,:), POINTER ::  to_be_resorted  !< points to array which needs to be resorted for output
10821
10822
10823    found    = .TRUE.
10824    grid     = 's'
10825    resorted = .FALSE.
10826
10827    SELECT CASE ( TRIM( variable ) )
10828
10829
10830       CASE ( 'rad_lw_in' )
10831          IF ( av == 0 )  THEN
10832             to_be_resorted => rad_lw_in
10833          ELSE
10834             to_be_resorted => rad_lw_in_av
10835          ENDIF
10836
10837       CASE ( 'rad_lw_out' )
10838          IF ( av == 0 )  THEN
10839             to_be_resorted => rad_lw_out
10840          ELSE
10841             to_be_resorted => rad_lw_out_av
10842          ENDIF
10843
10844       CASE ( 'rad_lw_cs_hr' )
10845          IF ( av == 0 )  THEN
10846             to_be_resorted => rad_lw_cs_hr
10847          ELSE
10848             to_be_resorted => rad_lw_cs_hr_av
10849          ENDIF
10850
10851       CASE ( 'rad_lw_hr' )
10852          IF ( av == 0 )  THEN
10853             to_be_resorted => rad_lw_hr
10854          ELSE
10855             to_be_resorted => rad_lw_hr_av
10856          ENDIF
10857
10858       CASE ( 'rad_sw_in' )
10859          IF ( av == 0 )  THEN
10860             to_be_resorted => rad_sw_in
10861          ELSE
10862             to_be_resorted => rad_sw_in_av
10863          ENDIF
10864
10865       CASE ( 'rad_sw_out' )
10866          IF ( av == 0 )  THEN
10867             to_be_resorted => rad_sw_out
10868          ELSE
10869             to_be_resorted => rad_sw_out_av
10870          ENDIF
10871
10872       CASE ( 'rad_sw_cs_hr' )
10873          IF ( av == 0 )  THEN
10874             to_be_resorted => rad_sw_cs_hr
10875          ELSE
10876             to_be_resorted => rad_sw_cs_hr_av
10877          ENDIF
10878
10879       CASE ( 'rad_sw_hr' )
10880          IF ( av == 0 )  THEN
10881             to_be_resorted => rad_sw_hr
10882          ELSE
10883             to_be_resorted => rad_sw_hr_av
10884          ENDIF
10885
10886       CASE DEFAULT
10887          found = .FALSE.
10888
10889    END SELECT
10890
10891!
10892!-- Resort the array to be output, if not done above
10893    IF ( .NOT. resorted )  THEN
10894       IF ( .NOT. mask_surface(mid) )  THEN
10895!
10896!--       Default masked output
10897          DO  i = 1, mask_size_l(mid,1)
10898             DO  j = 1, mask_size_l(mid,2)
10899                DO  k = 1, mask_size_l(mid,3)
10900                   local_pf(i,j,k) =  to_be_resorted(mask_k(mid,k), &
10901                                      mask_j(mid,j),mask_i(mid,i))
10902                ENDDO
10903             ENDDO
10904          ENDDO
10905
10906       ELSE
10907!
10908!--       Terrain-following masked output
10909          DO  i = 1, mask_size_l(mid,1)
10910             DO  j = 1, mask_size_l(mid,2)
10911!
10912!--             Get k index of highest horizontal surface
10913                topo_top_ind = get_topography_top_index_ji( mask_j(mid,j), &
10914                                                            mask_i(mid,i), &
10915                                                            grid )
10916!
10917!--             Save output array
10918                DO  k = 1, mask_size_l(mid,3)
10919                   local_pf(i,j,k) = to_be_resorted(                       &
10920                                          MIN( topo_top_ind+mask_k(mid,k), &
10921                                               nzt+1 ),                    &
10922                                          mask_j(mid,j),                   &
10923                                          mask_i(mid,i)                     )
10924                ENDDO
10925             ENDDO
10926          ENDDO
10927
10928       ENDIF
10929    ENDIF
10930
10931
10932
10933 END SUBROUTINE radiation_data_output_mask
10934
10935
10936!------------------------------------------------------------------------------!
10937! Description:
10938! ------------
10939!> Subroutine writes local (subdomain) restart data
10940!------------------------------------------------------------------------------!
10941 SUBROUTINE radiation_wrd_local
10942
10943
10944    IMPLICIT NONE
10945
10946
10947    IF ( ALLOCATED( rad_net_av ) )  THEN
10948       CALL wrd_write_string( 'rad_net_av' )
10949       WRITE ( 14 )  rad_net_av
10950    ENDIF
10951   
10952    IF ( ALLOCATED( rad_lw_in_xy_av ) )  THEN
10953       CALL wrd_write_string( 'rad_lw_in_xy_av' )
10954       WRITE ( 14 )  rad_lw_in_xy_av
10955    ENDIF
10956   
10957    IF ( ALLOCATED( rad_lw_out_xy_av ) )  THEN
10958       CALL wrd_write_string( 'rad_lw_out_xy_av' )
10959       WRITE ( 14 )  rad_lw_out_xy_av
10960    ENDIF
10961   
10962    IF ( ALLOCATED( rad_sw_in_xy_av ) )  THEN
10963       CALL wrd_write_string( 'rad_sw_in_xy_av' )
10964       WRITE ( 14 )  rad_sw_in_xy_av
10965    ENDIF
10966   
10967    IF ( ALLOCATED( rad_sw_out_xy_av ) )  THEN
10968       CALL wrd_write_string( 'rad_sw_out_xy_av' )
10969       WRITE ( 14 )  rad_sw_out_xy_av
10970    ENDIF
10971
10972    IF ( ALLOCATED( rad_lw_in ) )  THEN
10973       CALL wrd_write_string( 'rad_lw_in' )
10974       WRITE ( 14 )  rad_lw_in
10975    ENDIF
10976
10977    IF ( ALLOCATED( rad_lw_in_av ) )  THEN
10978       CALL wrd_write_string( 'rad_lw_in_av' )
10979       WRITE ( 14 )  rad_lw_in_av
10980    ENDIF
10981
10982    IF ( ALLOCATED( rad_lw_out ) )  THEN
10983       CALL wrd_write_string( 'rad_lw_out' )
10984       WRITE ( 14 )  rad_lw_out
10985    ENDIF
10986
10987    IF ( ALLOCATED( rad_lw_out_av) )  THEN
10988       CALL wrd_write_string( 'rad_lw_out_av' )
10989       WRITE ( 14 )  rad_lw_out_av
10990    ENDIF
10991
10992    IF ( ALLOCATED( rad_lw_cs_hr) )  THEN
10993       CALL wrd_write_string( 'rad_lw_cs_hr' )
10994       WRITE ( 14 )  rad_lw_cs_hr
10995    ENDIF
10996
10997    IF ( ALLOCATED( rad_lw_cs_hr_av) )  THEN
10998       CALL wrd_write_string( 'rad_lw_cs_hr_av' )
10999       WRITE ( 14 )  rad_lw_cs_hr_av
11000    ENDIF
11001
11002    IF ( ALLOCATED( rad_lw_hr) )  THEN
11003       CALL wrd_write_string( 'rad_lw_hr' )
11004       WRITE ( 14 )  rad_lw_hr
11005    ENDIF
11006
11007    IF ( ALLOCATED( rad_lw_hr_av) )  THEN
11008       CALL wrd_write_string( 'rad_lw_hr_av' )
11009       WRITE ( 14 )  rad_lw_hr_av
11010    ENDIF
11011
11012    IF ( ALLOCATED( rad_sw_in) )  THEN
11013       CALL wrd_write_string( 'rad_sw_in' )
11014       WRITE ( 14 )  rad_sw_in
11015    ENDIF
11016
11017    IF ( ALLOCATED( rad_sw_in_av) )  THEN
11018       CALL wrd_write_string( 'rad_sw_in_av' )
11019       WRITE ( 14 )  rad_sw_in_av
11020    ENDIF
11021
11022    IF ( ALLOCATED( rad_sw_out) )  THEN
11023       CALL wrd_write_string( 'rad_sw_out' )
11024       WRITE ( 14 )  rad_sw_out
11025    ENDIF
11026
11027    IF ( ALLOCATED( rad_sw_out_av) )  THEN
11028       CALL wrd_write_string( 'rad_sw_out_av' )
11029       WRITE ( 14 )  rad_sw_out_av
11030    ENDIF
11031
11032    IF ( ALLOCATED( rad_sw_cs_hr) )  THEN
11033       CALL wrd_write_string( 'rad_sw_cs_hr' )
11034       WRITE ( 14 )  rad_sw_cs_hr
11035    ENDIF
11036
11037    IF ( ALLOCATED( rad_sw_cs_hr_av) )  THEN
11038       CALL wrd_write_string( 'rad_sw_cs_hr_av' )
11039       WRITE ( 14 )  rad_sw_cs_hr_av
11040    ENDIF
11041
11042    IF ( ALLOCATED( rad_sw_hr) )  THEN
11043       CALL wrd_write_string( 'rad_sw_hr' )
11044       WRITE ( 14 )  rad_sw_hr
11045    ENDIF
11046
11047    IF ( ALLOCATED( rad_sw_hr_av) )  THEN
11048       CALL wrd_write_string( 'rad_sw_hr_av' )
11049       WRITE ( 14 )  rad_sw_hr_av
11050    ENDIF
11051
11052
11053 END SUBROUTINE radiation_wrd_local
11054
11055!------------------------------------------------------------------------------!
11056! Description:
11057! ------------
11058!> Subroutine reads local (subdomain) restart data
11059!------------------------------------------------------------------------------!
11060 SUBROUTINE radiation_rrd_local( i, k, nxlf, nxlc, nxl_on_file, nxrf, nxrc,    &
11061                                nxr_on_file, nynf, nync, nyn_on_file, nysf,    &
11062                                nysc, nys_on_file, tmp_2d, tmp_3d, found )
11063 
11064
11065    USE control_parameters
11066       
11067    USE indices
11068   
11069    USE kinds
11070   
11071    USE pegrid
11072
11073
11074    IMPLICIT NONE
11075
11076    INTEGER(iwp) ::  i               !<
11077    INTEGER(iwp) ::  k               !<
11078    INTEGER(iwp) ::  nxlc            !<
11079    INTEGER(iwp) ::  nxlf            !<
11080    INTEGER(iwp) ::  nxl_on_file     !<
11081    INTEGER(iwp) ::  nxrc            !<
11082    INTEGER(iwp) ::  nxrf            !<
11083    INTEGER(iwp) ::  nxr_on_file     !<
11084    INTEGER(iwp) ::  nync            !<
11085    INTEGER(iwp) ::  nynf            !<
11086    INTEGER(iwp) ::  nyn_on_file     !<
11087    INTEGER(iwp) ::  nysc            !<
11088    INTEGER(iwp) ::  nysf            !<
11089    INTEGER(iwp) ::  nys_on_file     !<
11090
11091    LOGICAL, INTENT(OUT)  :: found
11092
11093    REAL(wp), DIMENSION(nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_2d   !<
11094
11095    REAL(wp), DIMENSION(nzb:nzt+1,nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_3d   !<
11096
11097    REAL(wp), DIMENSION(0:0,nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_3d2   !<
11098
11099
11100    found = .TRUE.
11101
11102
11103    SELECT CASE ( restart_string(1:length) )
11104
11105       CASE ( 'rad_net_av' )
11106          IF ( .NOT. ALLOCATED( rad_net_av ) )  THEN
11107             ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
11108          ENDIF 
11109          IF ( k == 1 )  READ ( 13 )  tmp_2d
11110          rad_net_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =           &
11111                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11112                       
11113       CASE ( 'rad_lw_in_xy_av' )
11114          IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) )  THEN
11115             ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
11116          ENDIF 
11117          IF ( k == 1 )  READ ( 13 )  tmp_2d
11118          rad_lw_in_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =      &
11119                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11120                       
11121       CASE ( 'rad_lw_out_xy_av' )
11122          IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) )  THEN
11123             ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
11124          ENDIF 
11125          IF ( k == 1 )  READ ( 13 )  tmp_2d
11126          rad_lw_out_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =     &
11127                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11128                       
11129       CASE ( 'rad_sw_in_xy_av' )
11130          IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) )  THEN
11131             ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
11132          ENDIF 
11133          IF ( k == 1 )  READ ( 13 )  tmp_2d
11134          rad_sw_in_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =      &
11135                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11136                       
11137       CASE ( 'rad_sw_out_xy_av' )
11138          IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) )  THEN
11139             ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
11140          ENDIF 
11141          IF ( k == 1 )  READ ( 13 )  tmp_2d
11142          rad_sw_out_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =     &
11143                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11144                       
11145       CASE ( 'rad_lw_in' )
11146          IF ( .NOT. ALLOCATED( rad_lw_in ) )  THEN
11147             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11148                  radiation_scheme == 'constant')  THEN
11149                ALLOCATE( rad_lw_in(0:0,nysg:nyng,nxlg:nxrg) )
11150             ELSE
11151                ALLOCATE( rad_lw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11152             ENDIF
11153          ENDIF 
11154          IF ( k == 1 )  THEN
11155             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11156                  radiation_scheme == 'constant')  THEN
11157                READ ( 13 )  tmp_3d2
11158                rad_lw_in(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =   &
11159                   tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11160             ELSE
11161                READ ( 13 )  tmp_3d
11162                rad_lw_in(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11163                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11164             ENDIF
11165          ENDIF
11166
11167       CASE ( 'rad_lw_in_av' )
11168          IF ( .NOT. ALLOCATED( rad_lw_in_av ) )  THEN
11169             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11170                  radiation_scheme == 'constant')  THEN
11171                ALLOCATE( rad_lw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
11172             ELSE
11173                ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11174             ENDIF
11175          ENDIF 
11176          IF ( k == 1 )  THEN
11177             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11178                  radiation_scheme == 'constant')  THEN
11179                READ ( 13 )  tmp_3d2
11180                rad_lw_in_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =&
11181                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11182             ELSE
11183                READ ( 13 )  tmp_3d
11184                rad_lw_in_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11185                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11186             ENDIF
11187          ENDIF
11188
11189       CASE ( 'rad_lw_out' )
11190          IF ( .NOT. ALLOCATED( rad_lw_out ) )  THEN
11191             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11192                  radiation_scheme == 'constant')  THEN
11193                ALLOCATE( rad_lw_out(0:0,nysg:nyng,nxlg:nxrg) )
11194             ELSE
11195                ALLOCATE( rad_lw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11196             ENDIF
11197          ENDIF 
11198          IF ( k == 1 )  THEN
11199             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11200                  radiation_scheme == 'constant')  THEN
11201                READ ( 13 )  tmp_3d2
11202                rad_lw_out(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11203                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11204             ELSE
11205                READ ( 13 )  tmp_3d
11206                rad_lw_out(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =    &
11207                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11208             ENDIF
11209          ENDIF
11210
11211       CASE ( 'rad_lw_out_av' )
11212          IF ( .NOT. ALLOCATED( rad_lw_out_av ) )  THEN
11213             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11214                  radiation_scheme == 'constant')  THEN
11215                ALLOCATE( rad_lw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
11216             ELSE
11217                ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11218             ENDIF
11219          ENDIF 
11220          IF ( k == 1 )  THEN
11221             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11222                  radiation_scheme == 'constant')  THEN
11223                READ ( 13 )  tmp_3d2
11224                rad_lw_out_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) &
11225                   = tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11226             ELSE
11227                READ ( 13 )  tmp_3d
11228                rad_lw_out_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &
11229                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11230             ENDIF
11231          ENDIF
11232
11233       CASE ( 'rad_lw_cs_hr' )
11234          IF ( .NOT. ALLOCATED( rad_lw_cs_hr ) )  THEN
11235             ALLOCATE( rad_lw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11236          ENDIF
11237          IF ( k == 1 )  READ ( 13 )  tmp_3d
11238          rad_lw_cs_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11239                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11240
11241       CASE ( 'rad_lw_cs_hr_av' )
11242          IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) )  THEN
11243             ALLOCATE( rad_lw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11244          ENDIF
11245          IF ( k == 1 )  READ ( 13 )  tmp_3d
11246          rad_lw_cs_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11247                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11248
11249       CASE ( 'rad_lw_hr' )
11250          IF ( .NOT. ALLOCATED( rad_lw_hr ) )  THEN
11251             ALLOCATE( rad_lw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11252          ENDIF
11253          IF ( k == 1 )  READ ( 13 )  tmp_3d
11254          rad_lw_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =           &
11255                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11256
11257       CASE ( 'rad_lw_hr_av' )
11258          IF ( .NOT. ALLOCATED( rad_lw_hr_av ) )  THEN
11259             ALLOCATE( rad_lw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11260          ENDIF
11261          IF ( k == 1 )  READ ( 13 )  tmp_3d
11262          rad_lw_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11263                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11264
11265       CASE ( 'rad_sw_in' )
11266          IF ( .NOT. ALLOCATED( rad_sw_in ) )  THEN
11267             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11268                  radiation_scheme == 'constant')  THEN
11269                ALLOCATE( rad_sw_in(0:0,nysg:nyng,nxlg:nxrg) )
11270             ELSE
11271                ALLOCATE( rad_sw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11272             ENDIF
11273          ENDIF 
11274          IF ( k == 1 )  THEN
11275             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11276                  radiation_scheme == 'constant')  THEN
11277                READ ( 13 )  tmp_3d2
11278                rad_sw_in(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =   &
11279                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11280             ELSE
11281                READ ( 13 )  tmp_3d
11282                rad_sw_in(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11283                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11284             ENDIF
11285          ENDIF
11286
11287       CASE ( 'rad_sw_in_av' )
11288          IF ( .NOT. ALLOCATED( rad_sw_in_av ) )  THEN
11289             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11290                  radiation_scheme == 'constant')  THEN
11291                ALLOCATE( rad_sw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
11292             ELSE
11293                ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11294             ENDIF
11295          ENDIF 
11296          IF ( k == 1 )  THEN
11297             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11298                  radiation_scheme == 'constant')  THEN
11299                READ ( 13 )  tmp_3d2
11300                rad_sw_in_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =&
11301                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11302             ELSE
11303                READ ( 13 )  tmp_3d
11304                rad_sw_in_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11305                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11306             ENDIF
11307          ENDIF
11308
11309       CASE ( 'rad_sw_out' )
11310          IF ( .NOT. ALLOCATED( rad_sw_out ) )  THEN
11311             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11312                  radiation_scheme == 'constant')  THEN
11313                ALLOCATE( rad_sw_out(0:0,nysg:nyng,nxlg:nxrg) )
11314             ELSE
11315                ALLOCATE( rad_sw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11316             ENDIF
11317          ENDIF 
11318          IF ( k == 1 )  THEN
11319             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11320                  radiation_scheme == 'constant')  THEN
11321                READ ( 13 )  tmp_3d2
11322                rad_sw_out(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11323                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11324             ELSE
11325                READ ( 13 )  tmp_3d
11326                rad_sw_out(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =    &
11327                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11328             ENDIF
11329          ENDIF
11330
11331       CASE ( 'rad_sw_out_av' )
11332          IF ( .NOT. ALLOCATED( rad_sw_out_av ) )  THEN
11333             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11334                  radiation_scheme == 'constant')  THEN
11335                ALLOCATE( rad_sw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
11336             ELSE
11337                ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11338             ENDIF
11339          ENDIF 
11340          IF ( k == 1 )  THEN
11341             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11342                  radiation_scheme == 'constant')  THEN
11343                READ ( 13 )  tmp_3d2
11344                rad_sw_out_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) &
11345                   = tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11346             ELSE
11347                READ ( 13 )  tmp_3d
11348                rad_sw_out_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &
11349                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11350             ENDIF
11351          ENDIF
11352
11353       CASE ( 'rad_sw_cs_hr' )
11354          IF ( .NOT. ALLOCATED( rad_sw_cs_hr ) )  THEN
11355             ALLOCATE( rad_sw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11356          ENDIF
11357          IF ( k == 1 )  READ ( 13 )  tmp_3d
11358          rad_sw_cs_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11359                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11360
11361       CASE ( 'rad_sw_cs_hr_av' )
11362          IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) )  THEN
11363             ALLOCATE( rad_sw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11364          ENDIF
11365          IF ( k == 1 )  READ ( 13 )  tmp_3d
11366          rad_sw_cs_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11367                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11368
11369       CASE ( 'rad_sw_hr' )
11370          IF ( .NOT. ALLOCATED( rad_sw_hr ) )  THEN
11371             ALLOCATE( rad_sw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11372          ENDIF
11373          IF ( k == 1 )  READ ( 13 )  tmp_3d
11374          rad_sw_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =           &
11375                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11376
11377       CASE ( 'rad_sw_hr_av' )
11378          IF ( .NOT. ALLOCATED( rad_sw_hr_av ) )  THEN
11379             ALLOCATE( rad_sw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11380          ENDIF
11381          IF ( k == 1 )  READ ( 13 )  tmp_3d
11382          rad_lw_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11383                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11384
11385       CASE DEFAULT
11386
11387          found = .FALSE.
11388
11389    END SELECT
11390
11391 END SUBROUTINE radiation_rrd_local
11392
11393!------------------------------------------------------------------------------!
11394! Description:
11395! ------------
11396!> Subroutine writes debug information
11397!------------------------------------------------------------------------------!
11398 SUBROUTINE radiation_write_debug_log ( message )
11399    !> it writes debug log with time stamp
11400    CHARACTER(*)  :: message
11401    CHARACTER(15) :: dtc
11402    CHARACTER(8)  :: date
11403    CHARACTER(10) :: time
11404    CHARACTER(5)  :: zone
11405    CALL date_and_time(date, time, zone)
11406    dtc = date(7:8)//','//time(1:2)//':'//time(3:4)//':'//time(5:10)
11407    WRITE(9,'(2A)') dtc, TRIM(message)
11408    FLUSH(9)
11409 END SUBROUTINE radiation_write_debug_log
11410
11411 END MODULE radiation_model_mod
Note: See TracBrowser for help on using the repository browser.