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

Last change on this file since 3743 was 3743, checked in by moh.hefny, 6 years ago

added read/write number of MRT factors to the respective routines

  • 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: 499.2 KB
Line 
1!> @file radiation_model_mod.f90
2!------------------------------------------------------------------------------!
3! This file is part of the PALM model system.
4!
5! PALM is free software: you can redistribute it and/or modify it under the
6! terms of the GNU General Public License as published by the Free Software
7! Foundation, either version 3 of the License, or (at your option) any later
8! version.
9!
10! PALM is distributed in the hope that it will be useful, but WITHOUT ANY
11! WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12! A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
13!
14! You should have received a copy of the GNU General Public License along with
15! PALM. If not, see <http://www.gnu.org/licenses/>.
16!
17! Copyright 2015-2018 Institute of Computer Science of the
18!                     Czech Academy of Sciences, Prague
19! Copyright 2015-2018 Czech Technical University in Prague
20! Copyright 1997-2019 Leibniz Universitaet Hannover
21!------------------------------------------------------------------------------!
22!
23! Current revisions:
24! ------------------
25!
26!
27! Former revisions:
28! -----------------
29! $Id: radiation_model_mod.f90 3743 2019-02-15 08:50:40Z moh.hefny $
30! added read/write number of MRT factors to the respective routines
31!
32! 3705 2019-01-29 19:56:39Z suehring
33! Make variables that are sampled in virtual measurement module public
34!
35! 3704 2019-01-29 19:51:41Z suehring
36! Some interface calls moved to module_interface + cleanup
37!
38! 3667 2019-01-10 14:26:24Z schwenkel
39! Modified check for rrtmg input files
40!
41! 3655 2019-01-07 16:51:22Z knoop
42! nopointer option removed
43!
44! 3633 2018-12-17 16:17:57Z schwenkel
45! Include check for rrtmg files
46!
47! 3630 2018-12-17 11:04:17Z knoop
48! - fix initialization of date and time after calling zenith
49! - fix a bug in radiation_solar_pos
50!
51! 3616 2018-12-10 09:44:36Z Salim
52! fix manipulation of time variables in radiation_presimulate_solar_pos
53!
54! 3608 2018-12-07 12:59:57Z suehring $
55! Bugfix radiation output
56!
57! 3607 2018-12-07 11:56:58Z suehring
58! Output of radiation-related quantities migrated to radiation_model_mod.
59!
60! 3589 2018-11-30 15:09:51Z suehring
61! Remove erroneous UTF encoding
62!
63! 3572 2018-11-28 11:40:28Z suehring
64! Add filling the short- and longwave radiation flux arrays (e.g. diffuse,
65! direct, reflected, resedual) for all surfaces. This is required to surface
66! outputs in suface_output_mod. (M. Salim)
67!
68! 3571 2018-11-28 09:24:03Z moh.hefny
69! Add an epsilon value to compare values in if statement to fix possible
70! precsion related errors in raytrace routines.
71!
72! 3524 2018-11-14 13:36:44Z raasch
73! missing cpp-directives added
74!
75! 3495 2018-11-06 15:22:17Z kanani
76! Resort control_parameters ONLY list,
77! From branch radiation@3491 moh.hefny:
78! bugfix in calculating the apparent solar positions by updating
79! the simulated time so that the actual time is correct.
80!
81! 3464 2018-10-30 18:08:55Z kanani
82! From branch resler@3462, pavelkrc:
83! add MRT shaping function for human
84!
85! 3449 2018-10-29 19:36:56Z suehring
86! New RTM version 3.0: (Pavel Krc, Jaroslav Resler, ICS, Prague)
87!   - Interaction of plant canopy with LW radiation
88!   - Transpiration from resolved plant canopy dependent on radiation
89!     called from RTM
90!
91!
92! 3435 2018-10-26 18:25:44Z gronemeier
93! - workaround: return unit=illegal in check_data_output for certain variables
94!   when check called from init_masks
95! - Use pointer in masked output to reduce code redundancies
96! - Add terrain-following masked output
97!
98! 3424 2018-10-25 07:29:10Z gronemeier
99! bugfix: add rad_lw_in, rad_lw_out, rad_sw_out to radiation_check_data_output
100!
101! 3378 2018-10-19 12:34:59Z kanani
102! merge from radiation branch (r3362) into trunk
103! (moh.hefny):
104! - removed read/write_svf_on_init and read_dist_max_svf (not used anymore)
105! - bugfix nzut > nzpt in calculating maxboxes
106!
107! 3372 2018-10-18 14:03:19Z raasch
108! bugfix: kind type of 2nd argument of mpi_win_allocate changed, misplaced
109!         __parallel directive
110!
111! 3351 2018-10-15 18:40:42Z suehring
112! Do not overwrite values of spectral and broadband albedo during initialization
113! if they are already initialized in the urban-surface model via ASCII input.
114!
115! 3337 2018-10-12 15:17:09Z kanani
116! - New RTM version 2.9: (Pavel Krc, Jaroslav Resler, ICS, Prague)
117!   added calculation of the MRT inside the RTM module
118!   MRT fluxes are consequently used in the new biometeorology module
119!   for calculation of biological indices (MRT, PET)
120!   Fixes of v. 2.5 and SVN trunk:
121!    - proper initialization of rad_net_l
122!    - make arrays nsurfs and surfstart TARGET to prevent some MPI problems
123!    - initialization of arrays used in MPI one-sided operation as 1-D arrays
124!      to prevent problems with some MPI/compiler combinations
125!    - fix indexing of target displacement in subroutine request_itarget to
126!      consider nzub
127!    - fix LAD dimmension range in PCB calculation
128!    - check ierr in all MPI calls
129!    - use proper per-gridbox sky and diffuse irradiance
130!    - fix shading for reflected irradiance
131!    - clear away the residuals of "atmospheric surfaces" implementation
132!    - fix rounding bug in raytrace_2d introduced in SVN trunk
133! - New RTM version 2.5: (Pavel Krc, Jaroslav Resler, ICS, Prague)
134!   can use angular discretization for all SVF
135!   (i.e. reflected and emitted radiation in addition to direct and diffuse),
136!   allowing for much better scaling wih high resoltion and/or complex terrain
137! - Unite array grow factors
138! - Fix slightly shifted terrain height in raytrace_2d
139! - Use more efficient MPI_Win_allocate for reverse gridsurf index
140! - Fix random MPI RMA bugs on Intel compilers
141! - Fix approx. double plant canopy sink values for reflected radiation
142! - Fix mostly missing plant canopy sinks for direct radiation
143! - Fix discretization errors for plant canopy sink in diffuse radiation
144! - Fix rounding errors in raytrace_2d
145!
146! 3274 2018-09-24 15:42:55Z knoop
147! Modularization of all bulk cloud physics code components
148!
149! 3272 2018-09-24 10:16:32Z suehring
150! - split direct and diffusion shortwave radiation using RRTMG rather than using
151!   calc_diffusion_radiation, in case of RRTMG
152! - removed the namelist variable split_diffusion_radiation. Now splitting depends
153!   on the choise of radiation radiation scheme
154! - removed calculating the rdiation flux for surfaces at the radiation scheme
155!   in case of using RTM since it will be calculated anyway in the radiation
156!   interaction routine.
157! - set SW radiation flux for surfaces to zero at night in case of no RTM is used
158! - precalculate the unit vector yxdir of ray direction to avoid the temporarly
159!   array allocation during the subroutine call
160! - fixed a bug in calculating the max number of boxes ray can cross in the domain
161!
162! 3264 2018-09-20 13:54:11Z moh.hefny
163! Bugfix in raytrace_2d calls
164!
165! 3248 2018-09-14 09:42:06Z sward
166! Minor formating changes
167!
168! 3246 2018-09-13 15:14:50Z sward
169! Added error handling for input namelist via parin_fail_message
170!
171! 3241 2018-09-12 15:02:00Z raasch
172! unused variables removed or commented
173!
174! 3233 2018-09-07 13:21:24Z schwenkel
175! Adapted for the use of cloud_droplets
176!
177! 3230 2018-09-05 09:29:05Z schwenkel
178! Bugfix in radiation_constant_surf: changed (10.0 - emissivity_urb) to
179! (1.0 - emissivity_urb)
180!
181! 3226 2018-08-31 12:27:09Z suehring
182! Bugfixes in calculation of sky-view factors and canopy-sink factors.
183!
184! 3186 2018-07-30 17:07:14Z suehring
185! Remove print statement
186!
187! 3180 2018-07-27 11:00:56Z suehring
188! Revise concept for calculation of effective radiative temperature and mapping
189! of radiative heating
190!
191! 3175 2018-07-26 14:07:38Z suehring
192! Bugfix for commit 3172
193!
194! 3173 2018-07-26 12:55:23Z suehring
195! Revise output of surface radiation quantities in case of overhanging
196! structures
197!
198! 3172 2018-07-26 12:06:06Z suehring
199! Bugfixes:
200!  - temporal work-around for calculation of effective radiative surface
201!    temperature
202!  - prevent positive solar radiation during nighttime
203!
204! 3170 2018-07-25 15:19:37Z suehring
205! Bugfix, map signle-column radiation forcing profiles on top of any topography
206!
207! 3156 2018-07-19 16:30:54Z knoop
208! Bugfix: replaced usage of the pt array with the surf%pt_surface array
209!
210! 3137 2018-07-17 06:44:21Z maronga
211! String length for trace_names fixed
212!
213! 3127 2018-07-15 08:01:25Z maronga
214! A few pavement parameters updated.
215!
216! 3123 2018-07-12 16:21:53Z suehring
217! Correct working precision for INTEGER number
218!
219! 3122 2018-07-11 21:46:41Z maronga
220! Bugfix: maximum distance for raytracing was set to  -999 m by default,
221! effectively switching off all surface reflections when max_raytracing_dist
222! was not explicitly set in namelist
223!
224! 3117 2018-07-11 09:59:11Z maronga
225! Bugfix: water vapor was not transfered to RRTMG when bulk_cloud_model = .F.
226! Bugfix: changed the calculation of RRTMG boundary conditions (Mohamed Salim)
227! Bugfix: dry residual atmosphere is replaced by standard RRTMG atmosphere
228!
229! 3116 2018-07-10 14:31:58Z suehring
230! Output of long/shortwave radiation at surface
231!
232! 3107 2018-07-06 15:55:51Z suehring
233! Bugfix, missing index for dz
234!
235! 3066 2018-06-12 08:55:55Z Giersch
236! Error message revised
237!
238! 3065 2018-06-12 07:03:02Z Giersch
239! dz was replaced by dz(1), error message concerning vertical stretching was
240! added 
241!
242! 3049 2018-05-29 13:52:36Z Giersch
243! Error messages revised
244!
245! 3045 2018-05-28 07:55:41Z Giersch
246! Error message revised
247!
248! 3026 2018-05-22 10:30:53Z schwenkel
249! Changed the name specific humidity to mixing ratio, since we are computing
250! mixing ratios.
251!
252! 3016 2018-05-09 10:53:37Z Giersch
253! Revised structure of reading svf data according to PALM coding standard:
254! svf_code_field/len and fsvf removed, error messages PA0493 and PA0494 added,
255! allocation status of output arrays checked.
256!
257! 3014 2018-05-09 08:42:38Z maronga
258! Introduced plant canopy height similar to urban canopy height to limit
259! the memory requirement to allocate lad.
260! Deactivated automatic setting of minimum raytracing distance.
261!
262! 3004 2018-04-27 12:33:25Z Giersch
263! Further allocation checks implemented (averaged data will be assigned to fill
264! values if no allocation happened so far)
265!
266! 2995 2018-04-19 12:13:16Z Giersch
267! IF-statement in radiation_init removed so that the calculation of radiative
268! fluxes at model start is done in any case, bugfix in
269! radiation_presimulate_solar_pos (end_time is the sum of end_time and the
270! spinup_time specified in the p3d_file ), list of variables/fields that have
271! to be written out or read in case of restarts has been extended
272!
273! 2977 2018-04-17 10:27:57Z kanani
274! Implement changes from branch radiation (r2948-2971) with minor modifications,
275! plus some formatting.
276! (moh.hefny):
277! - replaced plant_canopy by npcbl to check tree existence to avoid weird
278!   allocation of related arrays (after domain decomposition some domains
279!   contains no trees although plant_canopy (global parameter) is still TRUE).
280! - added a namelist parameter to force RTM settings
281! - enabled the option to switch radiation reflections off
282! - renamed surf_reflections to surface_reflections
283! - removed average_radiation flag from the namelist (now it is implicitly set
284!   in init_3d_model according to RTM)
285! - edited read and write sky view factors and CSF routines to account for
286!   the sub-domains which may not contain any of them
287!
288! 2967 2018-04-13 11:22:08Z raasch
289! bugfix: missing parallel cpp-directives added
290!
291! 2964 2018-04-12 16:04:03Z Giersch
292! Error message PA0491 has been introduced which could be previously found in
293! check_open. The variable numprocs_previous_run is only known in case of
294! initializing_actions == read_restart_data
295!
296! 2963 2018-04-12 14:47:44Z suehring
297! - Introduce index for vegetation/wall, pavement/green-wall and water/window
298!   surfaces, for clearer access of surface fraction, albedo, emissivity, etc. .
299! - Minor bugfix in initialization of albedo for window surfaces
300!
301! 2944 2018-04-03 16:20:18Z suehring
302! Fixed bad commit
303!
304! 2943 2018-04-03 16:17:10Z suehring
305! No read of nsurfl from SVF file since it is calculated in
306! radiation_interaction_init,
307! allocation of arrays in radiation_read_svf only if not yet allocated,
308! update of 2920 revision comment.
309!
310! 2932 2018-03-26 09:39:22Z maronga
311! renamed radiation_par to radiation_parameters
312!
313! 2930 2018-03-23 16:30:46Z suehring
314! Remove default surfaces from radiation model, does not make much sense to
315! apply radiation model without energy-balance solvers; Further, add check for
316! this.
317!
318! 2920 2018-03-22 11:22:01Z kanani
319! - Bugfix: Initialize pcbl array (=-1)
320! RTM version 2.0 (Jaroslav Resler, Pavel Krc, Mohamed Salim):
321! - new major version of radiation interactions
322! - substantially enhanced performance and scalability
323! - processing of direct and diffuse solar radiation separated from reflected
324!   radiation, removed virtual surfaces
325! - new type of sky discretization by azimuth and elevation angles
326! - diffuse radiation processed cumulatively using sky view factor
327! - used precalculated apparent solar positions for direct irradiance
328! - added new 2D raytracing process for processing whole vertical column at once
329!   to increase memory efficiency and decrease number of MPI RMA operations
330! - enabled limiting the number of view factors between surfaces by the distance
331!   and value
332! - fixing issues induced by transferring radiation interactions from
333!   urban_surface_mod to radiation_mod
334! - bugfixes and other minor enhancements
335!
336! 2906 2018-03-19 08:56:40Z Giersch
337! NAMELIST paramter read/write_svf_on_init have been removed, functions
338! check_open and close_file are used now for opening/closing files related to
339! svf data, adjusted unit number and error numbers
340!
341! 2894 2018-03-15 09:17:58Z Giersch
342! Calculations of the index range of the subdomain on file which overlaps with
343! the current subdomain are already done in read_restart_data_mod
344! radiation_read_restart_data was renamed to radiation_rrd_local and
345! radiation_last_actions was renamed to radiation_wrd_local, variable named
346! found has been introduced for checking if restart data was found, reading
347! of restart strings has been moved completely to read_restart_data_mod,
348! radiation_rrd_local is already inside the overlap loop programmed in
349! read_restart_data_mod, the marker *** end rad *** is not necessary anymore,
350! strings and their respective lengths are written out and read now in case of
351! restart runs to get rid of prescribed character lengths (Giersch)
352!
353! 2809 2018-02-15 09:55:58Z suehring
354! Bugfix for gfortran: Replace the function C_SIZEOF with STORAGE_SIZE
355!
356! 2753 2018-01-16 14:16:49Z suehring
357! Tile approach for spectral albedo implemented.
358!
359! 2746 2018-01-15 12:06:04Z suehring
360! Move flag plant canopy to modules
361!
362! 2724 2018-01-05 12:12:38Z maronga
363! Set default of average_radiation to .FALSE.
364!
365! 2723 2018-01-05 09:27:03Z maronga
366! Bugfix in calculation of rad_lw_out (clear-sky). First grid level was used
367! instead of the surface value
368!
369! 2718 2018-01-02 08:49:38Z maronga
370! Corrected "Former revisions" section
371!
372! 2707 2017-12-18 18:34:46Z suehring
373! Changes from last commit documented
374!
375! 2706 2017-12-18 18:33:49Z suehring
376! Bugfix, in average radiation case calculate exner function before using it.
377!
378! 2701 2017-12-15 15:40:50Z suehring
379! Changes from last commit documented
380!
381! 2698 2017-12-14 18:46:24Z suehring
382! Bugfix in get_topography_top_index
383!
384! 2696 2017-12-14 17:12:51Z kanani
385! - Change in file header (GPL part)
386! - Improved reading/writing of SVF from/to file (BM)
387! - Bugfixes concerning RRTMG as well as average_radiation options (M. Salim)
388! - Revised initialization of surface albedo and some minor bugfixes (MS)
389! - Update net radiation after running radiation interaction routine (MS)
390! - Revisions from M Salim included
391! - Adjustment to topography and surface structure (MS)
392! - Initialization of albedo and surface emissivity via input file (MS)
393! - albedo_pars extended (MS)
394!
395! 2604 2017-11-06 13:29:00Z schwenkel
396! bugfix for calculation of effective radius using morrison microphysics
397!
398! 2601 2017-11-02 16:22:46Z scharf
399! added emissivity to namelist
400!
401! 2575 2017-10-24 09:57:58Z maronga
402! Bugfix: calculation of shortwave and longwave albedos for RRTMG swapped
403!
404! 2547 2017-10-16 12:41:56Z schwenkel
405! extended by cloud_droplets option, minor bugfix and correct calculation of
406! cloud droplet number concentration
407!
408! 2544 2017-10-13 18:09:32Z maronga
409! Moved date and time quantitis to separate module date_and_time_mod
410!
411! 2512 2017-10-04 08:26:59Z raasch
412! upper bounds of cross section and 3d output changed from nx+1,ny+1 to nx,ny
413! no output of ghost layer data
414!
415! 2504 2017-09-27 10:36:13Z maronga
416! Updates pavement types and albedo parameters
417!
418! 2328 2017-08-03 12:34:22Z maronga
419! Emissivity can now be set individually for each pixel.
420! Albedo type can be inferred from land surface model.
421! Added default albedo type for bare soil
422!
423! 2318 2017-07-20 17:27:44Z suehring
424! Get topography top index via Function call
425!
426! 2317 2017-07-20 17:27:19Z suehring
427! Improved syntax layout
428!
429! 2298 2017-06-29 09:28:18Z raasch
430! type of write_binary changed from CHARACTER to LOGICAL
431!
432! 2296 2017-06-28 07:53:56Z maronga
433! Added output of rad_sw_out for radiation_scheme = 'constant'
434!
435! 2270 2017-06-09 12:18:47Z maronga
436! Numbering changed (2 timeseries removed)
437!
438! 2249 2017-06-06 13:58:01Z sward
439! Allow for RRTMG runs without humidity/cloud physics
440!
441! 2248 2017-06-06 13:52:54Z sward
442! Error no changed
443!
444! 2233 2017-05-30 18:08:54Z suehring
445!
446! 2232 2017-05-30 17:47:52Z suehring
447! Adjustments to new topography concept
448! Bugfix in read restart
449!
450! 2200 2017-04-11 11:37:51Z suehring
451! Bugfix in call of exchange_horiz_2d and read restart data
452!
453! 2163 2017-03-01 13:23:15Z schwenkel
454! Bugfix in radiation_check_data_output
455!
456! 2157 2017-02-22 15:10:35Z suehring
457! Bugfix in read_restart data
458!
459! 2011 2016-09-19 17:29:57Z kanani
460! Removed CALL of auxiliary SUBROUTINE get_usm_info,
461! flag urban_surface is now defined in module control_parameters.
462!
463! 2007 2016-08-24 15:47:17Z kanani
464! Added calculation of solar directional vector for new urban surface
465! model,
466! accounted for urban_surface model in radiation_check_parameters,
467! correction of comments for zenith angle.
468!
469! 2000 2016-08-20 18:09:15Z knoop
470! Forced header and separation lines into 80 columns
471!
472! 1976 2016-07-27 13:28:04Z maronga
473! Output of 2D/3D/masked data is now directly done within this module. The
474! radiation schemes have been simplified for better usability so that
475! rad_lw_in, rad_lw_out, rad_sw_in, and rad_sw_out are available independent of
476! the radiation code used.
477!
478! 1856 2016-04-13 12:56:17Z maronga
479! Bugfix: allocation of rad_lw_out for radiation_scheme = 'clear-sky'
480!
481! 1853 2016-04-11 09:00:35Z maronga
482! Added routine for radiation_scheme = constant.
483
484! 1849 2016-04-08 11:33:18Z hoffmann
485! Adapted for modularization of microphysics
486!
487! 1826 2016-04-07 12:01:39Z maronga
488! Further modularization.
489!
490! 1788 2016-03-10 11:01:04Z maronga
491! Added new albedo class for pavements / roads.
492!
493! 1783 2016-03-06 18:36:17Z raasch
494! palm-netcdf-module removed in order to avoid a circular module dependency,
495! netcdf-variables moved to netcdf-module, new routine netcdf_handle_error_rad
496! added
497!
498! 1757 2016-02-22 15:49:32Z maronga
499! Added parameter unscheduled_radiation_calls. Bugfix: interpolation of sounding
500! profiles for pressure and temperature above the LES domain.
501!
502! 1709 2015-11-04 14:47:01Z maronga
503! Bugfix: set initial value for rrtm_lwuflx_dt to zero, small formatting
504! corrections
505!
506! 1701 2015-11-02 07:43:04Z maronga
507! Bugfixes: wrong index for output of timeseries, setting of nz_snd_end
508!
509! 1691 2015-10-26 16:17:44Z maronga
510! Added option for spin-up runs without radiation (skip_time_do_radiation). Bugfix
511! in calculation of pressure profiles. Bugfix in calculation of trace gas profiles.
512! Added output of radiative heating rates.
513!
514! 1682 2015-10-07 23:56:08Z knoop
515! Code annotations made doxygen readable
516!
517! 1606 2015-06-29 10:43:37Z maronga
518! Added preprocessor directive __netcdf to allow for compiling without netCDF.
519! Note, however, that RRTMG cannot be used without netCDF.
520!
521! 1590 2015-05-08 13:56:27Z maronga
522! Bugfix: definition of character strings requires same length for all elements
523!
524! 1587 2015-05-04 14:19:01Z maronga
525! Added albedo class for snow
526!
527! 1585 2015-04-30 07:05:52Z maronga
528! Added support for RRTMG
529!
530! 1571 2015-03-12 16:12:49Z maronga
531! Added missing KIND attribute. Removed upper-case variable names
532!
533! 1551 2015-03-03 14:18:16Z maronga
534! Added support for data output. Various variables have been renamed. Added
535! interface for different radiation schemes (currently: clear-sky, constant, and
536! RRTM (not yet implemented).
537!
538! 1496 2014-12-02 17:25:50Z maronga
539! Initial revision
540!
541!
542! Description:
543! ------------
544!> Radiation models and interfaces
545!> @todo Replace dz(1) appropriatly to account for grid stretching
546!> @todo move variable definitions used in radiation_init only to the subroutine
547!>       as they are no longer required after initialization.
548!> @todo Output of full column vertical profiles used in RRTMG
549!> @todo Output of other rrtm arrays (such as volume mixing ratios)
550!> @todo Check for mis-used NINT() calls in raytrace_2d
551!>       RESULT: Original was correct (carefully verified formula), the change
552!>               to INT broke raytracing      -- P. Krc
553!> @todo Optimize radiation_tendency routines
554!>
555!> @note Many variables have a leading dummy dimension (0:0) in order to
556!>       match the assume-size shape expected by the RRTMG model.
557!------------------------------------------------------------------------------!
558 MODULE radiation_model_mod
559 
560    USE arrays_3d,                                                             &
561        ONLY:  dzw, hyp, nc, pt, p, q, ql, u, v, w, zu, zw, exner, d_exner
562
563    USE basic_constants_and_equations_mod,                                     &
564        ONLY:  c_p, g, lv_d_cp, l_v, pi, r_d, rho_l, solar_constant,      &
565               barometric_formula
566
567    USE calc_mean_profile_mod,                                                 &
568        ONLY:  calc_mean_profile
569
570    USE control_parameters,                                                    &
571        ONLY:  cloud_droplets, coupling_char, dz, dt_spinup, end_time,         &
572               humidity,                                                       &
573               initializing_actions, io_blocks, io_group,                      &
574               land_surface, large_scale_forcing,                              &
575               latitude, longitude, lsf_surf,                                  &
576               message_string, plant_canopy, pt_surface,                       &
577               rho_surface, simulated_time, spinup_time, surface_pressure,     &
578               read_svf, write_svf,                                            &
579               time_since_reference_point, urban_surface, varnamelength
580
581    USE cpulog,                                                                &
582        ONLY:  cpu_log, log_point, log_point_s
583
584    USE grid_variables,                                                        &
585         ONLY:  ddx, ddy, dx, dy 
586
587    USE date_and_time_mod,                                                     &
588        ONLY:  calc_date_and_time, d_hours_day, d_seconds_hour, d_seconds_year,&
589               day_of_year, d_seconds_year, day_of_month, day_of_year_init,    &
590               init_date_and_time, month_of_year, time_utc_init, time_utc
591
592    USE indices,                                                               &
593        ONLY:  nnx, nny, nx, nxl, nxlg, nxr, nxrg, ny, nyn, nyng, nys, nysg,   &
594               nzb, nzt
595
596    USE, INTRINSIC :: iso_c_binding
597
598    USE kinds
599
600    USE bulk_cloud_model_mod,                                                  &
601        ONLY:  bulk_cloud_model, microphysics_morrison, na_init, nc_const, sigma_gc
602
603#if defined ( __netcdf )
604    USE NETCDF
605#endif
606
607    USE netcdf_data_input_mod,                                                 &
608        ONLY:  albedo_type_f, albedo_pars_f, building_type_f, pavement_type_f, &
609               vegetation_type_f, water_type_f
610
611    USE plant_canopy_model_mod,                                                &
612        ONLY:  lad_s, pc_heating_rate, pc_transpiration_rate, pc_latent_rate,  &
613               plant_canopy_transpiration, pcm_calc_transpiration_rate
614
615    USE pegrid
616
617#if defined ( __rrtmg )
618    USE parrrsw,                                                               &
619        ONLY:  naerec, nbndsw
620
621    USE parrrtm,                                                               &
622        ONLY:  nbndlw
623
624    USE rrtmg_lw_init,                                                         &
625        ONLY:  rrtmg_lw_ini
626
627    USE rrtmg_sw_init,                                                         &
628        ONLY:  rrtmg_sw_ini
629
630    USE rrtmg_lw_rad,                                                          &
631        ONLY:  rrtmg_lw
632
633    USE rrtmg_sw_rad,                                                          &
634        ONLY:  rrtmg_sw
635#endif
636    USE statistics,                                                            &
637        ONLY:  hom
638
639    USE surface_mod,                                                           &
640        ONLY:  get_topography_top_index, get_topography_top_index_ji,          &
641               ind_pav_green, ind_veg_wall, ind_wat_win,                       &
642               surf_lsm_h, surf_lsm_v, surf_type, surf_usm_h, surf_usm_v,      &
643               vertical_surfaces_exist
644
645    IMPLICIT NONE
646
647    CHARACTER(10) :: radiation_scheme = 'clear-sky' ! 'constant', 'clear-sky', or 'rrtmg'
648
649!
650!-- Predefined Land surface classes (albedo_type) after Briegleb (1992)
651    CHARACTER(37), DIMENSION(0:33), PARAMETER :: albedo_type_name = (/      &
652                                   'user defined                         ', & !  0
653                                   'ocean                                ', & !  1
654                                   'mixed farming, tall grassland        ', & !  2
655                                   'tall/medium grassland                ', & !  3
656                                   'evergreen shrubland                  ', & !  4
657                                   'short grassland/meadow/shrubland     ', & !  5
658                                   'evergreen needleleaf forest          ', & !  6
659                                   'mixed deciduous evergreen forest     ', & !  7
660                                   'deciduous forest                     ', & !  8
661                                   'tropical evergreen broadleaved forest', & !  9
662                                   'medium/tall grassland/woodland       ', & ! 10
663                                   'desert, sandy                        ', & ! 11
664                                   'desert, rocky                        ', & ! 12
665                                   'tundra                               ', & ! 13
666                                   'land ice                             ', & ! 14
667                                   'sea ice                              ', & ! 15
668                                   'snow                                 ', & ! 16
669                                   'bare soil                            ', & ! 17
670                                   'asphalt/concrete mix                 ', & ! 18
671                                   'asphalt (asphalt concrete)           ', & ! 19
672                                   'concrete (Portland concrete)         ', & ! 20
673                                   'sett                                 ', & ! 21
674                                   'paving stones                        ', & ! 22
675                                   'cobblestone                          ', & ! 23
676                                   'metal                                ', & ! 24
677                                   'wood                                 ', & ! 25
678                                   'gravel                               ', & ! 26
679                                   'fine gravel                          ', & ! 27
680                                   'pebblestone                          ', & ! 28
681                                   'woodchips                            ', & ! 29
682                                   'tartan (sports)                      ', & ! 30
683                                   'artifical turf (sports)              ', & ! 31
684                                   'clay (sports)                        ', & ! 32
685                                   'building (dummy)                     '  & ! 33
686                                                         /)
687
688    REAL(wp), PARAMETER :: sigma_sb       = 5.67037321E-8_wp !< Stefan-Boltzmann constant
689
690    INTEGER(iwp) :: albedo_type  = 9999999, & !< Albedo surface type
691                    dots_rad     = 0          !< starting index for timeseries output
692
693    LOGICAL ::  unscheduled_radiation_calls = .TRUE., & !< flag parameter indicating whether additional calls of the radiation code are allowed
694                constant_albedo = .FALSE.,            & !< flag parameter indicating whether the albedo may change depending on zenith
695                force_radiation_call = .FALSE.,       & !< flag parameter for unscheduled radiation calls
696                lw_radiation = .TRUE.,                & !< flag parameter indicating whether longwave radiation shall be calculated
697                radiation = .FALSE.,                  & !< flag parameter indicating whether the radiation model is used
698                sun_up    = .TRUE.,                   & !< flag parameter indicating whether the sun is up or down
699                sw_radiation = .TRUE.,                & !< flag parameter indicating whether shortwave radiation shall be calculated
700                sun_direction = .FALSE.,              & !< flag parameter indicating whether solar direction shall be calculated
701                average_radiation = .FALSE.,          & !< flag to set the calculation of radiation averaging for the domain
702                radiation_interactions = .FALSE.,     & !< flag to activiate RTM (TRUE only if vertical urban/land surface and trees exist)
703                surface_reflections = .TRUE.,         & !< flag to switch the calculation of radiation interaction between surfaces.
704                                                        !< When it switched off, only the effect of buildings and trees shadow
705                                                        !< will be considered. However fewer SVFs are expected.
706                radiation_interactions_on = .TRUE.      !< namelist flag to force RTM activiation regardless to vertical urban/land surface and trees
707
708    REAL(wp) :: albedo = 9999999.9_wp,           & !< NAMELIST alpha
709                albedo_lw_dif = 9999999.9_wp,    & !< NAMELIST aldif
710                albedo_lw_dir = 9999999.9_wp,    & !< NAMELIST aldir
711                albedo_sw_dif = 9999999.9_wp,    & !< NAMELIST asdif
712                albedo_sw_dir = 9999999.9_wp,    & !< NAMELIST asdir
713                decl_1,                          & !< declination coef. 1
714                decl_2,                          & !< declination coef. 2
715                decl_3,                          & !< declination coef. 3
716                dt_radiation = 0.0_wp,           & !< radiation model timestep
717                emissivity = 9999999.9_wp,       & !< NAMELIST surface emissivity
718                lon = 0.0_wp,                    & !< longitude in radians
719                lat = 0.0_wp,                    & !< latitude in radians
720                net_radiation = 0.0_wp,          & !< net radiation at surface
721                skip_time_do_radiation = 0.0_wp, & !< Radiation model is not called before this time
722                sky_trans,                       & !< sky transmissivity
723                time_radiation = 0.0_wp            !< time since last call of radiation code
724
725
726    REAL(wp), DIMENSION(0:0) ::  zenith,         & !< cosine of solar zenith angle
727                                 sun_dir_lat,    & !< solar directional vector in latitudes
728                                 sun_dir_lon       !< solar directional vector in longitudes
729
730    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_net_av       !< average of net radiation (rad_net) at surface
731    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_lw_in_xy_av  !< average of incoming longwave radiation at surface
732    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_lw_out_xy_av !< average of outgoing longwave radiation at surface
733    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_sw_in_xy_av  !< average of incoming shortwave radiation at surface
734    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_sw_out_xy_av !< average of outgoing shortwave radiation at surface
735!
736!-- Land surface albedos for solar zenith angle of 60degree after Briegleb (1992)     
737!-- (shortwave, longwave, broadband):   sw,      lw,      bb,
738    REAL(wp), DIMENSION(0:2,1:33), PARAMETER :: albedo_pars = RESHAPE( (/& 
739                                   0.06_wp, 0.06_wp, 0.06_wp,            & !  1
740                                   0.09_wp, 0.28_wp, 0.19_wp,            & !  2
741                                   0.11_wp, 0.33_wp, 0.23_wp,            & !  3
742                                   0.11_wp, 0.33_wp, 0.23_wp,            & !  4
743                                   0.14_wp, 0.34_wp, 0.25_wp,            & !  5
744                                   0.06_wp, 0.22_wp, 0.14_wp,            & !  6
745                                   0.06_wp, 0.27_wp, 0.17_wp,            & !  7
746                                   0.06_wp, 0.31_wp, 0.19_wp,            & !  8
747                                   0.06_wp, 0.22_wp, 0.14_wp,            & !  9
748                                   0.06_wp, 0.28_wp, 0.18_wp,            & ! 10
749                                   0.35_wp, 0.51_wp, 0.43_wp,            & ! 11
750                                   0.24_wp, 0.40_wp, 0.32_wp,            & ! 12
751                                   0.10_wp, 0.27_wp, 0.19_wp,            & ! 13
752                                   0.90_wp, 0.65_wp, 0.77_wp,            & ! 14
753                                   0.90_wp, 0.65_wp, 0.77_wp,            & ! 15
754                                   0.95_wp, 0.70_wp, 0.82_wp,            & ! 16
755                                   0.08_wp, 0.08_wp, 0.08_wp,            & ! 17
756                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 18
757                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 19
758                                   0.30_wp, 0.30_wp, 0.30_wp,            & ! 20
759                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 21
760                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 22
761                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 23
762                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 24
763                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 25
764                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 26
765                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 27
766                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 28
767                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 29
768                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 30
769                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 31
770                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 32
771                                   0.17_wp, 0.17_wp, 0.17_wp             & ! 33
772                                 /), (/ 3, 33 /) )
773
774    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE, TARGET :: &
775                        rad_lw_cs_hr,                  & !< longwave clear sky radiation heating rate (K/s)
776                        rad_lw_cs_hr_av,               & !< average of rad_lw_cs_hr
777                        rad_lw_hr,                     & !< longwave radiation heating rate (K/s)
778                        rad_lw_hr_av,                  & !< average of rad_sw_hr
779                        rad_lw_in,                     & !< incoming longwave radiation (W/m2)
780                        rad_lw_in_av,                  & !< average of rad_lw_in
781                        rad_lw_out,                    & !< outgoing longwave radiation (W/m2)
782                        rad_lw_out_av,                 & !< average of rad_lw_out
783                        rad_sw_cs_hr,                  & !< shortwave clear sky radiation heating rate (K/s)
784                        rad_sw_cs_hr_av,               & !< average of rad_sw_cs_hr
785                        rad_sw_hr,                     & !< shortwave radiation heating rate (K/s)
786                        rad_sw_hr_av,                  & !< average of rad_sw_hr
787                        rad_sw_in,                     & !< incoming shortwave radiation (W/m2)
788                        rad_sw_in_av,                  & !< average of rad_sw_in
789                        rad_sw_out,                    & !< outgoing shortwave radiation (W/m2)
790                        rad_sw_out_av                    !< average of rad_sw_out
791
792
793!
794!-- Variables and parameters used in RRTMG only
795#if defined ( __rrtmg )
796    CHARACTER(LEN=12) :: rrtm_input_file = "RAD_SND_DATA" !< name of the NetCDF input file (sounding data)
797
798
799!
800!-- Flag parameters for RRTMGS (should not be changed)
801    INTEGER(iwp), PARAMETER :: rrtm_idrv     = 1, & !< flag for longwave upward flux calculation option (0,1)
802                               rrtm_inflglw  = 2, & !< flag for lw cloud optical properties (0,1,2)
803                               rrtm_iceflglw = 0, & !< flag for lw ice particle specifications (0,1,2,3)
804                               rrtm_liqflglw = 1, & !< flag for lw liquid droplet specifications
805                               rrtm_inflgsw  = 2, & !< flag for sw cloud optical properties (0,1,2)
806                               rrtm_iceflgsw = 0, & !< flag for sw ice particle specifications (0,1,2,3)
807                               rrtm_liqflgsw = 1    !< flag for sw liquid droplet specifications
808
809!
810!-- The following variables should be only changed with care, as this will
811!-- require further setting of some variables, which is currently not
812!-- implemented (aerosols, ice phase).
813    INTEGER(iwp) :: nzt_rad,           & !< upper vertical limit for radiation calculations
814                    rrtm_icld = 0,     & !< cloud flag (0: clear sky column, 1: cloudy column)
815                    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)
816
817    INTEGER(iwp) :: nc_stat !< local variable for storin the result of netCDF calls for error message handling
818
819    LOGICAL :: snd_exists = .FALSE.      !< flag parameter to check whether a user-defined input files exists
820    LOGICAL :: sw_exists = .FALSE.       !< flag parameter to check whether that required rrtmg sw file exists
821    LOGICAL :: lw_exists = .FALSE.       !< flag parameter to check whether that required rrtmg lw file exists
822
823
824    REAL(wp), PARAMETER :: mol_mass_air_d_wv = 1.607793_wp !< molecular weight dry air / water vapor
825
826    REAL(wp), DIMENSION(:), ALLOCATABLE :: hyp_snd,     & !< hypostatic pressure from sounding data (hPa)
827                                           rrtm_tsfc,   & !< dummy array for storing surface temperature
828                                           t_snd          !< actual temperature from sounding data (hPa)
829
830    REAL(wp), DIMENSION(:,:), ALLOCATABLE :: rrtm_ccl4vmr,   & !< CCL4 volume mixing ratio (g/mol)
831                                             rrtm_cfc11vmr,  & !< CFC11 volume mixing ratio (g/mol)
832                                             rrtm_cfc12vmr,  & !< CFC12 volume mixing ratio (g/mol)
833                                             rrtm_cfc22vmr,  & !< CFC22 volume mixing ratio (g/mol)
834                                             rrtm_ch4vmr,    & !< CH4 volume mixing ratio
835                                             rrtm_cicewp,    & !< in-cloud ice water path (g/m2)
836                                             rrtm_cldfr,     & !< cloud fraction (0,1)
837                                             rrtm_cliqwp,    & !< in-cloud liquid water path (g/m2)
838                                             rrtm_co2vmr,    & !< CO2 volume mixing ratio (g/mol)
839                                             rrtm_emis,      & !< surface emissivity (0-1) 
840                                             rrtm_h2ovmr,    & !< H2O volume mixing ratio
841                                             rrtm_n2ovmr,    & !< N2O volume mixing ratio
842                                             rrtm_o2vmr,     & !< O2 volume mixing ratio
843                                             rrtm_o3vmr,     & !< O3 volume mixing ratio
844                                             rrtm_play,      & !< pressure layers (hPa, zu-grid)
845                                             rrtm_plev,      & !< pressure layers (hPa, zw-grid)
846                                             rrtm_reice,     & !< cloud ice effective radius (microns)
847                                             rrtm_reliq,     & !< cloud water drop effective radius (microns)
848                                             rrtm_tlay,      & !< actual temperature (K, zu-grid)
849                                             rrtm_tlev,      & !< actual temperature (K, zw-grid)
850                                             rrtm_lwdflx,    & !< RRTM output of incoming longwave radiation flux (W/m2)
851                                             rrtm_lwdflxc,   & !< RRTM output of outgoing clear sky longwave radiation flux (W/m2)
852                                             rrtm_lwuflx,    & !< RRTM output of outgoing longwave radiation flux (W/m2)
853                                             rrtm_lwuflxc,   & !< RRTM output of incoming clear sky longwave radiation flux (W/m2)
854                                             rrtm_lwuflx_dt, & !< RRTM output of incoming clear sky longwave radiation flux (W/m2)
855                                             rrtm_lwuflxc_dt,& !< RRTM output of outgoing clear sky longwave radiation flux (W/m2)
856                                             rrtm_lwhr,      & !< RRTM output of longwave radiation heating rate (K/d)
857                                             rrtm_lwhrc,     & !< RRTM output of incoming longwave clear sky radiation heating rate (K/d)
858                                             rrtm_swdflx,    & !< RRTM output of incoming shortwave radiation flux (W/m2)
859                                             rrtm_swdflxc,   & !< RRTM output of outgoing clear sky shortwave radiation flux (W/m2)
860                                             rrtm_swuflx,    & !< RRTM output of outgoing shortwave radiation flux (W/m2)
861                                             rrtm_swuflxc,   & !< RRTM output of incoming clear sky shortwave radiation flux (W/m2)
862                                             rrtm_swhr,      & !< RRTM output of shortwave radiation heating rate (K/d)
863                                             rrtm_swhrc,     & !< RRTM output of incoming shortwave clear sky radiation heating rate (K/d)
864                                             rrtm_dirdflux,  & !< RRTM output of incoming direct shortwave (W/m2)
865                                             rrtm_difdflux     !< RRTM output of incoming diffuse shortwave (W/m2)
866
867    REAL(wp), DIMENSION(1) ::                rrtm_aldif,     & !< surface albedo for longwave diffuse radiation
868                                             rrtm_aldir,     & !< surface albedo for longwave direct radiation
869                                             rrtm_asdif,     & !< surface albedo for shortwave diffuse radiation
870                                             rrtm_asdir        !< surface albedo for shortwave direct radiation
871
872!
873!-- Definition of arrays that are currently not used for calling RRTMG (due to setting of flag parameters)
874    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::  rad_lw_cs_in,   & !< incoming clear sky longwave radiation (W/m2) (not used)
875                                                rad_lw_cs_out,  & !< outgoing clear sky longwave radiation (W/m2) (not used)
876                                                rad_sw_cs_in,   & !< incoming clear sky shortwave radiation (W/m2) (not used)
877                                                rad_sw_cs_out,  & !< outgoing clear sky shortwave radiation (W/m2) (not used)
878                                                rrtm_lw_tauaer, & !< lw aerosol optical depth
879                                                rrtm_lw_taucld, & !< lw in-cloud optical depth
880                                                rrtm_sw_taucld, & !< sw in-cloud optical depth
881                                                rrtm_sw_ssacld, & !< sw in-cloud single scattering albedo
882                                                rrtm_sw_asmcld, & !< sw in-cloud asymmetry parameter
883                                                rrtm_sw_fsfcld, & !< sw in-cloud forward scattering fraction
884                                                rrtm_sw_tauaer, & !< sw aerosol optical depth
885                                                rrtm_sw_ssaaer, & !< sw aerosol single scattering albedo
886                                                rrtm_sw_asmaer, & !< sw aerosol asymmetry parameter
887                                                rrtm_sw_ecaer     !< sw aerosol optical detph at 0.55 microns (rrtm_iaer = 6 only)
888
889#endif
890!
891!-- Parameters of urban and land surface models
892    INTEGER(iwp)                                   ::  nzu                                !< number of layers of urban surface (will be calculated)
893    INTEGER(iwp)                                   ::  nzp                                !< number of layers of plant canopy (will be calculated)
894    INTEGER(iwp)                                   ::  nzub,nzut                          !< bottom and top layer of urban surface (will be calculated)
895    INTEGER(iwp)                                   ::  nzpt                               !< top layer of plant canopy (will be calculated)
896!-- parameters of urban and land surface models
897    INTEGER(iwp), PARAMETER                        ::  nzut_free = 3                      !< number of free layers above top of of topography
898    INTEGER(iwp), PARAMETER                        ::  ndsvf = 2                          !< number of dimensions of real values in SVF
899    INTEGER(iwp), PARAMETER                        ::  idsvf = 2                          !< number of dimensions of integer values in SVF
900    INTEGER(iwp), PARAMETER                        ::  ndcsf = 1                          !< number of dimensions of real values in CSF
901    INTEGER(iwp), PARAMETER                        ::  idcsf = 2                          !< number of dimensions of integer values in CSF
902    INTEGER(iwp), PARAMETER                        ::  kdcsf = 4                          !< number of dimensions of integer values in CSF calculation array
903    INTEGER(iwp), PARAMETER                        ::  id = 1                             !< position of d-index in surfl and surf
904    INTEGER(iwp), PARAMETER                        ::  iz = 2                             !< position of k-index in surfl and surf
905    INTEGER(iwp), PARAMETER                        ::  iy = 3                             !< position of j-index in surfl and surf
906    INTEGER(iwp), PARAMETER                        ::  ix = 4                             !< position of i-index in surfl and surf
907
908    INTEGER(iwp), PARAMETER                        ::  nsurf_type = 10                    !< number of surf types incl. phys.(land+urban) & (atm.,sky,boundary) surfaces - 1
909
910    INTEGER(iwp), PARAMETER                        ::  iup_u    = 0                       !< 0 - index of urban upward surface (ground or roof)
911    INTEGER(iwp), PARAMETER                        ::  idown_u  = 1                       !< 1 - index of urban downward surface (overhanging)
912    INTEGER(iwp), PARAMETER                        ::  inorth_u = 2                       !< 2 - index of urban northward facing wall
913    INTEGER(iwp), PARAMETER                        ::  isouth_u = 3                       !< 3 - index of urban southward facing wall
914    INTEGER(iwp), PARAMETER                        ::  ieast_u  = 4                       !< 4 - index of urban eastward facing wall
915    INTEGER(iwp), PARAMETER                        ::  iwest_u  = 5                       !< 5 - index of urban westward facing wall
916
917    INTEGER(iwp), PARAMETER                        ::  iup_l    = 6                       !< 6 - index of land upward surface (ground or roof)
918    INTEGER(iwp), PARAMETER                        ::  inorth_l = 7                       !< 7 - index of land northward facing wall
919    INTEGER(iwp), PARAMETER                        ::  isouth_l = 8                       !< 8 - index of land southward facing wall
920    INTEGER(iwp), PARAMETER                        ::  ieast_l  = 9                       !< 9 - index of land eastward facing wall
921    INTEGER(iwp), PARAMETER                        ::  iwest_l  = 10                      !< 10- index of land westward facing wall
922
923    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  idir = (/0, 0,0, 0,1,-1,0,0, 0,1,-1/)   !< surface normal direction x indices
924    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  jdir = (/0, 0,1,-1,0, 0,0,1,-1,0, 0/)   !< surface normal direction y indices
925    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  kdir = (/1,-1,0, 0,0, 0,1,0, 0,0, 0/)   !< surface normal direction z indices
926    REAL(wp),     DIMENSION(0:nsurf_type)          :: facearea                            !< area of single face in respective
927                                                                                          !< direction (will be calc'd)
928
929
930!-- indices and sizes of urban and land surface models
931    INTEGER(iwp)                                   ::  startland        !< start index of block of land and roof surfaces
932    INTEGER(iwp)                                   ::  endland          !< end index of block of land and roof surfaces
933    INTEGER(iwp)                                   ::  nlands           !< number of land and roof surfaces in local processor
934    INTEGER(iwp)                                   ::  startwall        !< start index of block of wall surfaces
935    INTEGER(iwp)                                   ::  endwall          !< end index of block of wall surfaces
936    INTEGER(iwp)                                   ::  nwalls           !< number of wall surfaces in local processor
937
938!-- indices needed for RTM netcdf output subroutines
939    INTEGER(iwp), PARAMETER                        :: nd = 5
940    CHARACTER(LEN=6), DIMENSION(0:nd-1), PARAMETER :: dirname = (/ '_roof ', '_south', '_north', '_west ', '_east ' /)
941    INTEGER(iwp), DIMENSION(0:nd-1), PARAMETER     :: dirint_u = (/ iup_u, isouth_u, inorth_u, iwest_u, ieast_u /)
942    INTEGER(iwp), DIMENSION(0:nd-1), PARAMETER     :: dirint_l = (/ iup_l, isouth_l, inorth_l, iwest_l, ieast_l /)
943    INTEGER(iwp), DIMENSION(0:nd-1)                :: dirstart
944    INTEGER(iwp), DIMENSION(0:nd-1)                :: dirend
945
946!-- indices and sizes of urban and land surface models
947    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surfl_l          !< coordinates of i-th local surface in local grid - surfl[:,k] = [d, z, y, x]
948    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surf_l           !< coordinates of i-th surface in grid - surf[:,k] = [d, z, y, x]
949    INTEGER(iwp), DIMENSION(:,:), POINTER          ::  surfl            !< coordinates of i-th local surface in local grid - surfl[:,k] = [d, z, y, x]
950    INTEGER(iwp), DIMENSION(:,:), POINTER          ::  surf             !< coordinates of i-th surface in grid - surf[:,k] = [d, z, y, x]
951    INTEGER(iwp)                                   ::  nsurfl           !< number of all surfaces in local processor
952    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  nsurfs           !< array of number of all surfaces in individual processors
953    INTEGER(iwp)                                   ::  nsurf            !< global number of surfaces in index array of surfaces (nsurf = proc nsurfs)
954    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surfstart        !< starts of blocks of surfaces for individual processors in array surf (indexed from 1)
955                                                                        !< respective block for particular processor is surfstart[iproc+1]+1 : surfstart[iproc+1]+nsurfs[iproc+1]
956
957!-- block variables needed for calculation of the plant canopy model inside the urban surface model
958    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pct              !< top layer of the plant canopy
959    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pch              !< heights of the plant canopy
960    INTEGER(iwp)                                   ::  npcbl = 0        !< number of the plant canopy gridboxes in local processor
961    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pcbl             !< k,j,i coordinates of l-th local plant canopy box pcbl[:,l] = [k, j, i]
962    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinsw          !< array of absorbed sw radiation for local plant canopy box
963    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdir       !< array of absorbed direct sw radiation for local plant canopy box
964    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdif       !< array of absorbed diffusion sw radiation for local plant canopy box
965    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinlw          !< array of absorbed lw radiation for local plant canopy box
966
967!-- configuration parameters (they can be setup in PALM config)
968    LOGICAL                                        ::  raytrace_mpi_rma = .TRUE.          !< use MPI RMA to access LAD and gridsurf from remote processes during raytracing
969    LOGICAL                                        ::  rad_angular_discretization = .TRUE.!< whether to use fixed resolution discretization of view factors for
970                                                                                          !< reflected radiation (as opposed to all mutually visible pairs)
971    LOGICAL                                        ::  plant_lw_interact = .TRUE.         !< whether plant canopy interacts with LW radiation (in addition to SW)
972    INTEGER(iwp)                                   ::  mrt_nlevels = 0                    !< number of vertical boxes above surface for which to calculate MRT
973    LOGICAL                                        ::  mrt_skip_roof = .TRUE.             !< do not calculate MRT above roof surfaces
974    LOGICAL                                        ::  mrt_include_sw = .TRUE.            !< should MRT calculation include SW radiation as well?
975    LOGICAL                                        ::  mrt_geom_human = .TRUE.            !< MRT direction weights simulate human body instead of a sphere
976    INTEGER(iwp)                                   ::  nrefsteps = 3                      !< number of reflection steps to perform
977    REAL(wp), PARAMETER                            ::  ext_coef = 0.6_wp                  !< extinction coefficient (a.k.a. alpha)
978    INTEGER(iwp), PARAMETER                        ::  rad_version_len = 10               !< length of identification string of rad version
979    CHARACTER(rad_version_len), PARAMETER          ::  rad_version = 'RAD v. 3.0'         !< identification of version of binary svf and restart files
980    INTEGER(iwp)                                   ::  raytrace_discrete_elevs = 40       !< number of discretization steps for elevation (nadir to zenith)
981    INTEGER(iwp)                                   ::  raytrace_discrete_azims = 80       !< number of discretization steps for azimuth (out of 360 degrees)
982    REAL(wp)                                       ::  max_raytracing_dist = -999.0_wp    !< maximum distance for raytracing (in metres)
983    REAL(wp)                                       ::  min_irrf_value = 1e-6_wp           !< minimum potential irradiance factor value for raytracing
984    REAL(wp), DIMENSION(1:30)                      ::  svfnorm_report_thresh = 1e21_wp    !< thresholds of SVF normalization values to report
985    INTEGER(iwp)                                   ::  svfnorm_report_num                 !< number of SVF normalization thresholds to report
986
987!-- radiation related arrays to be used in radiation_interaction routine
988    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_sw_in_dir    !< direct sw radiation
989    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_sw_in_diff   !< diffusion sw radiation
990    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_lw_in_diff   !< diffusion lw radiation
991
992!-- parameters required for RRTMG lower boundary condition
993    REAL(wp)                   :: albedo_urb      !< albedo value retuned to RRTMG boundary cond.
994    REAL(wp)                   :: emissivity_urb  !< emissivity value retuned to RRTMG boundary cond.
995    REAL(wp)                   :: t_rad_urb       !< temperature value retuned to RRTMG boundary cond.
996
997!-- type for calculation of svf
998    TYPE t_svf
999        INTEGER(iwp)                               :: isurflt           !<
1000        INTEGER(iwp)                               :: isurfs            !<
1001        REAL(wp)                                   :: rsvf              !<
1002        REAL(wp)                                   :: rtransp           !<
1003    END TYPE
1004
1005!-- type for calculation of csf
1006    TYPE t_csf
1007        INTEGER(iwp)                               :: ip                !<
1008        INTEGER(iwp)                               :: itx               !<
1009        INTEGER(iwp)                               :: ity               !<
1010        INTEGER(iwp)                               :: itz               !<
1011        INTEGER(iwp)                               :: isurfs            !< Idx of source face / -1 for sky
1012        REAL(wp)                                   :: rcvf              !< Canopy view factor for faces /
1013                                                                        !< canopy sink factor for sky (-1)
1014    END TYPE
1015
1016!-- arrays storing the values of USM
1017    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  svfsurf          !< svfsurf[:,isvf] = index of target and source surface for svf[isvf]
1018    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  svf              !< array of shape view factors+direct irradiation factors for local surfaces
1019    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfins          !< array of sw radiation falling to local surface after i-th reflection
1020    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinl          !< array of lw radiation for local surface after i-th reflection
1021
1022    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  skyvf            !< array of sky view factor for each local surface
1023    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  skyvft           !< array of sky view factor including transparency for each local surface
1024    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsitrans         !< dsidir[isvfl,i] = path transmittance of i-th
1025                                                                        !< direction of direct solar irradiance per target surface
1026    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsitransc        !< dtto per plant canopy box
1027    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsidir           !< dsidir[:,i] = unit vector of i-th
1028                                                                        !< direction of direct solar irradiance
1029    INTEGER(iwp)                                   ::  ndsidir          !< number of apparent solar directions used
1030    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  dsidir_rev       !< dsidir_rev[ielev,iazim] = i for dsidir or -1 if not present
1031
1032    INTEGER(iwp)                                   ::  nmrtbl           !< No. of local grid boxes for which MRT is calculated
1033    INTEGER(iwp)                                   ::  nmrtf            !< number of MRT factors for local processor
1034    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  mrtbl            !< coordinates of i-th local MRT box - surfl[:,i] = [z, y, x]
1035    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  mrtfsurf         !< mrtfsurf[:,imrtf] = index of target MRT box and source surface for mrtf[imrtf]
1036    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtf             !< array of MRT factors for each local MRT box
1037    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtft            !< array of MRT factors including transparency for each local MRT box
1038    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtsky           !< array of sky view factor for each local MRT box
1039    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtskyt          !< array of sky view factor including transparency for each local MRT box
1040    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  mrtdsit          !< array of direct solar transparencies for each local MRT box
1041    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinsw          !< mean SW radiant flux for each MRT box
1042    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinlw          !< mean LW radiant flux for each MRT box
1043    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrt              !< mean radiant temperature for each MRT box
1044    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinsw_av       !< time average mean SW radiant flux for each MRT box
1045    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinlw_av       !< time average mean LW radiant flux for each MRT box
1046    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrt_av           !< time average mean radiant temperature for each MRT box
1047
1048    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinsw         !< array of sw radiation falling to local surface including radiation from reflections
1049    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlw         !< array of lw radiation falling to local surface including radiation from reflections
1050    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdir      !< array of direct sw radiation falling to local surface
1051    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdif      !< array of diffuse sw radiation from sky and model boundary falling to local surface
1052    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwdif      !< array of diffuse lw radiation from sky and model boundary falling to local surface
1053   
1054                                                                        !< Outward radiation is only valid for nonvirtual surfaces
1055    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsl        !< array of reflected sw radiation for local surface in i-th reflection
1056    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutll        !< array of reflected + emitted lw radiation for local surface in i-th reflection
1057    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfouts         !< array of reflected sw radiation for all surfaces in i-th reflection
1058    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutl         !< array of reflected + emitted lw radiation for all surfaces in i-th reflection
1059    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlg         !< global array of incoming lw radiation from plant canopy
1060    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsw        !< array of total sw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1061    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutlw        !< array of total lw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1062    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfemitlwl      !< array of emitted lw radiation for local surface used to calculate effective surface temperature for radiation model
1063
1064!-- block variables needed for calculation of the plant canopy model inside the urban surface model
1065    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  csfsurf          !< csfsurf[:,icsf] = index of target surface and csf grid index for csf[icsf]
1066    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  csf              !< array of plant canopy sink fators + direct irradiation factors (transparency)
1067    REAL(wp), DIMENSION(:,:,:), POINTER            ::  sub_lad          !< subset of lad_s within urban surface, transformed to plain Z coordinate
1068    REAL(wp), DIMENSION(:), POINTER                ::  sub_lad_g        !< sub_lad globalized (used to avoid MPI RMA calls in raytracing)
1069    REAL(wp)                                       ::  prototype_lad    !< prototype leaf area density for computing effective optical depth
1070    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  nzterr, plantt   !< temporary global arrays for raytracing
1071    INTEGER(iwp)                                   ::  plantt_max
1072
1073!-- arrays and variables for calculation of svf and csf
1074    TYPE(t_svf), DIMENSION(:), POINTER             ::  asvf             !< pointer to growing svc array
1075    TYPE(t_csf), DIMENSION(:), POINTER             ::  acsf             !< pointer to growing csf array
1076    TYPE(t_svf), DIMENSION(:), POINTER             ::  amrtf            !< pointer to growing mrtf array
1077    TYPE(t_svf), DIMENSION(:), ALLOCATABLE, TARGET ::  asvf1, asvf2     !< realizations of svf array
1078    TYPE(t_csf), DIMENSION(:), ALLOCATABLE, TARGET ::  acsf1, acsf2     !< realizations of csf array
1079    TYPE(t_svf), DIMENSION(:), ALLOCATABLE, TARGET ::  amrtf1, amrtf2   !< realizations of mftf array
1080    INTEGER(iwp)                                   ::  nsvfla           !< dimmension of array allocated for storage of svf in local processor
1081    INTEGER(iwp)                                   ::  ncsfla           !< dimmension of array allocated for storage of csf in local processor
1082    INTEGER(iwp)                                   ::  nmrtfa           !< dimmension of array allocated for storage of mrt
1083    INTEGER(iwp)                                   ::  msvf, mcsf, mmrtf!< mod for swapping the growing array
1084    INTEGER(iwp), PARAMETER                        ::  gasize = 100000  !< initial size of growing arrays
1085    REAL(wp), PARAMETER                            ::  grow_factor = 1.4_wp !< growth factor of growing arrays
1086    INTEGER(iwp)                                   ::  nsvfl            !< number of svf for local processor
1087    INTEGER(iwp)                                   ::  ncsfl            !< no. of csf in local processor
1088                                                                        !< needed only during calc_svf but must be here because it is
1089                                                                        !< shared between subroutines calc_svf and raytrace
1090    INTEGER(iwp), DIMENSION(:,:,:,:), POINTER      ::  gridsurf         !< reverse index of local surfl[d,k,j,i] (for case rad_angular_discretization)
1091    INTEGER(iwp), DIMENSION(:,:,:), ALLOCATABLE    ::  gridpcbl         !< reverse index of local pcbl[k,j,i]
1092    INTEGER(iwp), PARAMETER                        ::  nsurf_type_u = 6 !< number of urban surf types (used in gridsurf)
1093
1094!-- temporary arrays for calculation of csf in raytracing
1095    INTEGER(iwp)                                   ::  maxboxesg        !< max number of boxes ray can cross in the domain
1096    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  boxes            !< coordinates of gridboxes being crossed by ray
1097    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  crlens           !< array of crossing lengths of ray for particular grid boxes
1098    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  lad_ip           !< array of numbers of process where lad is stored
1099#if defined( __parallel )
1100    INTEGER(kind=MPI_ADDRESS_KIND), &
1101                  DIMENSION(:), ALLOCATABLE        ::  lad_disp         !< array of displaycements of lad in local array of proc lad_ip
1102    INTEGER(iwp)                                   ::  win_lad          !< MPI RMA window for leaf area density
1103    INTEGER(iwp)                                   ::  win_gridsurf     !< MPI RMA window for reverse grid surface index
1104#endif
1105    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  lad_s_ray        !< array of received lad_s for appropriate gridboxes crossed by ray
1106    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  target_surfl
1107    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  rt2_track
1108    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rt2_track_lad
1109    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  rt2_track_dist
1110    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  rt2_dist
1111
1112!-- arrays for time averages
1113    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfradnet_av    !< average of net radiation to local surface including radiation from reflections
1114    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinsw_av      !< average of sw radiation falling to local surface including radiation from reflections
1115    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlw_av      !< average of lw radiation falling to local surface including radiation from reflections
1116    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdir_av   !< average of direct sw radiation falling to local surface
1117    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdif_av   !< average of diffuse sw radiation from sky and model boundary falling to local surface
1118    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwdif_av   !< average of diffuse lw radiation from sky and model boundary falling to local surface
1119    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswref_av   !< average of sw radiation falling to surface from reflections
1120    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwref_av   !< average of lw radiation falling to surface from reflections
1121    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsw_av     !< average of total sw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1122    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutlw_av     !< average of total lw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1123    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfins_av       !< average of array of residua of sw radiation absorbed in surface after last reflection
1124    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinl_av       !< average of array of residua of lw radiation absorbed in surface after last reflection
1125    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinlw_av       !< Average of pcbinlw
1126    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinsw_av       !< Average of pcbinsw
1127    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdir_av    !< Average of pcbinswdir
1128    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdif_av    !< Average of pcbinswdif
1129    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswref_av    !< Average of pcbinswref
1130
1131
1132!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1133!-- Energy balance variables
1134!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1135!-- parameters of the land, roof and wall surfaces
1136    REAL(wp), DIMENSION(:), ALLOCATABLE            :: albedo_surf        !< albedo of the surface
1137    REAL(wp), DIMENSION(:), ALLOCATABLE            :: emiss_surf         !< emissivity of the wall surface
1138
1139
1140    INTERFACE radiation_check_data_output
1141       MODULE PROCEDURE radiation_check_data_output
1142    END INTERFACE radiation_check_data_output
1143
1144    INTERFACE radiation_check_data_output_ts
1145       MODULE PROCEDURE radiation_check_data_output_ts
1146    END INTERFACE radiation_check_data_output_ts
1147
1148    INTERFACE radiation_check_data_output_pr
1149       MODULE PROCEDURE radiation_check_data_output_pr
1150    END INTERFACE radiation_check_data_output_pr
1151 
1152    INTERFACE radiation_check_parameters
1153       MODULE PROCEDURE radiation_check_parameters
1154    END INTERFACE radiation_check_parameters
1155 
1156    INTERFACE radiation_clearsky
1157       MODULE PROCEDURE radiation_clearsky
1158    END INTERFACE radiation_clearsky
1159 
1160    INTERFACE radiation_constant
1161       MODULE PROCEDURE radiation_constant
1162    END INTERFACE radiation_constant
1163 
1164    INTERFACE radiation_control
1165       MODULE PROCEDURE radiation_control
1166    END INTERFACE radiation_control
1167
1168    INTERFACE radiation_3d_data_averaging
1169       MODULE PROCEDURE radiation_3d_data_averaging
1170    END INTERFACE radiation_3d_data_averaging
1171
1172    INTERFACE radiation_data_output_2d
1173       MODULE PROCEDURE radiation_data_output_2d
1174    END INTERFACE radiation_data_output_2d
1175
1176    INTERFACE radiation_data_output_3d
1177       MODULE PROCEDURE radiation_data_output_3d
1178    END INTERFACE radiation_data_output_3d
1179
1180    INTERFACE radiation_data_output_mask
1181       MODULE PROCEDURE radiation_data_output_mask
1182    END INTERFACE radiation_data_output_mask
1183
1184    INTERFACE radiation_define_netcdf_grid
1185       MODULE PROCEDURE radiation_define_netcdf_grid
1186    END INTERFACE radiation_define_netcdf_grid
1187
1188    INTERFACE radiation_header
1189       MODULE PROCEDURE radiation_header
1190    END INTERFACE radiation_header 
1191 
1192    INTERFACE radiation_init
1193       MODULE PROCEDURE radiation_init
1194    END INTERFACE radiation_init
1195
1196    INTERFACE radiation_parin
1197       MODULE PROCEDURE radiation_parin
1198    END INTERFACE radiation_parin
1199   
1200    INTERFACE radiation_rrtmg
1201       MODULE PROCEDURE radiation_rrtmg
1202    END INTERFACE radiation_rrtmg
1203
1204    INTERFACE radiation_tendency
1205       MODULE PROCEDURE radiation_tendency
1206       MODULE PROCEDURE radiation_tendency_ij
1207    END INTERFACE radiation_tendency
1208
1209    INTERFACE radiation_rrd_local
1210       MODULE PROCEDURE radiation_rrd_local
1211    END INTERFACE radiation_rrd_local
1212
1213    INTERFACE radiation_wrd_local
1214       MODULE PROCEDURE radiation_wrd_local
1215    END INTERFACE radiation_wrd_local
1216
1217    INTERFACE radiation_interaction
1218       MODULE PROCEDURE radiation_interaction
1219    END INTERFACE radiation_interaction
1220
1221    INTERFACE radiation_interaction_init
1222       MODULE PROCEDURE radiation_interaction_init
1223    END INTERFACE radiation_interaction_init
1224 
1225    INTERFACE radiation_presimulate_solar_pos
1226       MODULE PROCEDURE radiation_presimulate_solar_pos
1227    END INTERFACE radiation_presimulate_solar_pos
1228
1229    INTERFACE radiation_radflux_gridbox
1230       MODULE PROCEDURE radiation_radflux_gridbox
1231    END INTERFACE radiation_radflux_gridbox
1232
1233    INTERFACE radiation_calc_svf
1234       MODULE PROCEDURE radiation_calc_svf
1235    END INTERFACE radiation_calc_svf
1236
1237    INTERFACE radiation_write_svf
1238       MODULE PROCEDURE radiation_write_svf
1239    END INTERFACE radiation_write_svf
1240
1241    INTERFACE radiation_read_svf
1242       MODULE PROCEDURE radiation_read_svf
1243    END INTERFACE radiation_read_svf
1244
1245
1246    SAVE
1247
1248    PRIVATE
1249
1250!
1251!-- Public functions / NEEDS SORTING
1252    PUBLIC radiation_check_data_output, radiation_check_data_output_pr,        &
1253           radiation_check_data_output_ts,                                     &
1254           radiation_check_parameters, radiation_control,                      &
1255           radiation_header, radiation_init, radiation_parin,                  &
1256           radiation_3d_data_averaging, radiation_tendency,                    &
1257           radiation_data_output_2d, radiation_data_output_3d,                 &
1258           radiation_define_netcdf_grid, radiation_wrd_local,                  &
1259           radiation_rrd_local, radiation_data_output_mask,                    &
1260           radiation_radflux_gridbox, radiation_calc_svf, radiation_write_svf, &
1261           radiation_interaction, radiation_interaction_init,                  &
1262           radiation_read_svf, radiation_presimulate_solar_pos
1263           
1264
1265   
1266!
1267!-- Public variables and constants / NEEDS SORTING
1268    PUBLIC albedo, albedo_type, decl_1, decl_2, decl_3, dots_rad, dt_radiation,&
1269           emissivity, force_radiation_call, lat, lon, mrt_geom_human,         &
1270           mrt_include_sw, mrt_nlevels, mrtbl, mrtinsw, mrtinlw, nmrtbl,       &
1271           rad_net_av, radiation, radiation_scheme, rad_lw_in,                 &
1272           rad_lw_in_av, rad_lw_out, rad_lw_out_av,                            &
1273           rad_lw_cs_hr, rad_lw_cs_hr_av, rad_lw_hr, rad_lw_hr_av, rad_sw_in,  &
1274           rad_sw_in_av, rad_sw_out, rad_sw_out_av, rad_sw_cs_hr,              &
1275           rad_sw_cs_hr_av, rad_sw_hr, rad_sw_hr_av, sigma_sb, solar_constant, &
1276           skip_time_do_radiation, time_radiation, unscheduled_radiation_calls,&
1277           zenith, calc_zenith, sun_direction, sun_dir_lat, sun_dir_lon,       &
1278           idir, jdir, kdir, id, iz, iy, ix,                                   &
1279           iup_u, inorth_u, isouth_u, ieast_u, iwest_u,                        &
1280           iup_l, inorth_l, isouth_l, ieast_l, iwest_l,                        &
1281           nsurf_type, nzub, nzut, nzu, pch, nsurf,                            &
1282           idsvf, ndsvf, idcsf, ndcsf, kdcsf, pct,                             &
1283           radiation_interactions, startwall, startland, endland, endwall,     &
1284           skyvf, skyvft, radiation_interactions_on, average_radiation,        &
1285           rad_sw_in_diff, rad_sw_in_dir
1286
1287
1288#if defined ( __rrtmg )
1289    PUBLIC rrtm_aldif, rrtm_aldir, rrtm_asdif, rrtm_asdir
1290#endif
1291
1292 CONTAINS
1293
1294
1295!------------------------------------------------------------------------------!
1296! Description:
1297! ------------
1298!> This subroutine controls the calls of the radiation schemes
1299!------------------------------------------------------------------------------!
1300    SUBROUTINE radiation_control
1301 
1302 
1303       IMPLICIT NONE
1304
1305
1306       SELECT CASE ( TRIM( radiation_scheme ) )
1307
1308          CASE ( 'constant' )
1309             CALL radiation_constant
1310         
1311          CASE ( 'clear-sky' ) 
1312             CALL radiation_clearsky
1313       
1314          CASE ( 'rrtmg' )
1315             CALL radiation_rrtmg
1316
1317          CASE DEFAULT
1318
1319       END SELECT
1320
1321
1322    END SUBROUTINE radiation_control
1323
1324!------------------------------------------------------------------------------!
1325! Description:
1326! ------------
1327!> Check data output for radiation model
1328!------------------------------------------------------------------------------!
1329    SUBROUTINE radiation_check_data_output( variable, unit, i, ilen, k )
1330 
1331 
1332       USE control_parameters,                                                 &
1333           ONLY: data_output, message_string
1334
1335       IMPLICIT NONE
1336
1337       CHARACTER (LEN=*) ::  unit          !<
1338       CHARACTER (LEN=*) ::  variable      !<
1339
1340       INTEGER(iwp) :: i, j, k, l
1341       INTEGER(iwp) :: ilen
1342       CHARACTER(LEN=varnamelength) :: var          !< TRIM(variable)
1343
1344       var = TRIM(variable)
1345
1346!--    first process diractional variables
1347       IF ( var(1:12) == 'rtm_rad_net_'  .OR.  var(1:13) == 'rtm_rad_insw_'  .OR.        &
1348            var(1:13) == 'rtm_rad_inlw_'  .OR.  var(1:16) == 'rtm_rad_inswdir_'  .OR.    &
1349            var(1:16) == 'rtm_rad_inswdif_'  .OR.  var(1:16) == 'rtm_rad_inswref_'  .OR. &
1350            var(1:16) == 'rtm_rad_inlwdif_'  .OR.  var(1:16) == 'rtm_rad_inlwref_'  .OR. &
1351            var(1:14) == 'rtm_rad_outsw_'  .OR.  var(1:14) == 'rtm_rad_outlw_'  .OR.     &
1352            var(1:14) == 'rtm_rad_ressw_'  .OR.  var(1:14) == 'rtm_rad_reslw_'  ) THEN
1353          IF ( .NOT.  radiation ) THEN
1354                message_string = 'output of "' // TRIM( var ) // '" require'&
1355                                 // 's radiation = .TRUE.'
1356                CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1357          ENDIF
1358          unit = 'W/m2'
1359       ELSE IF ( var(1:7) == 'rtm_svf'  .OR.  var(1:7) == 'rtm_dif'  .OR.                &
1360                 var(1:9) == 'rtm_skyvf' .OR. var(1:9) == 'rtm_skyvft' )  THEN
1361          IF ( .NOT.  radiation ) THEN
1362                message_string = 'output of "' // TRIM( var ) // '" require'&
1363                                 // 's radiation = .TRUE.'
1364                CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1365          ENDIF
1366          unit = '1'
1367       ELSE
1368!--       non-directional variables
1369          SELECT CASE ( TRIM( var ) )
1370             CASE ( 'rad_lw_cs_hr', 'rad_lw_hr', 'rad_lw_in', 'rad_lw_out', &
1371                    'rad_sw_cs_hr', 'rad_sw_hr', 'rad_sw_in', 'rad_sw_out'  )
1372                IF (  .NOT.  radiation  .OR.  radiation_scheme /= 'rrtmg' )  THEN
1373                   message_string = '"output of "' // TRIM( var ) // '" requi' // &
1374                                    'res radiation = .TRUE. and ' //              &
1375                                    'radiation_scheme = "rrtmg"'
1376                   CALL message( 'check_parameters', 'PA0406', 1, 2, 0, 6, 0 )
1377                ENDIF
1378                unit = 'K/h'
1379
1380             CASE ( 'rad_net*', 'rrtm_aldif*', 'rrtm_aldir*', 'rrtm_asdif*',      &
1381                    'rrtm_asdir*', 'rad_lw_in*', 'rad_lw_out*', 'rad_sw_in*',     &
1382                    'rad_sw_out*')
1383                IF ( i == 0 .AND. ilen == 0 .AND. k == 0)  THEN
1384                   ! Workaround for masked output (calls with i=ilen=k=0)
1385                   unit = 'illegal'
1386                   RETURN
1387                ENDIF
1388                IF ( k == 0  .OR.  data_output(i)(ilen-2:ilen) /= '_xy' )  THEN
1389                   message_string = 'illegal value for data_output: "' //         &
1390                                    TRIM( var ) // '" & only 2d-horizontal ' //   &
1391                                    'cross sections are allowed for this value'
1392                   CALL message( 'check_parameters', 'PA0111', 1, 2, 0, 6, 0 )
1393                ENDIF
1394                IF (  .NOT.  radiation  .OR.  radiation_scheme /= "rrtmg" )  THEN
1395                   IF ( TRIM( var ) == 'rrtm_aldif*'  .OR.                        &
1396                        TRIM( var ) == 'rrtm_aldir*'  .OR.                        &
1397                        TRIM( var ) == 'rrtm_asdif*'  .OR.                        &
1398                        TRIM( var ) == 'rrtm_asdir*'      )                       &
1399                   THEN
1400                      message_string = 'output of "' // TRIM( var ) // '" require'&
1401                                       // 's radiation = .TRUE. and radiation_sch'&
1402                                       // 'eme = "rrtmg"'
1403                      CALL message( 'check_parameters', 'PA0409', 1, 2, 0, 6, 0 )
1404                   ENDIF
1405                ENDIF
1406
1407                IF ( TRIM( var ) == 'rad_net*'      ) unit = 'W/m2'
1408                IF ( TRIM( var ) == 'rad_lw_in*'    ) unit = 'W/m2'
1409                IF ( TRIM( var ) == 'rad_lw_out*'   ) unit = 'W/m2'
1410                IF ( TRIM( var ) == 'rad_sw_in*'    ) unit = 'W/m2'
1411                IF ( TRIM( var ) == 'rad_sw_out*'   ) unit = 'W/m2'
1412                IF ( TRIM( var ) == 'rad_sw_in'     ) unit = 'W/m2'
1413                IF ( TRIM( var ) == 'rrtm_aldif*'   ) unit = ''
1414                IF ( TRIM( var ) == 'rrtm_aldir*'   ) unit = ''
1415                IF ( TRIM( var ) == 'rrtm_asdif*'   ) unit = ''
1416                IF ( TRIM( var ) == 'rrtm_asdir*'   ) unit = ''
1417
1418             CASE ( 'rtm_rad_pc_inlw', 'rtm_rad_pc_insw', 'rtm_rad_pc_inswdir', &
1419                    'rtm_rad_pc_inswdif', 'rtm_rad_pc_inswref')
1420                IF ( .NOT.  radiation ) THEN
1421                   message_string = 'output of "' // TRIM( var ) // '" require'&
1422                                    // 's radiation = .TRUE.'
1423                   CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1424                ENDIF
1425                unit = 'W'
1426
1427             CASE ( 'rtm_mrt', 'rtm_mrt_sw', 'rtm_mrt_lw'  )
1428                IF ( i == 0 .AND. ilen == 0 .AND. k == 0)  THEN
1429                   ! Workaround for masked output (calls with i=ilen=k=0)
1430                   unit = 'illegal'
1431                   RETURN
1432                ENDIF
1433
1434                IF ( .NOT.  radiation ) THEN
1435                   message_string = 'output of "' // TRIM( var ) // '" require'&
1436                                    // 's radiation = .TRUE.'
1437                   CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1438                ENDIF
1439                IF ( mrt_nlevels == 0 ) THEN
1440                   message_string = 'output of "' // TRIM( var ) // '" require'&
1441                                    // 's mrt_nlevels > 0'
1442                   CALL message( 'check_parameters', 'PA0510', 1, 2, 0, 6, 0 )
1443                ENDIF
1444                IF ( TRIM( var ) == 'rtm_mrt_sw'  .AND.  .NOT. mrt_include_sw ) THEN
1445                   message_string = 'output of "' // TRIM( var ) // '" require'&
1446                                    // 's rtm_mrt_sw = .TRUE.'
1447                   CALL message( 'check_parameters', 'PA0511', 1, 2, 0, 6, 0 )
1448                ENDIF
1449                IF ( TRIM( var ) == 'rtm_mrt' ) THEN
1450                   unit = 'K'
1451                ELSE
1452                   unit = 'W m-2'
1453                ENDIF
1454
1455             CASE DEFAULT
1456                unit = 'illegal'
1457
1458          END SELECT
1459       ENDIF
1460
1461    END SUBROUTINE radiation_check_data_output
1462
1463
1464!------------------------------------------------------------------------------!
1465! Description:
1466! ------------
1467!> Set module-specific timeseries units and labels
1468!------------------------------------------------------------------------------!
1469 SUBROUTINE radiation_check_data_output_ts( dots_max, dots_num, dots_label, dots_unit )
1470
1471
1472   INTEGER(iwp),      INTENT(IN)     ::  dots_max
1473   INTEGER(iwp),      INTENT(INOUT)  ::  dots_num
1474   CHARACTER (LEN=*), DIMENSION(dots_max), INTENT(INOUT)  :: dots_label
1475   CHARACTER (LEN=*), DIMENSION(dots_max), INTENT(INOUT)  :: dots_unit
1476
1477!
1478!-- Temporary solution to add LSM and radiation time series to the default
1479!-- output
1480    IF ( land_surface  .OR.  radiation )  THEN
1481       IF ( TRIM( radiation_scheme ) == 'rrtmg' )  THEN
1482          dots_num = dots_num + 15
1483       ELSE
1484          dots_num = dots_num + 11
1485       ENDIF
1486    ENDIF
1487
1488
1489 END SUBROUTINE radiation_check_data_output_ts
1490
1491!------------------------------------------------------------------------------!
1492! Description:
1493! ------------
1494!> Check data output of profiles for radiation model
1495!------------------------------------------------------------------------------! 
1496    SUBROUTINE radiation_check_data_output_pr( variable, var_count, unit,      &
1497               dopr_unit )
1498 
1499       USE arrays_3d,                                                          &
1500           ONLY: zu
1501
1502       USE control_parameters,                                                 &
1503           ONLY: data_output_pr, message_string
1504
1505       USE indices
1506
1507       USE profil_parameter
1508
1509       USE statistics
1510
1511       IMPLICIT NONE
1512   
1513       CHARACTER (LEN=*) ::  unit      !<
1514       CHARACTER (LEN=*) ::  variable  !<
1515       CHARACTER (LEN=*) ::  dopr_unit !< local value of dopr_unit
1516 
1517       INTEGER(iwp) ::  var_count     !<
1518
1519       SELECT CASE ( TRIM( variable ) )
1520       
1521         CASE ( 'rad_net' )
1522             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme == 'constant' )&
1523             THEN
1524                message_string = 'data_output_pr = ' //                        &
1525                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1526                                 'not available for radiation = .FALSE. or ' //&
1527                                 'radiation_scheme = "constant"'
1528                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1529             ELSE
1530                dopr_index(var_count) = 99
1531                dopr_unit  = 'W/m2'
1532                hom(:,2,99,:)  = SPREAD( zw, 2, statistic_regions+1 )
1533                unit = dopr_unit
1534             ENDIF
1535
1536          CASE ( 'rad_lw_in' )
1537             IF ( (  .NOT.  radiation)  .OR.  radiation_scheme == 'constant' ) &
1538             THEN
1539                message_string = 'data_output_pr = ' //                        &
1540                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1541                                 'not available for radiation = .FALSE. or ' //&
1542                                 'radiation_scheme = "constant"'
1543                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1544             ELSE
1545                dopr_index(var_count) = 100
1546                dopr_unit  = 'W/m2'
1547                hom(:,2,100,:)  = SPREAD( zw, 2, statistic_regions+1 )
1548                unit = dopr_unit 
1549             ENDIF
1550
1551          CASE ( 'rad_lw_out' )
1552             IF ( (  .NOT. radiation )  .OR.  radiation_scheme == 'constant' ) &
1553             THEN
1554                message_string = 'data_output_pr = ' //                        &
1555                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1556                                 'not available for radiation = .FALSE. or ' //&
1557                                 'radiation_scheme = "constant"'
1558                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1559             ELSE
1560                dopr_index(var_count) = 101
1561                dopr_unit  = 'W/m2'
1562                hom(:,2,101,:)  = SPREAD( zw, 2, statistic_regions+1 )
1563                unit = dopr_unit   
1564             ENDIF
1565
1566          CASE ( 'rad_sw_in' )
1567             IF ( (  .NOT. radiation )  .OR.  radiation_scheme == 'constant' ) &
1568             THEN
1569                message_string = 'data_output_pr = ' //                        &
1570                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1571                                 'not available for radiation = .FALSE. or ' //&
1572                                 'radiation_scheme = "constant"'
1573                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1574             ELSE
1575                dopr_index(var_count) = 102
1576                dopr_unit  = 'W/m2'
1577                hom(:,2,102,:)  = SPREAD( zw, 2, statistic_regions+1 )
1578                unit = dopr_unit
1579             ENDIF
1580
1581          CASE ( 'rad_sw_out')
1582             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme == 'constant' )&
1583             THEN
1584                message_string = 'data_output_pr = ' //                        &
1585                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1586                                 'not available for radiation = .FALSE. or ' //&
1587                                 'radiation_scheme = "constant"'
1588                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1589             ELSE
1590                dopr_index(var_count) = 103
1591                dopr_unit  = 'W/m2'
1592                hom(:,2,103,:)  = SPREAD( zw, 2, statistic_regions+1 )
1593                unit = dopr_unit
1594             ENDIF
1595
1596          CASE ( 'rad_lw_cs_hr' )
1597             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1598             THEN
1599                message_string = 'data_output_pr = ' //                        &
1600                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1601                                 'not available for radiation = .FALSE. or ' //&
1602                                 'radiation_scheme /= "rrtmg"'
1603                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1604             ELSE
1605                dopr_index(var_count) = 104
1606                dopr_unit  = 'K/h'
1607                hom(:,2,104,:)  = SPREAD( zu, 2, statistic_regions+1 )
1608                unit = dopr_unit
1609             ENDIF
1610
1611          CASE ( 'rad_lw_hr' )
1612             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1613             THEN
1614                message_string = 'data_output_pr = ' //                        &
1615                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1616                                 'not available for radiation = .FALSE. or ' //&
1617                                 'radiation_scheme /= "rrtmg"'
1618                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1619             ELSE
1620                dopr_index(var_count) = 105
1621                dopr_unit  = 'K/h'
1622                hom(:,2,105,:)  = SPREAD( zu, 2, statistic_regions+1 )
1623                unit = dopr_unit
1624             ENDIF
1625
1626          CASE ( 'rad_sw_cs_hr' )
1627             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1628             THEN
1629                message_string = 'data_output_pr = ' //                        &
1630                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1631                                 'not available for radiation = .FALSE. or ' //&
1632                                 'radiation_scheme /= "rrtmg"'
1633                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1634             ELSE
1635                dopr_index(var_count) = 106
1636                dopr_unit  = 'K/h'
1637                hom(:,2,106,:)  = SPREAD( zu, 2, statistic_regions+1 )
1638                unit = dopr_unit
1639             ENDIF
1640
1641          CASE ( 'rad_sw_hr' )
1642             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1643             THEN
1644                message_string = 'data_output_pr = ' //                        &
1645                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1646                                 'not available for radiation = .FALSE. or ' //&
1647                                 'radiation_scheme /= "rrtmg"'
1648                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1649             ELSE
1650                dopr_index(var_count) = 107
1651                dopr_unit  = 'K/h'
1652                hom(:,2,107,:)  = SPREAD( zu, 2, statistic_regions+1 )
1653                unit = dopr_unit
1654             ENDIF
1655
1656
1657          CASE DEFAULT
1658             unit = 'illegal'
1659
1660       END SELECT
1661
1662
1663    END SUBROUTINE radiation_check_data_output_pr
1664 
1665 
1666!------------------------------------------------------------------------------!
1667! Description:
1668! ------------
1669!> Check parameters routine for radiation model
1670!------------------------------------------------------------------------------!
1671    SUBROUTINE radiation_check_parameters
1672
1673       USE control_parameters,                                                 &
1674           ONLY: land_surface, message_string, urban_surface
1675
1676       USE netcdf_data_input_mod,                                              &
1677           ONLY:  input_pids_static                 
1678   
1679       IMPLICIT NONE
1680       
1681!
1682!--    In case no urban-surface or land-surface model is applied, usage of
1683!--    a radiation model make no sense.         
1684       IF ( .NOT. land_surface  .AND.  .NOT. urban_surface )  THEN
1685          message_string = 'Usage of radiation module is only allowed if ' //  &
1686                           'land-surface and/or urban-surface model is applied.'
1687          CALL message( 'check_parameters', 'PA0486', 1, 2, 0, 6, 0 )
1688       ENDIF
1689
1690       IF ( radiation_scheme /= 'constant'   .AND.                             &
1691            radiation_scheme /= 'clear-sky'  .AND.                             &
1692            radiation_scheme /= 'rrtmg' )  THEN
1693          message_string = 'unknown radiation_scheme = '//                     &
1694                           TRIM( radiation_scheme )
1695          CALL message( 'check_parameters', 'PA0405', 1, 2, 0, 6, 0 )
1696       ELSEIF ( radiation_scheme == 'rrtmg' )  THEN
1697#if ! defined ( __rrtmg )
1698          message_string = 'radiation_scheme = "rrtmg" requires ' //           & 
1699                           'compilation of PALM with pre-processor ' //        &
1700                           'directive -D__rrtmg'
1701          CALL message( 'check_parameters', 'PA0407', 1, 2, 0, 6, 0 )
1702#endif
1703#if defined ( __rrtmg ) && ! defined( __netcdf )
1704          message_string = 'radiation_scheme = "rrtmg" requires ' //           & 
1705                           'the use of NetCDF (preprocessor directive ' //     &
1706                           '-D__netcdf'
1707          CALL message( 'check_parameters', 'PA0412', 1, 2, 0, 6, 0 )
1708#endif
1709
1710       ENDIF
1711!
1712!--    Checks performed only if data is given via namelist only.
1713       IF ( .NOT. input_pids_static )  THEN
1714          IF ( albedo_type == 0  .AND.  albedo == 9999999.9_wp  .AND.          &
1715               radiation_scheme == 'clear-sky')  THEN
1716             message_string = 'radiation_scheme = "clear-sky" in combination'//& 
1717                              'with albedo_type = 0 requires setting of'//     &
1718                              'albedo /= 9999999.9'
1719             CALL message( 'check_parameters', 'PA0410', 1, 2, 0, 6, 0 )
1720          ENDIF
1721
1722          IF ( albedo_type == 0  .AND.  radiation_scheme == 'rrtmg'  .AND.     &
1723             ( albedo_lw_dif == 9999999.9_wp .OR. albedo_lw_dir == 9999999.9_wp&
1724          .OR. albedo_sw_dif == 9999999.9_wp .OR. albedo_sw_dir == 9999999.9_wp& 
1725             ) ) THEN
1726             message_string = 'radiation_scheme = "rrtmg" in combination' //   & 
1727                              'with albedo_type = 0 requires setting of ' //   &
1728                              'albedo_lw_dif /= 9999999.9' //                  &
1729                              'albedo_lw_dir /= 9999999.9' //                  &
1730                              'albedo_sw_dif /= 9999999.9 and' //              &
1731                              'albedo_sw_dir /= 9999999.9'
1732             CALL message( 'check_parameters', 'PA0411', 1, 2, 0, 6, 0 )
1733          ENDIF
1734       ENDIF
1735!
1736!--    Parallel rad_angular_discretization without raytrace_mpi_rma is not implemented
1737#if defined( __parallel )     
1738       IF ( rad_angular_discretization  .AND.  .NOT. raytrace_mpi_rma )  THEN
1739          message_string = 'rad_angular_discretization can only be used ' //  &
1740                           'together with raytrace_mpi_rma or when ' //  &
1741                           'no parallelization is applied.'
1742          CALL message( 'check_parameters', 'PA0486', 1, 2, 0, 6, 0 )
1743       ENDIF
1744#endif
1745
1746       IF ( cloud_droplets  .AND.   radiation_scheme == 'rrtmg'  .AND.         &
1747            average_radiation ) THEN
1748          message_string = 'average_radiation = .T. with radiation_scheme'//   & 
1749                           '= "rrtmg" in combination cloud_droplets = .T.'//   &
1750                           'is not implementd'
1751          CALL message( 'check_parameters', 'PA0560', 1, 2, 0, 6, 0 )
1752       ENDIF
1753
1754!
1755!--    Incialize svf normalization reporting histogram
1756       svfnorm_report_num = 1
1757       DO WHILE ( svfnorm_report_thresh(svfnorm_report_num) < 1e20_wp          &
1758                   .AND. svfnorm_report_num <= 30 )
1759          svfnorm_report_num = svfnorm_report_num + 1
1760       ENDDO
1761       svfnorm_report_num = svfnorm_report_num - 1
1762
1763
1764 
1765    END SUBROUTINE radiation_check_parameters 
1766 
1767 
1768!------------------------------------------------------------------------------!
1769! Description:
1770! ------------
1771!> Initialization of the radiation model
1772!------------------------------------------------------------------------------!
1773    SUBROUTINE radiation_init
1774   
1775       IMPLICIT NONE
1776
1777       INTEGER(iwp) ::  i         !< running index x-direction
1778       INTEGER(iwp) ::  ioff      !< offset in x between surface element reference grid point in atmosphere and actual surface
1779       INTEGER(iwp) ::  j         !< running index y-direction
1780       INTEGER(iwp) ::  joff      !< offset in y between surface element reference grid point in atmosphere and actual surface
1781       INTEGER(iwp) ::  l         !< running index for orientation of vertical surfaces
1782       INTEGER(iwp) ::  m         !< running index for surface elements
1783#if defined( __rrtmg )
1784       INTEGER(iwp) ::  ind_type  !< running index for subgrid-surface tiles
1785#endif
1786
1787!
1788!--    Activate radiation_interactions according to the existence of vertical surfaces and/or trees.
1789!--    The namelist parameter radiation_interactions_on can override this behavior.
1790!--    (This check cannot be performed in check_parameters, because vertical_surfaces_exist is first set in
1791!--    init_surface_arrays.)
1792       IF ( radiation_interactions_on )  THEN
1793          IF ( vertical_surfaces_exist  .OR.  plant_canopy )  THEN
1794             radiation_interactions    = .TRUE.
1795             average_radiation         = .TRUE.
1796          ELSE
1797             radiation_interactions_on = .FALSE.   !< reset namelist parameter: no interactions
1798                                                   !< calculations necessary in case of flat surface
1799          ENDIF
1800       ELSEIF ( vertical_surfaces_exist  .OR.  plant_canopy )  THEN
1801          message_string = 'radiation_interactions_on is set to .FALSE. although '     // &
1802                           'vertical surfaces and/or trees exist. The model will run ' // &
1803                           'without RTM (no shadows, no radiation reflections)'
1804          CALL message( 'init_3d_model', 'PA0348', 0, 1, 0, 6, 0 )
1805       ENDIF
1806!
1807!--    If required, initialize radiation interactions between surfaces
1808!--    via sky-view factors. This must be done before radiation is initialized.
1809       IF ( radiation_interactions )  CALL radiation_interaction_init
1810
1811!
1812!--    Initialize radiation model
1813       CALL location_message( 'initializing radiation model', .FALSE. )
1814
1815!
1816!--    Allocate array for storing the surface net radiation
1817       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_net )  .AND.                      &
1818                  surf_lsm_h%ns > 0  )   THEN
1819          ALLOCATE( surf_lsm_h%rad_net(1:surf_lsm_h%ns) )
1820          surf_lsm_h%rad_net = 0.0_wp 
1821       ENDIF
1822       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_net )  .AND.                      &
1823                  surf_usm_h%ns > 0  )  THEN
1824          ALLOCATE( surf_usm_h%rad_net(1:surf_usm_h%ns) )
1825          surf_usm_h%rad_net = 0.0_wp 
1826       ENDIF
1827       DO  l = 0, 3
1828          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_net )  .AND.                &
1829                     surf_lsm_v(l)%ns > 0  )  THEN
1830             ALLOCATE( surf_lsm_v(l)%rad_net(1:surf_lsm_v(l)%ns) )
1831             surf_lsm_v(l)%rad_net = 0.0_wp 
1832          ENDIF
1833          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_net )  .AND.                &
1834                     surf_usm_v(l)%ns > 0  )  THEN
1835             ALLOCATE( surf_usm_v(l)%rad_net(1:surf_usm_v(l)%ns) )
1836             surf_usm_v(l)%rad_net = 0.0_wp 
1837          ENDIF
1838       ENDDO
1839
1840
1841!
1842!--    Allocate array for storing the surface longwave (out) radiation change
1843       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_lw_out_change_0 )  .AND.          &
1844                  surf_lsm_h%ns > 0  )   THEN
1845          ALLOCATE( surf_lsm_h%rad_lw_out_change_0(1:surf_lsm_h%ns) )
1846          surf_lsm_h%rad_lw_out_change_0 = 0.0_wp 
1847       ENDIF
1848       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_lw_out_change_0 )  .AND.          &
1849                  surf_usm_h%ns > 0  )  THEN
1850          ALLOCATE( surf_usm_h%rad_lw_out_change_0(1:surf_usm_h%ns) )
1851          surf_usm_h%rad_lw_out_change_0 = 0.0_wp 
1852       ENDIF
1853       DO  l = 0, 3
1854          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_lw_out_change_0 )  .AND.    &
1855                     surf_lsm_v(l)%ns > 0  )  THEN
1856             ALLOCATE( surf_lsm_v(l)%rad_lw_out_change_0(1:surf_lsm_v(l)%ns) )
1857             surf_lsm_v(l)%rad_lw_out_change_0 = 0.0_wp 
1858          ENDIF
1859          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_lw_out_change_0 )  .AND.    &
1860                     surf_usm_v(l)%ns > 0  )  THEN
1861             ALLOCATE( surf_usm_v(l)%rad_lw_out_change_0(1:surf_usm_v(l)%ns) )
1862             surf_usm_v(l)%rad_lw_out_change_0 = 0.0_wp 
1863          ENDIF
1864       ENDDO
1865
1866!
1867!--    Allocate surface arrays for incoming/outgoing short/longwave radiation
1868       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_sw_in )  .AND.                    &
1869                  surf_lsm_h%ns > 0  )   THEN
1870          ALLOCATE( surf_lsm_h%rad_sw_in(1:surf_lsm_h%ns)  )
1871          ALLOCATE( surf_lsm_h%rad_sw_out(1:surf_lsm_h%ns) )
1872          ALLOCATE( surf_lsm_h%rad_sw_dir(1:surf_lsm_h%ns) )
1873          ALLOCATE( surf_lsm_h%rad_sw_dif(1:surf_lsm_h%ns) )
1874          ALLOCATE( surf_lsm_h%rad_sw_ref(1:surf_lsm_h%ns) )
1875          ALLOCATE( surf_lsm_h%rad_sw_res(1:surf_lsm_h%ns) )
1876          ALLOCATE( surf_lsm_h%rad_lw_in(1:surf_lsm_h%ns)  )
1877          ALLOCATE( surf_lsm_h%rad_lw_out(1:surf_lsm_h%ns) )
1878          ALLOCATE( surf_lsm_h%rad_lw_dif(1:surf_lsm_h%ns) )
1879          ALLOCATE( surf_lsm_h%rad_lw_ref(1:surf_lsm_h%ns) )
1880          ALLOCATE( surf_lsm_h%rad_lw_res(1:surf_lsm_h%ns) )
1881          surf_lsm_h%rad_sw_in  = 0.0_wp 
1882          surf_lsm_h%rad_sw_out = 0.0_wp 
1883          surf_lsm_h%rad_sw_dir = 0.0_wp 
1884          surf_lsm_h%rad_sw_dif = 0.0_wp 
1885          surf_lsm_h%rad_sw_ref = 0.0_wp 
1886          surf_lsm_h%rad_sw_res = 0.0_wp 
1887          surf_lsm_h%rad_lw_in  = 0.0_wp 
1888          surf_lsm_h%rad_lw_out = 0.0_wp 
1889          surf_lsm_h%rad_lw_dif = 0.0_wp 
1890          surf_lsm_h%rad_lw_ref = 0.0_wp 
1891          surf_lsm_h%rad_lw_res = 0.0_wp 
1892       ENDIF
1893       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_sw_in )  .AND.                    &
1894                  surf_usm_h%ns > 0  )  THEN
1895          ALLOCATE( surf_usm_h%rad_sw_in(1:surf_usm_h%ns)  )
1896          ALLOCATE( surf_usm_h%rad_sw_out(1:surf_usm_h%ns) )
1897          ALLOCATE( surf_usm_h%rad_sw_dir(1:surf_usm_h%ns) )
1898          ALLOCATE( surf_usm_h%rad_sw_dif(1:surf_usm_h%ns) )
1899          ALLOCATE( surf_usm_h%rad_sw_ref(1:surf_usm_h%ns) )
1900          ALLOCATE( surf_usm_h%rad_sw_res(1:surf_usm_h%ns) )
1901          ALLOCATE( surf_usm_h%rad_lw_in(1:surf_usm_h%ns)  )
1902          ALLOCATE( surf_usm_h%rad_lw_out(1:surf_usm_h%ns) )
1903          ALLOCATE( surf_usm_h%rad_lw_dif(1:surf_usm_h%ns) )
1904          ALLOCATE( surf_usm_h%rad_lw_ref(1:surf_usm_h%ns) )
1905          ALLOCATE( surf_usm_h%rad_lw_res(1:surf_usm_h%ns) )
1906          surf_usm_h%rad_sw_in  = 0.0_wp 
1907          surf_usm_h%rad_sw_out = 0.0_wp 
1908          surf_usm_h%rad_sw_dir = 0.0_wp 
1909          surf_usm_h%rad_sw_dif = 0.0_wp 
1910          surf_usm_h%rad_sw_ref = 0.0_wp 
1911          surf_usm_h%rad_sw_res = 0.0_wp 
1912          surf_usm_h%rad_lw_in  = 0.0_wp 
1913          surf_usm_h%rad_lw_out = 0.0_wp 
1914          surf_usm_h%rad_lw_dif = 0.0_wp 
1915          surf_usm_h%rad_lw_ref = 0.0_wp 
1916          surf_usm_h%rad_lw_res = 0.0_wp 
1917       ENDIF
1918       DO  l = 0, 3
1919          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_sw_in )  .AND.              &
1920                     surf_lsm_v(l)%ns > 0  )  THEN
1921             ALLOCATE( surf_lsm_v(l)%rad_sw_in(1:surf_lsm_v(l)%ns)  )
1922             ALLOCATE( surf_lsm_v(l)%rad_sw_out(1:surf_lsm_v(l)%ns) )
1923             ALLOCATE( surf_lsm_v(l)%rad_sw_dir(1:surf_lsm_v(l)%ns) )
1924             ALLOCATE( surf_lsm_v(l)%rad_sw_dif(1:surf_lsm_v(l)%ns) )
1925             ALLOCATE( surf_lsm_v(l)%rad_sw_ref(1:surf_lsm_v(l)%ns) )
1926             ALLOCATE( surf_lsm_v(l)%rad_sw_res(1:surf_lsm_v(l)%ns) )
1927
1928             ALLOCATE( surf_lsm_v(l)%rad_lw_in(1:surf_lsm_v(l)%ns)  )
1929             ALLOCATE( surf_lsm_v(l)%rad_lw_out(1:surf_lsm_v(l)%ns) )
1930             ALLOCATE( surf_lsm_v(l)%rad_lw_dif(1:surf_lsm_v(l)%ns) )
1931             ALLOCATE( surf_lsm_v(l)%rad_lw_ref(1:surf_lsm_v(l)%ns) )
1932             ALLOCATE( surf_lsm_v(l)%rad_lw_res(1:surf_lsm_v(l)%ns) )
1933
1934             surf_lsm_v(l)%rad_sw_in  = 0.0_wp 
1935             surf_lsm_v(l)%rad_sw_out = 0.0_wp
1936             surf_lsm_v(l)%rad_sw_dir = 0.0_wp
1937             surf_lsm_v(l)%rad_sw_dif = 0.0_wp
1938             surf_lsm_v(l)%rad_sw_ref = 0.0_wp
1939             surf_lsm_v(l)%rad_sw_res = 0.0_wp
1940
1941             surf_lsm_v(l)%rad_lw_in  = 0.0_wp 
1942             surf_lsm_v(l)%rad_lw_out = 0.0_wp 
1943             surf_lsm_v(l)%rad_lw_dif = 0.0_wp 
1944             surf_lsm_v(l)%rad_lw_ref = 0.0_wp 
1945             surf_lsm_v(l)%rad_lw_res = 0.0_wp 
1946          ENDIF
1947          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_sw_in )  .AND.              &
1948                     surf_usm_v(l)%ns > 0  )  THEN
1949             ALLOCATE( surf_usm_v(l)%rad_sw_in(1:surf_usm_v(l)%ns)  )
1950             ALLOCATE( surf_usm_v(l)%rad_sw_out(1:surf_usm_v(l)%ns) )
1951             ALLOCATE( surf_usm_v(l)%rad_sw_dir(1:surf_usm_v(l)%ns) )
1952             ALLOCATE( surf_usm_v(l)%rad_sw_dif(1:surf_usm_v(l)%ns) )
1953             ALLOCATE( surf_usm_v(l)%rad_sw_ref(1:surf_usm_v(l)%ns) )
1954             ALLOCATE( surf_usm_v(l)%rad_sw_res(1:surf_usm_v(l)%ns) )
1955             ALLOCATE( surf_usm_v(l)%rad_lw_in(1:surf_usm_v(l)%ns)  )
1956             ALLOCATE( surf_usm_v(l)%rad_lw_out(1:surf_usm_v(l)%ns) )
1957             ALLOCATE( surf_usm_v(l)%rad_lw_dif(1:surf_usm_v(l)%ns) )
1958             ALLOCATE( surf_usm_v(l)%rad_lw_ref(1:surf_usm_v(l)%ns) )
1959             ALLOCATE( surf_usm_v(l)%rad_lw_res(1:surf_usm_v(l)%ns) )
1960             surf_usm_v(l)%rad_sw_in  = 0.0_wp 
1961             surf_usm_v(l)%rad_sw_out = 0.0_wp
1962             surf_usm_v(l)%rad_sw_dir = 0.0_wp
1963             surf_usm_v(l)%rad_sw_dif = 0.0_wp
1964             surf_usm_v(l)%rad_sw_ref = 0.0_wp
1965             surf_usm_v(l)%rad_sw_res = 0.0_wp
1966             surf_usm_v(l)%rad_lw_in  = 0.0_wp 
1967             surf_usm_v(l)%rad_lw_out = 0.0_wp 
1968             surf_usm_v(l)%rad_lw_dif = 0.0_wp 
1969             surf_usm_v(l)%rad_lw_ref = 0.0_wp 
1970             surf_usm_v(l)%rad_lw_res = 0.0_wp 
1971          ENDIF
1972       ENDDO
1973!
1974!--    Fix net radiation in case of radiation_scheme = 'constant'
1975       IF ( radiation_scheme == 'constant' )  THEN
1976          IF ( ALLOCATED( surf_lsm_h%rad_net ) )                               &
1977             surf_lsm_h%rad_net    = net_radiation
1978          IF ( ALLOCATED( surf_usm_h%rad_net ) )                               &
1979             surf_usm_h%rad_net    = net_radiation
1980!
1981!--       Todo: weight with inclination angle
1982          DO  l = 0, 3
1983             IF ( ALLOCATED( surf_lsm_v(l)%rad_net ) )                         &
1984                surf_lsm_v(l)%rad_net = net_radiation
1985             IF ( ALLOCATED( surf_usm_v(l)%rad_net ) )                         &
1986                surf_usm_v(l)%rad_net = net_radiation
1987          ENDDO
1988!          radiation = .FALSE.
1989!
1990!--    Calculate orbital constants
1991       ELSE
1992          decl_1 = SIN(23.45_wp * pi / 180.0_wp)
1993          decl_2 = 2.0_wp * pi / 365.0_wp
1994          decl_3 = decl_2 * 81.0_wp
1995          lat    = latitude * pi / 180.0_wp
1996          lon    = longitude * pi / 180.0_wp
1997       ENDIF
1998
1999       IF ( radiation_scheme == 'clear-sky'  .OR.                              &
2000            radiation_scheme == 'constant')  THEN
2001
2002
2003!
2004!--       Allocate arrays for incoming/outgoing short/longwave radiation
2005          IF ( .NOT. ALLOCATED ( rad_sw_in ) )  THEN
2006             ALLOCATE ( rad_sw_in(0:0,nysg:nyng,nxlg:nxrg) )
2007          ENDIF
2008          IF ( .NOT. ALLOCATED ( rad_sw_out ) )  THEN
2009             ALLOCATE ( rad_sw_out(0:0,nysg:nyng,nxlg:nxrg) )
2010          ENDIF
2011
2012          IF ( .NOT. ALLOCATED ( rad_lw_in ) )  THEN
2013             ALLOCATE ( rad_lw_in(0:0,nysg:nyng,nxlg:nxrg) )
2014          ENDIF
2015          IF ( .NOT. ALLOCATED ( rad_lw_out ) )  THEN
2016             ALLOCATE ( rad_lw_out(0:0,nysg:nyng,nxlg:nxrg) )
2017          ENDIF
2018
2019!
2020!--       Allocate average arrays for incoming/outgoing short/longwave radiation
2021          IF ( .NOT. ALLOCATED ( rad_sw_in_av ) )  THEN
2022             ALLOCATE ( rad_sw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
2023          ENDIF
2024          IF ( .NOT. ALLOCATED ( rad_sw_out_av ) )  THEN
2025             ALLOCATE ( rad_sw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
2026          ENDIF
2027
2028          IF ( .NOT. ALLOCATED ( rad_lw_in_av ) )  THEN
2029             ALLOCATE ( rad_lw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
2030          ENDIF
2031          IF ( .NOT. ALLOCATED ( rad_lw_out_av ) )  THEN
2032             ALLOCATE ( rad_lw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
2033          ENDIF
2034!
2035!--       Allocate arrays for broadband albedo, and level 1 initialization
2036!--       via namelist paramter, unless not already allocated.
2037          IF ( .NOT. ALLOCATED(surf_lsm_h%albedo) )  THEN
2038             ALLOCATE( surf_lsm_h%albedo(0:2,1:surf_lsm_h%ns)     )
2039             surf_lsm_h%albedo    = albedo
2040          ENDIF
2041          IF ( .NOT. ALLOCATED(surf_usm_h%albedo) )  THEN
2042             ALLOCATE( surf_usm_h%albedo(0:2,1:surf_usm_h%ns)     )
2043             surf_usm_h%albedo    = albedo
2044          ENDIF
2045
2046          DO  l = 0, 3
2047             IF ( .NOT. ALLOCATED( surf_lsm_v(l)%albedo ) )  THEN
2048                ALLOCATE( surf_lsm_v(l)%albedo(0:2,1:surf_lsm_v(l)%ns) )
2049                surf_lsm_v(l)%albedo = albedo
2050             ENDIF
2051             IF ( .NOT. ALLOCATED( surf_usm_v(l)%albedo ) )  THEN
2052                ALLOCATE( surf_usm_v(l)%albedo(0:2,1:surf_usm_v(l)%ns) )
2053                surf_usm_v(l)%albedo = albedo
2054             ENDIF
2055          ENDDO
2056!
2057!--       Level 2 initialization of broadband albedo via given albedo_type.
2058!--       Only if albedo_type is non-zero. In case of urban surface and
2059!--       input data is read from ASCII file, albedo_type will be zero, so that
2060!--       albedo won't be overwritten.
2061          DO  m = 1, surf_lsm_h%ns
2062             IF ( surf_lsm_h%albedo_type(ind_veg_wall,m) /= 0 )                &
2063                surf_lsm_h%albedo(ind_veg_wall,m) =                            &
2064                           albedo_pars(2,surf_lsm_h%albedo_type(ind_veg_wall,m))
2065             IF ( surf_lsm_h%albedo_type(ind_pav_green,m) /= 0 )               &
2066                surf_lsm_h%albedo(ind_pav_green,m) =                           &
2067                           albedo_pars(2,surf_lsm_h%albedo_type(ind_pav_green,m))
2068             IF ( surf_lsm_h%albedo_type(ind_wat_win,m) /= 0 )                 &
2069                surf_lsm_h%albedo(ind_wat_win,m) =                             &
2070                           albedo_pars(2,surf_lsm_h%albedo_type(ind_wat_win,m))
2071          ENDDO
2072          DO  m = 1, surf_usm_h%ns
2073             IF ( surf_usm_h%albedo_type(ind_veg_wall,m) /= 0 )                &
2074                surf_usm_h%albedo(ind_veg_wall,m) =                            &
2075                           albedo_pars(2,surf_usm_h%albedo_type(ind_veg_wall,m))
2076             IF ( surf_usm_h%albedo_type(ind_pav_green,m) /= 0 )               &
2077                surf_usm_h%albedo(ind_pav_green,m) =                           &
2078                           albedo_pars(2,surf_usm_h%albedo_type(ind_pav_green,m))
2079             IF ( surf_usm_h%albedo_type(ind_wat_win,m) /= 0 )                 &
2080                surf_usm_h%albedo(ind_wat_win,m) =                             &
2081                           albedo_pars(2,surf_usm_h%albedo_type(ind_wat_win,m))
2082          ENDDO
2083
2084          DO  l = 0, 3
2085             DO  m = 1, surf_lsm_v(l)%ns
2086                IF ( surf_lsm_v(l)%albedo_type(ind_veg_wall,m) /= 0 )          &
2087                   surf_lsm_v(l)%albedo(ind_veg_wall,m) =                      &
2088                        albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_veg_wall,m))
2089                IF ( surf_lsm_v(l)%albedo_type(ind_pav_green,m) /= 0 )         &
2090                   surf_lsm_v(l)%albedo(ind_pav_green,m) =                     &
2091                        albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_pav_green,m))
2092                IF ( surf_lsm_v(l)%albedo_type(ind_wat_win,m) /= 0 )           &
2093                   surf_lsm_v(l)%albedo(ind_wat_win,m) =                       &
2094                        albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_wat_win,m))
2095             ENDDO
2096             DO  m = 1, surf_usm_v(l)%ns
2097                IF ( surf_usm_v(l)%albedo_type(ind_veg_wall,m) /= 0 )          &
2098                   surf_usm_v(l)%albedo(ind_veg_wall,m) =                      &
2099                        albedo_pars(2,surf_usm_v(l)%albedo_type(ind_veg_wall,m))
2100                IF ( surf_usm_v(l)%albedo_type(ind_pav_green,m) /= 0 )         &
2101                   surf_usm_v(l)%albedo(ind_pav_green,m) =                     &
2102                        albedo_pars(2,surf_usm_v(l)%albedo_type(ind_pav_green,m))
2103                IF ( surf_usm_v(l)%albedo_type(ind_wat_win,m) /= 0 )           &
2104                   surf_usm_v(l)%albedo(ind_wat_win,m) =                       &
2105                        albedo_pars(2,surf_usm_v(l)%albedo_type(ind_wat_win,m))
2106             ENDDO
2107          ENDDO
2108
2109!
2110!--       Level 3 initialization at grid points where albedo type is zero.
2111!--       This case, albedo is taken from file. In case of constant radiation
2112!--       or clear sky, only broadband albedo is given.
2113          IF ( albedo_pars_f%from_file )  THEN
2114!
2115!--          Horizontal surfaces
2116             DO  m = 1, surf_lsm_h%ns
2117                i = surf_lsm_h%i(m)
2118                j = surf_lsm_h%j(m)
2119                IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2120                   IF ( surf_lsm_h%albedo_type(ind_veg_wall,m) == 0 )          &
2121                      surf_lsm_h%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2122                   IF ( surf_lsm_h%albedo_type(ind_pav_green,m) == 0 )         &
2123                      surf_lsm_h%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2124                   IF ( surf_lsm_h%albedo_type(ind_wat_win,m) == 0 )           &
2125                      surf_lsm_h%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2126                ENDIF
2127             ENDDO
2128             DO  m = 1, surf_usm_h%ns
2129                i = surf_usm_h%i(m)
2130                j = surf_usm_h%j(m)
2131                IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2132                   IF ( surf_usm_h%albedo_type(ind_veg_wall,m) == 0 )          &
2133                      surf_usm_h%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2134                   IF ( surf_usm_h%albedo_type(ind_pav_green,m) == 0 )         &
2135                      surf_usm_h%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2136                   IF ( surf_usm_h%albedo_type(ind_wat_win,m) == 0 )           &
2137                      surf_usm_h%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2138                ENDIF
2139             ENDDO 
2140!
2141!--          Vertical surfaces           
2142             DO  l = 0, 3
2143
2144                ioff = surf_lsm_v(l)%ioff
2145                joff = surf_lsm_v(l)%joff
2146                DO  m = 1, surf_lsm_v(l)%ns
2147                   i = surf_lsm_v(l)%i(m) + ioff
2148                   j = surf_lsm_v(l)%j(m) + joff
2149                   IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2150                      IF ( surf_lsm_v(l)%albedo_type(ind_veg_wall,m) == 0 )    &
2151                         surf_lsm_v(l)%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2152                      IF ( surf_lsm_v(l)%albedo_type(ind_pav_green,m) == 0 )   &
2153                         surf_lsm_v(l)%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2154                      IF ( surf_lsm_v(l)%albedo_type(ind_wat_win,m) == 0 )     &
2155                         surf_lsm_v(l)%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2156                   ENDIF
2157                ENDDO
2158
2159                ioff = surf_usm_v(l)%ioff
2160                joff = surf_usm_v(l)%joff
2161                DO  m = 1, surf_usm_h%ns
2162                   i = surf_usm_h%i(m) + joff
2163                   j = surf_usm_h%j(m) + joff
2164                   IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2165                      IF ( surf_usm_v(l)%albedo_type(ind_veg_wall,m) == 0 )    &
2166                         surf_usm_v(l)%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2167                      IF ( surf_usm_v(l)%albedo_type(ind_pav_green,m) == 0 )   &
2168                         surf_usm_v(l)%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2169                      IF ( surf_usm_v(l)%albedo_type(ind_wat_win,m) == 0 )     &
2170                         surf_lsm_v(l)%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2171                   ENDIF
2172                ENDDO
2173             ENDDO
2174
2175          ENDIF 
2176!
2177!--    Initialization actions for RRTMG
2178       ELSEIF ( radiation_scheme == 'rrtmg' )  THEN
2179#if defined ( __rrtmg )
2180!
2181!--       Allocate albedos for short/longwave radiation, horizontal surfaces
2182!--       for wall/green/window (USM) or vegetation/pavement/water surfaces
2183!--       (LSM).
2184          ALLOCATE ( surf_lsm_h%aldif(0:2,1:surf_lsm_h%ns)       )
2185          ALLOCATE ( surf_lsm_h%aldir(0:2,1:surf_lsm_h%ns)       )
2186          ALLOCATE ( surf_lsm_h%asdif(0:2,1:surf_lsm_h%ns)       )
2187          ALLOCATE ( surf_lsm_h%asdir(0:2,1:surf_lsm_h%ns)       )
2188          ALLOCATE ( surf_lsm_h%rrtm_aldif(0:2,1:surf_lsm_h%ns)  )
2189          ALLOCATE ( surf_lsm_h%rrtm_aldir(0:2,1:surf_lsm_h%ns)  )
2190          ALLOCATE ( surf_lsm_h%rrtm_asdif(0:2,1:surf_lsm_h%ns)  )
2191          ALLOCATE ( surf_lsm_h%rrtm_asdir(0:2,1:surf_lsm_h%ns)  )
2192
2193          ALLOCATE ( surf_usm_h%aldif(0:2,1:surf_usm_h%ns)       )
2194          ALLOCATE ( surf_usm_h%aldir(0:2,1:surf_usm_h%ns)       )
2195          ALLOCATE ( surf_usm_h%asdif(0:2,1:surf_usm_h%ns)       )
2196          ALLOCATE ( surf_usm_h%asdir(0:2,1:surf_usm_h%ns)       )
2197          ALLOCATE ( surf_usm_h%rrtm_aldif(0:2,1:surf_usm_h%ns)  )
2198          ALLOCATE ( surf_usm_h%rrtm_aldir(0:2,1:surf_usm_h%ns)  )
2199          ALLOCATE ( surf_usm_h%rrtm_asdif(0:2,1:surf_usm_h%ns)  )
2200          ALLOCATE ( surf_usm_h%rrtm_asdir(0:2,1:surf_usm_h%ns)  )
2201
2202!
2203!--       Allocate broadband albedo (temporary for the current radiation
2204!--       implementations)
2205          IF ( .NOT. ALLOCATED(surf_lsm_h%albedo) )                            &
2206             ALLOCATE( surf_lsm_h%albedo(0:2,1:surf_lsm_h%ns)     )
2207          IF ( .NOT. ALLOCATED(surf_usm_h%albedo) )                            &
2208             ALLOCATE( surf_usm_h%albedo(0:2,1:surf_usm_h%ns)     )
2209
2210!
2211!--       Allocate albedos for short/longwave radiation, vertical surfaces
2212          DO  l = 0, 3
2213
2214             ALLOCATE ( surf_lsm_v(l)%aldif(0:2,1:surf_lsm_v(l)%ns)      )
2215             ALLOCATE ( surf_lsm_v(l)%aldir(0:2,1:surf_lsm_v(l)%ns)      )
2216             ALLOCATE ( surf_lsm_v(l)%asdif(0:2,1:surf_lsm_v(l)%ns)      )
2217             ALLOCATE ( surf_lsm_v(l)%asdir(0:2,1:surf_lsm_v(l)%ns)      )
2218
2219             ALLOCATE ( surf_lsm_v(l)%rrtm_aldif(0:2,1:surf_lsm_v(l)%ns) )
2220             ALLOCATE ( surf_lsm_v(l)%rrtm_aldir(0:2,1:surf_lsm_v(l)%ns) )
2221             ALLOCATE ( surf_lsm_v(l)%rrtm_asdif(0:2,1:surf_lsm_v(l)%ns) )
2222             ALLOCATE ( surf_lsm_v(l)%rrtm_asdir(0:2,1:surf_lsm_v(l)%ns) )
2223
2224             ALLOCATE ( surf_usm_v(l)%aldif(0:2,1:surf_usm_v(l)%ns)      )
2225             ALLOCATE ( surf_usm_v(l)%aldir(0:2,1:surf_usm_v(l)%ns)      )
2226             ALLOCATE ( surf_usm_v(l)%asdif(0:2,1:surf_usm_v(l)%ns)      )
2227             ALLOCATE ( surf_usm_v(l)%asdir(0:2,1:surf_usm_v(l)%ns)      )
2228
2229             ALLOCATE ( surf_usm_v(l)%rrtm_aldif(0:2,1:surf_usm_v(l)%ns) )
2230             ALLOCATE ( surf_usm_v(l)%rrtm_aldir(0:2,1:surf_usm_v(l)%ns) )
2231             ALLOCATE ( surf_usm_v(l)%rrtm_asdif(0:2,1:surf_usm_v(l)%ns) )
2232             ALLOCATE ( surf_usm_v(l)%rrtm_asdir(0:2,1:surf_usm_v(l)%ns) )
2233!
2234!--          Allocate broadband albedo (temporary for the current radiation
2235!--          implementations)
2236             IF ( .NOT. ALLOCATED( surf_lsm_v(l)%albedo ) )                    &
2237                ALLOCATE( surf_lsm_v(l)%albedo(0:2,1:surf_lsm_v(l)%ns) )
2238             IF ( .NOT. ALLOCATED( surf_usm_v(l)%albedo ) )                    &
2239                ALLOCATE( surf_usm_v(l)%albedo(0:2,1:surf_usm_v(l)%ns) )
2240
2241          ENDDO
2242!
2243!--       Level 1 initialization of spectral albedos via namelist
2244!--       paramters. Please note, this case all surface tiles are initialized
2245!--       the same.
2246          IF ( surf_lsm_h%ns > 0 )  THEN
2247             surf_lsm_h%aldif  = albedo_lw_dif
2248             surf_lsm_h%aldir  = albedo_lw_dir
2249             surf_lsm_h%asdif  = albedo_sw_dif
2250             surf_lsm_h%asdir  = albedo_sw_dir
2251             surf_lsm_h%albedo = albedo_sw_dif
2252          ENDIF
2253          IF ( surf_usm_h%ns > 0 )  THEN
2254             IF ( surf_usm_h%albedo_from_ascii )  THEN
2255                surf_usm_h%aldif  = surf_usm_h%albedo
2256                surf_usm_h%aldir  = surf_usm_h%albedo
2257                surf_usm_h%asdif  = surf_usm_h%albedo
2258                surf_usm_h%asdir  = surf_usm_h%albedo
2259             ELSE
2260                surf_usm_h%aldif  = albedo_lw_dif
2261                surf_usm_h%aldir  = albedo_lw_dir
2262                surf_usm_h%asdif  = albedo_sw_dif
2263                surf_usm_h%asdir  = albedo_sw_dir
2264                surf_usm_h%albedo = albedo_sw_dif
2265             ENDIF
2266          ENDIF
2267
2268          DO  l = 0, 3
2269
2270             IF ( surf_lsm_v(l)%ns > 0 )  THEN
2271                surf_lsm_v(l)%aldif  = albedo_lw_dif
2272                surf_lsm_v(l)%aldir  = albedo_lw_dir
2273                surf_lsm_v(l)%asdif  = albedo_sw_dif
2274                surf_lsm_v(l)%asdir  = albedo_sw_dir
2275                surf_lsm_v(l)%albedo = albedo_sw_dif
2276             ENDIF
2277
2278             IF ( surf_usm_v(l)%ns > 0 )  THEN
2279                IF ( surf_usm_v(l)%albedo_from_ascii )  THEN
2280                   surf_usm_v(l)%aldif  = surf_usm_v(l)%albedo
2281                   surf_usm_v(l)%aldir  = surf_usm_v(l)%albedo
2282                   surf_usm_v(l)%asdif  = surf_usm_v(l)%albedo
2283                   surf_usm_v(l)%asdir  = surf_usm_v(l)%albedo
2284                ELSE
2285                   surf_usm_v(l)%aldif  = albedo_lw_dif
2286                   surf_usm_v(l)%aldir  = albedo_lw_dir
2287                   surf_usm_v(l)%asdif  = albedo_sw_dif
2288                   surf_usm_v(l)%asdir  = albedo_sw_dir
2289                ENDIF
2290             ENDIF
2291          ENDDO
2292
2293!
2294!--       Level 2 initialization of spectral albedos via albedo_type.
2295!--       Please note, for natural- and urban-type surfaces, a tile approach
2296!--       is applied so that the resulting albedo is calculated via the weighted
2297!--       average of respective surface fractions.
2298          DO  m = 1, surf_lsm_h%ns
2299!
2300!--          Spectral albedos for vegetation/pavement/water surfaces
2301             DO  ind_type = 0, 2
2302                IF ( surf_lsm_h%albedo_type(ind_type,m) /= 0 )  THEN
2303                   surf_lsm_h%aldif(ind_type,m) =                              &
2304                               albedo_pars(0,surf_lsm_h%albedo_type(ind_type,m))
2305                   surf_lsm_h%asdif(ind_type,m) =                              &
2306                               albedo_pars(1,surf_lsm_h%albedo_type(ind_type,m))
2307                   surf_lsm_h%aldir(ind_type,m) =                              &
2308                               albedo_pars(0,surf_lsm_h%albedo_type(ind_type,m))
2309                   surf_lsm_h%asdir(ind_type,m) =                              &
2310                               albedo_pars(1,surf_lsm_h%albedo_type(ind_type,m))
2311                   surf_lsm_h%albedo(ind_type,m) =                             &
2312                               albedo_pars(2,surf_lsm_h%albedo_type(ind_type,m))
2313                ENDIF
2314             ENDDO
2315
2316          ENDDO
2317!
2318!--       For urban surface only if albedo has not been already initialized
2319!--       in the urban-surface model via the ASCII file.
2320          IF ( .NOT. surf_usm_h%albedo_from_ascii )  THEN
2321             DO  m = 1, surf_usm_h%ns
2322!
2323!--             Spectral albedos for wall/green/window surfaces
2324                DO  ind_type = 0, 2
2325                   IF ( surf_usm_h%albedo_type(ind_type,m) /= 0 )  THEN
2326                      surf_usm_h%aldif(ind_type,m) =                           &
2327                               albedo_pars(0,surf_usm_h%albedo_type(ind_type,m))
2328                      surf_usm_h%asdif(ind_type,m) =                           &
2329                               albedo_pars(1,surf_usm_h%albedo_type(ind_type,m))
2330                      surf_usm_h%aldir(ind_type,m) =                           &
2331                               albedo_pars(0,surf_usm_h%albedo_type(ind_type,m))
2332                      surf_usm_h%asdir(ind_type,m) =                           &
2333                               albedo_pars(1,surf_usm_h%albedo_type(ind_type,m))
2334                      surf_usm_h%albedo(ind_type,m) =                          &
2335                               albedo_pars(2,surf_usm_h%albedo_type(ind_type,m))
2336                   ENDIF
2337                ENDDO
2338
2339             ENDDO
2340          ENDIF
2341
2342          DO l = 0, 3
2343
2344             DO  m = 1, surf_lsm_v(l)%ns
2345!
2346!--             Spectral albedos for vegetation/pavement/water surfaces
2347                DO  ind_type = 0, 2
2348                   IF ( surf_lsm_v(l)%albedo_type(ind_type,m) /= 0 )  THEN
2349                      surf_lsm_v(l)%aldif(ind_type,m) =                        &
2350                            albedo_pars(0,surf_lsm_v(l)%albedo_type(ind_type,m))
2351                      surf_lsm_v(l)%asdif(ind_type,m) =                        &
2352                            albedo_pars(1,surf_lsm_v(l)%albedo_type(ind_type,m))
2353                      surf_lsm_v(l)%aldir(ind_type,m) =                        &
2354                            albedo_pars(0,surf_lsm_v(l)%albedo_type(ind_type,m))
2355                      surf_lsm_v(l)%asdir(ind_type,m) =                        &
2356                            albedo_pars(1,surf_lsm_v(l)%albedo_type(ind_type,m))
2357                      surf_lsm_v(l)%albedo(ind_type,m) =                       &
2358                            albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_type,m))
2359                   ENDIF
2360                ENDDO
2361             ENDDO
2362!
2363!--          For urban surface only if albedo has not been already initialized
2364!--          in the urban-surface model via the ASCII file.
2365             IF ( .NOT. surf_usm_v(l)%albedo_from_ascii )  THEN
2366                DO  m = 1, surf_usm_v(l)%ns
2367!
2368!--                Spectral albedos for wall/green/window surfaces
2369                   DO  ind_type = 0, 2
2370                      IF ( surf_usm_v(l)%albedo_type(ind_type,m) /= 0 )  THEN
2371                         surf_usm_v(l)%aldif(ind_type,m) =                     &
2372                            albedo_pars(0,surf_usm_v(l)%albedo_type(ind_type,m))
2373                         surf_usm_v(l)%asdif(ind_type,m) =                     &
2374                            albedo_pars(1,surf_usm_v(l)%albedo_type(ind_type,m))
2375                         surf_usm_v(l)%aldir(ind_type,m) =                     &
2376                            albedo_pars(0,surf_usm_v(l)%albedo_type(ind_type,m))
2377                         surf_usm_v(l)%asdir(ind_type,m) =                     &
2378                            albedo_pars(1,surf_usm_v(l)%albedo_type(ind_type,m))
2379                         surf_usm_v(l)%albedo(ind_type,m) =                    &
2380                            albedo_pars(2,surf_usm_v(l)%albedo_type(ind_type,m))
2381                      ENDIF
2382                   ENDDO
2383
2384                ENDDO
2385             ENDIF
2386          ENDDO
2387!
2388!--       Level 3 initialization at grid points where albedo type is zero.
2389!--       This case, spectral albedos are taken from file if available
2390          IF ( albedo_pars_f%from_file )  THEN
2391!
2392!--          Horizontal
2393             DO  m = 1, surf_lsm_h%ns
2394                i = surf_lsm_h%i(m)
2395                j = surf_lsm_h%j(m)
2396!
2397!--             Spectral albedos for vegetation/pavement/water surfaces
2398                DO  ind_type = 0, 2
2399                   IF ( surf_lsm_h%albedo_type(ind_type,m) == 0 )  THEN
2400                      IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2401                         surf_lsm_h%albedo(ind_type,m) =                       &
2402                                                albedo_pars_f%pars_xy(1,j,i)
2403                      IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2404                         surf_lsm_h%aldir(ind_type,m) =                        &
2405                                                albedo_pars_f%pars_xy(1,j,i)
2406                      IF ( albedo_pars_f%pars_xy(2,j,i) /= albedo_pars_f%fill )&
2407                         surf_lsm_h%aldif(ind_type,m) =                        &
2408                                                albedo_pars_f%pars_xy(2,j,i)
2409                      IF ( albedo_pars_f%pars_xy(3,j,i) /= albedo_pars_f%fill )&
2410                         surf_lsm_h%asdir(ind_type,m) =                        &
2411                                                albedo_pars_f%pars_xy(3,j,i)
2412                      IF ( albedo_pars_f%pars_xy(4,j,i) /= albedo_pars_f%fill )&
2413                         surf_lsm_h%asdif(ind_type,m) =                        &
2414                                                albedo_pars_f%pars_xy(4,j,i)
2415                   ENDIF
2416                ENDDO
2417             ENDDO
2418!
2419!--          For urban surface only if albedo has not been already initialized
2420!--          in the urban-surface model via the ASCII file.
2421             IF ( .NOT. surf_usm_h%albedo_from_ascii )  THEN
2422                DO  m = 1, surf_usm_h%ns
2423                   i = surf_usm_h%i(m)
2424                   j = surf_usm_h%j(m)
2425!
2426!--                Spectral albedos for wall/green/window surfaces
2427                   DO  ind_type = 0, 2
2428                      IF ( surf_usm_h%albedo_type(ind_type,m) == 0 )  THEN
2429                         IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2430                            surf_usm_h%albedo(ind_type,m) =                       &
2431                                                albedo_pars_f%pars_xy(1,j,i)
2432                         IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2433                            surf_usm_h%aldir(ind_type,m) =                        &
2434                                                albedo_pars_f%pars_xy(1,j,i)
2435                         IF ( albedo_pars_f%pars_xy(2,j,i) /= albedo_pars_f%fill )&
2436                            surf_usm_h%aldif(ind_type,m) =                        &
2437                                                albedo_pars_f%pars_xy(2,j,i)
2438                         IF ( albedo_pars_f%pars_xy(3,j,i) /= albedo_pars_f%fill )&
2439                            surf_usm_h%asdir(ind_type,m) =                        &
2440                                                albedo_pars_f%pars_xy(3,j,i)
2441                         IF ( albedo_pars_f%pars_xy(4,j,i) /= albedo_pars_f%fill )&
2442                            surf_usm_h%asdif(ind_type,m) =                        &
2443                                                albedo_pars_f%pars_xy(4,j,i)
2444                      ENDIF
2445                   ENDDO
2446
2447                ENDDO
2448             ENDIF
2449!
2450!--          Vertical
2451             DO  l = 0, 3
2452                ioff = surf_lsm_v(l)%ioff
2453                joff = surf_lsm_v(l)%joff
2454
2455                DO  m = 1, surf_lsm_v(l)%ns
2456                   i = surf_lsm_v(l)%i(m)
2457                   j = surf_lsm_v(l)%j(m)
2458!
2459!--                Spectral albedos for vegetation/pavement/water surfaces
2460                   DO  ind_type = 0, 2
2461                      IF ( surf_lsm_v(l)%albedo_type(ind_type,m) == 0 )  THEN
2462                         IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2463                              albedo_pars_f%fill )                             &
2464                            surf_lsm_v(l)%albedo(ind_type,m) =                 &
2465                                          albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2466                         IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2467                              albedo_pars_f%fill )                             &
2468                            surf_lsm_v(l)%aldir(ind_type,m) =                  &
2469                                          albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2470                         IF ( albedo_pars_f%pars_xy(2,j+joff,i+ioff) /=        &
2471                              albedo_pars_f%fill )                             &
2472                            surf_lsm_v(l)%aldif(ind_type,m) =                  &
2473                                          albedo_pars_f%pars_xy(2,j+joff,i+ioff)
2474                         IF ( albedo_pars_f%pars_xy(3,j+joff,i+ioff) /=        &
2475                              albedo_pars_f%fill )                             &
2476                            surf_lsm_v(l)%asdir(ind_type,m) =                  &
2477                                          albedo_pars_f%pars_xy(3,j+joff,i+ioff)
2478                         IF ( albedo_pars_f%pars_xy(4,j+joff,i+ioff) /=        &
2479                              albedo_pars_f%fill )                             &
2480                            surf_lsm_v(l)%asdif(ind_type,m) =                  &
2481                                          albedo_pars_f%pars_xy(4,j+joff,i+ioff)
2482                      ENDIF
2483                   ENDDO
2484                ENDDO
2485!
2486!--             For urban surface only if albedo has not been already initialized
2487!--             in the urban-surface model via the ASCII file.
2488                IF ( .NOT. surf_usm_v(l)%albedo_from_ascii )  THEN
2489                   ioff = surf_usm_v(l)%ioff
2490                   joff = surf_usm_v(l)%joff
2491
2492                   DO  m = 1, surf_usm_v(l)%ns
2493                      i = surf_usm_v(l)%i(m)
2494                      j = surf_usm_v(l)%j(m)
2495!
2496!--                   Spectral albedos for wall/green/window surfaces
2497                      DO  ind_type = 0, 2
2498                         IF ( surf_usm_v(l)%albedo_type(ind_type,m) == 0 )  THEN
2499                            IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2500                                 albedo_pars_f%fill )                             &
2501                               surf_usm_v(l)%albedo(ind_type,m) =                 &
2502                                             albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2503                            IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2504                                 albedo_pars_f%fill )                             &
2505                               surf_usm_v(l)%aldir(ind_type,m) =                  &
2506                                             albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2507                            IF ( albedo_pars_f%pars_xy(2,j+joff,i+ioff) /=        &
2508                                 albedo_pars_f%fill )                             &
2509                               surf_usm_v(l)%aldif(ind_type,m) =                  &
2510                                             albedo_pars_f%pars_xy(2,j+joff,i+ioff)
2511                            IF ( albedo_pars_f%pars_xy(3,j+joff,i+ioff) /=        &
2512                                 albedo_pars_f%fill )                             &
2513                               surf_usm_v(l)%asdir(ind_type,m) =                  &
2514                                             albedo_pars_f%pars_xy(3,j+joff,i+ioff)
2515                            IF ( albedo_pars_f%pars_xy(4,j+joff,i+ioff) /=        &
2516                                 albedo_pars_f%fill )                             &
2517                               surf_usm_v(l)%asdif(ind_type,m) =                  &
2518                                             albedo_pars_f%pars_xy(4,j+joff,i+ioff)
2519                         ENDIF
2520                      ENDDO
2521
2522                   ENDDO
2523                ENDIF
2524             ENDDO
2525
2526          ENDIF
2527
2528!
2529!--       Calculate initial values of current (cosine of) the zenith angle and
2530!--       whether the sun is up
2531          CALL calc_zenith     
2532          ! readjust date and time to its initial value
2533          CALL init_date_and_time
2534!
2535!--       Calculate initial surface albedo for different surfaces
2536          IF ( .NOT. constant_albedo )  THEN
2537#if defined( __netcdf )
2538!
2539!--          Horizontally aligned natural and urban surfaces
2540             CALL calc_albedo( surf_lsm_h    )
2541             CALL calc_albedo( surf_usm_h    )
2542!
2543!--          Vertically aligned natural and urban surfaces
2544             DO  l = 0, 3
2545                CALL calc_albedo( surf_lsm_v(l) )
2546                CALL calc_albedo( surf_usm_v(l) )
2547             ENDDO
2548#endif
2549          ELSE
2550!
2551!--          Initialize sun-inclination independent spectral albedos
2552!--          Horizontal surfaces
2553             IF ( surf_lsm_h%ns > 0 )  THEN
2554                surf_lsm_h%rrtm_aldir = surf_lsm_h%aldir
2555                surf_lsm_h%rrtm_asdir = surf_lsm_h%asdir
2556                surf_lsm_h%rrtm_aldif = surf_lsm_h%aldif
2557                surf_lsm_h%rrtm_asdif = surf_lsm_h%asdif
2558             ENDIF
2559             IF ( surf_usm_h%ns > 0 )  THEN
2560                surf_usm_h%rrtm_aldir = surf_usm_h%aldir
2561                surf_usm_h%rrtm_asdir = surf_usm_h%asdir
2562                surf_usm_h%rrtm_aldif = surf_usm_h%aldif
2563                surf_usm_h%rrtm_asdif = surf_usm_h%asdif
2564             ENDIF
2565!
2566!--          Vertical surfaces
2567             DO  l = 0, 3
2568                IF ( surf_lsm_v(l)%ns > 0 )  THEN
2569                   surf_lsm_v(l)%rrtm_aldir = surf_lsm_v(l)%aldir
2570                   surf_lsm_v(l)%rrtm_asdir = surf_lsm_v(l)%asdir
2571                   surf_lsm_v(l)%rrtm_aldif = surf_lsm_v(l)%aldif
2572                   surf_lsm_v(l)%rrtm_asdif = surf_lsm_v(l)%asdif
2573                ENDIF
2574                IF ( surf_usm_v(l)%ns > 0 )  THEN
2575                   surf_usm_v(l)%rrtm_aldir = surf_usm_v(l)%aldir
2576                   surf_usm_v(l)%rrtm_asdir = surf_usm_v(l)%asdir
2577                   surf_usm_v(l)%rrtm_aldif = surf_usm_v(l)%aldif
2578                   surf_usm_v(l)%rrtm_asdif = surf_usm_v(l)%asdif
2579                ENDIF
2580             ENDDO
2581
2582          ENDIF
2583
2584!
2585!--       Allocate 3d arrays of radiative fluxes and heating rates
2586          IF ( .NOT. ALLOCATED ( rad_sw_in ) )  THEN
2587             ALLOCATE ( rad_sw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2588             rad_sw_in = 0.0_wp
2589          ENDIF
2590
2591          IF ( .NOT. ALLOCATED ( rad_sw_in_av ) )  THEN
2592             ALLOCATE ( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2593          ENDIF
2594
2595          IF ( .NOT. ALLOCATED ( rad_sw_out ) )  THEN
2596             ALLOCATE ( rad_sw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2597             rad_sw_out = 0.0_wp
2598          ENDIF
2599
2600          IF ( .NOT. ALLOCATED ( rad_sw_out_av ) )  THEN
2601             ALLOCATE ( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2602          ENDIF
2603
2604          IF ( .NOT. ALLOCATED ( rad_sw_hr ) )  THEN
2605             ALLOCATE ( rad_sw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2606             rad_sw_hr = 0.0_wp
2607          ENDIF
2608
2609          IF ( .NOT. ALLOCATED ( rad_sw_hr_av ) )  THEN
2610             ALLOCATE ( rad_sw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2611             rad_sw_hr_av = 0.0_wp
2612          ENDIF
2613
2614          IF ( .NOT. ALLOCATED ( rad_sw_cs_hr ) )  THEN
2615             ALLOCATE ( rad_sw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2616             rad_sw_cs_hr = 0.0_wp
2617          ENDIF
2618
2619          IF ( .NOT. ALLOCATED ( rad_sw_cs_hr_av ) )  THEN
2620             ALLOCATE ( rad_sw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2621             rad_sw_cs_hr_av = 0.0_wp
2622          ENDIF
2623
2624          IF ( .NOT. ALLOCATED ( rad_lw_in ) )  THEN
2625             ALLOCATE ( rad_lw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2626             rad_lw_in     = 0.0_wp
2627          ENDIF
2628
2629          IF ( .NOT. ALLOCATED ( rad_lw_in_av ) )  THEN
2630             ALLOCATE ( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2631          ENDIF
2632
2633          IF ( .NOT. ALLOCATED ( rad_lw_out ) )  THEN
2634             ALLOCATE ( rad_lw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2635            rad_lw_out    = 0.0_wp
2636          ENDIF
2637
2638          IF ( .NOT. ALLOCATED ( rad_lw_out_av ) )  THEN
2639             ALLOCATE ( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2640          ENDIF
2641
2642          IF ( .NOT. ALLOCATED ( rad_lw_hr ) )  THEN
2643             ALLOCATE ( rad_lw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2644             rad_lw_hr = 0.0_wp
2645          ENDIF
2646
2647          IF ( .NOT. ALLOCATED ( rad_lw_hr_av ) )  THEN
2648             ALLOCATE ( rad_lw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2649             rad_lw_hr_av = 0.0_wp
2650          ENDIF
2651
2652          IF ( .NOT. ALLOCATED ( rad_lw_cs_hr ) )  THEN
2653             ALLOCATE ( rad_lw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2654             rad_lw_cs_hr = 0.0_wp
2655          ENDIF
2656
2657          IF ( .NOT. ALLOCATED ( rad_lw_cs_hr_av ) )  THEN
2658             ALLOCATE ( rad_lw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2659             rad_lw_cs_hr_av = 0.0_wp
2660          ENDIF
2661
2662          ALLOCATE ( rad_sw_cs_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2663          ALLOCATE ( rad_sw_cs_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2664          rad_sw_cs_in  = 0.0_wp
2665          rad_sw_cs_out = 0.0_wp
2666
2667          ALLOCATE ( rad_lw_cs_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2668          ALLOCATE ( rad_lw_cs_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2669          rad_lw_cs_in  = 0.0_wp
2670          rad_lw_cs_out = 0.0_wp
2671
2672!
2673!--       Allocate 1-element array for surface temperature
2674!--       (RRTMG anticipates an array as passed argument).
2675          ALLOCATE ( rrtm_tsfc(1) )
2676!
2677!--       Allocate surface emissivity.
2678!--       Values will be given directly before calling rrtm_lw.
2679          ALLOCATE ( rrtm_emis(0:0,1:nbndlw+1) )
2680
2681!
2682!--       Initialize RRTMG, before check if files are existent
2683          INQUIRE( FILE='rrtmg_lw.nc', EXIST=lw_exists )
2684          IF ( .NOT. lw_exists )  THEN
2685             message_string = 'Input file rrtmg_lw.nc' //                &
2686                            '&for rrtmg missing. ' // &
2687                            '&Please provide <jobname>_lsw file in the INPUT directory.'
2688             CALL message( 'radiation_init', 'PA0583', 1, 2, 0, 6, 0 )
2689          ENDIF         
2690          INQUIRE( FILE='rrtmg_sw.nc', EXIST=sw_exists )
2691          IF ( .NOT. sw_exists )  THEN
2692             message_string = 'Input file rrtmg_sw.nc' //                &
2693                            '&for rrtmg missing. ' // &
2694                            '&Please provide <jobname>_rsw file in the INPUT directory.'
2695             CALL message( 'radiation_init', 'PA0584', 1, 2, 0, 6, 0 )
2696          ENDIF         
2697         
2698          IF ( lw_radiation )  CALL rrtmg_lw_ini ( c_p )
2699          IF ( sw_radiation )  CALL rrtmg_sw_ini ( c_p )
2700         
2701!
2702!--       Set input files for RRTMG
2703          INQUIRE(FILE="RAD_SND_DATA", EXIST=snd_exists) 
2704          IF ( .NOT. snd_exists )  THEN
2705             rrtm_input_file = "rrtmg_lw.nc"
2706          ENDIF
2707
2708!
2709!--       Read vertical layers for RRTMG from sounding data
2710!--       The routine provides nzt_rad, hyp_snd(1:nzt_rad),
2711!--       t_snd(nzt+2:nzt_rad), rrtm_play(1:nzt_rad), rrtm_plev(1_nzt_rad+1),
2712!--       rrtm_tlay(nzt+2:nzt_rad), rrtm_tlev(nzt+2:nzt_rad+1)
2713          CALL read_sounding_data
2714
2715!
2716!--       Read trace gas profiles from file. This routine provides
2717!--       the rrtm_ arrays (1:nzt_rad+1)
2718          CALL read_trace_gas_data
2719#endif
2720       ENDIF
2721
2722!
2723!--    Perform user actions if required
2724       CALL user_init_radiation
2725
2726!
2727!--    Calculate radiative fluxes at model start
2728       SELECT CASE ( TRIM( radiation_scheme ) )
2729
2730          CASE ( 'rrtmg' )
2731             CALL radiation_rrtmg
2732
2733          CASE ( 'clear-sky' )
2734             CALL radiation_clearsky
2735
2736          CASE ( 'constant' )
2737             CALL radiation_constant
2738
2739          CASE DEFAULT
2740
2741       END SELECT
2742
2743! readjust date and time to its initial value
2744       CALL init_date_and_time
2745
2746       CALL location_message( 'finished', .TRUE. )
2747
2748!
2749!--    Find all discretized apparent solar positions for radiation interaction.
2750       IF ( radiation_interactions )  CALL radiation_presimulate_solar_pos
2751
2752!
2753!--    If required, read or calculate and write out the SVF
2754       IF ( radiation_interactions .AND. read_svf)  THEN
2755!
2756!--       Read sky-view factors and further required data from file
2757          CALL location_message( '    Start reading SVF from file', .FALSE. )
2758          CALL radiation_read_svf()
2759          CALL location_message( '    Reading SVF from file has finished', .TRUE. )
2760
2761       ELSEIF ( radiation_interactions .AND. .NOT. read_svf)  THEN
2762!
2763!--       calculate SFV and CSF
2764          CALL location_message( '    Start calculation of SVF', .FALSE. )
2765          CALL radiation_calc_svf()
2766          CALL location_message( '    Calculation of SVF has finished', .TRUE. )
2767       ENDIF
2768
2769       IF ( radiation_interactions .AND. write_svf)  THEN
2770!
2771!--       Write svf, csf svfsurf and csfsurf data to file
2772          CALL location_message( '    Start writing SVF in file', .FALSE. )
2773          CALL radiation_write_svf()
2774          CALL location_message( '    Writing SVF in file has finished', .TRUE. )
2775       ENDIF
2776
2777!
2778!--    Adjust radiative fluxes. In case of urban and land surfaces, also
2779!--    call an initial interaction.
2780       IF ( radiation_interactions )  THEN
2781          CALL radiation_interaction
2782       ENDIF
2783
2784       RETURN
2785
2786    END SUBROUTINE radiation_init
2787
2788
2789!------------------------------------------------------------------------------!
2790! Description:
2791! ------------
2792!> A simple clear sky radiation model
2793!------------------------------------------------------------------------------!
2794    SUBROUTINE radiation_clearsky
2795
2796
2797       IMPLICIT NONE
2798
2799       INTEGER(iwp) ::  l         !< running index for surface orientation
2800       REAL(wp)     ::  pt1       !< potential temperature at first grid level or mean value at urban layer top
2801       REAL(wp)     ::  pt1_l     !< potential temperature at first grid level or mean value at urban layer top at local subdomain
2802       REAL(wp)     ::  ql1       !< liquid water mixing ratio at first grid level or mean value at urban layer top
2803       REAL(wp)     ::  ql1_l     !< liquid water mixing ratio at first grid level or mean value at urban layer top at local subdomain
2804
2805       TYPE(surf_type), POINTER ::  surf !< pointer on respective surface type, used to generalize routine   
2806
2807!
2808!--    Calculate current zenith angle
2809       CALL calc_zenith
2810
2811!
2812!--    Calculate sky transmissivity
2813       sky_trans = 0.6_wp + 0.2_wp * zenith(0)
2814
2815!
2816!--    Calculate value of the Exner function at model surface
2817!
2818!--    In case averaged radiation is used, calculate mean temperature and
2819!--    liquid water mixing ratio at the urban-layer top.
2820       IF ( average_radiation ) THEN
2821          pt1   = 0.0_wp
2822          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1   = 0.0_wp
2823
2824          pt1_l = SUM( pt(nzut,nys:nyn,nxl:nxr) )
2825          IF ( bulk_cloud_model  .OR.  cloud_droplets  )  ql1_l = SUM( ql(nzut,nys:nyn,nxl:nxr) )
2826
2827#if defined( __parallel )     
2828          IF ( collective_wait )  CALL MPI_BARRIER( comm2d, ierr )
2829          CALL MPI_ALLREDUCE( pt1_l, pt1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
2830          IF ( ierr /= 0 ) THEN
2831              WRITE(9,*) 'Error MPI_AllReduce1:', ierr, pt1_l, pt1
2832              FLUSH(9)
2833          ENDIF
2834
2835          IF ( bulk_cloud_model  .OR.  cloud_droplets ) THEN
2836              CALL MPI_ALLREDUCE( ql1_l, ql1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
2837              IF ( ierr /= 0 ) THEN
2838                  WRITE(9,*) 'Error MPI_AllReduce2:', ierr, ql1_l, ql1
2839                  FLUSH(9)
2840              ENDIF
2841          ENDIF
2842#else
2843          pt1 = pt1_l 
2844          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1 = ql1_l
2845#endif
2846
2847          IF ( bulk_cloud_model  .OR.  cloud_droplets  )  pt1 = pt1 + lv_d_cp / exner(nzut) * ql1
2848!
2849!--       Finally, divide by number of grid points
2850          pt1 = pt1 / REAL( ( nx + 1 ) * ( ny + 1 ), KIND=wp )
2851       ENDIF
2852!
2853!--    Call clear-sky calculation for each surface orientation.
2854!--    First, horizontal surfaces
2855       surf => surf_lsm_h
2856       CALL radiation_clearsky_surf
2857       surf => surf_usm_h
2858       CALL radiation_clearsky_surf
2859!
2860!--    Vertical surfaces
2861       DO  l = 0, 3
2862          surf => surf_lsm_v(l)
2863          CALL radiation_clearsky_surf
2864          surf => surf_usm_v(l)
2865          CALL radiation_clearsky_surf
2866       ENDDO
2867
2868       CONTAINS
2869
2870          SUBROUTINE radiation_clearsky_surf
2871
2872             IMPLICIT NONE
2873
2874             INTEGER(iwp) ::  i         !< index x-direction
2875             INTEGER(iwp) ::  j         !< index y-direction
2876             INTEGER(iwp) ::  k         !< index z-direction
2877             INTEGER(iwp) ::  m         !< running index for surface elements
2878
2879             IF ( surf%ns < 1 )  RETURN
2880
2881!
2882!--          Calculate radiation fluxes and net radiation (rad_net) assuming
2883!--          homogeneous urban radiation conditions.
2884             IF ( average_radiation ) THEN       
2885
2886                k = nzut
2887
2888                surf%rad_sw_in  = solar_constant * sky_trans * zenith(0)
2889                surf%rad_sw_out = albedo_urb * surf%rad_sw_in
2890               
2891                surf%rad_lw_in  = 0.8_wp * sigma_sb * (pt1 * exner(k+1))**4
2892
2893                surf%rad_lw_out = emissivity_urb * sigma_sb * (t_rad_urb)**4   &
2894                                    + (1.0_wp - emissivity_urb) * surf%rad_lw_in
2895
2896                surf%rad_net = surf%rad_sw_in - surf%rad_sw_out                &
2897                             + surf%rad_lw_in - surf%rad_lw_out
2898
2899                surf%rad_lw_out_change_0 = 3.0_wp * emissivity_urb * sigma_sb  &
2900                                           * (t_rad_urb)**3
2901
2902!
2903!--          Calculate radiation fluxes and net radiation (rad_net) for each surface
2904!--          element.
2905             ELSE
2906
2907                DO  m = 1, surf%ns
2908                   i = surf%i(m)
2909                   j = surf%j(m)
2910                   k = surf%k(m)
2911
2912                   surf%rad_sw_in(m) = solar_constant * sky_trans * zenith(0)
2913
2914!
2915!--                Weighted average according to surface fraction.
2916!--                ATTENTION: when radiation interactions are switched on the
2917!--                calculated fluxes below are not actually used as they are
2918!--                overwritten in radiation_interaction.
2919                   surf%rad_sw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
2920                                          surf%albedo(ind_veg_wall,m)          &
2921                                        + surf%frac(ind_pav_green,m) *         &
2922                                          surf%albedo(ind_pav_green,m)         &
2923                                        + surf%frac(ind_wat_win,m)   *         &
2924                                          surf%albedo(ind_wat_win,m) )         &
2925                                        * surf%rad_sw_in(m)
2926
2927                   surf%rad_lw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
2928                                          surf%emissivity(ind_veg_wall,m)      &
2929                                        + surf%frac(ind_pav_green,m) *         &
2930                                          surf%emissivity(ind_pav_green,m)     &
2931                                        + surf%frac(ind_wat_win,m)   *         &
2932                                          surf%emissivity(ind_wat_win,m)       &
2933                                        )                                      &
2934                                        * sigma_sb                             &
2935                                        * ( surf%pt_surface(m) * exner(nzb) )**4
2936
2937                   surf%rad_lw_out_change_0(m) =                               &
2938                                      ( surf%frac(ind_veg_wall,m)  *           &
2939                                        surf%emissivity(ind_veg_wall,m)        &
2940                                      + surf%frac(ind_pav_green,m) *           &
2941                                        surf%emissivity(ind_pav_green,m)       &
2942                                      + surf%frac(ind_wat_win,m)   *           &
2943                                        surf%emissivity(ind_wat_win,m)         &
2944                                      ) * 3.0_wp * sigma_sb                    &
2945                                      * ( surf%pt_surface(m) * exner(nzb) )** 3
2946
2947
2948                   IF ( bulk_cloud_model  .OR.  cloud_droplets  )  THEN
2949                      pt1 = pt(k,j,i) + lv_d_cp / exner(k) * ql(k,j,i)
2950                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb * (pt1 * exner(k))**4
2951                   ELSE
2952                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb * (pt(k,j,i) * exner(k))**4
2953                   ENDIF
2954
2955                   surf%rad_net(m) = surf%rad_sw_in(m) - surf%rad_sw_out(m)    &
2956                                   + surf%rad_lw_in(m) - surf%rad_lw_out(m)
2957
2958                ENDDO
2959
2960             ENDIF
2961
2962!
2963!--          Fill out values in radiation arrays
2964             DO  m = 1, surf%ns
2965                i = surf%i(m)
2966                j = surf%j(m)
2967                rad_sw_in(0,j,i) = surf%rad_sw_in(m)
2968                rad_sw_out(0,j,i) = surf%rad_sw_out(m)
2969                rad_lw_in(0,j,i) = surf%rad_lw_in(m)
2970                rad_lw_out(0,j,i) = surf%rad_lw_out(m)
2971             ENDDO
2972 
2973          END SUBROUTINE radiation_clearsky_surf
2974
2975    END SUBROUTINE radiation_clearsky
2976
2977
2978!------------------------------------------------------------------------------!
2979! Description:
2980! ------------
2981!> This scheme keeps the prescribed net radiation constant during the run
2982!------------------------------------------------------------------------------!
2983    SUBROUTINE radiation_constant
2984
2985
2986       IMPLICIT NONE
2987
2988       INTEGER(iwp) ::  l         !< running index for surface orientation
2989
2990       REAL(wp)     ::  pt1       !< potential temperature at first grid level or mean value at urban layer top
2991       REAL(wp)     ::  pt1_l     !< potential temperature at first grid level or mean value at urban layer top at local subdomain
2992       REAL(wp)     ::  ql1       !< liquid water mixing ratio at first grid level or mean value at urban layer top
2993       REAL(wp)     ::  ql1_l     !< liquid water mixing ratio at first grid level or mean value at urban layer top at local subdomain
2994
2995       TYPE(surf_type), POINTER ::  surf !< pointer on respective surface type, used to generalize routine
2996
2997!
2998!--    In case averaged radiation is used, calculate mean temperature and
2999!--    liquid water mixing ratio at the urban-layer top.
3000       IF ( average_radiation ) THEN   
3001          pt1   = 0.0_wp
3002          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1   = 0.0_wp
3003
3004          pt1_l = SUM( pt(nzut,nys:nyn,nxl:nxr) )
3005          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1_l = SUM( ql(nzut,nys:nyn,nxl:nxr) )
3006
3007#if defined( __parallel )     
3008          IF ( collective_wait )  CALL MPI_BARRIER( comm2d, ierr )
3009          CALL MPI_ALLREDUCE( pt1_l, pt1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
3010          IF ( ierr /= 0 ) THEN
3011              WRITE(9,*) 'Error MPI_AllReduce3:', ierr, pt1_l, pt1
3012              FLUSH(9)
3013          ENDIF
3014          IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
3015             CALL MPI_ALLREDUCE( ql1_l, ql1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
3016             IF ( ierr /= 0 ) THEN
3017                 WRITE(9,*) 'Error MPI_AllReduce4:', ierr, ql1_l, ql1
3018                 FLUSH(9)
3019             ENDIF
3020          ENDIF
3021#else
3022          pt1 = pt1_l
3023          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1 = ql1_l
3024#endif
3025          IF ( bulk_cloud_model  .OR.  cloud_droplets )  pt1 = pt1 + lv_d_cp / exner(nzut+1) * ql1
3026!
3027!--       Finally, divide by number of grid points
3028          pt1 = pt1 / REAL( ( nx + 1 ) * ( ny + 1 ), KIND=wp )
3029       ENDIF
3030
3031!
3032!--    First, horizontal surfaces
3033       surf => surf_lsm_h
3034       CALL radiation_constant_surf
3035       surf => surf_usm_h
3036       CALL radiation_constant_surf
3037!
3038!--    Vertical surfaces
3039       DO  l = 0, 3
3040          surf => surf_lsm_v(l)
3041          CALL radiation_constant_surf
3042          surf => surf_usm_v(l)
3043          CALL radiation_constant_surf
3044       ENDDO
3045
3046       CONTAINS
3047
3048          SUBROUTINE radiation_constant_surf
3049
3050             IMPLICIT NONE
3051
3052             INTEGER(iwp) ::  i         !< index x-direction
3053             INTEGER(iwp) ::  ioff      !< offset between surface element and adjacent grid point along x
3054             INTEGER(iwp) ::  j         !< index y-direction
3055             INTEGER(iwp) ::  joff      !< offset between surface element and adjacent grid point along y
3056             INTEGER(iwp) ::  k         !< index z-direction
3057             INTEGER(iwp) ::  koff      !< offset between surface element and adjacent grid point along z
3058             INTEGER(iwp) ::  m         !< running index for surface elements
3059
3060             IF ( surf%ns < 1 )  RETURN
3061
3062!--          Calculate homogenoeus urban radiation fluxes
3063             IF ( average_radiation ) THEN
3064
3065                surf%rad_net = net_radiation
3066
3067                surf%rad_lw_in  = 0.8_wp * sigma_sb * (pt1 * exner(nzut+1))**4
3068
3069                surf%rad_lw_out = emissivity_urb * sigma_sb * (t_rad_urb)**4   &
3070                                    + ( 1.0_wp - emissivity_urb )             & ! shouldn't be this a bulk value -- emissivity_urb?
3071                                    * surf%rad_lw_in
3072
3073                surf%rad_lw_out_change_0 = 3.0_wp * emissivity_urb * sigma_sb  &
3074                                           * t_rad_urb**3
3075
3076                surf%rad_sw_in = ( surf%rad_net - surf%rad_lw_in               &
3077                                     + surf%rad_lw_out )                       &
3078                                     / ( 1.0_wp - albedo_urb )
3079
3080                surf%rad_sw_out =  albedo_urb * surf%rad_sw_in
3081
3082!
3083!--          Calculate radiation fluxes for each surface element
3084             ELSE
3085!
3086!--             Determine index offset between surface element and adjacent
3087!--             atmospheric grid point
3088                ioff = surf%ioff
3089                joff = surf%joff
3090                koff = surf%koff
3091
3092!
3093!--             Prescribe net radiation and estimate the remaining radiative fluxes
3094                DO  m = 1, surf%ns
3095                   i = surf%i(m)
3096                   j = surf%j(m)
3097                   k = surf%k(m)
3098
3099                   surf%rad_net(m) = net_radiation
3100
3101                   IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
3102                      pt1 = pt(k,j,i) + lv_d_cp / exner(k) * ql(k,j,i)
3103                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb * (pt1 * exner(k))**4
3104                   ELSE
3105                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb *                 &
3106                                             ( pt(k,j,i) * exner(k) )**4
3107                   ENDIF
3108
3109!
3110!--                Weighted average according to surface fraction.
3111                   surf%rad_lw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
3112                                          surf%emissivity(ind_veg_wall,m)      &
3113                                        + surf%frac(ind_pav_green,m) *         &
3114                                          surf%emissivity(ind_pav_green,m)     &
3115                                        + surf%frac(ind_wat_win,m)   *         &
3116                                          surf%emissivity(ind_wat_win,m)       &
3117                                        )                                      &
3118                                      * sigma_sb                               &
3119                                      * ( surf%pt_surface(m) * exner(nzb) )**4
3120
3121                   surf%rad_sw_in(m) = ( surf%rad_net(m) - surf%rad_lw_in(m)   &
3122                                       + surf%rad_lw_out(m) )                  &
3123                                       / ( 1.0_wp -                            &
3124                                          ( surf%frac(ind_veg_wall,m)  *       &
3125                                            surf%albedo(ind_veg_wall,m)        &
3126                                         +  surf%frac(ind_pav_green,m) *       &
3127                                            surf%albedo(ind_pav_green,m)       &
3128                                         +  surf%frac(ind_wat_win,m)   *       &
3129                                            surf%albedo(ind_wat_win,m) )       &
3130                                         )
3131
3132                   surf%rad_sw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
3133                                          surf%albedo(ind_veg_wall,m)          &
3134                                        + surf%frac(ind_pav_green,m) *         &
3135                                          surf%albedo(ind_pav_green,m)         &
3136                                        + surf%frac(ind_wat_win,m)   *         &
3137                                          surf%albedo(ind_wat_win,m) )         &
3138                                      * surf%rad_sw_in(m)
3139
3140                ENDDO
3141
3142             ENDIF
3143
3144!
3145!--          Fill out values in radiation arrays
3146             DO  m = 1, surf%ns
3147                i = surf%i(m)
3148                j = surf%j(m)
3149                rad_sw_in(0,j,i) = surf%rad_sw_in(m)
3150                rad_sw_out(0,j,i) = surf%rad_sw_out(m)
3151                rad_lw_in(0,j,i) = surf%rad_lw_in(m)
3152                rad_lw_out(0,j,i) = surf%rad_lw_out(m)
3153             ENDDO
3154
3155          END SUBROUTINE radiation_constant_surf
3156         
3157
3158    END SUBROUTINE radiation_constant
3159
3160!------------------------------------------------------------------------------!
3161! Description:
3162! ------------
3163!> Header output for radiation model
3164!------------------------------------------------------------------------------!
3165    SUBROUTINE radiation_header ( io )
3166
3167
3168       IMPLICIT NONE
3169 
3170       INTEGER(iwp), INTENT(IN) ::  io            !< Unit of the output file
3171   
3172
3173       
3174!
3175!--    Write radiation model header
3176       WRITE( io, 3 )
3177
3178       IF ( radiation_scheme == "constant" )  THEN
3179          WRITE( io, 4 ) net_radiation
3180       ELSEIF ( radiation_scheme == "clear-sky" )  THEN
3181          WRITE( io, 5 )
3182       ELSEIF ( radiation_scheme == "rrtmg" )  THEN
3183          WRITE( io, 6 )
3184          IF ( .NOT. lw_radiation )  WRITE( io, 10 )
3185          IF ( .NOT. sw_radiation )  WRITE( io, 11 )
3186       ENDIF
3187
3188       IF ( albedo_type_f%from_file  .OR.  vegetation_type_f%from_file  .OR.   &
3189            pavement_type_f%from_file  .OR.  water_type_f%from_file  .OR.      &
3190            building_type_f%from_file )  THEN
3191             WRITE( io, 13 )
3192       ELSE 
3193          IF ( albedo_type == 0 )  THEN
3194             WRITE( io, 7 ) albedo
3195          ELSE
3196             WRITE( io, 8 ) TRIM( albedo_type_name(albedo_type) )
3197          ENDIF
3198       ENDIF
3199       IF ( constant_albedo )  THEN
3200          WRITE( io, 9 )
3201       ENDIF
3202       
3203       WRITE( io, 12 ) dt_radiation
3204 
3205
3206 3 FORMAT (//' Radiation model information:'/                                  &
3207              ' ----------------------------'/)
3208 4 FORMAT ('    --> Using constant net radiation: net_radiation = ', F6.2,     &
3209           // 'W/m**2')
3210 5 FORMAT ('    --> Simple radiation scheme for clear sky is used (no clouds,',&
3211                   ' default)')
3212 6 FORMAT ('    --> RRTMG scheme is used')
3213 7 FORMAT (/'    User-specific surface albedo: albedo =', F6.3)
3214 8 FORMAT (/'    Albedo is set for land surface type: ', A)
3215 9 FORMAT (/'    --> Albedo is fixed during the run')
321610 FORMAT (/'    --> Longwave radiation is disabled')
321711 FORMAT (/'    --> Shortwave radiation is disabled.')
321812 FORMAT  ('    Timestep: dt_radiation = ', F6.2, '  s')
321913 FORMAT (/'    Albedo is set individually for each xy-location, according ', &
3220                 'to given surface type.')
3221
3222
3223    END SUBROUTINE radiation_header
3224   
3225
3226!------------------------------------------------------------------------------!
3227! Description:
3228! ------------
3229!> Parin for &radiation_parameters for radiation model
3230!------------------------------------------------------------------------------!
3231    SUBROUTINE radiation_parin
3232
3233
3234       IMPLICIT NONE
3235
3236       CHARACTER (LEN=80) ::  line  !< dummy string that contains the current line of the parameter file
3237       
3238       NAMELIST /radiation_par/   albedo, albedo_lw_dif, albedo_lw_dir,         &
3239                                  albedo_sw_dif, albedo_sw_dir, albedo_type,    &
3240                                  constant_albedo, dt_radiation, emissivity,    &
3241                                  lw_radiation, max_raytracing_dist,            &
3242                                  min_irrf_value, mrt_geom_human,               &
3243                                  mrt_include_sw, mrt_nlevels,                  &
3244                                  mrt_skip_roof, net_radiation, nrefsteps,      &
3245                                  plant_lw_interact, rad_angular_discretization,&
3246                                  radiation_interactions_on, radiation_scheme,  &
3247                                  raytrace_discrete_azims,                      &
3248                                  raytrace_discrete_elevs, raytrace_mpi_rma,    &
3249                                  skip_time_do_radiation, surface_reflections,  &
3250                                  svfnorm_report_thresh, sw_radiation,          &
3251                                  unscheduled_radiation_calls
3252
3253   
3254       NAMELIST /radiation_parameters/ albedo, albedo_lw_dif, albedo_lw_dir,    &
3255                                  albedo_sw_dif, albedo_sw_dir, albedo_type,    &
3256                                  constant_albedo, dt_radiation, emissivity,    &
3257                                  lw_radiation, max_raytracing_dist,            &
3258                                  min_irrf_value, mrt_geom_human,               &
3259                                  mrt_include_sw, mrt_nlevels,                  &
3260                                  mrt_skip_roof, net_radiation, nrefsteps,      &
3261                                  plant_lw_interact, rad_angular_discretization,&
3262                                  radiation_interactions_on, radiation_scheme,  &
3263                                  raytrace_discrete_azims,                      &
3264                                  raytrace_discrete_elevs, raytrace_mpi_rma,    &
3265                                  skip_time_do_radiation, surface_reflections,  &
3266                                  svfnorm_report_thresh, sw_radiation,          &
3267                                  unscheduled_radiation_calls
3268   
3269       line = ' '
3270       
3271!
3272!--    Try to find radiation model namelist
3273       REWIND ( 11 )
3274       line = ' '
3275       DO WHILE ( INDEX( line, '&radiation_parameters' ) == 0 )
3276          READ ( 11, '(A)', END=12 )  line
3277       ENDDO
3278       BACKSPACE ( 11 )
3279
3280!
3281!--    Read user-defined namelist
3282       READ ( 11, radiation_parameters, ERR = 10 )
3283
3284!
3285!--    Set flag that indicates that the radiation model is switched on
3286       radiation = .TRUE.
3287
3288       GOTO 14
3289
3290 10    BACKSPACE( 11 )
3291       READ( 11 , '(A)') line
3292       CALL parin_fail_message( 'radiation_parameters', line )
3293!
3294!--    Try to find old namelist
3295 12    REWIND ( 11 )
3296       line = ' '
3297       DO WHILE ( INDEX( line, '&radiation_par' ) == 0 )
3298          READ ( 11, '(A)', END=14 )  line
3299       ENDDO
3300       BACKSPACE ( 11 )
3301
3302!
3303!--    Read user-defined namelist
3304       READ ( 11, radiation_par, ERR = 13, END = 14 )
3305
3306       message_string = 'namelist radiation_par is deprecated and will be ' // &
3307                     'removed in near future. Please use namelist ' //         &
3308                     'radiation_parameters instead'
3309       CALL message( 'radiation_parin', 'PA0487', 0, 1, 0, 6, 0 )
3310
3311!
3312!--    Set flag that indicates that the radiation model is switched on
3313       radiation = .TRUE.
3314
3315       IF ( .NOT.  radiation_interactions_on  .AND.  surface_reflections )  THEN
3316          message_string = 'surface_reflections is allowed only when '      // &
3317               'radiation_interactions_on is set to TRUE'
3318          CALL message( 'radiation_parin', 'PA0293',1, 2, 0, 6, 0 )
3319       ENDIF
3320
3321       GOTO 14
3322
3323 13    BACKSPACE( 11 )
3324       READ( 11 , '(A)') line
3325       CALL parin_fail_message( 'radiation_par', line )
3326
3327 14    CONTINUE
3328       
3329    END SUBROUTINE radiation_parin
3330
3331
3332!------------------------------------------------------------------------------!
3333! Description:
3334! ------------
3335!> Implementation of the RRTMG radiation_scheme
3336!------------------------------------------------------------------------------!
3337    SUBROUTINE radiation_rrtmg
3338
3339#if defined ( __rrtmg )
3340       USE indices,                                                            &
3341           ONLY:  nbgp
3342
3343       USE particle_attributes,                                                &
3344           ONLY:  grid_particles, number_of_particles, particles,              &
3345                  particle_advection_start, prt_count
3346
3347       IMPLICIT NONE
3348
3349
3350       INTEGER(iwp) ::  i, j, k, l, m, n !< loop indices
3351       INTEGER(iwp) ::  k_topo     !< topography top index
3352
3353       REAL(wp)     ::  nc_rad, &    !< number concentration of cloud droplets
3354                        s_r2,   &    !< weighted sum over all droplets with r^2
3355                        s_r3         !< weighted sum over all droplets with r^3
3356
3357       REAL(wp), DIMENSION(0:nzt+1) :: pt_av, q_av, ql_av
3358!
3359!--    Just dummy arguments
3360       REAL(wp), DIMENSION(:,:,:), ALLOCATABLE :: rrtm_lw_taucld_dum,          &
3361                                                  rrtm_lw_tauaer_dum,          &
3362                                                  rrtm_sw_taucld_dum,          &
3363                                                  rrtm_sw_ssacld_dum,          &
3364                                                  rrtm_sw_asmcld_dum,          &
3365                                                  rrtm_sw_fsfcld_dum,          &
3366                                                  rrtm_sw_tauaer_dum,          &
3367                                                  rrtm_sw_ssaaer_dum,          &
3368                                                  rrtm_sw_asmaer_dum,          &
3369                                                  rrtm_sw_ecaer_dum
3370
3371!
3372!--    Calculate current (cosine of) zenith angle and whether the sun is up
3373       CALL calc_zenith     
3374!
3375!--    Calculate surface albedo. In case average radiation is applied,
3376!--    this is not required.
3377#if defined( __netcdf )
3378       IF ( .NOT. constant_albedo )  THEN
3379!
3380!--       Horizontally aligned default, natural and urban surfaces
3381          CALL calc_albedo( surf_lsm_h    )
3382          CALL calc_albedo( surf_usm_h    )
3383!
3384!--       Vertically aligned default, natural and urban surfaces
3385          DO  l = 0, 3
3386             CALL calc_albedo( surf_lsm_v(l) )
3387             CALL calc_albedo( surf_usm_v(l) )
3388          ENDDO
3389       ENDIF
3390#endif
3391
3392!
3393!--    Prepare input data for RRTMG
3394
3395!
3396!--    In case of large scale forcing with surface data, calculate new pressure
3397!--    profile. nzt_rad might be modified by these calls and all required arrays
3398!--    will then be re-allocated
3399       IF ( large_scale_forcing  .AND.  lsf_surf )  THEN
3400          CALL read_sounding_data
3401          CALL read_trace_gas_data
3402       ENDIF
3403
3404
3405       IF ( average_radiation ) THEN
3406
3407          rrtm_asdir(1)  = albedo_urb
3408          rrtm_asdif(1)  = albedo_urb
3409          rrtm_aldir(1)  = albedo_urb
3410          rrtm_aldif(1)  = albedo_urb
3411
3412          rrtm_emis = emissivity_urb
3413!
3414!--       Calculate mean pt profile. Actually, only one height level is required.
3415          CALL calc_mean_profile( pt, 4 )
3416          pt_av = hom(:, 1, 4, 0)
3417         
3418          IF ( humidity )  THEN
3419             CALL calc_mean_profile( q, 41 )
3420             q_av  = hom(:, 1, 41, 0)
3421          ENDIF
3422!
3423!--       Prepare profiles of temperature and H2O volume mixing ratio
3424          rrtm_tlev(0,nzb+1) = t_rad_urb
3425
3426          IF ( bulk_cloud_model )  THEN
3427
3428             CALL calc_mean_profile( ql, 54 )
3429             ! average ql is now in hom(:, 1, 54, 0)
3430             ql_av = hom(:, 1, 54, 0)
3431             
3432             DO k = nzb+1, nzt+1
3433                rrtm_tlay(0,k) = pt_av(k) * ( (hyp(k) ) / 100000._wp       &
3434                                 )**.286_wp + lv_d_cp * ql_av(k)
3435                rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * (q_av(k) - ql_av(k))
3436             ENDDO
3437          ELSE
3438             DO k = nzb+1, nzt+1
3439                rrtm_tlay(0,k) = pt_av(k) * ( (hyp(k) ) / 100000._wp       &
3440                                 )**.286_wp
3441             ENDDO
3442
3443             IF ( humidity )  THEN
3444                DO k = nzb+1, nzt+1
3445                   rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * q_av(k)
3446                ENDDO
3447             ELSE
3448                rrtm_h2ovmr(0,nzb+1:nzt+1) = 0.0_wp
3449             ENDIF
3450          ENDIF
3451
3452!
3453!--       Avoid temperature/humidity jumps at the top of the LES domain by
3454!--       linear interpolation from nzt+2 to nzt+7
3455          DO k = nzt+2, nzt+7
3456             rrtm_tlay(0,k) = rrtm_tlay(0,nzt+1)                            &
3457                           + ( rrtm_tlay(0,nzt+8) - rrtm_tlay(0,nzt+1) )    &
3458                           / ( rrtm_play(0,nzt+8) - rrtm_play(0,nzt+1) )    &
3459                           * ( rrtm_play(0,k) - rrtm_play(0,nzt+1) )
3460
3461             rrtm_h2ovmr(0,k) = rrtm_h2ovmr(0,nzt+1)                        &
3462                           + ( rrtm_h2ovmr(0,nzt+8) - rrtm_h2ovmr(0,nzt+1) )&
3463                           / ( rrtm_play(0,nzt+8)   - rrtm_play(0,nzt+1)   )&
3464                           * ( rrtm_play(0,k) - rrtm_play(0,nzt+1) )
3465
3466          ENDDO
3467
3468!--       Linear interpolate to zw grid
3469          DO k = nzb+2, nzt+8
3470             rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k) -        &
3471                                rrtm_tlay(0,k-1))                           &
3472                                / ( rrtm_play(0,k) - rrtm_play(0,k-1) )     &
3473                                * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
3474          ENDDO
3475
3476
3477!
3478!--       Calculate liquid water path and cloud fraction for each column.
3479!--       Note that LWP is required in g/m2 instead of kg/kg m.
3480          rrtm_cldfr  = 0.0_wp
3481          rrtm_reliq  = 0.0_wp
3482          rrtm_cliqwp = 0.0_wp
3483          rrtm_icld   = 0
3484
3485          IF ( bulk_cloud_model )  THEN
3486             DO k = nzb+1, nzt+1
3487                rrtm_cliqwp(0,k) =  ql_av(k) * 1000._wp *                   &
3488                                    (rrtm_plev(0,k) - rrtm_plev(0,k+1))     &
3489                                    * 100._wp / g 
3490
3491                IF ( rrtm_cliqwp(0,k) > 0._wp )  THEN
3492                   rrtm_cldfr(0,k) = 1._wp
3493                   IF ( rrtm_icld == 0 )  rrtm_icld = 1
3494
3495!
3496!--                Calculate cloud droplet effective radius
3497                   rrtm_reliq(0,k) = 1.0E6_wp * ( 3.0_wp * ql_av(k)         &
3498                                     * rho_surface                          &
3499                                     / ( 4.0_wp * pi * nc_const * rho_l )   &
3500                                     )**0.33333333333333_wp                 &
3501                                     * EXP( LOG( sigma_gc )**2 )
3502!
3503!--                Limit effective radius
3504                   IF ( rrtm_reliq(0,k) > 0.0_wp )  THEN
3505                      rrtm_reliq(0,k) = MAX(rrtm_reliq(0,k),2.5_wp)
3506                      rrtm_reliq(0,k) = MIN(rrtm_reliq(0,k),60.0_wp)
3507                   ENDIF
3508                ENDIF
3509             ENDDO
3510          ENDIF
3511
3512!
3513!--       Set surface temperature
3514          rrtm_tsfc = t_rad_urb
3515         
3516          IF ( lw_radiation )  THEN       
3517         
3518             CALL rrtmg_lw( 1, nzt_rad      , rrtm_icld    , rrtm_idrv      ,&
3519             rrtm_play       , rrtm_plev    , rrtm_tlay    , rrtm_tlev      ,&
3520             rrtm_tsfc       , rrtm_h2ovmr  , rrtm_o3vmr   , rrtm_co2vmr    ,&
3521             rrtm_ch4vmr     , rrtm_n2ovmr  , rrtm_o2vmr   , rrtm_cfc11vmr  ,&
3522             rrtm_cfc12vmr   , rrtm_cfc22vmr, rrtm_ccl4vmr , rrtm_emis      ,&
3523             rrtm_inflglw    , rrtm_iceflglw, rrtm_liqflglw, rrtm_cldfr     ,&
3524             rrtm_lw_taucld  , rrtm_cicewp  , rrtm_cliqwp  , rrtm_reice     ,& 
3525             rrtm_reliq      , rrtm_lw_tauaer,                               &
3526             rrtm_lwuflx     , rrtm_lwdflx  , rrtm_lwhr  ,                   &
3527             rrtm_lwuflxc    , rrtm_lwdflxc , rrtm_lwhrc ,                   &
3528             rrtm_lwuflx_dt  ,  rrtm_lwuflxc_dt )
3529
3530!
3531!--          Save fluxes
3532             DO k = nzb, nzt+1
3533                rad_lw_in(k,:,:)  = rrtm_lwdflx(0,k)
3534                rad_lw_out(k,:,:) = rrtm_lwuflx(0,k)
3535             ENDDO
3536             rad_lw_in_diff(:,:) = rad_lw_in(0,:,:)
3537!
3538!--          Save heating rates (convert from K/d to K/h).
3539!--          Further, even though an aggregated radiation is computed, map
3540!--          signle-column profiles on top of any topography, in order to
3541!--          obtain correct near surface radiation heating/cooling rates.
3542             DO  i = nxl, nxr
3543                DO  j = nys, nyn
3544                   k_topo = get_topography_top_index_ji( j, i, 's' )
3545                   DO k = k_topo+1, nzt+1
3546                      rad_lw_hr(k,j,i)     = rrtm_lwhr(0,k-k_topo)  * d_hours_day
3547                      rad_lw_cs_hr(k,j,i)  = rrtm_lwhrc(0,k-k_topo) * d_hours_day
3548                   ENDDO
3549                ENDDO
3550             ENDDO
3551
3552          ENDIF
3553
3554          IF ( sw_radiation .AND. sun_up )  THEN
3555             CALL rrtmg_sw( 1, nzt_rad      , rrtm_icld     , rrtm_iaer      ,&
3556             rrtm_play      , rrtm_plev     , rrtm_tlay     , rrtm_tlev      ,&
3557             rrtm_tsfc      , rrtm_h2ovmr   , rrtm_o3vmr    , rrtm_co2vmr    ,&
3558             rrtm_ch4vmr    , rrtm_n2ovmr   , rrtm_o2vmr    , rrtm_asdir     ,&
3559             rrtm_asdif     , rrtm_aldir    , rrtm_aldif    , zenith         ,&
3560             0.0_wp         , day_of_year   , solar_constant, rrtm_inflgsw   ,&
3561             rrtm_iceflgsw  , rrtm_liqflgsw , rrtm_cldfr    , rrtm_sw_taucld ,&
3562             rrtm_sw_ssacld , rrtm_sw_asmcld, rrtm_sw_fsfcld, rrtm_cicewp    ,&
3563             rrtm_cliqwp    , rrtm_reice    , rrtm_reliq    , rrtm_sw_tauaer ,&
3564             rrtm_sw_ssaaer , rrtm_sw_asmaer, rrtm_sw_ecaer , rrtm_swuflx    ,&
3565             rrtm_swdflx    , rrtm_swhr     , rrtm_swuflxc  , rrtm_swdflxc   ,&
3566             rrtm_swhrc     , rrtm_dirdflux , rrtm_difdflux )
3567 
3568!
3569!--          Save fluxes:
3570!--          - whole domain
3571             DO k = nzb, nzt+1
3572                rad_sw_in(k,:,:)  = rrtm_swdflx(0,k)
3573                rad_sw_out(k,:,:) = rrtm_swuflx(0,k)
3574             ENDDO
3575!--          - direct and diffuse SW at urban-surface-layer (required by RTM)
3576             rad_sw_in_dir(:,:) = rrtm_dirdflux(0,nzb)
3577             rad_sw_in_diff(:,:) = rrtm_difdflux(0,nzb)
3578
3579!
3580!--          Save heating rates (convert from K/d to K/s)
3581             DO k = nzb+1, nzt+1
3582                rad_sw_hr(k,:,:)     = rrtm_swhr(0,k)  * d_hours_day
3583                rad_sw_cs_hr(k,:,:)  = rrtm_swhrc(0,k) * d_hours_day
3584             ENDDO
3585!
3586!--       Solar radiation is zero during night
3587          ELSE
3588             rad_sw_in  = 0.0_wp
3589             rad_sw_out = 0.0_wp
3590             rad_sw_in_dir(:,:) = 0.0_wp
3591             rad_sw_in_diff(:,:) = 0.0_wp
3592          ENDIF
3593!
3594!--    RRTMG is called for each (j,i) grid point separately, starting at the
3595!--    highest topography level. Here no RTM is used since average_radiation is false
3596       ELSE
3597!
3598!--       Loop over all grid points
3599          DO i = nxl, nxr
3600             DO j = nys, nyn
3601
3602!
3603!--             Prepare profiles of temperature and H2O volume mixing ratio
3604                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
3605                   rrtm_tlev(0,nzb+1) = surf_lsm_h%pt_surface(m) * exner(nzb)
3606                ENDDO
3607                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
3608                   rrtm_tlev(0,nzb+1) = surf_usm_h%pt_surface(m) * exner(nzb)
3609                ENDDO
3610
3611
3612                IF ( bulk_cloud_model )  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) - ql(k,j,i))
3617                   ENDDO
3618                ELSEIF ( cloud_droplets )  THEN
3619                   DO k = nzb+1, nzt+1
3620                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)                     &
3621                                        + lv_d_cp * ql(k,j,i)
3622                      rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * q(k,j,i) 
3623                   ENDDO
3624                ELSE
3625                   DO k = nzb+1, nzt+1
3626                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)
3627                   ENDDO
3628
3629                   IF ( humidity )  THEN
3630                      DO k = nzb+1, nzt+1
3631                         rrtm_h2ovmr(0,k) =  mol_mass_air_d_wv * q(k,j,i)
3632                      ENDDO   
3633                   ELSE
3634                      rrtm_h2ovmr(0,nzb+1:nzt+1) = 0.0_wp
3635                   ENDIF
3636                ENDIF
3637
3638!
3639!--             Avoid temperature/humidity jumps at the top of the LES domain by
3640!--             linear interpolation from nzt+2 to nzt+7
3641                DO k = nzt+2, nzt+7
3642                   rrtm_tlay(0,k) = rrtm_tlay(0,nzt+1)                         &
3643                                 + ( rrtm_tlay(0,nzt+8) - rrtm_tlay(0,nzt+1) ) &
3644                                 / ( rrtm_play(0,nzt+8) - rrtm_play(0,nzt+1) ) &
3645                                 * ( rrtm_play(0,k)     - rrtm_play(0,nzt+1) )
3646
3647                   rrtm_h2ovmr(0,k) = rrtm_h2ovmr(0,nzt+1)                     &
3648                              + ( rrtm_h2ovmr(0,nzt+8) - rrtm_h2ovmr(0,nzt+1) )&
3649                              / ( rrtm_play(0,nzt+8)   - rrtm_play(0,nzt+1)   )&
3650                              * ( rrtm_play(0,k)       - rrtm_play(0,nzt+1) )
3651
3652                ENDDO
3653
3654!--             Linear interpolate to zw grid
3655                DO k = nzb+2, nzt+8
3656                   rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k) -     &
3657                                      rrtm_tlay(0,k-1))                        &
3658                                      / ( rrtm_play(0,k) - rrtm_play(0,k-1) )  &
3659                                      * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
3660                ENDDO
3661
3662
3663!
3664!--             Calculate liquid water path and cloud fraction for each column.
3665!--             Note that LWP is required in g/m2 instead of kg/kg m.
3666                rrtm_cldfr  = 0.0_wp
3667                rrtm_reliq  = 0.0_wp
3668                rrtm_cliqwp = 0.0_wp
3669                rrtm_icld   = 0
3670
3671                IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
3672                   DO k = nzb+1, nzt+1
3673                      rrtm_cliqwp(0,k) =  ql(k,j,i) * 1000.0_wp *              &
3674                                          (rrtm_plev(0,k) - rrtm_plev(0,k+1))  &
3675                                          * 100.0_wp / g 
3676
3677                      IF ( rrtm_cliqwp(0,k) > 0.0_wp )  THEN
3678                         rrtm_cldfr(0,k) = 1.0_wp
3679                         IF ( rrtm_icld == 0 )  rrtm_icld = 1
3680
3681!
3682!--                      Calculate cloud droplet effective radius
3683                         IF ( bulk_cloud_model )  THEN
3684!
3685!--                         Calculete effective droplet radius. In case of using
3686!--                         cloud_scheme = 'morrison' and a non reasonable number
3687!--                         of cloud droplets the inital aerosol number 
3688!--                         concentration is considered.
3689                            IF ( microphysics_morrison )  THEN
3690                               IF ( nc(k,j,i) > 1.0E-20_wp )  THEN
3691                                  nc_rad = nc(k,j,i)
3692                               ELSE
3693                                  nc_rad = na_init
3694                               ENDIF
3695                            ELSE
3696                               nc_rad = nc_const
3697                            ENDIF 
3698
3699                            rrtm_reliq(0,k) = 1.0E6_wp * ( 3.0_wp * ql(k,j,i)     &
3700                                              * rho_surface                       &
3701                                              / ( 4.0_wp * pi * nc_rad * rho_l )  &
3702                                              )**0.33333333333333_wp              &
3703                                              * EXP( LOG( sigma_gc )**2 )
3704
3705                         ELSEIF ( cloud_droplets )  THEN
3706                            number_of_particles = prt_count(k,j,i)
3707
3708                            IF (number_of_particles <= 0)  CYCLE
3709                            particles => grid_particles(k,j,i)%particles(1:number_of_particles)
3710                            s_r2 = 0.0_wp
3711                            s_r3 = 0.0_wp
3712
3713                            DO  n = 1, number_of_particles
3714                               IF ( particles(n)%particle_mask )  THEN
3715                                  s_r2 = s_r2 + particles(n)%radius**2 *       &
3716                                         particles(n)%weight_factor
3717                                  s_r3 = s_r3 + particles(n)%radius**3 *       &
3718                                         particles(n)%weight_factor
3719                               ENDIF
3720                            ENDDO
3721
3722                            IF ( s_r2 > 0.0_wp )  rrtm_reliq(0,k) = s_r3 / s_r2
3723
3724                         ENDIF
3725
3726!
3727!--                      Limit effective radius
3728                         IF ( rrtm_reliq(0,k) > 0.0_wp )  THEN
3729                            rrtm_reliq(0,k) = MAX(rrtm_reliq(0,k),2.5_wp)
3730                            rrtm_reliq(0,k) = MIN(rrtm_reliq(0,k),60.0_wp)
3731                        ENDIF
3732                      ENDIF
3733                   ENDDO
3734                ENDIF
3735
3736!
3737!--             Write surface emissivity and surface temperature at current
3738!--             surface element on RRTMG-shaped array.
3739!--             Please note, as RRTMG is a single column model, surface attributes
3740!--             are only obtained from horizontally aligned surfaces (for
3741!--             simplicity). Taking surface attributes from horizontal and
3742!--             vertical walls would lead to multiple solutions. 
3743!--             Moreover, for natural- and urban-type surfaces, several surface
3744!--             classes can exist at a surface element next to each other.
3745!--             To obtain bulk parameters, apply a weighted average for these
3746!--             surfaces.
3747                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
3748                   rrtm_emis = surf_lsm_h%frac(ind_veg_wall,m)  *              &
3749                               surf_lsm_h%emissivity(ind_veg_wall,m)  +        &
3750                               surf_lsm_h%frac(ind_pav_green,m) *              &
3751                               surf_lsm_h%emissivity(ind_pav_green,m) +        & 
3752                               surf_lsm_h%frac(ind_wat_win,m)   *              &
3753                               surf_lsm_h%emissivity(ind_wat_win,m)
3754                   rrtm_tsfc = surf_lsm_h%pt_surface(m) * exner(nzb)
3755                ENDDO             
3756                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
3757                   rrtm_emis = surf_usm_h%frac(ind_veg_wall,m)  *              &
3758                               surf_usm_h%emissivity(ind_veg_wall,m)  +        &
3759                               surf_usm_h%frac(ind_pav_green,m) *              &
3760                               surf_usm_h%emissivity(ind_pav_green,m) +        & 
3761                               surf_usm_h%frac(ind_wat_win,m)   *              &
3762                               surf_usm_h%emissivity(ind_wat_win,m)
3763                   rrtm_tsfc = surf_usm_h%pt_surface(m) * exner(nzb)
3764                ENDDO
3765!
3766!--             Obtain topography top index (lower bound of RRTMG)
3767                k_topo = get_topography_top_index_ji( j, i, 's' )
3768
3769                IF ( lw_radiation )  THEN
3770!
3771!--                Due to technical reasons, copy optical depth to dummy arguments
3772!--                which are allocated on the exact size as the rrtmg_lw is called.
3773!--                As one dimesion is allocated with zero size, compiler complains
3774!--                that rank of the array does not match that of the
3775!--                assumed-shaped arguments in the RRTMG library. In order to
3776!--                avoid this, write to dummy arguments and give pass the entire
3777!--                dummy array. Seems to be the only existing work-around. 
3778                   ALLOCATE( rrtm_lw_taucld_dum(1:nbndlw+1,0:0,k_topo+1:nzt_rad+1) )
3779                   ALLOCATE( rrtm_lw_tauaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndlw+1) )
3780
3781                   rrtm_lw_taucld_dum =                                        &
3782                               rrtm_lw_taucld(1:nbndlw+1,0:0,k_topo+1:nzt_rad+1)
3783                   rrtm_lw_tauaer_dum =                                        &
3784                               rrtm_lw_tauaer(0:0,k_topo+1:nzt_rad+1,1:nbndlw+1)
3785
3786                   CALL rrtmg_lw( 1,                                           &                                       
3787                                  nzt_rad-k_topo,                              &
3788                                  rrtm_icld,                                   &
3789                                  rrtm_idrv,                                   &
3790                                  rrtm_play(:,k_topo+1:nzt_rad+1),             &
3791                                  rrtm_plev(:,k_topo+1:nzt_rad+2),             &
3792                                  rrtm_tlay(:,k_topo+1:nzt_rad+1),             &
3793                                  rrtm_tlev(:,k_topo+1:nzt_rad+2),             &
3794                                  rrtm_tsfc,                                   &
3795                                  rrtm_h2ovmr(:,k_topo+1:nzt_rad+1),           &
3796                                  rrtm_o3vmr(:,k_topo+1:nzt_rad+1),            &
3797                                  rrtm_co2vmr(:,k_topo+1:nzt_rad+1),           &
3798                                  rrtm_ch4vmr(:,k_topo+1:nzt_rad+1),           &
3799                                  rrtm_n2ovmr(:,k_topo+1:nzt_rad+1),           &
3800                                  rrtm_o2vmr(:,k_topo+1:nzt_rad+1),            &
3801                                  rrtm_cfc11vmr(:,k_topo+1:nzt_rad+1),         &
3802                                  rrtm_cfc12vmr(:,k_topo+1:nzt_rad+1),         &
3803                                  rrtm_cfc22vmr(:,k_topo+1:nzt_rad+1),         &
3804                                  rrtm_ccl4vmr(:,k_topo+1:nzt_rad+1),          &
3805                                  rrtm_emis,                                   &
3806                                  rrtm_inflglw,                                &
3807                                  rrtm_iceflglw,                               &
3808                                  rrtm_liqflglw,                               &
3809                                  rrtm_cldfr(:,k_topo+1:nzt_rad+1),            &
3810                                  rrtm_lw_taucld_dum,                          &
3811                                  rrtm_cicewp(:,k_topo+1:nzt_rad+1),           &
3812                                  rrtm_cliqwp(:,k_topo+1:nzt_rad+1),           &
3813                                  rrtm_reice(:,k_topo+1:nzt_rad+1),            & 
3814                                  rrtm_reliq(:,k_topo+1:nzt_rad+1),            &
3815                                  rrtm_lw_tauaer_dum,                          &
3816                                  rrtm_lwuflx(:,k_topo:nzt_rad+1),             &
3817                                  rrtm_lwdflx(:,k_topo:nzt_rad+1),             &
3818                                  rrtm_lwhr(:,k_topo+1:nzt_rad+1),             &
3819                                  rrtm_lwuflxc(:,k_topo:nzt_rad+1),            &
3820                                  rrtm_lwdflxc(:,k_topo:nzt_rad+1),            &
3821                                  rrtm_lwhrc(:,k_topo+1:nzt_rad+1),            &
3822                                  rrtm_lwuflx_dt(:,k_topo:nzt_rad+1),          &
3823                                  rrtm_lwuflxc_dt(:,k_topo:nzt_rad+1) )
3824
3825                   DEALLOCATE ( rrtm_lw_taucld_dum )
3826                   DEALLOCATE ( rrtm_lw_tauaer_dum )
3827!
3828!--                Save fluxes
3829                   DO k = k_topo, nzt+1
3830                      rad_lw_in(k,j,i)  = rrtm_lwdflx(0,k)
3831                      rad_lw_out(k,j,i) = rrtm_lwuflx(0,k)
3832                   ENDDO
3833
3834!
3835!--                Save heating rates (convert from K/d to K/h)
3836                   DO k = k_topo+1, nzt+1
3837                      rad_lw_hr(k,j,i)     = rrtm_lwhr(0,k-k_topo)  * d_hours_day
3838                      rad_lw_cs_hr(k,j,i)  = rrtm_lwhrc(0,k-k_topo) * d_hours_day
3839                   ENDDO
3840
3841!
3842!--                Save surface radiative fluxes and change in LW heating rate
3843!--                onto respective surface elements
3844!--                Horizontal surfaces
3845                   DO  m = surf_lsm_h%start_index(j,i),                        &
3846                           surf_lsm_h%end_index(j,i)
3847                      surf_lsm_h%rad_lw_in(m)           = rrtm_lwdflx(0,k_topo)
3848                      surf_lsm_h%rad_lw_out(m)          = rrtm_lwuflx(0,k_topo)
3849                      surf_lsm_h%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k_topo)
3850                   ENDDO             
3851                   DO  m = surf_usm_h%start_index(j,i),                        &
3852                           surf_usm_h%end_index(j,i)
3853                      surf_usm_h%rad_lw_in(m)           = rrtm_lwdflx(0,k_topo)
3854                      surf_usm_h%rad_lw_out(m)          = rrtm_lwuflx(0,k_topo)
3855                      surf_usm_h%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k_topo)
3856                   ENDDO 
3857!
3858!--                Vertical surfaces. Fluxes are obtain at vertical level of the
3859!--                respective surface element
3860                   DO  l = 0, 3
3861                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
3862                              surf_lsm_v(l)%end_index(j,i)
3863                         k                                    = surf_lsm_v(l)%k(m)
3864                         surf_lsm_v(l)%rad_lw_in(m)           = rrtm_lwdflx(0,k)
3865                         surf_lsm_v(l)%rad_lw_out(m)          = rrtm_lwuflx(0,k)
3866                         surf_lsm_v(l)%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k)
3867                      ENDDO             
3868                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
3869                              surf_usm_v(l)%end_index(j,i)
3870                         k                                    = surf_usm_v(l)%k(m)
3871                         surf_usm_v(l)%rad_lw_in(m)           = rrtm_lwdflx(0,k)
3872                         surf_usm_v(l)%rad_lw_out(m)          = rrtm_lwuflx(0,k)
3873                         surf_usm_v(l)%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k)
3874                      ENDDO 
3875                   ENDDO
3876
3877                ENDIF
3878
3879                IF ( sw_radiation .AND. sun_up )  THEN
3880!
3881!--                Get albedo for direct/diffusive long/shortwave radiation at
3882!--                current (y,x)-location from surface variables.
3883!--                Only obtain it from horizontal surfaces, as RRTMG is a single
3884!--                column model
3885!--                (Please note, only one loop will entered, controlled by
3886!--                start-end index.)
3887                   DO  m = surf_lsm_h%start_index(j,i),                        &
3888                           surf_lsm_h%end_index(j,i)
3889                      rrtm_asdir(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3890                                            surf_lsm_h%rrtm_asdir(:,m) )
3891                      rrtm_asdif(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3892                                            surf_lsm_h%rrtm_asdif(:,m) )
3893                      rrtm_aldir(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3894                                            surf_lsm_h%rrtm_aldir(:,m) )
3895                      rrtm_aldif(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3896                                            surf_lsm_h%rrtm_aldif(:,m) )
3897                   ENDDO             
3898                   DO  m = surf_usm_h%start_index(j,i),                        &
3899                           surf_usm_h%end_index(j,i)
3900                      rrtm_asdir(1)  = SUM( surf_usm_h%frac(:,m) *             &
3901                                            surf_usm_h%rrtm_asdir(:,m) )
3902                      rrtm_asdif(1)  = SUM( surf_usm_h%frac(:,m) *             &
3903                                            surf_usm_h%rrtm_asdif(:,m) )
3904                      rrtm_aldir(1)  = SUM( surf_usm_h%frac(:,m) *             &
3905                                            surf_usm_h%rrtm_aldir(:,m) )
3906                      rrtm_aldif(1)  = SUM( surf_usm_h%frac(:,m) *             &
3907                                            surf_usm_h%rrtm_aldif(:,m) )
3908                   ENDDO
3909!
3910!--                Due to technical reasons, copy optical depths and other
3911!--                to dummy arguments which are allocated on the exact size as the
3912!--                rrtmg_sw is called.
3913!--                As one dimesion is allocated with zero size, compiler complains
3914!--                that rank of the array does not match that of the
3915!--                assumed-shaped arguments in the RRTMG library. In order to
3916!--                avoid this, write to dummy arguments and give pass the entire
3917!--                dummy array. Seems to be the only existing work-around. 
3918                   ALLOCATE( rrtm_sw_taucld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3919                   ALLOCATE( rrtm_sw_ssacld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3920                   ALLOCATE( rrtm_sw_asmcld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3921                   ALLOCATE( rrtm_sw_fsfcld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3922                   ALLOCATE( rrtm_sw_tauaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3923                   ALLOCATE( rrtm_sw_ssaaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3924                   ALLOCATE( rrtm_sw_asmaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3925                   ALLOCATE( rrtm_sw_ecaer_dum(0:0,k_topo+1:nzt_rad+1,1:naerec+1)  )
3926     
3927                   rrtm_sw_taucld_dum = rrtm_sw_taucld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3928                   rrtm_sw_ssacld_dum = rrtm_sw_ssacld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3929                   rrtm_sw_asmcld_dum = rrtm_sw_asmcld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3930                   rrtm_sw_fsfcld_dum = rrtm_sw_fsfcld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3931                   rrtm_sw_tauaer_dum = rrtm_sw_tauaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3932                   rrtm_sw_ssaaer_dum = rrtm_sw_ssaaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3933                   rrtm_sw_asmaer_dum = rrtm_sw_asmaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3934                   rrtm_sw_ecaer_dum  = rrtm_sw_ecaer(0:0,k_topo+1:nzt_rad+1,1:naerec+1)
3935
3936                   CALL rrtmg_sw( 1,                                           &
3937                                  nzt_rad-k_topo,                              &
3938                                  rrtm_icld,                                   &
3939                                  rrtm_iaer,                                   &
3940                                  rrtm_play(:,k_topo+1:nzt_rad+1),             &
3941                                  rrtm_plev(:,k_topo+1:nzt_rad+2),             &
3942                                  rrtm_tlay(:,k_topo+1:nzt_rad+1),             &
3943                                  rrtm_tlev(:,k_topo+1:nzt_rad+2),             &
3944                                  rrtm_tsfc,                                   &
3945                                  rrtm_h2ovmr(:,k_topo+1:nzt_rad+1),           &                               
3946                                  rrtm_o3vmr(:,k_topo+1:nzt_rad+1),            &       
3947                                  rrtm_co2vmr(:,k_topo+1:nzt_rad+1),           &
3948                                  rrtm_ch4vmr(:,k_topo+1:nzt_rad+1),           &
3949                                  rrtm_n2ovmr(:,k_topo+1:nzt_rad+1),           &
3950                                  rrtm_o2vmr(:,k_topo+1:nzt_rad+1),            &
3951                                  rrtm_asdir,                                  & 
3952                                  rrtm_asdif,                                  &
3953                                  rrtm_aldir,                                  &
3954                                  rrtm_aldif,                                  &
3955                                  zenith,                                      &
3956                                  0.0_wp,                                      &
3957                                  day_of_year,                                 &
3958                                  solar_constant,                              &
3959                                  rrtm_inflgsw,                                &
3960                                  rrtm_iceflgsw,                               &
3961                                  rrtm_liqflgsw,                               &
3962                                  rrtm_cldfr(:,k_topo+1:nzt_rad+1),            &
3963                                  rrtm_sw_taucld_dum,                          &
3964                                  rrtm_sw_ssacld_dum,                          &
3965                                  rrtm_sw_asmcld_dum,                          &
3966                                  rrtm_sw_fsfcld_dum,                          &
3967                                  rrtm_cicewp(:,k_topo+1:nzt_rad+1),           &
3968                                  rrtm_cliqwp(:,k_topo+1:nzt_rad+1),           &
3969                                  rrtm_reice(:,k_topo+1:nzt_rad+1),            &
3970                                  rrtm_reliq(:,k_topo+1:nzt_rad+1),            &
3971                                  rrtm_sw_tauaer_dum,                          &
3972                                  rrtm_sw_ssaaer_dum,                          &
3973                                  rrtm_sw_asmaer_dum,                          &
3974                                  rrtm_sw_ecaer_dum,                           &
3975                                  rrtm_swuflx(:,k_topo:nzt_rad+1),             & 
3976                                  rrtm_swdflx(:,k_topo:nzt_rad+1),             & 
3977                                  rrtm_swhr(:,k_topo+1:nzt_rad+1),             & 
3978                                  rrtm_swuflxc(:,k_topo:nzt_rad+1),            & 
3979                                  rrtm_swdflxc(:,k_topo:nzt_rad+1),            &
3980                                  rrtm_swhrc(:,k_topo+1:nzt_rad+1),            &
3981                                  rrtm_dirdflux(:,k_topo:nzt_rad+1),           &
3982                                  rrtm_difdflux(:,k_topo:nzt_rad+1) )
3983
3984                   DEALLOCATE( rrtm_sw_taucld_dum )
3985                   DEALLOCATE( rrtm_sw_ssacld_dum )
3986                   DEALLOCATE( rrtm_sw_asmcld_dum )
3987                   DEALLOCATE( rrtm_sw_fsfcld_dum )
3988                   DEALLOCATE( rrtm_sw_tauaer_dum )
3989                   DEALLOCATE( rrtm_sw_ssaaer_dum )
3990                   DEALLOCATE( rrtm_sw_asmaer_dum )
3991                   DEALLOCATE( rrtm_sw_ecaer_dum )
3992!
3993!--                Save fluxes
3994                   DO k = nzb, nzt+1
3995                      rad_sw_in(k,j,i)  = rrtm_swdflx(0,k)
3996                      rad_sw_out(k,j,i) = rrtm_swuflx(0,k)
3997                   ENDDO
3998!
3999!--                Save heating rates (convert from K/d to K/s)
4000                   DO k = nzb+1, nzt+1
4001                      rad_sw_hr(k,j,i)     = rrtm_swhr(0,k)  * d_hours_day
4002                      rad_sw_cs_hr(k,j,i)  = rrtm_swhrc(0,k) * d_hours_day
4003                   ENDDO
4004
4005!
4006!--                Save surface radiative fluxes onto respective surface elements
4007!--                Horizontal surfaces
4008                   DO  m = surf_lsm_h%start_index(j,i),                        &
4009                           surf_lsm_h%end_index(j,i)
4010                      surf_lsm_h%rad_sw_in(m)     = rrtm_swdflx(0,k_topo)
4011                      surf_lsm_h%rad_sw_out(m)    = rrtm_swuflx(0,k_topo)
4012                   ENDDO             
4013                   DO  m = surf_usm_h%start_index(j,i),                        &
4014                           surf_usm_h%end_index(j,i)
4015                      surf_usm_h%rad_sw_in(m)     = rrtm_swdflx(0,k_topo)
4016                      surf_usm_h%rad_sw_out(m)    = rrtm_swuflx(0,k_topo)
4017                   ENDDO 
4018!
4019!--                Vertical surfaces. Fluxes are obtain at respective vertical
4020!--                level of the surface element
4021                   DO  l = 0, 3
4022                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
4023                              surf_lsm_v(l)%end_index(j,i)
4024                         k                           = surf_lsm_v(l)%k(m)
4025                         surf_lsm_v(l)%rad_sw_in(m)  = rrtm_swdflx(0,k)
4026                         surf_lsm_v(l)%rad_sw_out(m) = rrtm_swuflx(0,k)
4027                      ENDDO             
4028                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
4029                              surf_usm_v(l)%end_index(j,i)
4030                         k                           = surf_usm_v(l)%k(m)
4031                         surf_usm_v(l)%rad_sw_in(m)  = rrtm_swdflx(0,k)
4032                         surf_usm_v(l)%rad_sw_out(m) = rrtm_swuflx(0,k)
4033                      ENDDO 
4034                   ENDDO
4035!
4036!--             Solar radiation is zero during night
4037                ELSE
4038                   rad_sw_in  = 0.0_wp
4039                   rad_sw_out = 0.0_wp
4040!--             !!!!!!!! ATTENSION !!!!!!!!!!!!!!!
4041!--             Surface radiative fluxes should be also set to zero here                 
4042!--                Save surface radiative fluxes onto respective surface elements
4043!--                Horizontal surfaces
4044                   DO  m = surf_lsm_h%start_index(j,i),                        &
4045                           surf_lsm_h%end_index(j,i)
4046                      surf_lsm_h%rad_sw_in(m)     = 0.0_wp
4047                      surf_lsm_h%rad_sw_out(m)    = 0.0_wp
4048                   ENDDO             
4049                   DO  m = surf_usm_h%start_index(j,i),                        &
4050                           surf_usm_h%end_index(j,i)
4051                      surf_usm_h%rad_sw_in(m)     = 0.0_wp
4052                      surf_usm_h%rad_sw_out(m)    = 0.0_wp
4053                   ENDDO 
4054!
4055!--                Vertical surfaces. Fluxes are obtain at respective vertical
4056!--                level of the surface element
4057                   DO  l = 0, 3
4058                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
4059                              surf_lsm_v(l)%end_index(j,i)
4060                         k                           = surf_lsm_v(l)%k(m)
4061                         surf_lsm_v(l)%rad_sw_in(m)  = 0.0_wp
4062                         surf_lsm_v(l)%rad_sw_out(m) = 0.0_wp
4063                      ENDDO             
4064                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
4065                              surf_usm_v(l)%end_index(j,i)
4066                         k                           = surf_usm_v(l)%k(m)
4067                         surf_usm_v(l)%rad_sw_in(m)  = 0.0_wp
4068                         surf_usm_v(l)%rad_sw_out(m) = 0.0_wp
4069                      ENDDO 
4070                   ENDDO
4071                ENDIF
4072
4073             ENDDO
4074          ENDDO
4075
4076       ENDIF
4077!
4078!--    Finally, calculate surface net radiation for surface elements.
4079       IF (  .NOT.  radiation_interactions  ) THEN
4080!--       First, for horizontal surfaces   
4081          DO  m = 1, surf_lsm_h%ns
4082             surf_lsm_h%rad_net(m) = surf_lsm_h%rad_sw_in(m)                   &
4083                                   - surf_lsm_h%rad_sw_out(m)                  &
4084                                   + surf_lsm_h%rad_lw_in(m)                   &
4085                                   - surf_lsm_h%rad_lw_out(m)
4086          ENDDO
4087          DO  m = 1, surf_usm_h%ns
4088             surf_usm_h%rad_net(m) = surf_usm_h%rad_sw_in(m)                   &
4089                                   - surf_usm_h%rad_sw_out(m)                  &
4090                                   + surf_usm_h%rad_lw_in(m)                   &
4091                                   - surf_usm_h%rad_lw_out(m)
4092          ENDDO
4093!
4094!--       Vertical surfaces.
4095!--       Todo: weight with azimuth and zenith angle according to their orientation!
4096          DO  l = 0, 3     
4097             DO  m = 1, surf_lsm_v(l)%ns
4098                surf_lsm_v(l)%rad_net(m) = surf_lsm_v(l)%rad_sw_in(m)          &
4099                                         - surf_lsm_v(l)%rad_sw_out(m)         &
4100                                         + surf_lsm_v(l)%rad_lw_in(m)          &
4101                                         - surf_lsm_v(l)%rad_lw_out(m)
4102             ENDDO
4103             DO  m = 1, surf_usm_v(l)%ns
4104                surf_usm_v(l)%rad_net(m) = surf_usm_v(l)%rad_sw_in(m)          &
4105                                         - surf_usm_v(l)%rad_sw_out(m)         &
4106                                         + surf_usm_v(l)%rad_lw_in(m)          &
4107                                         - surf_usm_v(l)%rad_lw_out(m)
4108             ENDDO
4109          ENDDO
4110       ENDIF
4111
4112
4113       CALL exchange_horiz( rad_lw_in,  nbgp )
4114       CALL exchange_horiz( rad_lw_out, nbgp )
4115       CALL exchange_horiz( rad_lw_hr,    nbgp )
4116       CALL exchange_horiz( rad_lw_cs_hr, nbgp )
4117
4118       CALL exchange_horiz( rad_sw_in,  nbgp )
4119       CALL exchange_horiz( rad_sw_out, nbgp ) 
4120       CALL exchange_horiz( rad_sw_hr,    nbgp )
4121       CALL exchange_horiz( rad_sw_cs_hr, nbgp )
4122
4123#endif
4124
4125    END SUBROUTINE radiation_rrtmg
4126
4127
4128!------------------------------------------------------------------------------!
4129! Description:
4130! ------------
4131!> Calculate the cosine of the zenith angle (variable is called zenith)
4132!------------------------------------------------------------------------------!
4133    SUBROUTINE calc_zenith
4134
4135       IMPLICIT NONE
4136
4137       REAL(wp) ::  declination,  & !< solar declination angle
4138                    hour_angle      !< solar hour angle
4139!
4140!--    Calculate current day and time based on the initial values and simulation
4141!--    time
4142       CALL calc_date_and_time
4143
4144!
4145!--    Calculate solar declination and hour angle   
4146       declination = ASIN( decl_1 * SIN(decl_2 * REAL(day_of_year, KIND=wp) - decl_3) )
4147       hour_angle  = 2.0_wp * pi * (time_utc / 86400.0_wp) + lon - pi
4148
4149!
4150!--    Calculate cosine of solar zenith angle
4151       zenith(0) = SIN(lat) * SIN(declination) + COS(lat) * COS(declination)   &
4152                                            * COS(hour_angle)
4153       zenith(0) = MAX(0.0_wp,zenith(0))
4154
4155!
4156!--    Calculate solar directional vector
4157       IF ( sun_direction )  THEN
4158
4159!
4160!--       Direction in longitudes equals to sin(solar_azimuth) * sin(zenith)
4161          sun_dir_lon(0) = -SIN(hour_angle) * COS(declination)
4162
4163!
4164!--       Direction in latitues equals to cos(solar_azimuth) * sin(zenith)
4165          sun_dir_lat(0) = SIN(declination) * COS(lat) - COS(hour_angle) &
4166                              * COS(declination) * SIN(lat)
4167       ENDIF
4168
4169!
4170!--    Check if the sun is up (otheriwse shortwave calculations can be skipped)
4171       IF ( zenith(0) > 0.0_wp )  THEN
4172          sun_up = .TRUE.
4173       ELSE
4174          sun_up = .FALSE.
4175       END IF
4176
4177    END SUBROUTINE calc_zenith
4178
4179#if defined ( __rrtmg ) && defined ( __netcdf )
4180!------------------------------------------------------------------------------!
4181! Description:
4182! ------------
4183!> Calculates surface albedo components based on Briegleb (1992) and
4184!> Briegleb et al. (1986)
4185!------------------------------------------------------------------------------!
4186    SUBROUTINE calc_albedo( surf )
4187
4188        IMPLICIT NONE
4189
4190        INTEGER(iwp)    ::  ind_type !< running index surface tiles
4191        INTEGER(iwp)    ::  m        !< running index surface elements
4192
4193        TYPE(surf_type) ::  surf !< treated surfaces
4194
4195        IF ( sun_up  .AND.  .NOT. average_radiation )  THEN
4196
4197           DO  m = 1, surf%ns
4198!
4199!--           Loop over surface elements
4200              DO  ind_type = 0, SIZE( surf%albedo_type, 1 ) - 1
4201           
4202!
4203!--              Ocean
4204                 IF ( surf%albedo_type(ind_type,m) == 1 )  THEN
4205                    surf%rrtm_aldir(ind_type,m) = 0.026_wp /                    &
4206                                                ( zenith(0)**1.7_wp + 0.065_wp )&
4207                                     + 0.15_wp * ( zenith(0) - 0.1_wp )         &
4208                                               * ( zenith(0) - 0.5_wp )         &
4209                                               * ( zenith(0) - 1.0_wp )
4210                    surf%rrtm_asdir(ind_type,m) = surf%rrtm_aldir(ind_type,m)
4211!
4212!--              Snow
4213                 ELSEIF ( surf%albedo_type(ind_type,m) == 16 )  THEN
4214                    IF ( zenith(0) < 0.5_wp )  THEN
4215                       surf%rrtm_aldir(ind_type,m) =                           &
4216                                 0.5_wp * ( 1.0_wp - surf%aldif(ind_type,m) )  &
4217                                        * ( 3.0_wp / ( 1.0_wp + 4.0_wp         &
4218                                        * zenith(0) ) ) - 1.0_wp
4219                       surf%rrtm_asdir(ind_type,m) =                           &
4220                                 0.5_wp * ( 1.0_wp - surf%asdif(ind_type,m) )  &
4221                                        * ( 3.0_wp / ( 1.0_wp + 4.0_wp         &
4222                                        * zenith(0) ) ) - 1.0_wp
4223
4224                       surf%rrtm_aldir(ind_type,m) =                           &
4225                                       MIN(0.98_wp, surf%rrtm_aldir(ind_type,m))
4226                       surf%rrtm_asdir(ind_type,m) =                           &
4227                                       MIN(0.98_wp, surf%rrtm_asdir(ind_type,m))
4228                    ELSE
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                    ENDIF
4232!
4233!--              Sea ice
4234                 ELSEIF ( surf%albedo_type(ind_type,m) == 15 )  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!--              Asphalt
4240                 ELSEIF ( surf%albedo_type(ind_type,m) == 17 )  THEN
4241                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4242                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4243
4244
4245!
4246!--              Bare soil
4247                 ELSEIF ( surf%albedo_type(ind_type,m) == 18 )  THEN
4248                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4249                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4250
4251!
4252!--              Land surfaces
4253                 ELSE
4254                    SELECT CASE ( surf%albedo_type(ind_type,m) )
4255
4256!
4257!--                    Surface types with strong zenith dependence
4258                       CASE ( 1, 2, 3, 4, 11, 12, 13 )
4259                          surf%rrtm_aldir(ind_type,m) =                        &
4260                                surf%aldif(ind_type,m) * 1.4_wp /              &
4261                                           ( 1.0_wp + 0.8_wp * zenith(0) )
4262                          surf%rrtm_asdir(ind_type,m) =                        &
4263                                surf%asdif(ind_type,m) * 1.4_wp /              &
4264                                           ( 1.0_wp + 0.8_wp * zenith(0) )
4265!
4266!--                    Surface types with weak zenith dependence
4267                       CASE ( 5, 6, 7, 8, 9, 10, 14 )
4268                          surf%rrtm_aldir(ind_type,m) =                        &
4269                                surf%aldif(ind_type,m) * 1.1_wp /              &
4270                                           ( 1.0_wp + 0.2_wp * zenith(0) )
4271                          surf%rrtm_asdir(ind_type,m) =                        &
4272                                surf%asdif(ind_type,m) * 1.1_wp /              &
4273                                           ( 1.0_wp + 0.2_wp * zenith(0) )
4274
4275                       CASE DEFAULT
4276
4277                    END SELECT
4278                 ENDIF
4279!
4280!--              Diffusive albedo is taken from Table 2
4281                 surf%rrtm_aldif(ind_type,m) = surf%aldif(ind_type,m)
4282                 surf%rrtm_asdif(ind_type,m) = surf%asdif(ind_type,m)
4283              ENDDO
4284           ENDDO
4285!
4286!--     Set albedo in case of average radiation
4287        ELSEIF ( sun_up  .AND.  average_radiation )  THEN
4288           surf%rrtm_asdir = albedo_urb
4289           surf%rrtm_asdif = albedo_urb
4290           surf%rrtm_aldir = albedo_urb
4291           surf%rrtm_aldif = albedo_urb 
4292!
4293!--     Darkness
4294        ELSE
4295           surf%rrtm_aldir = 0.0_wp
4296           surf%rrtm_asdir = 0.0_wp
4297           surf%rrtm_aldif = 0.0_wp
4298           surf%rrtm_asdif = 0.0_wp
4299        ENDIF
4300
4301    END SUBROUTINE calc_albedo
4302
4303!------------------------------------------------------------------------------!
4304! Description:
4305! ------------
4306!> Read sounding data (pressure and temperature) from RADIATION_DATA.
4307!------------------------------------------------------------------------------!
4308    SUBROUTINE read_sounding_data
4309
4310       IMPLICIT NONE
4311
4312       INTEGER(iwp) :: id,           & !< NetCDF id of input file
4313                       id_dim_zrad,  & !< pressure level id in the NetCDF file
4314                       id_var,       & !< NetCDF variable id
4315                       k,            & !< loop index
4316                       nz_snd,       & !< number of vertical levels in the sounding data
4317                       nz_snd_start, & !< start vertical index for sounding data to be used
4318                       nz_snd_end      !< end vertical index for souding data to be used
4319
4320       REAL(wp) :: t_surface           !< actual surface temperature
4321
4322       REAL(wp), DIMENSION(:), ALLOCATABLE ::  hyp_snd_tmp, & !< temporary hydrostatic pressure profile (sounding)
4323                                               t_snd_tmp      !< temporary temperature profile (sounding)
4324
4325!
4326!--    In case of updates, deallocate arrays first (sufficient to check one
4327!--    array as the others are automatically allocated). This is required
4328!--    because nzt_rad might change during the update
4329       IF ( ALLOCATED ( hyp_snd ) )  THEN
4330          DEALLOCATE( hyp_snd )
4331          DEALLOCATE( t_snd )
4332          DEALLOCATE ( rrtm_play )
4333          DEALLOCATE ( rrtm_plev )
4334          DEALLOCATE ( rrtm_tlay )
4335          DEALLOCATE ( rrtm_tlev )
4336
4337          DEALLOCATE ( rrtm_cicewp )
4338          DEALLOCATE ( rrtm_cldfr )
4339          DEALLOCATE ( rrtm_cliqwp )
4340          DEALLOCATE ( rrtm_reice )
4341          DEALLOCATE ( rrtm_reliq )
4342          DEALLOCATE ( rrtm_lw_taucld )
4343          DEALLOCATE ( rrtm_lw_tauaer )
4344
4345          DEALLOCATE ( rrtm_lwdflx  )
4346          DEALLOCATE ( rrtm_lwdflxc )
4347          DEALLOCATE ( rrtm_lwuflx  )
4348          DEALLOCATE ( rrtm_lwuflxc )
4349          DEALLOCATE ( rrtm_lwuflx_dt )
4350          DEALLOCATE ( rrtm_lwuflxc_dt )
4351          DEALLOCATE ( rrtm_lwhr  )
4352          DEALLOCATE ( rrtm_lwhrc )
4353
4354          DEALLOCATE ( rrtm_sw_taucld )
4355          DEALLOCATE ( rrtm_sw_ssacld )
4356          DEALLOCATE ( rrtm_sw_asmcld )
4357          DEALLOCATE ( rrtm_sw_fsfcld )
4358          DEALLOCATE ( rrtm_sw_tauaer )
4359          DEALLOCATE ( rrtm_sw_ssaaer )
4360          DEALLOCATE ( rrtm_sw_asmaer ) 
4361          DEALLOCATE ( rrtm_sw_ecaer )   
4362 
4363          DEALLOCATE ( rrtm_swdflx  )
4364          DEALLOCATE ( rrtm_swdflxc )
4365          DEALLOCATE ( rrtm_swuflx  )
4366          DEALLOCATE ( rrtm_swuflxc )
4367          DEALLOCATE ( rrtm_swhr  )
4368          DEALLOCATE ( rrtm_swhrc )
4369          DEALLOCATE ( rrtm_dirdflux )
4370          DEALLOCATE ( rrtm_difdflux )
4371
4372       ENDIF
4373
4374!
4375!--    Open file for reading
4376       nc_stat = NF90_OPEN( rrtm_input_file, NF90_NOWRITE, id )
4377       CALL netcdf_handle_error_rad( 'read_sounding_data', 549 )
4378
4379!
4380!--    Inquire dimension of z axis and save in nz_snd
4381       nc_stat = NF90_INQ_DIMID( id, "Pressure", id_dim_zrad )
4382       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim_zrad, len = nz_snd )
4383       CALL netcdf_handle_error_rad( 'read_sounding_data', 551 )
4384
4385!
4386! !--    Allocate temporary array for storing pressure data
4387       ALLOCATE( hyp_snd_tmp(1:nz_snd) )
4388       hyp_snd_tmp = 0.0_wp
4389
4390
4391!--    Read pressure from file
4392       nc_stat = NF90_INQ_VARID( id, "Pressure", id_var )
4393       nc_stat = NF90_GET_VAR( id, id_var, hyp_snd_tmp(:), start = (/1/),      &
4394                               count = (/nz_snd/) )
4395       CALL netcdf_handle_error_rad( 'read_sounding_data', 552 )
4396
4397!
4398!--    Allocate temporary array for storing temperature data
4399       ALLOCATE( t_snd_tmp(1:nz_snd) )
4400       t_snd_tmp = 0.0_wp
4401
4402!
4403!--    Read temperature from file
4404       nc_stat = NF90_INQ_VARID( id, "ReferenceTemperature", id_var )
4405       nc_stat = NF90_GET_VAR( id, id_var, t_snd_tmp(:), start = (/1/),        &
4406                               count = (/nz_snd/) )
4407       CALL netcdf_handle_error_rad( 'read_sounding_data', 553 )
4408
4409!
4410!--    Calculate start of sounding data
4411       nz_snd_start = nz_snd + 1
4412       nz_snd_end   = nz_snd + 1
4413
4414!
4415!--    Start filling vertical dimension at 10hPa above the model domain (hyp is
4416!--    in Pa, hyp_snd in hPa).
4417       DO  k = 1, nz_snd
4418          IF ( hyp_snd_tmp(k) < ( hyp(nzt+1) - 1000.0_wp) * 0.01_wp )  THEN
4419             nz_snd_start = k
4420             EXIT
4421          END IF
4422       END DO
4423
4424       IF ( nz_snd_start <= nz_snd )  THEN
4425          nz_snd_end = nz_snd
4426       END IF
4427
4428
4429!
4430!--    Calculate of total grid points for RRTMG calculations
4431       nzt_rad = nzt + nz_snd_end - nz_snd_start + 1
4432
4433!
4434!--    Save data above LES domain in hyp_snd, t_snd
4435       ALLOCATE( hyp_snd(nzb+1:nzt_rad) )
4436       ALLOCATE( t_snd(nzb+1:nzt_rad)   )
4437       hyp_snd = 0.0_wp
4438       t_snd = 0.0_wp
4439
4440       hyp_snd(nzt+2:nzt_rad) = hyp_snd_tmp(nz_snd_start+1:nz_snd_end)
4441       t_snd(nzt+2:nzt_rad)   = t_snd_tmp(nz_snd_start+1:nz_snd_end)
4442
4443       nc_stat = NF90_CLOSE( id )
4444
4445!
4446!--    Calculate pressure levels on zu and zw grid. Sounding data is added at
4447!--    top of the LES domain. This routine does not consider horizontal or
4448!--    vertical variability of pressure and temperature
4449       ALLOCATE ( rrtm_play(0:0,nzb+1:nzt_rad+1)   )
4450       ALLOCATE ( rrtm_plev(0:0,nzb+1:nzt_rad+2)   )
4451
4452       t_surface = pt_surface * exner(nzb)
4453       DO k = nzb+1, nzt+1
4454          rrtm_play(0,k) = hyp(k) * 0.01_wp
4455          rrtm_plev(0,k) = barometric_formula(zw(k-1),                         &
4456                              pt_surface * exner(nzb), &
4457                              surface_pressure )
4458       ENDDO
4459
4460       DO k = nzt+2, nzt_rad
4461          rrtm_play(0,k) = hyp_snd(k)
4462          rrtm_plev(0,k) = 0.5_wp * ( rrtm_play(0,k) + rrtm_play(0,k-1) )
4463       ENDDO
4464       rrtm_plev(0,nzt_rad+1) = MAX( 0.5 * hyp_snd(nzt_rad),                   &
4465                                   1.5 * hyp_snd(nzt_rad)                      &
4466                                 - 0.5 * hyp_snd(nzt_rad-1) )
4467       rrtm_plev(0,nzt_rad+2)  = MIN( 1.0E-4_wp,                               &
4468                                      0.25_wp * rrtm_plev(0,nzt_rad+1) )
4469
4470       rrtm_play(0,nzt_rad+1) = 0.5 * rrtm_plev(0,nzt_rad+1)
4471
4472!
4473!--    Calculate temperature/humidity levels at top of the LES domain.
4474!--    Currently, the temperature is taken from sounding data (might lead to a
4475!--    temperature jump at interface. To do: Humidity is currently not
4476!--    calculated above the LES domain.
4477       ALLOCATE ( rrtm_tlay(0:0,nzb+1:nzt_rad+1)   )
4478       ALLOCATE ( rrtm_tlev(0:0,nzb+1:nzt_rad+2)   )
4479
4480       DO k = nzt+8, nzt_rad
4481          rrtm_tlay(0,k)   = t_snd(k)
4482       ENDDO
4483       rrtm_tlay(0,nzt_rad+1) = 2.0_wp * rrtm_tlay(0,nzt_rad)                  &
4484                                - rrtm_tlay(0,nzt_rad-1)
4485       DO k = nzt+9, nzt_rad+1
4486          rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k)                &
4487                             - rrtm_tlay(0,k-1))                               &
4488                             / ( rrtm_play(0,k) - rrtm_play(0,k-1) )           &
4489                             * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
4490       ENDDO
4491
4492       rrtm_tlev(0,nzt_rad+2)   = 2.0_wp * rrtm_tlay(0,nzt_rad+1)              &
4493                                  - rrtm_tlev(0,nzt_rad)
4494!
4495!--    Allocate remaining RRTMG arrays
4496       ALLOCATE ( rrtm_cicewp(0:0,nzb+1:nzt_rad+1) )
4497       ALLOCATE ( rrtm_cldfr(0:0,nzb+1:nzt_rad+1) )
4498       ALLOCATE ( rrtm_cliqwp(0:0,nzb+1:nzt_rad+1) )
4499       ALLOCATE ( rrtm_reice(0:0,nzb+1:nzt_rad+1) )
4500       ALLOCATE ( rrtm_reliq(0:0,nzb+1:nzt_rad+1) )
4501       ALLOCATE ( rrtm_lw_taucld(1:nbndlw+1,0:0,nzb+1:nzt_rad+1) )
4502       ALLOCATE ( rrtm_lw_tauaer(0:0,nzb+1:nzt_rad+1,1:nbndlw+1) )
4503       ALLOCATE ( rrtm_sw_taucld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4504       ALLOCATE ( rrtm_sw_ssacld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4505       ALLOCATE ( rrtm_sw_asmcld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4506       ALLOCATE ( rrtm_sw_fsfcld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4507       ALLOCATE ( rrtm_sw_tauaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) )
4508       ALLOCATE ( rrtm_sw_ssaaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) )
4509       ALLOCATE ( rrtm_sw_asmaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) ) 
4510       ALLOCATE ( rrtm_sw_ecaer(0:0,nzb+1:nzt_rad+1,1:naerec+1) )   
4511
4512!
4513!--    The ice phase is currently not considered in PALM
4514       rrtm_cicewp = 0.0_wp
4515       rrtm_reice  = 0.0_wp
4516
4517!
4518!--    Set other parameters (move to NAMELIST parameters in the future)
4519       rrtm_lw_tauaer = 0.0_wp
4520       rrtm_lw_taucld = 0.0_wp
4521       rrtm_sw_taucld = 0.0_wp
4522       rrtm_sw_ssacld = 0.0_wp
4523       rrtm_sw_asmcld = 0.0_wp
4524       rrtm_sw_fsfcld = 0.0_wp
4525       rrtm_sw_tauaer = 0.0_wp
4526       rrtm_sw_ssaaer = 0.0_wp
4527       rrtm_sw_asmaer = 0.0_wp
4528       rrtm_sw_ecaer  = 0.0_wp
4529
4530
4531       ALLOCATE ( rrtm_swdflx(0:0,nzb:nzt_rad+1)  )
4532       ALLOCATE ( rrtm_swuflx(0:0,nzb:nzt_rad+1)  )
4533       ALLOCATE ( rrtm_swhr(0:0,nzb+1:nzt_rad+1)  )
4534       ALLOCATE ( rrtm_swuflxc(0:0,nzb:nzt_rad+1) )
4535       ALLOCATE ( rrtm_swdflxc(0:0,nzb:nzt_rad+1) )
4536       ALLOCATE ( rrtm_swhrc(0:0,nzb+1:nzt_rad+1) )
4537       ALLOCATE ( rrtm_dirdflux(0:0,nzb:nzt_rad+1) )
4538       ALLOCATE ( rrtm_difdflux(0:0,nzb:nzt_rad+1) )
4539
4540       rrtm_swdflx  = 0.0_wp
4541       rrtm_swuflx  = 0.0_wp
4542       rrtm_swhr    = 0.0_wp 
4543       rrtm_swuflxc = 0.0_wp
4544       rrtm_swdflxc = 0.0_wp
4545       rrtm_swhrc   = 0.0_wp
4546       rrtm_dirdflux = 0.0_wp
4547       rrtm_difdflux = 0.0_wp
4548
4549       ALLOCATE ( rrtm_lwdflx(0:0,nzb:nzt_rad+1)  )
4550       ALLOCATE ( rrtm_lwuflx(0:0,nzb:nzt_rad+1)  )
4551       ALLOCATE ( rrtm_lwhr(0:0,nzb+1:nzt_rad+1)  )
4552       ALLOCATE ( rrtm_lwuflxc(0:0,nzb:nzt_rad+1) )
4553       ALLOCATE ( rrtm_lwdflxc(0:0,nzb:nzt_rad+1) )
4554       ALLOCATE ( rrtm_lwhrc(0:0,nzb+1:nzt_rad+1) )
4555
4556       rrtm_lwdflx  = 0.0_wp
4557       rrtm_lwuflx  = 0.0_wp
4558       rrtm_lwhr    = 0.0_wp 
4559       rrtm_lwuflxc = 0.0_wp
4560       rrtm_lwdflxc = 0.0_wp
4561       rrtm_lwhrc   = 0.0_wp
4562
4563       ALLOCATE ( rrtm_lwuflx_dt(0:0,nzb:nzt_rad+1) )
4564       ALLOCATE ( rrtm_lwuflxc_dt(0:0,nzb:nzt_rad+1) )
4565
4566       rrtm_lwuflx_dt = 0.0_wp
4567       rrtm_lwuflxc_dt = 0.0_wp
4568
4569    END SUBROUTINE read_sounding_data
4570
4571
4572!------------------------------------------------------------------------------!
4573! Description:
4574! ------------
4575!> Read trace gas data from file
4576!------------------------------------------------------------------------------!
4577    SUBROUTINE read_trace_gas_data
4578
4579       USE rrsw_ncpar
4580
4581       IMPLICIT NONE
4582
4583       INTEGER(iwp), PARAMETER :: num_trace_gases = 10 !< number of trace gases (absorbers)
4584
4585       CHARACTER(LEN=5), DIMENSION(num_trace_gases), PARAMETER ::              & !< trace gas names
4586           trace_names = (/'O3   ', 'CO2  ', 'CH4  ', 'N2O  ', 'O2   ',        &
4587                           'CFC11', 'CFC12', 'CFC22', 'CCL4 ', 'H2O  '/)
4588
4589       INTEGER(iwp) :: id,     & !< NetCDF id
4590                       k,      & !< loop index
4591                       m,      & !< loop index
4592                       n,      & !< loop index
4593                       nabs,   & !< number of absorbers
4594                       np,     & !< number of pressure levels
4595                       id_abs, & !< NetCDF id of the respective absorber
4596                       id_dim, & !< NetCDF id of asborber's dimension
4597                       id_var    !< NetCDf id ot the absorber
4598
4599       REAL(wp) :: p_mls_l, p_mls_u, p_wgt_l, p_wgt_u, p_mls_m
4600
4601
4602       REAL(wp), DIMENSION(:), ALLOCATABLE   ::  p_mls,          & !< pressure levels for the absorbers
4603                                                 rrtm_play_tmp,  & !< temporary array for pressure zu-levels
4604                                                 rrtm_plev_tmp,  & !< temporary array for pressure zw-levels
4605                                                 trace_path_tmp    !< temporary array for storing trace gas path data
4606
4607       REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  trace_mls,      & !< array for storing the absorber amounts
4608                                                 trace_mls_path, & !< array for storing trace gas path data
4609                                                 trace_mls_tmp     !< temporary array for storing trace gas data
4610
4611
4612!
4613!--    In case of updates, deallocate arrays first (sufficient to check one
4614!--    array as the others are automatically allocated)
4615       IF ( ALLOCATED ( rrtm_o3vmr ) )  THEN
4616          DEALLOCATE ( rrtm_o3vmr  )
4617          DEALLOCATE ( rrtm_co2vmr )
4618          DEALLOCATE ( rrtm_ch4vmr )
4619          DEALLOCATE ( rrtm_n2ovmr )
4620          DEALLOCATE ( rrtm_o2vmr  )
4621          DEALLOCATE ( rrtm_cfc11vmr )
4622          DEALLOCATE ( rrtm_cfc12vmr )
4623          DEALLOCATE ( rrtm_cfc22vmr )
4624          DEALLOCATE ( rrtm_ccl4vmr  )
4625          DEALLOCATE ( rrtm_h2ovmr  )     
4626       ENDIF
4627
4628!
4629!--    Allocate trace gas profiles
4630       ALLOCATE ( rrtm_o3vmr(0:0,1:nzt_rad+1)  )
4631       ALLOCATE ( rrtm_co2vmr(0:0,1:nzt_rad+1) )
4632       ALLOCATE ( rrtm_ch4vmr(0:0,1:nzt_rad+1) )
4633       ALLOCATE ( rrtm_n2ovmr(0:0,1:nzt_rad+1) )
4634       ALLOCATE ( rrtm_o2vmr(0:0,1:nzt_rad+1)  )
4635       ALLOCATE ( rrtm_cfc11vmr(0:0,1:nzt_rad+1) )
4636       ALLOCATE ( rrtm_cfc12vmr(0:0,1:nzt_rad+1) )
4637       ALLOCATE ( rrtm_cfc22vmr(0:0,1:nzt_rad+1) )
4638       ALLOCATE ( rrtm_ccl4vmr(0:0,1:nzt_rad+1)  )
4639       ALLOCATE ( rrtm_h2ovmr(0:0,1:nzt_rad+1)  )
4640
4641!
4642!--    Open file for reading
4643       nc_stat = NF90_OPEN( rrtm_input_file, NF90_NOWRITE, id )
4644       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 549 )
4645!
4646!--    Inquire dimension ids and dimensions
4647       nc_stat = NF90_INQ_DIMID( id, "Pressure", id_dim )
4648       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4649       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim, len = np) 
4650       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4651
4652       nc_stat = NF90_INQ_DIMID( id, "Absorber", id_dim )
4653       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4654       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim, len = nabs ) 
4655       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4656   
4657
4658!
4659!--    Allocate pressure, and trace gas arrays     
4660       ALLOCATE( p_mls(1:np) )
4661       ALLOCATE( trace_mls(1:num_trace_gases,1:np) ) 
4662       ALLOCATE( trace_mls_tmp(1:nabs,1:np) ) 
4663
4664
4665       nc_stat = NF90_INQ_VARID( id, "Pressure", id_var )
4666       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4667       nc_stat = NF90_GET_VAR( id, id_var, p_mls )
4668       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4669
4670       nc_stat = NF90_INQ_VARID( id, "AbsorberAmountMLS", id_var )
4671       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4672       nc_stat = NF90_GET_VAR( id, id_var, trace_mls_tmp )
4673       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4674
4675
4676!
4677!--    Write absorber amounts (mls) to trace_mls
4678       DO n = 1, num_trace_gases
4679          CALL getAbsorberIndex( TRIM( trace_names(n) ), id_abs )
4680
4681          trace_mls(n,1:np) = trace_mls_tmp(id_abs,1:np)
4682
4683!
4684!--       Replace missing values by zero
4685          WHERE ( trace_mls(n,:) > 2.0_wp ) 
4686             trace_mls(n,:) = 0.0_wp
4687          END WHERE
4688       END DO
4689
4690       DEALLOCATE ( trace_mls_tmp )
4691
4692       nc_stat = NF90_CLOSE( id )
4693       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 551 )
4694
4695!
4696!--    Add extra pressure level for calculations of the trace gas paths
4697       ALLOCATE ( rrtm_play_tmp(1:nzt_rad+1) )
4698       ALLOCATE ( rrtm_plev_tmp(1:nzt_rad+2) )
4699
4700       rrtm_play_tmp(1:nzt_rad)   = rrtm_play(0,1:nzt_rad) 
4701       rrtm_plev_tmp(1:nzt_rad+1) = rrtm_plev(0,1:nzt_rad+1)
4702       rrtm_play_tmp(nzt_rad+1)   = rrtm_plev(0,nzt_rad+1) * 0.5_wp
4703       rrtm_plev_tmp(nzt_rad+2)   = MIN( 1.0E-4_wp, 0.25_wp                    &
4704                                         * rrtm_plev(0,nzt_rad+1) )
4705 
4706!
4707!--    Calculate trace gas path (zero at surface) with interpolation to the
4708!--    sounding levels
4709       ALLOCATE ( trace_mls_path(1:nzt_rad+2,1:num_trace_gases) )
4710
4711       trace_mls_path(nzb+1,:) = 0.0_wp
4712       
4713       DO k = nzb+2, nzt_rad+2
4714          DO m = 1, num_trace_gases
4715             trace_mls_path(k,m) = trace_mls_path(k-1,m)
4716
4717!
4718!--          When the pressure level is higher than the trace gas pressure
4719!--          level, assume that
4720             IF ( rrtm_plev_tmp(k-1) > p_mls(1) )  THEN             
4721               
4722                trace_mls_path(k,m) = trace_mls_path(k,m) + trace_mls(m,1)     &
4723                                      * ( rrtm_plev_tmp(k-1)                   &
4724                                          - MAX( p_mls(1), rrtm_plev_tmp(k) )  &
4725                                        ) / g
4726             ENDIF
4727
4728!
4729!--          Integrate for each sounding level from the contributing p_mls
4730!--          levels
4731             DO n = 2, np
4732!
4733!--             Limit p_mls so that it is within the model level
4734                p_mls_u = MIN( rrtm_plev_tmp(k-1),                             &
4735                          MAX( rrtm_plev_tmp(k), p_mls(n) ) )
4736                p_mls_l = MIN( rrtm_plev_tmp(k-1),                             &
4737                          MAX( rrtm_plev_tmp(k), p_mls(n-1) ) )
4738
4739                IF ( p_mls_l > p_mls_u )  THEN
4740
4741!
4742!--                Calculate weights for interpolation
4743                   p_mls_m = 0.5_wp * (p_mls_l + p_mls_u)
4744                   p_wgt_u = (p_mls(n-1) - p_mls_m) / (p_mls(n-1) - p_mls(n))
4745                   p_wgt_l = (p_mls_m - p_mls(n))   / (p_mls(n-1) - p_mls(n))
4746
4747!
4748!--                Add level to trace gas path
4749                   trace_mls_path(k,m) = trace_mls_path(k,m)                   &
4750                                         +  ( p_wgt_u * trace_mls(m,n)         &
4751                                            + p_wgt_l * trace_mls(m,n-1) )     &
4752                                         * (p_mls_l - p_mls_u) / g
4753                ENDIF
4754             ENDDO
4755
4756             IF ( rrtm_plev_tmp(k) < p_mls(np) )  THEN
4757                trace_mls_path(k,m) = trace_mls_path(k,m) + trace_mls(m,np)    &
4758                                      * ( MIN( rrtm_plev_tmp(k-1), p_mls(np) ) &
4759                                          - rrtm_plev_tmp(k)                   &
4760                                        ) / g 
4761             ENDIF 
4762          ENDDO
4763       ENDDO
4764
4765
4766!
4767!--    Prepare trace gas path profiles
4768       ALLOCATE ( trace_path_tmp(1:nzt_rad+1) )
4769
4770       DO m = 1, num_trace_gases
4771
4772          trace_path_tmp(1:nzt_rad+1) = ( trace_mls_path(2:nzt_rad+2,m)        &
4773                                       - trace_mls_path(1:nzt_rad+1,m) ) * g   &
4774                                       / ( rrtm_plev_tmp(1:nzt_rad+1)          &
4775                                       - rrtm_plev_tmp(2:nzt_rad+2) )
4776
4777!
4778!--       Save trace gas paths to the respective arrays
4779          SELECT CASE ( TRIM( trace_names(m) ) )
4780
4781             CASE ( 'O3' )
4782
4783                rrtm_o3vmr(0,:) = trace_path_tmp(:)
4784
4785             CASE ( 'CO2' )
4786
4787                rrtm_co2vmr(0,:) = trace_path_tmp(:)
4788
4789             CASE ( 'CH4' )
4790
4791                rrtm_ch4vmr(0,:) = trace_path_tmp(:)
4792
4793             CASE ( 'N2O' )
4794
4795                rrtm_n2ovmr(0,:) = trace_path_tmp(:)
4796
4797             CASE ( 'O2' )
4798
4799                rrtm_o2vmr(0,:) = trace_path_tmp(:)
4800
4801             CASE ( 'CFC11' )
4802
4803                rrtm_cfc11vmr(0,:) = trace_path_tmp(:)
4804
4805             CASE ( 'CFC12' )
4806
4807                rrtm_cfc12vmr(0,:) = trace_path_tmp(:)
4808
4809             CASE ( 'CFC22' )
4810
4811                rrtm_cfc22vmr(0,:) = trace_path_tmp(:)
4812
4813             CASE ( 'CCL4' )
4814
4815                rrtm_ccl4vmr(0,:) = trace_path_tmp(:)
4816
4817             CASE ( 'H2O' )
4818
4819                rrtm_h2ovmr(0,:) = trace_path_tmp(:)
4820               
4821             CASE DEFAULT
4822
4823          END SELECT
4824
4825       ENDDO
4826
4827       DEALLOCATE ( trace_path_tmp )
4828       DEALLOCATE ( trace_mls_path )
4829       DEALLOCATE ( rrtm_play_tmp )
4830       DEALLOCATE ( rrtm_plev_tmp )
4831       DEALLOCATE ( trace_mls )
4832       DEALLOCATE ( p_mls )
4833
4834    END SUBROUTINE read_trace_gas_data
4835
4836
4837    SUBROUTINE netcdf_handle_error_rad( routine_name, errno )
4838
4839       USE control_parameters,                                                 &
4840           ONLY:  message_string
4841
4842       USE NETCDF
4843
4844       USE pegrid
4845
4846       IMPLICIT NONE
4847
4848       CHARACTER(LEN=6) ::  message_identifier
4849       CHARACTER(LEN=*) ::  routine_name
4850
4851       INTEGER(iwp) ::  errno
4852
4853       IF ( nc_stat /= NF90_NOERR )  THEN
4854
4855          WRITE( message_identifier, '(''NC'',I4.4)' )  errno
4856          message_string = TRIM( NF90_STRERROR( nc_stat ) )
4857
4858          CALL message( routine_name, message_identifier, 2, 2, 0, 6, 1 )
4859
4860       ENDIF
4861
4862    END SUBROUTINE netcdf_handle_error_rad
4863#endif
4864
4865
4866!------------------------------------------------------------------------------!
4867! Description:
4868! ------------
4869!> Calculate temperature tendency due to radiative cooling/heating.
4870!> Cache-optimized version.
4871!------------------------------------------------------------------------------!
4872 SUBROUTINE radiation_tendency_ij ( i, j, tend )
4873
4874    IMPLICIT NONE
4875
4876    INTEGER(iwp) :: i, j, k !< loop indices
4877
4878    REAL(wp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg) :: tend !< pt tendency term
4879
4880    IF ( radiation_scheme == 'rrtmg' )  THEN
4881#if defined  ( __rrtmg )
4882!
4883!--    Calculate tendency based on heating rate
4884       DO k = nzb+1, nzt+1
4885          tend(k,j,i) = tend(k,j,i) + (rad_lw_hr(k,j,i) + rad_sw_hr(k,j,i))    &
4886                                         * d_exner(k) * d_seconds_hour
4887       ENDDO
4888#endif
4889    ENDIF
4890
4891    END SUBROUTINE radiation_tendency_ij
4892
4893
4894!------------------------------------------------------------------------------!
4895! Description:
4896! ------------
4897!> Calculate temperature tendency due to radiative cooling/heating.
4898!> Vector-optimized version
4899!------------------------------------------------------------------------------!
4900 SUBROUTINE radiation_tendency ( tend )
4901
4902    USE indices,                                                               &
4903        ONLY:  nxl, nxr, nyn, nys
4904
4905    IMPLICIT NONE
4906
4907    INTEGER(iwp) :: i, j, k !< loop indices
4908
4909    REAL(wp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg) :: tend !< pt tendency term
4910
4911    IF ( radiation_scheme == 'rrtmg' )  THEN
4912#if defined  ( __rrtmg )
4913!
4914!--    Calculate tendency based on heating rate
4915       DO  i = nxl, nxr
4916          DO  j = nys, nyn
4917             DO k = nzb+1, nzt+1
4918                tend(k,j,i) = tend(k,j,i) + ( rad_lw_hr(k,j,i)                 &
4919                                          +  rad_sw_hr(k,j,i) ) * d_exner(k)   &
4920                                          * d_seconds_hour
4921             ENDDO
4922          ENDDO
4923       ENDDO
4924#endif
4925    ENDIF
4926
4927
4928 END SUBROUTINE radiation_tendency
4929
4930!------------------------------------------------------------------------------!
4931! Description:
4932! ------------
4933!> This subroutine calculates interaction of the solar radiation
4934!> with urban and land surfaces and updates all surface heatfluxes.
4935!> It calculates also the required parameters for RRTMG lower BC.
4936!>
4937!> For more info. see Resler et al. 2017
4938!>
4939!> The new version 2.0 was radically rewriten, the discretization scheme
4940!> has been changed. This new version significantly improves effectivity
4941!> of the paralelization and the scalability of the model.
4942!------------------------------------------------------------------------------!
4943
4944 SUBROUTINE radiation_interaction
4945
4946     IMPLICIT NONE
4947
4948     INTEGER(iwp)                      :: i, j, k, kk, is, js, d, ku, refstep, m, mm, l, ll
4949     INTEGER(iwp)                      :: isurf, isurfsrc, isvf, icsf, ipcgb
4950     INTEGER(iwp)                      :: imrt, imrtf
4951     INTEGER(iwp)                      :: isd                !< solar direction number
4952     INTEGER(iwp)                      :: pc_box_dimshift    !< transform for best accuracy
4953     INTEGER(iwp), DIMENSION(0:3)      :: reorder = (/ 1, 0, 3, 2 /)
4954     
4955     REAL(wp), DIMENSION(3,3)          :: mrot               !< grid rotation matrix (zyx)
4956     REAL(wp), DIMENSION(3,0:nsurf_type):: vnorm             !< face direction normal vectors (zyx)
4957     REAL(wp), DIMENSION(3)            :: sunorig            !< grid rotated solar direction unit vector (zyx)
4958     REAL(wp), DIMENSION(3)            :: sunorig_grid       !< grid squashed solar direction unit vector (zyx)
4959     REAL(wp), DIMENSION(0:nsurf_type) :: costheta           !< direct irradiance factor of solar angle
4960     REAL(wp), DIMENSION(nzub:nzut)    :: pchf_prep          !< precalculated factor for canopy temperature tendency
4961     REAL(wp), PARAMETER               :: alpha = 0._wp      !< grid rotation (TODO: add to namelist or remove)
4962     REAL(wp)                          :: pc_box_area, pc_abs_frac, pc_abs_eff
4963     REAL(wp)                          :: asrc               !< area of source face
4964     REAL(wp)                          :: pcrad              !< irradiance from plant canopy
4965     REAL(wp)                          :: pabsswl  = 0.0_wp  !< total absorbed SW radiation energy in local processor (W)
4966     REAL(wp)                          :: pabssw   = 0.0_wp  !< total absorbed SW radiation energy in all processors (W)
4967     REAL(wp)                          :: pabslwl  = 0.0_wp  !< total absorbed LW radiation energy in local processor (W)
4968     REAL(wp)                          :: pabslw   = 0.0_wp  !< total absorbed LW radiation energy in all processors (W)
4969     REAL(wp)                          :: pemitlwl = 0.0_wp  !< total emitted LW radiation energy in all processors (W)
4970     REAL(wp)                          :: pemitlw  = 0.0_wp  !< total emitted LW radiation energy in all processors (W)
4971     REAL(wp)                          :: pinswl   = 0.0_wp  !< total received SW radiation energy in local processor (W)
4972     REAL(wp)                          :: pinsw    = 0.0_wp  !< total received SW radiation energy in all processor (W)
4973     REAL(wp)                          :: pinlwl   = 0.0_wp  !< total received LW radiation energy in local processor (W)
4974     REAL(wp)                          :: pinlw    = 0.0_wp  !< total received LW radiation energy in all processor (W)
4975     REAL(wp)                          :: emiss_sum_surfl    !< sum of emissisivity of surfaces in local processor
4976     REAL(wp)                          :: emiss_sum_surf     !< sum of emissisivity of surfaces in all processor
4977     REAL(wp)                          :: area_surfl         !< total area of surfaces in local processor
4978     REAL(wp)                          :: area_surf          !< total area of surfaces in all processor
4979     REAL(wp)                          :: area_hor           !< total horizontal area of domain in all processor
4980
4981
4982     IF ( plant_canopy )  THEN
4983         pchf_prep(:) = r_d * exner(nzub:nzut)                                 &
4984                     / (c_p * hyp(nzub:nzut) * dx*dy*dz(1)) !< equals to 1 / (rho * c_p * Vbox * T)
4985     ENDIF
4986
4987     sun_direction = .TRUE.
4988     CALL calc_zenith  !< required also for diffusion radiation
4989
4990!--     prepare rotated normal vectors and irradiance factor
4991     vnorm(1,:) = kdir(:)
4992     vnorm(2,:) = jdir(:)
4993     vnorm(3,:) = idir(:)
4994     mrot(1, :) = (/ 1._wp,  0._wp,      0._wp      /)
4995     mrot(2, :) = (/ 0._wp,  COS(alpha), SIN(alpha) /)
4996     mrot(3, :) = (/ 0._wp, -SIN(alpha), COS(alpha) /)
4997     sunorig = (/ zenith(0), sun_dir_lat, sun_dir_lon /)
4998     sunorig = MATMUL(mrot, sunorig)
4999     DO d = 0, nsurf_type
5000         costheta(d) = DOT_PRODUCT(sunorig, vnorm(:,d))
5001     ENDDO
5002
5003     IF ( zenith(0) > 0 )  THEN
5004!--      now we will "squash" the sunorig vector by grid box size in
5005!--      each dimension, so that this new direction vector will allow us
5006!--      to traverse the ray path within grid coordinates directly
5007         sunorig_grid = (/ sunorig(1)/dz(1), sunorig(2)/dy, sunorig(3)/dx /)
5008!--      sunorig_grid = sunorig_grid / norm2(sunorig_grid)
5009         sunorig_grid = sunorig_grid / SQRT(SUM(sunorig_grid**2))
5010
5011         IF ( npcbl > 0 )  THEN
5012!--         precompute effective box depth with prototype Leaf Area Density
5013            pc_box_dimshift = MAXLOC(ABS(sunorig), 1) - 1
5014            CALL box_absorb(CSHIFT((/dz(1),dy,dx/), pc_box_dimshift),       &
5015                                60, prototype_lad,                          &
5016                                CSHIFT(ABS(sunorig), pc_box_dimshift),      &
5017                                pc_box_area, pc_abs_frac)
5018            pc_box_area = pc_box_area * ABS(sunorig(pc_box_dimshift+1)      &
5019                          / sunorig(1))
5020            pc_abs_eff = LOG(1._wp - pc_abs_frac) / prototype_lad
5021         ENDIF
5022     ENDIF
5023
5024!--  if radiation scheme is not RRTMG, split diffusion and direct part of the solar downward radiation
5025!--  comming from radiation model and store it in 2D arrays
5026     IF (  radiation_scheme /= 'rrtmg'  )  CALL calc_diffusion_radiation
5027
5028!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5029!--     First pass: direct + diffuse irradiance + thermal
5030!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5031     surfinswdir   = 0._wp !nsurfl
5032     surfins       = 0._wp !nsurfl
5033     surfinl       = 0._wp !nsurfl
5034     surfoutsl(:)  = 0.0_wp !start-end
5035     surfoutll(:)  = 0.0_wp !start-end
5036     IF ( nmrtbl > 0 )  THEN
5037        mrtinsw(:) = 0._wp
5038        mrtinlw(:) = 0._wp
5039     ENDIF
5040     surfinlg(:)  = 0._wp !global
5041
5042
5043!--  Set up thermal radiation from surfaces
5044!--  emiss_surf is defined only for surfaces for which energy balance is calculated
5045!--  Workaround: reorder surface data type back on 1D array including all surfaces,
5046!--  which implies to reorder horizontal and vertical surfaces
5047!
5048!--  Horizontal walls
5049     mm = 1
5050     DO  i = nxl, nxr
5051        DO  j = nys, nyn
5052!--           urban
5053           DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
5054              surfoutll(mm) = SUM ( surf_usm_h%frac(:,m) *                  &
5055                                    surf_usm_h%emissivity(:,m) )            &
5056                                  * sigma_sb                                &
5057                                  * surf_usm_h%pt_surface(m)**4
5058              albedo_surf(mm) = SUM ( surf_usm_h%frac(:,m) *                &
5059                                      surf_usm_h%albedo(:,m) )
5060              emiss_surf(mm)  = SUM ( surf_usm_h%frac(:,m) *                &
5061                                      surf_usm_h%emissivity(:,m) )
5062              mm = mm + 1
5063           ENDDO
5064!--           land
5065           DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
5066              surfoutll(mm) = SUM ( surf_lsm_h%frac(:,m) *                  &
5067                                    surf_lsm_h%emissivity(:,m) )            &
5068                                  * sigma_sb                                &
5069                                  * surf_lsm_h%pt_surface(m)**4
5070              albedo_surf(mm) = SUM ( surf_lsm_h%frac(:,m) *                &
5071                                      surf_lsm_h%albedo(:,m) )
5072              emiss_surf(mm)  = SUM ( surf_lsm_h%frac(:,m) *                &
5073                                      surf_lsm_h%emissivity(:,m) )
5074              mm = mm + 1
5075           ENDDO
5076        ENDDO
5077     ENDDO
5078!
5079!--     Vertical walls
5080     DO  i = nxl, nxr
5081        DO  j = nys, nyn
5082           DO  ll = 0, 3
5083              l = reorder(ll)
5084!--              urban
5085              DO  m = surf_usm_v(l)%start_index(j,i),                       &
5086                      surf_usm_v(l)%end_index(j,i)
5087                 surfoutll(mm) = SUM ( surf_usm_v(l)%frac(:,m) *            &
5088                                       surf_usm_v(l)%emissivity(:,m) )      &
5089                                  * sigma_sb                                &
5090                                  * surf_usm_v(l)%pt_surface(m)**4
5091                 albedo_surf(mm) = SUM ( surf_usm_v(l)%frac(:,m) *          &
5092                                         surf_usm_v(l)%albedo(:,m) )
5093                 emiss_surf(mm)  = SUM ( surf_usm_v(l)%frac(:,m) *          &
5094                                         surf_usm_v(l)%emissivity(:,m) )
5095                 mm = mm + 1
5096              ENDDO
5097!--              land
5098              DO  m = surf_lsm_v(l)%start_index(j,i),                       &
5099                      surf_lsm_v(l)%end_index(j,i)
5100                 surfoutll(mm) = SUM ( surf_lsm_v(l)%frac(:,m) *            &
5101                                       surf_lsm_v(l)%emissivity(:,m) )      &
5102                                  * sigma_sb                                &
5103                                  * surf_lsm_v(l)%pt_surface(m)**4
5104                 albedo_surf(mm) = SUM ( surf_lsm_v(l)%frac(:,m) *          &
5105                                         surf_lsm_v(l)%albedo(:,m) )
5106                 emiss_surf(mm)  = SUM ( surf_lsm_v(l)%frac(:,m) *          &
5107                                         surf_lsm_v(l)%emissivity(:,m) )
5108                 mm = mm + 1
5109              ENDDO
5110           ENDDO
5111        ENDDO
5112     ENDDO
5113
5114#if defined( __parallel )
5115!--     might be optimized and gather only values relevant for current processor
5116     CALL MPI_AllGatherv(surfoutll, nsurfl, MPI_REAL, &
5117                         surfoutl, nsurfs, surfstart, MPI_REAL, comm2d, ierr) !nsurf global
5118     IF ( ierr /= 0 ) THEN
5119         WRITE(9,*) 'Error MPI_AllGatherv1:', ierr, SIZE(surfoutll), nsurfl, &
5120                     SIZE(surfoutl), nsurfs, surfstart
5121         FLUSH(9)
5122     ENDIF
5123#else
5124     surfoutl(:) = surfoutll(:) !nsurf global
5125#endif
5126
5127     IF ( surface_reflections)  THEN
5128        DO  isvf = 1, nsvfl
5129           isurf = svfsurf(1, isvf)
5130           k     = surfl(iz, isurf)
5131           j     = surfl(iy, isurf)
5132           i     = surfl(ix, isurf)
5133           isurfsrc = svfsurf(2, isvf)
5134!
5135!--        For surface-to-surface factors we calculate thermal radiation in 1st pass
5136           IF ( plant_lw_interact )  THEN
5137              surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * svf(2,isvf) * surfoutl(isurfsrc)
5138           ELSE
5139              surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * surfoutl(isurfsrc)
5140           ENDIF
5141        ENDDO
5142     ENDIF
5143!
5144!--  diffuse radiation using sky view factor
5145     DO isurf = 1, nsurfl
5146        j = surfl(iy, isurf)
5147        i = surfl(ix, isurf)
5148        surfinswdif(isurf) = rad_sw_in_diff(j,i) * skyvft(isurf)
5149        IF ( plant_lw_interact )  THEN
5150           surfinlwdif(isurf) = rad_lw_in_diff(j,i) * skyvft(isurf)
5151        ELSE
5152           surfinlwdif(isurf) = rad_lw_in_diff(j,i) * skyvf(isurf)
5153        ENDIF
5154     ENDDO
5155!
5156!--  MRT diffuse irradiance
5157     DO  imrt = 1, nmrtbl
5158        j = mrtbl(iy, imrt)
5159        i = mrtbl(ix, imrt)
5160        mrtinsw(imrt) = mrtskyt(imrt) * rad_sw_in_diff(j,i)
5161        mrtinlw(imrt) = mrtsky(imrt) * rad_lw_in_diff(j,i)
5162     ENDDO
5163
5164     !-- direct radiation
5165     IF ( zenith(0) > 0 )  THEN
5166        !--Identify solar direction vector (discretized number) 1)
5167        !--
5168        j = FLOOR(ACOS(zenith(0)) / pi * raytrace_discrete_elevs)
5169        i = MODULO(NINT(ATAN2(sun_dir_lon(0), sun_dir_lat(0))               &
5170                        / (2._wp*pi) * raytrace_discrete_azims-.5_wp, iwp), &
5171                   raytrace_discrete_azims)
5172        isd = dsidir_rev(j, i)
5173!-- TODO: check if isd = -1 to report that this solar position is not precalculated
5174        DO isurf = 1, nsurfl
5175           j = surfl(iy, isurf)
5176           i = surfl(ix, isurf)
5177           surfinswdir(isurf) = rad_sw_in_dir(j,i) *                        &
5178                costheta(surfl(id, isurf)) * dsitrans(isurf, isd) / zenith(0)
5179        ENDDO
5180!
5181!--     MRT direct irradiance
5182        DO  imrt = 1, nmrtbl
5183           j = mrtbl(iy, imrt)
5184           i = mrtbl(ix, imrt)
5185           mrtinsw(imrt) = mrtinsw(imrt) + mrtdsit(imrt, isd) * rad_sw_in_dir(j,i) &
5186                                     / zenith(0) / 4._wp ! normal to sphere
5187        ENDDO
5188     ENDIF
5189!
5190!--  MRT first pass thermal
5191     DO  imrtf = 1, nmrtf
5192        imrt = mrtfsurf(1, imrtf)
5193        isurfsrc = mrtfsurf(2, imrtf)
5194        mrtinlw(imrt) = mrtinlw(imrt) + mrtf(imrtf) * surfoutl(isurfsrc)
5195     ENDDO
5196
5197     IF ( npcbl > 0 )  THEN
5198
5199         pcbinswdir(:) = 0._wp
5200         pcbinswdif(:) = 0._wp
5201         pcbinlw(:) = 0._wp
5202!
5203!--      pcsf first pass
5204         DO icsf = 1, ncsfl
5205             ipcgb = csfsurf(1, icsf)
5206             i = pcbl(ix,ipcgb)
5207             j = pcbl(iy,ipcgb)
5208             k = pcbl(iz,ipcgb)
5209             isurfsrc = csfsurf(2, icsf)
5210
5211             IF ( isurfsrc == -1 )  THEN
5212!
5213!--             Diffuse rad from sky.
5214                pcbinswdif(ipcgb) = csf(1,icsf) * rad_sw_in_diff(j,i)
5215!
5216!--             Absorbed diffuse LW from sky minus emitted to sky
5217                IF ( plant_lw_interact )  THEN
5218                   pcbinlw(ipcgb) = csf(1,icsf)                                  &
5219                                       * (rad_lw_in_diff(j, i)                   &
5220                                          - sigma_sb * (pt(k,j,i)*exner(k))**4)
5221                ENDIF
5222!
5223!--             Direct rad
5224                IF ( zenith(0) > 0 )  THEN
5225!--                Estimate directed box absorption
5226                   pc_abs_frac = 1._wp - exp(pc_abs_eff * lad_s(k,j,i))
5227!
5228!--                isd has already been established, see 1)
5229                   pcbinswdir(ipcgb) = rad_sw_in_dir(j, i) * pc_box_area &
5230                                       * pc_abs_frac * dsitransc(ipcgb, isd)
5231                ENDIF
5232             ELSE
5233                IF ( plant_lw_interact )  THEN
5234!
5235!--                Thermal emission from plan canopy towards respective face
5236                   pcrad = sigma_sb * (pt(k,j,i) * exner(k))**4 * csf(1,icsf)
5237                   surfinlg(isurfsrc) = surfinlg(isurfsrc) + pcrad
5238!
5239!--                Remove the flux above + absorb LW from first pass from surfaces
5240                   asrc = facearea(surf(id, isurfsrc))
5241                   pcbinlw(ipcgb) = pcbinlw(ipcgb)                      &
5242                                    + (csf(1,icsf) * surfoutl(isurfsrc) & ! Absorb from first pass surf emit
5243                                       - pcrad)                         & ! Remove emitted heatflux
5244                                    * asrc
5245                ENDIF
5246             ENDIF
5247         ENDDO
5248
5249         pcbinsw(:) = pcbinswdir(:) + pcbinswdif(:)
5250     ENDIF
5251
5252     IF ( plant_lw_interact )  THEN
5253!
5254!--     Exchange incoming lw radiation from plant canopy
5255#if defined( __parallel )
5256        CALL MPI_Allreduce(MPI_IN_PLACE, surfinlg, nsurf, MPI_REAL, MPI_SUM, comm2d, ierr)
5257        IF ( ierr /= 0 )  THEN
5258           WRITE (9,*) 'Error MPI_Allreduce:', ierr
5259           FLUSH(9)
5260        ENDIF
5261        surfinl(:) = surfinl(:) + surfinlg(surfstart(myid)+1:surfstart(myid+1))
5262#else
5263        surfinl(:) = surfinl(:) + surfinlg(:)
5264#endif
5265     ENDIF
5266
5267     surfins = surfinswdir + surfinswdif
5268     surfinl = surfinl + surfinlwdif
5269     surfinsw = surfins
5270     surfinlw = surfinl
5271     surfoutsw = 0.0_wp
5272     surfoutlw = surfoutll
5273     surfemitlwl = surfoutll
5274
5275     IF ( .NOT.  surface_reflections )  THEN
5276!
5277!--     Set nrefsteps to 0 to disable reflections       
5278        nrefsteps = 0
5279        surfoutsl = albedo_surf * surfins
5280        surfoutll = (1._wp - emiss_surf) * surfinl
5281        surfoutsw = surfoutsw + surfoutsl
5282        surfoutlw = surfoutlw + surfoutll
5283     ENDIF
5284
5285!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5286!--     Next passes - reflections
5287!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5288     DO refstep = 1, nrefsteps
5289
5290         surfoutsl = albedo_surf * surfins
5291!--         for non-transparent surfaces, longwave albedo is 1 - emissivity
5292         surfoutll = (1._wp - emiss_surf) * surfinl
5293
5294#if defined( __parallel )
5295         CALL MPI_AllGatherv(surfoutsl, nsurfl, MPI_REAL, &
5296             surfouts, nsurfs, surfstart, MPI_REAL, comm2d, ierr)
5297         IF ( ierr /= 0 ) THEN
5298             WRITE(9,*) 'Error MPI_AllGatherv2:', ierr, SIZE(surfoutsl), nsurfl, &
5299                        SIZE(surfouts), nsurfs, surfstart
5300             FLUSH(9)
5301         ENDIF
5302
5303         CALL MPI_AllGatherv(surfoutll, nsurfl, MPI_REAL, &
5304             surfoutl, nsurfs, surfstart, MPI_REAL, comm2d, ierr)
5305         IF ( ierr /= 0 ) THEN
5306             WRITE(9,*) 'Error MPI_AllGatherv3:', ierr, SIZE(surfoutll), nsurfl, &
5307                        SIZE(surfoutl), nsurfs, surfstart
5308             FLUSH(9)
5309         ENDIF
5310
5311#else
5312         surfouts = surfoutsl
5313         surfoutl = surfoutll
5314#endif
5315
5316!--         reset for next pass input
5317         surfins = 0._wp
5318         surfinl = 0._wp
5319
5320!--         reflected radiation
5321         DO isvf = 1, nsvfl
5322             isurf = svfsurf(1, isvf)
5323             isurfsrc = svfsurf(2, isvf)
5324             surfins(isurf) = surfins(isurf) + svf(1,isvf) * svf(2,isvf) * surfouts(isurfsrc)
5325             IF ( plant_lw_interact )  THEN
5326                surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * svf(2,isvf) * surfoutl(isurfsrc)
5327             ELSE
5328                surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * surfoutl(isurfsrc)
5329             ENDIF
5330         ENDDO
5331!
5332!--      NOTE: PC absorbtion and MRT from reflected can both be done at once
5333!--      after all reflections if we do one more MPI_ALLGATHERV on surfout.
5334!--      Advantage: less local computation. Disadvantage: one more collective
5335!--      MPI call.
5336!
5337!--      Radiation absorbed by plant canopy
5338         DO  icsf = 1, ncsfl
5339             ipcgb = csfsurf(1, icsf)
5340             isurfsrc = csfsurf(2, icsf)
5341             IF ( isurfsrc == -1 )  CYCLE ! sky->face only in 1st pass, not here
5342!
5343!--          Calculate source surface area. If the `surf' array is removed
5344!--          before timestepping starts (future version), then asrc must be
5345!--          stored within `csf'
5346             asrc = facearea(surf(id, isurfsrc))
5347             pcbinsw(ipcgb) = pcbinsw(ipcgb) + csf(1,icsf) * surfouts(isurfsrc) * asrc
5348             IF ( plant_lw_interact )  THEN
5349                pcbinlw(ipcgb) = pcbinlw(ipcgb) + csf(1,icsf) * surfoutl(isurfsrc) * asrc
5350             ENDIF
5351         ENDDO
5352!
5353!--      MRT reflected
5354         DO  imrtf = 1, nmrtf
5355            imrt = mrtfsurf(1, imrtf)
5356            isurfsrc = mrtfsurf(2, imrtf)
5357            mrtinsw(imrt) = mrtinsw(imrt) + mrtft(imrtf) * surfouts(isurfsrc)
5358            mrtinlw(imrt) = mrtinlw(imrt) + mrtf(imrtf) * surfoutl(isurfsrc)
5359         ENDDO
5360
5361         surfinsw = surfinsw  + surfins
5362         surfinlw = surfinlw  + surfinl
5363         surfoutsw = surfoutsw + surfoutsl
5364         surfoutlw = surfoutlw + surfoutll
5365
5366     ENDDO ! refstep
5367
5368!--  push heat flux absorbed by plant canopy to respective 3D arrays
5369     IF ( npcbl > 0 )  THEN
5370         pc_heating_rate(:,:,:) = 0.0_wp
5371         DO ipcgb = 1, npcbl
5372             j = pcbl(iy, ipcgb)
5373             i = pcbl(ix, ipcgb)
5374             k = pcbl(iz, ipcgb)
5375!
5376!--          Following expression equals former kk = k - nzb_s_inner(j,i)
5377             kk = k - get_topography_top_index_ji( j, i, 's' )  !- lad arrays are defined flat
5378             pc_heating_rate(kk, j, i) = (pcbinsw(ipcgb) + pcbinlw(ipcgb)) &
5379                 * pchf_prep(k) * pt(k, j, i) !-- = dT/dt
5380         ENDDO
5381
5382         IF ( humidity .AND. plant_canopy_transpiration ) THEN
5383!--          Calculation of plant canopy transpiration rate and correspondidng latent heat rate
5384             pc_transpiration_rate(:,:,:) = 0.0_wp
5385             pc_latent_rate(:,:,:) = 0.0_wp
5386             DO ipcgb = 1, npcbl
5387                 i = pcbl(ix, ipcgb)
5388                 j = pcbl(iy, ipcgb)
5389                 k = pcbl(iz, ipcgb)
5390                 kk = k - get_topography_top_index_ji( j, i, 's' )  !- lad arrays are defined flat
5391                 CALL pcm_calc_transpiration_rate( i, j, k, kk, pcbinsw(ipcgb), pcbinlw(ipcgb), &
5392                                                   pc_transpiration_rate(kk,j,i), pc_latent_rate(kk,j,i) )
5393              ENDDO
5394         ENDIF
5395     ENDIF
5396!
5397!--  Calculate black body MRT (after all reflections)
5398     IF ( nmrtbl > 0 )  THEN
5399        IF ( mrt_include_sw )  THEN
5400           mrt(:) = ((mrtinsw(:) + mrtinlw(:)) / sigma_sb) ** .25_wp
5401        ELSE
5402           mrt(:) = (mrtinlw(:) / sigma_sb) ** .25_wp
5403        ENDIF
5404     ENDIF
5405!
5406!--     Transfer radiation arrays required for energy balance to the respective data types
5407     DO  i = 1, nsurfl
5408        m  = surfl(5,i)
5409!
5410!--     (1) Urban surfaces
5411!--     upward-facing
5412        IF ( surfl(1,i) == iup_u )  THEN
5413           surf_usm_h%rad_sw_in(m)  = surfinsw(i)
5414           surf_usm_h%rad_sw_out(m) = surfoutsw(i)
5415           surf_usm_h%rad_sw_dir(m) = surfinswdir(i)
5416           surf_usm_h%rad_sw_dif(m) = surfinswdif(i)
5417           surf_usm_h%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -        &
5418                                      surfinswdif(i)
5419           surf_usm_h%rad_sw_res(m) = surfins(i)
5420           surf_usm_h%rad_lw_in(m)  = surfinlw(i)
5421           surf_usm_h%rad_lw_out(m) = surfoutlw(i)
5422           surf_usm_h%rad_net(m)    = surfinsw(i) - surfoutsw(i) +          &
5423                                      surfinlw(i) - surfoutlw(i)
5424           surf_usm_h%rad_net_l(m)  = surf_usm_h%rad_net(m)
5425           surf_usm_h%rad_lw_dif(m) = surfinlwdif(i)
5426           surf_usm_h%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5427           surf_usm_h%rad_lw_res(m) = surfinl(i)
5428!
5429!--     northward-facding
5430        ELSEIF ( surfl(1,i) == inorth_u )  THEN
5431           surf_usm_v(0)%rad_sw_in(m)  = surfinsw(i)
5432           surf_usm_v(0)%rad_sw_out(m) = surfoutsw(i)
5433           surf_usm_v(0)%rad_sw_dir(m) = surfinswdir(i)
5434           surf_usm_v(0)%rad_sw_dif(m) = surfinswdif(i)
5435           surf_usm_v(0)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5436                                         surfinswdif(i)
5437           surf_usm_v(0)%rad_sw_res(m) = surfins(i)
5438           surf_usm_v(0)%rad_lw_in(m)  = surfinlw(i)
5439           surf_usm_v(0)%rad_lw_out(m) = surfoutlw(i)
5440           surf_usm_v(0)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5441                                         surfinlw(i) - surfoutlw(i)
5442           surf_usm_v(0)%rad_net_l(m)  = surf_usm_v(0)%rad_net(m)
5443           surf_usm_v(0)%rad_lw_dif(m) = surfinlwdif(i)
5444           surf_usm_v(0)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5445           surf_usm_v(0)%rad_lw_res(m) = surfinl(i)
5446!
5447!--     southward-facding
5448        ELSEIF ( surfl(1,i) == isouth_u )  THEN
5449           surf_usm_v(1)%rad_sw_in(m)  = surfinsw(i)
5450           surf_usm_v(1)%rad_sw_out(m) = surfoutsw(i)
5451           surf_usm_v(1)%rad_sw_dir(m) = surfinswdir(i)
5452           surf_usm_v(1)%rad_sw_dif(m) = surfinswdif(i)
5453           surf_usm_v(1)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5454                                         surfinswdif(i)
5455           surf_usm_v(1)%rad_sw_res(m) = surfins(i)
5456           surf_usm_v(1)%rad_lw_in(m)  = surfinlw(i)
5457           surf_usm_v(1)%rad_lw_out(m) = surfoutlw(i)
5458           surf_usm_v(1)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5459                                         surfinlw(i) - surfoutlw(i)
5460           surf_usm_v(1)%rad_net_l(m)  = surf_usm_v(1)%rad_net(m)
5461           surf_usm_v(1)%rad_lw_dif(m) = surfinlwdif(i)
5462           surf_usm_v(1)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5463           surf_usm_v(1)%rad_lw_res(m) = surfinl(i)
5464!
5465!--     eastward-facing
5466        ELSEIF ( surfl(1,i) == ieast_u )  THEN
5467           surf_usm_v(2)%rad_sw_in(m)  = surfinsw(i)
5468           surf_usm_v(2)%rad_sw_out(m) = surfoutsw(i)
5469           surf_usm_v(2)%rad_sw_dir(m) = surfinswdir(i)
5470           surf_usm_v(2)%rad_sw_dif(m) = surfinswdif(i)
5471           surf_usm_v(2)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5472                                         surfinswdif(i)
5473           surf_usm_v(2)%rad_sw_res(m) = surfins(i)
5474           surf_usm_v(2)%rad_lw_in(m)  = surfinlw(i)
5475           surf_usm_v(2)%rad_lw_out(m) = surfoutlw(i)
5476           surf_usm_v(2)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5477                                         surfinlw(i) - surfoutlw(i)
5478           surf_usm_v(2)%rad_net_l(m)  = surf_usm_v(2)%rad_net(m)
5479           surf_usm_v(2)%rad_lw_dif(m) = surfinlwdif(i)
5480           surf_usm_v(2)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5481           surf_usm_v(2)%rad_lw_res(m) = surfinl(i)
5482!
5483!--     westward-facding
5484        ELSEIF ( surfl(1,i) == iwest_u )  THEN
5485           surf_usm_v(3)%rad_sw_in(m)  = surfinsw(i)
5486           surf_usm_v(3)%rad_sw_out(m) = surfoutsw(i)
5487           surf_usm_v(3)%rad_sw_dir(m) = surfinswdir(i)
5488           surf_usm_v(3)%rad_sw_dif(m) = surfinswdif(i)
5489           surf_usm_v(3)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5490                                         surfinswdif(i)
5491           surf_usm_v(3)%rad_sw_res(m) = surfins(i)
5492           surf_usm_v(3)%rad_lw_in(m)  = surfinlw(i)
5493           surf_usm_v(3)%rad_lw_out(m) = surfoutlw(i)
5494           surf_usm_v(3)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5495                                         surfinlw(i) - surfoutlw(i)
5496           surf_usm_v(3)%rad_net_l(m)  = surf_usm_v(3)%rad_net(m)
5497           surf_usm_v(3)%rad_lw_dif(m) = surfinlwdif(i)
5498           surf_usm_v(3)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5499           surf_usm_v(3)%rad_lw_res(m) = surfinl(i)
5500!
5501!--     (2) land surfaces
5502!--     upward-facing
5503        ELSEIF ( surfl(1,i) == iup_l )  THEN
5504           surf_lsm_h%rad_sw_in(m)  = surfinsw(i)
5505           surf_lsm_h%rad_sw_out(m) = surfoutsw(i)
5506           surf_lsm_h%rad_sw_dir(m) = surfinswdir(i)
5507           surf_lsm_h%rad_sw_dif(m) = surfinswdif(i)
5508           surf_lsm_h%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -        &
5509                                         surfinswdif(i)
5510           surf_lsm_h%rad_sw_res(m) = surfins(i)
5511           surf_lsm_h%rad_lw_in(m)  = surfinlw(i)
5512           surf_lsm_h%rad_lw_out(m) = surfoutlw(i)
5513           surf_lsm_h%rad_net(m)    = surfinsw(i) - surfoutsw(i) +          &
5514                                      surfinlw(i) - surfoutlw(i)
5515           surf_lsm_h%rad_lw_dif(m) = surfinlwdif(i)
5516           surf_lsm_h%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5517           surf_lsm_h%rad_lw_res(m) = surfinl(i)
5518!
5519!--     northward-facding
5520        ELSEIF ( surfl(1,i) == inorth_l )  THEN
5521           surf_lsm_v(0)%rad_sw_in(m)  = surfinsw(i)
5522           surf_lsm_v(0)%rad_sw_out(m) = surfoutsw(i)
5523           surf_lsm_v(0)%rad_sw_dir(m) = surfinswdir(i)
5524           surf_lsm_v(0)%rad_sw_dif(m) = surfinswdif(i)
5525           surf_lsm_v(0)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5526                                         surfinswdif(i)
5527           surf_lsm_v(0)%rad_sw_res(m) = surfins(i)
5528           surf_lsm_v(0)%rad_lw_in(m)  = surfinlw(i)
5529           surf_lsm_v(0)%rad_lw_out(m) = surfoutlw(i)
5530           surf_lsm_v(0)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5531                                         surfinlw(i) - surfoutlw(i)
5532           surf_lsm_v(0)%rad_lw_dif(m) = surfinlwdif(i)
5533           surf_lsm_v(0)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5534           surf_lsm_v(0)%rad_lw_res(m) = surfinl(i)
5535!
5536!--     southward-facding
5537        ELSEIF ( surfl(1,i) == isouth_l )  THEN
5538           surf_lsm_v(1)%rad_sw_in(m)  = surfinsw(i)
5539           surf_lsm_v(1)%rad_sw_out(m) = surfoutsw(i)
5540           surf_lsm_v(1)%rad_sw_dir(m) = surfinswdir(i)
5541           surf_lsm_v(1)%rad_sw_dif(m) = surfinswdif(i)
5542           surf_lsm_v(1)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5543                                         surfinswdif(i)
5544           surf_lsm_v(1)%rad_sw_res(m) = surfins(i)
5545           surf_lsm_v(1)%rad_lw_in(m)  = surfinlw(i)
5546           surf_lsm_v(1)%rad_lw_out(m) = surfoutlw(i)
5547           surf_lsm_v(1)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5548                                         surfinlw(i) - surfoutlw(i)
5549           surf_lsm_v(1)%rad_lw_dif(m) = surfinlwdif(i)
5550           surf_lsm_v(1)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5551           surf_lsm_v(1)%rad_lw_res(m) = surfinl(i)
5552!
5553!--     eastward-facing
5554        ELSEIF ( surfl(1,i) == ieast_l )  THEN
5555           surf_lsm_v(2)%rad_sw_in(m)  = surfinsw(i)
5556           surf_lsm_v(2)%rad_sw_out(m) = surfoutsw(i)
5557           surf_lsm_v(2)%rad_sw_dir(m) = surfinswdir(i)
5558           surf_lsm_v(2)%rad_sw_dif(m) = surfinswdif(i)
5559           surf_lsm_v(2)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5560                                         surfinswdif(i)
5561           surf_lsm_v(2)%rad_sw_res(m) = surfins(i)
5562           surf_lsm_v(2)%rad_lw_in(m)  = surfinlw(i)
5563           surf_lsm_v(2)%rad_lw_out(m) = surfoutlw(i)
5564           surf_lsm_v(2)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5565                                         surfinlw(i) - surfoutlw(i)
5566           surf_lsm_v(2)%rad_lw_dif(m) = surfinlwdif(i)
5567           surf_lsm_v(2)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5568           surf_lsm_v(2)%rad_lw_res(m) = surfinl(i)
5569!
5570!--     westward-facing
5571        ELSEIF ( surfl(1,i) == iwest_l )  THEN
5572           surf_lsm_v(3)%rad_sw_in(m)  = surfinsw(i)
5573           surf_lsm_v(3)%rad_sw_out(m) = surfoutsw(i)
5574           surf_lsm_v(3)%rad_sw_dir(m) = surfinswdir(i)
5575           surf_lsm_v(3)%rad_sw_dif(m) = surfinswdif(i)
5576           surf_lsm_v(3)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5577                                         surfinswdif(i)
5578           surf_lsm_v(3)%rad_sw_res(m) = surfins(i)
5579           surf_lsm_v(3)%rad_lw_in(m)  = surfinlw(i)
5580           surf_lsm_v(3)%rad_lw_out(m) = surfoutlw(i)
5581           surf_lsm_v(3)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5582                                         surfinlw(i) - surfoutlw(i)
5583           surf_lsm_v(3)%rad_lw_dif(m) = surfinlwdif(i)
5584           surf_lsm_v(3)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5585           surf_lsm_v(3)%rad_lw_res(m) = surfinl(i)
5586        ENDIF
5587
5588     ENDDO
5589
5590     DO  m = 1, surf_usm_h%ns
5591        surf_usm_h%surfhf(m) = surf_usm_h%rad_sw_in(m)  +                   &
5592                               surf_usm_h%rad_lw_in(m)  -                   &
5593                               surf_usm_h%rad_sw_out(m) -                   &
5594                               surf_usm_h%rad_lw_out(m)
5595     ENDDO
5596     DO  m = 1, surf_lsm_h%ns
5597        surf_lsm_h%surfhf(m) = surf_lsm_h%rad_sw_in(m)  +                   &
5598                               surf_lsm_h%rad_lw_in(m)  -                   &
5599                               surf_lsm_h%rad_sw_out(m) -                   &
5600                               surf_lsm_h%rad_lw_out(m)
5601     ENDDO
5602
5603     DO  l = 0, 3
5604!--     urban
5605        DO  m = 1, surf_usm_v(l)%ns
5606           surf_usm_v(l)%surfhf(m) = surf_usm_v(l)%rad_sw_in(m)  +          &
5607                                     surf_usm_v(l)%rad_lw_in(m)  -          &
5608                                     surf_usm_v(l)%rad_sw_out(m) -          &
5609                                     surf_usm_v(l)%rad_lw_out(m)
5610        ENDDO
5611!--     land
5612        DO  m = 1, surf_lsm_v(l)%ns
5613           surf_lsm_v(l)%surfhf(m) = surf_lsm_v(l)%rad_sw_in(m)  +          &
5614                                     surf_lsm_v(l)%rad_lw_in(m)  -          &
5615                                     surf_lsm_v(l)%rad_sw_out(m) -          &
5616                                     surf_lsm_v(l)%rad_lw_out(m)
5617
5618        ENDDO
5619     ENDDO
5620!
5621!--  Calculate the average temperature, albedo, and emissivity for urban/land
5622!--  domain when using average_radiation in the respective radiation model
5623
5624!--  calculate horizontal area
5625! !!! ATTENTION!!! uniform grid is assumed here
5626     area_hor = (nx+1) * (ny+1) * dx * dy
5627!
5628!--  absorbed/received SW & LW and emitted LW energy of all physical
5629!--  surfaces (land and urban) in local processor
5630     pinswl = 0._wp
5631     pinlwl = 0._wp
5632     pabsswl = 0._wp
5633     pabslwl = 0._wp
5634     pemitlwl = 0._wp
5635     emiss_sum_surfl = 0._wp
5636     area_surfl = 0._wp
5637     DO  i = 1, nsurfl
5638        d = surfl(id, i)
5639!--  received SW & LW
5640        pinswl = pinswl + (surfinswdir(i) + surfinswdif(i)) * facearea(d)
5641        pinlwl = pinlwl + surfinlwdif(i) * facearea(d)
5642!--   absorbed SW & LW
5643        pabsswl = pabsswl + (1._wp - albedo_surf(i)) *                   &
5644                                                surfinsw(i) * facearea(d)
5645        pabslwl = pabslwl + emiss_surf(i) * surfinlw(i) * facearea(d)
5646!--   emitted LW
5647        pemitlwl = pemitlwl + surfemitlwl(i) * facearea(d)
5648!--   emissivity and area sum
5649        emiss_sum_surfl = emiss_sum_surfl + emiss_surf(i) * facearea(d)
5650        area_surfl = area_surfl + facearea(d)
5651     END DO
5652!
5653!--  add the absorbed SW energy by plant canopy
5654     IF ( npcbl > 0 )  THEN
5655        pabsswl = pabsswl + SUM(pcbinsw)
5656        pabslwl = pabslwl + SUM(pcbinlw)
5657        pinswl = pinswl + SUM(pcbinswdir) + SUM(pcbinswdif)
5658     ENDIF
5659!
5660!--  gather all rad flux energy in all processors
5661#if defined( __parallel )
5662     CALL MPI_ALLREDUCE( pinswl, pinsw, 1, MPI_REAL, MPI_SUM, comm2d, ierr)
5663     IF ( ierr /= 0 ) THEN
5664         WRITE(9,*) 'Error MPI_AllReduce5:', ierr, pinswl, pinsw
5665         FLUSH(9)
5666     ENDIF
5667     CALL MPI_ALLREDUCE( pinlwl, pinlw, 1, MPI_REAL, MPI_SUM, comm2d, ierr)
5668     IF ( ierr /= 0 ) THEN
5669         WRITE(9,*) 'Error MPI_AllReduce6:', ierr, pinlwl, pinlw
5670         FLUSH(9)
5671     ENDIF
5672     CALL MPI_ALLREDUCE( pabsswl, pabssw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5673     IF ( ierr /= 0 ) THEN
5674         WRITE(9,*) 'Error MPI_AllReduce7:', ierr, pabsswl, pabssw
5675         FLUSH(9)
5676     ENDIF
5677     CALL MPI_ALLREDUCE( pabslwl, pabslw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5678     IF ( ierr /= 0 ) THEN
5679         WRITE(9,*) 'Error MPI_AllReduce8:', ierr, pabslwl, pabslw
5680         FLUSH(9)
5681     ENDIF
5682     CALL MPI_ALLREDUCE( pemitlwl, pemitlw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5683     IF ( ierr /= 0 ) THEN
5684         WRITE(9,*) 'Error MPI_AllReduce8:', ierr, pemitlwl, pemitlw
5685         FLUSH(9)
5686     ENDIF
5687     CALL MPI_ALLREDUCE( emiss_sum_surfl, emiss_sum_surf, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5688     IF ( ierr /= 0 ) THEN
5689         WRITE(9,*) 'Error MPI_AllReduce9:', ierr, emiss_sum_surfl, emiss_sum_surf
5690         FLUSH(9)
5691     ENDIF
5692     CALL MPI_ALLREDUCE( area_surfl, area_surf, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5693     IF ( ierr /= 0 ) THEN
5694         WRITE(9,*) 'Error MPI_AllReduce10:', ierr, area_surfl, area_surf
5695         FLUSH(9)
5696     ENDIF
5697#else
5698     pinsw = pinswl
5699     pinlw = pinlwl
5700     pabssw = pabsswl
5701     pabslw = pabslwl
5702     pemitlw = pemitlwl
5703     emiss_sum_surf = emiss_sum_surfl
5704     area_surf = area_surfl
5705#endif
5706
5707!--  (1) albedo
5708     IF ( pinsw /= 0.0_wp )  &
5709          albedo_urb = (pinsw - pabssw) / pinsw
5710!--  (2) average emmsivity
5711     IF ( area_surf /= 0.0_wp ) &
5712          emissivity_urb = emiss_sum_surf / area_surf
5713!
5714!--  Temporally comment out calculation of effective radiative temperature.
5715!--  See below for more explanation.
5716!--  (3) temperature
5717!--   first we calculate an effective horizontal area to account for
5718!--   the effect of vertical surfaces (which contributes to LW emission)
5719!--   We simply use the ratio of the total LW to the incoming LW flux
5720      area_hor = pinlw/rad_lw_in_diff(nyn,nxl)
5721      t_rad_urb = ( (pemitlw - pabslw + emissivity_urb*pinlw) / &
5722           (emissivity_urb*sigma_sb * area_hor) )**0.25_wp
5723
5724    CONTAINS
5725
5726!------------------------------------------------------------------------------!
5727!> Calculates radiation absorbed by box with given size and LAD.
5728!>
5729!> Simulates resol**2 rays (by equally spacing a bounding horizontal square
5730!> conatining all possible rays that would cross the box) and calculates
5731!> average transparency per ray. Returns fraction of absorbed radiation flux
5732!> and area for which this fraction is effective.
5733!------------------------------------------------------------------------------!
5734    PURE SUBROUTINE box_absorb(boxsize, resol, dens, uvec, area, absorb)
5735       IMPLICIT NONE
5736
5737       REAL(wp), DIMENSION(3), INTENT(in) :: &
5738            boxsize, &      !< z, y, x size of box in m
5739            uvec            !< z, y, x unit vector of incoming flux
5740       INTEGER(iwp), INTENT(in) :: &
5741            resol           !< No. of rays in x and y dimensions
5742       REAL(wp), INTENT(in) :: &
5743            dens            !< box density (e.g. Leaf Area Density)
5744       REAL(wp), INTENT(out) :: &
5745            area, &         !< horizontal area for flux absorbtion
5746            absorb          !< fraction of absorbed flux
5747       REAL(wp) :: &
5748            xshift, yshift, &
5749            xmin, xmax, ymin, ymax, &
5750            xorig, yorig, &
5751            dx1, dy1, dz1, dx2, dy2, dz2, &
5752            crdist, &
5753            transp
5754       INTEGER(iwp) :: &
5755            i, j
5756
5757       xshift = uvec(3) / uvec(1) * boxsize(1)
5758       xmin = min(0._wp, -xshift)
5759       xmax = boxsize(3) + max(0._wp, -xshift)
5760       yshift = uvec(2) / uvec(1) * boxsize(1)
5761       ymin = min(0._wp, -yshift)
5762       ymax = boxsize(2) + max(0._wp, -yshift)
5763
5764       transp = 0._wp
5765       DO i = 1, resol
5766          xorig = xmin + (xmax-xmin) * (i-.5_wp) / resol
5767          DO j = 1, resol
5768             yorig = ymin + (ymax-ymin) * (j-.5_wp) / resol
5769
5770             dz1 = 0._wp
5771             dz2 = boxsize(1)/uvec(1)
5772
5773             IF ( uvec(2) > 0._wp )  THEN
5774                dy1 = -yorig             / uvec(2) !< crossing with y=0
5775                dy2 = (boxsize(2)-yorig) / uvec(2) !< crossing with y=boxsize(2)
5776             ELSE !uvec(2)==0
5777                dy1 = -huge(1._wp)
5778                dy2 = huge(1._wp)
5779             ENDIF
5780
5781             IF ( uvec(3) > 0._wp )  THEN
5782                dx1 = -xorig             / uvec(3) !< crossing with x=0
5783                dx2 = (boxsize(3)-xorig) / uvec(3) !< crossing with x=boxsize(3)
5784             ELSE !uvec(3)==0
5785                dx1 = -huge(1._wp)
5786                dx2 = huge(1._wp)
5787             ENDIF
5788
5789             crdist = max(0._wp, (min(dz2, dy2, dx2) - max(dz1, dy1, dx1)))
5790             transp = transp + exp(-ext_coef * dens * crdist)
5791          ENDDO
5792       ENDDO
5793       transp = transp / resol**2
5794       area = (boxsize(3)+xshift)*(boxsize(2)+yshift)
5795       absorb = 1._wp - transp
5796
5797    END SUBROUTINE box_absorb
5798
5799!------------------------------------------------------------------------------!
5800! Description:
5801! ------------
5802!> This subroutine splits direct and diffusion dw radiation
5803!> It sould not be called in case the radiation model already does it
5804!> It follows <CITATION>
5805!------------------------------------------------------------------------------!
5806    SUBROUTINE calc_diffusion_radiation 
5807   
5808        REAL(wp), PARAMETER                          :: lowest_solarUp = 0.1_wp  !< limit the sun elevation to protect stability of the calculation
5809        INTEGER(iwp)                                 :: i, j
5810        REAL(wp)                                     ::  year_angle              !< angle
5811        REAL(wp)                                     ::  etr                     !< extraterestrial radiation
5812        REAL(wp)                                     ::  corrected_solarUp       !< corrected solar up radiation
5813        REAL(wp)                                     ::  horizontalETR           !< horizontal extraterestrial radiation
5814        REAL(wp)                                     ::  clearnessIndex          !< clearness index
5815        REAL(wp)                                     ::  diff_frac               !< diffusion fraction of the radiation
5816
5817       
5818!--     Calculate current day and time based on the initial values and simulation time
5819        year_angle = ( (day_of_year_init * 86400) + time_utc_init              &
5820                        + time_since_reference_point )  * d_seconds_year       &
5821                        * 2.0_wp * pi
5822       
5823        etr = solar_constant * (1.00011_wp +                                   &
5824                          0.034221_wp * cos(year_angle) +                      &
5825                          0.001280_wp * sin(year_angle) +                      &
5826                          0.000719_wp * cos(2.0_wp * year_angle) +             &
5827                          0.000077_wp * sin(2.0_wp * year_angle))
5828       
5829!--   
5830!--     Under a very low angle, we keep extraterestrial radiation at
5831!--     the last small value, therefore the clearness index will be pushed
5832!--     towards 0 while keeping full continuity.
5833!--   
5834        IF ( zenith(0) <= lowest_solarUp )  THEN
5835            corrected_solarUp = lowest_solarUp
5836        ELSE
5837            corrected_solarUp = zenith(0)
5838        ENDIF
5839       
5840        horizontalETR = etr * corrected_solarUp
5841       
5842        DO i = nxl, nxr
5843            DO j = nys, nyn
5844                clearnessIndex = rad_sw_in(0,j,i) / horizontalETR
5845                diff_frac = 1.0_wp / (1.0_wp + exp(-5.0033_wp + 8.6025_wp * clearnessIndex))
5846                rad_sw_in_diff(j,i) = rad_sw_in(0,j,i) * diff_frac
5847                rad_sw_in_dir(j,i)  = rad_sw_in(0,j,i) * (1.0_wp - diff_frac)
5848                rad_lw_in_diff(j,i) = rad_lw_in(0,j,i)
5849            ENDDO
5850        ENDDO
5851       
5852    END SUBROUTINE calc_diffusion_radiation
5853
5854
5855 END SUBROUTINE radiation_interaction
5856   
5857!------------------------------------------------------------------------------!
5858! Description:
5859! ------------
5860!> This subroutine initializes structures needed for radiative transfer
5861!> model. This model calculates transformation processes of the
5862!> radiation inside urban and land canopy layer. The module includes also
5863!> the interaction of the radiation with the resolved plant canopy.
5864!>
5865!> For more info. see Resler et al. 2017
5866!>
5867!> The new version 2.0 was radically rewriten, the discretization scheme
5868!> has been changed. This new version significantly improves effectivity
5869!> of the paralelization and the scalability of the model.
5870!>
5871!------------------------------------------------------------------------------!
5872    SUBROUTINE radiation_interaction_init
5873
5874       USE control_parameters,                                                 &
5875           ONLY:  dz_stretch_level_start
5876           
5877       USE netcdf_data_input_mod,                                              &
5878           ONLY:  leaf_area_density_f
5879
5880       USE plant_canopy_model_mod,                                             &
5881           ONLY:  pch_index, lad_s
5882
5883       IMPLICIT NONE
5884
5885       INTEGER(iwp) :: i, j, k, l, m, d
5886       INTEGER(iwp) :: k_topo     !< vertical index indicating topography top for given (j,i)
5887       INTEGER(iwp) :: nzptl, nzubl, nzutl, isurf, ipcgb, imrt
5888       REAL(wp)     :: mrl
5889#if defined( __parallel )
5890       INTEGER(iwp), DIMENSION(:), POINTER       ::  gridsurf_rma   !< fortran pointer, but lower bounds are 1
5891       TYPE(c_ptr)                               ::  gridsurf_rma_p !< allocated c pointer
5892       INTEGER(iwp)                              ::  minfo          !< MPI RMA window info handle
5893#endif
5894
5895!
5896!--     precalculate face areas for different face directions using normal vector
5897        DO d = 0, nsurf_type
5898            facearea(d) = 1._wp
5899            IF ( idir(d) == 0 ) facearea(d) = facearea(d) * dx
5900            IF ( jdir(d) == 0 ) facearea(d) = facearea(d) * dy
5901            IF ( kdir(d) == 0 ) facearea(d) = facearea(d) * dz(1)
5902        ENDDO
5903!
5904!--    Find nzub, nzut, nzu via wall_flag_0 array (nzb_s_inner will be
5905!--    removed later). The following contruct finds the lowest / largest index
5906!--    for any upward-facing wall (see bit 12).
5907       nzubl = MINVAL( get_topography_top_index( 's' ) )
5908       nzutl = MAXVAL( get_topography_top_index( 's' ) )
5909
5910       nzubl = MAX( nzubl, nzb )
5911
5912       IF ( plant_canopy )  THEN
5913!--        allocate needed arrays
5914           ALLOCATE( pct(nys:nyn,nxl:nxr) )
5915           ALLOCATE( pch(nys:nyn,nxl:nxr) )
5916
5917!--        calculate plant canopy height
5918           npcbl = 0
5919           pct   = 0
5920           pch   = 0
5921           DO i = nxl, nxr
5922               DO j = nys, nyn
5923!
5924!--                Find topography top index
5925                   k_topo = get_topography_top_index_ji( j, i, 's' )
5926
5927                   DO k = nzt+1, 0, -1
5928                       IF ( lad_s(k,j,i) /= 0.0_wp )  THEN
5929!--                        we are at the top of the pcs
5930                           pct(j,i) = k + k_topo
5931                           pch(j,i) = k
5932                           npcbl = npcbl + pch(j,i)
5933                           EXIT
5934                       ENDIF
5935                   ENDDO
5936               ENDDO
5937           ENDDO
5938
5939           nzutl = MAX( nzutl, MAXVAL( pct ) )
5940           nzptl = MAXVAL( pct )
5941!--        code of plant canopy model uses parameter pch_index
5942!--        we need to setup it here to right value
5943!--        (pch_index, lad_s and other arrays in PCM are defined flat)
5944           pch_index = MERGE( leaf_area_density_f%nz - 1, MAXVAL( pch ),       &
5945                              leaf_area_density_f%from_file )
5946
5947           prototype_lad = MAXVAL( lad_s ) * .9_wp  !< better be *1.0 if lad is either 0 or maxval(lad) everywhere
5948           IF ( prototype_lad <= 0._wp ) prototype_lad = .3_wp
5949           !WRITE(message_string, '(a,f6.3)') 'Precomputing effective box optical ' &
5950           !    // 'depth using prototype leaf area density = ', prototype_lad
5951           !CALL message('radiation_interaction_init', 'PA0520', 0, 0, -1, 6, 0)
5952       ENDIF
5953
5954       nzutl = MIN( nzutl + nzut_free, nzt )
5955
5956#if defined( __parallel )
5957       CALL MPI_AllReduce(nzubl, nzub, 1, MPI_INTEGER, MPI_MIN, comm2d, ierr )
5958       IF ( ierr /= 0 ) THEN
5959           WRITE(9,*) 'Error MPI_AllReduce11:', ierr, nzubl, nzub
5960           FLUSH(9)
5961       ENDIF
5962       CALL MPI_AllReduce(nzutl, nzut, 1, MPI_INTEGER, MPI_MAX, comm2d, ierr )
5963       IF ( ierr /= 0 ) THEN
5964           WRITE(9,*) 'Error MPI_AllReduce12:', ierr, nzutl, nzut
5965           FLUSH(9)
5966       ENDIF
5967       CALL MPI_AllReduce(nzptl, nzpt, 1, MPI_INTEGER, MPI_MAX, comm2d, ierr )
5968       IF ( ierr /= 0 ) THEN
5969           WRITE(9,*) 'Error MPI_AllReduce13:', ierr, nzptl, nzpt
5970           FLUSH(9)
5971       ENDIF
5972#else
5973       nzub = nzubl
5974       nzut = nzutl
5975       nzpt = nzptl
5976#endif
5977!
5978!--    Stretching (non-uniform grid spacing) is not considered in the radiation
5979!--    model. Therefore, vertical stretching has to be applied above the area
5980!--    where the parts of the radiation model which assume constant grid spacing
5981!--    are active. ABS (...) is required because the default value of
5982!--    dz_stretch_level_start is -9999999.9_wp (negative).
5983       IF ( ABS( dz_stretch_level_start(1) ) <= zw(nzut) ) THEN
5984          WRITE( message_string, * ) 'The lowest level where vertical ',       &
5985                                     'stretching is applied have to be ',      &
5986                                     'greater than ', zw(nzut)
5987          CALL message( 'radiation_interaction_init', 'PA0496', 1, 2, 0, 6, 0 )
5988       ENDIF 
5989!
5990!--    global number of urban and plant layers
5991       nzu = nzut - nzub + 1
5992       nzp = nzpt - nzub + 1
5993!
5994!--    check max_raytracing_dist relative to urban surface layer height
5995       mrl = 2.0_wp * nzu * dz(1)
5996!--    set max_raytracing_dist to double the urban surface layer height, if not set
5997       IF ( max_raytracing_dist == -999.0_wp ) THEN
5998          max_raytracing_dist = mrl
5999       ENDIF
6000!--    check if max_raytracing_dist set too low (here we only warn the user. Other
6001!      option is to correct the value again to double the urban surface layer height)
6002       IF ( max_raytracing_dist  <  mrl ) THEN
6003          WRITE(message_string, '(a,f6.1)') 'Max_raytracing_dist is set less than ', &
6004               'double the urban surface layer height, i.e. ', mrl
6005          CALL message('radiation_interaction_init', 'PA0521', 0, 0, -1, 6, 0)
6006       ENDIF
6007!        IF ( max_raytracing_dist <= mrl ) THEN
6008!           IF ( max_raytracing_dist /= -999.0_wp ) THEN
6009! !--          max_raytracing_dist too low
6010!              WRITE(message_string, '(a,f6.1)') 'Max_raytracing_dist too low, ' &
6011!                    // 'override to value ', mrl
6012!              CALL message('radiation_interaction_init', 'PA0521', 0, 0, -1, 6, 0)
6013!           ENDIF
6014!           max_raytracing_dist = mrl
6015!        ENDIF
6016!
6017!--    allocate urban surfaces grid
6018!--    calc number of surfaces in local proc
6019       CALL location_message( '    calculation of indices for surfaces', .TRUE. )
6020       nsurfl = 0
6021!
6022!--    Number of horizontal surfaces including land- and roof surfaces in both USM and LSM. Note that
6023!--    All horizontal surface elements are already counted in surface_mod.
6024       startland = 1
6025       nsurfl    = surf_usm_h%ns + surf_lsm_h%ns
6026       endland   = nsurfl
6027       nlands    = endland - startland + 1
6028
6029!
6030!--    Number of vertical surfaces in both USM and LSM. Note that all vertical surface elements are
6031!--    already counted in surface_mod.
6032       startwall = nsurfl+1
6033       DO  i = 0,3
6034          nsurfl = nsurfl + surf_usm_v(i)%ns + surf_lsm_v(i)%ns
6035       ENDDO
6036       endwall = nsurfl
6037       nwalls  = endwall - startwall + 1
6038       dirstart = (/ startland, startwall, startwall, startwall, startwall /)
6039       dirend = (/ endland, endwall, endwall, endwall, endwall /)
6040
6041!--    fill gridpcbl and pcbl
6042       IF ( npcbl > 0 )  THEN
6043           ALLOCATE( pcbl(iz:ix, 1:npcbl) )
6044           ALLOCATE( gridpcbl(nzub:nzpt,nys:nyn,nxl:nxr) )
6045           pcbl = -1
6046           gridpcbl(:,:,:) = 0
6047           ipcgb = 0
6048           DO i = nxl, nxr
6049               DO j = nys, nyn
6050!
6051!--                Find topography top index
6052                   k_topo = get_topography_top_index_ji( j, i, 's' )
6053
6054                   DO k = k_topo + 1, pct(j,i)
6055                       ipcgb = ipcgb + 1
6056                       gridpcbl(k,j,i) = ipcgb
6057                       pcbl(:,ipcgb) = (/ k, j, i /)
6058                   ENDDO
6059               ENDDO
6060           ENDDO
6061           ALLOCATE( pcbinsw( 1:npcbl ) )
6062           ALLOCATE( pcbinswdir( 1:npcbl ) )
6063           ALLOCATE( pcbinswdif( 1:npcbl ) )
6064           ALLOCATE( pcbinlw( 1:npcbl ) )
6065       ENDIF
6066
6067!--    fill surfl (the ordering of local surfaces given by the following
6068!--    cycles must not be altered, certain file input routines may depend
6069!--    on it)
6070       ALLOCATE(surfl_l(5*nsurfl))  ! is it necessary to allocate it with (5,nsurfl)?
6071       surfl(1:5,1:nsurfl) => surfl_l(1:5*nsurfl)
6072       isurf = 0
6073       IF ( rad_angular_discretization )  THEN
6074!
6075!--       Allocate and fill the reverse indexing array gridsurf
6076#if defined( __parallel )
6077!
6078!--       raytrace_mpi_rma is asserted
6079
6080          CALL MPI_Info_create(minfo, ierr)
6081          IF ( ierr /= 0 ) THEN
6082              WRITE(9,*) 'Error MPI_Info_create1:', ierr
6083              FLUSH(9)
6084          ENDIF
6085          CALL MPI_Info_set(minfo, 'accumulate_ordering', '', ierr)
6086          IF ( ierr /= 0 ) THEN
6087              WRITE(9,*) 'Error MPI_Info_set1:', ierr
6088              FLUSH(9)
6089          ENDIF
6090          CALL MPI_Info_set(minfo, 'accumulate_ops', 'same_op', ierr)
6091          IF ( ierr /= 0 ) THEN
6092              WRITE(9,*) 'Error MPI_Info_set2:', ierr
6093              FLUSH(9)
6094          ENDIF
6095          CALL MPI_Info_set(minfo, 'same_size', 'true', ierr)
6096          IF ( ierr /= 0 ) THEN
6097              WRITE(9,*) 'Error MPI_Info_set3:', ierr
6098              FLUSH(9)
6099          ENDIF
6100          CALL MPI_Info_set(minfo, 'same_disp_unit', 'true', ierr)
6101          IF ( ierr /= 0 ) THEN
6102              WRITE(9,*) 'Error MPI_Info_set4:', ierr
6103              FLUSH(9)
6104          ENDIF
6105
6106          CALL MPI_Win_allocate(INT(STORAGE_SIZE(1_iwp)/8*nsurf_type_u*nzu*nny*nnx, &
6107                                    kind=MPI_ADDRESS_KIND), STORAGE_SIZE(1_iwp)/8,  &
6108                                minfo, comm2d, gridsurf_rma_p, win_gridsurf, ierr)
6109          IF ( ierr /= 0 ) THEN
6110              WRITE(9,*) 'Error MPI_Win_allocate1:', ierr, &
6111                 INT(STORAGE_SIZE(1_iwp)/8*nsurf_type_u*nzu*nny*nnx,kind=MPI_ADDRESS_KIND), &
6112                 STORAGE_SIZE(1_iwp)/8, win_gridsurf
6113              FLUSH(9)
6114          ENDIF
6115
6116          CALL MPI_Info_free(minfo, ierr)
6117          IF ( ierr /= 0 ) THEN
6118              WRITE(9,*) 'Error MPI_Info_free1:', ierr
6119              FLUSH(9)
6120          ENDIF
6121
6122!
6123!--       On Intel compilers, calling c_f_pointer to transform a C pointer
6124!--       directly to a multi-dimensional Fotran pointer leads to strange
6125!--       errors on dimension boundaries. However, transforming to a 1D
6126!--       pointer and then redirecting a multidimensional pointer to it works
6127!--       fine.
6128          CALL c_f_pointer(gridsurf_rma_p, gridsurf_rma, (/ nsurf_type_u*nzu*nny*nnx /))
6129          gridsurf(0:nsurf_type_u-1, nzub:nzut, nys:nyn, nxl:nxr) =>                &
6130                     gridsurf_rma(1:nsurf_type_u*nzu*nny*nnx)
6131#else
6132          ALLOCATE(gridsurf(0:nsurf_type_u-1,nzub:nzut,nys:nyn,nxl:nxr) )
6133#endif
6134          gridsurf(:,:,:,:) = -999
6135       ENDIF
6136
6137!--    add horizontal surface elements (land and urban surfaces)
6138!--    TODO: add urban overhanging surfaces (idown_u)
6139       DO i = nxl, nxr
6140           DO j = nys, nyn
6141              DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
6142                 k = surf_usm_h%k(m)
6143                 isurf = isurf + 1
6144                 surfl(:,isurf) = (/iup_u,k,j,i,m/)
6145                 IF ( rad_angular_discretization ) THEN
6146                    gridsurf(iup_u,k,j,i) = isurf
6147                 ENDIF
6148              ENDDO
6149
6150              DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6151                 k = surf_lsm_h%k(m)
6152                 isurf = isurf + 1
6153                 surfl(:,isurf) = (/iup_l,k,j,i,m/)
6154                 IF ( rad_angular_discretization ) THEN
6155                    gridsurf(iup_u,k,j,i) = isurf
6156                 ENDIF
6157              ENDDO
6158
6159           ENDDO
6160       ENDDO
6161
6162!--    add vertical surface elements (land and urban surfaces)
6163!--    TODO: remove the hard coding of l = 0 to l = idirection
6164       DO i = nxl, nxr
6165           DO j = nys, nyn
6166              l = 0
6167              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6168                 k = surf_usm_v(l)%k(m)
6169                 isurf = isurf + 1
6170                 surfl(:,isurf) = (/inorth_u,k,j,i,m/)
6171                 IF ( rad_angular_discretization ) THEN
6172                    gridsurf(inorth_u,k,j,i) = isurf
6173                 ENDIF
6174              ENDDO
6175              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6176                 k = surf_lsm_v(l)%k(m)
6177                 isurf = isurf + 1
6178                 surfl(:,isurf) = (/inorth_l,k,j,i,m/)
6179                 IF ( rad_angular_discretization ) THEN
6180                    gridsurf(inorth_u,k,j,i) = isurf
6181                 ENDIF
6182              ENDDO
6183
6184              l = 1
6185              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6186                 k = surf_usm_v(l)%k(m)
6187                 isurf = isurf + 1
6188                 surfl(:,isurf) = (/isouth_u,k,j,i,m/)
6189                 IF ( rad_angular_discretization ) THEN
6190                    gridsurf(isouth_u,k,j,i) = isurf
6191                 ENDIF
6192              ENDDO
6193              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6194                 k = surf_lsm_v(l)%k(m)
6195                 isurf = isurf + 1
6196                 surfl(:,isurf) = (/isouth_l,k,j,i,m/)
6197                 IF ( rad_angular_discretization ) THEN
6198                    gridsurf(isouth_u,k,j,i) = isurf
6199                 ENDIF
6200              ENDDO
6201
6202              l = 2
6203              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6204                 k = surf_usm_v(l)%k(m)
6205                 isurf = isurf + 1
6206                 surfl(:,isurf) = (/ieast_u,k,j,i,m/)
6207                 IF ( rad_angular_discretization ) THEN
6208                    gridsurf(ieast_u,k,j,i) = isurf
6209                 ENDIF
6210              ENDDO
6211              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6212                 k = surf_lsm_v(l)%k(m)
6213                 isurf = isurf + 1
6214                 surfl(:,isurf) = (/ieast_l,k,j,i,m/)
6215                 IF ( rad_angular_discretization ) THEN
6216                    gridsurf(ieast_u,k,j,i) = isurf
6217                 ENDIF
6218              ENDDO
6219
6220              l = 3
6221              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6222                 k = surf_usm_v(l)%k(m)
6223                 isurf = isurf + 1
6224                 surfl(:,isurf) = (/iwest_u,k,j,i,m/)
6225                 IF ( rad_angular_discretization ) THEN
6226                    gridsurf(iwest_u,k,j,i) = isurf
6227                 ENDIF
6228              ENDDO
6229              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6230                 k = surf_lsm_v(l)%k(m)
6231                 isurf = isurf + 1
6232                 surfl(:,isurf) = (/iwest_l,k,j,i,m/)
6233                 IF ( rad_angular_discretization ) THEN
6234                    gridsurf(iwest_u,k,j,i) = isurf
6235                 ENDIF
6236              ENDDO
6237           ENDDO
6238       ENDDO
6239!
6240!--    Add local MRT boxes for specified number of levels
6241       nmrtbl = 0
6242       IF ( mrt_nlevels > 0 )  THEN
6243          DO  i = nxl, nxr
6244             DO  j = nys, nyn
6245                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
6246!
6247!--                Skip roof if requested
6248                   IF ( mrt_skip_roof  .AND.  surf_usm_h%isroof_surf(m) )  CYCLE
6249!
6250!--                Cycle over specified no of levels
6251                   nmrtbl = nmrtbl + mrt_nlevels
6252                ENDDO
6253!
6254!--             Dtto for LSM
6255                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6256                   nmrtbl = nmrtbl + mrt_nlevels
6257                ENDDO
6258             ENDDO
6259          ENDDO
6260
6261          ALLOCATE( mrtbl(iz:ix,nmrtbl), mrtsky(nmrtbl), mrtskyt(nmrtbl), &
6262                    mrtinsw(nmrtbl), mrtinlw(nmrtbl), mrt(nmrtbl) )
6263
6264          imrt = 0
6265          DO  i = nxl, nxr
6266             DO  j = nys, nyn
6267                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
6268!
6269!--                Skip roof if requested
6270                   IF ( mrt_skip_roof  .AND.  surf_usm_h%isroof_surf(m) )  CYCLE
6271!
6272!--                Cycle over specified no of levels
6273                   l = surf_usm_h%k(m)
6274                   DO  k = l, l + mrt_nlevels - 1
6275                      imrt = imrt + 1
6276                      mrtbl(:,imrt) = (/k,j,i/)
6277                   ENDDO
6278                ENDDO
6279!
6280!--             Dtto for LSM
6281                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6282                   l = surf_lsm_h%k(m)
6283                   DO  k = l, l + mrt_nlevels - 1
6284                      imrt = imrt + 1
6285                      mrtbl(:,imrt) = (/k,j,i/)
6286                   ENDDO
6287                ENDDO
6288             ENDDO
6289          ENDDO
6290       ENDIF
6291
6292!
6293!--    broadband albedo of the land, roof and wall surface
6294!--    for domain border and sky set artifically to 1.0
6295!--    what allows us to calculate heat flux leaving over
6296!--    side and top borders of the domain
6297       ALLOCATE ( albedo_surf(nsurfl) )
6298       albedo_surf = 1.0_wp
6299!
6300!--    Also allocate further array for emissivity with identical order of
6301!--    surface elements as radiation arrays.
6302       ALLOCATE ( emiss_surf(nsurfl)  )
6303
6304
6305!
6306!--    global array surf of indices of surfaces and displacement index array surfstart
6307       ALLOCATE(nsurfs(0:numprocs-1))
6308
6309#if defined( __parallel )
6310       CALL MPI_Allgather(nsurfl,1,MPI_INTEGER,nsurfs,1,MPI_INTEGER,comm2d,ierr)
6311       IF ( ierr /= 0 ) THEN
6312         WRITE(9,*) 'Error MPI_AllGather1:', ierr, nsurfl, nsurfs
6313         FLUSH(9)
6314     ENDIF
6315
6316#else
6317       nsurfs(0) = nsurfl
6318#endif
6319       ALLOCATE(surfstart(0:numprocs))
6320       k = 0
6321       DO i=0,numprocs-1
6322           surfstart(i) = k
6323           k = k+nsurfs(i)
6324       ENDDO
6325       surfstart(numprocs) = k
6326       nsurf = k
6327       ALLOCATE(surf_l(5*nsurf))
6328       surf(1:5,1:nsurf) => surf_l(1:5*nsurf)
6329
6330#if defined( __parallel )
6331       CALL MPI_AllGatherv(surfl_l, nsurfl*5, MPI_INTEGER, surf_l, nsurfs*5, &
6332           surfstart(0:numprocs-1)*5, MPI_INTEGER, comm2d, ierr)
6333       IF ( ierr /= 0 ) THEN
6334           WRITE(9,*) 'Error MPI_AllGatherv4:', ierr, SIZE(surfl_l), nsurfl*5, &
6335                      SIZE(surf_l), nsurfs*5, surfstart(0:numprocs-1)*5
6336           FLUSH(9)
6337       ENDIF
6338#else
6339       surf = surfl
6340#endif
6341
6342!--
6343!--    allocation of the arrays for direct and diffusion radiation
6344       CALL location_message( '    allocation of radiation arrays', .TRUE. )
6345!--    rad_sw_in, rad_lw_in are computed in radiation model,
6346!--    splitting of direct and diffusion part is done
6347!--    in calc_diffusion_radiation for now
6348
6349       ALLOCATE( rad_sw_in_dir(nysg:nyng,nxlg:nxrg) )
6350       ALLOCATE( rad_sw_in_diff(nysg:nyng,nxlg:nxrg) )
6351       ALLOCATE( rad_lw_in_diff(nysg:nyng,nxlg:nxrg) )
6352       rad_sw_in_dir  = 0.0_wp
6353       rad_sw_in_diff = 0.0_wp
6354       rad_lw_in_diff = 0.0_wp
6355
6356!--    allocate radiation arrays
6357       ALLOCATE( surfins(nsurfl) )
6358       ALLOCATE( surfinl(nsurfl) )
6359       ALLOCATE( surfinsw(nsurfl) )
6360       ALLOCATE( surfinlw(nsurfl) )
6361       ALLOCATE( surfinswdir(nsurfl) )
6362       ALLOCATE( surfinswdif(nsurfl) )
6363       ALLOCATE( surfinlwdif(nsurfl) )
6364       ALLOCATE( surfoutsl(nsurfl) )
6365       ALLOCATE( surfoutll(nsurfl) )
6366       ALLOCATE( surfoutsw(nsurfl) )
6367       ALLOCATE( surfoutlw(nsurfl) )
6368       ALLOCATE( surfouts(nsurf) )
6369       ALLOCATE( surfoutl(nsurf) )
6370       ALLOCATE( surfinlg(nsurf) )
6371       ALLOCATE( skyvf(nsurfl) )
6372       ALLOCATE( skyvft(nsurfl) )
6373       ALLOCATE( surfemitlwl(nsurfl) )
6374
6375!
6376!--    In case of average_radiation, aggregated surface albedo and emissivity,
6377!--    also set initial value for t_rad_urb.
6378!--    For now set an arbitrary initial value.
6379       IF ( average_radiation )  THEN
6380          albedo_urb = 0.1_wp
6381          emissivity_urb = 0.9_wp
6382          t_rad_urb = pt_surface
6383       ENDIF
6384
6385    END SUBROUTINE radiation_interaction_init
6386
6387!------------------------------------------------------------------------------!
6388! Description:
6389! ------------
6390!> Calculates shape view factors (SVF), plant sink canopy factors (PCSF),
6391!> sky-view factors, discretized path for direct solar radiation, MRT factors
6392!> and other preprocessed data needed for radiation_interaction.
6393!------------------------------------------------------------------------------!
6394    SUBROUTINE radiation_calc_svf
6395   
6396        IMPLICIT NONE
6397       
6398        INTEGER(iwp)                                  :: i, j, k, d, ip, jp
6399        INTEGER(iwp)                                  :: isvf, ksvf, icsf, kcsf, npcsfl, isvf_surflt, imrt, imrtf, ipcgb
6400        INTEGER(iwp)                                  :: sd, td
6401        INTEGER(iwp)                                  :: iaz, izn      !< azimuth, zenith counters
6402        INTEGER(iwp)                                  :: naz, nzn      !< azimuth, zenith num of steps
6403        REAL(wp)                                      :: az0, zn0      !< starting azimuth/zenith
6404        REAL(wp)                                      :: azs, zns      !< azimuth/zenith cycle step
6405        REAL(wp)                                      :: az1, az2      !< relative azimuth of section borders
6406        REAL(wp)                                      :: azmid         !< ray (center) azimuth
6407        REAL(wp)                                      :: yxlen         !< |yxdir|
6408        REAL(wp), DIMENSION(2)                        :: yxdir         !< y,x *unit* vector of ray direction (in grid units)
6409        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zdirs         !< directions in z (tangent of elevation)
6410        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zcent         !< zenith angle centers
6411        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zbdry         !< zenith angle boundaries
6412        REAL(wp), DIMENSION(:), ALLOCATABLE           :: vffrac        !< view factor fractions for individual rays
6413        REAL(wp), DIMENSION(:), ALLOCATABLE           :: vffrac0       !< dtto (original values)
6414        REAL(wp), DIMENSION(:), ALLOCATABLE           :: ztransp       !< array of transparency in z steps
6415        INTEGER(iwp)                                  :: lowest_free_ray !< index into zdirs
6416        INTEGER(iwp), DIMENSION(:), ALLOCATABLE       :: itarget       !< face indices of detected obstacles
6417        INTEGER(iwp)                                  :: itarg0, itarg1
6418
6419        INTEGER(iwp)                                  :: udim
6420        INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET:: nzterrl_l
6421        INTEGER(iwp), DIMENSION(:,:), POINTER         :: nzterrl
6422        REAL(wp),     DIMENSION(:), ALLOCATABLE,TARGET:: csflt_l, pcsflt_l
6423        REAL(wp),     DIMENSION(:,:), POINTER         :: csflt, pcsflt
6424        INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET:: kcsflt_l,kpcsflt_l
6425        INTEGER(iwp), DIMENSION(:,:), POINTER         :: kcsflt,kpcsflt
6426        INTEGER(iwp), DIMENSION(:), ALLOCATABLE       :: icsflt,dcsflt,ipcsflt,dpcsflt
6427        REAL(wp), DIMENSION(3)                        :: uv
6428        LOGICAL                                       :: visible
6429        REAL(wp), DIMENSION(3)                        :: sa, ta          !< real coordinates z,y,x of source and target
6430        REAL(wp)                                      :: difvf           !< differential view factor
6431        REAL(wp)                                      :: transparency, rirrf, sqdist, svfsum
6432        INTEGER(iwp)                                  :: isurflt, isurfs, isurflt_prev
6433        INTEGER(idp)                                  :: ray_skip_maxdist, ray_skip_minval !< skipped raytracing counts
6434        INTEGER(iwp)                                  :: max_track_len !< maximum 2d track length
6435        INTEGER(iwp)                                  :: minfo
6436        REAL(wp), DIMENSION(:), POINTER               :: lad_s_rma       !< fortran 1D pointer
6437        TYPE(c_ptr)                                   :: lad_s_rma_p     !< allocated c pointer
6438#if defined( __parallel )
6439        INTEGER(kind=MPI_ADDRESS_KIND)                :: size_lad_rma
6440#endif
6441!   
6442        INTEGER(iwp), DIMENSION(0:svfnorm_report_num) :: svfnorm_counts
6443        CHARACTER(200)                                :: msg
6444
6445!--     calculation of the SVF
6446        CALL location_message( '    calculation of SVF and CSF', .TRUE. )
6447        CALL radiation_write_debug_log('Start calculation of SVF and CSF')
6448
6449!--     initialize variables and temporary arrays for calculation of svf and csf
6450        nsvfl  = 0
6451        ncsfl  = 0
6452        nsvfla = gasize
6453        msvf   = 1
6454        ALLOCATE( asvf1(nsvfla) )
6455        asvf => asvf1
6456        IF ( plant_canopy )  THEN
6457            ncsfla = gasize
6458            mcsf   = 1
6459            ALLOCATE( acsf1(ncsfla) )
6460            acsf => acsf1
6461        ENDIF
6462        nmrtf = 0
6463        IF ( mrt_nlevels > 0 )  THEN
6464           nmrtfa = gasize
6465           mmrtf = 1
6466           ALLOCATE ( amrtf1(nmrtfa) )
6467           amrtf => amrtf1
6468        ENDIF
6469        ray_skip_maxdist = 0
6470        ray_skip_minval = 0
6471       
6472!--     initialize temporary terrain and plant canopy height arrays (global 2D array!)
6473        ALLOCATE( nzterr(0:(nx+1)*(ny+1)-1) )
6474#if defined( __parallel )
6475        !ALLOCATE( nzterrl(nys:nyn,nxl:nxr) )
6476        ALLOCATE( nzterrl_l((nyn-nys+1)*(nxr-nxl+1)) )
6477        nzterrl(nys:nyn,nxl:nxr) => nzterrl_l(1:(nyn-nys+1)*(nxr-nxl+1))
6478        nzterrl = get_topography_top_index( 's' )
6479        CALL MPI_AllGather( nzterrl_l, nnx*nny, MPI_INTEGER, &
6480                            nzterr, nnx*nny, MPI_INTEGER, comm2d, ierr )
6481        IF ( ierr /= 0 ) THEN
6482            WRITE(9,*) 'Error MPI_AllGather1:', ierr, SIZE(nzterrl_l), nnx*nny, &
6483                       SIZE(nzterr), nnx*nny
6484            FLUSH(9)
6485        ENDIF
6486        DEALLOCATE(nzterrl_l)
6487#else
6488        nzterr = RESHAPE( get_topography_top_index( 's' ), (/(nx+1)*(ny+1)/) )
6489#endif
6490        IF ( plant_canopy )  THEN
6491            ALLOCATE( plantt(0:(nx+1)*(ny+1)-1) )
6492            maxboxesg = nx + ny + nzp + 1
6493            max_track_len = nx + ny + 1
6494!--         temporary arrays storing values for csf calculation during raytracing
6495            ALLOCATE( boxes(3, maxboxesg) )
6496            ALLOCATE( crlens(maxboxesg) )
6497
6498#if defined( __parallel )
6499            CALL MPI_AllGather( pct, nnx*nny, MPI_INTEGER, &
6500                                plantt, nnx*nny, MPI_INTEGER, comm2d, ierr )
6501            IF ( ierr /= 0 ) THEN
6502                WRITE(9,*) 'Error MPI_AllGather2:', ierr, SIZE(pct), nnx*nny, &
6503                           SIZE(plantt), nnx*nny
6504                FLUSH(9)
6505            ENDIF
6506
6507!--         temporary arrays storing values for csf calculation during raytracing
6508            ALLOCATE( lad_ip(maxboxesg) )
6509            ALLOCATE( lad_disp(maxboxesg) )
6510
6511            IF ( raytrace_mpi_rma )  THEN
6512                ALLOCATE( lad_s_ray(maxboxesg) )
6513               
6514                ! set conditions for RMA communication
6515                CALL MPI_Info_create(minfo, ierr)
6516                IF ( ierr /= 0 ) THEN
6517                    WRITE(9,*) 'Error MPI_Info_create2:', ierr
6518                    FLUSH(9)
6519                ENDIF
6520                CALL MPI_Info_set(minfo, 'accumulate_ordering', '', ierr)
6521                IF ( ierr /= 0 ) THEN
6522                    WRITE(9,*) 'Error MPI_Info_set5:', ierr
6523                    FLUSH(9)
6524                ENDIF
6525                CALL MPI_Info_set(minfo, 'accumulate_ops', 'same_op', ierr)
6526                IF ( ierr /= 0 ) THEN
6527                    WRITE(9,*) 'Error MPI_Info_set6:', ierr
6528                    FLUSH(9)
6529                ENDIF
6530                CALL MPI_Info_set(minfo, 'same_size', 'true', ierr)
6531                IF ( ierr /= 0 ) THEN
6532                    WRITE(9,*) 'Error MPI_Info_set7:', ierr
6533                    FLUSH(9)
6534                ENDIF
6535                CALL MPI_Info_set(minfo, 'same_disp_unit', 'true', ierr)
6536                IF ( ierr /= 0 ) THEN
6537                    WRITE(9,*) 'Error MPI_Info_set8:', ierr
6538                    FLUSH(9)
6539                ENDIF
6540
6541!--             Allocate and initialize the MPI RMA window
6542!--             must be in accordance with allocation of lad_s in plant_canopy_model
6543!--             optimization of memory should be done
6544!--             Argument X of function STORAGE_SIZE(X) needs arbitrary REAL(wp) value, set to 1.0_wp for now
6545                size_lad_rma = STORAGE_SIZE(1.0_wp)/8*nnx*nny*nzp
6546                CALL MPI_Win_allocate(size_lad_rma, STORAGE_SIZE(1.0_wp)/8, minfo, comm2d, &
6547                                        lad_s_rma_p, win_lad, ierr)
6548                IF ( ierr /= 0 ) THEN
6549                    WRITE(9,*) 'Error MPI_Win_allocate2:', ierr, size_lad_rma, &
6550                                STORAGE_SIZE(1.0_wp)/8, win_lad
6551                    FLUSH(9)
6552                ENDIF
6553                CALL c_f_pointer(lad_s_rma_p, lad_s_rma, (/ nzp*nny*nnx /))
6554                sub_lad(nzub:nzpt, nys:nyn, nxl:nxr) => lad_s_rma(1:nzp*nny*nnx)
6555            ELSE
6556                ALLOCATE(sub_lad(nzub:nzpt, nys:nyn, nxl:nxr))
6557            ENDIF
6558#else
6559            plantt = RESHAPE( pct(nys:nyn,nxl:nxr), (/(nx+1)*(ny+1)/) )
6560            ALLOCATE(sub_lad(nzub:nzpt, nys:nyn, nxl:nxr))
6561#endif
6562            plantt_max = MAXVAL(plantt)
6563            ALLOCATE( rt2_track(2, max_track_len), rt2_track_lad(nzub:plantt_max, max_track_len), &
6564                      rt2_track_dist(0:max_track_len), rt2_dist(plantt_max-nzub+2) )
6565
6566            sub_lad(:,:,:) = 0._wp
6567            DO i = nxl, nxr
6568                DO j = nys, nyn
6569                    k = get_topography_top_index_ji( j, i, 's' )
6570
6571                    sub_lad(k:nzpt, j, i) = lad_s(0:nzpt-k, j, i)
6572                ENDDO
6573            ENDDO
6574
6575#if defined( __parallel )
6576            IF ( raytrace_mpi_rma )  THEN
6577                CALL MPI_Info_free(minfo, ierr)
6578                IF ( ierr /= 0 ) THEN
6579                    WRITE(9,*) 'Error MPI_Info_free2:', ierr
6580                    FLUSH(9)
6581                ENDIF
6582                CALL MPI_Win_lock_all(0, win_lad, ierr)
6583                IF ( ierr /= 0 ) THEN
6584                    WRITE(9,*) 'Error MPI_Win_lock_all1:', ierr, win_lad
6585                    FLUSH(9)
6586                ENDIF
6587               
6588            ELSE
6589                ALLOCATE( sub_lad_g(0:(nx+1)*(ny+1)*nzp-1) )
6590                CALL MPI_AllGather( sub_lad, nnx*nny*nzp, MPI_REAL, &
6591                                    sub_lad_g, nnx*nny*nzp, MPI_REAL, comm2d, ierr )
6592                IF ( ierr /= 0 ) THEN
6593                    WRITE(9,*) 'Error MPI_AllGather3:', ierr, SIZE(sub_lad), &
6594                                nnx*nny*nzp, SIZE(sub_lad_g), nnx*nny*nzp
6595                    FLUSH(9)
6596                ENDIF
6597            ENDIF
6598#endif
6599        ENDIF
6600
6601!--     prepare the MPI_Win for collecting the surface indices
6602!--     from the reverse index arrays gridsurf from processors of target surfaces
6603#if defined( __parallel )
6604        IF ( rad_angular_discretization )  THEN
6605!
6606!--         raytrace_mpi_rma is asserted
6607            CALL MPI_Win_lock_all(0, win_gridsurf, ierr)
6608            IF ( ierr /= 0 ) THEN
6609                WRITE(9,*) 'Error MPI_Win_lock_all2:', ierr, win_gridsurf
6610                FLUSH(9)
6611            ENDIF
6612        ENDIF
6613#endif
6614
6615
6616        !--Directions opposite to face normals are not even calculated,
6617        !--they must be preset to 0
6618        !--
6619        dsitrans(:,:) = 0._wp
6620       
6621        DO isurflt = 1, nsurfl
6622!--         determine face centers
6623            td = surfl(id, isurflt)
6624            ta = (/ REAL(surfl(iz, isurflt), wp) - 0.5_wp * kdir(td),  &
6625                      REAL(surfl(iy, isurflt), wp) - 0.5_wp * jdir(td),  &
6626                      REAL(surfl(ix, isurflt), wp) - 0.5_wp * idir(td)  /)
6627
6628            !--Calculate sky view factor and raytrace DSI paths
6629            skyvf(isurflt) = 0._wp
6630            skyvft(isurflt) = 0._wp
6631
6632            !--Select a proper half-sphere for 2D raytracing
6633            SELECT CASE ( td )
6634               CASE ( iup_u, iup_l )
6635                  az0 = 0._wp
6636                  naz = raytrace_discrete_azims
6637                  azs = 2._wp * pi / REAL(naz, wp)
6638                  zn0 = 0._wp
6639                  nzn = raytrace_discrete_elevs / 2
6640                  zns = pi / 2._wp / REAL(nzn, wp)
6641               CASE ( isouth_u, isouth_l )
6642                  az0 = pi / 2._wp
6643                  naz = raytrace_discrete_azims / 2
6644                  azs = pi / REAL(naz, wp)
6645                  zn0 = 0._wp
6646                  nzn = raytrace_discrete_elevs
6647                  zns = pi / REAL(nzn, wp)
6648               CASE ( inorth_u, inorth_l )
6649                  az0 = - pi / 2._wp
6650                  naz = raytrace_discrete_azims / 2
6651                  azs = pi / REAL(naz, wp)
6652                  zn0 = 0._wp
6653                  nzn = raytrace_discrete_elevs
6654                  zns = pi / REAL(nzn, wp)
6655               CASE ( iwest_u, iwest_l )
6656                  az0 = pi
6657                  naz = raytrace_discrete_azims / 2
6658                  azs = pi / REAL(naz, wp)
6659                  zn0 = 0._wp
6660                  nzn = raytrace_discrete_elevs
6661                  zns = pi / REAL(nzn, wp)
6662               CASE ( ieast_u, ieast_l )
6663                  az0 = 0._wp
6664                  naz = raytrace_discrete_azims / 2
6665                  azs = pi / REAL(naz, wp)
6666                  zn0 = 0._wp
6667                  nzn = raytrace_discrete_elevs
6668                  zns = pi / REAL(nzn, wp)
6669               CASE DEFAULT
6670                  WRITE(message_string, *) 'ERROR: the surface type ', td,     &
6671                                           ' is not supported for calculating',&
6672                                           ' SVF'
6673                  CALL message( 'radiation_calc_svf', 'PA0488', 1, 2, 0, 6, 0 )
6674            END SELECT
6675
6676            ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), zbdry(0:nzn), vffrac(1:nzn*naz), &
6677                       ztransp(1:nzn*naz), itarget(1:nzn*naz) )   !FIXME allocate itarget only
6678                                                                  !in case of rad_angular_discretization
6679
6680            itarg0 = 1
6681            itarg1 = nzn
6682            zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
6683            zbdry(:) = (/( zn0+REAL(izn,wp)*zns, izn=0, nzn )/)
6684            IF ( td == iup_u  .OR.  td == iup_l )  THEN
6685               vffrac(1:nzn) = (COS(2 * zbdry(0:nzn-1)) - COS(2 * zbdry(1:nzn))) / 2._wp / REAL(naz, wp)
6686!
6687!--            For horizontal target, vf fractions are constant per azimuth
6688               DO iaz = 1, naz-1
6689                  vffrac(iaz*nzn+1:(iaz+1)*nzn) = vffrac(1:nzn)
6690               ENDDO
6691!--            sum of whole vffrac equals 1, verified
6692            ENDIF
6693!
6694!--         Calculate sky-view factor and direct solar visibility using 2D raytracing
6695            DO iaz = 1, naz
6696               azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
6697               IF ( td /= iup_u  .AND.  td /= iup_l )  THEN
6698                  az2 = REAL(iaz, wp) * azs - pi/2._wp
6699                  az1 = az2 - azs
6700                  !TODO precalculate after 1st line
6701                  vffrac(itarg0:itarg1) = (SIN(az2) - SIN(az1))               &
6702                              * (zbdry(1:nzn) - zbdry(0:nzn-1)                &
6703                                 + SIN(zbdry(0:nzn-1))*COS(zbdry(0:nzn-1))    &
6704                                 - SIN(zbdry(1:nzn))*COS(zbdry(1:nzn)))       &
6705                              / (2._wp * pi)
6706!--               sum of whole vffrac equals 1, verified
6707               ENDIF
6708               yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
6709               yxlen = SQRT(SUM(yxdir(:)**2))
6710               zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
6711               yxdir(:) = yxdir(:) / yxlen
6712
6713               CALL raytrace_2d(ta, yxdir, nzn, zdirs,                        &
6714                                    surfstart(myid) + isurflt, facearea(td),  &
6715                                    vffrac(itarg0:itarg1), .TRUE., .TRUE.,    &
6716                                    .FALSE., lowest_free_ray,                 &
6717                                    ztransp(itarg0:itarg1),                   &
6718                                    itarget(itarg0:itarg1))
6719
6720               skyvf(isurflt) = skyvf(isurflt) + &
6721                                SUM(vffrac(itarg0:itarg0+lowest_free_ray-1))
6722               skyvft(isurflt) = skyvft(isurflt) + &
6723                                 SUM(ztransp(itarg0:itarg0+lowest_free_ray-1) &
6724                                             * vffrac(itarg0:itarg0+lowest_free_ray-1))
6725 
6726!--            Save direct solar transparency
6727               j = MODULO(NINT(azmid/                                          &
6728                               (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
6729                          raytrace_discrete_azims)
6730
6731               DO k = 1, raytrace_discrete_elevs/2
6732                  i = dsidir_rev(k-1, j)
6733                  IF ( i /= -1  .AND.  k <= lowest_free_ray )  &
6734                     dsitrans(isurflt, i) = ztransp(itarg0+k-1)
6735               ENDDO
6736
6737!
6738!--            Advance itarget indices
6739               itarg0 = itarg1 + 1
6740               itarg1 = itarg1 + nzn
6741            ENDDO
6742
6743            IF ( rad_angular_discretization )  THEN
6744!--            sort itarget by face id
6745               CALL quicksort_itarget(itarget,vffrac,ztransp,1,nzn*naz)
6746!
6747!--            find the first valid position
6748               itarg0 = 1
6749               DO WHILE ( itarg0 <= nzn*naz )
6750                  IF ( itarget(itarg0) /= -1 )  EXIT
6751                  itarg0 = itarg0 + 1
6752               ENDDO
6753
6754               DO  i = itarg0, nzn*naz
6755!
6756!--               For duplicate values, only sum up vf fraction value
6757                  IF ( i < nzn*naz )  THEN
6758                     IF ( itarget(i+1) == itarget(i) )  THEN
6759                        vffrac(i+1) = vffrac(i+1) + vffrac(i)
6760                        CYCLE
6761                     ENDIF
6762                  ENDIF
6763!
6764!--               write to the svf array
6765                  nsvfl = nsvfl + 1
6766!--               check dimmension of asvf array and enlarge it if needed
6767                  IF ( nsvfla < nsvfl )  THEN
6768                     k = CEILING(REAL(nsvfla, kind=wp) * grow_factor)
6769                     IF ( msvf == 0 )  THEN
6770                        msvf = 1
6771                        ALLOCATE( asvf1(k) )
6772                        asvf => asvf1
6773                        asvf1(1:nsvfla) = asvf2
6774                        DEALLOCATE( asvf2 )
6775                     ELSE
6776                        msvf = 0
6777                        ALLOCATE( asvf2(k) )
6778                        asvf => asvf2
6779                        asvf2(1:nsvfla) = asvf1
6780                        DEALLOCATE( asvf1 )
6781                     ENDIF
6782
6783                     WRITE (msg,'(A,3I12)') 'Grow asvf:',nsvfl,nsvfla,k
6784                     CALL radiation_write_debug_log( msg )
6785                     
6786                     nsvfla = k
6787                  ENDIF
6788!--               write svf values into the array
6789                  asvf(nsvfl)%isurflt = isurflt
6790                  asvf(nsvfl)%isurfs = itarget(i)
6791                  asvf(nsvfl)%rsvf = vffrac(i)
6792                  asvf(nsvfl)%rtransp = ztransp(i)
6793               END DO
6794
6795            ENDIF ! rad_angular_discretization
6796
6797            DEALLOCATE ( zdirs, zcent, zbdry, vffrac, ztransp, itarget ) !FIXME itarget shall be allocated only
6798                                                                  !in case of rad_angular_discretization
6799!
6800!--         Following calculations only required for surface_reflections
6801            IF ( surface_reflections  .AND.  .NOT. rad_angular_discretization )  THEN
6802
6803               DO  isurfs = 1, nsurf
6804                  IF ( .NOT.  surface_facing(surfl(ix, isurflt), surfl(iy, isurflt), &
6805                     surfl(iz, isurflt), surfl(id, isurflt), &
6806                     surf(ix, isurfs), surf(iy, isurfs), &
6807                     surf(iz, isurfs), surf(id, isurfs)) )  THEN
6808                     CYCLE
6809                  ENDIF
6810                 
6811                  sd = surf(id, isurfs)
6812                  sa = (/ REAL(surf(iz, isurfs), wp) - 0.5_wp * kdir(sd),  &
6813                          REAL(surf(iy, isurfs), wp) - 0.5_wp * jdir(sd),  &
6814                          REAL(surf(ix, isurfs), wp) - 0.5_wp * idir(sd)  /)
6815
6816!--               unit vector source -> target
6817                  uv = (/ (ta(1)-sa(1))*dz(1), (ta(2)-sa(2))*dy, (ta(3)-sa(3))*dx /)
6818                  sqdist = SUM(uv(:)**2)
6819                  uv = uv / SQRT(sqdist)
6820
6821!--               reject raytracing above max distance
6822                  IF ( SQRT(sqdist) > max_raytracing_dist ) THEN
6823                     ray_skip_maxdist = ray_skip_maxdist + 1
6824                     CYCLE
6825                  ENDIF
6826                 
6827                  difvf = dot_product((/ kdir(sd), jdir(sd), idir(sd) /), uv) & ! cosine of source normal and direction
6828                      * dot_product((/ kdir(td), jdir(td), idir(td) /), -uv) &  ! cosine of target normal and reverse direction
6829                      / (pi * sqdist) ! square of distance between centers
6830!
6831!--               irradiance factor (our unshaded shape view factor) = view factor per differential target area * source area
6832                  rirrf = difvf * facearea(sd)
6833
6834!--               reject raytracing for potentially too small view factor values
6835                  IF ( rirrf < min_irrf_value ) THEN
6836                      ray_skip_minval = ray_skip_minval + 1
6837                      CYCLE
6838                  ENDIF
6839
6840!--               raytrace + process plant canopy sinks within
6841                  CALL raytrace(sa, ta, isurfs, difvf, facearea(td), .TRUE., &
6842                                visible, transparency)
6843
6844                  IF ( .NOT.  visible ) CYCLE
6845                 ! rsvf = rirrf * transparency
6846
6847!--               write to the svf array
6848                  nsvfl = nsvfl + 1
6849!--               check dimmension of asvf array and enlarge it if needed
6850                  IF ( nsvfla < nsvfl )  THEN
6851                     k = CEILING(REAL(nsvfla, kind=wp) * grow_factor)
6852                     IF ( msvf == 0 )  THEN
6853                        msvf = 1
6854                        ALLOCATE( asvf1(k) )
6855                        asvf => asvf1
6856                        asvf1(1:nsvfla) = asvf2
6857                        DEALLOCATE( asvf2 )
6858                     ELSE
6859                        msvf = 0
6860                        ALLOCATE( asvf2(k) )
6861                        asvf => asvf2
6862                        asvf2(1:nsvfla) = asvf1
6863                        DEALLOCATE( asvf1 )
6864                     ENDIF
6865
6866                     WRITE(msg,'(A,3I12)') 'Grow asvf:',nsvfl,nsvfla,k
6867                     CALL radiation_write_debug_log( msg )
6868                     
6869                     nsvfla = k
6870                  ENDIF
6871!--               write svf values into the array
6872                  asvf(nsvfl)%isurflt = isurflt
6873                  asvf(nsvfl)%isurfs = isurfs
6874                  asvf(nsvfl)%rsvf = rirrf !we postopne multiplication by transparency
6875                  asvf(nsvfl)%rtransp = transparency !a.k.a. Direct Irradiance Factor
6876               ENDDO
6877            ENDIF
6878        ENDDO
6879
6880!--
6881!--     Raytrace to canopy boxes to fill dsitransc TODO optimize
6882        dsitransc(:,:) = 0._wp
6883        az0 = 0._wp
6884        naz = raytrace_discrete_azims
6885        azs = 2._wp * pi / REAL(naz, wp)
6886        zn0 = 0._wp
6887        nzn = raytrace_discrete_elevs / 2
6888        zns = pi / 2._wp / REAL(nzn, wp)
6889        ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), vffrac(1:nzn), ztransp(1:nzn), &
6890               itarget(1:nzn) )
6891        zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
6892        vffrac(:) = 0._wp
6893
6894        DO  ipcgb = 1, npcbl
6895           ta = (/ REAL(pcbl(iz, ipcgb), wp),  &
6896                   REAL(pcbl(iy, ipcgb), wp),  &
6897                   REAL(pcbl(ix, ipcgb), wp) /)
6898!--        Calculate direct solar visibility using 2D raytracing
6899           DO  iaz = 1, naz
6900              azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
6901              yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
6902              yxlen = SQRT(SUM(yxdir(:)**2))
6903              zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
6904              yxdir(:) = yxdir(:) / yxlen
6905              CALL raytrace_2d(ta, yxdir, nzn, zdirs,                                &
6906                                   -999, -999._wp, vffrac, .FALSE., .FALSE., .TRUE., &
6907                                   lowest_free_ray, ztransp, itarget)
6908
6909!--           Save direct solar transparency
6910              j = MODULO(NINT(azmid/                                         &
6911                             (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
6912                         raytrace_discrete_azims)
6913              DO  k = 1, raytrace_discrete_elevs/2
6914                 i = dsidir_rev(k-1, j)
6915                 IF ( i /= -1  .AND.  k <= lowest_free_ray ) &
6916                    dsitransc(ipcgb, i) = ztransp(k)
6917              ENDDO
6918           ENDDO
6919        ENDDO
6920        DEALLOCATE ( zdirs, zcent, vffrac, ztransp, itarget )
6921!--
6922!--     Raytrace to MRT boxes
6923        IF ( nmrtbl > 0 )  THEN
6924           mrtdsit(:,:) = 0._wp
6925           mrtsky(:) = 0._wp
6926           mrtskyt(:) = 0._wp
6927           az0 = 0._wp
6928           naz = raytrace_discrete_azims
6929           azs = 2._wp * pi / REAL(naz, wp)
6930           zn0 = 0._wp
6931           nzn = raytrace_discrete_elevs
6932           zns = pi / REAL(nzn, wp)
6933           ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), zbdry(0:nzn), vffrac(1:nzn*naz), vffrac0(1:nzn), &
6934                      ztransp(1:nzn*naz), itarget(1:nzn*naz) )   !FIXME allocate itarget only
6935                                                                 !in case of rad_angular_discretization
6936
6937           zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
6938           zbdry(:) = (/( zn0+REAL(izn,wp)*zns, izn=0, nzn )/)
6939           vffrac0(:) = (COS(zbdry(0:nzn-1)) - COS(zbdry(1:nzn))) / 2._wp / REAL(naz, wp)
6940           !
6941           !--Modify direction weights to simulate human body (lower weight for top-down)
6942           IF ( mrt_geom_human )  THEN
6943              vffrac0(:) = vffrac0(:) * MAX(0._wp, SIN(zcent(:))*0.88_wp + COS(zcent(:))*0.12_wp)
6944              vffrac0(:) = vffrac0(:) / (SUM(vffrac0) * REAL(naz, wp))
6945           ENDIF
6946
6947           DO  imrt = 1, nmrtbl
6948              ta = (/ REAL(mrtbl(iz, imrt), wp),  &
6949                      REAL(mrtbl(iy, imrt), wp),  &
6950                      REAL(mrtbl(ix, imrt), wp) /)
6951!
6952!--           vf fractions are constant per azimuth
6953              DO iaz = 0, naz-1
6954                 vffrac(iaz*nzn+1:(iaz+1)*nzn) = vffrac0(:)
6955              ENDDO
6956!--           sum of whole vffrac equals 1, verified
6957              itarg0 = 1
6958              itarg1 = nzn
6959!
6960!--           Calculate sky-view factor and direct solar visibility using 2D raytracing
6961              DO  iaz = 1, naz
6962                 azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
6963                 yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
6964                 yxlen = SQRT(SUM(yxdir(:)**2))
6965                 zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
6966                 yxdir(:) = yxdir(:) / yxlen
6967
6968                 CALL raytrace_2d(ta, yxdir, nzn, zdirs,                         &
6969                                  -999, -999._wp, vffrac(itarg0:itarg1), .TRUE., &
6970                                  .FALSE., .TRUE., lowest_free_ray,              &
6971                                  ztransp(itarg0:itarg1),                        &
6972                                  itarget(itarg0:itarg1))
6973
6974!--              Sky view factors for MRT
6975                 mrtsky(imrt) = mrtsky(imrt) + &
6976                                  SUM(vffrac(itarg0:itarg0+lowest_free_ray-1))
6977                 mrtskyt(imrt) = mrtskyt(imrt) + &
6978                                   SUM(ztransp(itarg0:itarg0+lowest_free_ray-1) &
6979                                               * vffrac(itarg0:itarg0+lowest_free_ray-1))
6980!--              Direct solar transparency for MRT
6981                 j = MODULO(NINT(azmid/                                         &
6982                                (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
6983                            raytrace_discrete_azims)
6984                 DO  k = 1, raytrace_discrete_elevs/2
6985                    i = dsidir_rev(k-1, j)
6986                    IF ( i /= -1  .AND.  k <= lowest_free_ray ) &
6987                       mrtdsit(imrt, i) = ztransp(itarg0+k-1)
6988                 ENDDO
6989!
6990!--              Advance itarget indices
6991                 itarg0 = itarg1 + 1
6992                 itarg1 = itarg1 + nzn
6993              ENDDO
6994
6995!--           sort itarget by face id
6996              CALL quicksort_itarget(itarget,vffrac,ztransp,1,nzn*naz)
6997!
6998!--           find the first valid position
6999              itarg0 = 1
7000              DO WHILE ( itarg0 <= nzn*naz )
7001                 IF ( itarget(itarg0) /= -1 )  EXIT
7002                 itarg0 = itarg0 + 1
7003              ENDDO
7004
7005              DO  i = itarg0, nzn*naz
7006!
7007!--              For duplicate values, only sum up vf fraction value
7008                 IF ( i < nzn*naz )  THEN
7009                    IF ( itarget(i+1) == itarget(i) )  THEN
7010                       vffrac(i+1) = vffrac(i+1) + vffrac(i)
7011                       CYCLE
7012                    ENDIF
7013                 ENDIF
7014!
7015!--              write to the mrtf array
7016                 nmrtf = nmrtf + 1
7017!--              check dimmension of mrtf array and enlarge it if needed
7018                 IF ( nmrtfa < nmrtf )  THEN
7019                    k = CEILING(REAL(nmrtfa, kind=wp) * grow_factor)
7020                    IF ( mmrtf == 0 )  THEN
7021                       mmrtf = 1
7022                       ALLOCATE( amrtf1(k) )
7023                       amrtf => amrtf1
7024                       amrtf1(1:nmrtfa) = amrtf2
7025                       DEALLOCATE( amrtf2 )
7026                    ELSE
7027                       mmrtf = 0
7028                       ALLOCATE( amrtf2(k) )
7029                       amrtf => amrtf2
7030                       amrtf2(1:nmrtfa) = amrtf1
7031                       DEALLOCATE( amrtf1 )
7032                    ENDIF
7033
7034                    WRITE (msg,'(A,3I12)') 'Grow amrtf:', nmrtf, nmrtfa, k
7035                    CALL radiation_write_debug_log( msg )
7036
7037                    nmrtfa = k
7038                 ENDIF
7039!--              write mrtf values into the array
7040                 amrtf(nmrtf)%isurflt = imrt
7041                 amrtf(nmrtf)%isurfs = itarget(i)
7042                 amrtf(nmrtf)%rsvf = vffrac(i)
7043                 amrtf(nmrtf)%rtransp = ztransp(i)
7044              ENDDO ! itarg
7045
7046           ENDDO ! imrt
7047           DEALLOCATE ( zdirs, zcent, zbdry, vffrac, vffrac0, ztransp, itarget )
7048!
7049!--        Move MRT factors to final arrays
7050           ALLOCATE ( mrtf(nmrtf), mrtft(nmrtf), mrtfsurf(2,nmrtf) )
7051           DO  imrtf = 1, nmrtf
7052              mrtf(imrtf) = amrtf(imrtf)%rsvf
7053              mrtft(imrtf) = amrtf(imrtf)%rsvf * amrtf(imrtf)%rtransp
7054              mrtfsurf(:,imrtf) = (/amrtf(imrtf)%isurflt, amrtf(imrtf)%isurfs /)
7055           ENDDO
7056           IF ( ALLOCATED(amrtf1) )  DEALLOCATE( amrtf1 )
7057           IF ( ALLOCATED(amrtf2) )  DEALLOCATE( amrtf2 )
7058        ENDIF ! nmrtbl > 0
7059
7060        IF ( rad_angular_discretization )  THEN
7061#if defined( __parallel )
7062!--        finalize MPI_RMA communication established to get global index of the surface from grid indices
7063!--        flush all MPI window pending requests
7064           CALL MPI_Win_flush_all(win_gridsurf, ierr)
7065           IF ( ierr /= 0 ) THEN
7066               WRITE(9,*) 'Error MPI_Win_flush_all1:', ierr, win_gridsurf
7067               FLUSH(9)
7068           ENDIF
7069!--        unlock MPI window
7070           CALL MPI_Win_unlock_all(win_gridsurf, ierr)
7071           IF ( ierr /= 0 ) THEN
7072               WRITE(9,*) 'Error MPI_Win_unlock_all1:', ierr, win_gridsurf
7073               FLUSH(9)
7074           ENDIF
7075!--        free MPI window
7076           CALL MPI_Win_free(win_gridsurf, ierr)
7077           IF ( ierr /= 0 ) THEN
7078               WRITE(9,*) 'Error MPI_Win_free1:', ierr, win_gridsurf
7079               FLUSH(9)
7080           ENDIF
7081#else
7082           DEALLOCATE ( gridsurf )
7083#endif
7084        ENDIF
7085
7086        CALL radiation_write_debug_log( 'End of calculation SVF' )
7087        WRITE(msg, *) 'Raytracing skipped for maximum distance of ', &
7088           max_raytracing_dist, ' m on ', ray_skip_maxdist, ' pairs.'
7089        CALL radiation_write_debug_log( msg )
7090        WRITE(msg, *) 'Raytracing skipped for minimum potential value of ', &
7091           min_irrf_value , ' on ', ray_skip_minval, ' pairs.'
7092        CALL radiation_write_debug_log( msg )
7093
7094        CALL location_message( '    waiting for completion of SVF and CSF calculation in all processes', .TRUE. )
7095!--     deallocate temporary global arrays
7096        DEALLOCATE(nzterr)
7097       
7098        IF ( plant_canopy )  THEN
7099!--         finalize mpi_rma communication and deallocate temporary arrays
7100#if defined( __parallel )
7101            IF ( raytrace_mpi_rma )  THEN
7102                CALL MPI_Win_flush_all(win_lad, ierr)
7103                IF ( ierr /= 0 ) THEN
7104                    WRITE(9,*) 'Error MPI_Win_flush_all2:', ierr, win_lad
7105                    FLUSH(9)
7106                ENDIF
7107!--             unlock MPI window
7108                CALL MPI_Win_unlock_all(win_lad, ierr)
7109                IF ( ierr /= 0 ) THEN
7110                    WRITE(9,*) 'Error MPI_Win_unlock_all2:', ierr, win_lad
7111                    FLUSH(9)
7112                ENDIF
7113!--             free MPI window
7114                CALL MPI_Win_free(win_lad, ierr)
7115                IF ( ierr /= 0 ) THEN
7116                    WRITE(9,*) 'Error MPI_Win_free2:', ierr, win_lad
7117                    FLUSH(9)
7118                ENDIF
7119!--             deallocate temporary arrays storing values for csf calculation during raytracing
7120                DEALLOCATE( lad_s_ray )
7121!--             sub_lad is the pointer to lad_s_rma in case of raytrace_mpi_rma
7122!--             and must not be deallocated here
7123            ELSE
7124                DEALLOCATE(sub_lad)
7125                DEALLOCATE(sub_lad_g)
7126            ENDIF
7127#else
7128            DEALLOCATE(sub_lad)
7129#endif
7130            DEALLOCATE( boxes )
7131            DEALLOCATE( crlens )
7132            DEALLOCATE( plantt )
7133            DEALLOCATE( rt2_track, rt2_track_lad, rt2_track_dist, rt2_dist )
7134        ENDIF
7135
7136        CALL location_message( '    calculation of the complete SVF array', .TRUE. )
7137
7138        IF ( rad_angular_discretization )  THEN
7139           CALL radiation_write_debug_log( 'Load svf from the structure array to plain arrays' )
7140           ALLOCATE( svf(ndsvf,nsvfl) )
7141           ALLOCATE( svfsurf(idsvf,nsvfl) )
7142
7143           DO isvf = 1, nsvfl
7144               svf(:, isvf) = (/ asvf(isvf)%rsvf, asvf(isvf)%rtransp /)
7145               svfsurf(:, isvf) = (/ asvf(isvf)%isurflt, asvf(isvf)%isurfs /)
7146           ENDDO
7147        ELSE
7148           CALL radiation_write_debug_log( 'Start SVF sort' )
7149!--        sort svf ( a version of quicksort )
7150           CALL quicksort_svf(asvf,1,nsvfl)
7151
7152           !< load svf from the structure array to plain arrays
7153           CALL radiation_write_debug_log( 'Load svf from the structure array to plain arrays' )
7154           ALLOCATE( svf(ndsvf,nsvfl) )
7155           ALLOCATE( svfsurf(idsvf,nsvfl) )
7156           svfnorm_counts(:) = 0._wp
7157           isurflt_prev = -1
7158           ksvf = 1
7159           svfsum = 0._wp
7160           DO isvf = 1, nsvfl
7161!--            normalize svf per target face
7162               IF ( asvf(ksvf)%isurflt /= isurflt_prev )  THEN
7163                   IF ( isurflt_prev /= -1  .AND.  svfsum /= 0._wp )  THEN
7164                       !< update histogram of logged svf normalization values
7165                       i = searchsorted(svfnorm_report_thresh, svfsum / (1._wp-skyvf(isurflt_prev)))
7166                       svfnorm_counts(i) = svfnorm_counts(i) + 1
7167
7168                       svf(1, isvf_surflt:isvf-1) = svf(1, isvf_surflt:isvf-1) / svfsum * (1._wp-skyvf(isurflt_prev))
7169                   ENDIF
7170                   isurflt_prev = asvf(ksvf)%isurflt
7171                   isvf_surflt = isvf
7172                   svfsum = asvf(ksvf)%rsvf !?? / asvf(ksvf)%rtransp
7173               ELSE
7174                   svfsum = svfsum + asvf(ksvf)%rsvf !?? / asvf(ksvf)%rtransp
7175               ENDIF
7176
7177               svf(:, isvf) = (/ asvf(ksvf)%rsvf, asvf(ksvf)%rtransp /)
7178               svfsurf(:, isvf) = (/ asvf(ksvf)%isurflt, asvf(ksvf)%isurfs /)
7179
7180!--            next element
7181               ksvf = ksvf + 1
7182           ENDDO
7183
7184           IF ( isurflt_prev /= -1  .AND.  svfsum /= 0._wp )  THEN
7185               i = searchsorted(svfnorm_report_thresh, svfsum / (1._wp-skyvf(isurflt_prev)))
7186               svfnorm_counts(i) = svfnorm_counts(i) + 1
7187
7188               svf(1, isvf_surflt:nsvfl) = svf(1, isvf_surflt:nsvfl) / svfsum * (1._wp-skyvf(isurflt_prev))
7189           ENDIF
7190           WRITE(9, *) 'SVF normalization histogram:', svfnorm_counts,  &
7191                       'on thresholds:', svfnorm_report_thresh(1:svfnorm_report_num), '(val < thresh <= val)'
7192           !TODO we should be able to deallocate skyvf, from now on we only need skyvft
7193        ENDIF ! rad_angular_discretization
7194
7195!--     deallocate temporary asvf array
7196!--     DEALLOCATE(asvf) - ifort has a problem with deallocation of allocatable target
7197!--     via pointing pointer - we need to test original targets
7198        IF ( ALLOCATED(asvf1) )  THEN
7199            DEALLOCATE(asvf1)
7200        ENDIF
7201        IF ( ALLOCATED(asvf2) )  THEN
7202            DEALLOCATE(asvf2)
7203        ENDIF
7204
7205        npcsfl = 0
7206        IF ( plant_canopy )  THEN
7207
7208            CALL location_message( '    calculation of the complete CSF array', .TRUE. )
7209            CALL radiation_write_debug_log( 'Calculation of the complete CSF array' )
7210!--         sort and merge csf for the last time, keeping the array size to minimum
7211            CALL merge_and_grow_csf(-1)
7212           
7213!--         aggregate csb among processors
7214!--         allocate necessary arrays
7215            udim = max(ncsfl,1)
7216            ALLOCATE( csflt_l(ndcsf*udim) )
7217            csflt(1:ndcsf,1:udim) => csflt_l(1:ndcsf*udim)
7218            ALLOCATE( kcsflt_l(kdcsf*udim) )
7219            kcsflt(1:kdcsf,1:udim) => kcsflt_l(1:kdcsf*udim)
7220            ALLOCATE( icsflt(0:numprocs-1) )
7221            ALLOCATE( dcsflt(0:numprocs-1) )
7222            ALLOCATE( ipcsflt(0:numprocs-1) )
7223            ALLOCATE( dpcsflt(0:numprocs-1) )
7224           
7225!--         fill out arrays of csf values and
7226!--         arrays of number of elements and displacements
7227!--         for particular precessors
7228            icsflt = 0
7229            dcsflt = 0
7230            ip = -1
7231            j = -1
7232            d = 0
7233            DO kcsf = 1, ncsfl
7234                j = j+1
7235                IF ( acsf(kcsf)%ip /= ip )  THEN
7236!--                 new block of the processor
7237!--                 number of elements of previous block
7238                    IF ( ip>=0) icsflt(ip) = j
7239                    d = d+j
7240!--                 blank blocks
7241                    DO jp = ip+1, acsf(kcsf)%ip-1
7242!--                     number of elements is zero, displacement is equal to previous
7243                        icsflt(jp) = 0
7244                        dcsflt(jp) = d
7245                    ENDDO
7246!--                 the actual block
7247                    ip = acsf(kcsf)%ip
7248                    dcsflt(ip) = d
7249                    j = 0
7250                ENDIF
7251                csflt(1,kcsf) = acsf(kcsf)%rcvf
7252!--             fill out integer values of itz,ity,itx,isurfs
7253                kcsflt(1,kcsf) = acsf(kcsf)%itz
7254                kcsflt(2,kcsf) = acsf(kcsf)%ity
7255                kcsflt(3,kcsf) = acsf(kcsf)%itx
7256                kcsflt(4,kcsf) = acsf(kcsf)%isurfs
7257            ENDDO
7258!--         last blank blocks at the end of array
7259            j = j+1
7260            IF ( ip>=0 ) icsflt(ip) = j
7261            d = d+j
7262            DO jp = ip+1, numprocs-1
7263!--             number of elements is zero, displacement is equal to previous
7264                icsflt(jp) = 0
7265                dcsflt(jp) = d
7266            ENDDO
7267           
7268!--         deallocate temporary acsf array
7269!--         DEALLOCATE(acsf) - ifort has a problem with deallocation of allocatable target
7270!--         via pointing pointer - we need to test original targets
7271            IF ( ALLOCATED(acsf1) )  THEN
7272                DEALLOCATE(acsf1)
7273            ENDIF
7274            IF ( ALLOCATED(acsf2) )  THEN
7275                DEALLOCATE(acsf2)
7276            ENDIF
7277                   
7278#if defined( __parallel )
7279!--         scatter and gather the number of elements to and from all processor
7280!--         and calculate displacements
7281            CALL radiation_write_debug_log( 'Scatter and gather the number of elements to and from all processor' )
7282            CALL MPI_AlltoAll(icsflt,1,MPI_INTEGER,ipcsflt,1,MPI_INTEGER,comm2d, ierr)
7283            IF ( ierr /= 0 ) THEN
7284                WRITE(9,*) 'Error MPI_AlltoAll1:', ierr, SIZE(icsflt), SIZE(ipcsflt)
7285                FLUSH(9)
7286            ENDIF
7287
7288            npcsfl = SUM(ipcsflt)
7289            d = 0
7290            DO i = 0, numprocs-1
7291                dpcsflt(i) = d
7292                d = d + ipcsflt(i)
7293            ENDDO
7294
7295!--         exchange csf fields between processors
7296            CALL radiation_write_debug_log( 'Exchange csf fields between processors' )
7297            udim = max(npcsfl,1)
7298            ALLOCATE( pcsflt_l(ndcsf*udim) )
7299            pcsflt(1:ndcsf,1:udim) => pcsflt_l(1:ndcsf*udim)
7300            ALLOCATE( kpcsflt_l(kdcsf*udim) )
7301            kpcsflt(1:kdcsf,1:udim) => kpcsflt_l(1:kdcsf*udim)
7302            CALL MPI_AlltoAllv(csflt_l, ndcsf*icsflt, ndcsf*dcsflt, MPI_REAL, &
7303                pcsflt_l, ndcsf*ipcsflt, ndcsf*dpcsflt, MPI_REAL, comm2d, ierr)
7304            IF ( ierr /= 0 ) THEN
7305                WRITE(9,*) 'Error MPI_AlltoAllv1:', ierr, SIZE(ipcsflt), ndcsf*icsflt, &
7306                            ndcsf*dcsflt, SIZE(pcsflt_l),ndcsf*ipcsflt, ndcsf*dpcsflt
7307                FLUSH(9)
7308            ENDIF
7309
7310            CALL MPI_AlltoAllv(kcsflt_l, kdcsf*icsflt, kdcsf*dcsflt, MPI_INTEGER, &
7311                kpcsflt_l, kdcsf*ipcsflt, kdcsf*dpcsflt, MPI_INTEGER, comm2d, ierr)
7312            IF ( ierr /= 0 ) THEN
7313                WRITE(9,*) 'Error MPI_AlltoAllv2:', ierr, SIZE(kcsflt_l),kdcsf*icsflt, &
7314                           kdcsf*dcsflt, SIZE(kpcsflt_l), kdcsf*ipcsflt, kdcsf*dpcsflt
7315                FLUSH(9)
7316            ENDIF
7317           
7318#else
7319            npcsfl = ncsfl
7320            ALLOCATE( pcsflt(ndcsf,max(npcsfl,ndcsf)) )
7321            ALLOCATE( kpcsflt(kdcsf,max(npcsfl,kdcsf)) )
7322            pcsflt = csflt
7323            kpcsflt = kcsflt
7324#endif
7325
7326!--         deallocate temporary arrays
7327            DEALLOCATE( csflt_l )
7328            DEALLOCATE( kcsflt_l )
7329            DEALLOCATE( icsflt )
7330            DEALLOCATE( dcsflt )
7331            DEALLOCATE( ipcsflt )
7332            DEALLOCATE( dpcsflt )
7333
7334!--         sort csf ( a version of quicksort )
7335            CALL radiation_write_debug_log( 'Sort csf' )
7336            CALL quicksort_csf2(kpcsflt, pcsflt, 1, npcsfl)
7337
7338!--         aggregate canopy sink factor records with identical box & source
7339!--         againg across all values from all processors
7340            CALL radiation_write_debug_log( 'Aggregate canopy sink factor records with identical box' )
7341
7342            IF ( npcsfl > 0 )  THEN
7343                icsf = 1 !< reading index
7344                kcsf = 1 !< writing index
7345                DO while (icsf < npcsfl)
7346!--                 here kpcsf(kcsf) already has values from kpcsf(icsf)
7347                    IF ( kpcsflt(3,icsf) == kpcsflt(3,icsf+1)  .AND.  &
7348                         kpcsflt(2,icsf) == kpcsflt(2,icsf+1)  .AND.  &
7349                         kpcsflt(1,icsf) == kpcsflt(1,icsf+1)  .AND.  &
7350                         kpcsflt(4,icsf) == kpcsflt(4,icsf+1) )  THEN
7351
7352                        pcsflt(1,kcsf) = pcsflt(1,kcsf) + pcsflt(1,icsf+1)
7353
7354!--                     advance reading index, keep writing index
7355                        icsf = icsf + 1
7356                    ELSE
7357!--                     not identical, just advance and copy
7358                        icsf = icsf + 1
7359                        kcsf = kcsf + 1
7360                        kpcsflt(:,kcsf) = kpcsflt(:,icsf)
7361                        pcsflt(:,kcsf) = pcsflt(:,icsf)
7362                    ENDIF
7363                ENDDO
7364!--             last written item is now also the last item in valid part of array
7365                npcsfl = kcsf
7366            ENDIF
7367
7368            ncsfl = npcsfl
7369            IF ( ncsfl > 0 )  THEN
7370                ALLOCATE( csf(ndcsf,ncsfl) )
7371                ALLOCATE( csfsurf(idcsf,ncsfl) )
7372                DO icsf = 1, ncsfl
7373                    csf(:,icsf) = pcsflt(:,icsf)
7374                    csfsurf(1,icsf) =  gridpcbl(kpcsflt(1,icsf),kpcsflt(2,icsf),kpcsflt(3,icsf))
7375                    csfsurf(2,icsf) =  kpcsflt(4,icsf)
7376                ENDDO
7377            ENDIF
7378           
7379!--         deallocation of temporary arrays
7380            IF ( npcbl > 0 )  DEALLOCATE( gridpcbl )
7381            DEALLOCATE( pcsflt_l )
7382            DEALLOCATE( kpcsflt_l )
7383            CALL radiation_write_debug_log( 'End of aggregate csf' )
7384           
7385        ENDIF
7386
7387#if defined( __parallel )
7388        CALL MPI_BARRIER( comm2d, ierr )
7389#endif
7390        CALL radiation_write_debug_log( 'End of radiation_calc_svf (after mpi_barrier)' )
7391
7392        RETURN
7393       
7394!        WRITE( message_string, * )  &
7395!            'I/O error when processing shape view factors / ',  &
7396!            'plant canopy sink factors / direct irradiance factors.'
7397!        CALL message( 'init_urban_surface', 'PA0502', 2, 2, 0, 6, 0 )
7398       
7399    END SUBROUTINE radiation_calc_svf
7400
7401   
7402!------------------------------------------------------------------------------!
7403! Description:
7404! ------------
7405!> Raytracing for detecting obstacles and calculating compound canopy sink
7406!> factors. (A simple obstacle detection would only need to process faces in
7407!> 3 dimensions without any ordering.)
7408!> Assumtions:
7409!> -----------
7410!> 1. The ray always originates from a face midpoint (only one coordinate equals
7411!>    *.5, i.e. wall) and doesn't travel parallel to the surface (that would mean
7412!>    shape factor=0). Therefore, the ray may never travel exactly along a face
7413!>    or an edge.
7414!> 2. From grid bottom to urban surface top the grid has to be *equidistant*
7415!>    within each of the dimensions, including vertical (but the resolution
7416!>    doesn't need to be the same in all three dimensions).
7417!------------------------------------------------------------------------------!
7418    SUBROUTINE raytrace(src, targ, isrc, difvf, atarg, create_csf, visible, transparency)
7419        IMPLICIT NONE
7420
7421        REAL(wp), DIMENSION(3), INTENT(in)     :: src, targ    !< real coordinates z,y,x
7422        INTEGER(iwp), INTENT(in)               :: isrc         !< index of source face for csf
7423        REAL(wp), INTENT(in)                   :: difvf        !< differential view factor for csf
7424        REAL(wp), INTENT(in)                   :: atarg        !< target surface area for csf
7425        LOGICAL, INTENT(in)                    :: create_csf   !< whether to generate new CSFs during raytracing
7426        LOGICAL, INTENT(out)                   :: visible
7427        REAL(wp), INTENT(out)                  :: transparency !< along whole path
7428        INTEGER(iwp)                           :: i, k, d
7429        INTEGER(iwp)                           :: seldim       !< dimension to be incremented
7430        INTEGER(iwp)                           :: ncsb         !< no of written plant canopy sinkboxes
7431        INTEGER(iwp)                           :: maxboxes     !< max no of gridboxes visited
7432        REAL(wp)                               :: distance     !< euclidean along path
7433        REAL(wp)                               :: crlen        !< length of gridbox crossing
7434        REAL(wp)                               :: lastdist     !< beginning of current crossing
7435        REAL(wp)                               :: nextdist     !< end of current crossing
7436        REAL(wp)                               :: realdist     !< distance in meters per unit distance
7437        REAL(wp)                               :: crmid        !< midpoint of crossing
7438        REAL(wp)                               :: cursink      !< sink factor for current canopy box
7439        REAL(wp), DIMENSION(3)                 :: delta        !< path vector
7440        REAL(wp), DIMENSION(3)                 :: uvect        !< unit vector
7441        REAL(wp), DIMENSION(3)                 :: dimnextdist  !< distance for each dimension increments
7442        INTEGER(iwp), DIMENSION(3)             :: box          !< gridbox being crossed
7443        INTEGER(iwp), DIMENSION(3)             :: dimnext      !< next dimension increments along path
7444        INTEGER(iwp), DIMENSION(3)             :: dimdelta     !< dimension direction = +- 1
7445        INTEGER(iwp)                           :: px, py       !< number of processors in x and y dir before
7446                                                               !< the processor in the question
7447        INTEGER(iwp)                           :: ip           !< number of processor where gridbox reside
7448        INTEGER(iwp)                           :: ig           !< 1D index of gridbox in global 2D array
7449       
7450        REAL(wp)                               :: eps = 1E-10_wp !< epsilon for value comparison
7451        REAL(wp)                               :: lad_s_target   !< recieved lad_s of particular grid box
7452
7453!
7454!--     Maximum number of gridboxes visited equals to maximum number of boundaries crossed in each dimension plus one. That's also
7455!--     the maximum number of plant canopy boxes written. We grow the acsf array accordingly using exponential factor.
7456        maxboxes = SUM(ABS(NINT(targ, iwp) - NINT(src, iwp))) + 1
7457        IF ( plant_canopy  .AND.  ncsfl + maxboxes > ncsfla )  THEN
7458!--         use this code for growing by fixed exponential increments (equivalent to case where ncsfl always increases by 1)
7459!--         k = CEILING(grow_factor ** real(CEILING(log(real(ncsfl + maxboxes, kind=wp)) &
7460!--                                                / log(grow_factor)), kind=wp))
7461!--         or use this code to simply always keep some extra space after growing
7462            k = CEILING(REAL(ncsfl + maxboxes, kind=wp) * grow_factor)
7463
7464            CALL merge_and_grow_csf(k)
7465        ENDIF
7466       
7467        transparency = 1._wp
7468        ncsb = 0
7469
7470        delta(:) = targ(:) - src(:)
7471        distance = SQRT(SUM(delta(:)**2))
7472        IF ( distance == 0._wp )  THEN
7473            visible = .TRUE.
7474            RETURN
7475        ENDIF
7476        uvect(:) = delta(:) / distance
7477        realdist = SQRT(SUM( (uvect(:)*(/dz(1),dy,dx/))**2 ))
7478
7479        lastdist = 0._wp
7480
7481!--     Since all face coordinates have values *.5 and we'd like to use
7482!--     integers, all these have .5 added
7483        DO d = 1, 3
7484            IF ( uvect(d) == 0._wp )  THEN
7485                dimnext(d) = 999999999
7486                dimdelta(d) = 999999999
7487                dimnextdist(d) = 1.0E20_wp
7488            ELSE IF ( uvect(d) > 0._wp )  THEN
7489                dimnext(d) = CEILING(src(d) + .5_wp)
7490                dimdelta(d) = 1
7491                dimnextdist(d) = (dimnext(d) - .5_wp - src(d)) / uvect(d)
7492            ELSE
7493                dimnext(d) = FLOOR(src(d) + .5_wp)
7494                dimdelta(d) = -1
7495                dimnextdist(d) = (dimnext(d) - .5_wp - src(d)) / uvect(d)
7496            ENDIF
7497        ENDDO
7498
7499        DO
7500!--         along what dimension will the next wall crossing be?
7501            seldim = minloc(dimnextdist, 1)
7502            nextdist = dimnextdist(seldim)
7503            IF ( nextdist > distance ) nextdist = distance
7504
7505            crlen = nextdist - lastdist
7506            IF ( crlen > .001_wp )  THEN
7507                crmid = (lastdist + nextdist) * .5_wp
7508                box = NINT(src(:) + uvect(:) * crmid, iwp)
7509
7510!--             calculate index of the grid with global indices (box(2),box(3))
7511!--             in the array nzterr and plantt and id of the coresponding processor
7512                px = box(3)/nnx
7513                py = box(2)/nny
7514                ip = px*pdims(2)+py
7515                ig = ip*nnx*nny + (box(3)-px*nnx)*nny + box(2)-py*nny
7516                IF ( box(1) <= nzterr(ig) )  THEN
7517                    visible = .FALSE.
7518                    RETURN
7519                ENDIF
7520
7521                IF ( plant_canopy )  THEN
7522                    IF ( box(1) <= plantt(ig) )  THEN
7523                        ncsb = ncsb + 1
7524                        boxes(:,ncsb) = box
7525                        crlens(ncsb) = crlen
7526#if defined( __parallel )
7527                        lad_ip(ncsb) = ip
7528                        lad_disp(ncsb) = (box(3)-px*nnx)*(nny*nzp) + (box(2)-py*nny)*nzp + box(1)-nzub
7529#endif
7530                    ENDIF
7531                ENDIF
7532            ENDIF
7533
7534            IF ( ABS(distance - nextdist) < eps )  EXIT
7535            lastdist = nextdist
7536            dimnext(seldim) = dimnext(seldim) + dimdelta(seldim)
7537            dimnextdist(seldim) = (dimnext(seldim) - .5_wp - src(seldim)) / uvect(seldim)
7538        ENDDO
7539       
7540        IF ( plant_canopy )  THEN
7541#if defined( __parallel )
7542            IF ( raytrace_mpi_rma )  THEN
7543!--             send requests for lad_s to appropriate processor
7544                CALL cpu_log( log_point_s(77), 'rad_rma_lad', 'start' )
7545                DO i = 1, ncsb
7546                    CALL MPI_Get(lad_s_ray(i), 1, MPI_REAL, lad_ip(i), lad_disp(i), &
7547                                 1, MPI_REAL, win_lad, ierr)
7548                    IF ( ierr /= 0 )  THEN
7549                        WRITE(9,*) 'Error MPI_Get1:', ierr, lad_s_ray(i), &
7550                                   lad_ip(i), lad_disp(i), win_lad
7551                        FLUSH(9)
7552                    ENDIF
7553                ENDDO
7554               
7555!--             wait for all pending local requests complete
7556                CALL MPI_Win_flush_local_all(win_lad, ierr)
7557                IF ( ierr /= 0 )  THEN
7558                    WRITE(9,*) 'Error MPI_Win_flush_local_all1:', ierr, win_lad
7559                    FLUSH(9)
7560                ENDIF
7561                CALL cpu_log( log_point_s(77), 'rad_rma_lad', 'stop' )
7562               
7563            ENDIF
7564#endif
7565
7566!--         calculate csf and transparency
7567            DO i = 1, ncsb
7568#if defined( __parallel )
7569                IF ( raytrace_mpi_rma )  THEN
7570                    lad_s_target = lad_s_ray(i)
7571                ELSE
7572                    lad_s_target = sub_lad_g(lad_ip(i)*nnx*nny*nzp + lad_disp(i))
7573                ENDIF
7574#else
7575                lad_s_target = sub_lad(boxes(1,i),boxes(2,i),boxes(3,i))
7576#endif
7577                cursink = 1._wp - exp(-ext_coef * lad_s_target * crlens(i)*realdist)
7578
7579                IF ( create_csf )  THEN
7580!--                 write svf values into the array
7581                    ncsfl = ncsfl + 1
7582                    acsf(ncsfl)%ip = lad_ip(i)
7583                    acsf(ncsfl)%itx = boxes(3,i)
7584                    acsf(ncsfl)%ity = boxes(2,i)
7585                    acsf(ncsfl)%itz = boxes(1,i)
7586                    acsf(ncsfl)%isurfs = isrc
7587                    acsf(ncsfl)%rcvf = cursink*transparency*difvf*atarg
7588                ENDIF  !< create_csf
7589
7590                transparency = transparency * (1._wp - cursink)
7591               
7592            ENDDO
7593        ENDIF
7594       
7595        visible = .TRUE.
7596
7597    END SUBROUTINE raytrace
7598   
7599 
7600!------------------------------------------------------------------------------!
7601! Description:
7602! ------------
7603!> A new, more efficient version of ray tracing algorithm that processes a whole
7604!> arc instead of a single ray.
7605!>
7606!> In all comments, horizon means tangent of horizon angle, i.e.
7607!> vertical_delta / horizontal_distance
7608!------------------------------------------------------------------------------!
7609   SUBROUTINE raytrace_2d(origin, yxdir, nrays, zdirs, iorig, aorig, vffrac,  &
7610                              calc_svf, create_csf, skip_1st_pcb,             &
7611                              lowest_free_ray, transparency, itarget)
7612      IMPLICIT NONE
7613
7614      REAL(wp), DIMENSION(3), INTENT(IN)     ::  origin        !< z,y,x coordinates of ray origin
7615      REAL(wp), DIMENSION(2), INTENT(IN)     ::  yxdir         !< y,x *unit* vector of ray direction (in grid units)
7616      INTEGER(iwp)                           ::  nrays         !< number of rays (z directions) to raytrace
7617      REAL(wp), DIMENSION(nrays), INTENT(IN) ::  zdirs         !< list of z directions to raytrace (z/hdist, grid, zenith->nadir)
7618      INTEGER(iwp), INTENT(in)               ::  iorig         !< index of origin face for csf
7619      REAL(wp), INTENT(in)                   ::  aorig         !< origin face area for csf
7620      REAL(wp), DIMENSION(nrays), INTENT(in) ::  vffrac        !< view factor fractions of each ray for csf
7621      LOGICAL, INTENT(in)                    ::  calc_svf      !< whether to calculate SFV (identify obstacle surfaces)
7622      LOGICAL, INTENT(in)                    ::  create_csf    !< whether to create canopy sink factors
7623      LOGICAL, INTENT(in)                    ::  skip_1st_pcb  !< whether to skip first plant canopy box during raytracing
7624      INTEGER(iwp), INTENT(out)              ::  lowest_free_ray !< index into zdirs
7625      REAL(wp), DIMENSION(nrays), INTENT(OUT) ::  transparency !< transparencies of zdirs paths
7626      INTEGER(iwp), DIMENSION(nrays), INTENT(OUT) ::  itarget  !< global indices of target faces for zdirs
7627
7628      INTEGER(iwp), DIMENSION(nrays)         ::  target_procs
7629      REAL(wp)                               ::  horizon       !< highest horizon found after raytracing (z/hdist)
7630      INTEGER(iwp)                           ::  i, k, l, d
7631      INTEGER(iwp)                           ::  seldim       !< dimension to be incremented
7632      REAL(wp), DIMENSION(2)                 ::  yxorigin     !< horizontal copy of origin (y,x)
7633      REAL(wp)                               ::  distance     !< euclidean along path
7634      REAL(wp)                               ::  lastdist     !< beginning of current crossing
7635      REAL(wp)                               ::  nextdist     !< end of current crossing
7636      REAL(wp)                               ::  crmid        !< midpoint of crossing
7637      REAL(wp)                               ::  horz_entry   !< horizon at entry to column
7638      REAL(wp)                               ::  horz_exit    !< horizon at exit from column
7639      REAL(wp)                               ::  bdydim       !< boundary for current dimension
7640      REAL(wp), DIMENSION(2)                 ::  crossdist    !< distances to boundary for dimensions
7641      REAL(wp), DIMENSION(2)                 ::  dimnextdist  !< distance for each dimension increments
7642      INTEGER(iwp), DIMENSION(2)             ::  column       !< grid column being crossed
7643      INTEGER(iwp), DIMENSION(2)             ::  dimnext      !< next dimension increments along path
7644      INTEGER(iwp), DIMENSION(2)             ::  dimdelta     !< dimension direction = +- 1
7645      INTEGER(iwp)                           ::  px, py       !< number of processors in x and y dir before
7646                                                              !< the processor in the question
7647      INTEGER(iwp)                           ::  ip           !< number of processor where gridbox reside
7648      INTEGER(iwp)                           ::  ig           !< 1D index of gridbox in global 2D array
7649      INTEGER(iwp)                           ::  wcount       !< RMA window item count
7650      INTEGER(iwp)                           ::  maxboxes     !< max no of CSF created
7651      INTEGER(iwp)                           ::  nly          !< maximum  plant canopy height
7652      INTEGER(iwp)                           ::  ntrack
7653     
7654      INTEGER(iwp)                           ::  zb0
7655      INTEGER(iwp)                           ::  zb1
7656      INTEGER(iwp)                           ::  nz
7657      INTEGER(iwp)                           ::  iz
7658      INTEGER(iwp)                           ::  zsgn
7659      INTEGER(iwp)                           ::  lowest_lad   !< lowest column cell for which we need LAD
7660      INTEGER(iwp)                           ::  lastdir      !< wall direction before hitting this column
7661      INTEGER(iwp), DIMENSION(2)             ::  lastcolumn
7662
7663#if defined( __parallel )
7664      INTEGER(MPI_ADDRESS_KIND)              ::  wdisp        !< RMA window displacement
7665#endif
7666     
7667      REAL(wp)                               ::  eps = 1E-10_wp !< epsilon for value comparison
7668      REAL(wp)                               ::  zbottom, ztop !< urban surface boundary in real numbers
7669      REAL(wp)                               ::  zorig         !< z coordinate of ray column entry
7670      REAL(wp)                               ::  zexit         !< z coordinate of ray column exit
7671      REAL(wp)                               ::  qdist         !< ratio of real distance to z coord difference
7672      REAL(wp)                               ::  dxxyy         !< square of real horizontal distance
7673      REAL(wp)                               ::  curtrans      !< transparency of current PC box crossing
7674     
7675
7676     
7677      yxorigin(:) = origin(2:3)
7678      transparency(:) = 1._wp !-- Pre-set the all rays to transparent before reducing
7679      horizon = -HUGE(1._wp)
7680      lowest_free_ray = nrays
7681      IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7682         ALLOCATE(target_surfl(nrays))
7683         target_surfl(:) = -1
7684         lastdir = -999
7685         lastcolumn(:) = -999
7686      ENDIF
7687
7688!--   Determine distance to boundary (in 2D xy)
7689      IF ( yxdir(1) > 0._wp )  THEN
7690         bdydim = ny + .5_wp !< north global boundary
7691         crossdist(1) = (bdydim - yxorigin(1)) / yxdir(1)
7692      ELSEIF ( yxdir(1) == 0._wp )  THEN
7693         crossdist(1) = HUGE(1._wp)
7694      ELSE
7695          bdydim = -.5_wp !< south global boundary
7696          crossdist(1) = (bdydim - yxorigin(1)) / yxdir(1)
7697      ENDIF
7698
7699      IF ( yxdir(2) >= 0._wp )  THEN
7700          bdydim = nx + .5_wp !< east global boundary
7701          crossdist(2) = (bdydim - yxorigin(2)) / yxdir(2)
7702      ELSEIF ( yxdir(2) == 0._wp )  THEN
7703         crossdist(2) = HUGE(1._wp)
7704      ELSE
7705          bdydim = -.5_wp !< west global boundary
7706          crossdist(2) = (bdydim - yxorigin(2)) / yxdir(2)
7707      ENDIF
7708      distance = minval(crossdist, 1)
7709
7710      IF ( plant_canopy )  THEN
7711         rt2_track_dist(0) = 0._wp
7712         rt2_track_lad(:,:) = 0._wp
7713         nly = plantt_max - nzub + 1
7714      ENDIF
7715
7716      lastdist = 0._wp
7717
7718!--   Since all face coordinates have values *.5 and we'd like to use
7719!--   integers, all these have .5 added
7720      DO  d = 1, 2
7721          IF ( yxdir(d) == 0._wp )  THEN
7722              dimnext(d) = HUGE(1_iwp)
7723              dimdelta(d) = HUGE(1_iwp)
7724              dimnextdist(d) = HUGE(1._wp)
7725          ELSE IF ( yxdir(d) > 0._wp )  THEN
7726              dimnext(d) = FLOOR(yxorigin(d) + .5_wp) + 1
7727              dimdelta(d) = 1
7728              dimnextdist(d) = (dimnext(d) - .5_wp - yxorigin(d)) / yxdir(d)
7729          ELSE
7730              dimnext(d) = CEILING(yxorigin(d) + .5_wp) - 1
7731              dimdelta(d) = -1
7732              dimnextdist(d) = (dimnext(d) - .5_wp - yxorigin(d)) / yxdir(d)
7733          ENDIF
7734      ENDDO
7735
7736      ntrack = 0
7737      DO
7738!--      along what dimension will the next wall crossing be?
7739         seldim = minloc(dimnextdist, 1)
7740         nextdist = dimnextdist(seldim)
7741         IF ( nextdist > distance )  nextdist = distance
7742
7743         IF ( nextdist > lastdist )  THEN
7744            ntrack = ntrack + 1
7745            crmid = (lastdist + nextdist) * .5_wp
7746            column = NINT(yxorigin(:) + yxdir(:) * crmid, iwp)
7747
7748!--         calculate index of the grid with global indices (column(1),column(2))
7749!--         in the array nzterr and plantt and id of the coresponding processor
7750            px = column(2)/nnx
7751            py = column(1)/nny
7752            ip = px*pdims(2)+py
7753            ig = ip*nnx*nny + (column(2)-px*nnx)*nny + column(1)-py*nny
7754
7755            IF ( lastdist == 0._wp )  THEN
7756               horz_entry = -HUGE(1._wp)
7757            ELSE
7758               horz_entry = (REAL(nzterr(ig), wp) + .5_wp - origin(1)) / lastdist
7759            ENDIF
7760            horz_exit = (REAL(nzterr(ig), wp) + .5_wp - origin(1)) / nextdist
7761
7762            IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7763!
7764!--            Identify vertical obstacles hit by rays in current column
7765               DO WHILE ( lowest_free_ray > 0 )
7766                  IF ( zdirs(lowest_free_ray) > horz_entry )  EXIT
7767!
7768!--               This may only happen after 1st column, so lastdir and lastcolumn are valid
7769                  CALL request_itarget(lastdir,                                         &
7770                        CEILING(-0.5_wp + origin(1) + zdirs(lowest_free_ray)*lastdist), &
7771                        lastcolumn(1), lastcolumn(2),                                   &
7772                        target_surfl(lowest_free_ray), target_procs(lowest_free_ray))
7773                  lowest_free_ray = lowest_free_ray - 1
7774               ENDDO
7775!
7776!--            Identify horizontal obstacles hit by rays in current column
7777               DO WHILE ( lowest_free_ray > 0 )
7778                  IF ( zdirs(lowest_free_ray) > horz_exit )  EXIT
7779                  CALL request_itarget(iup_u, nzterr(ig)+1, column(1), column(2), &
7780                                       target_surfl(lowest_free_ray),           &
7781                                       target_procs(lowest_free_ray))
7782                  lowest_free_ray = lowest_free_ray - 1
7783               ENDDO
7784            ENDIF
7785
7786            horizon = MAX(horizon, horz_entry, horz_exit)
7787
7788            IF ( plant_canopy )  THEN
7789               rt2_track(:, ntrack) = column(:)
7790               rt2_track_dist(ntrack) = nextdist
7791            ENDIF
7792         ENDIF
7793
7794         IF ( ABS(distance - nextdist) < eps )  EXIT
7795
7796         IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7797!
7798!--         Save wall direction of coming building column (= this air column)
7799            IF ( seldim == 1 )  THEN
7800               IF ( dimdelta(seldim) == 1 )  THEN
7801                  lastdir = isouth_u
7802               ELSE
7803                  lastdir = inorth_u
7804               ENDIF
7805            ELSE
7806               IF ( dimdelta(seldim) == 1 )  THEN
7807                  lastdir = iwest_u
7808               ELSE
7809                  lastdir = ieast_u
7810               ENDIF
7811            ENDIF
7812            lastcolumn = column
7813         ENDIF
7814         lastdist = nextdist
7815         dimnext(seldim) = dimnext(seldim) + dimdelta(seldim)
7816         dimnextdist(seldim) = (dimnext(seldim) - .5_wp - yxorigin(seldim)) / yxdir(seldim)
7817      ENDDO
7818
7819      IF ( plant_canopy )  THEN
7820!--      Request LAD WHERE applicable
7821!--     
7822#if defined( __parallel )
7823         IF ( raytrace_mpi_rma )  THEN
7824!--         send requests for lad_s to appropriate processor
7825            !CALL cpu_log( log_point_s(77), 'usm_init_rma', 'start' )
7826            DO  i = 1, ntrack
7827               px = rt2_track(2,i)/nnx
7828               py = rt2_track(1,i)/nny
7829               ip = px*pdims(2)+py
7830               ig = ip*nnx*nny + (rt2_track(2,i)-px*nnx)*nny + rt2_track(1,i)-py*nny
7831
7832               IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7833!
7834!--               For fixed view resolution, we need plant canopy even for rays
7835!--               to opposing surfaces
7836                  lowest_lad = nzterr(ig) + 1
7837               ELSE
7838!
7839!--               We only need LAD for rays directed above horizon (to sky)
7840                  lowest_lad = CEILING( -0.5_wp + origin(1) +            &
7841                                    MIN( horizon * rt2_track_dist(i-1),  & ! entry
7842                                         horizon * rt2_track_dist(i)   ) ) ! exit
7843               ENDIF
7844!
7845!--            Skip asking for LAD where all plant canopy is under requested level
7846               IF ( plantt(ig) < lowest_lad )  CYCLE
7847
7848               wdisp = (rt2_track(2,i)-px*nnx)*(nny*nzp) + (rt2_track(1,i)-py*nny)*nzp + lowest_lad-nzub
7849               wcount = plantt(ig)-lowest_lad+1
7850               ! TODO send request ASAP - even during raytracing
7851               CALL MPI_Get(rt2_track_lad(lowest_lad:plantt(ig), i), wcount, MPI_REAL, ip,    &
7852                            wdisp, wcount, MPI_REAL, win_lad, ierr)
7853               IF ( ierr /= 0 )  THEN
7854                  WRITE(9,*) 'Error MPI_Get2:', ierr, rt2_track_lad(lowest_lad:plantt(ig), i), &
7855                             wcount, ip, wdisp, win_lad
7856                  FLUSH(9)
7857               ENDIF
7858            ENDDO
7859
7860!--         wait for all pending local requests complete
7861            ! TODO WAIT selectively for each column later when needed
7862            CALL MPI_Win_flush_local_all(win_lad, ierr)
7863            IF ( ierr /= 0 )  THEN
7864               WRITE(9,*) 'Error MPI_Win_flush_local_all2:', ierr, win_lad
7865               FLUSH(9)
7866            ENDIF
7867            !CALL cpu_log( log_point_s(77), 'usm_init_rma', 'stop' )
7868
7869         ELSE ! raytrace_mpi_rma = .F.
7870            DO  i = 1, ntrack
7871               px = rt2_track(2,i)/nnx
7872               py = rt2_track(1,i)/nny
7873               ip = px*pdims(2)+py
7874               ig = ip*nnx*nny*nzp + (rt2_track(2,i)-px*nnx)*(nny*nzp) + (rt2_track(1,i)-py*nny)*nzp
7875               rt2_track_lad(nzub:plantt_max, i) = sub_lad_g(ig:ig+nly-1)
7876            ENDDO
7877         ENDIF
7878#else
7879         DO  i = 1, ntrack
7880            rt2_track_lad(nzub:plantt_max, i) = sub_lad(rt2_track(1,i), rt2_track(2,i), nzub:plantt_max)
7881         ENDDO
7882#endif
7883      ENDIF ! plant_canopy
7884
7885      IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7886#if defined( __parallel )
7887!--      wait for all gridsurf requests to complete
7888         CALL MPI_Win_flush_local_all(win_gridsurf, ierr)
7889         IF ( ierr /= 0 )  THEN
7890            WRITE(9,*) 'Error MPI_Win_flush_local_all3:', ierr, win_gridsurf
7891            FLUSH(9)
7892         ENDIF
7893#endif
7894!
7895!--      recalculate local surf indices into global ones
7896         DO i = 1, nrays
7897            IF ( target_surfl(i) == -1 )  THEN
7898               itarget(i) = -1
7899            ELSE
7900               itarget(i) = target_surfl(i) + surfstart(target_procs(i))
7901            ENDIF
7902         ENDDO
7903         
7904         DEALLOCATE( target_surfl )
7905         
7906      ELSE
7907         itarget(:) = -1
7908      ENDIF ! rad_angular_discretization
7909
7910      IF ( plant_canopy )  THEN
7911!--      Skip the PCB around origin if requested (for MRT, the PCB might not be there)
7912!--     
7913         IF ( skip_1st_pcb  .AND.  NINT(origin(1)) <= plantt_max )  THEN
7914            rt2_track_lad(NINT(origin(1), iwp), 1) = 0._wp
7915         ENDIF
7916
7917!--      Assert that we have space allocated for CSFs
7918!--     
7919         maxboxes = (ntrack + MAX(CEILING(origin(1)-.5_wp) - nzub,          &
7920                                  nzut - CEILING(origin(1)-.5_wp))) * nrays
7921         IF ( ncsfl + maxboxes > ncsfla )  THEN
7922!--         use this code for growing by fixed exponential increments (equivalent to case where ncsfl always increases by 1)
7923!--         k = CEILING(grow_factor ** real(CEILING(log(real(ncsfl + maxboxes, kind=wp)) &
7924!--                                                / log(grow_factor)), kind=wp))
7925!--         or use this code to simply always keep some extra space after growing
7926            k = CEILING(REAL(ncsfl + maxboxes, kind=wp) * grow_factor)
7927            CALL merge_and_grow_csf(k)
7928         ENDIF
7929
7930!--      Calculate transparencies and store new CSFs
7931!--     
7932         zbottom = REAL(nzub, wp) - .5_wp
7933         ztop = REAL(plantt_max, wp) + .5_wp
7934
7935!--      Reverse direction of radiation (face->sky), only when calc_svf
7936!--     
7937         IF ( calc_svf )  THEN
7938            DO  i = 1, ntrack ! for each column
7939               dxxyy = ((dy*yxdir(1))**2 + (dx*yxdir(2))**2) * (rt2_track_dist(i)-rt2_track_dist(i-1))**2
7940               px = rt2_track(2,i)/nnx
7941               py = rt2_track(1,i)/nny
7942               ip = px*pdims(2)+py
7943
7944               DO  k = 1, nrays ! for each ray
7945!
7946!--               NOTE 6778:
7947!--               With traditional svf discretization, CSFs under the horizon
7948!--               (i.e. for surface to surface radiation)  are created in
7949!--               raytrace(). With rad_angular_discretization, we must create
7950!--               CSFs under horizon only for one direction, otherwise we would
7951!--               have duplicate amount of energy. Although we could choose
7952!--               either of the two directions (they differ only by
7953!--               discretization error with no bias), we choose the the backward
7954!--               direction, because it tends to cumulate high canopy sink
7955!--               factors closer to raytrace origin, i.e. it should potentially
7956!--               cause less moiree.
7957                  IF ( .NOT. rad_angular_discretization )  THEN
7958                     IF ( zdirs(k) <= horizon )  CYCLE
7959                  ENDIF
7960
7961                  zorig = origin(1) + zdirs(k) * rt2_track_dist(i-1)
7962                  IF ( zorig <= zbottom  .OR.  zorig >= ztop )  CYCLE
7963
7964                  zsgn = INT(SIGN(1._wp, zdirs(k)), iwp)
7965                  rt2_dist(1) = 0._wp
7966                  IF ( zdirs(k) == 0._wp )  THEN ! ray is exactly horizontal
7967                     nz = 2
7968                     rt2_dist(nz) = SQRT(dxxyy)
7969                     iz = CEILING(-.5_wp + zorig, iwp)
7970                  ELSE
7971                     zexit = MIN(MAX(origin(1) + zdirs(k) * rt2_track_dist(i), zbottom), ztop)
7972
7973                     zb0 = FLOOR(  zorig * zsgn - .5_wp) + 1  ! because it must be greater than orig
7974                     zb1 = CEILING(zexit * zsgn - .5_wp) - 1  ! because it must be smaller than exit
7975                     nz = MAX(zb1 - zb0 + 3, 2)
7976                     rt2_dist(nz) = SQRT(((zexit-zorig)*dz(1))**2 + dxxyy)
7977                     qdist = rt2_dist(nz) / (zexit-zorig)
7978                     rt2_dist(2:nz-1) = (/( ((REAL(l, wp) + .5_wp) * zsgn - zorig) * qdist , l = zb0, zb1 )/)
7979                     iz = zb0 * zsgn
7980                  ENDIF
7981
7982                  DO  l = 2, nz
7983                     IF ( rt2_track_lad(iz, i) > 0._wp )  THEN
7984                        curtrans = exp(-ext_coef * rt2_track_lad(iz, i) * (rt2_dist(l)-rt2_dist(l-1)))
7985
7986                        IF ( create_csf )  THEN
7987                           ncsfl = ncsfl + 1
7988                           acsf(ncsfl)%ip = ip
7989                           acsf(ncsfl)%itx = rt2_track(2,i)
7990                           acsf(ncsfl)%ity = rt2_track(1,i)
7991                           acsf(ncsfl)%itz = iz
7992                           acsf(ncsfl)%isurfs = iorig
7993                           acsf(ncsfl)%rcvf = (1._wp - curtrans)*transparency(k)*vffrac(k)
7994                        ENDIF
7995
7996                        transparency(k) = transparency(k) * curtrans
7997                     ENDIF
7998                     iz = iz + zsgn
7999                  ENDDO ! l = 1, nz - 1
8000               ENDDO ! k = 1, nrays
8001            ENDDO ! i = 1, ntrack
8002
8003            transparency(1:lowest_free_ray) = 1._wp !-- Reset rays above horizon to transparent (see NOTE 6778)
8004         ENDIF
8005
8006!--      Forward direction of radiation (sky->face), always
8007!--     
8008         DO  i = ntrack, 1, -1 ! for each column backwards
8009            dxxyy = ((dy*yxdir(1))**2 + (dx*yxdir(2))**2) * (rt2_track_dist(i)-rt2_track_dist(i-1))**2
8010            px = rt2_track(2,i)/nnx
8011            py = rt2_track(1,i)/nny
8012            ip = px*pdims(2)+py
8013
8014            DO  k = 1, nrays ! for each ray
8015!
8016!--            See NOTE 6778 above
8017               IF ( zdirs(k) <= horizon )  CYCLE
8018
8019               zexit = origin(1) + zdirs(k) * rt2_track_dist(i-1)
8020               IF ( zexit <= zbottom  .OR.  zexit >= ztop )  CYCLE
8021
8022               zsgn = -INT(SIGN(1._wp, zdirs(k)), iwp)
8023               rt2_dist(1) = 0._wp
8024               IF ( zdirs(k) == 0._wp )  THEN ! ray is exactly horizontal
8025                  nz = 2
8026                  rt2_dist(nz) = SQRT(dxxyy)
8027                  iz = NINT(zexit, iwp)
8028               ELSE
8029                  zorig = MIN(MAX(origin(1) + zdirs(k) * rt2_track_dist(i), zbottom), ztop)
8030
8031                  zb0 = FLOOR(  zorig * zsgn - .5_wp) + 1  ! because it must be greater than orig
8032                  zb1 = CEILING(zexit * zsgn - .5_wp) - 1  ! because it must be smaller than exit
8033                  nz = MAX(zb1 - zb0 + 3, 2)
8034                  rt2_dist(nz) = SQRT(((zexit-zorig)*dz(1))**2 + dxxyy)
8035                  qdist = rt2_dist(nz) / (zexit-zorig)
8036                  rt2_dist(2:nz-1) = (/( ((REAL(l, wp) + .5_wp) * zsgn - zorig) * qdist , l = zb0, zb1 )/)
8037                  iz = zb0 * zsgn
8038               ENDIF
8039
8040               DO  l = 2, nz
8041                  IF ( rt2_track_lad(iz, i) > 0._wp )  THEN
8042                     curtrans = exp(-ext_coef * rt2_track_lad(iz, i) * (rt2_dist(l)-rt2_dist(l-1)))
8043
8044                     IF ( create_csf )  THEN
8045                        ncsfl = ncsfl + 1
8046                        acsf(ncsfl)%ip = ip
8047                        acsf(ncsfl)%itx = rt2_track(2,i)
8048                        acsf(ncsfl)%ity = rt2_track(1,i)
8049                        acsf(ncsfl)%itz = iz
8050                        IF ( itarget(k) /= -1 ) STOP 1 !FIXME remove after test
8051                        acsf(ncsfl)%isurfs = -1
8052                        acsf(ncsfl)%rcvf = (1._wp - curtrans)*transparency(k)*aorig*vffrac(k)
8053                     ENDIF  ! create_csf
8054
8055                     transparency(k) = transparency(k) * curtrans
8056                  ENDIF
8057                  iz = iz + zsgn
8058               ENDDO ! l = 1, nz - 1
8059            ENDDO ! k = 1, nrays
8060         ENDDO ! i = 1, ntrack
8061      ENDIF ! plant_canopy
8062
8063      IF ( .NOT. (rad_angular_discretization  .AND.  calc_svf) )  THEN
8064!
8065!--      Just update lowest_free_ray according to horizon
8066         DO WHILE ( lowest_free_ray > 0 )
8067            IF ( zdirs(lowest_free_ray) > horizon )  EXIT
8068            lowest_free_ray = lowest_free_ray - 1
8069         ENDDO
8070      ENDIF
8071
8072   CONTAINS
8073
8074      SUBROUTINE request_itarget( d, z, y, x, isurfl, iproc )
8075
8076         INTEGER(iwp), INTENT(in)            ::  d, z, y, x
8077         INTEGER(iwp), TARGET, INTENT(out)   ::  isurfl
8078         INTEGER(iwp), INTENT(out)           ::  iproc
8079#if defined( __parallel )
8080#else
8081         INTEGER(iwp)                        ::  target_displ  !< index of the grid in the local gridsurf array
8082#endif
8083         INTEGER(iwp)                        ::  px, py        !< number of processors in x and y direction
8084                                                               !< before the processor in the question
8085#if defined( __parallel )
8086         INTEGER(KIND=MPI_ADDRESS_KIND)      ::  target_displ  !< index of the grid in the local gridsurf array
8087
8088!
8089!--      Calculate target processor and index in the remote local target gridsurf array
8090         px = x / nnx
8091         py = y / nny
8092         iproc = px * pdims(2) + py
8093         target_displ = ((x-px*nnx) * nny + y - py*nny ) * nzu * nsurf_type_u +&
8094                        ( z-nzub ) * nsurf_type_u + d
8095!
8096!--      Send MPI_Get request to obtain index target_surfl(i)
8097         CALL MPI_GET( isurfl, 1, MPI_INTEGER, iproc, target_displ,            &
8098                       1, MPI_INTEGER, win_gridsurf, ierr)
8099         IF ( ierr /= 0 )  THEN
8100            WRITE( 9,* ) 'Error MPI_Get3:', ierr, isurfl, iproc, target_displ, &
8101                         win_gridsurf
8102            FLUSH( 9 )
8103         ENDIF
8104#else
8105!--      set index target_surfl(i)
8106         isurfl = gridsurf(d,z,y,x)
8107#endif
8108
8109      END SUBROUTINE request_itarget
8110
8111   END SUBROUTINE raytrace_2d
8112 
8113
8114!------------------------------------------------------------------------------!
8115!
8116! Description:
8117! ------------
8118!> Calculates apparent solar positions for all timesteps and stores discretized
8119!> positions.
8120!------------------------------------------------------------------------------!
8121   SUBROUTINE radiation_presimulate_solar_pos
8122
8123      IMPLICIT NONE
8124
8125      INTEGER(iwp)                              ::  it, i, j
8126      INTEGER(iwp)                              ::  day_of_month_prev,month_of_year_prev
8127      REAL(wp)                                  ::  tsrp_prev
8128      REAL(wp)                                  ::  simulated_time_prev
8129      REAL(wp), DIMENSION(:,:), ALLOCATABLE     ::  dsidir_tmp       !< dsidir_tmp[:,i] = unit vector of i-th
8130                                                                     !< appreant solar direction
8131
8132      ALLOCATE ( dsidir_rev(0:raytrace_discrete_elevs/2-1,                 &
8133                            0:raytrace_discrete_azims-1) )
8134      dsidir_rev(:,:) = -1
8135      ALLOCATE ( dsidir_tmp(3,                                             &
8136                     raytrace_discrete_elevs/2*raytrace_discrete_azims) )
8137      ndsidir = 0
8138
8139!
8140!--   We will artificialy update time_since_reference_point and return to
8141!--   true value later
8142      tsrp_prev = time_since_reference_point
8143      simulated_time_prev = simulated_time
8144      day_of_month_prev = day_of_month
8145      month_of_year_prev = month_of_year
8146      sun_direction = .TRUE.
8147
8148!
8149!--   Process spinup time if configured
8150      IF ( spinup_time > 0._wp )  THEN
8151         DO  it = 0, CEILING(spinup_time / dt_spinup)
8152            time_since_reference_point = -spinup_time + REAL(it, wp) * dt_spinup
8153            simulated_time = simulated_time + dt_spinup
8154            CALL simulate_pos
8155         ENDDO
8156      ENDIF
8157!
8158!--   Process simulation time
8159      DO  it = 0, CEILING(( end_time - spinup_time ) / dt_radiation)
8160         time_since_reference_point = REAL(it, wp) * dt_radiation
8161         simulated_time = simulated_time + dt_radiation
8162         CALL simulate_pos
8163      ENDDO
8164!
8165!--   Return date and time to its original values
8166      time_since_reference_point = tsrp_prev
8167      simulated_time = simulated_time_prev
8168      day_of_month = day_of_month_prev
8169      month_of_year = month_of_year_prev
8170      CALL init_date_and_time
8171
8172!--   Allocate global vars which depend on ndsidir
8173      ALLOCATE ( dsidir ( 3, ndsidir ) )
8174      dsidir(:,:) = dsidir_tmp(:, 1:ndsidir)
8175      DEALLOCATE ( dsidir_tmp )
8176
8177      ALLOCATE ( dsitrans(nsurfl, ndsidir) )
8178      ALLOCATE ( dsitransc(npcbl, ndsidir) )
8179      IF ( nmrtbl > 0 )  ALLOCATE ( mrtdsit(nmrtbl, ndsidir) )
8180
8181      WRITE ( message_string, * ) 'Precalculated', ndsidir, ' solar positions', &
8182                                  'from', it, ' timesteps.'
8183      CALL message( 'radiation_presimulate_solar_pos', 'UI0013', 0, 0, 0, 6, 0 )
8184
8185      CONTAINS
8186
8187      !------------------------------------------------------------------------!
8188      ! Description:
8189      ! ------------
8190      !> Simuates a single position
8191      !------------------------------------------------------------------------!
8192      SUBROUTINE simulate_pos
8193         IMPLICIT NONE
8194!
8195!--      Update apparent solar position based on modified t_s_r_p
8196         CALL calc_zenith
8197         IF ( zenith(0) > 0 )  THEN
8198!--         
8199!--         Identify solar direction vector (discretized number) 1)
8200            i = MODULO(NINT(ATAN2(sun_dir_lon(0), sun_dir_lat(0))               &
8201                            / (2._wp*pi) * raytrace_discrete_azims-.5_wp, iwp), &
8202                       raytrace_discrete_azims)
8203            j = FLOOR(ACOS(zenith(0)) / pi * raytrace_discrete_elevs)
8204            IF ( dsidir_rev(j, i) == -1 )  THEN
8205               ndsidir = ndsidir + 1
8206               dsidir_tmp(:, ndsidir) =                                              &
8207                     (/ COS((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs), &
8208                        SIN((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs)  &
8209                      * COS((REAL(i,wp)+.5_wp) * 2_wp*pi / raytrace_discrete_azims), &
8210                        SIN((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs)  &
8211                      * SIN((REAL(i,wp)+.5_wp) * 2_wp*pi / raytrace_discrete_azims) /)
8212               dsidir_rev(j, i) = ndsidir
8213            ENDIF
8214         ENDIF
8215      END SUBROUTINE simulate_pos
8216
8217   END SUBROUTINE radiation_presimulate_solar_pos
8218
8219
8220
8221!------------------------------------------------------------------------------!
8222! Description:
8223! ------------
8224!> Determines whether two faces are oriented towards each other. Since the
8225!> surfaces follow the gird box surfaces, it checks first whether the two surfaces
8226!> are directed in the same direction, then it checks if the two surfaces are
8227!> located in confronted direction but facing away from each other, e.g. <--| |-->
8228!------------------------------------------------------------------------------!
8229    PURE LOGICAL FUNCTION surface_facing(x, y, z, d, x2, y2, z2, d2)
8230        IMPLICIT NONE
8231        INTEGER(iwp),   INTENT(in)  :: x, y, z, d, x2, y2, z2, d2
8232     
8233        surface_facing = .FALSE.
8234
8235!-- first check: are the two surfaces directed in the same direction
8236        IF ( (d==iup_u  .OR.  d==iup_l )                             &
8237             .AND. (d2==iup_u  .OR. d2==iup_l) ) RETURN
8238        IF ( (d==isouth_u  .OR.  d==isouth_l ) &
8239             .AND.  (d2==isouth_u  .OR.  d2==isouth_l) ) RETURN
8240        IF ( (d==inorth_u  .OR.  d==inorth_l ) &
8241             .AND.  (d2==inorth_u  .OR.  d2==inorth_l) ) RETURN
8242        IF ( (d==iwest_u  .OR.  d==iwest_l )     &
8243             .AND.  (d2==iwest_u  .OR.  d2==iwest_l ) ) RETURN
8244        IF ( (d==ieast_u  .OR.  d==ieast_l )     &
8245             .AND.  (d2==ieast_u  .OR.  d2==ieast_l ) ) RETURN
8246
8247!-- second check: are surfaces facing away from each other
8248        SELECT CASE (d)
8249            CASE (iup_u, iup_l)                     !< upward facing surfaces
8250                IF ( z2 < z ) RETURN
8251            CASE (isouth_u, isouth_l)               !< southward facing surfaces
8252                IF ( y2 > y ) RETURN
8253            CASE (inorth_u, inorth_l)               !< northward facing surfaces
8254                IF ( y2 < y ) RETURN
8255            CASE (iwest_u, iwest_l)                 !< westward facing surfaces
8256                IF ( x2 > x ) RETURN
8257            CASE (ieast_u, ieast_l)                 !< eastward facing surfaces
8258                IF ( x2 < x ) RETURN
8259        END SELECT
8260
8261        SELECT CASE (d2)
8262            CASE (iup_u)                            !< ground, roof
8263                IF ( z < z2 ) RETURN
8264            CASE (isouth_u, isouth_l)               !< south facing
8265                IF ( y > y2 ) RETURN
8266            CASE (inorth_u, inorth_l)               !< north facing
8267                IF ( y < y2 ) RETURN
8268            CASE (iwest_u, iwest_l)                 !< west facing
8269                IF ( x > x2 ) RETURN
8270            CASE (ieast_u, ieast_l)                 !< east facing
8271                IF ( x < x2 ) RETURN
8272            CASE (-1)
8273                CONTINUE
8274        END SELECT
8275
8276        surface_facing = .TRUE.
8277       
8278    END FUNCTION surface_facing
8279
8280
8281!------------------------------------------------------------------------------!
8282!
8283! Description:
8284! ------------
8285!> Soubroutine reads svf and svfsurf data from saved file
8286!> SVF means sky view factors and CSF means canopy sink factors
8287!------------------------------------------------------------------------------!
8288    SUBROUTINE radiation_read_svf
8289
8290       IMPLICIT NONE
8291       
8292       CHARACTER(rad_version_len)   :: rad_version_field
8293       
8294       INTEGER(iwp)                 :: i
8295       INTEGER(iwp)                 :: ndsidir_from_file = 0
8296       INTEGER(iwp)                 :: npcbl_from_file = 0
8297       INTEGER(iwp)                 :: nsurfl_from_file = 0
8298       INTEGER(iwp)                 :: nmrtbl_from_file = 0
8299       
8300       DO  i = 0, io_blocks-1
8301          IF ( i == io_group )  THEN
8302
8303!
8304!--          numprocs_previous_run is only known in case of reading restart
8305!--          data. If a new initial run which reads svf data is started the
8306!--          following query will be skipped
8307             IF ( initializing_actions == 'read_restart_data' ) THEN
8308
8309                IF ( numprocs_previous_run /= numprocs ) THEN
8310                   WRITE( message_string, * ) 'A different number of ',        &
8311                                              'processors between the run ',   &
8312                                              'that has written the svf data ',&
8313                                              'and the one that will read it ',&
8314                                              'is not allowed' 
8315                   CALL message( 'check_open', 'PA0491', 1, 2, 0, 6, 0 )
8316                ENDIF
8317
8318             ENDIF
8319             
8320!
8321!--          Open binary file
8322             CALL check_open( 88 )
8323
8324!
8325!--          read and check version
8326             READ ( 88 ) rad_version_field
8327             IF ( TRIM(rad_version_field) /= TRIM(rad_version) )  THEN
8328                 WRITE( message_string, * ) 'Version of binary SVF file "',    &
8329                             TRIM(rad_version_field), '" does not match ',     &
8330                             'the version of model "', TRIM(rad_version), '"'
8331                 CALL message( 'radiation_read_svf', 'PA0482', 1, 2, 0, 6, 0 )
8332             ENDIF
8333             
8334!
8335!--          read nsvfl, ncsfl, nsurfl, nmrtf
8336             READ ( 88 ) nsvfl, ncsfl, nsurfl_from_file, npcbl_from_file,      &
8337                         ndsidir_from_file, nmrtbl_from_file, nmrtf
8338             
8339             IF ( nsvfl < 0  .OR.  ncsfl < 0 )  THEN
8340                 WRITE( message_string, * ) 'Wrong number of SVF or CSF'
8341                 CALL message( 'radiation_read_svf', 'PA0483', 1, 2, 0, 6, 0 )
8342             ELSE
8343                 WRITE(message_string,*) '    Number of SVF, CSF, and nsurfl ',&
8344                                         'to read', nsvfl, ncsfl,              &
8345                                         nsurfl_from_file
8346                 CALL location_message( message_string, .TRUE. )
8347             ENDIF
8348             
8349             IF ( nsurfl_from_file /= nsurfl )  THEN
8350                 WRITE( message_string, * ) 'nsurfl from SVF file does not ',  &
8351                                            'match calculated nsurfl from ',   &
8352                                            'radiation_interaction_init'
8353                 CALL message( 'radiation_read_svf', 'PA0490', 1, 2, 0, 6, 0 )
8354             ENDIF
8355             
8356             IF ( npcbl_from_file /= npcbl )  THEN
8357                 WRITE( message_string, * ) 'npcbl from SVF file does not ',   &
8358                                            'match calculated npcbl from ',    &
8359                                            'radiation_interaction_init'
8360                 CALL message( 'radiation_read_svf', 'PA0493', 1, 2, 0, 6, 0 )
8361             ENDIF
8362             
8363             IF ( ndsidir_from_file /= ndsidir )  THEN
8364                 WRITE( message_string, * ) 'ndsidir from SVF file does not ', &
8365                                            'match calculated ndsidir from ',  &
8366                                            'radiation_presimulate_solar_pos'
8367                 CALL message( 'radiation_read_svf', 'PA0494', 1, 2, 0, 6, 0 )
8368             ENDIF
8369             IF ( nmrtbl_from_file /= nmrtbl )  THEN
8370                 WRITE( message_string, * ) 'nmrtbl from SVF file does not ',  &
8371                                            'match calculated nmrtbl from ',   &
8372                                            'radiation_interaction_init'
8373                 CALL message( 'radiation_read_svf', 'PA0494', 1, 2, 0, 6, 0 )
8374             ELSE
8375                 WRITE(message_string,*) '    Number of nmrtf to read ', nmrtf
8376                 CALL location_message( message_string, .TRUE. )
8377             ENDIF
8378             
8379!
8380!--          Arrays skyvf, skyvft, dsitrans and dsitransc are allready
8381!--          allocated in radiation_interaction_init and
8382!--          radiation_presimulate_solar_pos
8383             IF ( nsurfl > 0 )  THEN
8384                READ(88) skyvf
8385                READ(88) skyvft
8386                READ(88) dsitrans 
8387             ENDIF
8388             
8389             IF ( plant_canopy  .AND.  npcbl > 0 ) THEN
8390                READ ( 88 )  dsitransc
8391             ENDIF
8392             
8393!
8394!--          The allocation of svf, svfsurf, csf, csfsurf, mrtf, mrtft, and
8395!--          mrtfsurf happens in routine radiation_calc_svf which is not
8396!--          called if the program enters radiation_read_svf. Therefore
8397!--          these arrays has to allocate in the following
8398             IF ( nsvfl > 0 )  THEN
8399                ALLOCATE( svf(ndsvf,nsvfl) )
8400                ALLOCATE( svfsurf(idsvf,nsvfl) )
8401                READ(88) svf
8402                READ(88) svfsurf
8403             ENDIF
8404
8405             IF ( plant_canopy  .AND.  ncsfl > 0 )  THEN
8406                ALLOCATE( csf(ndcsf,ncsfl) )
8407                ALLOCATE( csfsurf(idcsf,ncsfl) )
8408                READ(88) csf
8409                READ(88) csfsurf
8410             ENDIF
8411
8412             IF ( nmrtbl > 0 )  THEN
8413                ALLOCATE ( mrtf(nmrtf) )
8414                ALLOCATE ( mrtft(nmrtf) )
8415                ALLOCATE ( mrtfsurf(2,nmrtf) )
8416                READ(88) mrtf
8417                READ(88) mrtft
8418                READ(88) mrtfsurf
8419             ENDIF
8420             
8421!
8422!--          Close binary file                 
8423             CALL close_file( 88 )
8424               
8425          ENDIF
8426#if defined( __parallel )
8427          CALL MPI_BARRIER( comm2d, ierr )
8428#endif
8429       ENDDO
8430
8431    END SUBROUTINE radiation_read_svf
8432
8433
8434!------------------------------------------------------------------------------!
8435!
8436! Description:
8437! ------------
8438!> Subroutine stores svf, svfsurf, csf and csfsurf data to a file.
8439!------------------------------------------------------------------------------!
8440    SUBROUTINE radiation_write_svf
8441
8442       IMPLICIT NONE
8443       
8444       INTEGER(iwp)        :: i
8445
8446       DO  i = 0, io_blocks-1
8447          IF ( i == io_group )  THEN
8448!
8449!--          Open binary file
8450             CALL check_open( 89 )
8451
8452             WRITE ( 89 )  rad_version
8453             WRITE ( 89 )  nsvfl, ncsfl, nsurfl, npcbl, ndsidir, nmrtbl, nmrtf
8454             IF ( nsurfl > 0 ) THEN
8455                WRITE ( 89 )  skyvf
8456                WRITE ( 89 )  skyvft
8457                WRITE ( 89 )  dsitrans
8458             ENDIF
8459             IF ( npcbl > 0 ) THEN
8460                WRITE ( 89 )  dsitransc
8461             ENDIF
8462             IF ( nsvfl > 0 ) THEN
8463                WRITE ( 89 )  svf
8464                WRITE ( 89 )  svfsurf
8465             ENDIF
8466             IF ( plant_canopy  .AND.  ncsfl > 0 )  THEN
8467                 WRITE ( 89 )  csf
8468                 WRITE ( 89 )  csfsurf
8469             ENDIF
8470             IF ( nmrtbl > 0 )  THEN
8471                 WRITE ( 89 )  mrtf
8472                 WRITE ( 89 )  mrtft               
8473                 WRITE ( 89 )  mrtfsurf
8474             ENDIF
8475!
8476!--          Close binary file                 
8477             CALL close_file( 89 )
8478
8479          ENDIF
8480#if defined( __parallel )
8481          CALL MPI_BARRIER( comm2d, ierr )
8482#endif
8483       ENDDO
8484    END SUBROUTINE radiation_write_svf
8485
8486!------------------------------------------------------------------------------!
8487!
8488! Description:
8489! ------------
8490!> Block of auxiliary subroutines:
8491!> 1. quicksort and corresponding comparison
8492!> 2. merge_and_grow_csf for implementation of "dynamical growing"
8493!>    array for csf
8494!------------------------------------------------------------------------------!
8495!-- quicksort.f -*-f90-*-
8496!-- Author: t-nissie, adaptation J.Resler
8497!-- License: GPLv3
8498!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8499    RECURSIVE SUBROUTINE quicksort_itarget(itarget, vffrac, ztransp, first, last)
8500        IMPLICIT NONE
8501        INTEGER(iwp), DIMENSION(:), INTENT(INOUT)   :: itarget
8502        REAL(wp), DIMENSION(:), INTENT(INOUT)       :: vffrac, ztransp
8503        INTEGER(iwp), INTENT(IN)                    :: first, last
8504        INTEGER(iwp)                                :: x, t
8505        INTEGER(iwp)                                :: i, j
8506        REAL(wp)                                    :: tr
8507
8508        IF ( first>=last ) RETURN
8509        x = itarget((first+last)/2)
8510        i = first
8511        j = last
8512        DO
8513            DO WHILE ( itarget(i) < x )
8514               i=i+1
8515            ENDDO
8516            DO WHILE ( x < itarget(j) )
8517                j=j-1
8518            ENDDO
8519            IF ( i >= j ) EXIT
8520            t = itarget(i);  itarget(i) = itarget(j);  itarget(j) = t
8521            tr = vffrac(i);  vffrac(i) = vffrac(j);  vffrac(j) = tr
8522            tr = ztransp(i);  ztransp(i) = ztransp(j);  ztransp(j) = tr
8523            i=i+1
8524            j=j-1
8525        ENDDO
8526        IF ( first < i-1 ) CALL quicksort_itarget(itarget, vffrac, ztransp, first, i-1)
8527        IF ( j+1 < last )  CALL quicksort_itarget(itarget, vffrac, ztransp, j+1, last)
8528    END SUBROUTINE quicksort_itarget
8529
8530    PURE FUNCTION svf_lt(svf1,svf2) result (res)
8531      TYPE (t_svf), INTENT(in) :: svf1,svf2
8532      LOGICAL                  :: res
8533      IF ( svf1%isurflt < svf2%isurflt  .OR.    &
8534          (svf1%isurflt == svf2%isurflt  .AND.  svf1%isurfs < svf2%isurfs) )  THEN
8535          res = .TRUE.
8536      ELSE
8537          res = .FALSE.
8538      ENDIF
8539    END FUNCTION svf_lt
8540
8541
8542!-- quicksort.f -*-f90-*-
8543!-- Author: t-nissie, adaptation J.Resler
8544!-- License: GPLv3
8545!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8546    RECURSIVE SUBROUTINE quicksort_svf(svfl, first, last)
8547        IMPLICIT NONE
8548        TYPE(t_svf), DIMENSION(:), INTENT(INOUT)  :: svfl
8549        INTEGER(iwp), INTENT(IN)                  :: first, last
8550        TYPE(t_svf)                               :: x, t
8551        INTEGER(iwp)                              :: i, j
8552
8553        IF ( first>=last ) RETURN
8554        x = svfl( (first+last) / 2 )
8555        i = first
8556        j = last
8557        DO
8558            DO while ( svf_lt(svfl(i),x) )
8559               i=i+1
8560            ENDDO
8561            DO while ( svf_lt(x,svfl(j)) )
8562                j=j-1
8563            ENDDO
8564            IF ( i >= j ) EXIT
8565            t = svfl(i);  svfl(i) = svfl(j);  svfl(j) = t
8566            i=i+1
8567            j=j-1
8568        ENDDO
8569        IF ( first < i-1 ) CALL quicksort_svf(svfl, first, i-1)
8570        IF ( j+1 < last )  CALL quicksort_svf(svfl, j+1, last)
8571    END SUBROUTINE quicksort_svf
8572
8573    PURE FUNCTION csf_lt(csf1,csf2) result (res)
8574      TYPE (t_csf), INTENT(in) :: csf1,csf2
8575      LOGICAL                  :: res
8576      IF ( csf1%ip < csf2%ip  .OR.    &
8577           (csf1%ip == csf2%ip  .AND.  csf1%itx < csf2%itx)  .OR.  &
8578           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity < csf2%ity)  .OR.  &
8579           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity == csf2%ity  .AND.   &
8580            csf1%itz < csf2%itz)  .OR.  &
8581           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity == csf2%ity  .AND.   &
8582            csf1%itz == csf2%itz  .AND.  csf1%isurfs < csf2%isurfs) )  THEN
8583          res = .TRUE.
8584      ELSE
8585          res = .FALSE.
8586      ENDIF
8587    END FUNCTION csf_lt
8588
8589
8590!-- quicksort.f -*-f90-*-
8591!-- Author: t-nissie, adaptation J.Resler
8592!-- License: GPLv3
8593!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8594    RECURSIVE SUBROUTINE quicksort_csf(csfl, first, last)
8595        IMPLICIT NONE
8596        TYPE(t_csf), DIMENSION(:), INTENT(INOUT)  :: csfl
8597        INTEGER(iwp), INTENT(IN)                  :: first, last
8598        TYPE(t_csf)                               :: x, t
8599        INTEGER(iwp)                              :: i, j
8600
8601        IF ( first>=last ) RETURN
8602        x = csfl( (first+last)/2 )
8603        i = first
8604        j = last
8605        DO
8606            DO while ( csf_lt(csfl(i),x) )
8607                i=i+1
8608            ENDDO
8609            DO while ( csf_lt(x,csfl(j)) )
8610                j=j-1
8611            ENDDO
8612            IF ( i >= j ) EXIT
8613            t = csfl(i);  csfl(i) = csfl(j);  csfl(j) = t
8614            i=i+1
8615            j=j-1
8616        ENDDO
8617        IF ( first < i-1 ) CALL quicksort_csf(csfl, first, i-1)
8618        IF ( j+1 < last )  CALL quicksort_csf(csfl, j+1, last)
8619    END SUBROUTINE quicksort_csf
8620
8621   
8622    SUBROUTINE merge_and_grow_csf(newsize)
8623        INTEGER(iwp), INTENT(in)                :: newsize  !< new array size after grow, must be >= ncsfl
8624                                                            !< or -1 to shrink to minimum
8625        INTEGER(iwp)                            :: iread, iwrite
8626        TYPE(t_csf), DIMENSION(:), POINTER      :: acsfnew
8627        CHARACTER(100)                          :: msg
8628
8629        IF ( newsize == -1 )  THEN
8630!--         merge in-place
8631            acsfnew => acsf
8632        ELSE
8633!--         allocate new array
8634            IF ( mcsf == 0 )  THEN
8635                ALLOCATE( acsf1(newsize) )
8636                acsfnew => acsf1
8637            ELSE
8638                ALLOCATE( acsf2(newsize) )
8639                acsfnew => acsf2
8640            ENDIF
8641        ENDIF
8642
8643        IF ( ncsfl >= 1 )  THEN
8644!--         sort csf in place (quicksort)
8645            CALL quicksort_csf(acsf,1,ncsfl)
8646
8647!--         while moving to a new array, aggregate canopy sink factor records with identical box & source
8648            acsfnew(1) = acsf(1)
8649            iwrite = 1
8650            DO iread = 2, ncsfl
8651!--             here acsf(kcsf) already has values from acsf(icsf)
8652                IF ( acsfnew(iwrite)%itx == acsf(iread)%itx &
8653                         .AND.  acsfnew(iwrite)%ity == acsf(iread)%ity &
8654                         .AND.  acsfnew(iwrite)%itz == acsf(iread)%itz &
8655                         .AND.  acsfnew(iwrite)%isurfs == acsf(iread)%isurfs )  THEN
8656
8657                    acsfnew(iwrite)%rcvf = acsfnew(iwrite)%rcvf + acsf(iread)%rcvf
8658!--                 advance reading index, keep writing index
8659                ELSE
8660!--                 not identical, just advance and copy
8661                    iwrite = iwrite + 1
8662                    acsfnew(iwrite) = acsf(iread)
8663                ENDIF
8664            ENDDO
8665            ncsfl = iwrite
8666        ENDIF
8667
8668        IF ( newsize == -1 )  THEN
8669!--         allocate new array and copy shrinked data
8670            IF ( mcsf == 0 )  THEN
8671                ALLOCATE( acsf1(ncsfl) )
8672                acsf1(1:ncsfl) = acsf2(1:ncsfl)
8673            ELSE
8674                ALLOCATE( acsf2(ncsfl) )
8675                acsf2(1:ncsfl) = acsf1(1:ncsfl)
8676            ENDIF
8677        ENDIF
8678
8679!--     deallocate old array
8680        IF ( mcsf == 0 )  THEN
8681            mcsf = 1
8682            acsf => acsf1
8683            DEALLOCATE( acsf2 )
8684        ELSE
8685            mcsf = 0
8686            acsf => acsf2
8687            DEALLOCATE( acsf1 )
8688        ENDIF
8689        ncsfla = newsize
8690
8691        WRITE(msg,'(A,2I12)') 'Grow acsf2:',ncsfl,ncsfla
8692        CALL radiation_write_debug_log( msg )
8693
8694    END SUBROUTINE merge_and_grow_csf
8695
8696   
8697!-- quicksort.f -*-f90-*-
8698!-- Author: t-nissie, adaptation J.Resler
8699!-- License: GPLv3
8700!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8701    RECURSIVE SUBROUTINE quicksort_csf2(kpcsflt, pcsflt, first, last)
8702        IMPLICIT NONE
8703        INTEGER(iwp), DIMENSION(:,:), INTENT(INOUT)  :: kpcsflt
8704        REAL(wp), DIMENSION(:,:), INTENT(INOUT)      :: pcsflt
8705        INTEGER(iwp), INTENT(IN)                     :: first, last
8706        REAL(wp), DIMENSION(ndcsf)                   :: t2
8707        INTEGER(iwp), DIMENSION(kdcsf)               :: x, t1
8708        INTEGER(iwp)                                 :: i, j
8709
8710        IF ( first>=last ) RETURN
8711        x = kpcsflt(:, (first+last)/2 )
8712        i = first
8713        j = last
8714        DO
8715            DO while ( csf_lt2(kpcsflt(:,i),x) )
8716                i=i+1
8717            ENDDO
8718            DO while ( csf_lt2(x,kpcsflt(:,j)) )
8719                j=j-1
8720            ENDDO
8721            IF ( i >= j ) EXIT
8722            t1 = kpcsflt(:,i);  kpcsflt(:,i) = kpcsflt(:,j);  kpcsflt(:,j) = t1
8723            t2 = pcsflt(:,i);  pcsflt(:,i) = pcsflt(:,j);  pcsflt(:,j) = t2
8724            i=i+1
8725            j=j-1
8726        ENDDO
8727        IF ( first < i-1 ) CALL quicksort_csf2(kpcsflt, pcsflt, first, i-1)
8728        IF ( j+1 < last )  CALL quicksort_csf2(kpcsflt, pcsflt, j+1, last)
8729    END SUBROUTINE quicksort_csf2
8730   
8731
8732    PURE FUNCTION csf_lt2(item1, item2) result(res)
8733        INTEGER(iwp), DIMENSION(kdcsf), INTENT(in)  :: item1, item2
8734        LOGICAL                                     :: res
8735        res = ( (item1(3) < item2(3))                                                        &
8736             .OR.  (item1(3) == item2(3)  .AND.  item1(2) < item2(2))                            &
8737             .OR.  (item1(3) == item2(3)  .AND.  item1(2) == item2(2)  .AND.  item1(1) < item2(1)) &
8738             .OR.  (item1(3) == item2(3)  .AND.  item1(2) == item2(2)  .AND.  item1(1) == item2(1) &
8739                 .AND.  item1(4) < item2(4)) )
8740    END FUNCTION csf_lt2
8741
8742    PURE FUNCTION searchsorted(athresh, val) result(ind)
8743        REAL(wp), DIMENSION(:), INTENT(IN)  :: athresh
8744        REAL(wp), INTENT(IN)                :: val
8745        INTEGER(iwp)                        :: ind
8746        INTEGER(iwp)                        :: i
8747
8748        DO i = LBOUND(athresh, 1), UBOUND(athresh, 1)
8749            IF ( val < athresh(i) ) THEN
8750                ind = i - 1
8751                RETURN
8752            ENDIF
8753        ENDDO
8754        ind = UBOUND(athresh, 1)
8755    END FUNCTION searchsorted
8756
8757!------------------------------------------------------------------------------!
8758! Description:
8759! ------------
8760!
8761!> radiation_radflux_gridbox subroutine gives the sw and lw radiation fluxes at the
8762!> faces of a gridbox defined at i,j,k and located in the urban layer.
8763!> The total sw and the diffuse sw radiation as well as the lw radiation fluxes at
8764!> the gridbox 6 faces are stored in sw_gridbox, swd_gridbox, and lw_gridbox arrays,
8765!> respectively, in the following order:
8766!>  up_face, down_face, north_face, south_face, east_face, west_face
8767!>
8768!> The subroutine reports also how successful was the search process via the parameter
8769!> i_feedback as follow:
8770!> - i_feedback =  1 : successful
8771!> - i_feedback = -1 : unsuccessful; the requisted point is outside the urban domain
8772!> - i_feedback =  0 : uncomplete; some gridbox faces fluxes are missing
8773!>
8774!>
8775!> It is called outside from usm_urban_surface_mod whenever the radiation fluxes
8776!> are needed.
8777!>
8778!> This routine is not used so far. However, it may serve as an interface for radiation
8779!> fluxes of urban and land surfaces
8780!>
8781!> TODO:
8782!>    - Compare performance when using some combination of the Fortran intrinsic
8783!>      functions, e.g. MINLOC, MAXLOC, ALL, ANY and COUNT functions, which search
8784!>      surfl array for elements meeting user-specified criterion, i.e. i,j,k
8785!>    - Report non-found or incomplete radiation fluxes arrays , if any, at the
8786!>      gridbox faces in an error message form
8787!>
8788!------------------------------------------------------------------------------!
8789    SUBROUTINE radiation_radflux_gridbox(i,j,k,sw_gridbox,swd_gridbox,lw_gridbox,i_feedback)
8790       
8791        IMPLICIT NONE
8792
8793        INTEGER(iwp),                 INTENT(in)  :: i,j,k                 !< gridbox indices at which fluxes are required
8794        INTEGER(iwp)                              :: ii,jj,kk,d            !< surface indices and type
8795        INTEGER(iwp)                              :: l                     !< surface id
8796        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
8797        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
8798        INTEGER(iwp),                 INTENT(out) :: i_feedback            !< feedback to report how the search was successful
8799
8800
8801!-- initialize variables
8802        i_feedback  = -999999
8803        sw_gridbox  = -999999.9_wp
8804        lw_gridbox  = -999999.9_wp
8805        swd_gridbox = -999999.9_wp
8806       
8807!-- check the requisted grid indices
8808        IF ( k < nzb   .OR.  k > nzut  .OR.   &
8809             j < nysg  .OR.  j > nyng  .OR.   &
8810             i < nxlg  .OR.  i > nxrg         &
8811             ) THEN
8812           i_feedback = -1
8813           RETURN
8814        ENDIF
8815
8816!-- search for the required grid and formulate the fluxes at the 6 gridbox faces
8817        DO l = 1, nsurfl
8818            ii = surfl(ix,l)
8819            jj = surfl(iy,l)
8820            kk = surfl(iz,l)
8821
8822            IF ( ii == i  .AND.  jj == j  .AND.  kk == k ) THEN
8823               d = surfl(id,l)
8824
8825               SELECT CASE ( d )
8826
8827               CASE (iup_u,iup_l)                          !- gridbox up_facing face
8828                  sw_gridbox(1) = surfinsw(l)
8829                  lw_gridbox(1) = surfinlw(l)
8830                  swd_gridbox(1) = surfinswdif(l)
8831
8832               CASE (inorth_u,inorth_l)                    !- gridbox north_facing face
8833                  sw_gridbox(3) = surfinsw(l)
8834                  lw_gridbox(3) = surfinlw(l)
8835                  swd_gridbox(3) = surfinswdif(l)
8836
8837               CASE (isouth_u,isouth_l)                    !- gridbox south_facing face
8838                  sw_gridbox(4) = surfinsw(l)
8839                  lw_gridbox(4) = surfinlw(l)
8840                  swd_gridbox(4) = surfinswdif(l)
8841
8842               CASE (ieast_u,ieast_l)                      !- gridbox east_facing face
8843                  sw_gridbox(5) = surfinsw(l)
8844                  lw_gridbox(5) = surfinlw(l)
8845                  swd_gridbox(5) = surfinswdif(l)
8846
8847               CASE (iwest_u,iwest_l)                      !- gridbox west_facing face
8848                  sw_gridbox(6) = surfinsw(l)
8849                  lw_gridbox(6) = surfinlw(l)
8850                  swd_gridbox(6) = surfinswdif(l)
8851
8852               END SELECT
8853
8854            ENDIF
8855
8856        IF ( ALL( sw_gridbox(:)  /= -999999.9_wp )  ) EXIT
8857        ENDDO
8858
8859!-- check the completeness of the fluxes at all gidbox faces       
8860!-- TODO: report non-found or incomplete rad fluxes arrays in an error message form
8861        IF ( ANY( sw_gridbox(:)  <= -999999.9_wp )  .OR.   &
8862             ANY( swd_gridbox(:) <= -999999.9_wp )  .OR.   &
8863             ANY( lw_gridbox(:)  <= -999999.9_wp ) ) THEN
8864           i_feedback = 0
8865        ELSE
8866           i_feedback = 1
8867        ENDIF
8868       
8869        RETURN
8870       
8871    END SUBROUTINE radiation_radflux_gridbox
8872
8873!------------------------------------------------------------------------------!
8874!
8875! Description:
8876! ------------
8877!> Subroutine for averaging 3D data
8878!------------------------------------------------------------------------------!
8879SUBROUTINE radiation_3d_data_averaging( mode, variable )
8880 
8881
8882    USE control_parameters
8883
8884    USE indices
8885
8886    USE kinds
8887
8888    IMPLICIT NONE
8889
8890    CHARACTER (LEN=*) ::  mode    !<
8891    CHARACTER (LEN=*) :: variable !<
8892
8893    LOGICAL      ::  match_lsm !< flag indicating natural-type surface
8894    LOGICAL      ::  match_usm !< flag indicating urban-type surface
8895   
8896    INTEGER(iwp) ::  i !<
8897    INTEGER(iwp) ::  j !<
8898    INTEGER(iwp) ::  k !<
8899    INTEGER(iwp) ::  l, m !< index of current surface element
8900
8901    INTEGER(iwp)                                       :: ids, idsint_u, idsint_l, isurf
8902    CHARACTER(LEN=varnamelength)                       :: var
8903
8904!-- find the real name of the variable
8905    ids = -1
8906    l = -1
8907    var = TRIM(variable)
8908    DO i = 0, nd-1
8909        k = len(TRIM(var))
8910        j = len(TRIM(dirname(i)))
8911        IF ( k-j+1 >= 1_iwp ) THEN
8912           IF ( TRIM(var(k-j+1:k)) == TRIM(dirname(i)) )  THEN
8913               ids = i
8914               idsint_u = dirint_u(ids)
8915               idsint_l = dirint_l(ids)
8916               var = var(:k-j)
8917               EXIT
8918           ENDIF
8919        ENDIF
8920    ENDDO
8921    IF ( ids == -1 )  THEN
8922        var = TRIM(variable)
8923    ENDIF
8924
8925    IF ( mode == 'allocate' )  THEN
8926
8927       SELECT CASE ( TRIM( var ) )
8928!--          block of large scale (e.g. RRTMG) radiation output variables
8929             CASE ( 'rad_net*' )
8930                IF ( .NOT. ALLOCATED( rad_net_av ) )  THEN
8931                   ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
8932                ENDIF
8933                rad_net_av = 0.0_wp
8934             
8935             CASE ( 'rad_lw_in*' )
8936                IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) )  THEN
8937                   ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
8938                ENDIF
8939                rad_lw_in_xy_av = 0.0_wp
8940               
8941             CASE ( 'rad_lw_out*' )
8942                IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) )  THEN
8943                   ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
8944                ENDIF
8945                rad_lw_out_xy_av = 0.0_wp
8946               
8947             CASE ( 'rad_sw_in*' )
8948                IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) )  THEN
8949                   ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
8950                ENDIF
8951                rad_sw_in_xy_av = 0.0_wp
8952               
8953             CASE ( 'rad_sw_out*' )
8954                IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) )  THEN
8955                   ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
8956                ENDIF
8957                rad_sw_out_xy_av = 0.0_wp               
8958
8959             CASE ( 'rad_lw_in' )
8960                IF ( .NOT. ALLOCATED( rad_lw_in_av ) )  THEN
8961                   ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8962                ENDIF
8963                rad_lw_in_av = 0.0_wp
8964
8965             CASE ( 'rad_lw_out' )
8966                IF ( .NOT. ALLOCATED( rad_lw_out_av ) )  THEN
8967                   ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8968                ENDIF
8969                rad_lw_out_av = 0.0_wp
8970
8971             CASE ( 'rad_lw_cs_hr' )
8972                IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) )  THEN
8973                   ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8974                ENDIF
8975                rad_lw_cs_hr_av = 0.0_wp
8976
8977             CASE ( 'rad_lw_hr' )
8978                IF ( .NOT. ALLOCATED( rad_lw_hr_av ) )  THEN
8979                   ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8980                ENDIF
8981                rad_lw_hr_av = 0.0_wp
8982
8983             CASE ( 'rad_sw_in' )
8984                IF ( .NOT. ALLOCATED( rad_sw_in_av ) )  THEN
8985                   ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8986                ENDIF
8987                rad_sw_in_av = 0.0_wp
8988
8989             CASE ( 'rad_sw_out' )
8990                IF ( .NOT. ALLOCATED( rad_sw_out_av ) )  THEN
8991                   ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8992                ENDIF
8993                rad_sw_out_av = 0.0_wp
8994
8995             CASE ( 'rad_sw_cs_hr' )
8996                IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) )  THEN
8997                   ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8998                ENDIF
8999                rad_sw_cs_hr_av = 0.0_wp
9000
9001             CASE ( 'rad_sw_hr' )
9002                IF ( .NOT. ALLOCATED( rad_sw_hr_av ) )  THEN
9003                   ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9004                ENDIF
9005                rad_sw_hr_av = 0.0_wp
9006
9007!--          block of RTM output variables
9008             CASE ( 'rtm_rad_net' )
9009!--              array of complete radiation balance
9010                 IF ( .NOT.  ALLOCATED(surfradnet_av) )  THEN
9011                     ALLOCATE( surfradnet_av(nsurfl) )
9012                     surfradnet_av = 0.0_wp
9013                 ENDIF
9014
9015             CASE ( 'rtm_rad_insw' )
9016!--                 array of sw radiation falling to surface after i-th reflection
9017                 IF ( .NOT.  ALLOCATED(surfinsw_av) )  THEN
9018                     ALLOCATE( surfinsw_av(nsurfl) )
9019                     surfinsw_av = 0.0_wp
9020                 ENDIF
9021
9022             CASE ( 'rtm_rad_inlw' )
9023!--                 array of lw radiation falling to surface after i-th reflection
9024                 IF ( .NOT.  ALLOCATED(surfinlw_av) )  THEN
9025                     ALLOCATE( surfinlw_av(nsurfl) )
9026                     surfinlw_av = 0.0_wp
9027                 ENDIF
9028
9029             CASE ( 'rtm_rad_inswdir' )
9030!--                 array of direct sw radiation falling to surface from sun
9031                 IF ( .NOT.  ALLOCATED(surfinswdir_av) )  THEN
9032                     ALLOCATE( surfinswdir_av(nsurfl) )
9033                     surfinswdir_av = 0.0_wp
9034                 ENDIF
9035
9036             CASE ( 'rtm_rad_inswdif' )
9037!--                 array of difusion sw radiation falling to surface from sky and borders of the domain
9038                 IF ( .NOT.  ALLOCATED(surfinswdif_av) )  THEN
9039                     ALLOCATE( surfinswdif_av(nsurfl) )
9040                     surfinswdif_av = 0.0_wp
9041                 ENDIF
9042
9043             CASE ( 'rtm_rad_inswref' )
9044!--                 array of sw radiation falling to surface from reflections
9045                 IF ( .NOT.  ALLOCATED(surfinswref_av) )  THEN
9046                     ALLOCATE( surfinswref_av(nsurfl) )
9047                     surfinswref_av = 0.0_wp
9048                 ENDIF
9049
9050             CASE ( 'rtm_rad_inlwdif' )
9051!--                 array of sw radiation falling to surface after i-th reflection
9052                IF ( .NOT.  ALLOCATED(surfinlwdif_av) )  THEN
9053                     ALLOCATE( surfinlwdif_av(nsurfl) )
9054                     surfinlwdif_av = 0.0_wp
9055                 ENDIF
9056
9057             CASE ( 'rtm_rad_inlwref' )
9058!--                 array of lw radiation falling to surface from reflections
9059                 IF ( .NOT.  ALLOCATED(surfinlwref_av) )  THEN
9060                     ALLOCATE( surfinlwref_av(nsurfl) )
9061                     surfinlwref_av = 0.0_wp
9062                 ENDIF
9063
9064             CASE ( 'rtm_rad_outsw' )
9065!--                 array of sw radiation emitted from surface after i-th reflection
9066                 IF ( .NOT.  ALLOCATED(surfoutsw_av) )  THEN
9067                     ALLOCATE( surfoutsw_av(nsurfl) )
9068                     surfoutsw_av = 0.0_wp
9069                 ENDIF
9070
9071             CASE ( 'rtm_rad_outlw' )
9072!--                 array of lw radiation emitted from surface after i-th reflection
9073                 IF ( .NOT.  ALLOCATED(surfoutlw_av) )  THEN
9074                     ALLOCATE( surfoutlw_av(nsurfl) )
9075                     surfoutlw_av = 0.0_wp
9076                 ENDIF
9077             CASE ( 'rtm_rad_ressw' )
9078!--                 array of residua of sw radiation absorbed in surface after last reflection
9079                 IF ( .NOT.  ALLOCATED(surfins_av) )  THEN
9080                     ALLOCATE( surfins_av(nsurfl) )
9081                     surfins_av = 0.0_wp
9082                 ENDIF
9083
9084             CASE ( 'rtm_rad_reslw' )
9085!--                 array of residua of lw radiation absorbed in surface after last reflection
9086                 IF ( .NOT.  ALLOCATED(surfinl_av) )  THEN
9087                     ALLOCATE( surfinl_av(nsurfl) )
9088                     surfinl_av = 0.0_wp
9089                 ENDIF
9090
9091             CASE ( 'rtm_rad_pc_inlw' )
9092!--                 array of of lw radiation absorbed in plant canopy
9093                 IF ( .NOT.  ALLOCATED(pcbinlw_av) )  THEN
9094                     ALLOCATE( pcbinlw_av(1:npcbl) )
9095                     pcbinlw_av = 0.0_wp
9096                 ENDIF
9097
9098             CASE ( 'rtm_rad_pc_insw' )
9099!--                 array of of sw radiation absorbed in plant canopy
9100                 IF ( .NOT.  ALLOCATED(pcbinsw_av) )  THEN
9101                     ALLOCATE( pcbinsw_av(1:npcbl) )
9102                     pcbinsw_av = 0.0_wp
9103                 ENDIF
9104
9105             CASE ( 'rtm_rad_pc_inswdir' )
9106!--                 array of of direct sw radiation absorbed in plant canopy
9107                 IF ( .NOT.  ALLOCATED(pcbinswdir_av) )  THEN
9108                     ALLOCATE( pcbinswdir_av(1:npcbl) )
9109                     pcbinswdir_av = 0.0_wp
9110                 ENDIF
9111
9112             CASE ( 'rtm_rad_pc_inswdif' )
9113!--                 array of of diffuse sw radiation absorbed in plant canopy
9114                 IF ( .NOT.  ALLOCATED(pcbinswdif_av) )  THEN
9115                     ALLOCATE( pcbinswdif_av(1:npcbl) )
9116                     pcbinswdif_av = 0.0_wp
9117                 ENDIF
9118
9119             CASE ( 'rtm_rad_pc_inswref' )
9120!--                 array of of reflected sw radiation absorbed in plant canopy
9121                 IF ( .NOT.  ALLOCATED(pcbinswref_av) )  THEN
9122                     ALLOCATE( pcbinswref_av(1:npcbl) )
9123                     pcbinswref_av = 0.0_wp
9124                 ENDIF
9125
9126             CASE ( 'rtm_mrt_sw' )
9127                IF ( .NOT. ALLOCATED( mrtinsw_av ) )  THEN
9128                   ALLOCATE( mrtinsw_av(nmrtbl) )
9129                ENDIF
9130                mrtinsw_av = 0.0_wp
9131
9132             CASE ( 'rtm_mrt_lw' )
9133                IF ( .NOT. ALLOCATED( mrtinlw_av ) )  THEN
9134                   ALLOCATE( mrtinlw_av(nmrtbl) )
9135                ENDIF
9136                mrtinlw_av = 0.0_wp
9137
9138             CASE ( 'rtm_mrt' )
9139                IF ( .NOT. ALLOCATED( mrt_av ) )  THEN
9140                   ALLOCATE( mrt_av(nmrtbl) )
9141                ENDIF
9142                mrt_av = 0.0_wp
9143
9144          CASE DEFAULT
9145             CONTINUE
9146
9147       END SELECT
9148
9149    ELSEIF ( mode == 'sum' )  THEN
9150
9151       SELECT CASE ( TRIM( var ) )
9152!--       block of large scale (e.g. RRTMG) radiation output variables
9153          CASE ( 'rad_net*' )
9154             IF ( ALLOCATED( rad_net_av ) ) THEN
9155                DO  i = nxl, nxr
9156                   DO  j = nys, nyn
9157                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9158                                  surf_lsm_h%end_index(j,i)
9159                      match_usm = surf_usm_h%start_index(j,i) <=               &
9160                                  surf_usm_h%end_index(j,i)
9161
9162                     IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9163                         m = surf_lsm_h%end_index(j,i)
9164                         rad_net_av(j,i) = rad_net_av(j,i) +                   &
9165                                         surf_lsm_h%rad_net(m)
9166                      ELSEIF ( match_usm )  THEN
9167                         m = surf_usm_h%end_index(j,i)
9168                         rad_net_av(j,i) = rad_net_av(j,i) +                   &
9169                                         surf_usm_h%rad_net(m)
9170                      ENDIF
9171                   ENDDO
9172                ENDDO
9173             ENDIF
9174
9175          CASE ( 'rad_lw_in*' )
9176             IF ( ALLOCATED( rad_lw_in_xy_av ) ) THEN
9177                DO  i = nxl, nxr
9178                   DO  j = nys, nyn
9179                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9180                                  surf_lsm_h%end_index(j,i)
9181                      match_usm = surf_usm_h%start_index(j,i) <=               &
9182                                  surf_usm_h%end_index(j,i)
9183
9184                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9185                         m = surf_lsm_h%end_index(j,i)
9186                         rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i) +         &
9187                                         surf_lsm_h%rad_lw_in(m)
9188                      ELSEIF ( match_usm )  THEN
9189                         m = surf_usm_h%end_index(j,i)
9190                         rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i) +         &
9191                                         surf_usm_h%rad_lw_in(m)
9192                      ENDIF
9193                   ENDDO
9194                ENDDO
9195             ENDIF
9196             
9197          CASE ( 'rad_lw_out*' )
9198             IF ( ALLOCATED( rad_lw_out_xy_av ) ) THEN
9199                DO  i = nxl, nxr
9200                   DO  j = nys, nyn
9201                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9202                                  surf_lsm_h%end_index(j,i)
9203                      match_usm = surf_usm_h%start_index(j,i) <=               &
9204                                  surf_usm_h%end_index(j,i)
9205
9206                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9207                         m = surf_lsm_h%end_index(j,i)
9208                         rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i) +       &
9209                                                 surf_lsm_h%rad_lw_out(m)
9210                      ELSEIF ( match_usm )  THEN
9211                         m = surf_usm_h%end_index(j,i)
9212                         rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i) +       &
9213                                                 surf_usm_h%rad_lw_out(m)
9214                      ENDIF
9215                   ENDDO
9216                ENDDO
9217             ENDIF
9218             
9219          CASE ( 'rad_sw_in*' )
9220             IF ( ALLOCATED( rad_sw_in_xy_av ) ) THEN
9221                DO  i = nxl, nxr
9222                   DO  j = nys, nyn
9223                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9224                                  surf_lsm_h%end_index(j,i)
9225                      match_usm = surf_usm_h%start_index(j,i) <=               &
9226                                  surf_usm_h%end_index(j,i)
9227
9228                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9229                         m = surf_lsm_h%end_index(j,i)
9230                         rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i) +         &
9231                                                surf_lsm_h%rad_sw_in(m)
9232                      ELSEIF ( match_usm )  THEN
9233                         m = surf_usm_h%end_index(j,i)
9234                         rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i) +         &
9235                                                surf_usm_h%rad_sw_in(m)
9236                      ENDIF
9237                   ENDDO
9238                ENDDO
9239             ENDIF
9240             
9241          CASE ( 'rad_sw_out*' )
9242             IF ( ALLOCATED( rad_sw_out_xy_av ) ) THEN
9243                DO  i = nxl, nxr
9244                   DO  j = nys, nyn
9245                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9246                                  surf_lsm_h%end_index(j,i)
9247                      match_usm = surf_usm_h%start_index(j,i) <=               &
9248                                  surf_usm_h%end_index(j,i)
9249
9250                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9251                         m = surf_lsm_h%end_index(j,i)
9252                         rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i) +       &
9253                                                 surf_lsm_h%rad_sw_out(m)
9254                      ELSEIF ( match_usm )  THEN
9255                         m = surf_usm_h%end_index(j,i)
9256                         rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i) +       &
9257                                                 surf_usm_h%rad_sw_out(m)
9258                      ENDIF
9259                   ENDDO
9260                ENDDO
9261             ENDIF
9262             
9263          CASE ( 'rad_lw_in' )
9264             IF ( ALLOCATED( rad_lw_in_av ) ) THEN
9265                DO  i = nxlg, nxrg
9266                   DO  j = nysg, nyng
9267                      DO  k = nzb, nzt+1
9268                         rad_lw_in_av(k,j,i) = rad_lw_in_av(k,j,i)             &
9269                                               + rad_lw_in(k,j,i)
9270                      ENDDO
9271                   ENDDO
9272                ENDDO
9273             ENDIF
9274
9275          CASE ( 'rad_lw_out' )
9276             IF ( ALLOCATED( rad_lw_out_av ) ) THEN
9277                DO  i = nxlg, nxrg
9278                   DO  j = nysg, nyng
9279                      DO  k = nzb, nzt+1
9280                         rad_lw_out_av(k,j,i) = rad_lw_out_av(k,j,i)           &
9281                                                + rad_lw_out(k,j,i)
9282                      ENDDO
9283                   ENDDO
9284                ENDDO
9285             ENDIF
9286
9287          CASE ( 'rad_lw_cs_hr' )
9288             IF ( ALLOCATED( rad_lw_cs_hr_av ) ) THEN
9289                DO  i = nxlg, nxrg
9290                   DO  j = nysg, nyng
9291                      DO  k = nzb, nzt+1
9292                         rad_lw_cs_hr_av(k,j,i) = rad_lw_cs_hr_av(k,j,i)       &
9293                                                  + rad_lw_cs_hr(k,j,i)
9294                      ENDDO
9295                   ENDDO
9296                ENDDO
9297             ENDIF
9298
9299          CASE ( 'rad_lw_hr' )
9300             IF ( ALLOCATED( rad_lw_hr_av ) ) THEN
9301                DO  i = nxlg, nxrg
9302                   DO  j = nysg, nyng
9303                      DO  k = nzb, nzt+1
9304                         rad_lw_hr_av(k,j,i) = rad_lw_hr_av(k,j,i)             &
9305                                               + rad_lw_hr(k,j,i)
9306                      ENDDO
9307                   ENDDO
9308                ENDDO
9309             ENDIF
9310
9311          CASE ( 'rad_sw_in' )
9312             IF ( ALLOCATED( rad_sw_in_av ) ) THEN
9313                DO  i = nxlg, nxrg
9314                   DO  j = nysg, nyng
9315                      DO  k = nzb, nzt+1
9316                         rad_sw_in_av(k,j,i) = rad_sw_in_av(k,j,i)             &
9317                                               + rad_sw_in(k,j,i)
9318                      ENDDO
9319                   ENDDO
9320                ENDDO
9321             ENDIF
9322
9323          CASE ( 'rad_sw_out' )
9324             IF ( ALLOCATED( rad_sw_out_av ) ) THEN
9325                DO  i = nxlg, nxrg
9326                   DO  j = nysg, nyng
9327                      DO  k = nzb, nzt+1
9328                         rad_sw_out_av(k,j,i) = rad_sw_out_av(k,j,i)           &
9329                                                + rad_sw_out(k,j,i)
9330                      ENDDO
9331                   ENDDO
9332                ENDDO
9333             ENDIF
9334
9335          CASE ( 'rad_sw_cs_hr' )
9336             IF ( ALLOCATED( rad_sw_cs_hr_av ) ) THEN
9337                DO  i = nxlg, nxrg
9338                   DO  j = nysg, nyng
9339                      DO  k = nzb, nzt+1
9340                         rad_sw_cs_hr_av(k,j,i) = rad_sw_cs_hr_av(k,j,i)       &
9341                                                  + rad_sw_cs_hr(k,j,i)
9342                      ENDDO
9343                   ENDDO
9344                ENDDO
9345             ENDIF
9346
9347          CASE ( 'rad_sw_hr' )
9348             IF ( ALLOCATED( rad_sw_hr_av ) ) THEN
9349                DO  i = nxlg, nxrg
9350                   DO  j = nysg, nyng
9351                      DO  k = nzb, nzt+1
9352                         rad_sw_hr_av(k,j,i) = rad_sw_hr_av(k,j,i)             &
9353                                               + rad_sw_hr(k,j,i)
9354                      ENDDO
9355                   ENDDO
9356                ENDDO
9357             ENDIF
9358
9359!--       block of RTM output variables
9360          CASE ( 'rtm_rad_net' )
9361!--           array of complete radiation balance
9362              DO isurf = dirstart(ids), dirend(ids)
9363                 IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9364                    surfradnet_av(isurf) = surfinsw(isurf) - surfoutsw(isurf) +  surfinlw(isurf) - surfoutlw(isurf)
9365                 ENDIF
9366              ENDDO
9367
9368          CASE ( 'rtm_rad_insw' )
9369!--           array of sw radiation falling to surface after i-th reflection
9370              DO isurf = dirstart(ids), dirend(ids)
9371                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9372                      surfinsw_av(isurf) = surfinsw_av(isurf) + surfinsw(isurf)
9373                  ENDIF
9374              ENDDO
9375
9376          CASE ( 'rtm_rad_inlw' )
9377!--           array of lw radiation falling to surface after i-th reflection
9378              DO isurf = dirstart(ids), dirend(ids)
9379                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9380                      surfinlw_av(isurf) = surfinlw_av(isurf) + surfinlw(isurf)
9381                  ENDIF
9382              ENDDO
9383
9384          CASE ( 'rtm_rad_inswdir' )
9385!--           array of direct sw radiation falling to surface from sun
9386              DO isurf = dirstart(ids), dirend(ids)
9387                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9388                      surfinswdir_av(isurf) = surfinswdir_av(isurf) + surfinswdir(isurf)
9389                  ENDIF
9390              ENDDO
9391
9392          CASE ( 'rtm_rad_inswdif' )
9393!--           array of difusion sw radiation falling to surface from sky and borders of the domain
9394              DO isurf = dirstart(ids), dirend(ids)
9395                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9396                      surfinswdif_av(isurf) = surfinswdif_av(isurf) + surfinswdif(isurf)
9397                  ENDIF
9398              ENDDO
9399
9400          CASE ( 'rtm_rad_inswref' )
9401!--           array of sw radiation falling to surface from reflections
9402              DO isurf = dirstart(ids), dirend(ids)
9403                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9404                      surfinswref_av(isurf) = surfinswref_av(isurf) + surfinsw(isurf) - &
9405                                          surfinswdir(isurf) - surfinswdif(isurf)
9406                  ENDIF
9407              ENDDO
9408
9409
9410          CASE ( 'rtm_rad_inlwdif' )
9411!--           array of sw radiation falling to surface after i-th reflection
9412              DO isurf = dirstart(ids), dirend(ids)
9413                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9414                      surfinlwdif_av(isurf) = surfinlwdif_av(isurf) + surfinlwdif(isurf)
9415                  ENDIF
9416              ENDDO
9417!
9418          CASE ( 'rtm_rad_inlwref' )
9419!--           array of lw radiation falling to surface from reflections
9420              DO isurf = dirstart(ids), dirend(ids)
9421                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9422                      surfinlwref_av(isurf) = surfinlwref_av(isurf) + &
9423                                          surfinlw(isurf) - surfinlwdif(isurf)
9424                  ENDIF
9425              ENDDO
9426
9427          CASE ( 'rtm_rad_outsw' )
9428!--           array of sw radiation emitted from surface after i-th reflection
9429              DO isurf = dirstart(ids), dirend(ids)
9430                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9431                      surfoutsw_av(isurf) = surfoutsw_av(isurf) + surfoutsw(isurf)
9432                  ENDIF
9433              ENDDO
9434
9435          CASE ( 'rtm_rad_outlw' )
9436!--           array of lw radiation emitted from surface after i-th reflection
9437              DO isurf = dirstart(ids), dirend(ids)
9438                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9439                      surfoutlw_av(isurf) = surfoutlw_av(isurf) + surfoutlw(isurf)
9440                  ENDIF
9441              ENDDO
9442
9443          CASE ( 'rtm_rad_ressw' )
9444!--           array of residua of sw radiation absorbed in surface after last reflection
9445              DO isurf = dirstart(ids), dirend(ids)
9446                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9447                      surfins_av(isurf) = surfins_av(isurf) + surfins(isurf)
9448                  ENDIF
9449              ENDDO
9450
9451          CASE ( 'rtm_rad_reslw' )
9452!--           array of residua of lw radiation absorbed in surface after last reflection
9453              DO isurf = dirstart(ids), dirend(ids)
9454                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9455                      surfinl_av(isurf) = surfinl_av(isurf) + surfinl(isurf)
9456                  ENDIF
9457              ENDDO
9458
9459          CASE ( 'rtm_rad_pc_inlw' )
9460              DO l = 1, npcbl
9461                 pcbinlw_av(l) = pcbinlw_av(l) + pcbinlw(l)
9462              ENDDO
9463
9464          CASE ( 'rtm_rad_pc_insw' )
9465              DO l = 1, npcbl
9466                 pcbinsw_av(l) = pcbinsw_av(l) + pcbinsw(l)
9467              ENDDO
9468
9469          CASE ( 'rtm_rad_pc_inswdir' )
9470              DO l = 1, npcbl
9471                 pcbinswdir_av(l) = pcbinswdir_av(l) + pcbinswdir(l)
9472              ENDDO
9473
9474          CASE ( 'rtm_rad_pc_inswdif' )
9475              DO l = 1, npcbl
9476                 pcbinswdif_av(l) = pcbinswdif_av(l) + pcbinswdif(l)
9477              ENDDO
9478
9479          CASE ( 'rtm_rad_pc_inswref' )
9480              DO l = 1, npcbl
9481                 pcbinswref_av(l) = pcbinswref_av(l) + pcbinsw(l) - pcbinswdir(l) - pcbinswdif(l)
9482              ENDDO
9483
9484          CASE ( 'rad_mrt_sw' )
9485             IF ( ALLOCATED( mrtinsw_av ) )  THEN
9486                mrtinsw_av(:) = mrtinsw_av(:) + mrtinsw(:)
9487             ENDIF
9488
9489          CASE ( 'rad_mrt_lw' )
9490             IF ( ALLOCATED( mrtinlw_av ) )  THEN
9491                mrtinlw_av(:) = mrtinlw_av(:) + mrtinlw(:)
9492             ENDIF
9493
9494          CASE ( 'rad_mrt' )
9495             IF ( ALLOCATED( mrt_av ) )  THEN
9496                mrt_av(:) = mrt_av(:) + mrt(:)
9497             ENDIF
9498
9499          CASE DEFAULT
9500             CONTINUE
9501
9502       END SELECT
9503
9504    ELSEIF ( mode == 'average' )  THEN
9505
9506       SELECT CASE ( TRIM( var ) )
9507!--       block of large scale (e.g. RRTMG) radiation output variables
9508          CASE ( 'rad_net*' )
9509             IF ( ALLOCATED( rad_net_av ) ) THEN
9510                DO  i = nxlg, nxrg
9511                   DO  j = nysg, nyng
9512                      rad_net_av(j,i) = rad_net_av(j,i)                        &
9513                                        / REAL( average_count_3d, KIND=wp )
9514                   ENDDO
9515                ENDDO
9516             ENDIF
9517             
9518          CASE ( 'rad_lw_in*' )
9519             IF ( ALLOCATED( rad_lw_in_xy_av ) ) THEN
9520                DO  i = nxlg, nxrg
9521                   DO  j = nysg, nyng
9522                      rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i)              &
9523                                        / REAL( average_count_3d, KIND=wp )
9524                   ENDDO
9525                ENDDO
9526             ENDIF
9527             
9528          CASE ( 'rad_lw_out*' )
9529             IF ( ALLOCATED( rad_lw_out_xy_av ) ) THEN
9530                DO  i = nxlg, nxrg
9531                   DO  j = nysg, nyng
9532                      rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i)            &
9533                                        / REAL( average_count_3d, KIND=wp )
9534                   ENDDO
9535                ENDDO
9536             ENDIF
9537             
9538          CASE ( 'rad_sw_in*' )
9539             IF ( ALLOCATED( rad_sw_in_xy_av ) ) THEN
9540                DO  i = nxlg, nxrg
9541                   DO  j = nysg, nyng
9542                      rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i)              &
9543                                        / REAL( average_count_3d, KIND=wp )
9544                   ENDDO
9545                ENDDO
9546             ENDIF
9547             
9548          CASE ( 'rad_sw_out*' )
9549             IF ( ALLOCATED( rad_sw_out_xy_av ) ) THEN
9550                DO  i = nxlg, nxrg
9551                   DO  j = nysg, nyng
9552                      rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i)             &
9553                                        / REAL( average_count_3d, KIND=wp )
9554                   ENDDO
9555                ENDDO
9556             ENDIF
9557
9558          CASE ( 'rad_lw_in' )
9559             IF ( ALLOCATED( rad_lw_in_av ) ) THEN
9560                DO  i = nxlg, nxrg
9561                   DO  j = nysg, nyng
9562                      DO  k = nzb, nzt+1
9563                         rad_lw_in_av(k,j,i) = rad_lw_in_av(k,j,i)             &
9564                                               / REAL( average_count_3d, KIND=wp )
9565                      ENDDO
9566                   ENDDO
9567                ENDDO
9568             ENDIF
9569
9570          CASE ( 'rad_lw_out' )
9571             IF ( ALLOCATED( rad_lw_out_av ) ) THEN
9572                DO  i = nxlg, nxrg
9573                   DO  j = nysg, nyng
9574                      DO  k = nzb, nzt+1
9575                         rad_lw_out_av(k,j,i) = rad_lw_out_av(k,j,i)           &
9576                                                / REAL( average_count_3d, KIND=wp )
9577                      ENDDO
9578                   ENDDO
9579                ENDDO
9580             ENDIF
9581
9582          CASE ( 'rad_lw_cs_hr' )
9583             IF ( ALLOCATED( rad_lw_cs_hr_av ) ) THEN
9584                DO  i = nxlg, nxrg
9585                   DO  j = nysg, nyng
9586                      DO  k = nzb, nzt+1
9587                         rad_lw_cs_hr_av(k,j,i) = rad_lw_cs_hr_av(k,j,i)       &
9588                                                / REAL( average_count_3d, KIND=wp )
9589                      ENDDO
9590                   ENDDO
9591                ENDDO
9592             ENDIF
9593
9594          CASE ( 'rad_lw_hr' )
9595             IF ( ALLOCATED( rad_lw_hr_av ) ) THEN
9596                DO  i = nxlg, nxrg
9597                   DO  j = nysg, nyng
9598                      DO  k = nzb, nzt+1
9599                         rad_lw_hr_av(k,j,i) = rad_lw_hr_av(k,j,i)             &
9600                                               / REAL( average_count_3d, KIND=wp )
9601                      ENDDO
9602                   ENDDO
9603                ENDDO
9604             ENDIF
9605
9606          CASE ( 'rad_sw_in' )
9607             IF ( ALLOCATED( rad_sw_in_av ) ) THEN
9608                DO  i = nxlg, nxrg
9609                   DO  j = nysg, nyng
9610                      DO  k = nzb, nzt+1
9611                         rad_sw_in_av(k,j,i) = rad_sw_in_av(k,j,i)             &
9612                                               / REAL( average_count_3d, KIND=wp )
9613                      ENDDO
9614                   ENDDO
9615                ENDDO
9616             ENDIF
9617
9618          CASE ( 'rad_sw_out' )
9619             IF ( ALLOCATED( rad_sw_out_av ) ) THEN
9620                DO  i = nxlg, nxrg
9621                   DO  j = nysg, nyng
9622                      DO  k = nzb, nzt+1
9623                         rad_sw_out_av(k,j,i) = rad_sw_out_av(k,j,i)           &
9624                                                / REAL( average_count_3d, KIND=wp )
9625                      ENDDO
9626                   ENDDO
9627                ENDDO
9628             ENDIF
9629
9630          CASE ( 'rad_sw_cs_hr' )
9631             IF ( ALLOCATED( rad_sw_cs_hr_av ) ) THEN
9632                DO  i = nxlg, nxrg
9633                   DO  j = nysg, nyng
9634                      DO  k = nzb, nzt+1
9635                         rad_sw_cs_hr_av(k,j,i) = rad_sw_cs_hr_av(k,j,i)       &
9636                                                / REAL( average_count_3d, KIND=wp )
9637                      ENDDO
9638                   ENDDO
9639                ENDDO
9640             ENDIF
9641
9642          CASE ( 'rad_sw_hr' )
9643             IF ( ALLOCATED( rad_sw_hr_av ) ) THEN
9644                DO  i = nxlg, nxrg
9645                   DO  j = nysg, nyng
9646                      DO  k = nzb, nzt+1
9647                         rad_sw_hr_av(k,j,i) = rad_sw_hr_av(k,j,i)             &
9648                                               / REAL( average_count_3d, KIND=wp )
9649                      ENDDO
9650                   ENDDO
9651                ENDDO
9652             ENDIF
9653
9654!--       block of RTM output variables
9655          CASE ( 'rtm_rad_net' )
9656!--           array of complete radiation balance
9657              DO isurf = dirstart(ids), dirend(ids)
9658                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9659                      surfradnet_av(isurf) = surfinsw_av(isurf) / REAL( average_count_3d, kind=wp )
9660                  ENDIF
9661              ENDDO
9662
9663          CASE ( 'rtm_rad_insw' )
9664!--           array of sw radiation falling to surface after i-th reflection
9665              DO isurf = dirstart(ids), dirend(ids)
9666                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9667                      surfinsw_av(isurf) = surfinsw_av(isurf) / REAL( average_count_3d, kind=wp )
9668                  ENDIF
9669              ENDDO
9670
9671          CASE ( 'rtm_rad_inlw' )
9672!--           array of lw radiation falling to surface after i-th reflection
9673              DO isurf = dirstart(ids), dirend(ids)
9674                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9675                      surfinlw_av(isurf) = surfinlw_av(isurf) / REAL( average_count_3d, kind=wp )
9676                  ENDIF
9677              ENDDO
9678
9679          CASE ( 'rtm_rad_inswdir' )
9680!--           array of direct sw radiation falling to surface from sun
9681              DO isurf = dirstart(ids), dirend(ids)
9682                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9683                      surfinswdir_av(isurf) = surfinswdir_av(isurf) / REAL( average_count_3d, kind=wp )
9684                  ENDIF
9685              ENDDO
9686
9687          CASE ( 'rtm_rad_inswdif' )
9688!--           array of difusion sw radiation falling to surface from sky and borders of the domain
9689              DO isurf = dirstart(ids), dirend(ids)
9690                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9691                      surfinswdif_av(isurf) = surfinswdif_av(isurf) / REAL( average_count_3d, kind=wp )
9692                  ENDIF
9693              ENDDO
9694
9695          CASE ( 'rtm_rad_inswref' )
9696!--           array of sw radiation falling to surface from reflections
9697              DO isurf = dirstart(ids), dirend(ids)
9698                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9699                      surfinswref_av(isurf) = surfinswref_av(isurf) / REAL( average_count_3d, kind=wp )
9700                  ENDIF
9701              ENDDO
9702
9703          CASE ( 'rtm_rad_inlwdif' )
9704!--           array of sw radiation falling to surface after i-th reflection
9705              DO isurf = dirstart(ids), dirend(ids)
9706                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9707                      surfinlwdif_av(isurf) = surfinlwdif_av(isurf) / REAL( average_count_3d, kind=wp )
9708                  ENDIF
9709              ENDDO
9710
9711          CASE ( 'rtm_rad_inlwref' )
9712!--           array of lw radiation falling to surface from reflections
9713              DO isurf = dirstart(ids), dirend(ids)
9714                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9715                      surfinlwref_av(isurf) = surfinlwref_av(isurf) / REAL( average_count_3d, kind=wp )
9716                  ENDIF
9717              ENDDO
9718
9719          CASE ( 'rtm_rad_outsw' )
9720!--           array of sw radiation emitted from surface after i-th reflection
9721              DO isurf = dirstart(ids), dirend(ids)
9722                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9723                      surfoutsw_av(isurf) = surfoutsw_av(isurf) / REAL( average_count_3d, kind=wp )
9724                  ENDIF
9725              ENDDO
9726
9727          CASE ( 'rtm_rad_outlw' )
9728!--           array of lw radiation emitted from surface after i-th reflection
9729              DO isurf = dirstart(ids), dirend(ids)
9730                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9731                      surfoutlw_av(isurf) = surfoutlw_av(isurf) / REAL( average_count_3d, kind=wp )
9732                  ENDIF
9733              ENDDO
9734
9735          CASE ( 'rtm_rad_ressw' )
9736!--           array of residua of sw radiation absorbed in surface after last reflection
9737              DO isurf = dirstart(ids), dirend(ids)
9738                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9739                      surfins_av(isurf) = surfins_av(isurf) / REAL( average_count_3d, kind=wp )
9740                  ENDIF
9741              ENDDO
9742
9743          CASE ( 'rtm_rad_reslw' )
9744!--           array of residua of lw radiation absorbed in surface after last reflection
9745              DO isurf = dirstart(ids), dirend(ids)
9746                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9747                      surfinl_av(isurf) = surfinl_av(isurf) / REAL( average_count_3d, kind=wp )
9748                  ENDIF
9749              ENDDO
9750
9751          CASE ( 'rtm_rad_pc_inlw' )
9752              DO l = 1, npcbl
9753                 pcbinlw_av(:) = pcbinlw_av(:) / REAL( average_count_3d, kind=wp )
9754              ENDDO
9755
9756          CASE ( 'rtm_rad_pc_insw' )
9757              DO l = 1, npcbl
9758                 pcbinsw_av(:) = pcbinsw_av(:) / REAL( average_count_3d, kind=wp )
9759              ENDDO
9760
9761          CASE ( 'rtm_rad_pc_inswdir' )
9762              DO l = 1, npcbl
9763                 pcbinswdir_av(:) = pcbinswdir_av(:) / REAL( average_count_3d, kind=wp )
9764              ENDDO
9765
9766          CASE ( 'rtm_rad_pc_inswdif' )
9767              DO l = 1, npcbl
9768                 pcbinswdif_av(:) = pcbinswdif_av(:) / REAL( average_count_3d, kind=wp )
9769              ENDDO
9770
9771          CASE ( 'rtm_rad_pc_inswref' )
9772              DO l = 1, npcbl
9773                 pcbinswref_av(:) = pcbinswref_av(:) / REAL( average_count_3d, kind=wp )
9774              ENDDO
9775
9776          CASE ( 'rad_mrt_lw' )
9777             IF ( ALLOCATED( mrtinlw_av ) )  THEN
9778                mrtinlw_av(:) = mrtinlw_av(:) / REAL( average_count_3d, KIND=wp )
9779             ENDIF
9780
9781          CASE ( 'rad_mrt' )
9782             IF ( ALLOCATED( mrt_av ) )  THEN
9783                mrt_av(:) = mrt_av(:) / REAL( average_count_3d, KIND=wp )
9784             ENDIF
9785
9786       END SELECT
9787
9788    ENDIF
9789
9790END SUBROUTINE radiation_3d_data_averaging
9791
9792
9793!------------------------------------------------------------------------------!
9794!
9795! Description:
9796! ------------
9797!> Subroutine defining appropriate grid for netcdf variables.
9798!> It is called out from subroutine netcdf.
9799!------------------------------------------------------------------------------!
9800SUBROUTINE radiation_define_netcdf_grid( variable, found, grid_x, grid_y, grid_z )
9801   
9802    IMPLICIT NONE
9803
9804    CHARACTER (LEN=*), INTENT(IN)  ::  variable    !<
9805    LOGICAL, INTENT(OUT)           ::  found       !<
9806    CHARACTER (LEN=*), INTENT(OUT) ::  grid_x      !<
9807    CHARACTER (LEN=*), INTENT(OUT) ::  grid_y      !<
9808    CHARACTER (LEN=*), INTENT(OUT) ::  grid_z      !<
9809
9810    CHARACTER (len=varnamelength)  :: var
9811
9812    found  = .TRUE.
9813
9814!
9815!-- Check for the grid
9816    var = TRIM(variable)
9817!-- RTM directional variables
9818    IF ( var(1:12) == 'rtm_rad_net_'  .OR.  var(1:13) == 'rtm_rad_insw_'  .OR.          &
9819         var(1:13) == 'rtm_rad_inlw_'  .OR.  var(1:16) == 'rtm_rad_inswdir_'  .OR.      &
9820         var(1:16) == 'rtm_rad_inswdif_'  .OR.  var(1:16) == 'rtm_rad_inswref_'  .OR.   &
9821         var(1:16) == 'rtm_rad_inlwdif_'  .OR.  var(1:16) == 'rtm_rad_inlwref_'  .OR.   &
9822         var(1:14) == 'rtm_rad_outsw_'  .OR.  var(1:14) == 'rtm_rad_outlw_'  .OR.       &
9823         var(1:14) == 'rtm_rad_ressw_'  .OR.  var(1:14) == 'rtm_rad_reslw_'  .OR.       &
9824         var == 'rtm_rad_pc_inlw'  .OR.                                                 &
9825         var == 'rtm_rad_pc_insw'  .OR.  var == 'rtm_rad_pc_inswdir'  .OR.              &
9826         var == 'rtm_rad_pc_inswdif'  .OR.  var == 'rtm_rad_pc_inswref'  .OR.           &
9827         var(1:7) == 'rtm_svf'  .OR.  var(1:7) == 'rtm_dif'  .OR.                       &
9828         var(1:9) == 'rtm_skyvf' .OR. var(1:10) == 'rtm_skyvft'  .OR.                   &
9829         var == 'rtm_mrt'  .OR.  var ==  'rtm_mrt_sw'  .OR.  var == 'rtm_mrt_lw' )  THEN
9830
9831         found = .TRUE.
9832         grid_x = 'x'
9833         grid_y = 'y'
9834         grid_z = 'zu'
9835    ELSE
9836
9837       SELECT CASE ( TRIM( var ) )
9838
9839          CASE ( 'rad_lw_cs_hr', 'rad_lw_hr', 'rad_sw_cs_hr', 'rad_sw_hr',        &
9840                 'rad_lw_cs_hr_xy', 'rad_lw_hr_xy', 'rad_sw_cs_hr_xy',            &
9841                 'rad_sw_hr_xy', 'rad_lw_cs_hr_xz', 'rad_lw_hr_xz',               &
9842                 'rad_sw_cs_hr_xz', 'rad_sw_hr_xz', 'rad_lw_cs_hr_yz',            &
9843                 'rad_lw_hr_yz', 'rad_sw_cs_hr_yz', 'rad_sw_hr_yz',               &
9844                 'rad_mrt', 'rad_mrt_sw', 'rad_mrt_lw' )
9845             grid_x = 'x'
9846             grid_y = 'y'
9847             grid_z = 'zu'
9848
9849          CASE ( 'rad_lw_in', 'rad_lw_out', 'rad_sw_in', 'rad_sw_out',            &
9850                 'rad_lw_in_xy', 'rad_lw_out_xy', 'rad_sw_in_xy','rad_sw_out_xy', &
9851                 'rad_lw_in_xz', 'rad_lw_out_xz', 'rad_sw_in_xz','rad_sw_out_xz', &
9852                 'rad_lw_in_yz', 'rad_lw_out_yz', 'rad_sw_in_yz','rad_sw_out_yz' )
9853             grid_x = 'x'
9854             grid_y = 'y'
9855             grid_z = 'zw'
9856
9857
9858          CASE DEFAULT
9859             found  = .FALSE.
9860             grid_x = 'none'
9861             grid_y = 'none'
9862             grid_z = 'none'
9863
9864           END SELECT
9865       ENDIF
9866
9867    END SUBROUTINE radiation_define_netcdf_grid
9868
9869!------------------------------------------------------------------------------!
9870!
9871! Description:
9872! ------------
9873!> Subroutine defining 2D output variables
9874!------------------------------------------------------------------------------!
9875 SUBROUTINE radiation_data_output_2d( av, variable, found, grid, mode,         &
9876                                      local_pf, two_d, nzb_do, nzt_do )
9877 
9878    USE indices
9879
9880    USE kinds
9881
9882
9883    IMPLICIT NONE
9884
9885    CHARACTER (LEN=*) ::  grid     !<
9886    CHARACTER (LEN=*) ::  mode     !<
9887    CHARACTER (LEN=*) ::  variable !<
9888
9889    INTEGER(iwp) ::  av !<
9890    INTEGER(iwp) ::  i  !<
9891    INTEGER(iwp) ::  j  !<
9892    INTEGER(iwp) ::  k  !<
9893    INTEGER(iwp) ::  m  !< index of surface element at grid point (j,i)
9894    INTEGER(iwp) ::  nzb_do   !<
9895    INTEGER(iwp) ::  nzt_do   !<
9896
9897    LOGICAL      ::  found !<
9898    LOGICAL      ::  two_d !< flag parameter that indicates 2D variables (horizontal cross sections)
9899
9900    REAL(wp) ::  fill_value = -999.0_wp    !< value for the _FillValue attribute
9901
9902    REAL(wp), DIMENSION(nxl:nxr,nys:nyn,nzb_do:nzt_do) ::  local_pf !<
9903
9904    found = .TRUE.
9905
9906    SELECT CASE ( TRIM( variable ) )
9907
9908       CASE ( 'rad_net*_xy' )        ! 2d-array
9909          IF ( av == 0 ) THEN
9910             DO  i = nxl, nxr
9911                DO  j = nys, nyn
9912!
9913!--                Obtain rad_net from its respective surface type
9914!--                Natural-type surfaces
9915                   DO  m = surf_lsm_h%start_index(j,i),                        &
9916                           surf_lsm_h%end_index(j,i) 
9917                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_net(m)
9918                   ENDDO
9919!
9920!--                Urban-type surfaces
9921                   DO  m = surf_usm_h%start_index(j,i),                        &
9922                           surf_usm_h%end_index(j,i) 
9923                      local_pf(i,j,nzb+1) = surf_usm_h%rad_net(m)
9924                   ENDDO
9925                ENDDO
9926             ENDDO
9927          ELSE
9928             IF ( .NOT. ALLOCATED( rad_net_av ) ) THEN
9929                ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
9930                rad_net_av = REAL( fill_value, KIND = wp )
9931             ENDIF
9932             DO  i = nxl, nxr
9933                DO  j = nys, nyn 
9934                   local_pf(i,j,nzb+1) = rad_net_av(j,i)
9935                ENDDO
9936             ENDDO
9937          ENDIF
9938          two_d = .TRUE.
9939          grid = 'zu1'
9940         
9941       CASE ( 'rad_lw_in*_xy' )        ! 2d-array
9942          IF ( av == 0 ) THEN
9943             DO  i = nxl, nxr
9944                DO  j = nys, nyn
9945!
9946!--                Obtain rad_net from its respective surface type
9947!--                Natural-type surfaces
9948                   DO  m = surf_lsm_h%start_index(j,i),                        &
9949                           surf_lsm_h%end_index(j,i) 
9950                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_lw_in(m)
9951                   ENDDO
9952!
9953!--                Urban-type surfaces
9954                   DO  m = surf_usm_h%start_index(j,i),                        &
9955                           surf_usm_h%end_index(j,i) 
9956                      local_pf(i,j,nzb+1) = surf_usm_h%rad_lw_in(m)
9957                   ENDDO
9958                ENDDO
9959             ENDDO
9960          ELSE
9961             IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) ) THEN
9962                ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
9963                rad_lw_in_xy_av = REAL( fill_value, KIND = wp )
9964             ENDIF
9965             DO  i = nxl, nxr
9966                DO  j = nys, nyn 
9967                   local_pf(i,j,nzb+1) = rad_lw_in_xy_av(j,i)
9968                ENDDO
9969             ENDDO
9970          ENDIF
9971          two_d = .TRUE.
9972          grid = 'zu1'
9973         
9974       CASE ( 'rad_lw_out*_xy' )        ! 2d-array
9975          IF ( av == 0 ) THEN
9976             DO  i = nxl, nxr
9977                DO  j = nys, nyn
9978!
9979!--                Obtain rad_net from its respective surface type
9980!--                Natural-type surfaces
9981                   DO  m = surf_lsm_h%start_index(j,i),                        &
9982                           surf_lsm_h%end_index(j,i) 
9983                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_lw_out(m)
9984                   ENDDO
9985!
9986!--                Urban-type surfaces
9987                   DO  m = surf_usm_h%start_index(j,i),                        &
9988                           surf_usm_h%end_index(j,i) 
9989                      local_pf(i,j,nzb+1) = surf_usm_h%rad_lw_out(m)
9990                   ENDDO
9991                ENDDO
9992             ENDDO
9993          ELSE
9994             IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) ) THEN
9995                ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
9996                rad_lw_out_xy_av = REAL( fill_value, KIND = wp )
9997             ENDIF
9998             DO  i = nxl, nxr
9999                DO  j = nys, nyn 
10000                   local_pf(i,j,nzb+1) = rad_lw_out_xy_av(j,i)
10001                ENDDO
10002             ENDDO
10003          ENDIF
10004          two_d = .TRUE.
10005          grid = 'zu1'
10006         
10007       CASE ( 'rad_sw_in*_xy' )        ! 2d-array
10008          IF ( av == 0 ) THEN
10009             DO  i = nxl, nxr
10010                DO  j = nys, nyn
10011!
10012!--                Obtain rad_net from its respective surface type
10013!--                Natural-type surfaces
10014                   DO  m = surf_lsm_h%start_index(j,i),                        &
10015                           surf_lsm_h%end_index(j,i) 
10016                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_sw_in(m)
10017                   ENDDO
10018!
10019!--                Urban-type surfaces
10020                   DO  m = surf_usm_h%start_index(j,i),                        &
10021                           surf_usm_h%end_index(j,i) 
10022                      local_pf(i,j,nzb+1) = surf_usm_h%rad_sw_in(m)
10023                   ENDDO
10024                ENDDO
10025             ENDDO
10026          ELSE
10027             IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) ) THEN
10028                ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
10029                rad_sw_in_xy_av = REAL( fill_value, KIND = wp )
10030             ENDIF
10031             DO  i = nxl, nxr
10032                DO  j = nys, nyn 
10033                   local_pf(i,j,nzb+1) = rad_sw_in_xy_av(j,i)
10034                ENDDO
10035             ENDDO
10036          ENDIF
10037          two_d = .TRUE.
10038          grid = 'zu1'
10039         
10040       CASE ( 'rad_sw_out*_xy' )        ! 2d-array
10041          IF ( av == 0 ) THEN
10042             DO  i = nxl, nxr
10043                DO  j = nys, nyn
10044!
10045!--                Obtain rad_net from its respective surface type
10046!--                Natural-type surfaces
10047                   DO  m = surf_lsm_h%start_index(j,i),                        &
10048                           surf_lsm_h%end_index(j,i) 
10049                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_sw_out(m)
10050                   ENDDO
10051!
10052!--                Urban-type surfaces
10053                   DO  m = surf_usm_h%start_index(j,i),                        &
10054                           surf_usm_h%end_index(j,i) 
10055                      local_pf(i,j,nzb+1) = surf_usm_h%rad_sw_out(m)
10056                   ENDDO
10057                ENDDO
10058             ENDDO
10059          ELSE
10060             IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) ) THEN
10061                ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
10062                rad_sw_out_xy_av = REAL( fill_value, KIND = wp )
10063             ENDIF
10064             DO  i = nxl, nxr
10065                DO  j = nys, nyn 
10066                   local_pf(i,j,nzb+1) = rad_sw_out_xy_av(j,i)
10067                ENDDO
10068             ENDDO
10069          ENDIF
10070          two_d = .TRUE.
10071          grid = 'zu1'         
10072         
10073       CASE ( 'rad_lw_in_xy', 'rad_lw_in_xz', 'rad_lw_in_yz' )
10074          IF ( av == 0 ) THEN
10075             DO  i = nxl, nxr
10076                DO  j = nys, nyn
10077                   DO  k = nzb_do, nzt_do
10078                      local_pf(i,j,k) = rad_lw_in(k,j,i)
10079                   ENDDO
10080                ENDDO
10081             ENDDO
10082          ELSE
10083            IF ( .NOT. ALLOCATED( rad_lw_in_av ) ) THEN
10084               ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10085               rad_lw_in_av = REAL( fill_value, KIND = wp )
10086            ENDIF
10087             DO  i = nxl, nxr
10088                DO  j = nys, nyn 
10089                   DO  k = nzb_do, nzt_do
10090                      local_pf(i,j,k) = rad_lw_in_av(k,j,i)
10091                   ENDDO
10092                ENDDO
10093             ENDDO
10094          ENDIF
10095          IF ( mode == 'xy' )  grid = 'zu'
10096
10097       CASE ( 'rad_lw_out_xy', 'rad_lw_out_xz', 'rad_lw_out_yz' )
10098          IF ( av == 0 ) THEN
10099             DO  i = nxl, nxr
10100                DO  j = nys, nyn
10101                   DO  k = nzb_do, nzt_do
10102                      local_pf(i,j,k) = rad_lw_out(k,j,i)
10103                   ENDDO
10104                ENDDO
10105             ENDDO
10106          ELSE
10107            IF ( .NOT. ALLOCATED( rad_lw_out_av ) ) THEN
10108               ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10109               rad_lw_out_av = REAL( fill_value, KIND = wp )
10110            ENDIF
10111             DO  i = nxl, nxr
10112                DO  j = nys, nyn 
10113                   DO  k = nzb_do, nzt_do
10114                      local_pf(i,j,k) = rad_lw_out_av(k,j,i)
10115                   ENDDO
10116                ENDDO
10117             ENDDO
10118          ENDIF   
10119          IF ( mode == 'xy' )  grid = 'zu'
10120
10121       CASE ( 'rad_lw_cs_hr_xy', 'rad_lw_cs_hr_xz', 'rad_lw_cs_hr_yz' )
10122          IF ( av == 0 ) THEN
10123             DO  i = nxl, nxr
10124                DO  j = nys, nyn
10125                   DO  k = nzb_do, nzt_do
10126                      local_pf(i,j,k) = rad_lw_cs_hr(k,j,i)
10127                   ENDDO
10128                ENDDO
10129             ENDDO
10130          ELSE
10131            IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) ) THEN
10132               ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10133               rad_lw_cs_hr_av = REAL( fill_value, KIND = wp )
10134            ENDIF
10135             DO  i = nxl, nxr
10136                DO  j = nys, nyn 
10137                   DO  k = nzb_do, nzt_do
10138                      local_pf(i,j,k) = rad_lw_cs_hr_av(k,j,i)
10139                   ENDDO
10140                ENDDO
10141             ENDDO
10142          ENDIF
10143          IF ( mode == 'xy' )  grid = 'zw'
10144
10145       CASE ( 'rad_lw_hr_xy', 'rad_lw_hr_xz', 'rad_lw_hr_yz' )
10146          IF ( av == 0 ) THEN
10147             DO  i = nxl, nxr
10148                DO  j = nys, nyn
10149                   DO  k = nzb_do, nzt_do
10150                      local_pf(i,j,k) = rad_lw_hr(k,j,i)
10151                   ENDDO
10152                ENDDO
10153             ENDDO
10154          ELSE
10155            IF ( .NOT. ALLOCATED( rad_lw_hr_av ) ) THEN
10156               ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10157               rad_lw_hr_av= REAL( fill_value, KIND = wp )
10158            ENDIF
10159             DO  i = nxl, nxr
10160                DO  j = nys, nyn 
10161                   DO  k = nzb_do, nzt_do
10162                      local_pf(i,j,k) = rad_lw_hr_av(k,j,i)
10163                   ENDDO
10164                ENDDO
10165             ENDDO
10166          ENDIF
10167          IF ( mode == 'xy' )  grid = 'zw'
10168
10169       CASE ( 'rad_sw_in_xy', 'rad_sw_in_xz', 'rad_sw_in_yz' )
10170          IF ( av == 0 ) THEN
10171             DO  i = nxl, nxr
10172                DO  j = nys, nyn
10173                   DO  k = nzb_do, nzt_do
10174                      local_pf(i,j,k) = rad_sw_in(k,j,i)
10175                   ENDDO
10176                ENDDO
10177             ENDDO
10178          ELSE
10179            IF ( .NOT. ALLOCATED( rad_sw_in_av ) ) THEN
10180               ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10181               rad_sw_in_av = REAL( fill_value, KIND = wp )
10182            ENDIF
10183             DO  i = nxl, nxr
10184                DO  j = nys, nyn 
10185                   DO  k = nzb_do, nzt_do
10186                      local_pf(i,j,k) = rad_sw_in_av(k,j,i)
10187                   ENDDO
10188                ENDDO
10189             ENDDO
10190          ENDIF
10191          IF ( mode == 'xy' )  grid = 'zu'
10192
10193       CASE ( 'rad_sw_out_xy', 'rad_sw_out_xz', 'rad_sw_out_yz' )
10194          IF ( av == 0 ) THEN
10195             DO  i = nxl, nxr
10196                DO  j = nys, nyn
10197                   DO  k = nzb_do, nzt_do
10198                      local_pf(i,j,k) = rad_sw_out(k,j,i)
10199                   ENDDO
10200                ENDDO
10201             ENDDO
10202          ELSE
10203            IF ( .NOT. ALLOCATED( rad_sw_out_av ) ) THEN
10204               ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10205               rad_sw_out_av = REAL( fill_value, KIND = wp )
10206            ENDIF
10207             DO  i = nxl, nxr
10208                DO  j = nys, nyn 
10209                   DO  k = nzb, nzt+1
10210                      local_pf(i,j,k) = rad_sw_out_av(k,j,i)
10211                   ENDDO
10212                ENDDO
10213             ENDDO
10214          ENDIF
10215          IF ( mode == 'xy' )  grid = 'zu'
10216
10217       CASE ( 'rad_sw_cs_hr_xy', 'rad_sw_cs_hr_xz', 'rad_sw_cs_hr_yz' )
10218          IF ( av == 0 ) THEN
10219             DO  i = nxl, nxr
10220                DO  j = nys, nyn
10221                   DO  k = nzb_do, nzt_do
10222                      local_pf(i,j,k) = rad_sw_cs_hr(k,j,i)
10223                   ENDDO
10224                ENDDO
10225             ENDDO
10226          ELSE
10227            IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) ) THEN
10228               ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10229               rad_sw_cs_hr_av = REAL( fill_value, KIND = wp )
10230            ENDIF
10231             DO  i = nxl, nxr
10232                DO  j = nys, nyn 
10233                   DO  k = nzb_do, nzt_do
10234                      local_pf(i,j,k) = rad_sw_cs_hr_av(k,j,i)
10235                   ENDDO
10236                ENDDO
10237             ENDDO
10238          ENDIF
10239          IF ( mode == 'xy' )  grid = 'zw'
10240
10241       CASE ( 'rad_sw_hr_xy', 'rad_sw_hr_xz', 'rad_sw_hr_yz' )
10242          IF ( av == 0 ) THEN
10243             DO  i = nxl, nxr
10244                DO  j = nys, nyn
10245                   DO  k = nzb_do, nzt_do
10246                      local_pf(i,j,k) = rad_sw_hr(k,j,i)
10247                   ENDDO
10248                ENDDO
10249             ENDDO
10250          ELSE
10251            IF ( .NOT. ALLOCATED( rad_sw_hr_av ) ) THEN
10252               ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10253               rad_sw_hr_av = REAL( fill_value, KIND = wp )
10254            ENDIF
10255             DO  i = nxl, nxr
10256                DO  j = nys, nyn 
10257                   DO  k = nzb_do, nzt_do
10258                      local_pf(i,j,k) = rad_sw_hr_av(k,j,i)
10259                   ENDDO
10260                ENDDO
10261             ENDDO
10262          ENDIF
10263          IF ( mode == 'xy' )  grid = 'zw'
10264
10265       CASE DEFAULT
10266          found = .FALSE.
10267          grid  = 'none'
10268
10269    END SELECT
10270 
10271 END SUBROUTINE radiation_data_output_2d
10272
10273
10274!------------------------------------------------------------------------------!
10275!
10276! Description:
10277! ------------
10278!> Subroutine defining 3D output variables
10279!------------------------------------------------------------------------------!
10280 SUBROUTINE radiation_data_output_3d( av, variable, found, local_pf, nzb_do, nzt_do )
10281 
10282
10283    USE indices
10284
10285    USE kinds
10286
10287
10288    IMPLICIT NONE
10289
10290    CHARACTER (LEN=*) ::  variable !<
10291
10292    INTEGER(iwp) ::  av          !<
10293    INTEGER(iwp) ::  i, j, k, l  !<
10294    INTEGER(iwp) ::  nzb_do      !<
10295    INTEGER(iwp) ::  nzt_do      !<
10296
10297    LOGICAL      ::  found       !<
10298
10299    REAL(wp)     ::  fill_value = -999.0_wp    !< value for the _FillValue attribute
10300
10301    REAL(sp), DIMENSION(nxl:nxr,nys:nyn,nzb_do:nzt_do) ::  local_pf !<
10302
10303    CHARACTER (len=varnamelength)                   :: var, surfid
10304    INTEGER(iwp)                                    :: ids,idsint_u,idsint_l,isurf,isvf,isurfs,isurflt,ipcgb
10305    INTEGER(iwp)                                    :: is, js, ks, istat
10306
10307    found = .TRUE.
10308
10309    ids = -1
10310    var = TRIM(variable)
10311    DO i = 0, nd-1
10312        k = len(TRIM(var))
10313        j = len(TRIM(dirname(i)))
10314        IF ( TRIM(var(k-j+1:k)) == TRIM(dirname(i)) )  THEN
10315            ids = i
10316            idsint_u = dirint_u(ids)
10317            idsint_l = dirint_l(ids)
10318            var = var(:k-j)
10319            EXIT
10320        ENDIF
10321    ENDDO
10322    IF ( ids == -1 )  THEN
10323        var = TRIM(variable)
10324    ENDIF
10325
10326    IF ( (var(1:8) == 'rtm_svf_'  .OR.  var(1:8) == 'rtm_dif_')  .AND.  len(TRIM(var)) >= 13 )  THEN
10327!--     svf values to particular surface
10328        surfid = var(9:)
10329        i = index(surfid,'_')
10330        j = index(surfid(i+1:),'_')
10331        READ(surfid(1:i-1),*, iostat=istat ) is
10332        IF ( istat == 0 )  THEN
10333            READ(surfid(i+1:i+j-1),*, iostat=istat ) js
10334        ENDIF
10335        IF ( istat == 0 )  THEN
10336            READ(surfid(i+j+1:),*, iostat=istat ) ks
10337        ENDIF
10338        IF ( istat == 0 )  THEN
10339            var = var(1:7)
10340        ENDIF
10341    ENDIF
10342
10343    local_pf = fill_value
10344
10345    SELECT CASE ( TRIM( var ) )
10346!--   block of large scale radiation model (e.g. RRTMG) output variables
10347      CASE ( 'rad_sw_in' )
10348         IF ( av == 0 )  THEN
10349            DO  i = nxl, nxr
10350               DO  j = nys, nyn
10351                  DO  k = nzb_do, nzt_do
10352                     local_pf(i,j,k) = rad_sw_in(k,j,i)
10353                  ENDDO
10354               ENDDO
10355            ENDDO
10356         ELSE
10357            IF ( .NOT. ALLOCATED( rad_sw_in_av ) ) THEN
10358               ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10359               rad_sw_in_av = REAL( fill_value, KIND = wp )
10360            ENDIF
10361            DO  i = nxl, nxr
10362               DO  j = nys, nyn
10363                  DO  k = nzb_do, nzt_do
10364                     local_pf(i,j,k) = rad_sw_in_av(k,j,i)
10365                  ENDDO
10366               ENDDO
10367            ENDDO
10368         ENDIF
10369
10370      CASE ( 'rad_sw_out' )
10371         IF ( av == 0 )  THEN
10372            DO  i = nxl, nxr
10373               DO  j = nys, nyn
10374                  DO  k = nzb_do, nzt_do
10375                     local_pf(i,j,k) = rad_sw_out(k,j,i)
10376                  ENDDO
10377               ENDDO
10378            ENDDO
10379         ELSE
10380            IF ( .NOT. ALLOCATED( rad_sw_out_av ) ) THEN
10381               ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10382               rad_sw_out_av = REAL( fill_value, KIND = wp )
10383            ENDIF
10384            DO  i = nxl, nxr
10385               DO  j = nys, nyn
10386                  DO  k = nzb_do, nzt_do
10387                     local_pf(i,j,k) = rad_sw_out_av(k,j,i)
10388                  ENDDO
10389               ENDDO
10390            ENDDO
10391         ENDIF
10392
10393      CASE ( 'rad_sw_cs_hr' )
10394         IF ( av == 0 )  THEN
10395            DO  i = nxl, nxr
10396               DO  j = nys, nyn
10397                  DO  k = nzb_do, nzt_do
10398                     local_pf(i,j,k) = rad_sw_cs_hr(k,j,i)
10399                  ENDDO
10400               ENDDO
10401            ENDDO
10402         ELSE
10403            IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) ) THEN
10404               ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10405               rad_sw_cs_hr_av = REAL( fill_value, KIND = wp )
10406            ENDIF
10407            DO  i = nxl, nxr
10408               DO  j = nys, nyn
10409                  DO  k = nzb_do, nzt_do
10410                     local_pf(i,j,k) = rad_sw_cs_hr_av(k,j,i)
10411                  ENDDO
10412               ENDDO
10413            ENDDO
10414         ENDIF
10415
10416      CASE ( 'rad_sw_hr' )
10417         IF ( av == 0 )  THEN
10418            DO  i = nxl, nxr
10419               DO  j = nys, nyn
10420                  DO  k = nzb_do, nzt_do
10421                     local_pf(i,j,k) = rad_sw_hr(k,j,i)
10422                  ENDDO
10423               ENDDO
10424            ENDDO
10425         ELSE
10426            IF ( .NOT. ALLOCATED( rad_sw_hr_av ) ) THEN
10427               ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10428               rad_sw_hr_av = REAL( fill_value, KIND = wp )
10429            ENDIF
10430            DO  i = nxl, nxr
10431               DO  j = nys, nyn
10432                  DO  k = nzb_do, nzt_do
10433                     local_pf(i,j,k) = rad_sw_hr_av(k,j,i)
10434                  ENDDO
10435               ENDDO
10436            ENDDO
10437         ENDIF
10438
10439      CASE ( 'rad_lw_in' )
10440         IF ( av == 0 )  THEN
10441            DO  i = nxl, nxr
10442               DO  j = nys, nyn
10443                  DO  k = nzb_do, nzt_do
10444                     local_pf(i,j,k) = rad_lw_in(k,j,i)
10445                  ENDDO
10446               ENDDO
10447            ENDDO
10448         ELSE
10449            IF ( .NOT. ALLOCATED( rad_lw_in_av ) ) THEN
10450               ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10451               rad_lw_in_av = REAL( fill_value, KIND = wp )
10452            ENDIF
10453            DO  i = nxl, nxr
10454               DO  j = nys, nyn
10455                  DO  k = nzb_do, nzt_do
10456                     local_pf(i,j,k) = rad_lw_in_av(k,j,i)
10457                  ENDDO
10458               ENDDO
10459            ENDDO
10460         ENDIF
10461
10462      CASE ( 'rad_lw_out' )
10463         IF ( av == 0 )  THEN
10464            DO  i = nxl, nxr
10465               DO  j = nys, nyn
10466                  DO  k = nzb_do, nzt_do
10467                     local_pf(i,j,k) = rad_lw_out(k,j,i)
10468                  ENDDO
10469               ENDDO
10470            ENDDO
10471         ELSE
10472            IF ( .NOT. ALLOCATED( rad_lw_out_av ) ) THEN
10473               ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10474               rad_lw_out_av = REAL( fill_value, KIND = wp )
10475            ENDIF
10476            DO  i = nxl, nxr
10477               DO  j = nys, nyn
10478                  DO  k = nzb_do, nzt_do
10479                     local_pf(i,j,k) = rad_lw_out_av(k,j,i)
10480                  ENDDO
10481               ENDDO
10482            ENDDO
10483         ENDIF
10484
10485      CASE ( 'rad_lw_cs_hr' )
10486         IF ( av == 0 )  THEN
10487            DO  i = nxl, nxr
10488               DO  j = nys, nyn
10489                  DO  k = nzb_do, nzt_do
10490                     local_pf(i,j,k) = rad_lw_cs_hr(k,j,i)
10491                  ENDDO
10492               ENDDO
10493            ENDDO
10494         ELSE
10495            IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) ) THEN
10496               ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10497               rad_lw_cs_hr_av = REAL( fill_value, KIND = wp )
10498            ENDIF
10499            DO  i = nxl, nxr
10500               DO  j = nys, nyn
10501                  DO  k = nzb_do, nzt_do
10502                     local_pf(i,j,k) = rad_lw_cs_hr_av(k,j,i)
10503                  ENDDO
10504               ENDDO
10505            ENDDO
10506         ENDIF
10507
10508      CASE ( 'rad_lw_hr' )
10509         IF ( av == 0 )  THEN
10510            DO  i = nxl, nxr
10511               DO  j = nys, nyn
10512                  DO  k = nzb_do, nzt_do
10513                     local_pf(i,j,k) = rad_lw_hr(k,j,i)
10514                  ENDDO
10515               ENDDO
10516            ENDDO
10517         ELSE
10518            IF ( .NOT. ALLOCATED( rad_lw_hr_av ) ) THEN
10519               ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10520              rad_lw_hr_av = REAL( fill_value, KIND = wp )
10521            ENDIF
10522            DO  i = nxl, nxr
10523               DO  j = nys, nyn
10524                  DO  k = nzb_do, nzt_do
10525                     local_pf(i,j,k) = rad_lw_hr_av(k,j,i)
10526                  ENDDO
10527               ENDDO
10528            ENDDO
10529         ENDIF
10530
10531!--   block of RTM output variables
10532!--   variables are intended mainly for debugging and detailed analyse purposes
10533      CASE ( 'rtm_skyvf' )
10534!--        sky view factor
10535         DO isurf = dirstart(ids), dirend(ids)
10536            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10537               local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = skyvf(isurf)
10538            ENDIF
10539         ENDDO
10540
10541      CASE ( 'rtm_skyvft' )
10542!--      sky view factor
10543         DO isurf = dirstart(ids), dirend(ids)
10544            IF ( surfl(id,isurf) == ids )  THEN
10545               local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = skyvft(isurf)
10546            ENDIF
10547         ENDDO
10548
10549      CASE ( 'rtm_svf', 'rtm_dif' )
10550!--      shape view factors or iradiance factors to selected surface
10551         IF ( TRIM(var)=='rtm_svf' )  THEN
10552             k = 1
10553         ELSE
10554             k = 2
10555         ENDIF
10556         DO isvf = 1, nsvfl
10557            isurflt = svfsurf(1, isvf)
10558            isurfs = svfsurf(2, isvf)
10559
10560            IF ( surf(ix,isurfs) == is  .AND.  surf(iy,isurfs) == js  .AND. surf(iz,isurfs) == ks  .AND. &
10561                 (surf(id,isurfs) == idsint_u .OR. surfl(id,isurfs) == idsint_l ) ) THEN
10562!--            correct source surface
10563               local_pf(surfl(ix,isurflt),surfl(iy,isurflt),surfl(iz,isurflt)) = svf(k,isvf)
10564            ENDIF
10565         ENDDO
10566
10567      CASE ( 'rtm_rad_net' )
10568!--     array of complete radiation balance
10569         DO isurf = dirstart(ids), dirend(ids)
10570            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10571               IF ( av == 0 )  THEN
10572                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = &
10573                         surfinsw(isurf) - surfoutsw(isurf) +  surfinlw(isurf) - surfoutlw(isurf)
10574               ELSE
10575                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfradnet_av(isurf)
10576               ENDIF
10577            ENDIF
10578         ENDDO
10579
10580      CASE ( 'rtm_rad_insw' )
10581!--      array of sw radiation falling to surface after i-th reflection
10582         DO isurf = dirstart(ids), dirend(ids)
10583            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10584               IF ( av == 0 )  THEN
10585                 local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinsw(isurf)
10586               ELSE
10587                 local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinsw_av(isurf)
10588               ENDIF
10589            ENDIF
10590         ENDDO
10591
10592      CASE ( 'rtm_rad_inlw' )
10593!--      array of lw radiation falling to surface after i-th reflection
10594         DO isurf = dirstart(ids), dirend(ids)
10595            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10596               IF ( av == 0 )  THEN
10597                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlw(isurf)
10598               ELSE
10599                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlw_av(isurf)
10600               ENDIF
10601             ENDIF
10602         ENDDO
10603
10604      CASE ( 'rtm_rad_inswdir' )
10605!--      array of direct sw radiation falling to surface from sun
10606         DO isurf = dirstart(ids), dirend(ids)
10607            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10608               IF ( av == 0 )  THEN
10609                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdir(isurf)
10610               ELSE
10611                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdir_av(isurf)
10612               ENDIF
10613            ENDIF
10614         ENDDO
10615
10616      CASE ( 'rtm_rad_inswdif' )
10617!--      array of difusion sw radiation falling to surface from sky and borders of the domain
10618         DO isurf = dirstart(ids), dirend(ids)
10619            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10620               IF ( av == 0 )  THEN
10621                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdif(isurf)
10622               ELSE
10623                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdif_av(isurf)
10624               ENDIF
10625            ENDIF
10626         ENDDO
10627
10628      CASE ( 'rtm_rad_inswref' )
10629!--      array of sw radiation falling to surface from reflections
10630         DO isurf = dirstart(ids), dirend(ids)
10631            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10632               IF ( av == 0 )  THEN
10633                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = &
10634                    surfinsw(isurf) - surfinswdir(isurf) - surfinswdif(isurf)
10635               ELSE
10636                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswref_av(isurf)
10637               ENDIF
10638            ENDIF
10639         ENDDO
10640
10641      CASE ( 'rtm_rad_inlwdif' )
10642!--      array of difusion lw radiation falling to surface from sky and borders of the domain
10643         DO isurf = dirstart(ids), dirend(ids)
10644            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10645               IF ( av == 0 )  THEN
10646                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlwdif(isurf)
10647               ELSE
10648                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlwdif_av(isurf)
10649               ENDIF
10650            ENDIF
10651         ENDDO
10652
10653      CASE ( 'rtm_rad_inlwref' )
10654!--      array of lw radiation falling to surface from reflections
10655         DO isurf = dirstart(ids), dirend(ids)
10656            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10657               IF ( av == 0 )  THEN
10658                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlw(isurf) - surfinlwdif(isurf)
10659               ELSE
10660                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlwref_av(isurf)
10661               ENDIF
10662            ENDIF
10663         ENDDO
10664
10665      CASE ( 'rtm_rad_outsw' )
10666!--      array of sw radiation emitted from surface after i-th reflection
10667         DO isurf = dirstart(ids), dirend(ids)
10668            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10669               IF ( av == 0 )  THEN
10670                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutsw(isurf)
10671               ELSE
10672                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutsw_av(isurf)
10673               ENDIF
10674            ENDIF
10675         ENDDO
10676
10677      CASE ( 'rtm_rad_outlw' )
10678!--      array of lw radiation emitted from surface after i-th reflection
10679         DO isurf = dirstart(ids), dirend(ids)
10680            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10681               IF ( av == 0 )  THEN
10682                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutlw(isurf)
10683               ELSE
10684                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutlw_av(isurf)
10685               ENDIF
10686            ENDIF
10687         ENDDO
10688
10689      CASE ( 'rtm_rad_ressw' )
10690!--      average of array of residua of sw radiation absorbed in surface after last reflection
10691         DO isurf = dirstart(ids), dirend(ids)
10692            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10693               IF ( av == 0 )  THEN
10694                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfins(isurf)
10695               ELSE
10696                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfins_av(isurf)
10697               ENDIF
10698            ENDIF
10699         ENDDO
10700
10701      CASE ( 'rtm_rad_reslw' )
10702!--      average of array of residua of lw radiation absorbed in surface after last reflection
10703         DO isurf = dirstart(ids), dirend(ids)
10704            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10705               IF ( av == 0 )  THEN
10706                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinl(isurf)
10707               ELSE
10708                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinl_av(isurf)
10709               ENDIF
10710            ENDIF
10711         ENDDO
10712
10713      CASE ( 'rtm_rad_pc_inlw' )
10714!--      array of lw radiation absorbed by plant canopy
10715         DO ipcgb = 1, npcbl
10716            IF ( av == 0 )  THEN
10717               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinlw(ipcgb)
10718            ELSE
10719               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinlw_av(ipcgb)
10720            ENDIF
10721         ENDDO
10722
10723      CASE ( 'rtm_rad_pc_insw' )
10724!--      array of sw radiation absorbed by plant canopy
10725         DO ipcgb = 1, npcbl
10726            IF ( av == 0 )  THEN
10727              local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinsw(ipcgb)
10728            ELSE
10729              local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinsw_av(ipcgb)
10730            ENDIF
10731         ENDDO
10732
10733      CASE ( 'rtm_rad_pc_inswdir' )
10734!--      array of direct sw radiation absorbed by plant canopy
10735         DO ipcgb = 1, npcbl
10736            IF ( av == 0 )  THEN
10737               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdir(ipcgb)
10738            ELSE
10739               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdir_av(ipcgb)
10740            ENDIF
10741         ENDDO
10742
10743      CASE ( 'rtm_rad_pc_inswdif' )
10744!--      array of diffuse sw radiation absorbed by plant canopy
10745         DO ipcgb = 1, npcbl
10746            IF ( av == 0 )  THEN
10747               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdif(ipcgb)
10748            ELSE
10749               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdif_av(ipcgb)
10750            ENDIF
10751         ENDDO
10752
10753      CASE ( 'rtm_rad_pc_inswref' )
10754!--      array of reflected sw radiation absorbed by plant canopy
10755         DO ipcgb = 1, npcbl
10756            IF ( av == 0 )  THEN
10757               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = &
10758                                    pcbinsw(ipcgb) - pcbinswdir(ipcgb) - pcbinswdif(ipcgb)
10759            ELSE
10760               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswref_av(ipcgb)
10761            ENDIF
10762         ENDDO
10763
10764      CASE ( 'rtm_mrt_sw' )
10765         local_pf = REAL( fill_value, KIND = wp )
10766         IF ( av == 0 )  THEN
10767            DO  l = 1, nmrtbl
10768               local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinsw(l)
10769            ENDDO
10770         ELSE
10771            IF ( ALLOCATED( mrtinsw_av ) ) THEN
10772               DO  l = 1, nmrtbl
10773                  local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinsw_av(l)
10774               ENDDO
10775            ENDIF
10776         ENDIF
10777
10778      CASE ( 'rtm_mrt_lw' )
10779         local_pf = REAL( fill_value, KIND = wp )
10780         IF ( av == 0 )  THEN
10781            DO  l = 1, nmrtbl
10782               local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinlw(l)
10783            ENDDO
10784         ELSE
10785            IF ( ALLOCATED( mrtinlw_av ) ) THEN
10786               DO  l = 1, nmrtbl
10787                  local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinlw_av(l)
10788               ENDDO
10789            ENDIF
10790         ENDIF
10791
10792      CASE ( 'rtm_mrt' )
10793         local_pf = REAL( fill_value, KIND = wp )
10794         IF ( av == 0 )  THEN
10795            DO  l = 1, nmrtbl
10796               local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrt(l)
10797            ENDDO
10798         ELSE
10799            IF ( ALLOCATED( mrt_av ) ) THEN
10800               DO  l = 1, nmrtbl
10801                  local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrt_av(l)
10802               ENDDO
10803            ENDIF
10804         ENDIF
10805
10806       CASE DEFAULT
10807          found = .FALSE.
10808
10809    END SELECT
10810
10811
10812 END SUBROUTINE radiation_data_output_3d
10813
10814!------------------------------------------------------------------------------!
10815!
10816! Description:
10817! ------------
10818!> Subroutine defining masked data output
10819!------------------------------------------------------------------------------!
10820 SUBROUTINE radiation_data_output_mask( av, variable, found, local_pf )
10821 
10822    USE control_parameters
10823       
10824    USE indices
10825   
10826    USE kinds
10827   
10828
10829    IMPLICIT NONE
10830
10831    CHARACTER (LEN=*) ::  variable   !<
10832
10833    CHARACTER(LEN=5) ::  grid        !< flag to distinquish between staggered grids
10834
10835    INTEGER(iwp) ::  av              !<
10836    INTEGER(iwp) ::  i               !<
10837    INTEGER(iwp) ::  j               !<
10838    INTEGER(iwp) ::  k               !<
10839    INTEGER(iwp) ::  topo_top_ind    !< k index of highest horizontal surface
10840
10841    LOGICAL ::  found                !< true if output array was found
10842    LOGICAL ::  resorted             !< true if array is resorted
10843
10844
10845    REAL(wp),                                                                  &
10846       DIMENSION(mask_size_l(mid,1),mask_size_l(mid,2),mask_size_l(mid,3)) ::  &
10847          local_pf   !<
10848
10849    REAL(wp), DIMENSION(:,:,:), POINTER ::  to_be_resorted  !< points to array which needs to be resorted for output
10850
10851
10852    found    = .TRUE.
10853    grid     = 's'
10854    resorted = .FALSE.
10855
10856    SELECT CASE ( TRIM( variable ) )
10857
10858
10859       CASE ( 'rad_lw_in' )
10860          IF ( av == 0 )  THEN
10861             to_be_resorted => rad_lw_in
10862          ELSE
10863             to_be_resorted => rad_lw_in_av
10864          ENDIF
10865
10866       CASE ( 'rad_lw_out' )
10867          IF ( av == 0 )  THEN
10868             to_be_resorted => rad_lw_out
10869          ELSE
10870             to_be_resorted => rad_lw_out_av
10871          ENDIF
10872
10873       CASE ( 'rad_lw_cs_hr' )
10874          IF ( av == 0 )  THEN
10875             to_be_resorted => rad_lw_cs_hr
10876          ELSE
10877             to_be_resorted => rad_lw_cs_hr_av
10878          ENDIF
10879
10880       CASE ( 'rad_lw_hr' )
10881          IF ( av == 0 )  THEN
10882             to_be_resorted => rad_lw_hr
10883          ELSE
10884             to_be_resorted => rad_lw_hr_av
10885          ENDIF
10886
10887       CASE ( 'rad_sw_in' )
10888          IF ( av == 0 )  THEN
10889             to_be_resorted => rad_sw_in
10890          ELSE
10891             to_be_resorted => rad_sw_in_av
10892          ENDIF
10893
10894       CASE ( 'rad_sw_out' )
10895          IF ( av == 0 )  THEN
10896             to_be_resorted => rad_sw_out
10897          ELSE
10898             to_be_resorted => rad_sw_out_av
10899          ENDIF
10900
10901       CASE ( 'rad_sw_cs_hr' )
10902          IF ( av == 0 )  THEN
10903             to_be_resorted => rad_sw_cs_hr
10904          ELSE
10905             to_be_resorted => rad_sw_cs_hr_av
10906          ENDIF
10907
10908       CASE ( 'rad_sw_hr' )
10909          IF ( av == 0 )  THEN
10910             to_be_resorted => rad_sw_hr
10911          ELSE
10912             to_be_resorted => rad_sw_hr_av
10913          ENDIF
10914
10915       CASE DEFAULT
10916          found = .FALSE.
10917
10918    END SELECT
10919
10920!
10921!-- Resort the array to be output, if not done above
10922    IF ( .NOT. resorted )  THEN
10923       IF ( .NOT. mask_surface(mid) )  THEN
10924!
10925!--       Default masked output
10926          DO  i = 1, mask_size_l(mid,1)
10927             DO  j = 1, mask_size_l(mid,2)
10928                DO  k = 1, mask_size_l(mid,3)
10929                   local_pf(i,j,k) =  to_be_resorted(mask_k(mid,k), &
10930                                      mask_j(mid,j),mask_i(mid,i))
10931                ENDDO
10932             ENDDO
10933          ENDDO
10934
10935       ELSE
10936!
10937!--       Terrain-following masked output
10938          DO  i = 1, mask_size_l(mid,1)
10939             DO  j = 1, mask_size_l(mid,2)
10940!
10941!--             Get k index of highest horizontal surface
10942                topo_top_ind = get_topography_top_index_ji( mask_j(mid,j), &
10943                                                            mask_i(mid,i), &
10944                                                            grid )
10945!
10946!--             Save output array
10947                DO  k = 1, mask_size_l(mid,3)
10948                   local_pf(i,j,k) = to_be_resorted(                       &
10949                                          MIN( topo_top_ind+mask_k(mid,k), &
10950                                               nzt+1 ),                    &
10951                                          mask_j(mid,j),                   &
10952                                          mask_i(mid,i)                     )
10953                ENDDO
10954             ENDDO
10955          ENDDO
10956
10957       ENDIF
10958    ENDIF
10959
10960
10961
10962 END SUBROUTINE radiation_data_output_mask
10963
10964
10965!------------------------------------------------------------------------------!
10966! Description:
10967! ------------
10968!> Subroutine writes local (subdomain) restart data
10969!------------------------------------------------------------------------------!
10970 SUBROUTINE radiation_wrd_local
10971
10972
10973    IMPLICIT NONE
10974
10975
10976    IF ( ALLOCATED( rad_net_av ) )  THEN
10977       CALL wrd_write_string( 'rad_net_av' )
10978       WRITE ( 14 )  rad_net_av
10979    ENDIF
10980   
10981    IF ( ALLOCATED( rad_lw_in_xy_av ) )  THEN
10982       CALL wrd_write_string( 'rad_lw_in_xy_av' )
10983       WRITE ( 14 )  rad_lw_in_xy_av
10984    ENDIF
10985   
10986    IF ( ALLOCATED( rad_lw_out_xy_av ) )  THEN
10987       CALL wrd_write_string( 'rad_lw_out_xy_av' )
10988       WRITE ( 14 )  rad_lw_out_xy_av
10989    ENDIF
10990   
10991    IF ( ALLOCATED( rad_sw_in_xy_av ) )  THEN
10992       CALL wrd_write_string( 'rad_sw_in_xy_av' )
10993       WRITE ( 14 )  rad_sw_in_xy_av
10994    ENDIF
10995   
10996    IF ( ALLOCATED( rad_sw_out_xy_av ) )  THEN
10997       CALL wrd_write_string( 'rad_sw_out_xy_av' )
10998       WRITE ( 14 )  rad_sw_out_xy_av
10999    ENDIF
11000
11001    IF ( ALLOCATED( rad_lw_in ) )  THEN
11002       CALL wrd_write_string( 'rad_lw_in' )
11003       WRITE ( 14 )  rad_lw_in
11004    ENDIF
11005
11006    IF ( ALLOCATED( rad_lw_in_av ) )  THEN
11007       CALL wrd_write_string( 'rad_lw_in_av' )
11008       WRITE ( 14 )  rad_lw_in_av
11009    ENDIF
11010
11011    IF ( ALLOCATED( rad_lw_out ) )  THEN
11012       CALL wrd_write_string( 'rad_lw_out' )
11013       WRITE ( 14 )  rad_lw_out
11014    ENDIF
11015
11016    IF ( ALLOCATED( rad_lw_out_av) )  THEN
11017       CALL wrd_write_string( 'rad_lw_out_av' )
11018       WRITE ( 14 )  rad_lw_out_av
11019    ENDIF
11020
11021    IF ( ALLOCATED( rad_lw_cs_hr) )  THEN
11022       CALL wrd_write_string( 'rad_lw_cs_hr' )
11023       WRITE ( 14 )  rad_lw_cs_hr
11024    ENDIF
11025
11026    IF ( ALLOCATED( rad_lw_cs_hr_av) )  THEN
11027       CALL wrd_write_string( 'rad_lw_cs_hr_av' )
11028       WRITE ( 14 )  rad_lw_cs_hr_av
11029    ENDIF
11030
11031    IF ( ALLOCATED( rad_lw_hr) )  THEN
11032       CALL wrd_write_string( 'rad_lw_hr' )
11033       WRITE ( 14 )  rad_lw_hr
11034    ENDIF
11035
11036    IF ( ALLOCATED( rad_lw_hr_av) )  THEN
11037       CALL wrd_write_string( 'rad_lw_hr_av' )
11038       WRITE ( 14 )  rad_lw_hr_av
11039    ENDIF
11040
11041    IF ( ALLOCATED( rad_sw_in) )  THEN
11042       CALL wrd_write_string( 'rad_sw_in' )
11043       WRITE ( 14 )  rad_sw_in
11044    ENDIF
11045
11046    IF ( ALLOCATED( rad_sw_in_av) )  THEN
11047       CALL wrd_write_string( 'rad_sw_in_av' )
11048       WRITE ( 14 )  rad_sw_in_av
11049    ENDIF
11050
11051    IF ( ALLOCATED( rad_sw_out) )  THEN
11052       CALL wrd_write_string( 'rad_sw_out' )
11053       WRITE ( 14 )  rad_sw_out
11054    ENDIF
11055
11056    IF ( ALLOCATED( rad_sw_out_av) )  THEN
11057       CALL wrd_write_string( 'rad_sw_out_av' )
11058       WRITE ( 14 )  rad_sw_out_av
11059    ENDIF
11060
11061    IF ( ALLOCATED( rad_sw_cs_hr) )  THEN
11062       CALL wrd_write_string( 'rad_sw_cs_hr' )
11063       WRITE ( 14 )  rad_sw_cs_hr
11064    ENDIF
11065
11066    IF ( ALLOCATED( rad_sw_cs_hr_av) )  THEN
11067       CALL wrd_write_string( 'rad_sw_cs_hr_av' )
11068       WRITE ( 14 )  rad_sw_cs_hr_av
11069    ENDIF
11070
11071    IF ( ALLOCATED( rad_sw_hr) )  THEN
11072       CALL wrd_write_string( 'rad_sw_hr' )
11073       WRITE ( 14 )  rad_sw_hr
11074    ENDIF
11075
11076    IF ( ALLOCATED( rad_sw_hr_av) )  THEN
11077       CALL wrd_write_string( 'rad_sw_hr_av' )
11078       WRITE ( 14 )  rad_sw_hr_av
11079    ENDIF
11080
11081
11082 END SUBROUTINE radiation_wrd_local
11083
11084!------------------------------------------------------------------------------!
11085! Description:
11086! ------------
11087!> Subroutine reads local (subdomain) restart data
11088!------------------------------------------------------------------------------!
11089 SUBROUTINE radiation_rrd_local( i, k, nxlf, nxlc, nxl_on_file, nxrf, nxrc,    &
11090                                nxr_on_file, nynf, nync, nyn_on_file, nysf,    &
11091                                nysc, nys_on_file, tmp_2d, tmp_3d, found )
11092 
11093
11094    USE control_parameters
11095       
11096    USE indices
11097   
11098    USE kinds
11099   
11100    USE pegrid
11101
11102
11103    IMPLICIT NONE
11104
11105    INTEGER(iwp) ::  i               !<
11106    INTEGER(iwp) ::  k               !<
11107    INTEGER(iwp) ::  nxlc            !<
11108    INTEGER(iwp) ::  nxlf            !<
11109    INTEGER(iwp) ::  nxl_on_file     !<
11110    INTEGER(iwp) ::  nxrc            !<
11111    INTEGER(iwp) ::  nxrf            !<
11112    INTEGER(iwp) ::  nxr_on_file     !<
11113    INTEGER(iwp) ::  nync            !<
11114    INTEGER(iwp) ::  nynf            !<
11115    INTEGER(iwp) ::  nyn_on_file     !<
11116    INTEGER(iwp) ::  nysc            !<
11117    INTEGER(iwp) ::  nysf            !<
11118    INTEGER(iwp) ::  nys_on_file     !<
11119
11120    LOGICAL, INTENT(OUT)  :: found
11121
11122    REAL(wp), DIMENSION(nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_2d   !<
11123
11124    REAL(wp), DIMENSION(nzb:nzt+1,nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_3d   !<
11125
11126    REAL(wp), DIMENSION(0:0,nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_3d2   !<
11127
11128
11129    found = .TRUE.
11130
11131
11132    SELECT CASE ( restart_string(1:length) )
11133
11134       CASE ( 'rad_net_av' )
11135          IF ( .NOT. ALLOCATED( rad_net_av ) )  THEN
11136             ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
11137          ENDIF 
11138          IF ( k == 1 )  READ ( 13 )  tmp_2d
11139          rad_net_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =           &
11140                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11141                       
11142       CASE ( 'rad_lw_in_xy_av' )
11143          IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) )  THEN
11144             ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
11145          ENDIF 
11146          IF ( k == 1 )  READ ( 13 )  tmp_2d
11147          rad_lw_in_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =      &
11148                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11149                       
11150       CASE ( 'rad_lw_out_xy_av' )
11151          IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) )  THEN
11152             ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
11153          ENDIF 
11154          IF ( k == 1 )  READ ( 13 )  tmp_2d
11155          rad_lw_out_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =     &
11156                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11157                       
11158       CASE ( 'rad_sw_in_xy_av' )
11159          IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) )  THEN
11160             ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
11161          ENDIF 
11162          IF ( k == 1 )  READ ( 13 )  tmp_2d
11163          rad_sw_in_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =      &
11164                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11165                       
11166       CASE ( 'rad_sw_out_xy_av' )
11167          IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) )  THEN
11168             ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
11169          ENDIF 
11170          IF ( k == 1 )  READ ( 13 )  tmp_2d
11171          rad_sw_out_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =     &
11172                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11173                       
11174       CASE ( 'rad_lw_in' )
11175          IF ( .NOT. ALLOCATED( rad_lw_in ) )  THEN
11176             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11177                  radiation_scheme == 'constant')  THEN
11178                ALLOCATE( rad_lw_in(0:0,nysg:nyng,nxlg:nxrg) )
11179             ELSE
11180                ALLOCATE( rad_lw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11181             ENDIF
11182          ENDIF 
11183          IF ( k == 1 )  THEN
11184             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11185                  radiation_scheme == 'constant')  THEN
11186                READ ( 13 )  tmp_3d2
11187                rad_lw_in(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =   &
11188                   tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11189             ELSE
11190                READ ( 13 )  tmp_3d
11191                rad_lw_in(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11192                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11193             ENDIF
11194          ENDIF
11195
11196       CASE ( 'rad_lw_in_av' )
11197          IF ( .NOT. ALLOCATED( rad_lw_in_av ) )  THEN
11198             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11199                  radiation_scheme == 'constant')  THEN
11200                ALLOCATE( rad_lw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
11201             ELSE
11202                ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11203             ENDIF
11204          ENDIF 
11205          IF ( k == 1 )  THEN
11206             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11207                  radiation_scheme == 'constant')  THEN
11208                READ ( 13 )  tmp_3d2
11209                rad_lw_in_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =&
11210                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11211             ELSE
11212                READ ( 13 )  tmp_3d
11213                rad_lw_in_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11214                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11215             ENDIF
11216          ENDIF
11217
11218       CASE ( 'rad_lw_out' )
11219          IF ( .NOT. ALLOCATED( rad_lw_out ) )  THEN
11220             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11221                  radiation_scheme == 'constant')  THEN
11222                ALLOCATE( rad_lw_out(0:0,nysg:nyng,nxlg:nxrg) )
11223             ELSE
11224                ALLOCATE( rad_lw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11225             ENDIF
11226          ENDIF 
11227          IF ( k == 1 )  THEN
11228             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11229                  radiation_scheme == 'constant')  THEN
11230                READ ( 13 )  tmp_3d2
11231                rad_lw_out(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11232                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11233             ELSE
11234                READ ( 13 )  tmp_3d
11235                rad_lw_out(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =    &
11236                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11237             ENDIF
11238          ENDIF
11239
11240       CASE ( 'rad_lw_out_av' )
11241          IF ( .NOT. ALLOCATED( rad_lw_out_av ) )  THEN
11242             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11243                  radiation_scheme == 'constant')  THEN
11244                ALLOCATE( rad_lw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
11245             ELSE
11246                ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11247             ENDIF
11248          ENDIF 
11249          IF ( k == 1 )  THEN
11250             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11251                  radiation_scheme == 'constant')  THEN
11252                READ ( 13 )  tmp_3d2
11253                rad_lw_out_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) &
11254                   = tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11255             ELSE
11256                READ ( 13 )  tmp_3d
11257                rad_lw_out_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &
11258                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11259             ENDIF
11260          ENDIF
11261
11262       CASE ( 'rad_lw_cs_hr' )
11263          IF ( .NOT. ALLOCATED( rad_lw_cs_hr ) )  THEN
11264             ALLOCATE( rad_lw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11265          ENDIF
11266          IF ( k == 1 )  READ ( 13 )  tmp_3d
11267          rad_lw_cs_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11268                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11269
11270       CASE ( 'rad_lw_cs_hr_av' )
11271          IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) )  THEN
11272             ALLOCATE( rad_lw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11273          ENDIF
11274          IF ( k == 1 )  READ ( 13 )  tmp_3d
11275          rad_lw_cs_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11276                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11277
11278       CASE ( 'rad_lw_hr' )
11279          IF ( .NOT. ALLOCATED( rad_lw_hr ) )  THEN
11280             ALLOCATE( rad_lw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11281          ENDIF
11282          IF ( k == 1 )  READ ( 13 )  tmp_3d
11283          rad_lw_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =           &
11284                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11285
11286       CASE ( 'rad_lw_hr_av' )
11287          IF ( .NOT. ALLOCATED( rad_lw_hr_av ) )  THEN
11288             ALLOCATE( rad_lw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11289          ENDIF
11290          IF ( k == 1 )  READ ( 13 )  tmp_3d
11291          rad_lw_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11292                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11293
11294       CASE ( 'rad_sw_in' )
11295          IF ( .NOT. ALLOCATED( rad_sw_in ) )  THEN
11296             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11297                  radiation_scheme == 'constant')  THEN
11298                ALLOCATE( rad_sw_in(0:0,nysg:nyng,nxlg:nxrg) )
11299             ELSE
11300                ALLOCATE( rad_sw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11301             ENDIF
11302          ENDIF 
11303          IF ( k == 1 )  THEN
11304             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11305                  radiation_scheme == 'constant')  THEN
11306                READ ( 13 )  tmp_3d2
11307                rad_sw_in(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =   &
11308                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11309             ELSE
11310                READ ( 13 )  tmp_3d
11311                rad_sw_in(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11312                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11313             ENDIF
11314          ENDIF
11315
11316       CASE ( 'rad_sw_in_av' )
11317          IF ( .NOT. ALLOCATED( rad_sw_in_av ) )  THEN
11318             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11319                  radiation_scheme == 'constant')  THEN
11320                ALLOCATE( rad_sw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
11321             ELSE
11322                ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11323             ENDIF
11324          ENDIF 
11325          IF ( k == 1 )  THEN
11326             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11327                  radiation_scheme == 'constant')  THEN
11328                READ ( 13 )  tmp_3d2
11329                rad_sw_in_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =&
11330                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11331             ELSE
11332                READ ( 13 )  tmp_3d
11333                rad_sw_in_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11334                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11335             ENDIF
11336          ENDIF
11337
11338       CASE ( 'rad_sw_out' )
11339          IF ( .NOT. ALLOCATED( rad_sw_out ) )  THEN
11340             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11341                  radiation_scheme == 'constant')  THEN
11342                ALLOCATE( rad_sw_out(0:0,nysg:nyng,nxlg:nxrg) )
11343             ELSE
11344                ALLOCATE( rad_sw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11345             ENDIF
11346          ENDIF 
11347          IF ( k == 1 )  THEN
11348             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11349                  radiation_scheme == 'constant')  THEN
11350                READ ( 13 )  tmp_3d2
11351                rad_sw_out(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11352                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11353             ELSE
11354                READ ( 13 )  tmp_3d
11355                rad_sw_out(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =    &
11356                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11357             ENDIF
11358          ENDIF
11359
11360       CASE ( 'rad_sw_out_av' )
11361          IF ( .NOT. ALLOCATED( rad_sw_out_av ) )  THEN
11362             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11363                  radiation_scheme == 'constant')  THEN
11364                ALLOCATE( rad_sw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
11365             ELSE
11366                ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11367             ENDIF
11368          ENDIF 
11369          IF ( k == 1 )  THEN
11370             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11371                  radiation_scheme == 'constant')  THEN
11372                READ ( 13 )  tmp_3d2
11373                rad_sw_out_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) &
11374                   = tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11375             ELSE
11376                READ ( 13 )  tmp_3d
11377                rad_sw_out_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &
11378                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11379             ENDIF
11380          ENDIF
11381
11382       CASE ( 'rad_sw_cs_hr' )
11383          IF ( .NOT. ALLOCATED( rad_sw_cs_hr ) )  THEN
11384             ALLOCATE( rad_sw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11385          ENDIF
11386          IF ( k == 1 )  READ ( 13 )  tmp_3d
11387          rad_sw_cs_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11388                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11389
11390       CASE ( 'rad_sw_cs_hr_av' )
11391          IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) )  THEN
11392             ALLOCATE( rad_sw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11393          ENDIF
11394          IF ( k == 1 )  READ ( 13 )  tmp_3d
11395          rad_sw_cs_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11396                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11397
11398       CASE ( 'rad_sw_hr' )
11399          IF ( .NOT. ALLOCATED( rad_sw_hr ) )  THEN
11400             ALLOCATE( rad_sw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11401          ENDIF
11402          IF ( k == 1 )  READ ( 13 )  tmp_3d
11403          rad_sw_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =           &
11404                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11405
11406       CASE ( 'rad_sw_hr_av' )
11407          IF ( .NOT. ALLOCATED( rad_sw_hr_av ) )  THEN
11408             ALLOCATE( rad_sw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11409          ENDIF
11410          IF ( k == 1 )  READ ( 13 )  tmp_3d
11411          rad_lw_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11412                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11413
11414       CASE DEFAULT
11415
11416          found = .FALSE.
11417
11418    END SELECT
11419
11420 END SUBROUTINE radiation_rrd_local
11421
11422!------------------------------------------------------------------------------!
11423! Description:
11424! ------------
11425!> Subroutine writes debug information
11426!------------------------------------------------------------------------------!
11427 SUBROUTINE radiation_write_debug_log ( message )
11428    !> it writes debug log with time stamp
11429    CHARACTER(*)  :: message
11430    CHARACTER(15) :: dtc
11431    CHARACTER(8)  :: date
11432    CHARACTER(10) :: time
11433    CHARACTER(5)  :: zone
11434    CALL date_and_time(date, time, zone)
11435    dtc = date(7:8)//','//time(1:2)//':'//time(3:4)//':'//time(5:10)
11436    WRITE(9,'(2A)') dtc, TRIM(message)
11437    FLUSH(9)
11438 END SUBROUTINE radiation_write_debug_log
11439
11440 END MODULE radiation_model_mod
Note: See TracBrowser for help on using the repository browser.