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

Last change on this file since 3435 was 3435, checked in by gronemeier, 6 years ago

new: terrain-following masked output; bugfixes: increase vertical dimension of gamma_w_green_sat by 1, add checks for masked output for chemistry_model and radiation_model, reordered calls to xxx_define_netcdf_grid in masked output part

  • Property svn:keywords set to Id
File size: 444.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-2018 Leibniz Universitaet Hannover
21!------------------------------------------------------------------------------!
22!
23! Current revisions:
24! ------------------
25!
26!
27! Former revisions:
28! -----------------
29! $Id: radiation_model_mod.f90 3435 2018-10-26 18:25:44Z gronemeier $
30! - workaround: return unit=illegal in check_data_output for certain variables
31!   when check called from init_masks
32! - Use pointer in masked output to reduce code redundancies
33! - Add terrain-following masked output
34!
35! 3424 2018-10-25 07:29:10Z gronemeier
36! bugfix: add rad_lw_in, rad_lw_out, rad_sw_out to radiation_check_data_output
37!
38! 3378 2018-10-19 12:34:59Z kanani
39! merge from radiation branch (r3362) into trunk
40! (moh.hefny):
41! - removed read/write_svf_on_init and read_dist_max_svf (not used anymore)
42! - bugfix nzut > nzpt in calculating maxboxes
43!
44! 3372 2018-10-18 14:03:19Z raasch
45! bugfix: kind type of 2nd argument of mpi_win_allocate changed, misplaced
46!         __parallel directive
47!
48! 3351 2018-10-15 18:40:42Z suehring
49! Do not overwrite values of spectral and broadband albedo during initialization
50! if they are already initialized in the urban-surface model via ASCII input.
51!
52! 3337 2018-10-12 15:17:09Z kanani
53! - New RTM version 2.9: (Pavel Krc, Jaroslav Resler, ICS, Prague)
54!   added calculation of the MRT inside the RTM module
55!   MRT fluxes are consequently used in the new biometeorology module
56!   for calculation of biological indices (MRT, PET)
57!   Fixes of v. 2.5 and SVN trunk:
58!    - proper initialization of rad_net_l
59!    - make arrays nsurfs and surfstart TARGET to prevent some MPI problems
60!    - initialization of arrays used in MPI one-sided operation as 1-D arrays
61!      to prevent problems with some MPI/compiler combinations
62!    - fix indexing of target displacement in subroutine request_itarget to
63!      consider nzub
64!    - fix LAD dimmension range in PCB calculation
65!    - check ierr in all MPI calls
66!    - use proper per-gridbox sky and diffuse irradiance
67!    - fix shading for reflected irradiance
68!    - clear away the residuals of "atmospheric surfaces" implementation
69!    - fix rounding bug in raytrace_2d introduced in SVN trunk
70! - New RTM version 2.5: (Pavel Krc, Jaroslav Resler, ICS, Prague)
71!   can use angular discretization for all SVF
72!   (i.e. reflected and emitted radiation in addition to direct and diffuse),
73!   allowing for much better scaling wih high resoltion and/or complex terrain
74! - Unite array grow factors
75! - Fix slightly shifted terrain height in raytrace_2d
76! - Use more efficient MPI_Win_allocate for reverse gridsurf index
77! - Fix random MPI RMA bugs on Intel compilers
78! - Fix approx. double plant canopy sink values for reflected radiation
79! - Fix mostly missing plant canopy sinks for direct radiation
80! - Fix discretization errors for plant canopy sink in diffuse radiation
81! - Fix rounding errors in raytrace_2d
82!
83! 3274 2018-09-24 15:42:55Z knoop
84! Modularization of all bulk cloud physics code components
85!
86! 3272 2018-09-24 10:16:32Z suehring
87! - split direct and diffusion shortwave radiation using RRTMG rather than using
88!   calc_diffusion_radiation, in case of RRTMG
89! - removed the namelist variable split_diffusion_radiation. Now splitting depends
90!   on the choise of radiation radiation scheme
91! - removed calculating the rdiation flux for surfaces at the radiation scheme
92!   in case of using RTM since it will be calculated anyway in the radiation
93!   interaction routine.
94! - set SW radiation flux for surfaces to zero at night in case of no RTM is used
95! - precalculate the unit vector yxdir of ray direction to avoid the temporarly
96!   array allocation during the subroutine call
97! - fixed a bug in calculating the max number of boxes ray can cross in the domain
98!
99! 3264 2018-09-20 13:54:11Z moh.hefny
100! Bugfix in raytrace_2d calls
101!
102! 3248 2018-09-14 09:42:06Z sward
103! Minor formating changes
104!
105! 3246 2018-09-13 15:14:50Z sward
106! Added error handling for input namelist via parin_fail_message
107!
108! 3241 2018-09-12 15:02:00Z raasch
109! unused variables removed or commented
110!
111! 3233 2018-09-07 13:21:24Z schwenkel
112! Adapted for the use of cloud_droplets
113!
114! 3230 2018-09-05 09:29:05Z schwenkel
115! Bugfix in radiation_constant_surf: changed (10.0 - emissivity_urb) to
116! (1.0 - emissivity_urb)
117!
118! 3226 2018-08-31 12:27:09Z suehring
119! Bugfixes in calculation of sky-view factors and canopy-sink factors.
120!
121! 3186 2018-07-30 17:07:14Z suehring
122! Remove print statement
123!
124! 3180 2018-07-27 11:00:56Z suehring
125! Revise concept for calculation of effective radiative temperature and mapping
126! of radiative heating
127!
128! 3175 2018-07-26 14:07:38Z suehring
129! Bugfix for commit 3172
130!
131! 3173 2018-07-26 12:55:23Z suehring
132! Revise output of surface radiation quantities in case of overhanging
133! structures
134!
135! 3172 2018-07-26 12:06:06Z suehring
136! Bugfixes:
137!  - temporal work-around for calculation of effective radiative surface
138!    temperature
139!  - prevent positive solar radiation during nighttime
140!
141! 3170 2018-07-25 15:19:37Z suehring
142! Bugfix, map signle-column radiation forcing profiles on top of any topography
143!
144! 3156 2018-07-19 16:30:54Z knoop
145! Bugfix: replaced usage of the pt array with the surf%pt_surface array
146!
147! 3137 2018-07-17 06:44:21Z maronga
148! String length for trace_names fixed
149!
150! 3127 2018-07-15 08:01:25Z maronga
151! A few pavement parameters updated.
152!
153! 3123 2018-07-12 16:21:53Z suehring
154! Correct working precision for INTEGER number
155!
156! 3122 2018-07-11 21:46:41Z maronga
157! Bugfix: maximum distance for raytracing was set to  -999 m by default,
158! effectively switching off all surface reflections when max_raytracing_dist
159! was not explicitly set in namelist
160!
161! 3117 2018-07-11 09:59:11Z maronga
162! Bugfix: water vapor was not transfered to RRTMG when bulk_cloud_model = .F.
163! Bugfix: changed the calculation of RRTMG boundary conditions (Mohamed Salim)
164! Bugfix: dry residual atmosphere is replaced by standard RRTMG atmosphere
165!
166! 3116 2018-07-10 14:31:58Z suehring
167! Output of long/shortwave radiation at surface
168!
169! 3107 2018-07-06 15:55:51Z suehring
170! Bugfix, missing index for dz
171!
172! 3066 2018-06-12 08:55:55Z Giersch
173! Error message revised
174!
175! 3065 2018-06-12 07:03:02Z Giersch
176! dz was replaced by dz(1), error message concerning vertical stretching was
177! added 
178!
179! 3049 2018-05-29 13:52:36Z Giersch
180! Error messages revised
181!
182! 3045 2018-05-28 07:55:41Z Giersch
183! Error message revised
184!
185! 3026 2018-05-22 10:30:53Z schwenkel
186! Changed the name specific humidity to mixing ratio, since we are computing
187! mixing ratios.
188!
189! 3016 2018-05-09 10:53:37Z Giersch
190! Revised structure of reading svf data according to PALM coding standard:
191! svf_code_field/len and fsvf removed, error messages PA0493 and PA0494 added,
192! allocation status of output arrays checked.
193!
194! 3014 2018-05-09 08:42:38Z maronga
195! Introduced plant canopy height similar to urban canopy height to limit
196! the memory requirement to allocate lad.
197! Deactivated automatic setting of minimum raytracing distance.
198!
199! 3004 2018-04-27 12:33:25Z Giersch
200! Further allocation checks implemented (averaged data will be assigned to fill
201! values if no allocation happened so far)
202!
203! 2995 2018-04-19 12:13:16Z Giersch
204! IF-statement in radiation_init removed so that the calculation of radiative
205! fluxes at model start is done in any case, bugfix in
206! radiation_presimulate_solar_pos (end_time is the sum of end_time and the
207! spinup_time specified in the p3d_file ), list of variables/fields that have
208! to be written out or read in case of restarts has been extended
209!
210! 2977 2018-04-17 10:27:57Z kanani
211! Implement changes from branch radiation (r2948-2971) with minor modifications,
212! plus some formatting.
213! (moh.hefny):
214! - replaced plant_canopy by npcbl to check tree existence to avoid weird
215!   allocation of related arrays (after domain decomposition some domains
216!   contains no trees although plant_canopy (global parameter) is still TRUE).
217! - added a namelist parameter to force RTM settings
218! - enabled the option to switch radiation reflections off
219! - renamed surf_reflections to surface_reflections
220! - removed average_radiation flag from the namelist (now it is implicitly set
221!   in init_3d_model according to RTM)
222! - edited read and write sky view factors and CSF routines to account for
223!   the sub-domains which may not contain any of them
224!
225! 2967 2018-04-13 11:22:08Z raasch
226! bugfix: missing parallel cpp-directives added
227!
228! 2964 2018-04-12 16:04:03Z Giersch
229! Error message PA0491 has been introduced which could be previously found in
230! check_open. The variable numprocs_previous_run is only known in case of
231! initializing_actions == read_restart_data
232!
233! 2963 2018-04-12 14:47:44Z suehring
234! - Introduce index for vegetation/wall, pavement/green-wall and water/window
235!   surfaces, for clearer access of surface fraction, albedo, emissivity, etc. .
236! - Minor bugfix in initialization of albedo for window surfaces
237!
238! 2944 2018-04-03 16:20:18Z suehring
239! Fixed bad commit
240!
241! 2943 2018-04-03 16:17:10Z suehring
242! No read of nsurfl from SVF file since it is calculated in
243! radiation_interaction_init,
244! allocation of arrays in radiation_read_svf only if not yet allocated,
245! update of 2920 revision comment.
246!
247! 2932 2018-03-26 09:39:22Z maronga
248! renamed radiation_par to radiation_parameters
249!
250! 2930 2018-03-23 16:30:46Z suehring
251! Remove default surfaces from radiation model, does not make much sense to
252! apply radiation model without energy-balance solvers; Further, add check for
253! this.
254!
255! 2920 2018-03-22 11:22:01Z kanani
256! - Bugfix: Initialize pcbl array (=-1)
257! RTM version 2.0 (Jaroslav Resler, Pavel Krc, Mohamed Salim):
258! - new major version of radiation interactions
259! - substantially enhanced performance and scalability
260! - processing of direct and diffuse solar radiation separated from reflected
261!   radiation, removed virtual surfaces
262! - new type of sky discretization by azimuth and elevation angles
263! - diffuse radiation processed cumulatively using sky view factor
264! - used precalculated apparent solar positions for direct irradiance
265! - added new 2D raytracing process for processing whole vertical column at once
266!   to increase memory efficiency and decrease number of MPI RMA operations
267! - enabled limiting the number of view factors between surfaces by the distance
268!   and value
269! - fixing issues induced by transferring radiation interactions from
270!   urban_surface_mod to radiation_mod
271! - bugfixes and other minor enhancements
272!
273! 2906 2018-03-19 08:56:40Z Giersch
274! NAMELIST paramter read/write_svf_on_init have been removed, functions
275! check_open and close_file are used now for opening/closing files related to
276! svf data, adjusted unit number and error numbers
277!
278! 2894 2018-03-15 09:17:58Z Giersch
279! Calculations of the index range of the subdomain on file which overlaps with
280! the current subdomain are already done in read_restart_data_mod
281! radiation_read_restart_data was renamed to radiation_rrd_local and
282! radiation_last_actions was renamed to radiation_wrd_local, variable named
283! found has been introduced for checking if restart data was found, reading
284! of restart strings has been moved completely to read_restart_data_mod,
285! radiation_rrd_local is already inside the overlap loop programmed in
286! read_restart_data_mod, the marker *** end rad *** is not necessary anymore,
287! strings and their respective lengths are written out and read now in case of
288! restart runs to get rid of prescribed character lengths (Giersch)
289!
290! 2809 2018-02-15 09:55:58Z suehring
291! Bugfix for gfortran: Replace the function C_SIZEOF with STORAGE_SIZE
292!
293! 2753 2018-01-16 14:16:49Z suehring
294! Tile approach for spectral albedo implemented.
295!
296! 2746 2018-01-15 12:06:04Z suehring
297! Move flag plant canopy to modules
298!
299! 2724 2018-01-05 12:12:38Z maronga
300! Set default of average_radiation to .FALSE.
301!
302! 2723 2018-01-05 09:27:03Z maronga
303! Bugfix in calculation of rad_lw_out (clear-sky). First grid level was used
304! instead of the surface value
305!
306! 2718 2018-01-02 08:49:38Z maronga
307! Corrected "Former revisions" section
308!
309! 2707 2017-12-18 18:34:46Z suehring
310! Changes from last commit documented
311!
312! 2706 2017-12-18 18:33:49Z suehring
313! Bugfix, in average radiation case calculate exner function before using it.
314!
315! 2701 2017-12-15 15:40:50Z suehring
316! Changes from last commit documented
317!
318! 2698 2017-12-14 18:46:24Z suehring
319! Bugfix in get_topography_top_index
320!
321! 2696 2017-12-14 17:12:51Z kanani
322! - Change in file header (GPL part)
323! - Improved reading/writing of SVF from/to file (BM)
324! - Bugfixes concerning RRTMG as well as average_radiation options (M. Salim)
325! - Revised initialization of surface albedo and some minor bugfixes (MS)
326! - Update net radiation after running radiation interaction routine (MS)
327! - Revisions from M Salim included
328! - Adjustment to topography and surface structure (MS)
329! - Initialization of albedo and surface emissivity via input file (MS)
330! - albedo_pars extended (MS)
331!
332! 2604 2017-11-06 13:29:00Z schwenkel
333! bugfix for calculation of effective radius using morrison microphysics
334!
335! 2601 2017-11-02 16:22:46Z scharf
336! added emissivity to namelist
337!
338! 2575 2017-10-24 09:57:58Z maronga
339! Bugfix: calculation of shortwave and longwave albedos for RRTMG swapped
340!
341! 2547 2017-10-16 12:41:56Z schwenkel
342! extended by cloud_droplets option, minor bugfix and correct calculation of
343! cloud droplet number concentration
344!
345! 2544 2017-10-13 18:09:32Z maronga
346! Moved date and time quantitis to separate module date_and_time_mod
347!
348! 2512 2017-10-04 08:26:59Z raasch
349! upper bounds of cross section and 3d output changed from nx+1,ny+1 to nx,ny
350! no output of ghost layer data
351!
352! 2504 2017-09-27 10:36:13Z maronga
353! Updates pavement types and albedo parameters
354!
355! 2328 2017-08-03 12:34:22Z maronga
356! Emissivity can now be set individually for each pixel.
357! Albedo type can be inferred from land surface model.
358! Added default albedo type for bare soil
359!
360! 2318 2017-07-20 17:27:44Z suehring
361! Get topography top index via Function call
362!
363! 2317 2017-07-20 17:27:19Z suehring
364! Improved syntax layout
365!
366! 2298 2017-06-29 09:28:18Z raasch
367! type of write_binary changed from CHARACTER to LOGICAL
368!
369! 2296 2017-06-28 07:53:56Z maronga
370! Added output of rad_sw_out for radiation_scheme = 'constant'
371!
372! 2270 2017-06-09 12:18:47Z maronga
373! Numbering changed (2 timeseries removed)
374!
375! 2249 2017-06-06 13:58:01Z sward
376! Allow for RRTMG runs without humidity/cloud physics
377!
378! 2248 2017-06-06 13:52:54Z sward
379! Error no changed
380!
381! 2233 2017-05-30 18:08:54Z suehring
382!
383! 2232 2017-05-30 17:47:52Z suehring
384! Adjustments to new topography concept
385! Bugfix in read restart
386!
387! 2200 2017-04-11 11:37:51Z suehring
388! Bugfix in call of exchange_horiz_2d and read restart data
389!
390! 2163 2017-03-01 13:23:15Z schwenkel
391! Bugfix in radiation_check_data_output
392!
393! 2157 2017-02-22 15:10:35Z suehring
394! Bugfix in read_restart data
395!
396! 2011 2016-09-19 17:29:57Z kanani
397! Removed CALL of auxiliary SUBROUTINE get_usm_info,
398! flag urban_surface is now defined in module control_parameters.
399!
400! 2007 2016-08-24 15:47:17Z kanani
401! Added calculation of solar directional vector for new urban surface
402! model,
403! accounted for urban_surface model in radiation_check_parameters,
404! correction of comments for zenith angle.
405!
406! 2000 2016-08-20 18:09:15Z knoop
407! Forced header and separation lines into 80 columns
408!
409! 1976 2016-07-27 13:28:04Z maronga
410! Output of 2D/3D/masked data is now directly done within this module. The
411! radiation schemes have been simplified for better usability so that
412! rad_lw_in, rad_lw_out, rad_sw_in, and rad_sw_out are available independent of
413! the radiation code used.
414!
415! 1856 2016-04-13 12:56:17Z maronga
416! Bugfix: allocation of rad_lw_out for radiation_scheme = 'clear-sky'
417!
418! 1853 2016-04-11 09:00:35Z maronga
419! Added routine for radiation_scheme = constant.
420
421! 1849 2016-04-08 11:33:18Z hoffmann
422! Adapted for modularization of microphysics
423!
424! 1826 2016-04-07 12:01:39Z maronga
425! Further modularization.
426!
427! 1788 2016-03-10 11:01:04Z maronga
428! Added new albedo class for pavements / roads.
429!
430! 1783 2016-03-06 18:36:17Z raasch
431! palm-netcdf-module removed in order to avoid a circular module dependency,
432! netcdf-variables moved to netcdf-module, new routine netcdf_handle_error_rad
433! added
434!
435! 1757 2016-02-22 15:49:32Z maronga
436! Added parameter unscheduled_radiation_calls. Bugfix: interpolation of sounding
437! profiles for pressure and temperature above the LES domain.
438!
439! 1709 2015-11-04 14:47:01Z maronga
440! Bugfix: set initial value for rrtm_lwuflx_dt to zero, small formatting
441! corrections
442!
443! 1701 2015-11-02 07:43:04Z maronga
444! Bugfixes: wrong index for output of timeseries, setting of nz_snd_end
445!
446! 1691 2015-10-26 16:17:44Z maronga
447! Added option for spin-up runs without radiation (skip_time_do_radiation). Bugfix
448! in calculation of pressure profiles. Bugfix in calculation of trace gas profiles.
449! Added output of radiative heating rates.
450!
451! 1682 2015-10-07 23:56:08Z knoop
452! Code annotations made doxygen readable
453!
454! 1606 2015-06-29 10:43:37Z maronga
455! Added preprocessor directive __netcdf to allow for compiling without netCDF.
456! Note, however, that RRTMG cannot be used without netCDF.
457!
458! 1590 2015-05-08 13:56:27Z maronga
459! Bugfix: definition of character strings requires same length for all elements
460!
461! 1587 2015-05-04 14:19:01Z maronga
462! Added albedo class for snow
463!
464! 1585 2015-04-30 07:05:52Z maronga
465! Added support for RRTMG
466!
467! 1571 2015-03-12 16:12:49Z maronga
468! Added missing KIND attribute. Removed upper-case variable names
469!
470! 1551 2015-03-03 14:18:16Z maronga
471! Added support for data output. Various variables have been renamed. Added
472! interface for different radiation schemes (currently: clear-sky, constant, and
473! RRTM (not yet implemented).
474!
475! 1496 2014-12-02 17:25:50Z maronga
476! Initial revision
477!
478!
479! Description:
480! ------------
481!> Radiation models and interfaces
482!> @todo Replace dz(1) appropriatly to account for grid stretching
483!> @todo move variable definitions used in radiation_init only to the subroutine
484!>       as they are no longer required after initialization.
485!> @todo Output of full column vertical profiles used in RRTMG
486!> @todo Output of other rrtm arrays (such as volume mixing ratios)
487!> @todo Check for mis-used NINT() calls in raytrace_2d
488!>       RESULT: Original was correct (carefully verified formula), the change
489!>               to INT broke raytracing      -- P. Krc
490!> @todo Optimize radiation_tendency routines
491!>
492!> @note Many variables have a leading dummy dimension (0:0) in order to
493!>       match the assume-size shape expected by the RRTMG model.
494!------------------------------------------------------------------------------!
495 MODULE radiation_model_mod
496 
497    USE arrays_3d,                                                             &
498        ONLY:  dzw, hyp, nc, pt, p, q, ql, u, v, w, zu, zw, exner, d_exner
499
500    USE basic_constants_and_equations_mod,                                     &
501        ONLY:  c_p, g, lv_d_cp, l_v, pi, r_d, rho_l, solar_constant,           &
502               barometric_formula
503
504    USE calc_mean_profile_mod,                                                 &
505        ONLY:  calc_mean_profile
506
507    USE control_parameters,                                                    &
508        ONLY:  cloud_droplets, coupling_char, dz,                              &
509               humidity,                                                       &
510               initializing_actions, io_blocks, io_group,                      &
511               latitude, longitude, large_scale_forcing, lsf_surf,             &
512               message_string, plant_canopy, pt_surface,&
513               rho_surface, surface_pressure, time_since_reference_point,      &
514               urban_surface, land_surface, end_time, spinup_time, dt_spinup
515
516    USE cpulog,                                                                &
517        ONLY:  cpu_log, log_point, log_point_s
518
519    USE grid_variables,                                                        &
520         ONLY:  ddx, ddy, dx, dy 
521
522    USE date_and_time_mod,                                                     &
523        ONLY:  calc_date_and_time, d_hours_day, d_seconds_hour, day_of_year,   &
524               d_seconds_year, day_of_year_init, time_utc_init, time_utc
525
526    USE indices,                                                               &
527        ONLY:  nnx, nny, nx, nxl, nxlg, nxr, nxrg, ny, nyn, nyng, nys, nysg,   &
528               nzb, nzt
529
530    USE, INTRINSIC :: iso_c_binding
531
532    USE kinds
533
534    USE bulk_cloud_model_mod,                                                  &
535        ONLY:  bulk_cloud_model, microphysics_morrison, na_init, nc_const, sigma_gc
536
537#if defined ( __netcdf )
538    USE NETCDF
539#endif
540
541    USE netcdf_data_input_mod,                                                 &
542        ONLY:  albedo_type_f, albedo_pars_f, building_type_f, pavement_type_f, &
543               vegetation_type_f, water_type_f
544
545    USE plant_canopy_model_mod,                                                &
546        ONLY:  lad_s, pc_heating_rate, pc_transpiration_rate
547
548    USE pegrid
549
550#if defined ( __rrtmg )
551    USE parrrsw,                                                               &
552        ONLY:  naerec, nbndsw
553
554    USE parrrtm,                                                               &
555        ONLY:  nbndlw
556
557    USE rrtmg_lw_init,                                                         &
558        ONLY:  rrtmg_lw_ini
559
560    USE rrtmg_sw_init,                                                         &
561        ONLY:  rrtmg_sw_ini
562
563    USE rrtmg_lw_rad,                                                          &
564        ONLY:  rrtmg_lw
565
566    USE rrtmg_sw_rad,                                                          &
567        ONLY:  rrtmg_sw
568#endif
569    USE statistics,                                                            &
570        ONLY:  hom
571
572    USE surface_mod,                                                           &
573        ONLY:  get_topography_top_index, get_topography_top_index_ji,          &
574               ind_pav_green, ind_veg_wall, ind_wat_win,                       &
575               surf_lsm_h, surf_lsm_v, surf_type, surf_usm_h, surf_usm_v
576
577    IMPLICIT NONE
578
579    CHARACTER(10) :: radiation_scheme = 'clear-sky' ! 'constant', 'clear-sky', or 'rrtmg'
580
581!
582!-- Predefined Land surface classes (albedo_type) after Briegleb (1992)
583    CHARACTER(37), DIMENSION(0:33), PARAMETER :: albedo_type_name = (/      &
584                                   'user defined                         ', & !  0
585                                   'ocean                                ', & !  1
586                                   'mixed farming, tall grassland        ', & !  2
587                                   'tall/medium grassland                ', & !  3
588                                   'evergreen shrubland                  ', & !  4
589                                   'short grassland/meadow/shrubland     ', & !  5
590                                   'evergreen needleleaf forest          ', & !  6
591                                   'mixed deciduous evergreen forest     ', & !  7
592                                   'deciduous forest                     ', & !  8
593                                   'tropical evergreen broadleaved forest', & !  9
594                                   'medium/tall grassland/woodland       ', & ! 10
595                                   'desert, sandy                        ', & ! 11
596                                   'desert, rocky                        ', & ! 12
597                                   'tundra                               ', & ! 13
598                                   'land ice                             ', & ! 14
599                                   'sea ice                              ', & ! 15
600                                   'snow                                 ', & ! 16
601                                   'bare soil                            ', & ! 17
602                                   'asphalt/concrete mix                 ', & ! 18
603                                   'asphalt (asphalt concrete)           ', & ! 19
604                                   'concrete (Portland concrete)         ', & ! 20
605                                   'sett                                 ', & ! 21
606                                   'paving stones                        ', & ! 22
607                                   'cobblestone                          ', & ! 23
608                                   'metal                                ', & ! 24
609                                   'wood                                 ', & ! 25
610                                   'gravel                               ', & ! 26
611                                   'fine gravel                          ', & ! 27
612                                   'pebblestone                          ', & ! 28
613                                   'woodchips                            ', & ! 29
614                                   'tartan (sports)                      ', & ! 30
615                                   'artifical turf (sports)              ', & ! 31
616                                   'clay (sports)                        ', & ! 32
617                                   'building (dummy)                     '  & ! 33
618                                                         /)
619
620    REAL(wp), PARAMETER :: sigma_sb       = 5.67037321E-8_wp !< Stefan-Boltzmann constant
621
622    INTEGER(iwp) :: albedo_type  = 9999999, & !< Albedo surface type
623                    dots_rad     = 0          !< starting index for timeseries output
624
625    LOGICAL ::  unscheduled_radiation_calls = .TRUE., & !< flag parameter indicating whether additional calls of the radiation code are allowed
626                constant_albedo = .FALSE.,            & !< flag parameter indicating whether the albedo may change depending on zenith
627                force_radiation_call = .FALSE.,       & !< flag parameter for unscheduled radiation calls
628                lw_radiation = .TRUE.,                & !< flag parameter indicating whether longwave radiation shall be calculated
629                radiation = .FALSE.,                  & !< flag parameter indicating whether the radiation model is used
630                sun_up    = .TRUE.,                   & !< flag parameter indicating whether the sun is up or down
631                sw_radiation = .TRUE.,                & !< flag parameter indicating whether shortwave radiation shall be calculated
632                sun_direction = .FALSE.,              & !< flag parameter indicating whether solar direction shall be calculated
633                average_radiation = .FALSE.,          & !< flag to set the calculation of radiation averaging for the domain
634                radiation_interactions = .FALSE.,     & !< flag to activiate RTM (TRUE only if vertical urban/land surface and trees exist)
635                surface_reflections = .TRUE.,         & !< flag to switch the calculation of radiation interaction between surfaces.
636                                                        !< When it switched off, only the effect of buildings and trees shadow
637                                                        !< will be considered. However fewer SVFs are expected.
638                radiation_interactions_on = .TRUE.      !< namelist flag to force RTM activiation regardless to vertical urban/land surface and trees
639
640    REAL(wp) :: albedo = 9999999.9_wp,           & !< NAMELIST alpha
641                albedo_lw_dif = 9999999.9_wp,    & !< NAMELIST aldif
642                albedo_lw_dir = 9999999.9_wp,    & !< NAMELIST aldir
643                albedo_sw_dif = 9999999.9_wp,    & !< NAMELIST asdif
644                albedo_sw_dir = 9999999.9_wp,    & !< NAMELIST asdir
645                decl_1,                          & !< declination coef. 1
646                decl_2,                          & !< declination coef. 2
647                decl_3,                          & !< declination coef. 3
648                dt_radiation = 0.0_wp,           & !< radiation model timestep
649                emissivity = 9999999.9_wp,       & !< NAMELIST surface emissivity
650                lon = 0.0_wp,                    & !< longitude in radians
651                lat = 0.0_wp,                    & !< latitude in radians
652                net_radiation = 0.0_wp,          & !< net radiation at surface
653                skip_time_do_radiation = 0.0_wp, & !< Radiation model is not called before this time
654                sky_trans,                       & !< sky transmissivity
655                time_radiation = 0.0_wp            !< time since last call of radiation code
656
657
658    REAL(wp), DIMENSION(0:0) ::  zenith,         & !< cosine of solar zenith angle
659                                 sun_dir_lat,    & !< solar directional vector in latitudes
660                                 sun_dir_lon       !< solar directional vector in longitudes
661
662    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_net_av       !< average of net radiation (rad_net) at surface
663    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_lw_in_xy_av  !< average of incoming longwave radiation at surface
664    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_lw_out_xy_av !< average of outgoing longwave radiation at surface
665    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_sw_in_xy_av  !< average of incoming shortwave radiation at surface
666    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_sw_out_xy_av !< average of outgoing shortwave radiation at surface
667!
668!-- Land surface albedos for solar zenith angle of 60° after Briegleb (1992)     
669!-- (shortwave, longwave, broadband):   sw,      lw,      bb,
670    REAL(wp), DIMENSION(0:2,1:33), PARAMETER :: albedo_pars = RESHAPE( (/& 
671                                   0.06_wp, 0.06_wp, 0.06_wp,            & !  1
672                                   0.09_wp, 0.28_wp, 0.19_wp,            & !  2
673                                   0.11_wp, 0.33_wp, 0.23_wp,            & !  3
674                                   0.11_wp, 0.33_wp, 0.23_wp,            & !  4
675                                   0.14_wp, 0.34_wp, 0.25_wp,            & !  5
676                                   0.06_wp, 0.22_wp, 0.14_wp,            & !  6
677                                   0.06_wp, 0.27_wp, 0.17_wp,            & !  7
678                                   0.06_wp, 0.31_wp, 0.19_wp,            & !  8
679                                   0.06_wp, 0.22_wp, 0.14_wp,            & !  9
680                                   0.06_wp, 0.28_wp, 0.18_wp,            & ! 10
681                                   0.35_wp, 0.51_wp, 0.43_wp,            & ! 11
682                                   0.24_wp, 0.40_wp, 0.32_wp,            & ! 12
683                                   0.10_wp, 0.27_wp, 0.19_wp,            & ! 13
684                                   0.90_wp, 0.65_wp, 0.77_wp,            & ! 14
685                                   0.90_wp, 0.65_wp, 0.77_wp,            & ! 15
686                                   0.95_wp, 0.70_wp, 0.82_wp,            & ! 16
687                                   0.08_wp, 0.08_wp, 0.08_wp,            & ! 17
688                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 18
689                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 19
690                                   0.30_wp, 0.30_wp, 0.30_wp,            & ! 20
691                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 21
692                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 22
693                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 23
694                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 24
695                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 25
696                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 26
697                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 27
698                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 28
699                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 29
700                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 30
701                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 31
702                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 32
703                                   0.17_wp, 0.17_wp, 0.17_wp             & ! 33
704                                 /), (/ 3, 33 /) )
705
706    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE, TARGET :: &
707                        rad_lw_cs_hr,                  & !< longwave clear sky radiation heating rate (K/s)
708                        rad_lw_cs_hr_av,               & !< average of rad_lw_cs_hr
709                        rad_lw_hr,                     & !< longwave radiation heating rate (K/s)
710                        rad_lw_hr_av,                  & !< average of rad_sw_hr
711                        rad_lw_in,                     & !< incoming longwave radiation (W/m2)
712                        rad_lw_in_av,                  & !< average of rad_lw_in
713                        rad_lw_out,                    & !< outgoing longwave radiation (W/m2)
714                        rad_lw_out_av,                 & !< average of rad_lw_out
715                        rad_sw_cs_hr,                  & !< shortwave clear sky radiation heating rate (K/s)
716                        rad_sw_cs_hr_av,               & !< average of rad_sw_cs_hr
717                        rad_sw_hr,                     & !< shortwave radiation heating rate (K/s)
718                        rad_sw_hr_av,                  & !< average of rad_sw_hr
719                        rad_sw_in,                     & !< incoming shortwave radiation (W/m2)
720                        rad_sw_in_av,                  & !< average of rad_sw_in
721                        rad_sw_out,                    & !< outgoing shortwave radiation (W/m2)
722                        rad_sw_out_av                    !< average of rad_sw_out
723
724
725!
726!-- Variables and parameters used in RRTMG only
727#if defined ( __rrtmg )
728    CHARACTER(LEN=12) :: rrtm_input_file = "RAD_SND_DATA" !< name of the NetCDF input file (sounding data)
729
730
731!
732!-- Flag parameters for RRTMGS (should not be changed)
733    INTEGER(iwp), PARAMETER :: rrtm_idrv     = 1, & !< flag for longwave upward flux calculation option (0,1)
734                               rrtm_inflglw  = 2, & !< flag for lw cloud optical properties (0,1,2)
735                               rrtm_iceflglw = 0, & !< flag for lw ice particle specifications (0,1,2,3)
736                               rrtm_liqflglw = 1, & !< flag for lw liquid droplet specifications
737                               rrtm_inflgsw  = 2, & !< flag for sw cloud optical properties (0,1,2)
738                               rrtm_iceflgsw = 0, & !< flag for sw ice particle specifications (0,1,2,3)
739                               rrtm_liqflgsw = 1    !< flag for sw liquid droplet specifications
740
741!
742!-- The following variables should be only changed with care, as this will
743!-- require further setting of some variables, which is currently not
744!-- implemented (aerosols, ice phase).
745    INTEGER(iwp) :: nzt_rad,           & !< upper vertical limit for radiation calculations
746                    rrtm_icld = 0,     & !< cloud flag (0: clear sky column, 1: cloudy column)
747                    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)
748
749    INTEGER(iwp) :: nc_stat !< local variable for storin the result of netCDF calls for error message handling
750
751    LOGICAL :: snd_exists = .FALSE.      !< flag parameter to check whether a user-defined input files exists
752
753    REAL(wp), PARAMETER :: mol_mass_air_d_wv = 1.607793_wp !< molecular weight dry air / water vapor
754
755    REAL(wp), DIMENSION(:), ALLOCATABLE :: hyp_snd,     & !< hypostatic pressure from sounding data (hPa)
756                                           rrtm_tsfc,   & !< dummy array for storing surface temperature
757                                           t_snd          !< actual temperature from sounding data (hPa)
758
759    REAL(wp), DIMENSION(:,:), ALLOCATABLE :: rrtm_ccl4vmr,   & !< CCL4 volume mixing ratio (g/mol)
760                                             rrtm_cfc11vmr,  & !< CFC11 volume mixing ratio (g/mol)
761                                             rrtm_cfc12vmr,  & !< CFC12 volume mixing ratio (g/mol)
762                                             rrtm_cfc22vmr,  & !< CFC22 volume mixing ratio (g/mol)
763                                             rrtm_ch4vmr,    & !< CH4 volume mixing ratio
764                                             rrtm_cicewp,    & !< in-cloud ice water path (g/m²)
765                                             rrtm_cldfr,     & !< cloud fraction (0,1)
766                                             rrtm_cliqwp,    & !< in-cloud liquid water path (g/m²)
767                                             rrtm_co2vmr,    & !< CO2 volume mixing ratio (g/mol)
768                                             rrtm_emis,      & !< surface emissivity (0-1) 
769                                             rrtm_h2ovmr,    & !< H2O volume mixing ratio
770                                             rrtm_n2ovmr,    & !< N2O volume mixing ratio
771                                             rrtm_o2vmr,     & !< O2 volume mixing ratio
772                                             rrtm_o3vmr,     & !< O3 volume mixing ratio
773                                             rrtm_play,      & !< pressure layers (hPa, zu-grid)
774                                             rrtm_plev,      & !< pressure layers (hPa, zw-grid)
775                                             rrtm_reice,     & !< cloud ice effective radius (microns)
776                                             rrtm_reliq,     & !< cloud water drop effective radius (microns)
777                                             rrtm_tlay,      & !< actual temperature (K, zu-grid)
778                                             rrtm_tlev,      & !< actual temperature (K, zw-grid)
779                                             rrtm_lwdflx,    & !< RRTM output of incoming longwave radiation flux (W/m2)
780                                             rrtm_lwdflxc,   & !< RRTM output of outgoing clear sky longwave radiation flux (W/m2)
781                                             rrtm_lwuflx,    & !< RRTM output of outgoing longwave radiation flux (W/m2)
782                                             rrtm_lwuflxc,   & !< RRTM output of incoming clear sky longwave radiation flux (W/m2)
783                                             rrtm_lwuflx_dt, & !< RRTM output of incoming clear sky longwave radiation flux (W/m2)
784                                             rrtm_lwuflxc_dt,& !< RRTM output of outgoing clear sky longwave radiation flux (W/m2)
785                                             rrtm_lwhr,      & !< RRTM output of longwave radiation heating rate (K/d)
786                                             rrtm_lwhrc,     & !< RRTM output of incoming longwave clear sky radiation heating rate (K/d)
787                                             rrtm_swdflx,    & !< RRTM output of incoming shortwave radiation flux (W/m2)
788                                             rrtm_swdflxc,   & !< RRTM output of outgoing clear sky shortwave radiation flux (W/m2)
789                                             rrtm_swuflx,    & !< RRTM output of outgoing shortwave radiation flux (W/m2)
790                                             rrtm_swuflxc,   & !< RRTM output of incoming clear sky shortwave radiation flux (W/m2)
791                                             rrtm_swhr,      & !< RRTM output of shortwave radiation heating rate (K/d)
792                                             rrtm_swhrc,     & !< RRTM output of incoming shortwave clear sky radiation heating rate (K/d)
793                                             rrtm_dirdflux,  & !< RRTM output of incoming direct shortwave (W/m2)
794                                             rrtm_difdflux     !< RRTM output of incoming diffuse shortwave (W/m2)
795
796    REAL(wp), DIMENSION(1) ::                rrtm_aldif,     & !< surface albedo for longwave diffuse radiation
797                                             rrtm_aldir,     & !< surface albedo for longwave direct radiation
798                                             rrtm_asdif,     & !< surface albedo for shortwave diffuse radiation
799                                             rrtm_asdir        !< surface albedo for shortwave direct radiation
800
801!
802!-- Definition of arrays that are currently not used for calling RRTMG (due to setting of flag parameters)
803    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::  rad_lw_cs_in,   & !< incoming clear sky longwave radiation (W/m2) (not used)
804                                                rad_lw_cs_out,  & !< outgoing clear sky longwave radiation (W/m2) (not used)
805                                                rad_sw_cs_in,   & !< incoming clear sky shortwave radiation (W/m2) (not used)
806                                                rad_sw_cs_out,  & !< outgoing clear sky shortwave radiation (W/m2) (not used)
807                                                rrtm_lw_tauaer, & !< lw aerosol optical depth
808                                                rrtm_lw_taucld, & !< lw in-cloud optical depth
809                                                rrtm_sw_taucld, & !< sw in-cloud optical depth
810                                                rrtm_sw_ssacld, & !< sw in-cloud single scattering albedo
811                                                rrtm_sw_asmcld, & !< sw in-cloud asymmetry parameter
812                                                rrtm_sw_fsfcld, & !< sw in-cloud forward scattering fraction
813                                                rrtm_sw_tauaer, & !< sw aerosol optical depth
814                                                rrtm_sw_ssaaer, & !< sw aerosol single scattering albedo
815                                                rrtm_sw_asmaer, & !< sw aerosol asymmetry parameter
816                                                rrtm_sw_ecaer     !< sw aerosol optical detph at 0.55 microns (rrtm_iaer = 6 only)
817
818#endif
819!
820!-- Parameters of urban and land surface models
821    INTEGER(iwp)                                   ::  nzu                                !< number of layers of urban surface (will be calculated)
822    INTEGER(iwp)                                   ::  nzp                                !< number of layers of plant canopy (will be calculated)
823    INTEGER(iwp)                                   ::  nzub,nzut                          !< bottom and top layer of urban surface (will be calculated)
824    INTEGER(iwp)                                   ::  nzpt                               !< top layer of plant canopy (will be calculated)
825!-- parameters of urban and land surface models
826    INTEGER(iwp), PARAMETER                        ::  nzut_free = 3                      !< number of free layers above top of of topography
827    INTEGER(iwp), PARAMETER                        ::  ndsvf = 2                          !< number of dimensions of real values in SVF
828    INTEGER(iwp), PARAMETER                        ::  idsvf = 2                          !< number of dimensions of integer values in SVF
829    INTEGER(iwp), PARAMETER                        ::  ndcsf = 1                          !< number of dimensions of real values in CSF
830    INTEGER(iwp), PARAMETER                        ::  idcsf = 2                          !< number of dimensions of integer values in CSF
831    INTEGER(iwp), PARAMETER                        ::  kdcsf = 4                          !< number of dimensions of integer values in CSF calculation array
832    INTEGER(iwp), PARAMETER                        ::  id = 1                             !< position of d-index in surfl and surf
833    INTEGER(iwp), PARAMETER                        ::  iz = 2                             !< position of k-index in surfl and surf
834    INTEGER(iwp), PARAMETER                        ::  iy = 3                             !< position of j-index in surfl and surf
835    INTEGER(iwp), PARAMETER                        ::  ix = 4                             !< position of i-index in surfl and surf
836
837    INTEGER(iwp), PARAMETER                        ::  nsurf_type = 10                    !< number of surf types incl. phys.(land+urban) & (atm.,sky,boundary) surfaces - 1
838
839    INTEGER(iwp), PARAMETER                        ::  iup_u    = 0                       !< 0 - index of urban upward surface (ground or roof)
840    INTEGER(iwp), PARAMETER                        ::  idown_u  = 1                       !< 1 - index of urban downward surface (overhanging)
841    INTEGER(iwp), PARAMETER                        ::  inorth_u = 2                       !< 2 - index of urban northward facing wall
842    INTEGER(iwp), PARAMETER                        ::  isouth_u = 3                       !< 3 - index of urban southward facing wall
843    INTEGER(iwp), PARAMETER                        ::  ieast_u  = 4                       !< 4 - index of urban eastward facing wall
844    INTEGER(iwp), PARAMETER                        ::  iwest_u  = 5                       !< 5 - index of urban westward facing wall
845
846    INTEGER(iwp), PARAMETER                        ::  iup_l    = 6                       !< 6 - index of land upward surface (ground or roof)
847    INTEGER(iwp), PARAMETER                        ::  inorth_l = 7                       !< 7 - index of land northward facing wall
848    INTEGER(iwp), PARAMETER                        ::  isouth_l = 8                       !< 8 - index of land southward facing wall
849    INTEGER(iwp), PARAMETER                        ::  ieast_l  = 9                       !< 9 - index of land eastward facing wall
850    INTEGER(iwp), PARAMETER                        ::  iwest_l  = 10                      !< 10- index of land westward facing wall
851
852    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  idir = (/0, 0,0, 0,1,-1,0,0, 0,1,-1/)   !< surface normal direction x indices
853    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  jdir = (/0, 0,1,-1,0, 0,0,1,-1,0, 0/)   !< surface normal direction y indices
854    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  kdir = (/1,-1,0, 0,0, 0,1,0, 0,0, 0/)   !< surface normal direction z indices
855                                                                                          !< parameter but set in the code
856
857
858!-- indices and sizes of urban and land surface models
859    INTEGER(iwp)                                   ::  startland        !< start index of block of land and roof surfaces
860    INTEGER(iwp)                                   ::  endland          !< end index of block of land and roof surfaces
861    INTEGER(iwp)                                   ::  nlands           !< number of land and roof surfaces in local processor
862    INTEGER(iwp)                                   ::  startwall        !< start index of block of wall surfaces
863    INTEGER(iwp)                                   ::  endwall          !< end index of block of wall surfaces
864    INTEGER(iwp)                                   ::  nwalls           !< number of wall surfaces in local processor
865
866!-- indices and sizes of urban and land surface models
867    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surfl_l          !< coordinates of i-th local surface in local grid - surfl[:,k] = [d, z, y, x]
868    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surf_l           !< coordinates of i-th surface in grid - surf[:,k] = [d, z, y, x]
869    INTEGER(iwp), DIMENSION(:,:), POINTER          ::  surfl            !< coordinates of i-th local surface in local grid - surfl[:,k] = [d, z, y, x]
870    INTEGER(iwp), DIMENSION(:,:), POINTER          ::  surf             !< coordinates of i-th surface in grid - surf[:,k] = [d, z, y, x]
871    INTEGER(iwp)                                   ::  nsurfl           !< number of all surfaces in local processor
872    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  nsurfs           !< array of number of all surfaces in individual processors
873    INTEGER(iwp)                                   ::  nsurf            !< global number of surfaces in index array of surfaces (nsurf = proc nsurfs)
874    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surfstart        !< starts of blocks of surfaces for individual processors in array surf (indexed from 1)
875                                                                        !< respective block for particular processor is surfstart[iproc+1]+1 : surfstart[iproc+1]+nsurfs[iproc+1]
876
877!-- block variables needed for calculation of the plant canopy model inside the urban surface model
878    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pct              !< top layer of the plant canopy
879    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pch              !< heights of the plant canopy
880    INTEGER(iwp)                                   ::  npcbl = 0        !< number of the plant canopy gridboxes in local processor
881    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pcbl             !< k,j,i coordinates of l-th local plant canopy box pcbl[:,l] = [k, j, i]
882    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinsw          !< array of absorbed sw radiation for local plant canopy box
883    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdir       !< array of absorbed direct sw radiation for local plant canopy box
884    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdif       !< array of absorbed diffusion sw radiation for local plant canopy box
885    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinlw          !< array of absorbed lw radiation for local plant canopy box
886
887!-- configuration parameters (they can be setup in PALM config)
888    LOGICAL                                        ::  raytrace_mpi_rma = .TRUE.          !< use MPI RMA to access LAD and gridsurf from remote processes during raytracing
889    LOGICAL                                        ::  read_svf_on_init = .FALSE.         !< flag parameter indicating wheather SVFs will be read from a file at initialization
890    LOGICAL                                        ::  write_svf_on_init = .FALSE.        !< flag parameter indicating wheather SVFs will be written out to a file
891    LOGICAL                                        ::  rad_angular_discretization = .TRUE.!< whether to use fixed resolution discretization of view factors for
892                                                                                          !< reflected radiation (as opposed to all mutually visible pairs)
893    INTEGER(iwp)                                   ::  mrt_nlevels = 0                    !< number of vertical boxes above surface for which to calculate MRT
894    LOGICAL                                        ::  mrt_skip_roof = .TRUE.             !< do not calculate MRT above roof surfaces
895    LOGICAL                                        ::  mrt_include_sw = .TRUE.            !< should MRT calculation include SW radiation as well?
896    INTEGER(iwp)                                   ::  nrefsteps = 0                      !< number of reflection steps to perform
897    REAL(wp), PARAMETER                            ::  ext_coef = 0.6_wp                  !< extinction coefficient (a.k.a. alpha)
898    INTEGER(iwp), PARAMETER                        ::  rad_version_len = 10               !< length of identification string of rad version
899    CHARACTER(rad_version_len), PARAMETER          ::  rad_version = 'RAD v. 1.1'         !< identification of version of binary svf and restart files
900    INTEGER(iwp)                                   ::  raytrace_discrete_elevs = 40       !< number of discretization steps for elevation (nadir to zenith)
901    INTEGER(iwp)                                   ::  raytrace_discrete_azims = 80       !< number of discretization steps for azimuth (out of 360 degrees)
902    REAL(wp)                                       ::  max_raytracing_dist = -999.0_wp    !< maximum distance for raytracing (in metres)
903    REAL(wp)                                       ::  min_irrf_value = 1e-6_wp           !< minimum potential irradiance factor value for raytracing
904    REAL(wp), DIMENSION(1:30)                      ::  svfnorm_report_thresh = 1e21_wp    !< thresholds of SVF normalization values to report
905    INTEGER(iwp)                                   ::  svfnorm_report_num                 !< number of SVF normalization thresholds to report
906
907!-- radiation related arrays to be used in radiation_interaction routine
908    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_sw_in_dir    !< direct sw radiation
909    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_sw_in_diff   !< diffusion sw radiation
910    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_lw_in_diff   !< diffusion lw radiation
911
912!-- parameters required for RRTMG lower boundary condition
913    REAL(wp)                   :: albedo_urb      !< albedo value retuned to RRTMG boundary cond.
914    REAL(wp)                   :: emissivity_urb  !< emissivity value retuned to RRTMG boundary cond.
915    REAL(wp)                   :: t_rad_urb       !< temperature value retuned to RRTMG boundary cond.
916
917!-- type for calculation of svf
918    TYPE t_svf
919        INTEGER(iwp)                               :: isurflt           !<
920        INTEGER(iwp)                               :: isurfs            !<
921        REAL(wp)                                   :: rsvf              !<
922        REAL(wp)                                   :: rtransp           !<
923    END TYPE
924
925!-- type for calculation of csf
926    TYPE t_csf
927        INTEGER(iwp)                               :: ip                !<
928        INTEGER(iwp)                               :: itx               !<
929        INTEGER(iwp)                               :: ity               !<
930        INTEGER(iwp)                               :: itz               !<
931        INTEGER(iwp)                               :: isurfs            !<
932        REAL(wp)                                   :: rsvf              !<
933    END TYPE
934
935!-- arrays storing the values of USM
936    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  svfsurf          !< svfsurf[:,isvf] = index of target and source surface for svf[isvf]
937    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  svf              !< array of shape view factors+direct irradiation factors for local surfaces
938    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfins          !< array of sw radiation falling to local surface after i-th reflection
939    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinl          !< array of lw radiation for local surface after i-th reflection
940
941    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  skyvf            !< array of sky view factor for each local surface
942    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  skyvft           !< array of sky view factor including transparency for each local surface
943    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsitrans         !< dsidir[isvfl,i] = path transmittance of i-th
944                                                                        !< direction of direct solar irradiance per target surface
945    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsitransc        !< dtto per plant canopy box
946    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsidir           !< dsidir[:,i] = unit vector of i-th
947                                                                        !< direction of direct solar irradiance
948    INTEGER(iwp)                                   ::  ndsidir          !< number of apparent solar directions used
949    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  dsidir_rev       !< dsidir_rev[ielev,iazim] = i for dsidir or -1 if not present
950
951    INTEGER(iwp)                                   ::  nmrtbl           !< No. of local grid boxes for which MRT is calculated
952    INTEGER(iwp)                                   ::  nmrtf            !< number of MRT factors for local processor
953    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  mrtbl            !< coordinates of i-th local MRT box - surfl[:,i] = [z, y, x]
954    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  mrtfsurf         !< mrtfsurf[:,imrtf] = index of target MRT box and source surface for mrtf[imrtf]
955    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtf             !< array of MRT factors for each local MRT box
956    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtft            !< array of MRT factors including transparency for each local MRT box
957    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtsky           !< array of sky view factor for each local MRT box
958    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtskyt          !< array of sky view factor including transparency for each local MRT box
959    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  mrtdsit          !< array of direct solar transparencies for each local MRT box
960    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinsw          !< mean SW radiant flux for each MRT box
961    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinlw          !< mean LW radiant flux for each MRT box
962    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrt              !< mean radiant temperature for each MRT box
963    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinsw_av       !< time average mean SW radiant flux for each MRT box
964    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinlw_av       !< time average mean LW radiant flux for each MRT box
965    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrt_av           !< time average mean radiant temperature for each MRT box
966
967    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinsw         !< array of sw radiation falling to local surface including radiation from reflections
968    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlw         !< array of lw radiation falling to local surface including radiation from reflections
969    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdir      !< array of direct sw radiation falling to local surface
970    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdif      !< array of diffuse sw radiation from sky and model boundary falling to local surface
971    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwdif      !< array of diffuse lw radiation from sky and model boundary falling to local surface
972   
973                                                                        !< Outward radiation is only valid for nonvirtual surfaces
974    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsl        !< array of reflected sw radiation for local surface in i-th reflection
975    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutll        !< array of reflected + emitted lw radiation for local surface in i-th reflection
976    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfouts         !< array of reflected sw radiation for all surfaces in i-th reflection
977    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutl         !< array of reflected + emitted lw radiation for all surfaces in i-th reflection
978    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsw        !< array of total sw radiation outgoing from nonvirtual surfaces surfaces after all reflection
979    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutlw        !< array of total lw radiation outgoing from nonvirtual surfaces surfaces after all reflection
980    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfemitlwl      !< array of emitted lw radiation for local surface used to calculate effective surface temperature for radiation model
981
982!-- block variables needed for calculation of the plant canopy model inside the urban surface model
983    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  csfsurf          !< csfsurf[:,icsf] = index of target surface and csf grid index for csf[icsf]
984    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  csf              !< array of plant canopy sink fators + direct irradiation factors (transparency)
985    REAL(wp), DIMENSION(:,:,:), POINTER            ::  sub_lad          !< subset of lad_s within urban surface, transformed to plain Z coordinate
986    REAL(wp), DIMENSION(:), POINTER                ::  sub_lad_g        !< sub_lad globalized (used to avoid MPI RMA calls in raytracing)
987    REAL(wp)                                       ::  prototype_lad    !< prototype leaf area density for computing effective optical depth
988    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  nzterr, plantt   !< temporary global arrays for raytracing
989    INTEGER(iwp)                                   ::  plantt_max
990
991!-- arrays and variables for calculation of svf and csf
992    TYPE(t_svf), DIMENSION(:), POINTER             ::  asvf             !< pointer to growing svc array
993    TYPE(t_csf), DIMENSION(:), POINTER             ::  acsf             !< pointer to growing csf array
994    TYPE(t_svf), DIMENSION(:), POINTER             ::  amrtf            !< pointer to growing mrtf array
995    TYPE(t_svf), DIMENSION(:), ALLOCATABLE, TARGET ::  asvf1, asvf2     !< realizations of svf array
996    TYPE(t_csf), DIMENSION(:), ALLOCATABLE, TARGET ::  acsf1, acsf2     !< realizations of csf array
997    TYPE(t_svf), DIMENSION(:), ALLOCATABLE, TARGET ::  amrtf1, amrtf2   !< realizations of mftf array
998    INTEGER(iwp)                                   ::  nsvfla           !< dimmension of array allocated for storage of svf in local processor
999    INTEGER(iwp)                                   ::  ncsfla           !< dimmension of array allocated for storage of csf in local processor
1000    INTEGER(iwp)                                   ::  nmrtfa           !< dimmension of array allocated for storage of mrt
1001    INTEGER(iwp)                                   ::  msvf, mcsf, mmrtf!< mod for swapping the growing array
1002    INTEGER(iwp), PARAMETER                        ::  gasize = 100000  !< initial size of growing arrays
1003    REAL(wp), PARAMETER                            ::  grow_factor = 1.4_wp !< growth factor of growing arrays
1004    INTEGER(iwp)                                   ::  nsvfl            !< number of svf for local processor
1005    INTEGER(iwp)                                   ::  ncsfl            !< no. of csf in local processor
1006                                                                        !< needed only during calc_svf but must be here because it is
1007                                                                        !< shared between subroutines calc_svf and raytrace
1008    INTEGER(iwp), DIMENSION(:,:,:,:), POINTER      ::  gridsurf         !< reverse index of local surfl[d,k,j,i] (for case rad_angular_discretization)
1009    INTEGER(iwp), DIMENSION(:,:,:), ALLOCATABLE    ::  gridpcbl         !< reverse index of local pcbl[k,j,i]
1010    INTEGER(iwp), PARAMETER                        ::  nsurf_type_u = 6 !< number of urban surf types (used in gridsurf)
1011
1012!-- temporary arrays for calculation of csf in raytracing
1013    INTEGER(iwp)                                   ::  maxboxesg        !< max number of boxes ray can cross in the domain
1014    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  boxes            !< coordinates of gridboxes being crossed by ray
1015    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  crlens           !< array of crossing lengths of ray for particular grid boxes
1016    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  lad_ip           !< array of numbers of process where lad is stored
1017#if defined( __parallel )
1018    INTEGER(kind=MPI_ADDRESS_KIND), &
1019                  DIMENSION(:), ALLOCATABLE        ::  lad_disp         !< array of displaycements of lad in local array of proc lad_ip
1020    INTEGER(iwp)                                   ::  win_lad          !< MPI RMA window for leaf area density
1021    INTEGER(iwp)                                   ::  win_gridsurf     !< MPI RMA window for reverse grid surface index
1022#endif
1023    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  lad_s_ray        !< array of received lad_s for appropriate gridboxes crossed by ray
1024    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  target_surfl
1025    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  rt2_track
1026    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rt2_track_lad
1027    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  rt2_track_dist
1028    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  rt2_dist
1029
1030
1031
1032!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1033!-- Energy balance variables
1034!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1035!-- parameters of the land, roof and wall surfaces
1036    REAL(wp), DIMENSION(:), ALLOCATABLE            :: albedo_surf        !< albedo of the surface
1037    REAL(wp), DIMENSION(:), ALLOCATABLE            :: emiss_surf         !< emissivity of the wall surface
1038
1039
1040    INTERFACE radiation_check_data_output
1041       MODULE PROCEDURE radiation_check_data_output
1042    END INTERFACE radiation_check_data_output
1043
1044    INTERFACE radiation_check_data_output_pr
1045       MODULE PROCEDURE radiation_check_data_output_pr
1046    END INTERFACE radiation_check_data_output_pr
1047 
1048    INTERFACE radiation_check_parameters
1049       MODULE PROCEDURE radiation_check_parameters
1050    END INTERFACE radiation_check_parameters
1051 
1052    INTERFACE radiation_clearsky
1053       MODULE PROCEDURE radiation_clearsky
1054    END INTERFACE radiation_clearsky
1055 
1056    INTERFACE radiation_constant
1057       MODULE PROCEDURE radiation_constant
1058    END INTERFACE radiation_constant
1059 
1060    INTERFACE radiation_control
1061       MODULE PROCEDURE radiation_control
1062    END INTERFACE radiation_control
1063
1064    INTERFACE radiation_3d_data_averaging
1065       MODULE PROCEDURE radiation_3d_data_averaging
1066    END INTERFACE radiation_3d_data_averaging
1067
1068    INTERFACE radiation_data_output_2d
1069       MODULE PROCEDURE radiation_data_output_2d
1070    END INTERFACE radiation_data_output_2d
1071
1072    INTERFACE radiation_data_output_3d
1073       MODULE PROCEDURE radiation_data_output_3d
1074    END INTERFACE radiation_data_output_3d
1075
1076    INTERFACE radiation_data_output_mask
1077       MODULE PROCEDURE radiation_data_output_mask
1078    END INTERFACE radiation_data_output_mask
1079
1080    INTERFACE radiation_define_netcdf_grid
1081       MODULE PROCEDURE radiation_define_netcdf_grid
1082    END INTERFACE radiation_define_netcdf_grid
1083
1084    INTERFACE radiation_header
1085       MODULE PROCEDURE radiation_header
1086    END INTERFACE radiation_header 
1087 
1088    INTERFACE radiation_init
1089       MODULE PROCEDURE radiation_init
1090    END INTERFACE radiation_init
1091
1092    INTERFACE radiation_parin
1093       MODULE PROCEDURE radiation_parin
1094    END INTERFACE radiation_parin
1095   
1096    INTERFACE radiation_rrtmg
1097       MODULE PROCEDURE radiation_rrtmg
1098    END INTERFACE radiation_rrtmg
1099
1100    INTERFACE radiation_tendency
1101       MODULE PROCEDURE radiation_tendency
1102       MODULE PROCEDURE radiation_tendency_ij
1103    END INTERFACE radiation_tendency
1104
1105    INTERFACE radiation_rrd_local
1106       MODULE PROCEDURE radiation_rrd_local
1107    END INTERFACE radiation_rrd_local
1108
1109    INTERFACE radiation_wrd_local
1110       MODULE PROCEDURE radiation_wrd_local
1111    END INTERFACE radiation_wrd_local
1112
1113    INTERFACE radiation_interaction
1114       MODULE PROCEDURE radiation_interaction
1115    END INTERFACE radiation_interaction
1116
1117    INTERFACE radiation_interaction_init
1118       MODULE PROCEDURE radiation_interaction_init
1119    END INTERFACE radiation_interaction_init
1120 
1121    INTERFACE radiation_presimulate_solar_pos
1122       MODULE PROCEDURE radiation_presimulate_solar_pos
1123    END INTERFACE radiation_presimulate_solar_pos
1124
1125    INTERFACE radiation_radflux_gridbox
1126       MODULE PROCEDURE radiation_radflux_gridbox
1127    END INTERFACE radiation_radflux_gridbox
1128
1129    INTERFACE radiation_calc_svf
1130       MODULE PROCEDURE radiation_calc_svf
1131    END INTERFACE radiation_calc_svf
1132
1133    INTERFACE radiation_write_svf
1134       MODULE PROCEDURE radiation_write_svf
1135    END INTERFACE radiation_write_svf
1136
1137    INTERFACE radiation_read_svf
1138       MODULE PROCEDURE radiation_read_svf
1139    END INTERFACE radiation_read_svf
1140
1141
1142    SAVE
1143
1144    PRIVATE
1145
1146!
1147!-- Public functions / NEEDS SORTING
1148    PUBLIC radiation_check_data_output, radiation_check_data_output_pr,        &
1149           radiation_check_parameters, radiation_control,                      &
1150           radiation_header, radiation_init, radiation_parin,                  &
1151           radiation_3d_data_averaging, radiation_tendency,                    &
1152           radiation_data_output_2d, radiation_data_output_3d,                 &
1153           radiation_define_netcdf_grid, radiation_wrd_local,                  &
1154           radiation_rrd_local, radiation_data_output_mask,                    &
1155           radiation_radflux_gridbox, radiation_calc_svf, radiation_write_svf, &
1156           radiation_interaction, radiation_interaction_init,                  &
1157           radiation_read_svf, radiation_presimulate_solar_pos
1158           
1159
1160   
1161!
1162!-- Public variables and constants / NEEDS SORTING
1163    PUBLIC albedo, albedo_type, decl_1, decl_2, decl_3, dots_rad, dt_radiation,&
1164           emissivity, force_radiation_call, lat, lon,                         &
1165           mrt_include_sw, mrt_nlevels, mrtbl, mrtinsw, mrtinlw, nmrtbl,       &
1166           rad_net_av, radiation, radiation_scheme, rad_lw_in,                 &
1167           rad_lw_in_av, rad_lw_out, rad_lw_out_av,                            &
1168           rad_lw_cs_hr, rad_lw_cs_hr_av, rad_lw_hr, rad_lw_hr_av, rad_sw_in,  &
1169           rad_sw_in_av, rad_sw_out, rad_sw_out_av, rad_sw_cs_hr,              &
1170           rad_sw_cs_hr_av, rad_sw_hr, rad_sw_hr_av, sigma_sb, solar_constant, &
1171           skip_time_do_radiation, time_radiation, unscheduled_radiation_calls,&
1172           zenith, calc_zenith, sun_direction, sun_dir_lat, sun_dir_lon,       &
1173           nrefsteps, nsvfl, svf,                                              &
1174           svfsurf, surfinsw, surfinlw, surfins, surfinl, surfinswdir,         &
1175           surfinswdif, surfoutsw, surfoutlw, surfinlwdif, rad_sw_in_dir,      &
1176           rad_sw_in_diff, rad_lw_in_diff, surfouts, surfoutl, surfoutsl,      &
1177           surfoutll, idir, jdir, kdir, id, iz, iy, ix,                        &
1178           surf, surfl, nsurfl, pcbinswdir, pcbinswdif, pcbinsw, pcbinlw,      &
1179           iup_u, inorth_u, isouth_u, ieast_u, iwest_u,                        &
1180           iup_l, inorth_l, isouth_l, ieast_l, iwest_l,                        &
1181           nsurf_type, nzub, nzut, nzu, pch, nsurf,                            &
1182           idsvf, ndsvf, idcsf, ndcsf, kdcsf, pct,                             &
1183           radiation_interactions, startwall, startland, endland, endwall,     &
1184           skyvf, skyvft, radiation_interactions_on, average_radiation, npcbl, &
1185           pcbl
1186
1187#if defined ( __rrtmg )
1188    PUBLIC rrtm_aldif, rrtm_aldir, rrtm_asdif, rrtm_asdir
1189#endif
1190
1191 CONTAINS
1192
1193
1194!------------------------------------------------------------------------------!
1195! Description:
1196! ------------
1197!> This subroutine controls the calls of the radiation schemes
1198!------------------------------------------------------------------------------!
1199    SUBROUTINE radiation_control
1200 
1201 
1202       IMPLICIT NONE
1203
1204
1205       SELECT CASE ( TRIM( radiation_scheme ) )
1206
1207          CASE ( 'constant' )
1208             CALL radiation_constant
1209         
1210          CASE ( 'clear-sky' ) 
1211             CALL radiation_clearsky
1212       
1213          CASE ( 'rrtmg' )
1214             CALL radiation_rrtmg
1215
1216          CASE DEFAULT
1217
1218       END SELECT
1219
1220
1221    END SUBROUTINE radiation_control
1222
1223!------------------------------------------------------------------------------!
1224! Description:
1225! ------------
1226!> Check data output for radiation model
1227!------------------------------------------------------------------------------!
1228    SUBROUTINE radiation_check_data_output( var, unit, i, ilen, k )
1229 
1230 
1231       USE control_parameters,                                                 &
1232           ONLY: data_output, message_string
1233
1234       IMPLICIT NONE
1235
1236       CHARACTER (LEN=*) ::  unit     !<
1237       CHARACTER (LEN=*) ::  var      !<
1238
1239       INTEGER(iwp) :: i
1240       INTEGER(iwp) :: ilen
1241       INTEGER(iwp) :: k
1242
1243       SELECT CASE ( TRIM( var ) )
1244
1245          CASE ( 'rad_lw_cs_hr', 'rad_lw_hr', 'rad_lw_in', 'rad_lw_out', &
1246                 'rad_sw_cs_hr', 'rad_sw_hr', 'rad_sw_in', 'rad_sw_out'  )
1247             IF (  .NOT.  radiation  .OR.  radiation_scheme /= 'rrtmg' )  THEN
1248                message_string = '"output of "' // TRIM( var ) // '" requi' // &
1249                                 'res radiation = .TRUE. and ' //              &
1250                                 'radiation_scheme = "rrtmg"'
1251                CALL message( 'check_parameters', 'PA0406', 1, 2, 0, 6, 0 )
1252             ENDIF
1253             unit = 'K/h'     
1254
1255          CASE ( 'rad_net*', 'rrtm_aldif*', 'rrtm_aldir*', 'rrtm_asdif*',      &
1256                 'rrtm_asdir*', 'rad_lw_in*', 'rad_lw_out*', 'rad_sw_in*',     &
1257                 'rad_sw_out*')
1258             IF ( i == 0 .AND. ilen == 0 .AND. k == 0)  THEN
1259                ! Workaround for masked output (calls with i=ilen=k=0)
1260                unit = 'illegal'
1261                RETURN
1262             ENDIF
1263             IF ( k == 0  .OR.  data_output(i)(ilen-2:ilen) /= '_xy' )  THEN
1264                message_string = 'illegal value for data_output: "' //         &
1265                                 TRIM( var ) // '" & only 2d-horizontal ' //   &
1266                                 'cross sections are allowed for this value'
1267                CALL message( 'check_parameters', 'PA0111', 1, 2, 0, 6, 0 )
1268             ENDIF
1269             IF (  .NOT.  radiation  .OR.  radiation_scheme /= "rrtmg" )  THEN
1270                IF ( TRIM( var ) == 'rrtm_aldif*'  .OR.                        &
1271                     TRIM( var ) == 'rrtm_aldir*'  .OR.                        &
1272                     TRIM( var ) == 'rrtm_asdif*'  .OR.                        &
1273                     TRIM( var ) == 'rrtm_asdir*'      )                       &
1274                THEN
1275                   message_string = 'output of "' // TRIM( var ) // '" require'&
1276                                    // 's radiation = .TRUE. and radiation_sch'&
1277                                    // 'eme = "rrtmg"'
1278                   CALL message( 'check_parameters', 'PA0409', 1, 2, 0, 6, 0 )
1279                ENDIF
1280             ENDIF
1281
1282             IF ( TRIM( var ) == 'rad_net*'      ) unit = 'W/m2'   
1283             IF ( TRIM( var ) == 'rad_lw_in*'    ) unit = 'W/m2'
1284             IF ( TRIM( var ) == 'rad_lw_out*'   ) unit = 'W/m2'
1285             IF ( TRIM( var ) == 'rad_sw_in*'    ) unit = 'W/m2'
1286             IF ( TRIM( var ) == 'rad_sw_out*'   ) unit = 'W/m2'
1287             IF ( TRIM( var ) == 'rad_sw_in'     ) unit = 'W/m2'
1288             IF ( TRIM( var ) == 'rrtm_aldif*'   ) unit = ''   
1289             IF ( TRIM( var ) == 'rrtm_aldir*'   ) unit = '' 
1290             IF ( TRIM( var ) == 'rrtm_asdif*'   ) unit = '' 
1291             IF ( TRIM( var ) == 'rrtm_asdir*'   ) unit = '' 
1292
1293          CASE ( 'rad_mrt', 'rad_mrt_sw', 'rad_mrt_lw'  )
1294
1295             IF ( i == 0 .AND. ilen == 0 .AND. k == 0)  THEN
1296                ! Workaround for masked output (calls with i=ilen=k=0)
1297                unit = 'illegal'
1298                RETURN
1299             ENDIF
1300
1301             IF ( .NOT.  radiation ) THEN
1302                message_string = 'output of "' // TRIM( var ) // '" require'&
1303                                 // 's radiation = .TRUE.'
1304                CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1305             ENDIF
1306             IF ( mrt_nlevels == 0 ) THEN
1307                message_string = 'output of "' // TRIM( var ) // '" require'&
1308                                 // 's mrt_nlevels > 0'
1309                CALL message( 'check_parameters', 'PA0510', 1, 2, 0, 6, 0 )
1310             ENDIF
1311             IF ( TRIM( var ) == 'rad_mrt_sw'  .AND.  .NOT. mrt_include_sw ) THEN
1312                message_string = 'output of "' // TRIM( var ) // '" require'&
1313                                 // 's rad_mrt_sw = .TRUE.'
1314                CALL message( 'check_parameters', 'PA0511', 1, 2, 0, 6, 0 )
1315             ENDIF
1316             IF ( TRIM( var ) == 'rad_mrt' ) THEN
1317                unit = 'K'
1318             ELSE
1319                unit = 'W m-2'
1320             ENDIF
1321
1322          CASE DEFAULT
1323             unit = 'illegal'
1324
1325       END SELECT
1326
1327
1328    END SUBROUTINE radiation_check_data_output
1329
1330!------------------------------------------------------------------------------!
1331! Description:
1332! ------------
1333!> Check data output of profiles for radiation model
1334!------------------------------------------------------------------------------! 
1335    SUBROUTINE radiation_check_data_output_pr( variable, var_count, unit,      &
1336               dopr_unit )
1337 
1338       USE arrays_3d,                                                          &
1339           ONLY: zu
1340
1341       USE control_parameters,                                                 &
1342           ONLY: data_output_pr, message_string
1343
1344       USE indices
1345
1346       USE profil_parameter
1347
1348       USE statistics
1349
1350       IMPLICIT NONE
1351   
1352       CHARACTER (LEN=*) ::  unit      !<
1353       CHARACTER (LEN=*) ::  variable  !<
1354       CHARACTER (LEN=*) ::  dopr_unit !< local value of dopr_unit
1355 
1356       INTEGER(iwp) ::  var_count     !<
1357
1358       SELECT CASE ( TRIM( variable ) )
1359       
1360         CASE ( 'rad_net' )
1361             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme == 'constant' )&
1362             THEN
1363                message_string = 'data_output_pr = ' //                        &
1364                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1365                                 'not available for radiation = .FALSE. or ' //&
1366                                 'radiation_scheme = "constant"'
1367                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1368             ELSE
1369                dopr_index(var_count) = 99
1370                dopr_unit  = 'W/m2'
1371                hom(:,2,99,:)  = SPREAD( zw, 2, statistic_regions+1 )
1372                unit = dopr_unit
1373             ENDIF
1374
1375          CASE ( 'rad_lw_in' )
1376             IF ( (  .NOT.  radiation)  .OR.  radiation_scheme == 'constant' ) &
1377             THEN
1378                message_string = 'data_output_pr = ' //                        &
1379                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1380                                 'not available for radiation = .FALSE. or ' //&
1381                                 'radiation_scheme = "constant"'
1382                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1383             ELSE
1384                dopr_index(var_count) = 100
1385                dopr_unit  = 'W/m2'
1386                hom(:,2,100,:)  = SPREAD( zw, 2, statistic_regions+1 )
1387                unit = dopr_unit 
1388             ENDIF
1389
1390          CASE ( 'rad_lw_out' )
1391             IF ( (  .NOT. radiation )  .OR.  radiation_scheme == 'constant' ) &
1392             THEN
1393                message_string = 'data_output_pr = ' //                        &
1394                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1395                                 'not available for radiation = .FALSE. or ' //&
1396                                 'radiation_scheme = "constant"'
1397                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1398             ELSE
1399                dopr_index(var_count) = 101
1400                dopr_unit  = 'W/m2'
1401                hom(:,2,101,:)  = SPREAD( zw, 2, statistic_regions+1 )
1402                unit = dopr_unit   
1403             ENDIF
1404
1405          CASE ( 'rad_sw_in' )
1406             IF ( (  .NOT. radiation )  .OR.  radiation_scheme == 'constant' ) &
1407             THEN
1408                message_string = 'data_output_pr = ' //                        &
1409                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1410                                 'not available for radiation = .FALSE. or ' //&
1411                                 'radiation_scheme = "constant"'
1412                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1413             ELSE
1414                dopr_index(var_count) = 102
1415                dopr_unit  = 'W/m2'
1416                hom(:,2,102,:)  = SPREAD( zw, 2, statistic_regions+1 )
1417                unit = dopr_unit
1418             ENDIF
1419
1420          CASE ( 'rad_sw_out')
1421             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme == 'constant' )&
1422             THEN
1423                message_string = 'data_output_pr = ' //                        &
1424                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1425                                 'not available for radiation = .FALSE. or ' //&
1426                                 'radiation_scheme = "constant"'
1427                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1428             ELSE
1429                dopr_index(var_count) = 103
1430                dopr_unit  = 'W/m2'
1431                hom(:,2,103,:)  = SPREAD( zw, 2, statistic_regions+1 )
1432                unit = dopr_unit
1433             ENDIF
1434
1435          CASE ( 'rad_lw_cs_hr' )
1436             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1437             THEN
1438                message_string = 'data_output_pr = ' //                        &
1439                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1440                                 'not available for radiation = .FALSE. or ' //&
1441                                 'radiation_scheme /= "rrtmg"'
1442                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1443             ELSE
1444                dopr_index(var_count) = 104
1445                dopr_unit  = 'K/h'
1446                hom(:,2,104,:)  = SPREAD( zu, 2, statistic_regions+1 )
1447                unit = dopr_unit
1448             ENDIF
1449
1450          CASE ( 'rad_lw_hr' )
1451             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1452             THEN
1453                message_string = 'data_output_pr = ' //                        &
1454                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1455                                 'not available for radiation = .FALSE. or ' //&
1456                                 'radiation_scheme /= "rrtmg"'
1457                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1458             ELSE
1459                dopr_index(var_count) = 105
1460                dopr_unit  = 'K/h'
1461                hom(:,2,105,:)  = SPREAD( zu, 2, statistic_regions+1 )
1462                unit = dopr_unit
1463             ENDIF
1464
1465          CASE ( 'rad_sw_cs_hr' )
1466             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1467             THEN
1468                message_string = 'data_output_pr = ' //                        &
1469                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1470                                 'not available for radiation = .FALSE. or ' //&
1471                                 'radiation_scheme /= "rrtmg"'
1472                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1473             ELSE
1474                dopr_index(var_count) = 106
1475                dopr_unit  = 'K/h'
1476                hom(:,2,106,:)  = SPREAD( zu, 2, statistic_regions+1 )
1477                unit = dopr_unit
1478             ENDIF
1479
1480          CASE ( 'rad_sw_hr' )
1481             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1482             THEN
1483                message_string = 'data_output_pr = ' //                        &
1484                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1485                                 'not available for radiation = .FALSE. or ' //&
1486                                 'radiation_scheme /= "rrtmg"'
1487                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1488             ELSE
1489                dopr_index(var_count) = 107
1490                dopr_unit  = 'K/h'
1491                hom(:,2,107,:)  = SPREAD( zu, 2, statistic_regions+1 )
1492                unit = dopr_unit
1493             ENDIF
1494
1495
1496          CASE DEFAULT
1497             unit = 'illegal'
1498
1499       END SELECT
1500
1501
1502    END SUBROUTINE radiation_check_data_output_pr
1503 
1504 
1505!------------------------------------------------------------------------------!
1506! Description:
1507! ------------
1508!> Check parameters routine for radiation model
1509!------------------------------------------------------------------------------!
1510    SUBROUTINE radiation_check_parameters
1511
1512       USE control_parameters,                                                 &
1513           ONLY: land_surface, message_string, urban_surface
1514
1515       USE netcdf_data_input_mod,                                              &
1516           ONLY:  input_pids_static                 
1517   
1518       IMPLICIT NONE
1519       
1520!
1521!--    In case no urban-surface or land-surface model is applied, usage of
1522!--    a radiation model make no sense.         
1523       IF ( .NOT. land_surface  .AND.  .NOT. urban_surface )  THEN
1524          message_string = 'Usage of radiation module is only allowed if ' //  &
1525                           'land-surface and/or urban-surface model is applied.'
1526          CALL message( 'check_parameters', 'PA0486', 1, 2, 0, 6, 0 )
1527       ENDIF
1528
1529       IF ( radiation_scheme /= 'constant'   .AND.                             &
1530            radiation_scheme /= 'clear-sky'  .AND.                             &
1531            radiation_scheme /= 'rrtmg' )  THEN
1532          message_string = 'unknown radiation_scheme = '//                     &
1533                           TRIM( radiation_scheme )
1534          CALL message( 'check_parameters', 'PA0405', 1, 2, 0, 6, 0 )
1535       ELSEIF ( radiation_scheme == 'rrtmg' )  THEN
1536#if ! defined ( __rrtmg )
1537          message_string = 'radiation_scheme = "rrtmg" requires ' //           & 
1538                           'compilation of PALM with pre-processor ' //        &
1539                           'directive -D__rrtmg'
1540          CALL message( 'check_parameters', 'PA0407', 1, 2, 0, 6, 0 )
1541#endif
1542#if defined ( __rrtmg ) && ! defined( __netcdf )
1543          message_string = 'radiation_scheme = "rrtmg" requires ' //           & 
1544                           'the use of NetCDF (preprocessor directive ' //     &
1545                           '-D__netcdf'
1546          CALL message( 'check_parameters', 'PA0412', 1, 2, 0, 6, 0 )
1547#endif
1548
1549       ENDIF
1550!
1551!--    Checks performed only if data is given via namelist only.
1552       IF ( .NOT. input_pids_static )  THEN
1553          IF ( albedo_type == 0  .AND.  albedo == 9999999.9_wp  .AND.          &
1554               radiation_scheme == 'clear-sky')  THEN
1555             message_string = 'radiation_scheme = "clear-sky" in combination'//& 
1556                              'with albedo_type = 0 requires setting of'//     &
1557                              'albedo /= 9999999.9'
1558             CALL message( 'check_parameters', 'PA0410', 1, 2, 0, 6, 0 )
1559          ENDIF
1560
1561          IF ( albedo_type == 0  .AND.  radiation_scheme == 'rrtmg'  .AND.     &
1562             ( albedo_lw_dif == 9999999.9_wp .OR. albedo_lw_dir == 9999999.9_wp&
1563          .OR. albedo_sw_dif == 9999999.9_wp .OR. albedo_sw_dir == 9999999.9_wp& 
1564             ) ) THEN
1565             message_string = 'radiation_scheme = "rrtmg" in combination' //   & 
1566                              'with albedo_type = 0 requires setting of ' //   &
1567                              'albedo_lw_dif /= 9999999.9' //                  &
1568                              'albedo_lw_dir /= 9999999.9' //                  &
1569                              'albedo_sw_dif /= 9999999.9 and' //              &
1570                              'albedo_sw_dir /= 9999999.9'
1571             CALL message( 'check_parameters', 'PA0411', 1, 2, 0, 6, 0 )
1572          ENDIF
1573       ENDIF
1574!
1575!--    Parallel rad_angular_discretization without raytrace_mpi_rma is not implemented
1576#if defined( __parallel )     
1577       IF ( rad_angular_discretization  .AND.  .NOT. raytrace_mpi_rma )  THEN
1578          message_string = 'rad_angular_discretization can only be used ' //  &
1579                           'together with raytrace_mpi_rma or when ' //  &
1580                           'no parallelization is applied.'
1581          CALL message( 'check_parameters', 'PA0486', 1, 2, 0, 6, 0 )
1582       ENDIF
1583#endif
1584
1585       IF ( cloud_droplets  .AND.   radiation_scheme == 'rrtmg'  .AND.         &
1586            average_radiation ) THEN
1587          message_string = 'average_radiation = .T. with radiation_scheme'//   & 
1588                           '= "rrtmg" in combination cloud_droplets = .T.'//   &
1589                           'is not implementd'
1590          CALL message( 'check_parameters', 'PA0560', 1, 2, 0, 6, 0 )
1591       ENDIF
1592
1593!
1594!--    Incialize svf normalization reporting histogram
1595       svfnorm_report_num = 1
1596       DO WHILE ( svfnorm_report_thresh(svfnorm_report_num) < 1e20_wp          &
1597                   .AND. svfnorm_report_num <= 30 )
1598          svfnorm_report_num = svfnorm_report_num + 1
1599       ENDDO
1600       svfnorm_report_num = svfnorm_report_num - 1
1601
1602
1603 
1604    END SUBROUTINE radiation_check_parameters 
1605 
1606 
1607!------------------------------------------------------------------------------!
1608! Description:
1609! ------------
1610!> Initialization of the radiation model
1611!------------------------------------------------------------------------------!
1612    SUBROUTINE radiation_init
1613   
1614       IMPLICIT NONE
1615
1616       INTEGER(iwp) ::  i         !< running index x-direction
1617       INTEGER(iwp) ::  ioff      !< offset in x between surface element reference grid point in atmosphere and actual surface
1618       INTEGER(iwp) ::  j         !< running index y-direction
1619       INTEGER(iwp) ::  joff      !< offset in y between surface element reference grid point in atmosphere and actual surface
1620       INTEGER(iwp) ::  l         !< running index for orientation of vertical surfaces
1621       INTEGER(iwp) ::  m         !< running index for surface elements
1622#if defined( __rrtmg )
1623       INTEGER(iwp) ::  ind_type  !< running index for subgrid-surface tiles
1624#endif
1625
1626!
1627!--    Allocate array for storing the surface net radiation
1628       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_net )  .AND.                      &
1629                  surf_lsm_h%ns > 0  )   THEN
1630          ALLOCATE( surf_lsm_h%rad_net(1:surf_lsm_h%ns) )
1631          surf_lsm_h%rad_net = 0.0_wp 
1632       ENDIF
1633       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_net )  .AND.                      &
1634                  surf_usm_h%ns > 0  )  THEN
1635          ALLOCATE( surf_usm_h%rad_net(1:surf_usm_h%ns) )
1636          surf_usm_h%rad_net = 0.0_wp 
1637       ENDIF
1638       DO  l = 0, 3
1639          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_net )  .AND.                &
1640                     surf_lsm_v(l)%ns > 0  )  THEN
1641             ALLOCATE( surf_lsm_v(l)%rad_net(1:surf_lsm_v(l)%ns) )
1642             surf_lsm_v(l)%rad_net = 0.0_wp 
1643          ENDIF
1644          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_net )  .AND.                &
1645                     surf_usm_v(l)%ns > 0  )  THEN
1646             ALLOCATE( surf_usm_v(l)%rad_net(1:surf_usm_v(l)%ns) )
1647             surf_usm_v(l)%rad_net = 0.0_wp 
1648          ENDIF
1649       ENDDO
1650
1651
1652!
1653!--    Allocate array for storing the surface longwave (out) radiation change
1654       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_lw_out_change_0 )  .AND.          &
1655                  surf_lsm_h%ns > 0  )   THEN
1656          ALLOCATE( surf_lsm_h%rad_lw_out_change_0(1:surf_lsm_h%ns) )
1657          surf_lsm_h%rad_lw_out_change_0 = 0.0_wp 
1658       ENDIF
1659       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_lw_out_change_0 )  .AND.          &
1660                  surf_usm_h%ns > 0  )  THEN
1661          ALLOCATE( surf_usm_h%rad_lw_out_change_0(1:surf_usm_h%ns) )
1662          surf_usm_h%rad_lw_out_change_0 = 0.0_wp 
1663       ENDIF
1664       DO  l = 0, 3
1665          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_lw_out_change_0 )  .AND.    &
1666                     surf_lsm_v(l)%ns > 0  )  THEN
1667             ALLOCATE( surf_lsm_v(l)%rad_lw_out_change_0(1:surf_lsm_v(l)%ns) )
1668             surf_lsm_v(l)%rad_lw_out_change_0 = 0.0_wp 
1669          ENDIF
1670          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_lw_out_change_0 )  .AND.    &
1671                     surf_usm_v(l)%ns > 0  )  THEN
1672             ALLOCATE( surf_usm_v(l)%rad_lw_out_change_0(1:surf_usm_v(l)%ns) )
1673             surf_usm_v(l)%rad_lw_out_change_0 = 0.0_wp 
1674          ENDIF
1675       ENDDO
1676
1677!
1678!--    Allocate surface arrays for incoming/outgoing short/longwave radiation
1679       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_sw_in )  .AND.                    &
1680                  surf_lsm_h%ns > 0  )   THEN
1681          ALLOCATE( surf_lsm_h%rad_sw_in(1:surf_lsm_h%ns)  )
1682          ALLOCATE( surf_lsm_h%rad_sw_out(1:surf_lsm_h%ns) )
1683          ALLOCATE( surf_lsm_h%rad_lw_in(1:surf_lsm_h%ns)  )
1684          ALLOCATE( surf_lsm_h%rad_lw_out(1:surf_lsm_h%ns) )
1685          surf_lsm_h%rad_sw_in  = 0.0_wp 
1686          surf_lsm_h%rad_sw_out = 0.0_wp 
1687          surf_lsm_h%rad_lw_in  = 0.0_wp 
1688          surf_lsm_h%rad_lw_out = 0.0_wp 
1689       ENDIF
1690       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_sw_in )  .AND.                    &
1691                  surf_usm_h%ns > 0  )  THEN
1692          ALLOCATE( surf_usm_h%rad_sw_in(1:surf_usm_h%ns)  )
1693          ALLOCATE( surf_usm_h%rad_sw_out(1:surf_usm_h%ns) )
1694          ALLOCATE( surf_usm_h%rad_lw_in(1:surf_usm_h%ns)  )
1695          ALLOCATE( surf_usm_h%rad_lw_out(1:surf_usm_h%ns) )
1696          surf_usm_h%rad_sw_in  = 0.0_wp 
1697          surf_usm_h%rad_sw_out = 0.0_wp 
1698          surf_usm_h%rad_lw_in  = 0.0_wp 
1699          surf_usm_h%rad_lw_out = 0.0_wp 
1700       ENDIF
1701       DO  l = 0, 3
1702          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_sw_in )  .AND.              &
1703                     surf_lsm_v(l)%ns > 0  )  THEN
1704             ALLOCATE( surf_lsm_v(l)%rad_sw_in(1:surf_lsm_v(l)%ns)  )
1705             ALLOCATE( surf_lsm_v(l)%rad_sw_out(1:surf_lsm_v(l)%ns) )
1706             ALLOCATE( surf_lsm_v(l)%rad_lw_in(1:surf_lsm_v(l)%ns)  )
1707             ALLOCATE( surf_lsm_v(l)%rad_lw_out(1:surf_lsm_v(l)%ns) )
1708             surf_lsm_v(l)%rad_sw_in  = 0.0_wp 
1709             surf_lsm_v(l)%rad_sw_out = 0.0_wp 
1710             surf_lsm_v(l)%rad_lw_in  = 0.0_wp 
1711             surf_lsm_v(l)%rad_lw_out = 0.0_wp 
1712          ENDIF
1713          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_sw_in )  .AND.              &
1714                     surf_usm_v(l)%ns > 0  )  THEN
1715             ALLOCATE( surf_usm_v(l)%rad_sw_in(1:surf_usm_v(l)%ns)  )
1716             ALLOCATE( surf_usm_v(l)%rad_sw_out(1:surf_usm_v(l)%ns) )
1717             ALLOCATE( surf_usm_v(l)%rad_lw_in(1:surf_usm_v(l)%ns)  )
1718             ALLOCATE( surf_usm_v(l)%rad_lw_out(1:surf_usm_v(l)%ns) )
1719             surf_usm_v(l)%rad_sw_in  = 0.0_wp 
1720             surf_usm_v(l)%rad_sw_out = 0.0_wp 
1721             surf_usm_v(l)%rad_lw_in  = 0.0_wp 
1722             surf_usm_v(l)%rad_lw_out = 0.0_wp 
1723          ENDIF
1724       ENDDO
1725!
1726!--    Fix net radiation in case of radiation_scheme = 'constant'
1727       IF ( radiation_scheme == 'constant' )  THEN
1728          IF ( ALLOCATED( surf_lsm_h%rad_net ) )                               &
1729             surf_lsm_h%rad_net    = net_radiation
1730          IF ( ALLOCATED( surf_usm_h%rad_net ) )                               &
1731             surf_usm_h%rad_net    = net_radiation
1732!
1733!--       Todo: weight with inclination angle
1734          DO  l = 0, 3
1735             IF ( ALLOCATED( surf_lsm_v(l)%rad_net ) )                         &
1736                surf_lsm_v(l)%rad_net = net_radiation
1737             IF ( ALLOCATED( surf_usm_v(l)%rad_net ) )                         &
1738                surf_usm_v(l)%rad_net = net_radiation
1739          ENDDO
1740!          radiation = .FALSE.
1741!
1742!--    Calculate orbital constants
1743       ELSE
1744          decl_1 = SIN(23.45_wp * pi / 180.0_wp)
1745          decl_2 = 2.0_wp * pi / 365.0_wp
1746          decl_3 = decl_2 * 81.0_wp
1747          lat    = latitude * pi / 180.0_wp
1748          lon    = longitude * pi / 180.0_wp
1749       ENDIF
1750
1751       IF ( radiation_scheme == 'clear-sky'  .OR.                              &
1752            radiation_scheme == 'constant')  THEN
1753
1754
1755!
1756!--       Allocate arrays for incoming/outgoing short/longwave radiation
1757          IF ( .NOT. ALLOCATED ( rad_sw_in ) )  THEN
1758             ALLOCATE ( rad_sw_in(0:0,nysg:nyng,nxlg:nxrg) )
1759          ENDIF
1760          IF ( .NOT. ALLOCATED ( rad_sw_out ) )  THEN
1761             ALLOCATE ( rad_sw_out(0:0,nysg:nyng,nxlg:nxrg) )
1762          ENDIF
1763
1764          IF ( .NOT. ALLOCATED ( rad_lw_in ) )  THEN
1765             ALLOCATE ( rad_lw_in(0:0,nysg:nyng,nxlg:nxrg) )
1766          ENDIF
1767          IF ( .NOT. ALLOCATED ( rad_lw_out ) )  THEN
1768             ALLOCATE ( rad_lw_out(0:0,nysg:nyng,nxlg:nxrg) )
1769          ENDIF
1770
1771!
1772!--       Allocate average arrays for incoming/outgoing short/longwave radiation
1773          IF ( .NOT. ALLOCATED ( rad_sw_in_av ) )  THEN
1774             ALLOCATE ( rad_sw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
1775          ENDIF
1776          IF ( .NOT. ALLOCATED ( rad_sw_out_av ) )  THEN
1777             ALLOCATE ( rad_sw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
1778          ENDIF
1779
1780          IF ( .NOT. ALLOCATED ( rad_lw_in_av ) )  THEN
1781             ALLOCATE ( rad_lw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
1782          ENDIF
1783          IF ( .NOT. ALLOCATED ( rad_lw_out_av ) )  THEN
1784             ALLOCATE ( rad_lw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
1785          ENDIF
1786!
1787!--       Allocate arrays for broadband albedo, and level 1 initialization
1788!--       via namelist paramter, unless not already allocated.
1789          IF ( .NOT. ALLOCATED(surf_lsm_h%albedo) )  THEN
1790             ALLOCATE( surf_lsm_h%albedo(0:2,1:surf_lsm_h%ns)     )
1791             surf_lsm_h%albedo    = albedo
1792          ENDIF
1793          IF ( .NOT. ALLOCATED(surf_usm_h%albedo) )  THEN
1794             ALLOCATE( surf_usm_h%albedo(0:2,1:surf_usm_h%ns)     )
1795             surf_usm_h%albedo    = albedo
1796          ENDIF
1797
1798          DO  l = 0, 3
1799             IF ( .NOT. ALLOCATED( surf_lsm_v(l)%albedo ) )  THEN
1800                ALLOCATE( surf_lsm_v(l)%albedo(0:2,1:surf_lsm_v(l)%ns) )
1801                surf_lsm_v(l)%albedo = albedo
1802             ENDIF
1803             IF ( .NOT. ALLOCATED( surf_usm_v(l)%albedo ) )  THEN
1804                ALLOCATE( surf_usm_v(l)%albedo(0:2,1:surf_usm_v(l)%ns) )
1805                surf_usm_v(l)%albedo = albedo
1806             ENDIF
1807          ENDDO
1808!
1809!--       Level 2 initialization of broadband albedo via given albedo_type.
1810!--       Only if albedo_type is non-zero. In case of urban surface and
1811!--       input data is read from ASCII file, albedo_type will be zero, so that
1812!--       albedo won't be overwritten.
1813          DO  m = 1, surf_lsm_h%ns
1814             IF ( surf_lsm_h%albedo_type(ind_veg_wall,m) /= 0 )                &
1815                surf_lsm_h%albedo(ind_veg_wall,m) =                            &
1816                           albedo_pars(2,surf_lsm_h%albedo_type(ind_veg_wall,m))
1817             IF ( surf_lsm_h%albedo_type(ind_pav_green,m) /= 0 )               &
1818                surf_lsm_h%albedo(ind_pav_green,m) =                           &
1819                           albedo_pars(2,surf_lsm_h%albedo_type(ind_pav_green,m))
1820             IF ( surf_lsm_h%albedo_type(ind_wat_win,m) /= 0 )                 &
1821                surf_lsm_h%albedo(ind_wat_win,m) =                             &
1822                           albedo_pars(2,surf_lsm_h%albedo_type(ind_wat_win,m))
1823          ENDDO
1824          DO  m = 1, surf_usm_h%ns
1825             IF ( surf_usm_h%albedo_type(ind_veg_wall,m) /= 0 )                &
1826                surf_usm_h%albedo(ind_veg_wall,m) =                            &
1827                           albedo_pars(2,surf_usm_h%albedo_type(ind_veg_wall,m))
1828             IF ( surf_usm_h%albedo_type(ind_pav_green,m) /= 0 )               &
1829                surf_usm_h%albedo(ind_pav_green,m) =                           &
1830                           albedo_pars(2,surf_usm_h%albedo_type(ind_pav_green,m))
1831             IF ( surf_usm_h%albedo_type(ind_wat_win,m) /= 0 )                 &
1832                surf_usm_h%albedo(ind_wat_win,m) =                             &
1833                           albedo_pars(2,surf_usm_h%albedo_type(ind_wat_win,m))
1834          ENDDO
1835
1836          DO  l = 0, 3
1837             DO  m = 1, surf_lsm_v(l)%ns
1838                IF ( surf_lsm_v(l)%albedo_type(ind_veg_wall,m) /= 0 )          &
1839                   surf_lsm_v(l)%albedo(ind_veg_wall,m) =                      &
1840                        albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_veg_wall,m))
1841                IF ( surf_lsm_v(l)%albedo_type(ind_pav_green,m) /= 0 )         &
1842                   surf_lsm_v(l)%albedo(ind_pav_green,m) =                     &
1843                        albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_pav_green,m))
1844                IF ( surf_lsm_v(l)%albedo_type(ind_wat_win,m) /= 0 )           &
1845                   surf_lsm_v(l)%albedo(ind_wat_win,m) =                       &
1846                        albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_wat_win,m))
1847             ENDDO
1848             DO  m = 1, surf_usm_v(l)%ns
1849                IF ( surf_usm_v(l)%albedo_type(ind_veg_wall,m) /= 0 )          &
1850                   surf_usm_v(l)%albedo(ind_veg_wall,m) =                      &
1851                        albedo_pars(2,surf_usm_v(l)%albedo_type(ind_veg_wall,m))
1852                IF ( surf_usm_v(l)%albedo_type(ind_pav_green,m) /= 0 )         &
1853                   surf_usm_v(l)%albedo(ind_pav_green,m) =                     &
1854                        albedo_pars(2,surf_usm_v(l)%albedo_type(ind_pav_green,m))
1855                IF ( surf_usm_v(l)%albedo_type(ind_wat_win,m) /= 0 )           &
1856                   surf_usm_v(l)%albedo(ind_wat_win,m) =                       &
1857                        albedo_pars(2,surf_usm_v(l)%albedo_type(ind_wat_win,m))
1858             ENDDO
1859          ENDDO
1860
1861!
1862!--       Level 3 initialization at grid points where albedo type is zero.
1863!--       This case, albedo is taken from file. In case of constant radiation
1864!--       or clear sky, only broadband albedo is given.
1865          IF ( albedo_pars_f%from_file )  THEN
1866!
1867!--          Horizontal surfaces
1868             DO  m = 1, surf_lsm_h%ns
1869                i = surf_lsm_h%i(m)
1870                j = surf_lsm_h%j(m)
1871                IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
1872                   IF ( surf_lsm_h%albedo_type(ind_veg_wall,m) == 0 )          &
1873                      surf_lsm_h%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
1874                   IF ( surf_lsm_h%albedo_type(ind_pav_green,m) == 0 )         &
1875                      surf_lsm_h%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
1876                   IF ( surf_lsm_h%albedo_type(ind_wat_win,m) == 0 )           &
1877                      surf_lsm_h%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
1878                ENDIF
1879             ENDDO
1880             DO  m = 1, surf_usm_h%ns
1881                i = surf_usm_h%i(m)
1882                j = surf_usm_h%j(m)
1883                IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
1884                   IF ( surf_usm_h%albedo_type(ind_veg_wall,m) == 0 )          &
1885                      surf_usm_h%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
1886                   IF ( surf_usm_h%albedo_type(ind_pav_green,m) == 0 )         &
1887                      surf_usm_h%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
1888                   IF ( surf_usm_h%albedo_type(ind_wat_win,m) == 0 )           &
1889                      surf_usm_h%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
1890                ENDIF
1891             ENDDO 
1892!
1893!--          Vertical surfaces           
1894             DO  l = 0, 3
1895
1896                ioff = surf_lsm_v(l)%ioff
1897                joff = surf_lsm_v(l)%joff
1898                DO  m = 1, surf_lsm_v(l)%ns
1899                   i = surf_lsm_v(l)%i(m) + ioff
1900                   j = surf_lsm_v(l)%j(m) + joff
1901                   IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
1902                      IF ( surf_lsm_v(l)%albedo_type(ind_veg_wall,m) == 0 )    &
1903                         surf_lsm_v(l)%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
1904                      IF ( surf_lsm_v(l)%albedo_type(ind_pav_green,m) == 0 )   &
1905                         surf_lsm_v(l)%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
1906                      IF ( surf_lsm_v(l)%albedo_type(ind_wat_win,m) == 0 )     &
1907                         surf_lsm_v(l)%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
1908                   ENDIF
1909                ENDDO
1910
1911                ioff = surf_usm_v(l)%ioff
1912                joff = surf_usm_v(l)%joff
1913                DO  m = 1, surf_usm_h%ns
1914                   i = surf_usm_h%i(m) + joff
1915                   j = surf_usm_h%j(m) + joff
1916                   IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
1917                      IF ( surf_usm_v(l)%albedo_type(ind_veg_wall,m) == 0 )    &
1918                         surf_usm_v(l)%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
1919                      IF ( surf_usm_v(l)%albedo_type(ind_pav_green,m) == 0 )   &
1920                         surf_usm_v(l)%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
1921                      IF ( surf_usm_v(l)%albedo_type(ind_wat_win,m) == 0 )     &
1922                         surf_lsm_v(l)%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
1923                   ENDIF
1924                ENDDO
1925             ENDDO
1926
1927          ENDIF 
1928!
1929!--    Initialization actions for RRTMG
1930       ELSEIF ( radiation_scheme == 'rrtmg' )  THEN
1931#if defined ( __rrtmg )
1932!
1933!--       Allocate albedos for short/longwave radiation, horizontal surfaces
1934!--       for wall/green/window (USM) or vegetation/pavement/water surfaces
1935!--       (LSM).
1936          ALLOCATE ( surf_lsm_h%aldif(0:2,1:surf_lsm_h%ns)       )
1937          ALLOCATE ( surf_lsm_h%aldir(0:2,1:surf_lsm_h%ns)       )
1938          ALLOCATE ( surf_lsm_h%asdif(0:2,1:surf_lsm_h%ns)       )
1939          ALLOCATE ( surf_lsm_h%asdir(0:2,1:surf_lsm_h%ns)       )
1940          ALLOCATE ( surf_lsm_h%rrtm_aldif(0:2,1:surf_lsm_h%ns)  )
1941          ALLOCATE ( surf_lsm_h%rrtm_aldir(0:2,1:surf_lsm_h%ns)  )
1942          ALLOCATE ( surf_lsm_h%rrtm_asdif(0:2,1:surf_lsm_h%ns)  )
1943          ALLOCATE ( surf_lsm_h%rrtm_asdir(0:2,1:surf_lsm_h%ns)  )
1944
1945          ALLOCATE ( surf_usm_h%aldif(0:2,1:surf_usm_h%ns)       )
1946          ALLOCATE ( surf_usm_h%aldir(0:2,1:surf_usm_h%ns)       )
1947          ALLOCATE ( surf_usm_h%asdif(0:2,1:surf_usm_h%ns)       )
1948          ALLOCATE ( surf_usm_h%asdir(0:2,1:surf_usm_h%ns)       )
1949          ALLOCATE ( surf_usm_h%rrtm_aldif(0:2,1:surf_usm_h%ns)  )
1950          ALLOCATE ( surf_usm_h%rrtm_aldir(0:2,1:surf_usm_h%ns)  )
1951          ALLOCATE ( surf_usm_h%rrtm_asdif(0:2,1:surf_usm_h%ns)  )
1952          ALLOCATE ( surf_usm_h%rrtm_asdir(0:2,1:surf_usm_h%ns)  )
1953
1954!
1955!--       Allocate broadband albedo (temporary for the current radiation
1956!--       implementations)
1957          IF ( .NOT. ALLOCATED(surf_lsm_h%albedo) )                            &
1958             ALLOCATE( surf_lsm_h%albedo(0:2,1:surf_lsm_h%ns)     )
1959          IF ( .NOT. ALLOCATED(surf_usm_h%albedo) )                            &
1960             ALLOCATE( surf_usm_h%albedo(0:2,1:surf_usm_h%ns)     )
1961
1962!
1963!--       Allocate albedos for short/longwave radiation, vertical surfaces
1964          DO  l = 0, 3
1965
1966             ALLOCATE ( surf_lsm_v(l)%aldif(0:2,1:surf_lsm_v(l)%ns)      )
1967             ALLOCATE ( surf_lsm_v(l)%aldir(0:2,1:surf_lsm_v(l)%ns)      )
1968             ALLOCATE ( surf_lsm_v(l)%asdif(0:2,1:surf_lsm_v(l)%ns)      )
1969             ALLOCATE ( surf_lsm_v(l)%asdir(0:2,1:surf_lsm_v(l)%ns)      )
1970
1971             ALLOCATE ( surf_lsm_v(l)%rrtm_aldif(0:2,1:surf_lsm_v(l)%ns) )
1972             ALLOCATE ( surf_lsm_v(l)%rrtm_aldir(0:2,1:surf_lsm_v(l)%ns) )
1973             ALLOCATE ( surf_lsm_v(l)%rrtm_asdif(0:2,1:surf_lsm_v(l)%ns) )
1974             ALLOCATE ( surf_lsm_v(l)%rrtm_asdir(0:2,1:surf_lsm_v(l)%ns) )
1975
1976             ALLOCATE ( surf_usm_v(l)%aldif(0:2,1:surf_usm_v(l)%ns)      )
1977             ALLOCATE ( surf_usm_v(l)%aldir(0:2,1:surf_usm_v(l)%ns)      )
1978             ALLOCATE ( surf_usm_v(l)%asdif(0:2,1:surf_usm_v(l)%ns)      )
1979             ALLOCATE ( surf_usm_v(l)%asdir(0:2,1:surf_usm_v(l)%ns)      )
1980
1981             ALLOCATE ( surf_usm_v(l)%rrtm_aldif(0:2,1:surf_usm_v(l)%ns) )
1982             ALLOCATE ( surf_usm_v(l)%rrtm_aldir(0:2,1:surf_usm_v(l)%ns) )
1983             ALLOCATE ( surf_usm_v(l)%rrtm_asdif(0:2,1:surf_usm_v(l)%ns) )
1984             ALLOCATE ( surf_usm_v(l)%rrtm_asdir(0:2,1:surf_usm_v(l)%ns) )
1985!
1986!--          Allocate broadband albedo (temporary for the current radiation
1987!--          implementations)
1988             IF ( .NOT. ALLOCATED( surf_lsm_v(l)%albedo ) )                    &
1989                ALLOCATE( surf_lsm_v(l)%albedo(0:2,1:surf_lsm_v(l)%ns) )
1990             IF ( .NOT. ALLOCATED( surf_usm_v(l)%albedo ) )                    &
1991                ALLOCATE( surf_usm_v(l)%albedo(0:2,1:surf_usm_v(l)%ns) )
1992
1993          ENDDO
1994!
1995!--       Level 1 initialization of spectral albedos via namelist
1996!--       paramters. Please note, this case all surface tiles are initialized
1997!--       the same.
1998          IF ( surf_lsm_h%ns > 0 )  THEN
1999             surf_lsm_h%aldif  = albedo_lw_dif
2000             surf_lsm_h%aldir  = albedo_lw_dir
2001             surf_lsm_h%asdif  = albedo_sw_dif
2002             surf_lsm_h%asdir  = albedo_sw_dir
2003             surf_lsm_h%albedo = albedo_sw_dif
2004          ENDIF
2005          IF ( surf_usm_h%ns > 0 )  THEN
2006             IF ( surf_usm_h%albedo_from_ascii )  THEN
2007                surf_usm_h%aldif  = surf_usm_h%albedo
2008                surf_usm_h%aldir  = surf_usm_h%albedo
2009                surf_usm_h%asdif  = surf_usm_h%albedo
2010                surf_usm_h%asdir  = surf_usm_h%albedo
2011             ELSE
2012                surf_usm_h%aldif  = albedo_lw_dif
2013                surf_usm_h%aldir  = albedo_lw_dir
2014                surf_usm_h%asdif  = albedo_sw_dif
2015                surf_usm_h%asdir  = albedo_sw_dir
2016                surf_usm_h%albedo = albedo_sw_dif
2017             ENDIF
2018          ENDIF
2019
2020          DO  l = 0, 3
2021
2022             IF ( surf_lsm_v(l)%ns > 0 )  THEN
2023                surf_lsm_v(l)%aldif  = albedo_lw_dif
2024                surf_lsm_v(l)%aldir  = albedo_lw_dir
2025                surf_lsm_v(l)%asdif  = albedo_sw_dif
2026                surf_lsm_v(l)%asdir  = albedo_sw_dir
2027                surf_lsm_v(l)%albedo = albedo_sw_dif
2028             ENDIF
2029
2030             IF ( surf_usm_v(l)%ns > 0 )  THEN
2031                IF ( surf_usm_v(l)%albedo_from_ascii )  THEN
2032                   surf_usm_v(l)%aldif  = surf_usm_v(l)%albedo
2033                   surf_usm_v(l)%aldir  = surf_usm_v(l)%albedo
2034                   surf_usm_v(l)%asdif  = surf_usm_v(l)%albedo
2035                   surf_usm_v(l)%asdir  = surf_usm_v(l)%albedo
2036                ELSE
2037                   surf_usm_v(l)%aldif  = albedo_lw_dif
2038                   surf_usm_v(l)%aldir  = albedo_lw_dir
2039                   surf_usm_v(l)%asdif  = albedo_sw_dif
2040                   surf_usm_v(l)%asdir  = albedo_sw_dir
2041                ENDIF
2042             ENDIF
2043          ENDDO
2044
2045!
2046!--       Level 2 initialization of spectral albedos via albedo_type.
2047!--       Please note, for natural- and urban-type surfaces, a tile approach
2048!--       is applied so that the resulting albedo is calculated via the weighted
2049!--       average of respective surface fractions.
2050          DO  m = 1, surf_lsm_h%ns
2051!
2052!--          Spectral albedos for vegetation/pavement/water surfaces
2053             DO  ind_type = 0, 2
2054                IF ( surf_lsm_h%albedo_type(ind_type,m) /= 0 )  THEN
2055                   surf_lsm_h%aldif(ind_type,m) =                              &
2056                               albedo_pars(0,surf_lsm_h%albedo_type(ind_type,m))
2057                   surf_lsm_h%asdif(ind_type,m) =                              &
2058                               albedo_pars(1,surf_lsm_h%albedo_type(ind_type,m))
2059                   surf_lsm_h%aldir(ind_type,m) =                              &
2060                               albedo_pars(0,surf_lsm_h%albedo_type(ind_type,m))
2061                   surf_lsm_h%asdir(ind_type,m) =                              &
2062                               albedo_pars(1,surf_lsm_h%albedo_type(ind_type,m))
2063                   surf_lsm_h%albedo(ind_type,m) =                             &
2064                               albedo_pars(2,surf_lsm_h%albedo_type(ind_type,m))
2065                ENDIF
2066             ENDDO
2067
2068          ENDDO
2069!
2070!--       For urban surface only if albedo has not been already initialized
2071!--       in the urban-surface model via the ASCII file.
2072          IF ( .NOT. surf_usm_h%albedo_from_ascii )  THEN
2073             DO  m = 1, surf_usm_h%ns
2074!
2075!--             Spectral albedos for wall/green/window surfaces
2076                DO  ind_type = 0, 2
2077                   IF ( surf_usm_h%albedo_type(ind_type,m) /= 0 )  THEN
2078                      surf_usm_h%aldif(ind_type,m) =                           &
2079                               albedo_pars(0,surf_usm_h%albedo_type(ind_type,m))
2080                      surf_usm_h%asdif(ind_type,m) =                           &
2081                               albedo_pars(1,surf_usm_h%albedo_type(ind_type,m))
2082                      surf_usm_h%aldir(ind_type,m) =                           &
2083                               albedo_pars(0,surf_usm_h%albedo_type(ind_type,m))
2084                      surf_usm_h%asdir(ind_type,m) =                           &
2085                               albedo_pars(1,surf_usm_h%albedo_type(ind_type,m))
2086                      surf_usm_h%albedo(ind_type,m) =                          &
2087                               albedo_pars(2,surf_usm_h%albedo_type(ind_type,m))
2088                   ENDIF
2089                ENDDO
2090
2091             ENDDO
2092          ENDIF
2093
2094          DO l = 0, 3
2095
2096             DO  m = 1, surf_lsm_v(l)%ns
2097!
2098!--             Spectral albedos for vegetation/pavement/water surfaces
2099                DO  ind_type = 0, 2
2100                   IF ( surf_lsm_v(l)%albedo_type(ind_type,m) /= 0 )  THEN
2101                      surf_lsm_v(l)%aldif(ind_type,m) =                        &
2102                            albedo_pars(0,surf_lsm_v(l)%albedo_type(ind_type,m))
2103                      surf_lsm_v(l)%asdif(ind_type,m) =                        &
2104                            albedo_pars(1,surf_lsm_v(l)%albedo_type(ind_type,m))
2105                      surf_lsm_v(l)%aldir(ind_type,m) =                        &
2106                            albedo_pars(0,surf_lsm_v(l)%albedo_type(ind_type,m))
2107                      surf_lsm_v(l)%asdir(ind_type,m) =                        &
2108                            albedo_pars(1,surf_lsm_v(l)%albedo_type(ind_type,m))
2109                      surf_lsm_v(l)%albedo(ind_type,m) =                       &
2110                            albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_type,m))
2111                   ENDIF
2112                ENDDO
2113             ENDDO
2114!
2115!--          For urban surface only if albedo has not been already initialized
2116!--          in the urban-surface model via the ASCII file.
2117             IF ( .NOT. surf_usm_v(l)%albedo_from_ascii )  THEN
2118                DO  m = 1, surf_usm_v(l)%ns
2119!
2120!--                Spectral albedos for wall/green/window surfaces
2121                   DO  ind_type = 0, 2
2122                      IF ( surf_usm_v(l)%albedo_type(ind_type,m) /= 0 )  THEN
2123                         surf_usm_v(l)%aldif(ind_type,m) =                     &
2124                            albedo_pars(0,surf_usm_v(l)%albedo_type(ind_type,m))
2125                         surf_usm_v(l)%asdif(ind_type,m) =                     &
2126                            albedo_pars(1,surf_usm_v(l)%albedo_type(ind_type,m))
2127                         surf_usm_v(l)%aldir(ind_type,m) =                     &
2128                            albedo_pars(0,surf_usm_v(l)%albedo_type(ind_type,m))
2129                         surf_usm_v(l)%asdir(ind_type,m) =                     &
2130                            albedo_pars(1,surf_usm_v(l)%albedo_type(ind_type,m))
2131                         surf_usm_v(l)%albedo(ind_type,m) =                    &
2132                            albedo_pars(2,surf_usm_v(l)%albedo_type(ind_type,m))
2133                      ENDIF
2134                   ENDDO
2135
2136                ENDDO
2137             ENDIF
2138          ENDDO
2139!
2140!--       Level 3 initialization at grid points where albedo type is zero.
2141!--       This case, spectral albedos are taken from file if available
2142          IF ( albedo_pars_f%from_file )  THEN
2143!
2144!--          Horizontal
2145             DO  m = 1, surf_lsm_h%ns
2146                i = surf_lsm_h%i(m)
2147                j = surf_lsm_h%j(m)
2148!
2149!--             Spectral albedos for vegetation/pavement/water surfaces
2150                DO  ind_type = 0, 2
2151                   IF ( surf_lsm_h%albedo_type(ind_type,m) == 0 )  THEN
2152                      IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2153                         surf_lsm_h%albedo(ind_type,m) =                       &
2154                                                albedo_pars_f%pars_xy(1,j,i)
2155                      IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2156                         surf_lsm_h%aldir(ind_type,m) =                        &
2157                                                albedo_pars_f%pars_xy(1,j,i)
2158                      IF ( albedo_pars_f%pars_xy(2,j,i) /= albedo_pars_f%fill )&
2159                         surf_lsm_h%aldif(ind_type,m) =                        &
2160                                                albedo_pars_f%pars_xy(2,j,i)
2161                      IF ( albedo_pars_f%pars_xy(3,j,i) /= albedo_pars_f%fill )&
2162                         surf_lsm_h%asdir(ind_type,m) =                        &
2163                                                albedo_pars_f%pars_xy(3,j,i)
2164                      IF ( albedo_pars_f%pars_xy(4,j,i) /= albedo_pars_f%fill )&
2165                         surf_lsm_h%asdif(ind_type,m) =                        &
2166                                                albedo_pars_f%pars_xy(4,j,i)
2167                   ENDIF
2168                ENDDO
2169             ENDDO
2170!
2171!--          For urban surface only if albedo has not been already initialized
2172!--          in the urban-surface model via the ASCII file.
2173             IF ( .NOT. surf_usm_h%albedo_from_ascii )  THEN
2174                DO  m = 1, surf_usm_h%ns
2175                   i = surf_usm_h%i(m)
2176                   j = surf_usm_h%j(m)
2177!
2178!--                Spectral albedos for wall/green/window surfaces
2179                   DO  ind_type = 0, 2
2180                      IF ( surf_usm_h%albedo_type(ind_type,m) == 0 )  THEN
2181                         IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2182                            surf_usm_h%albedo(ind_type,m) =                       &
2183                                                albedo_pars_f%pars_xy(1,j,i)
2184                         IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2185                            surf_usm_h%aldir(ind_type,m) =                        &
2186                                                albedo_pars_f%pars_xy(1,j,i)
2187                         IF ( albedo_pars_f%pars_xy(2,j,i) /= albedo_pars_f%fill )&
2188                            surf_usm_h%aldif(ind_type,m) =                        &
2189                                                albedo_pars_f%pars_xy(2,j,i)
2190                         IF ( albedo_pars_f%pars_xy(3,j,i) /= albedo_pars_f%fill )&
2191                            surf_usm_h%asdir(ind_type,m) =                        &
2192                                                albedo_pars_f%pars_xy(3,j,i)
2193                         IF ( albedo_pars_f%pars_xy(4,j,i) /= albedo_pars_f%fill )&
2194                            surf_usm_h%asdif(ind_type,m) =                        &
2195                                                albedo_pars_f%pars_xy(4,j,i)
2196                      ENDIF
2197                   ENDDO
2198
2199                ENDDO
2200             ENDIF
2201!
2202!--          Vertical
2203             DO  l = 0, 3
2204                ioff = surf_lsm_v(l)%ioff
2205                joff = surf_lsm_v(l)%joff
2206
2207                DO  m = 1, surf_lsm_v(l)%ns
2208                   i = surf_lsm_v(l)%i(m)
2209                   j = surf_lsm_v(l)%j(m)
2210!
2211!--                Spectral albedos for vegetation/pavement/water surfaces
2212                   DO  ind_type = 0, 2
2213                      IF ( surf_lsm_v(l)%albedo_type(ind_type,m) == 0 )  THEN
2214                         IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2215                              albedo_pars_f%fill )                             &
2216                            surf_lsm_v(l)%albedo(ind_type,m) =                 &
2217                                          albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2218                         IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2219                              albedo_pars_f%fill )                             &
2220                            surf_lsm_v(l)%aldir(ind_type,m) =                  &
2221                                          albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2222                         IF ( albedo_pars_f%pars_xy(2,j+joff,i+ioff) /=        &
2223                              albedo_pars_f%fill )                             &
2224                            surf_lsm_v(l)%aldif(ind_type,m) =                  &
2225                                          albedo_pars_f%pars_xy(2,j+joff,i+ioff)
2226                         IF ( albedo_pars_f%pars_xy(3,j+joff,i+ioff) /=        &
2227                              albedo_pars_f%fill )                             &
2228                            surf_lsm_v(l)%asdir(ind_type,m) =                  &
2229                                          albedo_pars_f%pars_xy(3,j+joff,i+ioff)
2230                         IF ( albedo_pars_f%pars_xy(4,j+joff,i+ioff) /=        &
2231                              albedo_pars_f%fill )                             &
2232                            surf_lsm_v(l)%asdif(ind_type,m) =                  &
2233                                          albedo_pars_f%pars_xy(4,j+joff,i+ioff)
2234                      ENDIF
2235                   ENDDO
2236                ENDDO
2237!
2238!--             For urban surface only if albedo has not been already initialized
2239!--             in the urban-surface model via the ASCII file.
2240                IF ( .NOT. surf_usm_v(l)%albedo_from_ascii )  THEN
2241                   ioff = surf_usm_v(l)%ioff
2242                   joff = surf_usm_v(l)%joff
2243
2244                   DO  m = 1, surf_usm_v(l)%ns
2245                      i = surf_usm_v(l)%i(m)
2246                      j = surf_usm_v(l)%j(m)
2247!
2248!--                   Spectral albedos for wall/green/window surfaces
2249                      DO  ind_type = 0, 2
2250                         IF ( surf_usm_v(l)%albedo_type(ind_type,m) == 0 )  THEN
2251                            IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2252                                 albedo_pars_f%fill )                             &
2253                               surf_usm_v(l)%albedo(ind_type,m) =                 &
2254                                             albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2255                            IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2256                                 albedo_pars_f%fill )                             &
2257                               surf_usm_v(l)%aldir(ind_type,m) =                  &
2258                                             albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2259                            IF ( albedo_pars_f%pars_xy(2,j+joff,i+ioff) /=        &
2260                                 albedo_pars_f%fill )                             &
2261                               surf_usm_v(l)%aldif(ind_type,m) =                  &
2262                                             albedo_pars_f%pars_xy(2,j+joff,i+ioff)
2263                            IF ( albedo_pars_f%pars_xy(3,j+joff,i+ioff) /=        &
2264                                 albedo_pars_f%fill )                             &
2265                               surf_usm_v(l)%asdir(ind_type,m) =                  &
2266                                             albedo_pars_f%pars_xy(3,j+joff,i+ioff)
2267                            IF ( albedo_pars_f%pars_xy(4,j+joff,i+ioff) /=        &
2268                                 albedo_pars_f%fill )                             &
2269                               surf_usm_v(l)%asdif(ind_type,m) =                  &
2270                                             albedo_pars_f%pars_xy(4,j+joff,i+ioff)
2271                         ENDIF
2272                      ENDDO
2273
2274                   ENDDO
2275                ENDIF
2276             ENDDO
2277
2278          ENDIF
2279
2280!
2281!--       Calculate initial values of current (cosine of) the zenith angle and
2282!--       whether the sun is up
2283          CALL calc_zenith     
2284!
2285!--       Calculate initial surface albedo for different surfaces
2286          IF ( .NOT. constant_albedo )  THEN
2287!
2288!--          Horizontally aligned natural and urban surfaces
2289             CALL calc_albedo( surf_lsm_h    )
2290             CALL calc_albedo( surf_usm_h    )
2291!
2292!--          Vertically aligned natural and urban surfaces
2293             DO  l = 0, 3
2294                CALL calc_albedo( surf_lsm_v(l) )
2295                CALL calc_albedo( surf_usm_v(l) )
2296             ENDDO
2297          ELSE
2298!
2299!--          Initialize sun-inclination independent spectral albedos
2300!--          Horizontal surfaces
2301             IF ( surf_lsm_h%ns > 0 )  THEN
2302                surf_lsm_h%rrtm_aldir = surf_lsm_h%aldir
2303                surf_lsm_h%rrtm_asdir = surf_lsm_h%asdir
2304                surf_lsm_h%rrtm_aldif = surf_lsm_h%aldif
2305                surf_lsm_h%rrtm_asdif = surf_lsm_h%asdif
2306             ENDIF
2307             IF ( surf_usm_h%ns > 0 )  THEN
2308                surf_usm_h%rrtm_aldir = surf_usm_h%aldir
2309                surf_usm_h%rrtm_asdir = surf_usm_h%asdir
2310                surf_usm_h%rrtm_aldif = surf_usm_h%aldif
2311                surf_usm_h%rrtm_asdif = surf_usm_h%asdif
2312             ENDIF
2313!
2314!--          Vertical surfaces
2315             DO  l = 0, 3
2316                IF ( surf_lsm_v(l)%ns > 0 )  THEN
2317                   surf_lsm_v(l)%rrtm_aldir = surf_lsm_v(l)%aldir
2318                   surf_lsm_v(l)%rrtm_asdir = surf_lsm_v(l)%asdir
2319                   surf_lsm_v(l)%rrtm_aldif = surf_lsm_v(l)%aldif
2320                   surf_lsm_v(l)%rrtm_asdif = surf_lsm_v(l)%asdif
2321                ENDIF
2322                IF ( surf_usm_v(l)%ns > 0 )  THEN
2323                   surf_usm_v(l)%rrtm_aldir = surf_usm_v(l)%aldir
2324                   surf_usm_v(l)%rrtm_asdir = surf_usm_v(l)%asdir
2325                   surf_usm_v(l)%rrtm_aldif = surf_usm_v(l)%aldif
2326                   surf_usm_v(l)%rrtm_asdif = surf_usm_v(l)%asdif
2327                ENDIF
2328             ENDDO
2329
2330          ENDIF
2331
2332!
2333!--       Allocate 3d arrays of radiative fluxes and heating rates
2334          IF ( .NOT. ALLOCATED ( rad_sw_in ) )  THEN
2335             ALLOCATE ( rad_sw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2336             rad_sw_in = 0.0_wp
2337          ENDIF
2338
2339          IF ( .NOT. ALLOCATED ( rad_sw_in_av ) )  THEN
2340             ALLOCATE ( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2341          ENDIF
2342
2343          IF ( .NOT. ALLOCATED ( rad_sw_out ) )  THEN
2344             ALLOCATE ( rad_sw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2345             rad_sw_out = 0.0_wp
2346          ENDIF
2347
2348          IF ( .NOT. ALLOCATED ( rad_sw_out_av ) )  THEN
2349             ALLOCATE ( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2350          ENDIF
2351
2352          IF ( .NOT. ALLOCATED ( rad_sw_hr ) )  THEN
2353             ALLOCATE ( rad_sw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2354             rad_sw_hr = 0.0_wp
2355          ENDIF
2356
2357          IF ( .NOT. ALLOCATED ( rad_sw_hr_av ) )  THEN
2358             ALLOCATE ( rad_sw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2359             rad_sw_hr_av = 0.0_wp
2360          ENDIF
2361
2362          IF ( .NOT. ALLOCATED ( rad_sw_cs_hr ) )  THEN
2363             ALLOCATE ( rad_sw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2364             rad_sw_cs_hr = 0.0_wp
2365          ENDIF
2366
2367          IF ( .NOT. ALLOCATED ( rad_sw_cs_hr_av ) )  THEN
2368             ALLOCATE ( rad_sw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2369             rad_sw_cs_hr_av = 0.0_wp
2370          ENDIF
2371
2372          IF ( .NOT. ALLOCATED ( rad_lw_in ) )  THEN
2373             ALLOCATE ( rad_lw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2374             rad_lw_in     = 0.0_wp
2375          ENDIF
2376
2377          IF ( .NOT. ALLOCATED ( rad_lw_in_av ) )  THEN
2378             ALLOCATE ( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2379          ENDIF
2380
2381          IF ( .NOT. ALLOCATED ( rad_lw_out ) )  THEN
2382             ALLOCATE ( rad_lw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2383            rad_lw_out    = 0.0_wp
2384          ENDIF
2385
2386          IF ( .NOT. ALLOCATED ( rad_lw_out_av ) )  THEN
2387             ALLOCATE ( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2388          ENDIF
2389
2390          IF ( .NOT. ALLOCATED ( rad_lw_hr ) )  THEN
2391             ALLOCATE ( rad_lw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2392             rad_lw_hr = 0.0_wp
2393          ENDIF
2394
2395          IF ( .NOT. ALLOCATED ( rad_lw_hr_av ) )  THEN
2396             ALLOCATE ( rad_lw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2397             rad_lw_hr_av = 0.0_wp
2398          ENDIF
2399
2400          IF ( .NOT. ALLOCATED ( rad_lw_cs_hr ) )  THEN
2401             ALLOCATE ( rad_lw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2402             rad_lw_cs_hr = 0.0_wp
2403          ENDIF
2404
2405          IF ( .NOT. ALLOCATED ( rad_lw_cs_hr_av ) )  THEN
2406             ALLOCATE ( rad_lw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2407             rad_lw_cs_hr_av = 0.0_wp
2408          ENDIF
2409
2410          ALLOCATE ( rad_sw_cs_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2411          ALLOCATE ( rad_sw_cs_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2412          rad_sw_cs_in  = 0.0_wp
2413          rad_sw_cs_out = 0.0_wp
2414
2415          ALLOCATE ( rad_lw_cs_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2416          ALLOCATE ( rad_lw_cs_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2417          rad_lw_cs_in  = 0.0_wp
2418          rad_lw_cs_out = 0.0_wp
2419
2420!
2421!--       Allocate 1-element array for surface temperature
2422!--       (RRTMG anticipates an array as passed argument).
2423          ALLOCATE ( rrtm_tsfc(1) )
2424!
2425!--       Allocate surface emissivity.
2426!--       Values will be given directly before calling rrtm_lw.
2427          ALLOCATE ( rrtm_emis(0:0,1:nbndlw+1) )
2428
2429!
2430!--       Initialize RRTMG
2431          IF ( lw_radiation )  CALL rrtmg_lw_ini ( c_p )
2432          IF ( sw_radiation )  CALL rrtmg_sw_ini ( c_p )
2433
2434!
2435!--       Set input files for RRTMG
2436          INQUIRE(FILE="RAD_SND_DATA", EXIST=snd_exists) 
2437          IF ( .NOT. snd_exists )  THEN
2438             rrtm_input_file = "rrtmg_lw.nc"
2439          ENDIF
2440
2441!
2442!--       Read vertical layers for RRTMG from sounding data
2443!--       The routine provides nzt_rad, hyp_snd(1:nzt_rad),
2444!--       t_snd(nzt+2:nzt_rad), rrtm_play(1:nzt_rad), rrtm_plev(1_nzt_rad+1),
2445!--       rrtm_tlay(nzt+2:nzt_rad), rrtm_tlev(nzt+2:nzt_rad+1)
2446          CALL read_sounding_data
2447
2448!
2449!--       Read trace gas profiles from file. This routine provides
2450!--       the rrtm_ arrays (1:nzt_rad+1)
2451          CALL read_trace_gas_data
2452#endif
2453       ENDIF
2454
2455!
2456!--    Perform user actions if required
2457       CALL user_init_radiation
2458
2459!
2460!--    Calculate radiative fluxes at model start
2461       SELECT CASE ( TRIM( radiation_scheme ) )
2462
2463          CASE ( 'rrtmg' )
2464             CALL radiation_rrtmg
2465
2466          CASE ( 'clear-sky' )
2467             CALL radiation_clearsky
2468
2469          CASE ( 'constant' )
2470             CALL radiation_constant
2471
2472          CASE DEFAULT
2473
2474       END SELECT
2475
2476       RETURN
2477
2478    END SUBROUTINE radiation_init
2479
2480
2481!------------------------------------------------------------------------------!
2482! Description:
2483! ------------
2484!> A simple clear sky radiation model
2485!------------------------------------------------------------------------------!
2486    SUBROUTINE radiation_clearsky
2487
2488
2489       IMPLICIT NONE
2490
2491       INTEGER(iwp) ::  l         !< running index for surface orientation
2492       REAL(wp)     ::  pt1       !< potential temperature at first grid level or mean value at urban layer top
2493       REAL(wp)     ::  pt1_l     !< potential temperature at first grid level or mean value at urban layer top at local subdomain
2494       REAL(wp)     ::  ql1       !< liquid water mixing ratio at first grid level or mean value at urban layer top
2495       REAL(wp)     ::  ql1_l     !< liquid water mixing ratio at first grid level or mean value at urban layer top at local subdomain
2496
2497       TYPE(surf_type), POINTER ::  surf !< pointer on respective surface type, used to generalize routine   
2498
2499!
2500!--    Calculate current zenith angle
2501       CALL calc_zenith
2502
2503!
2504!--    Calculate sky transmissivity
2505       sky_trans = 0.6_wp + 0.2_wp * zenith(0)
2506
2507!
2508!--    Calculate value of the Exner function at model surface
2509!
2510!--    In case averaged radiation is used, calculate mean temperature and
2511!--    liquid water mixing ratio at the urban-layer top.
2512       IF ( average_radiation ) THEN
2513          pt1   = 0.0_wp
2514          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1   = 0.0_wp
2515
2516          pt1_l = SUM( pt(nzut,nys:nyn,nxl:nxr) )
2517          IF ( bulk_cloud_model  .OR.  cloud_droplets  )  ql1_l = SUM( ql(nzut,nys:nyn,nxl:nxr) )
2518
2519#if defined( __parallel )     
2520          IF ( collective_wait )  CALL MPI_BARRIER( comm2d, ierr )
2521          CALL MPI_ALLREDUCE( pt1_l, pt1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
2522          IF ( ierr /= 0 ) THEN
2523              WRITE(9,*) 'Error MPI_AllReduce1:', ierr, pt1_l, pt1
2524              FLUSH(9)
2525          ENDIF
2526
2527          IF ( bulk_cloud_model  .OR.  cloud_droplets ) THEN
2528              CALL MPI_ALLREDUCE( ql1_l, ql1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
2529              IF ( ierr /= 0 ) THEN
2530                  WRITE(9,*) 'Error MPI_AllReduce2:', ierr, ql1_l, ql1
2531                  FLUSH(9)
2532              ENDIF
2533          ENDIF
2534#else
2535          pt1 = pt1_l 
2536          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1 = ql1_l
2537#endif
2538
2539          IF ( bulk_cloud_model  .OR.  cloud_droplets  )  pt1 = pt1 + lv_d_cp / exner(nzut) * ql1
2540!
2541!--       Finally, divide by number of grid points
2542          pt1 = pt1 / REAL( ( nx + 1 ) * ( ny + 1 ), KIND=wp )
2543       ENDIF
2544!
2545!--    Call clear-sky calculation for each surface orientation.
2546!--    First, horizontal surfaces
2547       surf => surf_lsm_h
2548       CALL radiation_clearsky_surf
2549       surf => surf_usm_h
2550       CALL radiation_clearsky_surf
2551!
2552!--    Vertical surfaces
2553       DO  l = 0, 3
2554          surf => surf_lsm_v(l)
2555          CALL radiation_clearsky_surf
2556          surf => surf_usm_v(l)
2557          CALL radiation_clearsky_surf
2558       ENDDO
2559
2560       CONTAINS
2561
2562          SUBROUTINE radiation_clearsky_surf
2563
2564             IMPLICIT NONE
2565
2566             INTEGER(iwp) ::  i         !< index x-direction
2567             INTEGER(iwp) ::  j         !< index y-direction
2568             INTEGER(iwp) ::  k         !< index z-direction
2569             INTEGER(iwp) ::  m         !< running index for surface elements
2570
2571             IF ( surf%ns < 1 )  RETURN
2572
2573!
2574!--          Calculate radiation fluxes and net radiation (rad_net) assuming
2575!--          homogeneous urban radiation conditions.
2576             IF ( average_radiation ) THEN       
2577
2578                k = nzut
2579
2580                surf%rad_sw_in  = solar_constant * sky_trans * zenith(0)
2581                surf%rad_sw_out = albedo_urb * surf%rad_sw_in
2582               
2583                surf%rad_lw_in  = 0.8_wp * sigma_sb * (pt1 * exner(k+1))**4
2584
2585                surf%rad_lw_out = emissivity_urb * sigma_sb * (t_rad_urb)**4   &
2586                                    + (1.0_wp - emissivity_urb) * surf%rad_lw_in
2587
2588                surf%rad_net = surf%rad_sw_in - surf%rad_sw_out                &
2589                             + surf%rad_lw_in - surf%rad_lw_out
2590
2591                surf%rad_lw_out_change_0 = 3.0_wp * emissivity_urb * sigma_sb  &
2592                                           * (t_rad_urb)**3
2593
2594!
2595!--          Calculate radiation fluxes and net radiation (rad_net) for each surface
2596!--          element.
2597             ELSE
2598
2599                DO  m = 1, surf%ns
2600                   i = surf%i(m)
2601                   j = surf%j(m)
2602                   k = surf%k(m)
2603
2604                   surf%rad_sw_in(m) = solar_constant * sky_trans * zenith(0)
2605
2606!
2607!--                Weighted average according to surface fraction.
2608!--                ATTENTION: when radiation interactions are switched on the
2609!--                calculated fluxes below are not actually used as they are
2610!--                overwritten in radiation_interaction.
2611                   surf%rad_sw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
2612                                          surf%albedo(ind_veg_wall,m)          &
2613                                        + surf%frac(ind_pav_green,m) *         &
2614                                          surf%albedo(ind_pav_green,m)         &
2615                                        + surf%frac(ind_wat_win,m)   *         &
2616                                          surf%albedo(ind_wat_win,m) )         &
2617                                        * surf%rad_sw_in(m)
2618
2619                   surf%rad_lw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
2620                                          surf%emissivity(ind_veg_wall,m)      &
2621                                        + surf%frac(ind_pav_green,m) *         &
2622                                          surf%emissivity(ind_pav_green,m)     &
2623                                        + surf%frac(ind_wat_win,m)   *         &
2624                                          surf%emissivity(ind_wat_win,m)       &
2625                                        )                                      &
2626                                        * sigma_sb                             &
2627                                        * ( surf%pt_surface(m) * exner(nzb) )**4
2628
2629                   surf%rad_lw_out_change_0(m) =                               &
2630                                      ( surf%frac(ind_veg_wall,m)  *           &
2631                                        surf%emissivity(ind_veg_wall,m)        &
2632                                      + surf%frac(ind_pav_green,m) *           &
2633                                        surf%emissivity(ind_pav_green,m)       &
2634                                      + surf%frac(ind_wat_win,m)   *           &
2635                                        surf%emissivity(ind_wat_win,m)         &
2636                                      ) * 3.0_wp * sigma_sb                    &
2637                                      * ( surf%pt_surface(m) * exner(nzb) )** 3
2638
2639
2640                   IF ( bulk_cloud_model  .OR.  cloud_droplets  )  THEN
2641                      pt1 = pt(k,j,i) + lv_d_cp / exner(k) * ql(k,j,i)
2642                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb * (pt1 * exner(k))**4
2643                   ELSE
2644                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb * (pt(k,j,i) * exner(k))**4
2645                   ENDIF
2646
2647                   surf%rad_net(m) = surf%rad_sw_in(m) - surf%rad_sw_out(m)    &
2648                                   + surf%rad_lw_in(m) - surf%rad_lw_out(m)
2649
2650                ENDDO
2651
2652             ENDIF
2653
2654!
2655!--          Fill out values in radiation arrays
2656             DO  m = 1, surf%ns
2657                i = surf%i(m)
2658                j = surf%j(m)
2659                rad_sw_in(0,j,i) = surf%rad_sw_in(m)
2660                rad_sw_out(0,j,i) = surf%rad_sw_out(m)
2661                rad_lw_in(0,j,i) = surf%rad_lw_in(m)
2662                rad_lw_out(0,j,i) = surf%rad_lw_out(m)
2663             ENDDO
2664 
2665          END SUBROUTINE radiation_clearsky_surf
2666
2667    END SUBROUTINE radiation_clearsky
2668
2669
2670!------------------------------------------------------------------------------!
2671! Description:
2672! ------------
2673!> This scheme keeps the prescribed net radiation constant during the run
2674!------------------------------------------------------------------------------!
2675    SUBROUTINE radiation_constant
2676
2677
2678       IMPLICIT NONE
2679
2680       INTEGER(iwp) ::  l         !< running index for surface orientation
2681
2682       REAL(wp)     ::  pt1       !< potential temperature at first grid level or mean value at urban layer top
2683       REAL(wp)     ::  pt1_l     !< potential temperature at first grid level or mean value at urban layer top at local subdomain
2684       REAL(wp)     ::  ql1       !< liquid water mixing ratio at first grid level or mean value at urban layer top
2685       REAL(wp)     ::  ql1_l     !< liquid water mixing ratio at first grid level or mean value at urban layer top at local subdomain
2686
2687       TYPE(surf_type), POINTER ::  surf !< pointer on respective surface type, used to generalize routine
2688
2689!
2690!--    In case averaged radiation is used, calculate mean temperature and
2691!--    liquid water mixing ratio at the urban-layer top.
2692       IF ( average_radiation ) THEN   
2693          pt1   = 0.0_wp
2694          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1   = 0.0_wp
2695
2696          pt1_l = SUM( pt(nzut,nys:nyn,nxl:nxr) )
2697          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1_l = SUM( ql(nzut,nys:nyn,nxl:nxr) )
2698
2699#if defined( __parallel )     
2700          IF ( collective_wait )  CALL MPI_BARRIER( comm2d, ierr )
2701          CALL MPI_ALLREDUCE( pt1_l, pt1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
2702          IF ( ierr /= 0 ) THEN
2703              WRITE(9,*) 'Error MPI_AllReduce3:', ierr, pt1_l, pt1
2704              FLUSH(9)
2705          ENDIF
2706          IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
2707             CALL MPI_ALLREDUCE( ql1_l, ql1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
2708             IF ( ierr /= 0 ) THEN
2709                 WRITE(9,*) 'Error MPI_AllReduce4:', ierr, ql1_l, ql1
2710                 FLUSH(9)
2711             ENDIF
2712          ENDIF
2713#else
2714          pt1 = pt1_l
2715          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1 = ql1_l
2716#endif
2717          IF ( bulk_cloud_model  .OR.  cloud_droplets )  pt1 = pt1 + lv_d_cp / exner(nzut+1) * ql1
2718!
2719!--       Finally, divide by number of grid points
2720          pt1 = pt1 / REAL( ( nx + 1 ) * ( ny + 1 ), KIND=wp )
2721       ENDIF
2722
2723!
2724!--    First, horizontal surfaces
2725       surf => surf_lsm_h
2726       CALL radiation_constant_surf
2727       surf => surf_usm_h
2728       CALL radiation_constant_surf
2729!
2730!--    Vertical surfaces
2731       DO  l = 0, 3
2732          surf => surf_lsm_v(l)
2733          CALL radiation_constant_surf
2734          surf => surf_usm_v(l)
2735          CALL radiation_constant_surf
2736       ENDDO
2737
2738       CONTAINS
2739
2740          SUBROUTINE radiation_constant_surf
2741
2742             IMPLICIT NONE
2743
2744             INTEGER(iwp) ::  i         !< index x-direction
2745             INTEGER(iwp) ::  ioff      !< offset between surface element and adjacent grid point along x
2746             INTEGER(iwp) ::  j         !< index y-direction
2747             INTEGER(iwp) ::  joff      !< offset between surface element and adjacent grid point along y
2748             INTEGER(iwp) ::  k         !< index z-direction
2749             INTEGER(iwp) ::  koff      !< offset between surface element and adjacent grid point along z
2750             INTEGER(iwp) ::  m         !< running index for surface elements
2751
2752             IF ( surf%ns < 1 )  RETURN
2753
2754!--          Calculate homogenoeus urban radiation fluxes
2755             IF ( average_radiation ) THEN
2756
2757                surf%rad_net = net_radiation
2758
2759                surf%rad_lw_in  = 0.8_wp * sigma_sb * (pt1 * exner(nzut+1))**4
2760
2761                surf%rad_lw_out = emissivity_urb * sigma_sb * (t_rad_urb)**4   &
2762                                    + ( 1.0_wp - emissivity_urb )             & ! shouldn't be this a bulk value -- emissivity_urb?
2763                                    * surf%rad_lw_in
2764
2765                surf%rad_lw_out_change_0 = 3.0_wp * emissivity_urb * sigma_sb  &
2766                                           * t_rad_urb**3
2767
2768                surf%rad_sw_in = ( surf%rad_net - surf%rad_lw_in               &
2769                                     + surf%rad_lw_out )                       &
2770                                     / ( 1.0_wp - albedo_urb )
2771
2772                surf%rad_sw_out =  albedo_urb * surf%rad_sw_in
2773
2774!
2775!--          Calculate radiation fluxes for each surface element
2776             ELSE
2777!
2778!--             Determine index offset between surface element and adjacent
2779!--             atmospheric grid point
2780                ioff = surf%ioff
2781                joff = surf%joff
2782                koff = surf%koff
2783
2784!
2785!--             Prescribe net radiation and estimate the remaining radiative fluxes
2786                DO  m = 1, surf%ns
2787                   i = surf%i(m)
2788                   j = surf%j(m)
2789                   k = surf%k(m)
2790
2791                   surf%rad_net(m) = net_radiation
2792
2793                   IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
2794                      pt1 = pt(k,j,i) + lv_d_cp / exner(k) * ql(k,j,i)
2795                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb * (pt1 * exner(k))**4
2796                   ELSE
2797                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb *                 &
2798                                             ( pt(k,j,i) * exner(k) )**4
2799                   ENDIF
2800
2801!
2802!--                Weighted average according to surface fraction.
2803                   surf%rad_lw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
2804                                          surf%emissivity(ind_veg_wall,m)      &
2805                                        + surf%frac(ind_pav_green,m) *         &
2806                                          surf%emissivity(ind_pav_green,m)     &
2807                                        + surf%frac(ind_wat_win,m)   *         &
2808                                          surf%emissivity(ind_wat_win,m)       &
2809                                        )                                      &
2810                                      * sigma_sb                               &
2811                                      * ( surf%pt_surface(m) * exner(nzb) )**4
2812
2813                   surf%rad_sw_in(m) = ( surf%rad_net(m) - surf%rad_lw_in(m)   &
2814                                       + surf%rad_lw_out(m) )                  &
2815                                       / ( 1.0_wp -                            &
2816                                          ( surf%frac(ind_veg_wall,m)  *       &
2817                                            surf%albedo(ind_veg_wall,m)        &
2818                                         +  surf%frac(ind_pav_green,m) *       &
2819                                            surf%albedo(ind_pav_green,m)       &
2820                                         +  surf%frac(ind_wat_win,m)   *       &
2821                                            surf%albedo(ind_wat_win,m) )       &
2822                                         )
2823
2824                   surf%rad_sw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
2825                                          surf%albedo(ind_veg_wall,m)          &
2826                                        + surf%frac(ind_pav_green,m) *         &
2827                                          surf%albedo(ind_pav_green,m)         &
2828                                        + surf%frac(ind_wat_win,m)   *         &
2829                                          surf%albedo(ind_wat_win,m) )         &
2830                                      * surf%rad_sw_in(m)
2831
2832                ENDDO
2833
2834             ENDIF
2835
2836!
2837!--          Fill out values in radiation arrays
2838             DO  m = 1, surf%ns
2839                i = surf%i(m)
2840                j = surf%j(m)
2841                rad_sw_in(0,j,i) = surf%rad_sw_in(m)
2842                rad_sw_out(0,j,i) = surf%rad_sw_out(m)
2843                rad_lw_in(0,j,i) = surf%rad_lw_in(m)
2844                rad_lw_out(0,j,i) = surf%rad_lw_out(m)
2845             ENDDO
2846
2847          END SUBROUTINE radiation_constant_surf
2848         
2849
2850    END SUBROUTINE radiation_constant
2851
2852!------------------------------------------------------------------------------!
2853! Description:
2854! ------------
2855!> Header output for radiation model
2856!------------------------------------------------------------------------------!
2857    SUBROUTINE radiation_header ( io )
2858
2859
2860       IMPLICIT NONE
2861 
2862       INTEGER(iwp), INTENT(IN) ::  io            !< Unit of the output file
2863   
2864
2865       
2866!
2867!--    Write radiation model header
2868       WRITE( io, 3 )
2869
2870       IF ( radiation_scheme == "constant" )  THEN
2871          WRITE( io, 4 ) net_radiation
2872       ELSEIF ( radiation_scheme == "clear-sky" )  THEN
2873          WRITE( io, 5 )
2874       ELSEIF ( radiation_scheme == "rrtmg" )  THEN
2875          WRITE( io, 6 )
2876          IF ( .NOT. lw_radiation )  WRITE( io, 10 )
2877          IF ( .NOT. sw_radiation )  WRITE( io, 11 )
2878       ENDIF
2879
2880       IF ( albedo_type_f%from_file  .OR.  vegetation_type_f%from_file  .OR.   &
2881            pavement_type_f%from_file  .OR.  water_type_f%from_file  .OR.      &
2882            building_type_f%from_file )  THEN
2883             WRITE( io, 13 )
2884       ELSE 
2885          IF ( albedo_type == 0 )  THEN
2886             WRITE( io, 7 ) albedo
2887          ELSE
2888             WRITE( io, 8 ) TRIM( albedo_type_name(albedo_type) )
2889          ENDIF
2890       ENDIF
2891       IF ( constant_albedo )  THEN
2892          WRITE( io, 9 )
2893       ENDIF
2894       
2895       WRITE( io, 12 ) dt_radiation
2896 
2897
2898 3 FORMAT (//' Radiation model information:'/                                  &
2899              ' ----------------------------'/)
2900 4 FORMAT ('    --> Using constant net radiation: net_radiation = ', F6.2,     &
2901           // 'W/m**2')
2902 5 FORMAT ('    --> Simple radiation scheme for clear sky is used (no clouds,',&
2903                   ' default)')
2904 6 FORMAT ('    --> RRTMG scheme is used')
2905 7 FORMAT (/'    User-specific surface albedo: albedo =', F6.3)
2906 8 FORMAT (/'    Albedo is set for land surface type: ', A)
2907 9 FORMAT (/'    --> Albedo is fixed during the run')
290810 FORMAT (/'    --> Longwave radiation is disabled')
290911 FORMAT (/'    --> Shortwave radiation is disabled.')
291012 FORMAT  ('    Timestep: dt_radiation = ', F6.2, '  s')
291113 FORMAT (/'    Albedo is set individually for each xy-location, according ', &
2912                 'to given surface type.')
2913
2914
2915    END SUBROUTINE radiation_header
2916   
2917
2918!------------------------------------------------------------------------------!
2919! Description:
2920! ------------
2921!> Parin for &radiation_parameters for radiation model
2922!------------------------------------------------------------------------------!
2923    SUBROUTINE radiation_parin
2924
2925
2926       IMPLICIT NONE
2927
2928       CHARACTER (LEN=80) ::  line  !< dummy string that contains the current line of the parameter file
2929       
2930       NAMELIST /radiation_par/   albedo, albedo_type, albedo_lw_dir,          &
2931                                  albedo_lw_dif, albedo_sw_dir, albedo_sw_dif, &
2932                                  constant_albedo, dt_radiation, emissivity,   &
2933                                  lw_radiation, mrt_nlevels, mrt_skip_roof,    &
2934                                  mrt_include_sw,  net_radiation,              &
2935                                  radiation_scheme, skip_time_do_radiation,    &
2936                                  sw_radiation, unscheduled_radiation_calls,   &
2937                                  max_raytracing_dist, min_irrf_value,         &
2938                                  nrefsteps, raytrace_mpi_rma,                 &
2939                                  surface_reflections, svfnorm_report_thresh,  &
2940                                  radiation_interactions_on,                   &
2941                                  rad_angular_discretization,                  &
2942                                  raytrace_discrete_azims,                     &
2943                                  raytrace_discrete_elevs
2944   
2945       NAMELIST /radiation_parameters/   albedo, albedo_type, albedo_lw_dir,   &
2946                                  albedo_lw_dif, albedo_sw_dir, albedo_sw_dif, &
2947                                  constant_albedo, dt_radiation, emissivity,   &
2948                                  lw_radiation, mrt_nlevels, mrt_skip_roof,    &
2949                                  mrt_include_sw,  net_radiation,              &
2950                                  radiation_scheme, skip_time_do_radiation,    &
2951                                  sw_radiation, unscheduled_radiation_calls,   &
2952                                  max_raytracing_dist, min_irrf_value,         &
2953                                  nrefsteps, raytrace_mpi_rma,                 &
2954                                  surface_reflections, svfnorm_report_thresh,  &
2955                                  radiation_interactions_on,                   &
2956                                  rad_angular_discretization,                  &
2957                                  raytrace_discrete_azims,                     &
2958                                  raytrace_discrete_elevs
2959   
2960       line = ' '
2961       
2962!
2963!--    Try to find radiation model namelist
2964       REWIND ( 11 )
2965       line = ' '
2966       DO WHILE ( INDEX( line, '&radiation_parameters' ) == 0 )
2967          READ ( 11, '(A)', END=12 )  line
2968       ENDDO
2969       BACKSPACE ( 11 )
2970
2971!
2972!--    Read user-defined namelist
2973       READ ( 11, radiation_parameters, ERR = 10 )
2974
2975!
2976!--    Set flag that indicates that the radiation model is switched on
2977       radiation = .TRUE.
2978
2979       GOTO 14
2980
2981 10    BACKSPACE( 11 )
2982       READ( 11 , '(A)') line
2983       CALL parin_fail_message( 'radiation_parameters', line )
2984!
2985!--    Try to find old namelist
2986 12    REWIND ( 11 )
2987       line = ' '
2988       DO WHILE ( INDEX( line, '&radiation_par' ) == 0 )
2989          READ ( 11, '(A)', END=14 )  line
2990       ENDDO
2991       BACKSPACE ( 11 )
2992
2993!
2994!--    Read user-defined namelist
2995       READ ( 11, radiation_par, ERR = 13, END = 14 )
2996
2997       message_string = 'namelist radiation_par is deprecated and will be ' // &
2998                     'removed in near future. Please use namelist ' //         &
2999                     'radiation_parameters instead'
3000       CALL message( 'radiation_parin', 'PA0487', 0, 1, 0, 6, 0 )
3001
3002!
3003!--    Set flag that indicates that the radiation model is switched on
3004       radiation = .TRUE.
3005
3006       IF ( .NOT.  radiation_interactions_on  .AND.  surface_reflections )  THEN
3007          message_string = 'surface_reflections is allowed only when '      // &
3008               'radiation_interactions_on is set to TRUE'
3009          CALL message( 'radiation_parin', 'PA0293',1, 2, 0, 6, 0 )
3010       ENDIF
3011
3012       GOTO 14
3013
3014 13    BACKSPACE( 11 )
3015       READ( 11 , '(A)') line
3016       CALL parin_fail_message( 'radiation_par', line )
3017
3018 14    CONTINUE
3019       
3020    END SUBROUTINE radiation_parin
3021
3022
3023!------------------------------------------------------------------------------!
3024! Description:
3025! ------------
3026!> Implementation of the RRTMG radiation_scheme
3027!------------------------------------------------------------------------------!
3028    SUBROUTINE radiation_rrtmg
3029
3030#if defined ( __rrtmg )
3031       USE indices,                                                            &
3032           ONLY:  nbgp
3033
3034       USE particle_attributes,                                                &
3035           ONLY:  grid_particles, number_of_particles, particles,              &
3036                  particle_advection_start, prt_count
3037
3038       IMPLICIT NONE
3039
3040
3041       INTEGER(iwp) ::  i, j, k, l, m, n !< loop indices
3042       INTEGER(iwp) ::  k_topo     !< topography top index
3043
3044       REAL(wp)     ::  nc_rad, &    !< number concentration of cloud droplets
3045                        s_r2,   &    !< weighted sum over all droplets with r^2
3046                        s_r3         !< weighted sum over all droplets with r^3
3047
3048       REAL(wp), DIMENSION(0:nzt+1) :: pt_av, q_av, ql_av
3049!
3050!--    Just dummy arguments
3051       REAL(wp), DIMENSION(:,:,:), ALLOCATABLE :: rrtm_lw_taucld_dum,          &
3052                                                  rrtm_lw_tauaer_dum,          &
3053                                                  rrtm_sw_taucld_dum,          &
3054                                                  rrtm_sw_ssacld_dum,          &
3055                                                  rrtm_sw_asmcld_dum,          &
3056                                                  rrtm_sw_fsfcld_dum,          &
3057                                                  rrtm_sw_tauaer_dum,          &
3058                                                  rrtm_sw_ssaaer_dum,          &
3059                                                  rrtm_sw_asmaer_dum,          &
3060                                                  rrtm_sw_ecaer_dum
3061
3062!
3063!--    Calculate current (cosine of) zenith angle and whether the sun is up
3064       CALL calc_zenith     
3065!
3066!--    Calculate surface albedo. In case average radiation is applied,
3067!--    this is not required.
3068       IF ( .NOT. constant_albedo )  THEN
3069!
3070!--       Horizontally aligned default, natural and urban surfaces
3071          CALL calc_albedo( surf_lsm_h    )
3072          CALL calc_albedo( surf_usm_h    )
3073!
3074!--       Vertically aligned default, natural and urban surfaces
3075          DO  l = 0, 3
3076             CALL calc_albedo( surf_lsm_v(l) )
3077             CALL calc_albedo( surf_usm_v(l) )
3078          ENDDO
3079       ENDIF
3080
3081!
3082!--    Prepare input data for RRTMG
3083
3084!
3085!--    In case of large scale forcing with surface data, calculate new pressure
3086!--    profile. nzt_rad might be modified by these calls and all required arrays
3087!--    will then be re-allocated
3088       IF ( large_scale_forcing  .AND.  lsf_surf )  THEN
3089          CALL read_sounding_data
3090          CALL read_trace_gas_data
3091       ENDIF
3092
3093
3094       IF ( average_radiation ) THEN
3095
3096          rrtm_asdir(1)  = albedo_urb
3097          rrtm_asdif(1)  = albedo_urb
3098          rrtm_aldir(1)  = albedo_urb
3099          rrtm_aldif(1)  = albedo_urb
3100
3101          rrtm_emis = emissivity_urb
3102!
3103!--       Calculate mean pt profile. Actually, only one height level is required.
3104          CALL calc_mean_profile( pt, 4 )
3105          pt_av = hom(:, 1, 4, 0)
3106         
3107          IF ( humidity )  THEN
3108             CALL calc_mean_profile( q, 41 )
3109             q_av  = hom(:, 1, 41, 0)
3110          ENDIF
3111!
3112!--       Prepare profiles of temperature and H2O volume mixing ratio
3113          rrtm_tlev(0,nzb+1) = t_rad_urb
3114
3115          IF ( bulk_cloud_model )  THEN
3116
3117             CALL calc_mean_profile( ql, 54 )
3118             ! average ql is now in hom(:, 1, 54, 0)
3119             ql_av = hom(:, 1, 54, 0)
3120             
3121             DO k = nzb+1, nzt+1
3122                rrtm_tlay(0,k) = pt_av(k) * ( (hyp(k) ) / 100000._wp       &
3123                                 )**.286_wp + lv_d_cp * ql_av(k)
3124                rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * (q_av(k) - ql_av(k))
3125             ENDDO
3126          ELSE
3127             DO k = nzb+1, nzt+1
3128                rrtm_tlay(0,k) = pt_av(k) * ( (hyp(k) ) / 100000._wp       &
3129                                 )**.286_wp
3130             ENDDO
3131
3132             IF ( humidity )  THEN
3133                DO k = nzb+1, nzt+1
3134                   rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * q_av(k)
3135                ENDDO
3136             ELSE
3137                rrtm_h2ovmr(0,nzb+1:nzt+1) = 0.0_wp
3138             ENDIF
3139          ENDIF
3140
3141!
3142!--       Avoid temperature/humidity jumps at the top of the LES domain by
3143!--       linear interpolation from nzt+2 to nzt+7
3144          DO k = nzt+2, nzt+7
3145             rrtm_tlay(0,k) = rrtm_tlay(0,nzt+1)                            &
3146                           + ( rrtm_tlay(0,nzt+8) - rrtm_tlay(0,nzt+1) )    &
3147                           / ( rrtm_play(0,nzt+8) - rrtm_play(0,nzt+1) )    &
3148                           * ( rrtm_play(0,k) - rrtm_play(0,nzt+1) )
3149
3150             rrtm_h2ovmr(0,k) = rrtm_h2ovmr(0,nzt+1)                        &
3151                           + ( rrtm_h2ovmr(0,nzt+8) - rrtm_h2ovmr(0,nzt+1) )&
3152                           / ( rrtm_play(0,nzt+8)   - rrtm_play(0,nzt+1)   )&
3153                           * ( rrtm_play(0,k) - rrtm_play(0,nzt+1) )
3154
3155          ENDDO
3156
3157!--       Linear interpolate to zw grid
3158          DO k = nzb+2, nzt+8
3159             rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k) -        &
3160                                rrtm_tlay(0,k-1))                           &
3161                                / ( rrtm_play(0,k) - rrtm_play(0,k-1) )     &
3162                                * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
3163          ENDDO
3164
3165
3166!
3167!--       Calculate liquid water path and cloud fraction for each column.
3168!--       Note that LWP is required in g/m² instead of kg/kg m.
3169          rrtm_cldfr  = 0.0_wp
3170          rrtm_reliq  = 0.0_wp
3171          rrtm_cliqwp = 0.0_wp
3172          rrtm_icld   = 0
3173
3174          IF ( bulk_cloud_model )  THEN
3175             DO k = nzb+1, nzt+1
3176                rrtm_cliqwp(0,k) =  ql_av(k) * 1000._wp *                   &
3177                                    (rrtm_plev(0,k) - rrtm_plev(0,k+1))     &
3178                                    * 100._wp / g 
3179
3180                IF ( rrtm_cliqwp(0,k) > 0._wp )  THEN
3181                   rrtm_cldfr(0,k) = 1._wp
3182                   IF ( rrtm_icld == 0 )  rrtm_icld = 1
3183
3184!
3185!--                Calculate cloud droplet effective radius
3186                   rrtm_reliq(0,k) = 1.0E6_wp * ( 3.0_wp * ql_av(k)         &
3187                                     * rho_surface                          &
3188                                     / ( 4.0_wp * pi * nc_const * rho_l )   &
3189                                     )**0.33333333333333_wp                 &
3190                                     * EXP( LOG( sigma_gc )**2 )
3191!
3192!--                Limit effective radius
3193                   IF ( rrtm_reliq(0,k) > 0.0_wp )  THEN
3194                      rrtm_reliq(0,k) = MAX(rrtm_reliq(0,k),2.5_wp)
3195                      rrtm_reliq(0,k) = MIN(rrtm_reliq(0,k),60.0_wp)
3196                   ENDIF
3197                ENDIF
3198             ENDDO
3199          ENDIF
3200
3201!
3202!--       Set surface temperature
3203          rrtm_tsfc = t_rad_urb
3204         
3205          IF ( lw_radiation )  THEN       
3206         
3207             CALL rrtmg_lw( 1, nzt_rad      , rrtm_icld    , rrtm_idrv      ,&
3208             rrtm_play       , rrtm_plev    , rrtm_tlay    , rrtm_tlev      ,&
3209             rrtm_tsfc       , rrtm_h2ovmr  , rrtm_o3vmr   , rrtm_co2vmr    ,&
3210             rrtm_ch4vmr     , rrtm_n2ovmr  , rrtm_o2vmr   , rrtm_cfc11vmr  ,&
3211             rrtm_cfc12vmr   , rrtm_cfc22vmr, rrtm_ccl4vmr , rrtm_emis      ,&
3212             rrtm_inflglw    , rrtm_iceflglw, rrtm_liqflglw, rrtm_cldfr     ,&
3213             rrtm_lw_taucld  , rrtm_cicewp  , rrtm_cliqwp  , rrtm_reice     ,& 
3214             rrtm_reliq      , rrtm_lw_tauaer,                               &
3215             rrtm_lwuflx     , rrtm_lwdflx  , rrtm_lwhr  ,                   &
3216             rrtm_lwuflxc    , rrtm_lwdflxc , rrtm_lwhrc ,                   &
3217             rrtm_lwuflx_dt  ,  rrtm_lwuflxc_dt )
3218
3219!
3220!--          Save fluxes
3221             DO k = nzb, nzt+1
3222                rad_lw_in(k,:,:)  = rrtm_lwdflx(0,k)
3223                rad_lw_out(k,:,:) = rrtm_lwuflx(0,k)
3224             ENDDO
3225             rad_lw_in_diff(:,:) = rad_lw_in(0,:,:)
3226!
3227!--          Save heating rates (convert from K/d to K/h).
3228!--          Further, even though an aggregated radiation is computed, map
3229!--          signle-column profiles on top of any topography, in order to
3230!--          obtain correct near surface radiation heating/cooling rates.
3231             DO  i = nxl, nxr
3232                DO  j = nys, nyn
3233                   k_topo = get_topography_top_index_ji( j, i, 's' )
3234                   DO k = k_topo+1, nzt+1
3235                      rad_lw_hr(k,j,i)     = rrtm_lwhr(0,k-k_topo)  * d_hours_day
3236                      rad_lw_cs_hr(k,j,i)  = rrtm_lwhrc(0,k-k_topo) * d_hours_day
3237                   ENDDO
3238                ENDDO
3239             ENDDO
3240
3241          ENDIF
3242
3243          IF ( sw_radiation .AND. sun_up )  THEN
3244             CALL rrtmg_sw( 1, nzt_rad      , rrtm_icld     , rrtm_iaer      ,&
3245             rrtm_play      , rrtm_plev     , rrtm_tlay     , rrtm_tlev      ,&
3246             rrtm_tsfc      , rrtm_h2ovmr   , rrtm_o3vmr    , rrtm_co2vmr    ,&
3247             rrtm_ch4vmr    , rrtm_n2ovmr   , rrtm_o2vmr    , rrtm_asdir     ,&
3248             rrtm_asdif     , rrtm_aldir    , rrtm_aldif    , zenith         ,&
3249             0.0_wp         , day_of_year   , solar_constant, rrtm_inflgsw   ,&
3250             rrtm_iceflgsw  , rrtm_liqflgsw , rrtm_cldfr    , rrtm_sw_taucld ,&
3251             rrtm_sw_ssacld , rrtm_sw_asmcld, rrtm_sw_fsfcld, rrtm_cicewp    ,&
3252             rrtm_cliqwp    , rrtm_reice    , rrtm_reliq    , rrtm_sw_tauaer ,&
3253             rrtm_sw_ssaaer , rrtm_sw_asmaer, rrtm_sw_ecaer , rrtm_swuflx    ,&
3254             rrtm_swdflx    , rrtm_swhr     , rrtm_swuflxc  , rrtm_swdflxc   ,&
3255             rrtm_swhrc     , rrtm_dirdflux , rrtm_difdflux )
3256 
3257!
3258!--          Save fluxes:
3259!--          - whole domain
3260             DO k = nzb, nzt+1
3261                rad_sw_in(k,:,:)  = rrtm_swdflx(0,k)
3262                rad_sw_out(k,:,:) = rrtm_swuflx(0,k)
3263             ENDDO
3264!--          - direct and diffuse SW at urban-surface-layer (required by RTM)
3265             rad_sw_in_dir(:,:) = rrtm_dirdflux(0,nzb)
3266             rad_sw_in_diff(:,:) = rrtm_difdflux(0,nzb)
3267
3268!
3269!--          Save heating rates (convert from K/d to K/s)
3270             DO k = nzb+1, nzt+1
3271                rad_sw_hr(k,:,:)     = rrtm_swhr(0,k)  * d_hours_day
3272                rad_sw_cs_hr(k,:,:)  = rrtm_swhrc(0,k) * d_hours_day
3273             ENDDO
3274!
3275!--       Solar radiation is zero during night
3276          ELSE
3277             rad_sw_in  = 0.0_wp
3278             rad_sw_out = 0.0_wp
3279             rad_sw_in_dir(:,:) = 0.0_wp
3280             rad_sw_in_diff(:,:) = 0.0_wp
3281          ENDIF
3282!
3283!--    RRTMG is called for each (j,i) grid point separately, starting at the
3284!--    highest topography level. Here no RTM is used since average_radiation is false
3285       ELSE
3286!
3287!--       Loop over all grid points
3288          DO i = nxl, nxr
3289             DO j = nys, nyn
3290
3291!
3292!--             Prepare profiles of temperature and H2O volume mixing ratio
3293                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
3294                   rrtm_tlev(0,nzb+1) = surf_lsm_h%pt_surface(m) * exner(nzb)
3295                ENDDO
3296                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
3297                   rrtm_tlev(0,nzb+1) = surf_usm_h%pt_surface(m) * exner(nzb)
3298                ENDDO
3299
3300
3301                IF ( bulk_cloud_model )  THEN
3302                   DO k = nzb+1, nzt+1
3303                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)                    &
3304                                        + lv_d_cp * ql(k,j,i)
3305                      rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * (q(k,j,i) - ql(k,j,i))
3306                   ENDDO
3307                ELSEIF ( cloud_droplets )  THEN
3308                   DO k = nzb+1, nzt+1
3309                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)                     &
3310                                        + lv_d_cp * ql(k,j,i)
3311                      rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * q(k,j,i) 
3312                   ENDDO
3313                ELSE
3314                   DO k = nzb+1, nzt+1
3315                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)
3316                   ENDDO
3317
3318                   IF ( humidity )  THEN
3319                      DO k = nzb+1, nzt+1
3320                         rrtm_h2ovmr(0,k) =  mol_mass_air_d_wv * q(k,j,i)
3321                      ENDDO   
3322                   ELSE
3323                      rrtm_h2ovmr(0,nzb+1:nzt+1) = 0.0_wp
3324                   ENDIF
3325                ENDIF
3326
3327!
3328!--             Avoid temperature/humidity jumps at the top of the LES domain by
3329!--             linear interpolation from nzt+2 to nzt+7
3330                DO k = nzt+2, nzt+7
3331                   rrtm_tlay(0,k) = rrtm_tlay(0,nzt+1)                         &
3332                                 + ( rrtm_tlay(0,nzt+8) - rrtm_tlay(0,nzt+1) ) &
3333                                 / ( rrtm_play(0,nzt+8) - rrtm_play(0,nzt+1) ) &
3334                                 * ( rrtm_play(0,k)     - rrtm_play(0,nzt+1) )
3335
3336                   rrtm_h2ovmr(0,k) = rrtm_h2ovmr(0,nzt+1)                     &
3337                              + ( rrtm_h2ovmr(0,nzt+8) - rrtm_h2ovmr(0,nzt+1) )&
3338                              / ( rrtm_play(0,nzt+8)   - rrtm_play(0,nzt+1)   )&
3339                              * ( rrtm_play(0,k)       - rrtm_play(0,nzt+1) )
3340
3341                ENDDO
3342
3343!--             Linear interpolate to zw grid
3344                DO k = nzb+2, nzt+8
3345                   rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k) -     &
3346                                      rrtm_tlay(0,k-1))                        &
3347                                      / ( rrtm_play(0,k) - rrtm_play(0,k-1) )  &
3348                                      * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
3349                ENDDO
3350
3351
3352!
3353!--             Calculate liquid water path and cloud fraction for each column.
3354!--             Note that LWP is required in g/m² instead of kg/kg m.
3355                rrtm_cldfr  = 0.0_wp
3356                rrtm_reliq  = 0.0_wp
3357                rrtm_cliqwp = 0.0_wp
3358                rrtm_icld   = 0
3359
3360                IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
3361                   DO k = nzb+1, nzt+1
3362                      rrtm_cliqwp(0,k) =  ql(k,j,i) * 1000.0_wp *              &
3363                                          (rrtm_plev(0,k) - rrtm_plev(0,k+1))  &
3364                                          * 100.0_wp / g 
3365
3366                      IF ( rrtm_cliqwp(0,k) > 0.0_wp )  THEN
3367                         rrtm_cldfr(0,k) = 1.0_wp
3368                         IF ( rrtm_icld == 0 )  rrtm_icld = 1
3369
3370!
3371!--                      Calculate cloud droplet effective radius
3372                         IF ( bulk_cloud_model )  THEN
3373!
3374!--                         Calculete effective droplet radius. In case of using
3375!--                         cloud_scheme = 'morrison' and a non reasonable number
3376!--                         of cloud droplets the inital aerosol number 
3377!--                         concentration is considered.
3378                            IF ( microphysics_morrison )  THEN
3379                               IF ( nc(k,j,i) > 1.0E-20_wp )  THEN
3380                                  nc_rad = nc(k,j,i)
3381                               ELSE
3382                                  nc_rad = na_init
3383                               ENDIF
3384                            ELSE
3385                               nc_rad = nc_const
3386                            ENDIF 
3387
3388                            rrtm_reliq(0,k) = 1.0E6_wp * ( 3.0_wp * ql(k,j,i)     &
3389                                              * rho_surface                       &
3390                                              / ( 4.0_wp * pi * nc_rad * rho_l )  &
3391                                              )**0.33333333333333_wp              &
3392                                              * EXP( LOG( sigma_gc )**2 )
3393
3394                         ELSEIF ( cloud_droplets )  THEN
3395                            number_of_particles = prt_count(k,j,i)
3396
3397                            IF (number_of_particles <= 0)  CYCLE
3398                            particles => grid_particles(k,j,i)%particles(1:number_of_particles)
3399                            s_r2 = 0.0_wp
3400                            s_r3 = 0.0_wp
3401
3402                            DO  n = 1, number_of_particles
3403                               IF ( particles(n)%particle_mask )  THEN
3404                                  s_r2 = s_r2 + particles(n)%radius**2 *       &
3405                                         particles(n)%weight_factor
3406                                  s_r3 = s_r3 + particles(n)%radius**3 *       &
3407                                         particles(n)%weight_factor
3408                               ENDIF
3409                            ENDDO
3410
3411                            IF ( s_r2 > 0.0_wp )  rrtm_reliq(0,k) = s_r3 / s_r2
3412
3413                         ENDIF
3414
3415!
3416!--                      Limit effective radius
3417                         IF ( rrtm_reliq(0,k) > 0.0_wp )  THEN
3418                            rrtm_reliq(0,k) = MAX(rrtm_reliq(0,k),2.5_wp)
3419                            rrtm_reliq(0,k) = MIN(rrtm_reliq(0,k),60.0_wp)
3420                        ENDIF
3421                      ENDIF
3422                   ENDDO
3423                ENDIF
3424
3425!
3426!--             Write surface emissivity and surface temperature at current
3427!--             surface element on RRTMG-shaped array.
3428!--             Please note, as RRTMG is a single column model, surface attributes
3429!--             are only obtained from horizontally aligned surfaces (for
3430!--             simplicity). Taking surface attributes from horizontal and
3431!--             vertical walls would lead to multiple solutions. 
3432!--             Moreover, for natural- and urban-type surfaces, several surface
3433!--             classes can exist at a surface element next to each other.
3434!--             To obtain bulk parameters, apply a weighted average for these
3435!--             surfaces.
3436                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
3437                   rrtm_emis = surf_lsm_h%frac(ind_veg_wall,m)  *              &
3438                               surf_lsm_h%emissivity(ind_veg_wall,m)  +        &
3439                               surf_lsm_h%frac(ind_pav_green,m) *              &
3440                               surf_lsm_h%emissivity(ind_pav_green,m) +        & 
3441                               surf_lsm_h%frac(ind_wat_win,m)   *              &
3442                               surf_lsm_h%emissivity(ind_wat_win,m)
3443                   rrtm_tsfc = surf_lsm_h%pt_surface(m) * exner(nzb)
3444                ENDDO             
3445                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
3446                   rrtm_emis = surf_usm_h%frac(ind_veg_wall,m)  *              &
3447                               surf_usm_h%emissivity(ind_veg_wall,m)  +        &
3448                               surf_usm_h%frac(ind_pav_green,m) *              &
3449                               surf_usm_h%emissivity(ind_pav_green,m) +        & 
3450                               surf_usm_h%frac(ind_wat_win,m)   *              &
3451                               surf_usm_h%emissivity(ind_wat_win,m)
3452                   rrtm_tsfc = surf_usm_h%pt_surface(m) * exner(nzb)
3453                ENDDO
3454!
3455!--             Obtain topography top index (lower bound of RRTMG)
3456                k_topo = get_topography_top_index_ji( j, i, 's' )
3457
3458                IF ( lw_radiation )  THEN
3459!
3460!--                Due to technical reasons, copy optical depth to dummy arguments
3461!--                which are allocated on the exact size as the rrtmg_lw is called.
3462!--                As one dimesion is allocated with zero size, compiler complains
3463!--                that rank of the array does not match that of the
3464!--                assumed-shaped arguments in the RRTMG library. In order to
3465!--                avoid this, write to dummy arguments and give pass the entire
3466!--                dummy array. Seems to be the only existing work-around. 
3467                   ALLOCATE( rrtm_lw_taucld_dum(1:nbndlw+1,0:0,k_topo+1:nzt_rad+1) )
3468                   ALLOCATE( rrtm_lw_tauaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndlw+1) )
3469
3470                   rrtm_lw_taucld_dum =                                        &
3471                               rrtm_lw_taucld(1:nbndlw+1,0:0,k_topo+1:nzt_rad+1)
3472                   rrtm_lw_tauaer_dum =                                        &
3473                               rrtm_lw_tauaer(0:0,k_topo+1:nzt_rad+1,1:nbndlw+1)
3474
3475                   CALL rrtmg_lw( 1,                                           &                                       
3476                                  nzt_rad-k_topo,                              &
3477                                  rrtm_icld,                                   &
3478                                  rrtm_idrv,                                   &
3479                                  rrtm_play(:,k_topo+1:nzt_rad+1),             &
3480                                  rrtm_plev(:,k_topo+1:nzt_rad+2),             &
3481                                  rrtm_tlay(:,k_topo+1:nzt_rad+1),             &
3482                                  rrtm_tlev(:,k_topo+1:nzt_rad+2),             &
3483                                  rrtm_tsfc,                                   &
3484                                  rrtm_h2ovmr(:,k_topo+1:nzt_rad+1),           &
3485                                  rrtm_o3vmr(:,k_topo+1:nzt_rad+1),            &
3486                                  rrtm_co2vmr(:,k_topo+1:nzt_rad+1),           &
3487                                  rrtm_ch4vmr(:,k_topo+1:nzt_rad+1),           &
3488                                  rrtm_n2ovmr(:,k_topo+1:nzt_rad+1),           &
3489                                  rrtm_o2vmr(:,k_topo+1:nzt_rad+1),            &
3490                                  rrtm_cfc11vmr(:,k_topo+1:nzt_rad+1),         &
3491                                  rrtm_cfc12vmr(:,k_topo+1:nzt_rad+1),         &
3492                                  rrtm_cfc22vmr(:,k_topo+1:nzt_rad+1),         &
3493                                  rrtm_ccl4vmr(:,k_topo+1:nzt_rad+1),          &
3494                                  rrtm_emis,                                   &
3495                                  rrtm_inflglw,                                &
3496                                  rrtm_iceflglw,                               &
3497                                  rrtm_liqflglw,                               &
3498                                  rrtm_cldfr(:,k_topo+1:nzt_rad+1),            &
3499                                  rrtm_lw_taucld_dum,                          &
3500                                  rrtm_cicewp(:,k_topo+1:nzt_rad+1),           &
3501                                  rrtm_cliqwp(:,k_topo+1:nzt_rad+1),           &
3502                                  rrtm_reice(:,k_topo+1:nzt_rad+1),            & 
3503                                  rrtm_reliq(:,k_topo+1:nzt_rad+1),            &
3504                                  rrtm_lw_tauaer_dum,                          &
3505                                  rrtm_lwuflx(:,k_topo:nzt_rad+1),             &
3506                                  rrtm_lwdflx(:,k_topo:nzt_rad+1),             &
3507                                  rrtm_lwhr(:,k_topo+1:nzt_rad+1),             &
3508                                  rrtm_lwuflxc(:,k_topo:nzt_rad+1),            &
3509                                  rrtm_lwdflxc(:,k_topo:nzt_rad+1),            &
3510                                  rrtm_lwhrc(:,k_topo+1:nzt_rad+1),            &
3511                                  rrtm_lwuflx_dt(:,k_topo:nzt_rad+1),          &
3512                                  rrtm_lwuflxc_dt(:,k_topo:nzt_rad+1) )
3513
3514                   DEALLOCATE ( rrtm_lw_taucld_dum )
3515                   DEALLOCATE ( rrtm_lw_tauaer_dum )
3516!
3517!--                Save fluxes
3518                   DO k = k_topo, nzt+1
3519                      rad_lw_in(k,j,i)  = rrtm_lwdflx(0,k)
3520                      rad_lw_out(k,j,i) = rrtm_lwuflx(0,k)
3521                   ENDDO
3522
3523!
3524!--                Save heating rates (convert from K/d to K/h)
3525                   DO k = k_topo+1, nzt+1
3526                      rad_lw_hr(k,j,i)     = rrtm_lwhr(0,k-k_topo)  * d_hours_day
3527                      rad_lw_cs_hr(k,j,i)  = rrtm_lwhrc(0,k-k_topo) * d_hours_day
3528                   ENDDO
3529
3530!
3531!--                Save surface radiative fluxes and change in LW heating rate
3532!--                onto respective surface elements
3533!--                Horizontal surfaces
3534                   DO  m = surf_lsm_h%start_index(j,i),                        &
3535                           surf_lsm_h%end_index(j,i)
3536                      surf_lsm_h%rad_lw_in(m)           = rrtm_lwdflx(0,k_topo)
3537                      surf_lsm_h%rad_lw_out(m)          = rrtm_lwuflx(0,k_topo)
3538                      surf_lsm_h%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k_topo)
3539                   ENDDO             
3540                   DO  m = surf_usm_h%start_index(j,i),                        &
3541                           surf_usm_h%end_index(j,i)
3542                      surf_usm_h%rad_lw_in(m)           = rrtm_lwdflx(0,k_topo)
3543                      surf_usm_h%rad_lw_out(m)          = rrtm_lwuflx(0,k_topo)
3544                      surf_usm_h%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k_topo)
3545                   ENDDO 
3546!
3547!--                Vertical surfaces. Fluxes are obtain at vertical level of the
3548!--                respective surface element
3549                   DO  l = 0, 3
3550                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
3551                              surf_lsm_v(l)%end_index(j,i)
3552                         k                                    = surf_lsm_v(l)%k(m)
3553                         surf_lsm_v(l)%rad_lw_in(m)           = rrtm_lwdflx(0,k)
3554                         surf_lsm_v(l)%rad_lw_out(m)          = rrtm_lwuflx(0,k)
3555                         surf_lsm_v(l)%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k)
3556                      ENDDO             
3557                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
3558                              surf_usm_v(l)%end_index(j,i)
3559                         k                                    = surf_usm_v(l)%k(m)
3560                         surf_usm_v(l)%rad_lw_in(m)           = rrtm_lwdflx(0,k)
3561                         surf_usm_v(l)%rad_lw_out(m)          = rrtm_lwuflx(0,k)
3562                         surf_usm_v(l)%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k)
3563                      ENDDO 
3564                   ENDDO
3565
3566                ENDIF
3567
3568                IF ( sw_radiation .AND. sun_up )  THEN
3569!
3570!--                Get albedo for direct/diffusive long/shortwave radiation at
3571!--                current (y,x)-location from surface variables.
3572!--                Only obtain it from horizontal surfaces, as RRTMG is a single
3573!--                column model
3574!--                (Please note, only one loop will entered, controlled by
3575!--                start-end index.)
3576                   DO  m = surf_lsm_h%start_index(j,i),                        &
3577                           surf_lsm_h%end_index(j,i)
3578                      rrtm_asdir(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3579                                            surf_lsm_h%rrtm_asdir(:,m) )
3580                      rrtm_asdif(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3581                                            surf_lsm_h%rrtm_asdif(:,m) )
3582                      rrtm_aldir(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3583                                            surf_lsm_h%rrtm_aldir(:,m) )
3584                      rrtm_aldif(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3585                                            surf_lsm_h%rrtm_aldif(:,m) )
3586                   ENDDO             
3587                   DO  m = surf_usm_h%start_index(j,i),                        &
3588                           surf_usm_h%end_index(j,i)
3589                      rrtm_asdir(1)  = SUM( surf_usm_h%frac(:,m) *             &
3590                                            surf_usm_h%rrtm_asdir(:,m) )
3591                      rrtm_asdif(1)  = SUM( surf_usm_h%frac(:,m) *             &
3592                                            surf_usm_h%rrtm_asdif(:,m) )
3593                      rrtm_aldir(1)  = SUM( surf_usm_h%frac(:,m) *             &
3594                                            surf_usm_h%rrtm_aldir(:,m) )
3595                      rrtm_aldif(1)  = SUM( surf_usm_h%frac(:,m) *             &
3596                                            surf_usm_h%rrtm_aldif(:,m) )
3597                   ENDDO
3598!
3599!--                Due to technical reasons, copy optical depths and other
3600!--                to dummy arguments which are allocated on the exact size as the
3601!--                rrtmg_sw is called.
3602!--                As one dimesion is allocated with zero size, compiler complains
3603!--                that rank of the array does not match that of the
3604!--                assumed-shaped arguments in the RRTMG library. In order to
3605!--                avoid this, write to dummy arguments and give pass the entire
3606!--                dummy array. Seems to be the only existing work-around. 
3607                   ALLOCATE( rrtm_sw_taucld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3608                   ALLOCATE( rrtm_sw_ssacld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3609                   ALLOCATE( rrtm_sw_asmcld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3610                   ALLOCATE( rrtm_sw_fsfcld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3611                   ALLOCATE( rrtm_sw_tauaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3612                   ALLOCATE( rrtm_sw_ssaaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3613                   ALLOCATE( rrtm_sw_asmaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3614                   ALLOCATE( rrtm_sw_ecaer_dum(0:0,k_topo+1:nzt_rad+1,1:naerec+1)  )
3615     
3616                   rrtm_sw_taucld_dum = rrtm_sw_taucld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3617                   rrtm_sw_ssacld_dum = rrtm_sw_ssacld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3618                   rrtm_sw_asmcld_dum = rrtm_sw_asmcld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3619                   rrtm_sw_fsfcld_dum = rrtm_sw_fsfcld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3620                   rrtm_sw_tauaer_dum = rrtm_sw_tauaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3621                   rrtm_sw_ssaaer_dum = rrtm_sw_ssaaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3622                   rrtm_sw_asmaer_dum = rrtm_sw_asmaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3623                   rrtm_sw_ecaer_dum  = rrtm_sw_ecaer(0:0,k_topo+1:nzt_rad+1,1:naerec+1)
3624
3625                   CALL rrtmg_sw( 1,                                           &
3626                                  nzt_rad-k_topo,                              &
3627                                  rrtm_icld,                                   &
3628                                  rrtm_iaer,                                   &
3629                                  rrtm_play(:,k_topo+1:nzt_rad+1),             &
3630                                  rrtm_plev(:,k_topo+1:nzt_rad+2),             &
3631                                  rrtm_tlay(:,k_topo+1:nzt_rad+1),             &
3632                                  rrtm_tlev(:,k_topo+1:nzt_rad+2),             &
3633                                  rrtm_tsfc,                                   &
3634                                  rrtm_h2ovmr(:,k_topo+1:nzt_rad+1),           &                               
3635                                  rrtm_o3vmr(:,k_topo+1:nzt_rad+1),            &       
3636                                  rrtm_co2vmr(:,k_topo+1:nzt_rad+1),           &
3637                                  rrtm_ch4vmr(:,k_topo+1:nzt_rad+1),           &
3638                                  rrtm_n2ovmr(:,k_topo+1:nzt_rad+1),           &
3639                                  rrtm_o2vmr(:,k_topo+1:nzt_rad+1),            &
3640                                  rrtm_asdir,                                  & 
3641                                  rrtm_asdif,                                  &
3642                                  rrtm_aldir,                                  &
3643                                  rrtm_aldif,                                  &
3644                                  zenith,                                      &
3645                                  0.0_wp,                                      &
3646                                  day_of_year,                                 &
3647                                  solar_constant,                              &
3648                                  rrtm_inflgsw,                                &
3649                                  rrtm_iceflgsw,                               &
3650                                  rrtm_liqflgsw,                               &
3651                                  rrtm_cldfr(:,k_topo+1:nzt_rad+1),            &
3652                                  rrtm_sw_taucld_dum,                          &
3653                                  rrtm_sw_ssacld_dum,                          &
3654                                  rrtm_sw_asmcld_dum,                          &
3655                                  rrtm_sw_fsfcld_dum,                          &
3656                                  rrtm_cicewp(:,k_topo+1:nzt_rad+1),           &
3657                                  rrtm_cliqwp(:,k_topo+1:nzt_rad+1),           &
3658                                  rrtm_reice(:,k_topo+1:nzt_rad+1),            &
3659                                  rrtm_reliq(:,k_topo+1:nzt_rad+1),            &
3660                                  rrtm_sw_tauaer_dum,                          &
3661                                  rrtm_sw_ssaaer_dum,                          &
3662                                  rrtm_sw_asmaer_dum,                          &
3663                                  rrtm_sw_ecaer_dum,                           &
3664                                  rrtm_swuflx(:,k_topo:nzt_rad+1),             & 
3665                                  rrtm_swdflx(:,k_topo:nzt_rad+1),             & 
3666                                  rrtm_swhr(:,k_topo+1:nzt_rad+1),             & 
3667                                  rrtm_swuflxc(:,k_topo:nzt_rad+1),            & 
3668                                  rrtm_swdflxc(:,k_topo:nzt_rad+1),            &
3669                                  rrtm_swhrc(:,k_topo+1:nzt_rad+1),            &
3670                                  rrtm_dirdflux(:,k_topo:nzt_rad+1),           &
3671                                  rrtm_difdflux(:,k_topo:nzt_rad+1) )
3672
3673                   DEALLOCATE( rrtm_sw_taucld_dum )
3674                   DEALLOCATE( rrtm_sw_ssacld_dum )
3675                   DEALLOCATE( rrtm_sw_asmcld_dum )
3676                   DEALLOCATE( rrtm_sw_fsfcld_dum )
3677                   DEALLOCATE( rrtm_sw_tauaer_dum )
3678                   DEALLOCATE( rrtm_sw_ssaaer_dum )
3679                   DEALLOCATE( rrtm_sw_asmaer_dum )
3680                   DEALLOCATE( rrtm_sw_ecaer_dum )
3681!
3682!--                Save fluxes
3683                   DO k = nzb, nzt+1
3684                      rad_sw_in(k,j,i)  = rrtm_swdflx(0,k)
3685                      rad_sw_out(k,j,i) = rrtm_swuflx(0,k)
3686                   ENDDO
3687!
3688!--                Save heating rates (convert from K/d to K/s)
3689                   DO k = nzb+1, nzt+1
3690                      rad_sw_hr(k,j,i)     = rrtm_swhr(0,k)  * d_hours_day
3691                      rad_sw_cs_hr(k,j,i)  = rrtm_swhrc(0,k) * d_hours_day
3692                   ENDDO
3693
3694!
3695!--                Save surface radiative fluxes onto respective surface elements
3696!--                Horizontal surfaces
3697                   DO  m = surf_lsm_h%start_index(j,i),                        &
3698                           surf_lsm_h%end_index(j,i)
3699                      surf_lsm_h%rad_sw_in(m)     = rrtm_swdflx(0,k_topo)
3700                      surf_lsm_h%rad_sw_out(m)    = rrtm_swuflx(0,k_topo)
3701                   ENDDO             
3702                   DO  m = surf_usm_h%start_index(j,i),                        &
3703                           surf_usm_h%end_index(j,i)
3704                      surf_usm_h%rad_sw_in(m)     = rrtm_swdflx(0,k_topo)
3705                      surf_usm_h%rad_sw_out(m)    = rrtm_swuflx(0,k_topo)
3706                   ENDDO 
3707!
3708!--                Vertical surfaces. Fluxes are obtain at respective vertical
3709!--                level of the surface element
3710                   DO  l = 0, 3
3711                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
3712                              surf_lsm_v(l)%end_index(j,i)
3713                         k                           = surf_lsm_v(l)%k(m)
3714                         surf_lsm_v(l)%rad_sw_in(m)  = rrtm_swdflx(0,k)
3715                         surf_lsm_v(l)%rad_sw_out(m) = rrtm_swuflx(0,k)
3716                      ENDDO             
3717                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
3718                              surf_usm_v(l)%end_index(j,i)
3719                         k                           = surf_usm_v(l)%k(m)
3720                         surf_usm_v(l)%rad_sw_in(m)  = rrtm_swdflx(0,k)
3721                         surf_usm_v(l)%rad_sw_out(m) = rrtm_swuflx(0,k)
3722                      ENDDO 
3723                   ENDDO
3724!
3725!--             Solar radiation is zero during night
3726                ELSE
3727                   rad_sw_in  = 0.0_wp
3728                   rad_sw_out = 0.0_wp
3729!--             !!!!!!!! ATTENSION !!!!!!!!!!!!!!!
3730!--             Surface radiative fluxes should be also set to zero here                 
3731!--                Save surface radiative fluxes onto respective surface elements
3732!--                Horizontal surfaces
3733                   DO  m = surf_lsm_h%start_index(j,i),                        &
3734                           surf_lsm_h%end_index(j,i)
3735                      surf_lsm_h%rad_sw_in(m)     = 0.0_wp
3736                      surf_lsm_h%rad_sw_out(m)    = 0.0_wp
3737                   ENDDO             
3738                   DO  m = surf_usm_h%start_index(j,i),                        &
3739                           surf_usm_h%end_index(j,i)
3740                      surf_usm_h%rad_sw_in(m)     = 0.0_wp
3741                      surf_usm_h%rad_sw_out(m)    = 0.0_wp
3742                   ENDDO 
3743!
3744!--                Vertical surfaces. Fluxes are obtain at respective vertical
3745!--                level of the surface element
3746                   DO  l = 0, 3
3747                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
3748                              surf_lsm_v(l)%end_index(j,i)
3749                         k                           = surf_lsm_v(l)%k(m)
3750                         surf_lsm_v(l)%rad_sw_in(m)  = 0.0_wp
3751                         surf_lsm_v(l)%rad_sw_out(m) = 0.0_wp
3752                      ENDDO             
3753                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
3754                              surf_usm_v(l)%end_index(j,i)
3755                         k                           = surf_usm_v(l)%k(m)
3756                         surf_usm_v(l)%rad_sw_in(m)  = 0.0_wp
3757                         surf_usm_v(l)%rad_sw_out(m) = 0.0_wp
3758                      ENDDO 
3759                   ENDDO
3760                ENDIF
3761
3762             ENDDO
3763          ENDDO
3764
3765       ENDIF
3766!
3767!--    Finally, calculate surface net radiation for surface elements.
3768       IF (  .NOT.  radiation_interactions  ) THEN
3769!--       First, for horizontal surfaces   
3770          DO  m = 1, surf_lsm_h%ns
3771             surf_lsm_h%rad_net(m) = surf_lsm_h%rad_sw_in(m)                   &
3772                                   - surf_lsm_h%rad_sw_out(m)                  &
3773                                   + surf_lsm_h%rad_lw_in(m)                   &
3774                                   - surf_lsm_h%rad_lw_out(m)
3775          ENDDO
3776          DO  m = 1, surf_usm_h%ns
3777             surf_usm_h%rad_net(m) = surf_usm_h%rad_sw_in(m)                   &
3778                                   - surf_usm_h%rad_sw_out(m)                  &
3779                                   + surf_usm_h%rad_lw_in(m)                   &
3780                                   - surf_usm_h%rad_lw_out(m)
3781          ENDDO
3782!
3783!--       Vertical surfaces.
3784!--       Todo: weight with azimuth and zenith angle according to their orientation!
3785          DO  l = 0, 3     
3786             DO  m = 1, surf_lsm_v(l)%ns
3787                surf_lsm_v(l)%rad_net(m) = surf_lsm_v(l)%rad_sw_in(m)          &
3788                                         - surf_lsm_v(l)%rad_sw_out(m)         &
3789                                         + surf_lsm_v(l)%rad_lw_in(m)          &
3790                                         - surf_lsm_v(l)%rad_lw_out(m)
3791             ENDDO
3792             DO  m = 1, surf_usm_v(l)%ns
3793                surf_usm_v(l)%rad_net(m) = surf_usm_v(l)%rad_sw_in(m)          &
3794                                         - surf_usm_v(l)%rad_sw_out(m)         &
3795                                         + surf_usm_v(l)%rad_lw_in(m)          &
3796                                         - surf_usm_v(l)%rad_lw_out(m)
3797             ENDDO
3798          ENDDO
3799       ENDIF
3800
3801
3802       CALL exchange_horiz( rad_lw_in,  nbgp )
3803       CALL exchange_horiz( rad_lw_out, nbgp )
3804       CALL exchange_horiz( rad_lw_hr,    nbgp )
3805       CALL exchange_horiz( rad_lw_cs_hr, nbgp )
3806
3807       CALL exchange_horiz( rad_sw_in,  nbgp )
3808       CALL exchange_horiz( rad_sw_out, nbgp ) 
3809       CALL exchange_horiz( rad_sw_hr,    nbgp )
3810       CALL exchange_horiz( rad_sw_cs_hr, nbgp )
3811
3812#endif
3813
3814    END SUBROUTINE radiation_rrtmg
3815
3816
3817!------------------------------------------------------------------------------!
3818! Description:
3819! ------------
3820!> Calculate the cosine of the zenith angle (variable is called zenith)
3821!------------------------------------------------------------------------------!
3822    SUBROUTINE calc_zenith
3823
3824       IMPLICIT NONE
3825
3826       REAL(wp) ::  declination,  & !< solar declination angle
3827                    hour_angle      !< solar hour angle
3828!
3829!--    Calculate current day and time based on the initial values and simulation
3830!--    time
3831       CALL calc_date_and_time
3832
3833!
3834!--    Calculate solar declination and hour angle   
3835       declination = ASIN( decl_1 * SIN(decl_2 * REAL(day_of_year, KIND=wp) - decl_3) )
3836       hour_angle  = 2.0_wp * pi * (time_utc / 86400.0_wp) + lon - pi
3837
3838!
3839!--    Calculate cosine of solar zenith angle
3840       zenith(0) = SIN(lat) * SIN(declination) + COS(lat) * COS(declination)   &
3841                                            * COS(hour_angle)
3842       zenith(0) = MAX(0.0_wp,zenith(0))
3843
3844!
3845!--    Calculate solar directional vector
3846       IF ( sun_direction )  THEN
3847
3848!
3849!--       Direction in longitudes equals to sin(solar_azimuth) * sin(zenith)
3850          sun_dir_lon(0) = -SIN(hour_angle) * COS(declination)
3851
3852!
3853!--       Direction in latitues equals to cos(solar_azimuth) * sin(zenith)
3854          sun_dir_lat(0) = SIN(declination) * COS(lat) - COS(hour_angle) &
3855                              * COS(declination) * SIN(lat)
3856       ENDIF
3857
3858!
3859!--    Check if the sun is up (otheriwse shortwave calculations can be skipped)
3860       IF ( zenith(0) > 0.0_wp )  THEN
3861          sun_up = .TRUE.
3862       ELSE
3863          sun_up = .FALSE.
3864       END IF
3865
3866    END SUBROUTINE calc_zenith
3867
3868#if defined ( __rrtmg ) && defined ( __netcdf )
3869!------------------------------------------------------------------------------!
3870! Description:
3871! ------------
3872!> Calculates surface albedo components based on Briegleb (1992) and
3873!> Briegleb et al. (1986)
3874!------------------------------------------------------------------------------!
3875    SUBROUTINE calc_albedo( surf )
3876
3877        IMPLICIT NONE
3878
3879        INTEGER(iwp)    ::  ind_type !< running index surface tiles
3880        INTEGER(iwp)    ::  m        !< running index surface elements
3881
3882        TYPE(surf_type) ::  surf !< treated surfaces
3883
3884        IF ( sun_up  .AND.  .NOT. average_radiation )  THEN
3885
3886           DO  m = 1, surf%ns
3887!
3888!--           Loop over surface elements
3889              DO  ind_type = 0, SIZE( surf%albedo_type, 1 ) - 1
3890           
3891!
3892!--              Ocean
3893                 IF ( surf%albedo_type(ind_type,m) == 1 )  THEN
3894                    surf%rrtm_aldir(ind_type,m) = 0.026_wp /                    &
3895                                                ( zenith(0)**1.7_wp + 0.065_wp )&
3896                                     + 0.15_wp * ( zenith(0) - 0.1_wp )         &
3897                                               * ( zenith(0) - 0.5_wp )         &
3898                                               * ( zenith(0) - 1.0_wp )
3899                    surf%rrtm_asdir(ind_type,m) = surf%rrtm_aldir(ind_type,m)
3900!
3901!--              Snow
3902                 ELSEIF ( surf%albedo_type(ind_type,m) == 16 )  THEN
3903                    IF ( zenith(0) < 0.5_wp )  THEN
3904                       surf%rrtm_aldir(ind_type,m) =                           &
3905                                 0.5_wp * ( 1.0_wp - surf%aldif(ind_type,m) )  &
3906                                        * ( 3.0_wp / ( 1.0_wp + 4.0_wp         &
3907                                        * zenith(0) ) ) - 1.0_wp
3908                       surf%rrtm_asdir(ind_type,m) =                           &
3909                                 0.5_wp * ( 1.0_wp - surf%asdif(ind_type,m) )  &
3910                                        * ( 3.0_wp / ( 1.0_wp + 4.0_wp         &
3911                                        * zenith(0) ) ) - 1.0_wp
3912
3913                       surf%rrtm_aldir(ind_type,m) =                           &
3914                                       MIN(0.98_wp, surf%rrtm_aldir(ind_type,m))
3915                       surf%rrtm_asdir(ind_type,m) =                           &
3916                                       MIN(0.98_wp, surf%rrtm_asdir(ind_type,m))
3917                    ELSE
3918                       surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
3919                       surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
3920                    ENDIF
3921!
3922!--              Sea ice
3923                 ELSEIF ( surf%albedo_type(ind_type,m) == 15 )  THEN
3924                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
3925                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
3926
3927!
3928!--              Asphalt
3929                 ELSEIF ( surf%albedo_type(ind_type,m) == 17 )  THEN
3930                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
3931                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
3932
3933
3934!
3935!--              Bare soil
3936                 ELSEIF ( surf%albedo_type(ind_type,m) == 18 )  THEN
3937                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
3938                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
3939
3940!
3941!--              Land surfaces
3942                 ELSE
3943                    SELECT CASE ( surf%albedo_type(ind_type,m) )
3944
3945!
3946!--                    Surface types with strong zenith dependence
3947                       CASE ( 1, 2, 3, 4, 11, 12, 13 )
3948                          surf%rrtm_aldir(ind_type,m) =                        &
3949                                surf%aldif(ind_type,m) * 1.4_wp /              &
3950                                           ( 1.0_wp + 0.8_wp * zenith(0) )
3951                          surf%rrtm_asdir(ind_type,m) =                        &
3952                                surf%asdif(ind_type,m) * 1.4_wp /              &
3953                                           ( 1.0_wp + 0.8_wp * zenith(0) )
3954!
3955!--                    Surface types with weak zenith dependence
3956                       CASE ( 5, 6, 7, 8, 9, 10, 14 )
3957                          surf%rrtm_aldir(ind_type,m) =                        &
3958                                surf%aldif(ind_type,m) * 1.1_wp /              &
3959                                           ( 1.0_wp + 0.2_wp * zenith(0) )
3960                          surf%rrtm_asdir(ind_type,m) =                        &
3961                                surf%asdif(ind_type,m) * 1.1_wp /              &
3962                                           ( 1.0_wp + 0.2_wp * zenith(0) )
3963
3964                       CASE DEFAULT
3965
3966                    END SELECT
3967                 ENDIF
3968!
3969!--              Diffusive albedo is taken from Table 2
3970                 surf%rrtm_aldif(ind_type,m) = surf%aldif(ind_type,m)
3971                 surf%rrtm_asdif(ind_type,m) = surf%asdif(ind_type,m)
3972              ENDDO
3973           ENDDO
3974!
3975!--     Set albedo in case of average radiation
3976        ELSEIF ( sun_up  .AND.  average_radiation )  THEN
3977           surf%rrtm_asdir = albedo_urb
3978           surf%rrtm_asdif = albedo_urb
3979           surf%rrtm_aldir = albedo_urb
3980           surf%rrtm_aldif = albedo_urb 
3981!
3982!--     Darkness
3983        ELSE
3984           surf%rrtm_aldir = 0.0_wp
3985           surf%rrtm_asdir = 0.0_wp
3986           surf%rrtm_aldif = 0.0_wp
3987           surf%rrtm_asdif = 0.0_wp
3988        ENDIF
3989
3990    END SUBROUTINE calc_albedo
3991
3992!------------------------------------------------------------------------------!
3993! Description:
3994! ------------
3995!> Read sounding data (pressure and temperature) from RADIATION_DATA.
3996!------------------------------------------------------------------------------!
3997    SUBROUTINE read_sounding_data
3998
3999       IMPLICIT NONE
4000
4001       INTEGER(iwp) :: id,           & !< NetCDF id of input file
4002                       id_dim_zrad,  & !< pressure level id in the NetCDF file
4003                       id_var,       & !< NetCDF variable id
4004                       k,            & !< loop index
4005                       nz_snd,       & !< number of vertical levels in the sounding data
4006                       nz_snd_start, & !< start vertical index for sounding data to be used
4007                       nz_snd_end      !< end vertical index for souding data to be used
4008
4009       REAL(wp) :: t_surface           !< actual surface temperature
4010
4011       REAL(wp), DIMENSION(:), ALLOCATABLE ::  hyp_snd_tmp, & !< temporary hydrostatic pressure profile (sounding)
4012                                               t_snd_tmp      !< temporary temperature profile (sounding)
4013
4014!
4015!--    In case of updates, deallocate arrays first (sufficient to check one
4016!--    array as the others are automatically allocated). This is required
4017!--    because nzt_rad might change during the update
4018       IF ( ALLOCATED ( hyp_snd ) )  THEN
4019          DEALLOCATE( hyp_snd )
4020          DEALLOCATE( t_snd )
4021          DEALLOCATE ( rrtm_play )
4022          DEALLOCATE ( rrtm_plev )
4023          DEALLOCATE ( rrtm_tlay )
4024          DEALLOCATE ( rrtm_tlev )
4025
4026          DEALLOCATE ( rrtm_cicewp )
4027          DEALLOCATE ( rrtm_cldfr )
4028          DEALLOCATE ( rrtm_cliqwp )
4029          DEALLOCATE ( rrtm_reice )
4030          DEALLOCATE ( rrtm_reliq )
4031          DEALLOCATE ( rrtm_lw_taucld )
4032          DEALLOCATE ( rrtm_lw_tauaer )
4033
4034          DEALLOCATE ( rrtm_lwdflx  )
4035          DEALLOCATE ( rrtm_lwdflxc )
4036          DEALLOCATE ( rrtm_lwuflx  )
4037          DEALLOCATE ( rrtm_lwuflxc )
4038          DEALLOCATE ( rrtm_lwuflx_dt )
4039          DEALLOCATE ( rrtm_lwuflxc_dt )
4040          DEALLOCATE ( rrtm_lwhr  )
4041          DEALLOCATE ( rrtm_lwhrc )
4042
4043          DEALLOCATE ( rrtm_sw_taucld )
4044          DEALLOCATE ( rrtm_sw_ssacld )
4045          DEALLOCATE ( rrtm_sw_asmcld )
4046          DEALLOCATE ( rrtm_sw_fsfcld )
4047          DEALLOCATE ( rrtm_sw_tauaer )
4048          DEALLOCATE ( rrtm_sw_ssaaer )
4049          DEALLOCATE ( rrtm_sw_asmaer ) 
4050          DEALLOCATE ( rrtm_sw_ecaer )   
4051 
4052          DEALLOCATE ( rrtm_swdflx  )
4053          DEALLOCATE ( rrtm_swdflxc )
4054          DEALLOCATE ( rrtm_swuflx  )
4055          DEALLOCATE ( rrtm_swuflxc )
4056          DEALLOCATE ( rrtm_swhr  )
4057          DEALLOCATE ( rrtm_swhrc )
4058          DEALLOCATE ( rrtm_dirdflux )
4059          DEALLOCATE ( rrtm_difdflux )
4060
4061       ENDIF
4062
4063!
4064!--    Open file for reading
4065       nc_stat = NF90_OPEN( rrtm_input_file, NF90_NOWRITE, id )
4066       CALL netcdf_handle_error_rad( 'read_sounding_data', 549 )
4067
4068!
4069!--    Inquire dimension of z axis and save in nz_snd
4070       nc_stat = NF90_INQ_DIMID( id, "Pressure", id_dim_zrad )
4071       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim_zrad, len = nz_snd )
4072       CALL netcdf_handle_error_rad( 'read_sounding_data', 551 )
4073
4074!
4075! !--    Allocate temporary array for storing pressure data
4076       ALLOCATE( hyp_snd_tmp(1:nz_snd) )
4077       hyp_snd_tmp = 0.0_wp
4078
4079
4080!--    Read pressure from file
4081       nc_stat = NF90_INQ_VARID( id, "Pressure", id_var )
4082       nc_stat = NF90_GET_VAR( id, id_var, hyp_snd_tmp(:), start = (/1/),      &
4083                               count = (/nz_snd/) )
4084       CALL netcdf_handle_error_rad( 'read_sounding_data', 552 )
4085
4086!
4087!--    Allocate temporary array for storing temperature data
4088       ALLOCATE( t_snd_tmp(1:nz_snd) )
4089       t_snd_tmp = 0.0_wp
4090
4091!
4092!--    Read temperature from file
4093       nc_stat = NF90_INQ_VARID( id, "ReferenceTemperature", id_var )
4094       nc_stat = NF90_GET_VAR( id, id_var, t_snd_tmp(:), start = (/1/),        &
4095                               count = (/nz_snd/) )
4096       CALL netcdf_handle_error_rad( 'read_sounding_data', 553 )
4097
4098!
4099!--    Calculate start of sounding data
4100       nz_snd_start = nz_snd + 1
4101       nz_snd_end   = nz_snd + 1
4102
4103!
4104!--    Start filling vertical dimension at 10hPa above the model domain (hyp is
4105!--    in Pa, hyp_snd in hPa).
4106       DO  k = 1, nz_snd
4107          IF ( hyp_snd_tmp(k) < ( hyp(nzt+1) - 1000.0_wp) * 0.01_wp )  THEN
4108             nz_snd_start = k
4109             EXIT
4110          END IF
4111       END DO
4112
4113       IF ( nz_snd_start <= nz_snd )  THEN
4114          nz_snd_end = nz_snd
4115       END IF
4116
4117
4118!
4119!--    Calculate of total grid points for RRTMG calculations
4120       nzt_rad = nzt + nz_snd_end - nz_snd_start + 1
4121
4122!
4123!--    Save data above LES domain in hyp_snd, t_snd
4124       ALLOCATE( hyp_snd(nzb+1:nzt_rad) )
4125       ALLOCATE( t_snd(nzb+1:nzt_rad)   )
4126       hyp_snd = 0.0_wp
4127       t_snd = 0.0_wp
4128
4129       hyp_snd(nzt+2:nzt_rad) = hyp_snd_tmp(nz_snd_start+1:nz_snd_end)
4130       t_snd(nzt+2:nzt_rad)   = t_snd_tmp(nz_snd_start+1:nz_snd_end)
4131
4132       nc_stat = NF90_CLOSE( id )
4133
4134!
4135!--    Calculate pressure levels on zu and zw grid. Sounding data is added at
4136!--    top of the LES domain. This routine does not consider horizontal or
4137!--    vertical variability of pressure and temperature
4138       ALLOCATE ( rrtm_play(0:0,nzb+1:nzt_rad+1)   )
4139       ALLOCATE ( rrtm_plev(0:0,nzb+1:nzt_rad+2)   )
4140
4141       t_surface = pt_surface * exner(nzb)
4142       DO k = nzb+1, nzt+1
4143          rrtm_play(0,k) = hyp(k) * 0.01_wp
4144          rrtm_plev(0,k) = barometric_formula(zw(k-1),                         &
4145                              pt_surface * exner(nzb), &
4146                              surface_pressure )
4147       ENDDO
4148
4149       DO k = nzt+2, nzt_rad
4150          rrtm_play(0,k) = hyp_snd(k)
4151          rrtm_plev(0,k) = 0.5_wp * ( rrtm_play(0,k) + rrtm_play(0,k-1) )
4152       ENDDO
4153       rrtm_plev(0,nzt_rad+1) = MAX( 0.5 * hyp_snd(nzt_rad),                   &
4154                                   1.5 * hyp_snd(nzt_rad)                      &
4155                                 - 0.5 * hyp_snd(nzt_rad-1) )
4156       rrtm_plev(0,nzt_rad+2)  = MIN( 1.0E-4_wp,                               &
4157                                      0.25_wp * rrtm_plev(0,nzt_rad+1) )
4158
4159       rrtm_play(0,nzt_rad+1) = 0.5 * rrtm_plev(0,nzt_rad+1)
4160
4161!
4162!--    Calculate temperature/humidity levels at top of the LES domain.
4163!--    Currently, the temperature is taken from sounding data (might lead to a
4164!--    temperature jump at interface. To do: Humidity is currently not
4165!--    calculated above the LES domain.
4166       ALLOCATE ( rrtm_tlay(0:0,nzb+1:nzt_rad+1)   )
4167       ALLOCATE ( rrtm_tlev(0:0,nzb+1:nzt_rad+2)   )
4168
4169       DO k = nzt+8, nzt_rad
4170          rrtm_tlay(0,k)   = t_snd(k)
4171       ENDDO
4172       rrtm_tlay(0,nzt_rad+1) = 2.0_wp * rrtm_tlay(0,nzt_rad)                  &
4173                                - rrtm_tlay(0,nzt_rad-1)
4174       DO k = nzt+9, nzt_rad+1
4175          rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k)                &
4176                             - rrtm_tlay(0,k-1))                               &
4177                             / ( rrtm_play(0,k) - rrtm_play(0,k-1) )           &
4178                             * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
4179       ENDDO
4180
4181       rrtm_tlev(0,nzt_rad+2)   = 2.0_wp * rrtm_tlay(0,nzt_rad+1)              &
4182                                  - rrtm_tlev(0,nzt_rad)
4183!
4184!--    Allocate remaining RRTMG arrays
4185       ALLOCATE ( rrtm_cicewp(0:0,nzb+1:nzt_rad+1) )
4186       ALLOCATE ( rrtm_cldfr(0:0,nzb+1:nzt_rad+1) )
4187       ALLOCATE ( rrtm_cliqwp(0:0,nzb+1:nzt_rad+1) )
4188       ALLOCATE ( rrtm_reice(0:0,nzb+1:nzt_rad+1) )
4189       ALLOCATE ( rrtm_reliq(0:0,nzb+1:nzt_rad+1) )
4190       ALLOCATE ( rrtm_lw_taucld(1:nbndlw+1,0:0,nzb+1:nzt_rad+1) )
4191       ALLOCATE ( rrtm_lw_tauaer(0:0,nzb+1:nzt_rad+1,1:nbndlw+1) )
4192       ALLOCATE ( rrtm_sw_taucld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4193       ALLOCATE ( rrtm_sw_ssacld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4194       ALLOCATE ( rrtm_sw_asmcld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4195       ALLOCATE ( rrtm_sw_fsfcld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4196       ALLOCATE ( rrtm_sw_tauaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) )
4197       ALLOCATE ( rrtm_sw_ssaaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) )
4198       ALLOCATE ( rrtm_sw_asmaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) ) 
4199       ALLOCATE ( rrtm_sw_ecaer(0:0,nzb+1:nzt_rad+1,1:naerec+1) )   
4200
4201!
4202!--    The ice phase is currently not considered in PALM
4203       rrtm_cicewp = 0.0_wp
4204       rrtm_reice  = 0.0_wp
4205
4206!
4207!--    Set other parameters (move to NAMELIST parameters in the future)
4208       rrtm_lw_tauaer = 0.0_wp
4209       rrtm_lw_taucld = 0.0_wp
4210       rrtm_sw_taucld = 0.0_wp
4211       rrtm_sw_ssacld = 0.0_wp
4212       rrtm_sw_asmcld = 0.0_wp
4213       rrtm_sw_fsfcld = 0.0_wp
4214       rrtm_sw_tauaer = 0.0_wp
4215       rrtm_sw_ssaaer = 0.0_wp
4216       rrtm_sw_asmaer = 0.0_wp
4217       rrtm_sw_ecaer  = 0.0_wp
4218
4219
4220       ALLOCATE ( rrtm_swdflx(0:0,nzb:nzt_rad+1)  )
4221       ALLOCATE ( rrtm_swuflx(0:0,nzb:nzt_rad+1)  )
4222       ALLOCATE ( rrtm_swhr(0:0,nzb+1:nzt_rad+1)  )
4223       ALLOCATE ( rrtm_swuflxc(0:0,nzb:nzt_rad+1) )
4224       ALLOCATE ( rrtm_swdflxc(0:0,nzb:nzt_rad+1) )
4225       ALLOCATE ( rrtm_swhrc(0:0,nzb+1:nzt_rad+1) )
4226       ALLOCATE ( rrtm_dirdflux(0:0,nzb:nzt_rad+1) )
4227       ALLOCATE ( rrtm_difdflux(0:0,nzb:nzt_rad+1) )
4228
4229       rrtm_swdflx  = 0.0_wp
4230       rrtm_swuflx  = 0.0_wp
4231       rrtm_swhr    = 0.0_wp 
4232       rrtm_swuflxc = 0.0_wp
4233       rrtm_swdflxc = 0.0_wp
4234       rrtm_swhrc   = 0.0_wp
4235       rrtm_dirdflux = 0.0_wp
4236       rrtm_difdflux = 0.0_wp
4237
4238       ALLOCATE ( rrtm_lwdflx(0:0,nzb:nzt_rad+1)  )
4239       ALLOCATE ( rrtm_lwuflx(0:0,nzb:nzt_rad+1)  )
4240       ALLOCATE ( rrtm_lwhr(0:0,nzb+1:nzt_rad+1)  )
4241       ALLOCATE ( rrtm_lwuflxc(0:0,nzb:nzt_rad+1) )
4242       ALLOCATE ( rrtm_lwdflxc(0:0,nzb:nzt_rad+1) )
4243       ALLOCATE ( rrtm_lwhrc(0:0,nzb+1:nzt_rad+1) )
4244
4245       rrtm_lwdflx  = 0.0_wp
4246       rrtm_lwuflx  = 0.0_wp
4247       rrtm_lwhr    = 0.0_wp 
4248       rrtm_lwuflxc = 0.0_wp
4249       rrtm_lwdflxc = 0.0_wp
4250       rrtm_lwhrc   = 0.0_wp
4251
4252       ALLOCATE ( rrtm_lwuflx_dt(0:0,nzb:nzt_rad+1) )
4253       ALLOCATE ( rrtm_lwuflxc_dt(0:0,nzb:nzt_rad+1) )
4254
4255       rrtm_lwuflx_dt = 0.0_wp
4256       rrtm_lwuflxc_dt = 0.0_wp
4257
4258    END SUBROUTINE read_sounding_data
4259
4260
4261!------------------------------------------------------------------------------!
4262! Description:
4263! ------------
4264!> Read trace gas data from file
4265!------------------------------------------------------------------------------!
4266    SUBROUTINE read_trace_gas_data
4267
4268       USE rrsw_ncpar
4269
4270       IMPLICIT NONE
4271
4272       INTEGER(iwp), PARAMETER :: num_trace_gases = 10 !< number of trace gases (absorbers)
4273
4274       CHARACTER(LEN=5), DIMENSION(num_trace_gases), PARAMETER ::              & !< trace gas names
4275           trace_names = (/'O3   ', 'CO2  ', 'CH4  ', 'N2O  ', 'O2   ',        &
4276                           'CFC11', 'CFC12', 'CFC22', 'CCL4 ', 'H2O  '/)
4277
4278       INTEGER(iwp) :: id,     & !< NetCDF id
4279                       k,      & !< loop index
4280                       m,      & !< loop index
4281                       n,      & !< loop index
4282                       nabs,   & !< number of absorbers
4283                       np,     & !< number of pressure levels
4284                       id_abs, & !< NetCDF id of the respective absorber
4285                       id_dim, & !< NetCDF id of asborber's dimension
4286                       id_var    !< NetCDf id ot the absorber
4287
4288       REAL(wp) :: p_mls_l, p_mls_u, p_wgt_l, p_wgt_u, p_mls_m
4289
4290
4291       REAL(wp), DIMENSION(:), ALLOCATABLE   ::  p_mls,          & !< pressure levels for the absorbers
4292                                                 rrtm_play_tmp,  & !< temporary array for pressure zu-levels
4293                                                 rrtm_plev_tmp,  & !< temporary array for pressure zw-levels
4294                                                 trace_path_tmp    !< temporary array for storing trace gas path data
4295
4296       REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  trace_mls,      & !< array for storing the absorber amounts
4297                                                 trace_mls_path, & !< array for storing trace gas path data
4298                                                 trace_mls_tmp     !< temporary array for storing trace gas data
4299
4300
4301!
4302!--    In case of updates, deallocate arrays first (sufficient to check one
4303!--    array as the others are automatically allocated)
4304       IF ( ALLOCATED ( rrtm_o3vmr ) )  THEN
4305          DEALLOCATE ( rrtm_o3vmr  )
4306          DEALLOCATE ( rrtm_co2vmr )
4307          DEALLOCATE ( rrtm_ch4vmr )
4308          DEALLOCATE ( rrtm_n2ovmr )
4309          DEALLOCATE ( rrtm_o2vmr  )
4310          DEALLOCATE ( rrtm_cfc11vmr )
4311          DEALLOCATE ( rrtm_cfc12vmr )
4312          DEALLOCATE ( rrtm_cfc22vmr )
4313          DEALLOCATE ( rrtm_ccl4vmr  )
4314          DEALLOCATE ( rrtm_h2ovmr  )     
4315       ENDIF
4316
4317!
4318!--    Allocate trace gas profiles
4319       ALLOCATE ( rrtm_o3vmr(0:0,1:nzt_rad+1)  )
4320       ALLOCATE ( rrtm_co2vmr(0:0,1:nzt_rad+1) )
4321       ALLOCATE ( rrtm_ch4vmr(0:0,1:nzt_rad+1) )
4322       ALLOCATE ( rrtm_n2ovmr(0:0,1:nzt_rad+1) )
4323       ALLOCATE ( rrtm_o2vmr(0:0,1:nzt_rad+1)  )
4324       ALLOCATE ( rrtm_cfc11vmr(0:0,1:nzt_rad+1) )
4325       ALLOCATE ( rrtm_cfc12vmr(0:0,1:nzt_rad+1) )
4326       ALLOCATE ( rrtm_cfc22vmr(0:0,1:nzt_rad+1) )
4327       ALLOCATE ( rrtm_ccl4vmr(0:0,1:nzt_rad+1)  )
4328       ALLOCATE ( rrtm_h2ovmr(0:0,1:nzt_rad+1)  )
4329
4330!
4331!--    Open file for reading
4332       nc_stat = NF90_OPEN( rrtm_input_file, NF90_NOWRITE, id )
4333       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 549 )
4334!
4335!--    Inquire dimension ids and dimensions
4336       nc_stat = NF90_INQ_DIMID( id, "Pressure", id_dim )
4337       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4338       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim, len = np) 
4339       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4340
4341       nc_stat = NF90_INQ_DIMID( id, "Absorber", id_dim )
4342       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4343       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim, len = nabs ) 
4344       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4345   
4346
4347!
4348!--    Allocate pressure, and trace gas arrays     
4349       ALLOCATE( p_mls(1:np) )
4350       ALLOCATE( trace_mls(1:num_trace_gases,1:np) ) 
4351       ALLOCATE( trace_mls_tmp(1:nabs,1:np) ) 
4352
4353
4354       nc_stat = NF90_INQ_VARID( id, "Pressure", id_var )
4355       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4356       nc_stat = NF90_GET_VAR( id, id_var, p_mls )
4357       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4358
4359       nc_stat = NF90_INQ_VARID( id, "AbsorberAmountMLS", id_var )
4360       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4361       nc_stat = NF90_GET_VAR( id, id_var, trace_mls_tmp )
4362       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4363
4364
4365!
4366!--    Write absorber amounts (mls) to trace_mls
4367       DO n = 1, num_trace_gases
4368          CALL getAbsorberIndex( TRIM( trace_names(n) ), id_abs )
4369
4370          trace_mls(n,1:np) = trace_mls_tmp(id_abs,1:np)
4371
4372!
4373!--       Replace missing values by zero
4374          WHERE ( trace_mls(n,:) > 2.0_wp ) 
4375             trace_mls(n,:) = 0.0_wp
4376          END WHERE
4377       END DO
4378
4379       DEALLOCATE ( trace_mls_tmp )
4380
4381       nc_stat = NF90_CLOSE( id )
4382       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 551 )
4383
4384!
4385!--    Add extra pressure level for calculations of the trace gas paths
4386       ALLOCATE ( rrtm_play_tmp(1:nzt_rad+1) )
4387       ALLOCATE ( rrtm_plev_tmp(1:nzt_rad+2) )
4388
4389       rrtm_play_tmp(1:nzt_rad)   = rrtm_play(0,1:nzt_rad) 
4390       rrtm_plev_tmp(1:nzt_rad+1) = rrtm_plev(0,1:nzt_rad+1)
4391       rrtm_play_tmp(nzt_rad+1)   = rrtm_plev(0,nzt_rad+1) * 0.5_wp
4392       rrtm_plev_tmp(nzt_rad+2)   = MIN( 1.0E-4_wp, 0.25_wp                    &
4393                                         * rrtm_plev(0,nzt_rad+1) )
4394 
4395!
4396!--    Calculate trace gas path (zero at surface) with interpolation to the
4397!--    sounding levels
4398       ALLOCATE ( trace_mls_path(1:nzt_rad+2,1:num_trace_gases) )
4399
4400       trace_mls_path(nzb+1,:) = 0.0_wp
4401       
4402       DO k = nzb+2, nzt_rad+2
4403          DO m = 1, num_trace_gases
4404             trace_mls_path(k,m) = trace_mls_path(k-1,m)
4405
4406!
4407!--          When the pressure level is higher than the trace gas pressure
4408!--          level, assume that
4409             IF ( rrtm_plev_tmp(k-1) > p_mls(1) )  THEN             
4410               
4411                trace_mls_path(k,m) = trace_mls_path(k,m) + trace_mls(m,1)     &
4412                                      * ( rrtm_plev_tmp(k-1)                   &
4413                                          - MAX( p_mls(1), rrtm_plev_tmp(k) )  &
4414                                        ) / g
4415             ENDIF
4416
4417!
4418!--          Integrate for each sounding level from the contributing p_mls
4419!--          levels
4420             DO n = 2, np
4421!
4422!--             Limit p_mls so that it is within the model level
4423                p_mls_u = MIN( rrtm_plev_tmp(k-1),                             &
4424                          MAX( rrtm_plev_tmp(k), p_mls(n) ) )
4425                p_mls_l = MIN( rrtm_plev_tmp(k-1),                             &
4426                          MAX( rrtm_plev_tmp(k), p_mls(n-1) ) )
4427
4428                IF ( p_mls_l > p_mls_u )  THEN
4429
4430!
4431!--                Calculate weights for interpolation
4432                   p_mls_m = 0.5_wp * (p_mls_l + p_mls_u)
4433                   p_wgt_u = (p_mls(n-1) - p_mls_m) / (p_mls(n-1) - p_mls(n))
4434                   p_wgt_l = (p_mls_m - p_mls(n))   / (p_mls(n-1) - p_mls(n))
4435
4436!
4437!--                Add level to trace gas path
4438                   trace_mls_path(k,m) = trace_mls_path(k,m)                   &
4439                                         +  ( p_wgt_u * trace_mls(m,n)         &
4440                                            + p_wgt_l * trace_mls(m,n-1) )     &
4441                                         * (p_mls_l - p_mls_u) / g
4442                ENDIF
4443             ENDDO
4444
4445             IF ( rrtm_plev_tmp(k) < p_mls(np) )  THEN
4446                trace_mls_path(k,m) = trace_mls_path(k,m) + trace_mls(m,np)    &
4447                                      * ( MIN( rrtm_plev_tmp(k-1), p_mls(np) ) &
4448                                          - rrtm_plev_tmp(k)                   &
4449                                        ) / g 
4450             ENDIF 
4451          ENDDO
4452       ENDDO
4453
4454
4455!
4456!--    Prepare trace gas path profiles
4457       ALLOCATE ( trace_path_tmp(1:nzt_rad+1) )
4458
4459       DO m = 1, num_trace_gases
4460
4461          trace_path_tmp(1:nzt_rad+1) = ( trace_mls_path(2:nzt_rad+2,m)        &
4462                                       - trace_mls_path(1:nzt_rad+1,m) ) * g   &
4463                                       / ( rrtm_plev_tmp(1:nzt_rad+1)          &
4464                                       - rrtm_plev_tmp(2:nzt_rad+2) )
4465
4466!
4467!--       Save trace gas paths to the respective arrays
4468          SELECT CASE ( TRIM( trace_names(m) ) )
4469
4470             CASE ( 'O3' )
4471
4472                rrtm_o3vmr(0,:) = trace_path_tmp(:)
4473
4474             CASE ( 'CO2' )
4475
4476                rrtm_co2vmr(0,:) = trace_path_tmp(:)
4477
4478             CASE ( 'CH4' )
4479
4480                rrtm_ch4vmr(0,:) = trace_path_tmp(:)
4481
4482             CASE ( 'N2O' )
4483
4484                rrtm_n2ovmr(0,:) = trace_path_tmp(:)
4485
4486             CASE ( 'O2' )
4487
4488                rrtm_o2vmr(0,:) = trace_path_tmp(:)
4489
4490             CASE ( 'CFC11' )
4491
4492                rrtm_cfc11vmr(0,:) = trace_path_tmp(:)
4493
4494             CASE ( 'CFC12' )
4495
4496                rrtm_cfc12vmr(0,:) = trace_path_tmp(:)
4497
4498             CASE ( 'CFC22' )
4499
4500                rrtm_cfc22vmr(0,:) = trace_path_tmp(:)
4501
4502             CASE ( 'CCL4' )
4503
4504                rrtm_ccl4vmr(0,:) = trace_path_tmp(:)
4505
4506             CASE ( 'H2O' )
4507
4508                rrtm_h2ovmr(0,:) = trace_path_tmp(:)
4509               
4510             CASE DEFAULT
4511
4512          END SELECT
4513
4514       ENDDO
4515
4516       DEALLOCATE ( trace_path_tmp )
4517       DEALLOCATE ( trace_mls_path )
4518       DEALLOCATE ( rrtm_play_tmp )
4519       DEALLOCATE ( rrtm_plev_tmp )
4520       DEALLOCATE ( trace_mls )
4521       DEALLOCATE ( p_mls )
4522
4523    END SUBROUTINE read_trace_gas_data
4524
4525
4526    SUBROUTINE netcdf_handle_error_rad( routine_name, errno )
4527
4528       USE control_parameters,                                                 &
4529           ONLY:  message_string
4530
4531       USE NETCDF
4532
4533       USE pegrid
4534
4535       IMPLICIT NONE
4536
4537       CHARACTER(LEN=6) ::  message_identifier
4538       CHARACTER(LEN=*) ::  routine_name
4539
4540       INTEGER(iwp) ::  errno
4541
4542       IF ( nc_stat /= NF90_NOERR )  THEN
4543
4544          WRITE( message_identifier, '(''NC'',I4.4)' )  errno
4545          message_string = TRIM( NF90_STRERROR( nc_stat ) )
4546
4547          CALL message( routine_name, message_identifier, 2, 2, 0, 6, 1 )
4548
4549       ENDIF
4550
4551    END SUBROUTINE netcdf_handle_error_rad
4552#endif
4553
4554
4555!------------------------------------------------------------------------------!
4556! Description:
4557! ------------
4558!> Calculate temperature tendency due to radiative cooling/heating.
4559!> Cache-optimized version.
4560!------------------------------------------------------------------------------!
4561 SUBROUTINE radiation_tendency_ij ( i, j, tend )
4562
4563    IMPLICIT NONE
4564
4565    INTEGER(iwp) :: i, j, k !< loop indices
4566
4567    REAL(wp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg) :: tend !< pt tendency term
4568
4569    IF ( radiation_scheme == 'rrtmg' )  THEN
4570#if defined  ( __rrtmg )
4571!
4572!--    Calculate tendency based on heating rate
4573       DO k = nzb+1, nzt+1
4574          tend(k,j,i) = tend(k,j,i) + (rad_lw_hr(k,j,i) + rad_sw_hr(k,j,i))    &
4575                                         * d_exner(k) * d_seconds_hour
4576       ENDDO
4577#endif
4578    ENDIF
4579
4580    END SUBROUTINE radiation_tendency_ij
4581
4582
4583!------------------------------------------------------------------------------!
4584! Description:
4585! ------------
4586!> Calculate temperature tendency due to radiative cooling/heating.
4587!> Vector-optimized version
4588!------------------------------------------------------------------------------!
4589 SUBROUTINE radiation_tendency ( tend )
4590
4591    USE indices,                                                               &
4592        ONLY:  nxl, nxr, nyn, nys
4593
4594    IMPLICIT NONE
4595
4596    INTEGER(iwp) :: i, j, k !< loop indices
4597
4598    REAL(wp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg) :: tend !< pt tendency term
4599
4600    IF ( radiation_scheme == 'rrtmg' )  THEN
4601#if defined  ( __rrtmg )
4602!
4603!--    Calculate tendency based on heating rate
4604       DO  i = nxl, nxr
4605          DO  j = nys, nyn
4606             DO k = nzb+1, nzt+1
4607                tend(k,j,i) = tend(k,j,i) + ( rad_lw_hr(k,j,i)                 &
4608                                          +  rad_sw_hr(k,j,i) ) * d_exner(k)   &
4609                                          * d_seconds_hour
4610             ENDDO
4611          ENDDO
4612       ENDDO
4613#endif
4614    ENDIF
4615
4616
4617 END SUBROUTINE radiation_tendency
4618
4619!------------------------------------------------------------------------------!
4620! Description:
4621! ------------
4622!> This subroutine calculates interaction of the solar radiation
4623!> with urban and land surfaces and updates all surface heatfluxes.
4624!> It calculates also the required parameters for RRTMG lower BC.
4625!>
4626!> For more info. see Resler et al. 2017
4627!>
4628!> The new version 2.0 was radically rewriten, the discretization scheme
4629!> has been changed. This new version significantly improves effectivity
4630!> of the paralelization and the scalability of the model.
4631!------------------------------------------------------------------------------!
4632
4633 SUBROUTINE radiation_interaction
4634
4635     IMPLICIT NONE
4636
4637     INTEGER(iwp)                      :: i, j, k, kk, is, js, d, ku, refstep, m, mm, l, ll
4638     INTEGER(iwp)                      :: isurf, isurfsrc, isvf, icsf, ipcgb
4639     INTEGER(iwp)                      :: imrt, imrtf
4640     INTEGER(iwp)                      :: isd                !< solar direction number
4641     INTEGER(iwp)                      :: pc_box_dimshift    !< transform for best accuracy
4642     INTEGER(iwp), DIMENSION(0:3)      :: reorder = (/ 1, 0, 3, 2 /)
4643     
4644     REAL(wp), DIMENSION(3,3)          :: mrot               !< grid rotation matrix (zyx)
4645     REAL(wp), DIMENSION(3,0:nsurf_type):: vnorm             !< face direction normal vectors (zyx)
4646     REAL(wp), DIMENSION(3)            :: sunorig            !< grid rotated solar direction unit vector (zyx)
4647     REAL(wp), DIMENSION(3)            :: sunorig_grid       !< grid squashed solar direction unit vector (zyx)
4648     REAL(wp), DIMENSION(0:nsurf_type) :: costheta           !< direct irradiance factor of solar angle
4649     REAL(wp), DIMENSION(nzub:nzut)    :: pchf_prep          !< precalculated factor for canopy temperature tendency
4650     REAL(wp), DIMENSION(nzub:nzut)    :: pctf_prep          !< precalculated factor for canopy transpiration tendency
4651     REAL(wp), PARAMETER               :: alpha = 0._wp      !< grid rotation (TODO: add to namelist or remove)
4652     REAL(wp)                          :: pc_box_area, pc_abs_frac, pc_abs_eff
4653     REAL(wp), DIMENSION(0:nsurf_type) :: facearea
4654     REAL(wp)                          :: pabsswl  = 0.0_wp  !< total absorbed SW radiation energy in local processor (W)
4655     REAL(wp)                          :: pabssw   = 0.0_wp  !< total absorbed SW radiation energy in all processors (W)
4656     REAL(wp)                          :: pabslwl  = 0.0_wp  !< total absorbed LW radiation energy in local processor (W)
4657     REAL(wp)                          :: pabslw   = 0.0_wp  !< total absorbed LW radiation energy in all processors (W)
4658     REAL(wp)                          :: pemitlwl = 0.0_wp  !< total emitted LW radiation energy in all processors (W)
4659     REAL(wp)                          :: pemitlw  = 0.0_wp  !< total emitted LW radiation energy in all processors (W)
4660     REAL(wp)                          :: pinswl   = 0.0_wp  !< total received SW radiation energy in local processor (W)
4661     REAL(wp)                          :: pinsw    = 0.0_wp  !< total received SW radiation energy in all processor (W)
4662     REAL(wp)                          :: pinlwl   = 0.0_wp  !< total received LW radiation energy in local processor (W)
4663     REAL(wp)                          :: pinlw    = 0.0_wp  !< total received LW radiation energy in all processor (W)
4664     REAL(wp)                          :: emiss_sum_surfl    !< sum of emissisivity of surfaces in local processor
4665     REAL(wp)                          :: emiss_sum_surf     !< sum of emissisivity of surfaces in all processor
4666     REAL(wp)                          :: area_surfl         !< total area of surfaces in local processor
4667     REAL(wp)                          :: area_surf          !< total area of surfaces in all processor
4668     REAL(wp)                          :: area_hor           !< total horizontal area of domain in all processor
4669
4670#if ! defined( __nopointer )
4671     IF ( plant_canopy )  THEN
4672         pchf_prep(:) = r_d * exner(nzub:nzut)                                 &
4673                     / (c_p * hyp(nzub:nzut) * dx*dy*dz(1)) !< equals to 1 / (rho * c_p * Vbox * T)
4674         pctf_prep(:) = r_d * exner(nzub:nzut)                                 &
4675                     / (l_v * hyp(nzub:nzut) * dx*dy*dz(1))
4676     ENDIF
4677#endif
4678     sun_direction = .TRUE.
4679     CALL calc_zenith  !< required also for diffusion radiation
4680
4681!--     prepare rotated normal vectors and irradiance factor
4682     vnorm(1,:) = kdir(:)
4683     vnorm(2,:) = jdir(:)
4684     vnorm(3,:) = idir(:)
4685     mrot(1, :) = (/ 1._wp,  0._wp,      0._wp      /)
4686     mrot(2, :) = (/ 0._wp,  COS(alpha), SIN(alpha) /)
4687     mrot(3, :) = (/ 0._wp, -SIN(alpha), COS(alpha) /)
4688     sunorig = (/ zenith(0), sun_dir_lat, sun_dir_lon /)
4689     sunorig = MATMUL(mrot, sunorig)
4690     DO d = 0, nsurf_type
4691         costheta(d) = DOT_PRODUCT(sunorig, vnorm(:,d))
4692     ENDDO
4693
4694     IF ( zenith(0) > 0 )  THEN
4695!--      now we will "squash" the sunorig vector by grid box size in
4696!--      each dimension, so that this new direction vector will allow us
4697!--      to traverse the ray path within grid coordinates directly
4698         sunorig_grid = (/ sunorig(1)/dz(1), sunorig(2)/dy, sunorig(3)/dx /)
4699!--      sunorig_grid = sunorig_grid / norm2(sunorig_grid)
4700         sunorig_grid = sunorig_grid / SQRT(SUM(sunorig_grid**2))
4701
4702         IF ( npcbl > 0 )  THEN
4703!--         precompute effective box depth with prototype Leaf Area Density
4704            pc_box_dimshift = MAXLOC(ABS(sunorig), 1) - 1
4705            CALL box_absorb(CSHIFT((/dz(1),dy,dx/), pc_box_dimshift),       &
4706                                60, prototype_lad,                          &
4707                                CSHIFT(ABS(sunorig), pc_box_dimshift),      &
4708                                pc_box_area, pc_abs_frac)
4709            pc_box_area = pc_box_area * ABS(sunorig(pc_box_dimshift+1)      &
4710                          / sunorig(1))
4711            pc_abs_eff = LOG(1._wp - pc_abs_frac) / prototype_lad
4712         ENDIF
4713     ENDIF
4714
4715!--  if radiation scheme is not RRTMG, split diffusion and direct part of the solar downward radiation
4716!--  comming from radiation model and store it in 2D arrays
4717     IF (  radiation_scheme /= 'rrtmg'  )  CALL calc_diffusion_radiation
4718
4719!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4720!--     First pass: direct + diffuse irradiance + thermal
4721!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4722     surfinswdir   = 0._wp !nsurfl
4723     surfins       = 0._wp !nsurfl
4724     surfinl       = 0._wp !nsurfl
4725     surfoutsl(:)  = 0.0_wp !start-end
4726     surfoutll(:)  = 0.0_wp !start-end
4727     IF ( nmrtbl > 0 )  THEN
4728        mrtinsw(:) = 0._wp
4729        mrtinlw(:) = 0._wp
4730     ENDIF
4731
4732
4733!--  Set up thermal radiation from surfaces
4734!--  emiss_surf is defined only for surfaces for which energy balance is calculated
4735!--  Workaround: reorder surface data type back on 1D array including all surfaces,
4736!--  which implies to reorder horizontal and vertical surfaces
4737!
4738!--  Horizontal walls
4739     mm = 1
4740     DO  i = nxl, nxr
4741        DO  j = nys, nyn
4742!--           urban
4743           DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
4744              surfoutll(mm) = SUM ( surf_usm_h%frac(:,m) *                  &
4745                                    surf_usm_h%emissivity(:,m) )            &
4746                                  * sigma_sb                                &
4747                                  * surf_usm_h%pt_surface(m)**4
4748              albedo_surf(mm) = SUM ( surf_usm_h%frac(:,m) *                &
4749                                      surf_usm_h%albedo(:,m) )
4750              emiss_surf(mm)  = SUM ( surf_usm_h%frac(:,m) *                &
4751                                      surf_usm_h%emissivity(:,m) )
4752              mm = mm + 1
4753           ENDDO
4754!--           land
4755           DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
4756              surfoutll(mm) = SUM ( surf_lsm_h%frac(:,m) *                  &
4757                                    surf_lsm_h%emissivity(:,m) )            &
4758                                  * sigma_sb                                &
4759                                  * surf_lsm_h%pt_surface(m)**4
4760              albedo_surf(mm) = SUM ( surf_lsm_h%frac(:,m) *                &
4761                                      surf_lsm_h%albedo(:,m) )
4762              emiss_surf(mm)  = SUM ( surf_lsm_h%frac(:,m) *                &
4763                                      surf_lsm_h%emissivity(:,m) )
4764              mm = mm + 1
4765           ENDDO
4766        ENDDO
4767     ENDDO
4768!
4769!--     Vertical walls
4770     DO  i = nxl, nxr
4771        DO  j = nys, nyn
4772           DO  ll = 0, 3
4773              l = reorder(ll)
4774!--              urban
4775              DO  m = surf_usm_v(l)%start_index(j,i),                       &
4776                      surf_usm_v(l)%end_index(j,i)
4777                 surfoutll(mm) = SUM ( surf_usm_v(l)%frac(:,m) *            &
4778                                       surf_usm_v(l)%emissivity(:,m) )      &
4779                                  * sigma_sb                                &
4780                                  * surf_usm_v(l)%pt_surface(m)**4
4781                 albedo_surf(mm) = SUM ( surf_usm_v(l)%frac(:,m) *          &
4782                                         surf_usm_v(l)%albedo(:,m) )
4783                 emiss_surf(mm)  = SUM ( surf_usm_v(l)%frac(:,m) *          &
4784                                         surf_usm_v(l)%emissivity(:,m) )
4785                 mm = mm + 1
4786              ENDDO
4787!--              land
4788              DO  m = surf_lsm_v(l)%start_index(j,i),                       &
4789                      surf_lsm_v(l)%end_index(j,i)
4790                 surfoutll(mm) = SUM ( surf_lsm_v(l)%frac(:,m) *            &
4791                                       surf_lsm_v(l)%emissivity(:,m) )      &
4792                                  * sigma_sb                                &
4793                                  * surf_lsm_v(l)%pt_surface(m)**4
4794                 albedo_surf(mm) = SUM ( surf_lsm_v(l)%frac(:,m) *          &
4795                                         surf_lsm_v(l)%albedo(:,m) )
4796                 emiss_surf(mm)  = SUM ( surf_lsm_v(l)%frac(:,m) *          &
4797                                         surf_lsm_v(l)%emissivity(:,m) )
4798                 mm = mm + 1
4799              ENDDO
4800           ENDDO
4801        ENDDO
4802     ENDDO
4803
4804#if defined( __parallel )
4805!--     might be optimized and gather only values relevant for current processor
4806     CALL MPI_AllGatherv(surfoutll, nsurfl, MPI_REAL, &
4807                         surfoutl, nsurfs, surfstart, MPI_REAL, comm2d, ierr) !nsurf global
4808     IF ( ierr /= 0 ) THEN
4809         WRITE(9,*) 'Error MPI_AllGatherv1:', ierr, SIZE(surfoutll), nsurfl, &
4810                     SIZE(surfoutl), nsurfs, surfstart
4811         FLUSH(9)
4812     ENDIF
4813#else
4814     surfoutl(:) = surfoutll(:) !nsurf global
4815#endif
4816
4817     IF ( surface_reflections)  THEN
4818        DO  isvf = 1, nsvfl
4819           isurf = svfsurf(1, isvf)
4820           k     = surfl(iz, isurf)
4821           j     = surfl(iy, isurf)
4822           i     = surfl(ix, isurf)
4823           isurfsrc = svfsurf(2, isvf)
4824!
4825!--        For surface-to-surface factors we calculate thermal radiation in 1st pass
4826           surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * surfoutl(isurfsrc)
4827        ENDDO
4828     ENDIF
4829!
4830!--  diffuse radiation using sky view factor
4831     DO isurf = 1, nsurfl
4832        j = surfl(iy, isurf)
4833        i = surfl(ix, isurf)
4834        surfinswdif(isurf) = rad_sw_in_diff(j,i) * skyvft(isurf)
4835        surfinlwdif(isurf) = rad_lw_in_diff(j,i) * skyvf(isurf)
4836     ENDDO
4837!
4838!--  MRT diffuse irradiance
4839     DO  imrt = 1, nmrtbl
4840        j = mrtbl(iy, imrt)
4841        i = mrtbl(ix, imrt)
4842        mrtinsw(imrt) = mrtskyt(imrt) * rad_sw_in_diff(j,i)
4843        mrtinlw(imrt) = mrtsky(imrt) * rad_lw_in_diff(j,i)
4844     ENDDO
4845
4846     !-- direct radiation
4847     IF ( zenith(0) > 0 )  THEN
4848        !--Identify solar direction vector (discretized number) 1)
4849        !--
4850        j = FLOOR(ACOS(zenith(0)) / pi * raytrace_discrete_elevs)
4851        i = MODULO(NINT(ATAN2(sun_dir_lon(0), sun_dir_lat(0))               &
4852                        / (2._wp*pi) * raytrace_discrete_azims-.5_wp, iwp), &
4853                   raytrace_discrete_azims)
4854        isd = dsidir_rev(j, i)
4855        DO isurf = 1, nsurfl
4856           j = surfl(iy, isurf)
4857           i = surfl(ix, isurf)
4858           surfinswdir(isurf) = rad_sw_in_dir(j,i) *                        &
4859                costheta(surfl(id, isurf)) * dsitrans(isurf, isd) / zenith(0)
4860        ENDDO
4861!
4862!--     MRT direct irradiance
4863        DO  imrt = 1, nmrtbl
4864           j = mrtbl(iy, imrt)
4865           i = mrtbl(ix, imrt)
4866           mrtinsw(imrt) = mrtinsw(imrt) + mrtdsit(imrt, isd) * rad_sw_in_dir(j,i) &
4867                                     / zenith(0) / 4._wp ! normal to sphere
4868        ENDDO
4869     ENDIF
4870!
4871!--  MRT first pass thermal
4872     DO  imrtf = 1, nmrtf
4873        imrt = mrtfsurf(1, imrtf)
4874        isurfsrc = mrtfsurf(2, imrtf)
4875        mrtinlw(imrt) = mrtinlw(imrt) + mrtf(imrtf) * surfoutl(isurfsrc)
4876     ENDDO
4877
4878     IF ( npcbl > 0 )  THEN
4879
4880         pcbinswdir(:) = 0._wp
4881         pcbinswdif(:) = 0._wp
4882         pcbinlw(:) = 0._wp  !< will stay always 0 since we don't absorb lw anymore
4883!
4884!--         pcsf first pass
4885         DO icsf = 1, ncsfl
4886             ipcgb = csfsurf(1, icsf)
4887             i = pcbl(ix,ipcgb)
4888             j = pcbl(iy,ipcgb)
4889             k = pcbl(iz,ipcgb)
4890             isurfsrc = csfsurf(2, icsf)
4891
4892             IF ( isurfsrc == -1 )  THEN
4893!--                 Diffuse rad from sky.
4894                 pcbinswdif(ipcgb) = csf(1,icsf) * rad_sw_in_diff(j,i)
4895
4896                 !--Direct rad
4897                 IF ( zenith(0) > 0 )  THEN
4898                    !--Estimate directed box absorption
4899                    pc_abs_frac = 1._wp - exp(pc_abs_eff * lad_s(k,j,i))
4900
4901                    !--isd has already been established, see 1)
4902                    pcbinswdir(ipcgb) = rad_sw_in_dir(j, i) * pc_box_area &
4903                                        * pc_abs_frac * dsitransc(ipcgb, isd)
4904                 ENDIF
4905             ENDIF
4906         ENDDO
4907
4908         pcbinsw(:) = pcbinswdir(:) + pcbinswdif(:)
4909     ENDIF
4910     surfins = surfinswdir + surfinswdif
4911     surfinl = surfinl + surfinlwdif
4912     surfinsw = surfins
4913     surfinlw = surfinl
4914     surfoutsw = 0.0_wp
4915     surfoutlw = surfoutll
4916     surfemitlwl = surfoutll
4917
4918     IF ( .NOT.  surface_reflections )  THEN
4919!
4920!--     Set nrefsteps to 0 to disable reflections       
4921        nrefsteps = 0
4922        surfoutsl = albedo_surf * surfins
4923        surfoutll = (1._wp - emiss_surf) * surfinl
4924        surfoutsw = surfoutsw + surfoutsl
4925        surfoutlw = surfoutlw + surfoutll
4926     ENDIF
4927
4928!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4929!--     Next passes - reflections
4930!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4931     DO refstep = 1, nrefsteps
4932
4933         surfoutsl = albedo_surf * surfins
4934!--         for non-transparent surfaces, longwave albedo is 1 - emissivity
4935         surfoutll = (1._wp - emiss_surf) * surfinl
4936
4937#if defined( __parallel )
4938         CALL MPI_AllGatherv(surfoutsl, nsurfl, MPI_REAL, &
4939             surfouts, nsurfs, surfstart, MPI_REAL, comm2d, ierr)
4940         IF ( ierr /= 0 ) THEN
4941             WRITE(9,*) 'Error MPI_AllGatherv2:', ierr, SIZE(surfoutsl), nsurfl, &
4942                        SIZE(surfouts), nsurfs, surfstart
4943             FLUSH(9)
4944         ENDIF
4945
4946         CALL MPI_AllGatherv(surfoutll, nsurfl, MPI_REAL, &
4947             surfoutl, nsurfs, surfstart, MPI_REAL, comm2d, ierr)
4948         IF ( ierr /= 0 ) THEN
4949             WRITE(9,*) 'Error MPI_AllGatherv3:', ierr, SIZE(surfoutll), nsurfl, &
4950                        SIZE(surfoutl), nsurfs, surfstart
4951             FLUSH(9)
4952         ENDIF
4953
4954#else
4955         surfouts = surfoutsl
4956         surfoutl = surfoutll
4957#endif
4958
4959!--         reset for next pass input
4960         surfins = 0._wp
4961         surfinl = 0._wp
4962
4963!--         reflected radiation
4964         DO isvf = 1, nsvfl
4965             isurf = svfsurf(1, isvf)
4966             isurfsrc = svfsurf(2, isvf)
4967             surfins(isurf) = surfins(isurf) + svf(1,isvf) * svf(2,isvf) * surfouts(isurfsrc)
4968             surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * surfoutl(isurfsrc)
4969         ENDDO
4970
4971!--         radiation absorbed by plant canopy
4972         DO icsf = 1, ncsfl
4973             ipcgb = csfsurf(1, icsf)
4974             isurfsrc = csfsurf(2, icsf)
4975             IF ( isurfsrc == -1 )  CYCLE ! sky->face only in 1st pass, not here
4976
4977             pcbinsw(ipcgb) = pcbinsw(ipcgb) + csf(1,icsf) * surfouts(isurfsrc)
4978         ENDDO
4979!
4980!--      MRT reflected
4981         DO  imrtf = 1, nmrtf
4982            imrt = mrtfsurf(1, imrtf)
4983            isurfsrc = mrtfsurf(2, imrtf)
4984            mrtinsw(imrt) = mrtinsw(imrt) + mrtft(imrtf) * surfouts(isurfsrc)
4985            mrtinlw(imrt) = mrtinlw(imrt) + mrtf(imrtf) * surfoutl(isurfsrc)
4986         ENDDO
4987
4988         surfinsw = surfinsw  + surfins
4989         surfinlw = surfinlw  + surfinl
4990         surfoutsw = surfoutsw + surfoutsl
4991         surfoutlw = surfoutlw + surfoutll
4992
4993     ENDDO ! refstep
4994
4995!--  push heat flux absorbed by plant canopy to respective 3D arrays
4996     IF ( npcbl > 0 )  THEN
4997         pc_heating_rate(:,:,:) = 0.0_wp
4998         pc_transpiration_rate(:,:,:) = 0.0_wp
4999         DO ipcgb = 1, npcbl
5000                 
5001             j = pcbl(iy, ipcgb)
5002             i = pcbl(ix, ipcgb)
5003             k = pcbl(iz, ipcgb)
5004!
5005!--             Following expression equals former kk = k - nzb_s_inner(j,i)
5006             kk = k - get_topography_top_index_ji( j, i, 's' )  !- lad arrays are defined flat
5007             pc_heating_rate(kk, j, i) = (pcbinsw(ipcgb) + pcbinlw(ipcgb)) &
5008                 * pchf_prep(k) * pt(k, j, i) !-- = dT/dt
5009
5010!             pc_transpiration_rate(kk,j,i) = 0.75_wp* (pcbinsw(ipcgb) + pcbinlw(ipcgb)) &
5011!                 * pctf_prep(k) * pt(k, j, i) !-- = dq/dt
5012
5013         ENDDO
5014     ENDIF
5015!
5016!--  Calculate black body MRT (after all reflections)
5017     IF ( nmrtbl > 0 )  THEN
5018        IF ( mrt_include_sw )  THEN
5019           mrt(:) = ((mrtinsw(:) + mrtinlw(:)) / sigma_sb) ** .25_wp
5020        ELSE
5021           mrt(:) = (mrtinlw(:) / sigma_sb) ** .25_wp
5022        ENDIF
5023     ENDIF
5024!
5025!--     Transfer radiation arrays required for energy balance to the respective data types
5026     DO  i = 1, nsurfl
5027        m  = surfl(5,i)
5028!
5029!--     (1) Urban surfaces
5030!--     upward-facing
5031        IF ( surfl(1,i) == iup_u )  THEN
5032           surf_usm_h%rad_sw_in(m)  = surfinsw(i)
5033           surf_usm_h%rad_sw_out(m) = surfoutsw(i)
5034           surf_usm_h%rad_lw_in(m)  = surfinlw(i)
5035           surf_usm_h%rad_lw_out(m) = surfoutlw(i)
5036           surf_usm_h%rad_net(m)    = surfinsw(i) - surfoutsw(i) +          &
5037                                      surfinlw(i) - surfoutlw(i)
5038           surf_usm_h%rad_net_l(m)  = surf_usm_h%rad_net(m)
5039!
5040!--     northward-facding
5041        ELSEIF ( surfl(1,i) == inorth_u )  THEN
5042           surf_usm_v(0)%rad_sw_in(m)  = surfinsw(i)
5043           surf_usm_v(0)%rad_sw_out(m) = surfoutsw(i)
5044           surf_usm_v(0)%rad_lw_in(m)  = surfinlw(i)
5045           surf_usm_v(0)%rad_lw_out(m) = surfoutlw(i)
5046           surf_usm_v(0)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5047                                         surfinlw(i) - surfoutlw(i)
5048           surf_usm_v(0)%rad_net_l(m)  = surf_usm_v(0)%rad_net(m)
5049!
5050!--     southward-facding
5051        ELSEIF ( surfl(1,i) == isouth_u )  THEN
5052           surf_usm_v(1)%rad_sw_in(m)  = surfinsw(i)
5053           surf_usm_v(1)%rad_sw_out(m) = surfoutsw(i)
5054           surf_usm_v(1)%rad_lw_in(m)  = surfinlw(i)
5055           surf_usm_v(1)%rad_lw_out(m) = surfoutlw(i)
5056           surf_usm_v(1)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5057                                         surfinlw(i) - surfoutlw(i)
5058           surf_usm_v(1)%rad_net_l(m)  = surf_usm_v(1)%rad_net(m)
5059!
5060!--     eastward-facing
5061        ELSEIF ( surfl(1,i) == ieast_u )  THEN
5062           surf_usm_v(2)%rad_sw_in(m)  = surfinsw(i)
5063           surf_usm_v(2)%rad_sw_out(m) = surfoutsw(i)
5064           surf_usm_v(2)%rad_lw_in(m)  = surfinlw(i)
5065           surf_usm_v(2)%rad_lw_out(m) = surfoutlw(i)
5066           surf_usm_v(2)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5067                                         surfinlw(i) - surfoutlw(i)
5068           surf_usm_v(2)%rad_net_l(m)  = surf_usm_v(2)%rad_net(m)
5069!
5070!--     westward-facding
5071        ELSEIF ( surfl(1,i) == iwest_u )  THEN
5072           surf_usm_v(3)%rad_sw_in(m)  = surfinsw(i)
5073           surf_usm_v(3)%rad_sw_out(m) = surfoutsw(i)
5074           surf_usm_v(3)%rad_lw_in(m)  = surfinlw(i)
5075           surf_usm_v(3)%rad_lw_out(m) = surfoutlw(i)
5076           surf_usm_v(3)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5077                                         surfinlw(i) - surfoutlw(i)
5078           surf_usm_v(3)%rad_net_l(m)  = surf_usm_v(3)%rad_net(m)
5079!
5080!--     (2) land surfaces
5081!--     upward-facing
5082        ELSEIF ( surfl(1,i) == iup_l )  THEN
5083           surf_lsm_h%rad_sw_in(m)  = surfinsw(i)
5084           surf_lsm_h%rad_sw_out(m) = surfoutsw(i)
5085           surf_lsm_h%rad_lw_in(m)  = surfinlw(i)
5086           surf_lsm_h%rad_lw_out(m) = surfoutlw(i)
5087           surf_lsm_h%rad_net(m)    = surfinsw(i) - surfoutsw(i) +          &
5088                                      surfinlw(i) - surfoutlw(i)
5089!
5090!--     northward-facding
5091        ELSEIF ( surfl(1,i) == inorth_l )  THEN
5092           surf_lsm_v(0)%rad_sw_in(m)  = surfinsw(i)
5093           surf_lsm_v(0)%rad_sw_out(m) = surfoutsw(i)
5094           surf_lsm_v(0)%rad_lw_in(m)  = surfinlw(i)
5095           surf_lsm_v(0)%rad_lw_out(m) = surfoutlw(i)
5096           surf_lsm_v(0)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5097                                         surfinlw(i) - surfoutlw(i)
5098!
5099!--     southward-facding
5100        ELSEIF ( surfl(1,i) == isouth_l )  THEN
5101           surf_lsm_v(1)%rad_sw_in(m)  = surfinsw(i)
5102           surf_lsm_v(1)%rad_sw_out(m) = surfoutsw(i)
5103           surf_lsm_v(1)%rad_lw_in(m)  = surfinlw(i)
5104           surf_lsm_v(1)%rad_lw_out(m) = surfoutlw(i)
5105           surf_lsm_v(1)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5106                                         surfinlw(i) - surfoutlw(i)
5107!
5108!--     eastward-facing
5109        ELSEIF ( surfl(1,i) == ieast_l )  THEN
5110           surf_lsm_v(2)%rad_sw_in(m)  = surfinsw(i)
5111           surf_lsm_v(2)%rad_sw_out(m) = surfoutsw(i)
5112           surf_lsm_v(2)%rad_lw_in(m)  = surfinlw(i)
5113           surf_lsm_v(2)%rad_lw_out(m) = surfoutlw(i)
5114           surf_lsm_v(2)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5115                                         surfinlw(i) - surfoutlw(i)
5116!
5117!--     westward-facing
5118        ELSEIF ( surfl(1,i) == iwest_l )  THEN
5119           surf_lsm_v(3)%rad_sw_in(m)  = surfinsw(i)
5120           surf_lsm_v(3)%rad_sw_out(m) = surfoutsw(i)
5121           surf_lsm_v(3)%rad_lw_in(m)  = surfinlw(i)
5122           surf_lsm_v(3)%rad_lw_out(m) = surfoutlw(i)
5123           surf_lsm_v(3)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5124                                         surfinlw(i) - surfoutlw(i)
5125        ENDIF
5126
5127     ENDDO
5128
5129     DO  m = 1, surf_usm_h%ns
5130        surf_usm_h%surfhf(m) = surf_usm_h%rad_sw_in(m)  +                   &
5131                               surf_usm_h%rad_lw_in(m)  -                   &
5132                               surf_usm_h%rad_sw_out(m) -                   &
5133                               surf_usm_h%rad_lw_out(m)
5134     ENDDO
5135     DO  m = 1, surf_lsm_h%ns
5136        surf_lsm_h%surfhf(m) = surf_lsm_h%rad_sw_in(m)  +                   &
5137                               surf_lsm_h%rad_lw_in(m)  -                   &
5138                               surf_lsm_h%rad_sw_out(m) -                   &
5139                               surf_lsm_h%rad_lw_out(m)
5140     ENDDO
5141
5142     DO  l = 0, 3
5143!--     urban
5144        DO  m = 1, surf_usm_v(l)%ns
5145           surf_usm_v(l)%surfhf(m) = surf_usm_v(l)%rad_sw_in(m)  +          &
5146                                     surf_usm_v(l)%rad_lw_in(m)  -          &
5147                                     surf_usm_v(l)%rad_sw_out(m) -          &
5148                                     surf_usm_v(l)%rad_lw_out(m)
5149        ENDDO
5150!--     land
5151        DO  m = 1, surf_lsm_v(l)%ns
5152           surf_lsm_v(l)%surfhf(m) = surf_lsm_v(l)%rad_sw_in(m)  +          &
5153                                     surf_lsm_v(l)%rad_lw_in(m)  -          &
5154                                     surf_lsm_v(l)%rad_sw_out(m) -          &
5155                                     surf_lsm_v(l)%rad_lw_out(m)
5156
5157        ENDDO
5158     ENDDO
5159!
5160!--  Calculate the average temperature, albedo, and emissivity for urban/land
5161!--  domain when using average_radiation in the respective radiation model
5162
5163!--  Precalculate face areas for all face directions using normal vector
5164     DO d = 0, nsurf_type
5165        facearea(d) = 1._wp
5166        IF ( idir(d) == 0 ) facearea(d) = facearea(d) * dx
5167        IF ( jdir(d) == 0 ) facearea(d) = facearea(d) * dy
5168        IF ( kdir(d) == 0 ) facearea(d) = facearea(d) * dz(1)
5169     ENDDO
5170!--  calculate horizontal area
5171! !!! ATTENTION!!! uniform grid is assumed here
5172     area_hor = (nx+1) * (ny+1) * dx * dy
5173!
5174!--  absorbed/received SW & LW and emitted LW energy of all physical
5175!--  surfaces (land and urban) in local processor
5176     pinswl = 0._wp
5177     pinlwl = 0._wp
5178     pabsswl = 0._wp
5179     pabslwl = 0._wp
5180     pemitlwl = 0._wp
5181     emiss_sum_surfl = 0._wp
5182     area_surfl = 0._wp
5183     DO  i = 1, nsurfl
5184        d = surfl(id, i)
5185!--  received SW & LW
5186        pinswl = pinswl + (surfinswdir(i) + surfinswdif(i)) * facearea(d)
5187        pinlwl = pinlwl + surfinlwdif(i) * facearea(d)
5188!--   absorbed SW & LW
5189        pabsswl = pabsswl + (1._wp - albedo_surf(i)) *                   &
5190                                                surfinsw(i) * facearea(d)
5191        pabslwl = pabslwl + emiss_surf(i) * surfinlw(i) * facearea(d)
5192!--   emitted LW
5193        pemitlwl = pemitlwl + surfemitlwl(i) * facearea(d)
5194!--   emissivity and area sum
5195        emiss_sum_surfl = emiss_sum_surfl + emiss_surf(i) * facearea(d)
5196        area_surfl = area_surfl + facearea(d)
5197     END DO
5198!
5199!--  add the absorbed SW energy by plant canopy
5200     IF ( npcbl > 0 )  THEN
5201        pabsswl = pabsswl + SUM(pcbinsw)
5202        pabslwl = pabslwl + SUM(pcbinlw)
5203        pinswl = pinswl + SUM(pcbinswdir) + SUM(pcbinswdif)
5204     ENDIF
5205!
5206!--  gather all rad flux energy in all processors
5207#if defined( __parallel )
5208     CALL MPI_ALLREDUCE( pinswl, pinsw, 1, MPI_REAL, MPI_SUM, comm2d, ierr)
5209     IF ( ierr /= 0 ) THEN
5210         WRITE(9,*) 'Error MPI_AllReduce5:', ierr, pinswl, pinsw
5211         FLUSH(9)
5212     ENDIF
5213     CALL MPI_ALLREDUCE( pinlwl, pinlw, 1, MPI_REAL, MPI_SUM, comm2d, ierr)
5214     IF ( ierr /= 0 ) THEN
5215         WRITE(9,*) 'Error MPI_AllReduce6:', ierr, pinlwl, pinlw
5216         FLUSH(9)
5217     ENDIF
5218     CALL MPI_ALLREDUCE( pabsswl, pabssw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5219     IF ( ierr /= 0 ) THEN
5220         WRITE(9,*) 'Error MPI_AllReduce7:', ierr, pabsswl, pabssw
5221         FLUSH(9)
5222     ENDIF
5223     CALL MPI_ALLREDUCE( pabslwl, pabslw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5224     IF ( ierr /= 0 ) THEN
5225         WRITE(9,*) 'Error MPI_AllReduce8:', ierr, pabslwl, pabslw
5226         FLUSH(9)
5227     ENDIF
5228     CALL MPI_ALLREDUCE( pemitlwl, pemitlw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5229     IF ( ierr /= 0 ) THEN
5230         WRITE(9,*) 'Error MPI_AllReduce8:', ierr, pemitlwl, pemitlw
5231         FLUSH(9)
5232     ENDIF
5233     CALL MPI_ALLREDUCE( emiss_sum_surfl, emiss_sum_surf, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5234     IF ( ierr /= 0 ) THEN
5235         WRITE(9,*) 'Error MPI_AllReduce9:', ierr, emiss_sum_surfl, emiss_sum_surf
5236         FLUSH(9)
5237     ENDIF
5238     CALL MPI_ALLREDUCE( area_surfl, area_surf, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5239     IF ( ierr /= 0 ) THEN
5240         WRITE(9,*) 'Error MPI_AllReduce10:', ierr, area_surfl, area_surf
5241         FLUSH(9)
5242     ENDIF
5243#else
5244     pinsw = pinswl
5245     pinlw = pinlwl
5246     pabssw = pabsswl
5247     pabslw = pabslwl
5248     pemitlw = pemitlwl
5249     emiss_sum_surf = emiss_sum_surfl
5250     area_surf = area_surfl
5251#endif
5252
5253!--  (1) albedo
5254     IF ( pinsw /= 0.0_wp )  &
5255          albedo_urb = (pinsw - pabssw) / pinsw
5256!--  (2) average emmsivity
5257     IF ( area_surf /= 0.0_wp ) &
5258          emissivity_urb = emiss_sum_surf / area_surf
5259!
5260!--  Temporally comment out calculation of effective radiative temperature.
5261!--  See below for more explanation.
5262!--  (3) temperature
5263!--   first we calculate an effective horizontal area to account for
5264!--   the effect of vertical surfaces (which contributes to LW emission)
5265!--   We simply use the ratio of the total LW to the incoming LW flux
5266      area_hor = pinlw/rad_lw_in_diff(nyn,nxl)
5267      t_rad_urb = ( (pemitlw - pabslw + emissivity_urb*pinlw) / &
5268           (emissivity_urb*sigma_sb * area_hor) )**0.25_wp
5269
5270    CONTAINS
5271
5272!------------------------------------------------------------------------------!
5273!> Calculates radiation absorbed by box with given size and LAD.
5274!>
5275!> Simulates resol**2 rays (by equally spacing a bounding horizontal square
5276!> conatining all possible rays that would cross the box) and calculates
5277!> average transparency per ray. Returns fraction of absorbed radiation flux
5278!> and area for which this fraction is effective.
5279!------------------------------------------------------------------------------!
5280    PURE SUBROUTINE box_absorb(boxsize, resol, dens, uvec, area, absorb)
5281       IMPLICIT NONE
5282
5283       REAL(wp), DIMENSION(3), INTENT(in) :: &
5284            boxsize, &      !< z, y, x size of box in m
5285            uvec            !< z, y, x unit vector of incoming flux
5286       INTEGER(iwp), INTENT(in) :: &
5287            resol           !< No. of rays in x and y dimensions
5288       REAL(wp), INTENT(in) :: &
5289            dens            !< box density (e.g. Leaf Area Density)
5290       REAL(wp), INTENT(out) :: &
5291            area, &         !< horizontal area for flux absorbtion
5292            absorb          !< fraction of absorbed flux
5293       REAL(wp) :: &
5294            xshift, yshift, &
5295            xmin, xmax, ymin, ymax, &
5296            xorig, yorig, &
5297            dx1, dy1, dz1, dx2, dy2, dz2, &
5298            crdist, &
5299            transp
5300       INTEGER(iwp) :: &
5301            i, j
5302
5303       xshift = uvec(3) / uvec(1) * boxsize(1)
5304       xmin = min(0._wp, -xshift)
5305       xmax = boxsize(3) + max(0._wp, -xshift)
5306       yshift = uvec(2) / uvec(1) * boxsize(1)
5307       ymin = min(0._wp, -yshift)
5308       ymax = boxsize(2) + max(0._wp, -yshift)
5309
5310       transp = 0._wp
5311       DO i = 1, resol
5312          xorig = xmin + (xmax-xmin) * (i-.5_wp) / resol
5313          DO j = 1, resol
5314             yorig = ymin + (ymax-ymin) * (j-.5_wp) / resol
5315
5316             dz1 = 0._wp
5317             dz2 = boxsize(1)/uvec(1)
5318
5319             IF ( uvec(2) > 0._wp )  THEN
5320                dy1 = -yorig             / uvec(2) !< crossing with y=0
5321                dy2 = (boxsize(2)-yorig) / uvec(2) !< crossing with y=boxsize(2)
5322             ELSE !uvec(2)==0
5323                dy1 = -huge(1._wp)
5324                dy2 = huge(1._wp)
5325             ENDIF
5326
5327             IF ( uvec(3) > 0._wp )  THEN
5328                dx1 = -xorig             / uvec(3) !< crossing with x=0
5329                dx2 = (boxsize(3)-xorig) / uvec(3) !< crossing with x=boxsize(3)
5330             ELSE !uvec(3)==0
5331                dx1 = -huge(1._wp)
5332                dx2 = huge(1._wp)
5333             ENDIF
5334
5335             crdist = max(0._wp, (min(dz2, dy2, dx2) - max(dz1, dy1, dx1)))
5336             transp = transp + exp(-ext_coef * dens * crdist)
5337          ENDDO
5338       ENDDO
5339       transp = transp / resol**2
5340       area = (boxsize(3)+xshift)*(boxsize(2)+yshift)
5341       absorb = 1._wp - transp
5342
5343    END SUBROUTINE box_absorb
5344
5345!------------------------------------------------------------------------------!
5346! Description:
5347! ------------
5348!> This subroutine splits direct and diffusion dw radiation
5349!> It sould not be called in case the radiation model already does it
5350!> It follows <CITATION>
5351!------------------------------------------------------------------------------!
5352    SUBROUTINE calc_diffusion_radiation 
5353   
5354        REAL(wp), PARAMETER                          :: lowest_solarUp = 0.1_wp  !< limit the sun elevation to protect stability of the calculation
5355        INTEGER(iwp)                                 :: i, j
5356        REAL(wp)                                     ::  year_angle              !< angle
5357        REAL(wp)                                     ::  etr                     !< extraterestrial radiation
5358        REAL(wp)                                     ::  corrected_solarUp       !< corrected solar up radiation
5359        REAL(wp)                                     ::  horizontalETR           !< horizontal extraterestrial radiation
5360        REAL(wp)                                     ::  clearnessIndex          !< clearness index
5361        REAL(wp)                                     ::  diff_frac               !< diffusion fraction of the radiation
5362
5363       
5364!--     Calculate current day and time based on the initial values and simulation time
5365        year_angle = ( (day_of_year_init * 86400) + time_utc_init              &
5366                        + time_since_reference_point )  * d_seconds_year       &
5367                        * 2.0_wp * pi
5368       
5369        etr = solar_constant * (1.00011_wp +                                   &
5370                          0.034221_wp * cos(year_angle) +                      &
5371                          0.001280_wp * sin(year_angle) +                      &
5372                          0.000719_wp * cos(2.0_wp * year_angle) +             &
5373                          0.000077_wp * sin(2.0_wp * year_angle))
5374       
5375!--   
5376!--     Under a very low angle, we keep extraterestrial radiation at
5377!--     the last small value, therefore the clearness index will be pushed
5378!--     towards 0 while keeping full continuity.
5379!--   
5380        IF ( zenith(0) <= lowest_solarUp )  THEN
5381            corrected_solarUp = lowest_solarUp
5382        ELSE
5383            corrected_solarUp = zenith(0)
5384        ENDIF
5385       
5386        horizontalETR = etr * corrected_solarUp
5387       
5388        DO i = nxl, nxr
5389            DO j = nys, nyn
5390                clearnessIndex = rad_sw_in(0,j,i) / horizontalETR
5391                diff_frac = 1.0_wp / (1.0_wp + exp(-5.0033_wp + 8.6025_wp * clearnessIndex))
5392                rad_sw_in_diff(j,i) = rad_sw_in(0,j,i) * diff_frac
5393                rad_sw_in_dir(j,i)  = rad_sw_in(0,j,i) * (1.0_wp - diff_frac)
5394                rad_lw_in_diff(j,i) = rad_lw_in(0,j,i)
5395            ENDDO
5396        ENDDO
5397       
5398    END SUBROUTINE calc_diffusion_radiation
5399
5400
5401 END SUBROUTINE radiation_interaction
5402   
5403!------------------------------------------------------------------------------!
5404! Description:
5405! ------------
5406!> This subroutine initializes structures needed for radiative transfer
5407!> model. This model calculates transformation processes of the
5408!> radiation inside urban and land canopy layer. The module includes also
5409!> the interaction of the radiation with the resolved plant canopy.
5410!>
5411!> For more info. see Resler et al. 2017
5412!>
5413!> The new version 2.0 was radically rewriten, the discretization scheme
5414!> has been changed. This new version significantly improves effectivity
5415!> of the paralelization and the scalability of the model.
5416!>
5417!------------------------------------------------------------------------------!
5418    SUBROUTINE radiation_interaction_init
5419
5420       USE control_parameters,                                                 &
5421           ONLY:  dz_stretch_level_start
5422           
5423       USE netcdf_data_input_mod,                                              &
5424           ONLY:  leaf_area_density_f
5425
5426       USE plant_canopy_model_mod,                                             &
5427           ONLY:  pch_index, lad_s
5428
5429       IMPLICIT NONE
5430
5431       INTEGER(iwp) :: i, j, k, l, m
5432       INTEGER(iwp) :: k_topo     !< vertical index indicating topography top for given (j,i)
5433       INTEGER(iwp) :: nzptl, nzubl, nzutl, isurf, ipcgb, imrt
5434       REAL(wp)     :: mrl
5435#if defined( __parallel )
5436       INTEGER(iwp), DIMENSION(:), POINTER       ::  gridsurf_rma   !< fortran pointer, but lower bounds are 1
5437       TYPE(c_ptr)                               ::  gridsurf_rma_p !< allocated c pointer
5438       INTEGER(iwp)                              ::  minfo          !< MPI RMA window info handle
5439#endif
5440
5441!
5442!--    Find nzub, nzut, nzu via wall_flag_0 array (nzb_s_inner will be
5443!--    removed later). The following contruct finds the lowest / largest index
5444!--    for any upward-facing wall (see bit 12).
5445       nzubl = MINVAL( get_topography_top_index( 's' ) )
5446       nzutl = MAXVAL( get_topography_top_index( 's' ) )
5447
5448       nzubl = MAX( nzubl, nzb )
5449
5450       IF ( plant_canopy )  THEN
5451!--        allocate needed arrays
5452           ALLOCATE( pct(nys:nyn,nxl:nxr) )
5453           ALLOCATE( pch(nys:nyn,nxl:nxr) )
5454
5455!--        calculate plant canopy height
5456           npcbl = 0
5457           pct   = 0
5458           pch   = 0
5459           DO i = nxl, nxr
5460               DO j = nys, nyn
5461!
5462!--                Find topography top index
5463                   k_topo = get_topography_top_index_ji( j, i, 's' )
5464
5465                   DO k = nzt+1, 0, -1
5466                       IF ( lad_s(k,j,i) /= 0.0_wp )  THEN
5467!--                        we are at the top of the pcs
5468                           pct(j,i) = k + k_topo
5469                           pch(j,i) = k
5470                           npcbl = npcbl + pch(j,i)
5471                           EXIT
5472                       ENDIF
5473                   ENDDO
5474               ENDDO
5475           ENDDO
5476
5477           nzutl = MAX( nzutl, MAXVAL( pct ) )
5478           nzptl = MAXVAL( pct )
5479!--        code of plant canopy model uses parameter pch_index
5480!--        we need to setup it here to right value
5481!--        (pch_index, lad_s and other arrays in PCM are defined flat)
5482           pch_index = MERGE( leaf_area_density_f%nz - 1, MAXVAL( pch ),       &
5483                              leaf_area_density_f%from_file )
5484
5485           prototype_lad = MAXVAL( lad_s ) * .9_wp  !< better be *1.0 if lad is either 0 or maxval(lad) everywhere
5486           IF ( prototype_lad <= 0._wp ) prototype_lad = .3_wp
5487           !WRITE(message_string, '(a,f6.3)') 'Precomputing effective box optical ' &
5488           !    // 'depth using prototype leaf area density = ', prototype_lad
5489           !CALL message('usm_init_urban_surface', 'PA0520', 0, 0, -1, 6, 0)
5490       ENDIF
5491
5492       nzutl = MIN( nzutl + nzut_free, nzt )
5493
5494#if defined( __parallel )
5495       CALL MPI_AllReduce(nzubl, nzub, 1, MPI_INTEGER, MPI_MIN, comm2d, ierr )
5496       IF ( ierr /= 0 ) THEN
5497           WRITE(9,*) 'Error MPI_AllReduce11:', ierr, nzubl, nzub
5498           FLUSH(9)
5499       ENDIF
5500       CALL MPI_AllReduce(nzutl, nzut, 1, MPI_INTEGER, MPI_MAX, comm2d, ierr )
5501       IF ( ierr /= 0 ) THEN
5502           WRITE(9,*) 'Error MPI_AllReduce12:', ierr, nzutl, nzut
5503           FLUSH(9)
5504       ENDIF
5505       CALL MPI_AllReduce(nzptl, nzpt, 1, MPI_INTEGER, MPI_MAX, comm2d, ierr )
5506       IF ( ierr /= 0 ) THEN
5507           WRITE(9,*) 'Error MPI_AllReduce13:', ierr, nzptl, nzpt
5508           FLUSH(9)
5509       ENDIF
5510#else
5511       nzub = nzubl
5512       nzut = nzutl
5513       nzpt = nzptl
5514#endif
5515!
5516!--    Stretching (non-uniform grid spacing) is not considered in the radiation
5517!--    model. Therefore, vertical stretching has to be applied above the area
5518!--    where the parts of the radiation model which assume constant grid spacing
5519!--    are active. ABS (...) is required because the default value of
5520!--    dz_stretch_level_start is -9999999.9_wp (negative).
5521       IF ( ABS( dz_stretch_level_start(1) ) <= zw(nzut) ) THEN
5522          WRITE( message_string, * ) 'The lowest level where vertical ',       &
5523                                     'stretching is applied have to be ',      &
5524                                     'greater than ', zw(nzut)
5525          CALL message( 'radiation_interaction_init', 'PA0496', 1, 2, 0, 6, 0 )
5526       ENDIF 
5527!
5528!--    global number of urban and plant layers
5529       nzu = nzut - nzub + 1
5530       nzp = nzpt - nzub + 1
5531!
5532!--    check max_raytracing_dist relative to urban surface layer height
5533       mrl = 2.0_wp * nzu * dz(1)
5534!--    set max_raytracing_dist to double the urban surface layer height, if not set
5535       IF ( max_raytracing_dist == -999.0_wp ) THEN
5536          max_raytracing_dist = mrl
5537       ENDIF
5538!--    check if max_raytracing_dist set too low (here we only warn the user. Other
5539!      option is to correct the value again to double the urban surface layer height)
5540       IF ( max_raytracing_dist  <  mrl ) THEN
5541          WRITE(message_string, '(a,f6.1)') 'Max_raytracing_dist is set less than ', &
5542               'double the urban surface layer height, i.e. ', mrl
5543          CALL message('radiation_interaction_init', 'PA0521', 0, 0, -1, 6, 0)
5544       ENDIF
5545!        IF ( max_raytracing_dist <= mrl ) THEN
5546!           IF ( max_raytracing_dist /= -999.0_wp ) THEN
5547! !--          max_raytracing_dist too low
5548!              WRITE(message_string, '(a,f6.1)') 'Max_raytracing_dist too low, ' &
5549!                    // 'override to value ', mrl
5550!              CALL message('radiation_interaction_init', 'PA0521', 0, 0, -1, 6, 0)
5551!           ENDIF
5552!           max_raytracing_dist = mrl
5553!        ENDIF
5554!
5555!--    allocate urban surfaces grid
5556!--    calc number of surfaces in local proc
5557       CALL location_message( '    calculation of indices for surfaces', .TRUE. )
5558       nsurfl = 0
5559!
5560!--    Number of horizontal surfaces including land- and roof surfaces in both USM and LSM. Note that
5561!--    All horizontal surface elements are already counted in surface_mod.
5562       startland = 1
5563       nsurfl    = surf_usm_h%ns + surf_lsm_h%ns
5564       endland   = nsurfl
5565       nlands    = endland - startland + 1
5566
5567!
5568!--    Number of vertical surfaces in both USM and LSM. Note that all vertical surface elements are
5569!--    already counted in surface_mod.
5570       startwall = nsurfl+1
5571       DO  i = 0,3
5572          nsurfl = nsurfl + surf_usm_v(i)%ns + surf_lsm_v(i)%ns
5573       ENDDO
5574       endwall = nsurfl
5575       nwalls  = endwall - startwall + 1
5576
5577!--    fill gridpcbl and pcbl
5578       IF ( npcbl > 0 )  THEN
5579           ALLOCATE( pcbl(iz:ix, 1:npcbl) )
5580           ALLOCATE( gridpcbl(nzub:nzpt,nys:nyn,nxl:nxr) )
5581           pcbl = -1
5582           gridpcbl(:,:,:) = 0
5583           ipcgb = 0
5584           DO i = nxl, nxr
5585               DO j = nys, nyn
5586!
5587!--                Find topography top index
5588                   k_topo = get_topography_top_index_ji( j, i, 's' )
5589
5590                   DO k = k_topo + 1, pct(j,i)
5591                       ipcgb = ipcgb + 1
5592                       gridpcbl(k,j,i) = ipcgb
5593                       pcbl(:,ipcgb) = (/ k, j, i /)
5594                   ENDDO
5595               ENDDO
5596           ENDDO
5597           ALLOCATE( pcbinsw( 1:npcbl ) )
5598           ALLOCATE( pcbinswdir( 1:npcbl ) )
5599           ALLOCATE( pcbinswdif( 1:npcbl ) )
5600           ALLOCATE( pcbinlw( 1:npcbl ) )
5601       ENDIF
5602
5603!--    fill surfl (the ordering of local surfaces given by the following
5604!--    cycles must not be altered, certain file input routines may depend
5605!--    on it)
5606       ALLOCATE(surfl_l(5*nsurfl))  ! is it necessary to allocate it with (5,nsurfl)?
5607       surfl(1:5,1:nsurfl) => surfl_l(1:5*nsurfl)
5608       isurf = 0
5609       IF ( rad_angular_discretization )  THEN
5610!
5611!--       Allocate and fill the reverse indexing array gridsurf
5612#if defined( __parallel )
5613!
5614!--       raytrace_mpi_rma is asserted
5615
5616          CALL MPI_Info_create(minfo, ierr)
5617          IF ( ierr /= 0 ) THEN
5618              WRITE(9,*) 'Error MPI_Info_create1:', ierr
5619              FLUSH(9)
5620          ENDIF
5621          CALL MPI_Info_set(minfo, 'accumulate_ordering', '', ierr)
5622          IF ( ierr /= 0 ) THEN
5623              WRITE(9,*) 'Error MPI_Info_set1:', ierr
5624              FLUSH(9)
5625          ENDIF
5626          CALL MPI_Info_set(minfo, 'accumulate_ops', 'same_op', ierr)
5627          IF ( ierr /= 0 ) THEN
5628              WRITE(9,*) 'Error MPI_Info_set2:', ierr
5629              FLUSH(9)
5630          ENDIF
5631          CALL MPI_Info_set(minfo, 'same_size', 'true', ierr)
5632          IF ( ierr /= 0 ) THEN
5633              WRITE(9,*) 'Error MPI_Info_set3:', ierr
5634              FLUSH(9)
5635          ENDIF
5636          CALL MPI_Info_set(minfo, 'same_disp_unit', 'true', ierr)
5637          IF ( ierr /= 0 ) THEN
5638              WRITE(9,*) 'Error MPI_Info_set4:', ierr
5639              FLUSH(9)
5640          ENDIF
5641
5642          CALL MPI_Win_allocate(INT(STORAGE_SIZE(1_iwp)/8*nsurf_type_u*nzu*nny*nnx, &
5643                                    kind=MPI_ADDRESS_KIND), STORAGE_SIZE(1_iwp)/8,  &
5644                                minfo, comm2d, gridsurf_rma_p, win_gridsurf, ierr)
5645          IF ( ierr /= 0 ) THEN
5646              WRITE(9,*) 'Error MPI_Win_allocate1:', ierr, &
5647                 INT(STORAGE_SIZE(1_iwp)/8*nsurf_type_u*nzu*nny*nnx,kind=MPI_ADDRESS_KIND), &
5648                 STORAGE_SIZE(1_iwp)/8, win_gridsurf
5649              FLUSH(9)
5650          ENDIF
5651
5652          CALL MPI_Info_free(minfo, ierr)
5653          IF ( ierr /= 0 ) THEN
5654              WRITE(9,*) 'Error MPI_Info_free1:', ierr
5655              FLUSH(9)
5656          ENDIF
5657
5658!
5659!--       On Intel compilers, calling c_f_pointer to transform a C pointer
5660!--       directly to a multi-dimensional Fotran pointer leads to strange
5661!--       errors on dimension boundaries. However, transforming to a 1D
5662!--       pointer and then redirecting a multidimensional pointer to it works
5663!--       fine.
5664          CALL c_f_pointer(gridsurf_rma_p, gridsurf_rma, (/ nsurf_type_u*nzu*nny*nnx /))
5665          gridsurf(0:nsurf_type_u-1, nzub:nzut, nys:nyn, nxl:nxr) =>                &
5666                     gridsurf_rma(1:nsurf_type_u*nzu*nny*nnx)
5667#else
5668          ALLOCATE(gridsurf(0:nsurf_type_u-1,nzub:nzut,nys:nyn,nxl:nxr) )
5669#endif
5670          gridsurf(:,:,:,:) = -999
5671       ENDIF
5672
5673!--    add horizontal surface elements (land and urban surfaces)
5674!--    TODO: add urban overhanging surfaces (idown_u)
5675       DO i = nxl, nxr
5676           DO j = nys, nyn
5677              DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
5678                 k = surf_usm_h%k(m)
5679                 isurf = isurf + 1
5680                 surfl(:,isurf) = (/iup_u,k,j,i,m/)
5681                 IF ( rad_angular_discretization ) THEN
5682                    gridsurf(iup_u,k,j,i) = isurf
5683                 ENDIF
5684              ENDDO
5685
5686              DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
5687                 k = surf_lsm_h%k(m)
5688                 isurf = isurf + 1
5689                 surfl(:,isurf) = (/iup_l,k,j,i,m/)
5690                 IF ( rad_angular_discretization ) THEN
5691                    gridsurf(iup_u,k,j,i) = isurf
5692                 ENDIF
5693              ENDDO
5694
5695           ENDDO
5696       ENDDO
5697
5698!--    add vertical surface elements (land and urban surfaces)
5699!--    TODO: remove the hard coding of l = 0 to l = idirection
5700       DO i = nxl, nxr
5701           DO j = nys, nyn
5702              l = 0
5703              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
5704                 k = surf_usm_v(l)%k(m)
5705                 isurf = isurf + 1
5706                 surfl(:,isurf) = (/inorth_u,k,j,i,m/)
5707                 IF ( rad_angular_discretization ) THEN
5708                    gridsurf(inorth_u,k,j,i) = isurf
5709                 ENDIF
5710              ENDDO
5711              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
5712                 k = surf_lsm_v(l)%k(m)
5713                 isurf = isurf + 1
5714                 surfl(:,isurf) = (/inorth_l,k,j,i,m/)
5715                 IF ( rad_angular_discretization ) THEN
5716                    gridsurf(inorth_u,k,j,i) = isurf
5717                 ENDIF
5718              ENDDO
5719
5720              l = 1
5721              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
5722                 k = surf_usm_v(l)%k(m)
5723                 isurf = isurf + 1
5724                 surfl(:,isurf) = (/isouth_u,k,j,i,m/)
5725                 IF ( rad_angular_discretization ) THEN
5726                    gridsurf(isouth_u,k,j,i) = isurf
5727                 ENDIF
5728              ENDDO
5729              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
5730                 k = surf_lsm_v(l)%k(m)
5731                 isurf = isurf + 1
5732                 surfl(:,isurf) = (/isouth_l,k,j,i,m/)
5733                 IF ( rad_angular_discretization ) THEN
5734                    gridsurf(isouth_u,k,j,i) = isurf
5735                 ENDIF
5736              ENDDO
5737
5738              l = 2
5739              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
5740                 k = surf_usm_v(l)%k(m)
5741                 isurf = isurf + 1
5742                 surfl(:,isurf) = (/ieast_u,k,j,i,m/)
5743                 IF ( rad_angular_discretization ) THEN
5744                    gridsurf(ieast_u,k,j,i) = isurf
5745                 ENDIF
5746              ENDDO
5747              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
5748                 k = surf_lsm_v(l)%k(m)
5749                 isurf = isurf + 1
5750                 surfl(:,isurf) = (/ieast_l,k,j,i,m/)
5751                 IF ( rad_angular_discretization ) THEN
5752                    gridsurf(ieast_u,k,j,i) = isurf
5753                 ENDIF
5754              ENDDO
5755
5756              l = 3
5757              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
5758                 k = surf_usm_v(l)%k(m)
5759                 isurf = isurf + 1
5760                 surfl(:,isurf) = (/iwest_u,k,j,i,m/)
5761                 IF ( rad_angular_discretization ) THEN
5762                    gridsurf(iwest_u,k,j,i) = isurf
5763                 ENDIF
5764              ENDDO
5765              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
5766                 k = surf_lsm_v(l)%k(m)
5767                 isurf = isurf + 1
5768                 surfl(:,isurf) = (/iwest_l,k,j,i,m/)
5769                 IF ( rad_angular_discretization ) THEN
5770                    gridsurf(iwest_u,k,j,i) = isurf
5771                 ENDIF
5772              ENDDO
5773           ENDDO
5774       ENDDO
5775!
5776!--    Add local MRT boxes for specified number of levels
5777       nmrtbl = 0
5778       IF ( mrt_nlevels > 0 )  THEN
5779          DO  i = nxl, nxr
5780             DO  j = nys, nyn
5781                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
5782!
5783!--                Skip roof if requested
5784                   IF ( mrt_skip_roof  .AND.  surf_usm_h%isroof_surf(m) )  CYCLE
5785!
5786!--                Cycle over specified no of levels
5787                   nmrtbl = nmrtbl + mrt_nlevels
5788                ENDDO
5789!
5790!--             Dtto for LSM
5791                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
5792                   nmrtbl = nmrtbl + mrt_nlevels
5793                ENDDO
5794             ENDDO
5795          ENDDO
5796
5797          ALLOCATE( mrtbl(iz:ix,nmrtbl), mrtsky(nmrtbl), mrtskyt(nmrtbl), &
5798                    mrtinsw(nmrtbl), mrtinlw(nmrtbl), mrt(nmrtbl) )
5799
5800          imrt = 0
5801          DO  i = nxl, nxr
5802             DO  j = nys, nyn
5803                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
5804!
5805!--                Skip roof if requested
5806                   IF ( mrt_skip_roof  .AND.  surf_usm_h%isroof_surf(m) )  CYCLE
5807!
5808!--                Cycle over specified no of levels
5809                   l = surf_usm_h%k(m)
5810                   DO  k = l, l + mrt_nlevels - 1
5811                      imrt = imrt + 1
5812                      mrtbl(:,imrt) = (/k,j,i/)
5813                   ENDDO
5814                ENDDO
5815!
5816!--             Dtto for LSM
5817                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
5818                   l = surf_lsm_h%k(m)
5819                   DO  k = l, l + mrt_nlevels - 1
5820                      imrt = imrt + 1
5821                      mrtbl(:,imrt) = (/k,j,i/)
5822                   ENDDO
5823                ENDDO
5824             ENDDO
5825          ENDDO
5826       ENDIF
5827
5828!
5829!--    broadband albedo of the land, roof and wall surface
5830!--    for domain border and sky set artifically to 1.0
5831!--    what allows us to calculate heat flux leaving over
5832!--    side and top borders of the domain
5833       ALLOCATE ( albedo_surf(nsurfl) )
5834       albedo_surf = 1.0_wp
5835!
5836!--    Also allocate further array for emissivity with identical order of
5837!--    surface elements as radiation arrays.
5838       ALLOCATE ( emiss_surf(nsurfl)  )
5839
5840
5841!
5842!--    global array surf of indices of surfaces and displacement index array surfstart
5843       ALLOCATE(nsurfs(0:numprocs-1))
5844
5845#if defined( __parallel )
5846       CALL MPI_Allgather(nsurfl,1,MPI_INTEGER,nsurfs,1,MPI_INTEGER,comm2d,ierr)
5847       IF ( ierr /= 0 ) THEN
5848         WRITE(9,*) 'Error MPI_AllGather1:', ierr, nsurfl, nsurfs
5849         FLUSH(9)
5850     ENDIF
5851
5852#else
5853       nsurfs(0) = nsurfl
5854#endif
5855       ALLOCATE(surfstart(0:numprocs))
5856       k = 0
5857       DO i=0,numprocs-1
5858           surfstart(i) = k
5859           k = k+nsurfs(i)
5860       ENDDO
5861       surfstart(numprocs) = k
5862       nsurf = k
5863       ALLOCATE(surf_l(5*nsurf))
5864       surf(1:5,1:nsurf) => surf_l(1:5*nsurf)
5865
5866#if defined( __parallel )
5867       CALL MPI_AllGatherv(surfl_l, nsurfl*5, MPI_INTEGER, surf_l, nsurfs*5, &
5868           surfstart(0:numprocs-1)*5, MPI_INTEGER, comm2d, ierr)
5869       IF ( ierr /= 0 ) THEN
5870           WRITE(9,*) 'Error MPI_AllGatherv4:', ierr, SIZE(surfl_l), nsurfl*5, &
5871                      SIZE(surf_l), nsurfs*5, surfstart(0:numprocs-1)*5
5872           FLUSH(9)
5873       ENDIF
5874#else
5875       surf = surfl
5876#endif
5877
5878!--
5879!--    allocation of the arrays for direct and diffusion radiation
5880       CALL location_message( '    allocation of radiation arrays', .TRUE. )
5881!--    rad_sw_in, rad_lw_in are computed in radiation model,
5882!--    splitting of direct and diffusion part is done
5883!--    in calc_diffusion_radiation for now
5884
5885       ALLOCATE( rad_sw_in_dir(nysg:nyng,nxlg:nxrg) )
5886       ALLOCATE( rad_sw_in_diff(nysg:nyng,nxlg:nxrg) )
5887       ALLOCATE( rad_lw_in_diff(nysg:nyng,nxlg:nxrg) )
5888       rad_sw_in_dir  = 0.0_wp
5889       rad_sw_in_diff = 0.0_wp
5890       rad_lw_in_diff = 0.0_wp
5891
5892!--    allocate radiation arrays
5893       ALLOCATE( surfins(nsurfl) )
5894       ALLOCATE( surfinl(nsurfl) )
5895       ALLOCATE( surfinsw(nsurfl) )
5896       ALLOCATE( surfinlw(nsurfl) )
5897       ALLOCATE( surfinswdir(nsurfl) )
5898       ALLOCATE( surfinswdif(nsurfl) )
5899       ALLOCATE( surfinlwdif(nsurfl) )
5900       ALLOCATE( surfoutsl(nsurfl) )
5901       ALLOCATE( surfoutll(nsurfl) )
5902       ALLOCATE( surfoutsw(nsurfl) )
5903       ALLOCATE( surfoutlw(nsurfl) )
5904       ALLOCATE( surfouts(nsurf) )
5905       ALLOCATE( surfoutl(nsurf) )
5906       ALLOCATE( skyvf(nsurfl) )
5907       ALLOCATE( skyvft(nsurfl) )
5908       ALLOCATE( surfemitlwl(nsurfl) )
5909
5910!
5911!--    In case of average_radiation, aggregated surface albedo and emissivity,
5912!--    also set initial value for t_rad_urb.
5913!--    For now set an arbitrary initial value.
5914       IF ( average_radiation )  THEN
5915          albedo_urb = 0.1_wp
5916          emissivity_urb = 0.9_wp
5917          t_rad_urb = pt_surface
5918       ENDIF
5919
5920    END SUBROUTINE radiation_interaction_init
5921
5922!------------------------------------------------------------------------------!
5923! Description:
5924! ------------
5925!> Calculates shape view factors (SVF), plant sink canopy factors (PCSF),
5926!> sky-view factors, discretized path for direct solar radiation, MRT factors
5927!> and other preprocessed data needed for radiation_interaction.
5928!------------------------------------------------------------------------------!
5929    SUBROUTINE radiation_calc_svf
5930   
5931        IMPLICIT NONE
5932       
5933        INTEGER(iwp)                                  :: i, j, k, d, ip, jp
5934        INTEGER(iwp)                                  :: isvf, ksvf, icsf, kcsf, npcsfl, isvf_surflt, imrt, imrtf, ipcgb
5935        INTEGER(iwp)                                  :: sd, td
5936        INTEGER(iwp)                                  :: iaz, izn      !< azimuth, zenith counters
5937        INTEGER(iwp)                                  :: naz, nzn      !< azimuth, zenith num of steps
5938        REAL(wp)                                      :: az0, zn0      !< starting azimuth/zenith
5939        REAL(wp)                                      :: azs, zns      !< azimuth/zenith cycle step
5940        REAL(wp)                                      :: az1, az2      !< relative azimuth of section borders
5941        REAL(wp)                                      :: azmid         !< ray (center) azimuth
5942        REAL(wp), DIMENSION(2)                        :: yxdir         !< y,x *unit* vector of ray direction (in grid units)
5943        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zdirs         !< directions in z (tangent of elevation)
5944        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zbdry         !< zenith angle boundaries
5945        REAL(wp), DIMENSION(:), ALLOCATABLE           :: vffrac        !< view factor fractions for individual rays
5946        REAL(wp), DIMENSION(:), ALLOCATABLE           :: vffrac0       !< dtto (original values)
5947        REAL(wp), DIMENSION(:), ALLOCATABLE           :: ztransp       !< array of transparency in z steps
5948        INTEGER(iwp)                                  :: lowest_free_ray !< index into zdirs
5949        INTEGER(iwp), DIMENSION(:), ALLOCATABLE       :: itarget       !< face indices of detected obstacles
5950        INTEGER(iwp)                                  :: itarg0, itarg1
5951#if defined( __parallel )
5952#endif
5953
5954
5955
5956        REAL(wp),     DIMENSION(0:nsurf_type)         :: facearea
5957        INTEGER(iwp)                                  :: udim
5958        INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET:: nzterrl_l
5959        INTEGER(iwp), DIMENSION(:,:), POINTER         :: nzterrl
5960        REAL(wp),     DIMENSION(:), ALLOCATABLE,TARGET:: csflt_l, pcsflt_l
5961        REAL(wp),     DIMENSION(:,:), POINTER         :: csflt, pcsflt
5962        INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET:: kcsflt_l,kpcsflt_l
5963        INTEGER(iwp), DIMENSION(:,:), POINTER         :: kcsflt,kpcsflt
5964        INTEGER(iwp), DIMENSION(:), ALLOCATABLE       :: icsflt,dcsflt,ipcsflt,dpcsflt
5965        REAL(wp), DIMENSION(3)                        :: uv
5966        LOGICAL                                       :: visible
5967        REAL(wp), DIMENSION(3)                        :: sa, ta          !< real coordinates z,y,x of source and target
5968        REAL(wp)                                      :: transparency, rirrf, sqdist, svfsum
5969        INTEGER(iwp)                                  :: isurflt, isurfs, isurflt_prev
5970        INTEGER(idp)                                  :: ray_skip_maxdist, ray_skip_minval !< skipped raytracing counts
5971        INTEGER(iwp)                                  :: max_track_len !< maximum 2d track length
5972        INTEGER(iwp)                                  :: minfo
5973        REAL(wp), DIMENSION(:), POINTER               :: lad_s_rma       !< fortran 1D pointer
5974        TYPE(c_ptr)                                   :: lad_s_rma_p     !< allocated c pointer
5975#if defined( __parallel )
5976        INTEGER(kind=MPI_ADDRESS_KIND)                :: size_lad_rma
5977#endif
5978!   
5979        INTEGER(iwp), DIMENSION(0:svfnorm_report_num) :: svfnorm_counts
5980        CHARACTER(200)                                :: msg
5981
5982!--     calculation of the SVF
5983        CALL location_message( '    calculation of SVF and CSF', .TRUE. )
5984        CALL radiation_write_debug_log('Start calculation of SVF and CSF')
5985
5986!--     precalculate face areas for different face directions using normal vector
5987        DO d = 0, nsurf_type
5988            facearea(d) = 1._wp
5989            IF ( idir(d) == 0 ) facearea(d) = facearea(d) * dx
5990            IF ( jdir(d) == 0 ) facearea(d) = facearea(d) * dy
5991            IF ( kdir(d) == 0 ) facearea(d) = facearea(d) * dz(1)
5992        ENDDO
5993
5994!--     initialize variables and temporary arrays for calculation of svf and csf
5995        nsvfl  = 0
5996        ncsfl  = 0
5997        nsvfla = gasize
5998        msvf   = 1
5999        ALLOCATE( asvf1(nsvfla) )
6000        asvf => asvf1
6001        IF ( plant_canopy )  THEN
6002            ncsfla = gasize
6003            mcsf   = 1
6004            ALLOCATE( acsf1(ncsfla) )
6005            acsf => acsf1
6006        ENDIF
6007        nmrtf = 0
6008        IF ( mrt_nlevels > 0 )  THEN
6009           nmrtfa = gasize
6010           mmrtf = 1
6011           ALLOCATE ( amrtf1(nmrtfa) )
6012           amrtf => amrtf1
6013        ENDIF
6014        ray_skip_maxdist = 0
6015        ray_skip_minval = 0
6016       
6017!--     initialize temporary terrain and plant canopy height arrays (global 2D array!)
6018        ALLOCATE( nzterr(0:(nx+1)*(ny+1)-1) )
6019#if defined( __parallel )
6020        !ALLOCATE( nzterrl(nys:nyn,nxl:nxr) )
6021        ALLOCATE( nzterrl_l((nyn-nys+1)*(nxr-nxl+1)) )
6022        nzterrl(nys:nyn,nxl:nxr) => nzterrl_l(1:(nyn-nys+1)*(nxr-nxl+1))
6023        nzterrl = get_topography_top_index( 's' )
6024        CALL MPI_AllGather( nzterrl_l, nnx*nny, MPI_INTEGER, &
6025                            nzterr, nnx*nny, MPI_INTEGER, comm2d, ierr )
6026        IF ( ierr /= 0 ) THEN
6027            WRITE(9,*) 'Error MPI_AllGather1:', ierr, SIZE(nzterrl_l), nnx*nny, &
6028                       SIZE(nzterr), nnx*nny
6029            FLUSH(9)
6030        ENDIF
6031        DEALLOCATE(nzterrl_l)
6032#else
6033        nzterr = RESHAPE( get_topography_top_index( 's' ), (/(nx+1)*(ny+1)/) )
6034#endif
6035        IF ( plant_canopy )  THEN
6036            ALLOCATE( plantt(0:(nx+1)*(ny+1)-1) )
6037            maxboxesg = nx + ny + nzp + 1
6038            max_track_len = nx + ny + 1
6039!--         temporary arrays storing values for csf calculation during raytracing
6040            ALLOCATE( boxes(3, maxboxesg) )
6041            ALLOCATE( crlens(maxboxesg) )
6042
6043#if defined( __parallel )
6044            CALL MPI_AllGather( pct, nnx*nny, MPI_INTEGER, &
6045                                plantt, nnx*nny, MPI_INTEGER, comm2d, ierr )
6046            IF ( ierr /= 0 ) THEN
6047                WRITE(9,*) 'Error MPI_AllGather2:', ierr, SIZE(pct), nnx*nny, &
6048                           SIZE(plantt), nnx*nny
6049                FLUSH(9)
6050            ENDIF
6051
6052!--         temporary arrays storing values for csf calculation during raytracing
6053            ALLOCATE( lad_ip(maxboxesg) )
6054            ALLOCATE( lad_disp(maxboxesg) )
6055
6056            IF ( raytrace_mpi_rma )  THEN
6057                ALLOCATE( lad_s_ray(maxboxesg) )
6058               
6059                ! set conditions for RMA communication
6060                CALL MPI_Info_create(minfo, ierr)
6061                IF ( ierr /= 0 ) THEN
6062                    WRITE(9,*) 'Error MPI_Info_create2:', ierr
6063                    FLUSH(9)
6064                ENDIF
6065                CALL MPI_Info_set(minfo, 'accumulate_ordering', '', ierr)
6066                IF ( ierr /= 0 ) THEN
6067                    WRITE(9,*) 'Error MPI_Info_set5:', ierr
6068                    FLUSH(9)
6069                ENDIF
6070                CALL MPI_Info_set(minfo, 'accumulate_ops', 'same_op', ierr)
6071                IF ( ierr /= 0 ) THEN
6072                    WRITE(9,*) 'Error MPI_Info_set6:', ierr
6073                    FLUSH(9)
6074                ENDIF
6075                CALL MPI_Info_set(minfo, 'same_size', 'true', ierr)
6076                IF ( ierr /= 0 ) THEN
6077                    WRITE(9,*) 'Error MPI_Info_set7:', ierr
6078                    FLUSH(9)
6079                ENDIF
6080                CALL MPI_Info_set(minfo, 'same_disp_unit', 'true', ierr)
6081                IF ( ierr /= 0 ) THEN
6082                    WRITE(9,*) 'Error MPI_Info_set8:', ierr
6083                    FLUSH(9)
6084                ENDIF
6085
6086!--             Allocate and initialize the MPI RMA window
6087!--             must be in accordance with allocation of lad_s in plant_canopy_model
6088!--             optimization of memory should be done
6089!--             Argument X of function STORAGE_SIZE(X) needs arbitrary REAL(wp) value, set to 1.0_wp for now
6090                size_lad_rma = STORAGE_SIZE(1.0_wp)/8*nnx*nny*nzp
6091                CALL MPI_Win_allocate(size_lad_rma, STORAGE_SIZE(1.0_wp)/8, minfo, comm2d, &
6092                                        lad_s_rma_p, win_lad, ierr)
6093                IF ( ierr /= 0 ) THEN
6094                    WRITE(9,*) 'Error MPI_Win_allocate2:', ierr, size_lad_rma, &
6095                                STORAGE_SIZE(1.0_wp)/8, win_lad
6096                    FLUSH(9)
6097                ENDIF
6098                CALL c_f_pointer(lad_s_rma_p, lad_s_rma, (/ nzp*nny*nnx /))
6099                sub_lad(nzub:nzpt, nys:nyn, nxl:nxr) => lad_s_rma(1:nzp*nny*nnx)
6100            ELSE
6101                ALLOCATE(sub_lad(nzub:nzpt, nys:nyn, nxl:nxr))
6102            ENDIF
6103#else
6104            plantt = RESHAPE( pct(nys:nyn,nxl:nxr), (/(nx+1)*(ny+1)/) )
6105            ALLOCATE(sub_lad(nzub:nzpt, nys:nyn, nxl:nxr))
6106#endif
6107            plantt_max = MAXVAL(plantt)
6108            ALLOCATE( rt2_track(2, max_track_len), rt2_track_lad(nzub:plantt_max, max_track_len), &
6109                      rt2_track_dist(0:max_track_len), rt2_dist(plantt_max-nzub+2) )
6110
6111            sub_lad(:,:,:) = 0._wp
6112            DO i = nxl, nxr
6113                DO j = nys, nyn
6114                    k = get_topography_top_index_ji( j, i, 's' )
6115
6116                    sub_lad(k:nzpt, j, i) = lad_s(0:nzpt-k, j, i)
6117                ENDDO
6118            ENDDO
6119
6120#if defined( __parallel )
6121            IF ( raytrace_mpi_rma )  THEN
6122                CALL MPI_Info_free(minfo, ierr)
6123                IF ( ierr /= 0 ) THEN
6124                    WRITE(9,*) 'Error MPI_Info_free2:', ierr
6125                    FLUSH(9)
6126                ENDIF
6127                CALL MPI_Win_lock_all(0, win_lad, ierr)
6128                IF ( ierr /= 0 ) THEN
6129                    WRITE(9,*) 'Error MPI_Win_lock_all1:', ierr, win_lad
6130                    FLUSH(9)
6131                ENDIF
6132               
6133            ELSE
6134                ALLOCATE( sub_lad_g(0:(nx+1)*(ny+1)*nzp-1) )
6135                CALL MPI_AllGather( sub_lad, nnx*nny*nzp, MPI_REAL, &
6136                                    sub_lad_g, nnx*nny*nzp, MPI_REAL, comm2d, ierr )
6137                IF ( ierr /= 0 ) THEN
6138                    WRITE(9,*) 'Error MPI_AllGather3:', ierr, SIZE(sub_lad), &
6139                                nnx*nny*nzp, SIZE(sub_lad_g), nnx*nny*nzp
6140                    FLUSH(9)
6141                ENDIF
6142            ENDIF
6143#endif
6144        ENDIF
6145
6146!--     prepare the MPI_Win for collecting the surface indices
6147!--     from the reverse index arrays gridsurf from processors of target surfaces
6148#if defined( __parallel )
6149        IF ( rad_angular_discretization )  THEN
6150!
6151!--         raytrace_mpi_rma is asserted
6152            CALL MPI_Win_lock_all(0, win_gridsurf, ierr)
6153            IF ( ierr /= 0 ) THEN
6154                WRITE(9,*) 'Error MPI_Win_lock_all2:', ierr, win_gridsurf
6155                FLUSH(9)
6156            ENDIF
6157        ENDIF
6158#endif
6159
6160
6161        !--Directions opposite to face normals are not even calculated,
6162        !--they must be preset to 0
6163        !--
6164        dsitrans(:,:) = 0._wp
6165       
6166        DO isurflt = 1, nsurfl
6167!--         determine face centers
6168            td = surfl(id, isurflt)
6169            ta = (/ REAL(surfl(iz, isurflt), wp) - 0.5_wp * kdir(td),  &
6170                      REAL(surfl(iy, isurflt), wp) - 0.5_wp * jdir(td),  &
6171                      REAL(surfl(ix, isurflt), wp) - 0.5_wp * idir(td)  /)
6172
6173            !--Calculate sky view factor and raytrace DSI paths
6174            skyvf(isurflt) = 0._wp
6175            skyvft(isurflt) = 0._wp
6176
6177            !--Select a proper half-sphere for 2D raytracing
6178            SELECT CASE ( td )
6179               CASE ( iup_u, iup_l )
6180                  az0 = 0._wp
6181                  naz = raytrace_discrete_azims
6182                  azs = 2._wp * pi / REAL(naz, wp)
6183                  zn0 = 0._wp
6184                  nzn = raytrace_discrete_elevs / 2
6185                  zns = pi / 2._wp / REAL(nzn, wp)
6186               CASE ( isouth_u, isouth_l )
6187                  az0 = pi / 2._wp
6188                  naz = raytrace_discrete_azims / 2
6189                  azs = pi / REAL(naz, wp)
6190                  zn0 = 0._wp
6191                  nzn = raytrace_discrete_elevs
6192                  zns = pi / REAL(nzn, wp)
6193               CASE ( inorth_u, inorth_l )
6194                  az0 = - pi / 2._wp
6195                  naz = raytrace_discrete_azims / 2
6196                  azs = pi / REAL(naz, wp)
6197                  zn0 = 0._wp
6198                  nzn = raytrace_discrete_elevs
6199                  zns = pi / REAL(nzn, wp)
6200               CASE ( iwest_u, iwest_l )
6201                  az0 = pi
6202                  naz = raytrace_discrete_azims / 2
6203                  azs = pi / REAL(naz, wp)
6204                  zn0 = 0._wp
6205                  nzn = raytrace_discrete_elevs
6206                  zns = pi / REAL(nzn, wp)
6207               CASE ( ieast_u, ieast_l )
6208                  az0 = 0._wp
6209                  naz = raytrace_discrete_azims / 2
6210                  azs = pi / REAL(naz, wp)
6211                  zn0 = 0._wp
6212                  nzn = raytrace_discrete_elevs
6213                  zns = pi / REAL(nzn, wp)
6214               CASE DEFAULT
6215                  WRITE(message_string, *) 'ERROR: the surface type ', td,     &
6216                                           ' is not supported for calculating',&
6217                                           ' SVF'
6218                  CALL message( 'radiation_calc_svf', 'PA0488', 1, 2, 0, 6, 0 )
6219            END SELECT
6220
6221            ALLOCATE ( zdirs(1:nzn), zbdry(0:nzn), vffrac(1:nzn*naz), &
6222                       ztransp(1:nzn*naz), itarget(1:nzn*naz) )   !FIXME allocate itarget only
6223                                                                  !in case of rad_angular_discretization
6224
6225            itarg0 = 1
6226            itarg1 = nzn
6227            zdirs(:) = (/( TAN(pi/2 - (zn0+(REAL(izn,wp)-.5_wp)*zns)), izn=1, nzn )/)
6228            zbdry(:) = (/( zn0+REAL(izn,wp)*zns, izn=0, nzn )/)
6229            IF ( td == iup_u  .OR.  td == iup_l )  THEN
6230               vffrac(1:nzn) = (COS(2 * zbdry(0:nzn-1)) - COS(2 * zbdry(1:nzn))) / 2._wp / REAL(naz, wp)
6231!
6232!--            For horizontal target, vf fractions are constant per azimuth
6233               DO iaz = 1, naz-1
6234                  vffrac(iaz*nzn+1:(iaz+1)*nzn) = vffrac(1:nzn)
6235               ENDDO
6236!--            sum of whole vffrac equals 1, verified
6237            ENDIF
6238!
6239!--         Calculate sky-view factor and direct solar visibility using 2D raytracing
6240            DO iaz = 1, naz
6241               azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
6242               IF ( td /= iup_u  .AND.  td /= iup_l )  THEN
6243                  az2 = REAL(iaz, wp) * azs - pi/2._wp
6244                  az1 = az2 - azs
6245                  !TODO precalculate after 1st line
6246                  vffrac(itarg0:itarg1) = (SIN(az2) - SIN(az1))               &
6247                              * (zbdry(1:nzn) - zbdry(0:nzn-1)                &
6248                                 + SIN(zbdry(0:nzn-1))*COS(zbdry(0:nzn-1))    &
6249                                 - SIN(zbdry(1:nzn))*COS(zbdry(1:nzn)))       &
6250                              / (2._wp * pi)
6251!--               sum of whole vffrac equals 1, verified
6252               ENDIF
6253               yxdir = (/ COS(azmid), SIN(azmid) /)
6254               CALL raytrace_2d(ta, yxdir, nzn, zdirs,                        &
6255                                    surfstart(myid) + isurflt, facearea(td),  &
6256                                    vffrac(itarg0:itarg1), .TRUE., .TRUE.,    &
6257                                    .FALSE., lowest_free_ray,                 &
6258                                    ztransp(itarg0:itarg1),                   &
6259                                    itarget(itarg0:itarg1))   !FIXME unit vect in grid units + zdirs
6260                                                              !FIXME itarget available only in
6261                                                              !case of rad_angular_discretization
6262               skyvf(isurflt) = skyvf(isurflt) + &
6263                                SUM(vffrac(itarg0:itarg0+lowest_free_ray-1))
6264               skyvft(isurflt) = skyvft(isurflt) + &
6265                                 SUM(ztransp(itarg0:itarg0+lowest_free_ray-1) &
6266                                             * vffrac(itarg0:itarg0+lowest_free_ray-1))
6267 
6268!--            Save direct solar transparency
6269               j = MODULO(NINT(azmid/                                          &
6270                               (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
6271                          raytrace_discrete_azims)
6272
6273               DO k = 1, raytrace_discrete_elevs/2
6274                  i = dsidir_rev(k-1, j)
6275                  IF ( i /= -1  .AND.  k <= lowest_free_ray )  &
6276                     dsitrans(isurflt, i) = ztransp(itarg0+k-1)
6277               ENDDO
6278
6279!
6280!--            Advance itarget indices
6281               itarg0 = itarg1 + 1
6282               itarg1 = itarg1 + nzn
6283            ENDDO
6284
6285            IF ( rad_angular_discretization )  THEN
6286!--            sort itarget by face id
6287               CALL quicksort_itarget(itarget,vffrac,ztransp,1,nzn*naz)
6288!
6289!--            find the first valid position
6290               itarg0 = 1
6291               DO WHILE ( itarg0 <= nzn*naz )
6292                  IF ( itarget(itarg0) /= -1 )  EXIT
6293                  itarg0 = itarg0 + 1
6294               ENDDO
6295
6296               DO  i = itarg0, nzn*naz
6297!
6298!--               For duplicate values, only sum up vf fraction value
6299                  IF ( i < nzn*naz )  THEN
6300                     IF ( itarget(i+1) == itarget(i) )  THEN
6301                        vffrac(i+1) = vffrac(i+1) + vffrac(i)
6302                        CYCLE
6303                     ENDIF
6304                  ENDIF
6305!
6306!--               write to the svf array
6307                  nsvfl = nsvfl + 1
6308!--               check dimmension of asvf array and enlarge it if needed
6309                  IF ( nsvfla < nsvfl )  THEN
6310                     k = CEILING(REAL(nsvfla, kind=wp) * grow_factor)
6311                     IF ( msvf == 0 )  THEN
6312                        msvf = 1
6313                        ALLOCATE( asvf1(k) )
6314                        asvf => asvf1
6315                        asvf1(1:nsvfla) = asvf2
6316                        DEALLOCATE( asvf2 )
6317                     ELSE
6318                        msvf = 0
6319                        ALLOCATE( asvf2(k) )
6320                        asvf => asvf2
6321                        asvf2(1:nsvfla) = asvf1
6322                        DEALLOCATE( asvf1 )
6323                     ENDIF
6324
6325                     WRITE (msg,'(A,3I12)') 'Grow asvf:',nsvfl,nsvfla,k
6326                     CALL radiation_write_debug_log( msg )
6327                     
6328                     nsvfla = k
6329                  ENDIF
6330!--               write svf values into the array
6331                  asvf(nsvfl)%isurflt = isurflt
6332                  asvf(nsvfl)%isurfs = itarget(i)
6333                  asvf(nsvfl)%rsvf = vffrac(i)
6334                  asvf(nsvfl)%rtransp = ztransp(i)
6335               END DO
6336
6337            ENDIF ! rad_angular_discretization
6338
6339            DEALLOCATE ( zdirs, zbdry, vffrac, ztransp, itarget ) !FIXME itarget shall be allocated only
6340                                                                  !in case of rad_angular_discretization
6341!
6342!--         Following calculations only required for surface_reflections
6343            IF ( surface_reflections  .AND.  .NOT. rad_angular_discretization )  THEN
6344
6345               DO  isurfs = 1, nsurf
6346                  IF ( .NOT.  surface_facing(surfl(ix, isurflt), surfl(iy, isurflt), &
6347                     surfl(iz, isurflt), surfl(id, isurflt), &
6348                     surf(ix, isurfs), surf(iy, isurfs), &
6349                     surf(iz, isurfs), surf(id, isurfs)) )  THEN
6350                     CYCLE
6351                  ENDIF
6352                 
6353                  sd = surf(id, isurfs)
6354                  sa = (/ REAL(surf(iz, isurfs), wp) - 0.5_wp * kdir(sd),  &
6355                          REAL(surf(iy, isurfs), wp) - 0.5_wp * jdir(sd),  &
6356                          REAL(surf(ix, isurfs), wp) - 0.5_wp * idir(sd)  /)
6357
6358!--               unit vector source -> target
6359                  uv = (/ (ta(1)-sa(1))*dz(1), (ta(2)-sa(2))*dy, (ta(3)-sa(3))*dx /)
6360                  sqdist = SUM(uv(:)**2)
6361                  uv = uv / SQRT(sqdist)
6362
6363!--               reject raytracing above max distance
6364                  IF ( SQRT(sqdist) > max_raytracing_dist ) THEN
6365                     ray_skip_maxdist = ray_skip_maxdist + 1
6366                     CYCLE
6367                  ENDIF
6368                 
6369!--               irradiance factor (our unshaded shape view factor) = view factor per differential target area * source area
6370                  rirrf = dot_product((/ kdir(sd), jdir(sd), idir(sd) /), uv) & ! cosine of source normal and direction
6371                      * dot_product((/ kdir(td), jdir(td), idir(td) /), -uv) &  ! cosine of target normal and reverse direction
6372                      / (pi * sqdist) & ! square of distance between centers
6373                      * facearea(sd)
6374
6375!--               reject raytracing for potentially too small view factor values
6376                  IF ( rirrf < min_irrf_value ) THEN
6377                      ray_skip_minval = ray_skip_minval + 1
6378                      CYCLE
6379                  ENDIF
6380
6381!--               raytrace + process plant canopy sinks within
6382                  CALL raytrace(sa, ta, isurfs, rirrf, facearea(td), .TRUE., &
6383                                visible, transparency)
6384
6385                  IF ( .NOT.  visible ) CYCLE
6386                 ! rsvf = rirrf * transparency
6387
6388!--               write to the svf array
6389                  nsvfl = nsvfl + 1
6390!--               check dimmension of asvf array and enlarge it if needed
6391                  IF ( nsvfla < nsvfl )  THEN
6392                     k = CEILING(REAL(nsvfla, kind=wp) * grow_factor)
6393                     IF ( msvf == 0 )  THEN
6394                        msvf = 1
6395                        ALLOCATE( asvf1(k) )
6396                        asvf => asvf1
6397                        asvf1(1:nsvfla) = asvf2
6398                        DEALLOCATE( asvf2 )
6399                     ELSE
6400                        msvf = 0
6401                        ALLOCATE( asvf2(k) )
6402                        asvf => asvf2
6403                        asvf2(1:nsvfla) = asvf1
6404                        DEALLOCATE( asvf1 )
6405                     ENDIF
6406
6407                     WRITE(msg,'(A,3I12)') 'Grow asvf:',nsvfl,nsvfla,k
6408                     CALL radiation_write_debug_log( msg )
6409                     
6410                     nsvfla = k
6411                  ENDIF
6412!--               write svf values into the array
6413                  asvf(nsvfl)%isurflt = isurflt
6414                  asvf(nsvfl)%isurfs = isurfs
6415                  asvf(nsvfl)%rsvf = rirrf !we postopne multiplication by transparency
6416                  asvf(nsvfl)%rtransp = transparency !a.k.a. Direct Irradiance Factor
6417               ENDDO
6418            ENDIF
6419        ENDDO
6420
6421!--
6422!--     Raytrace to canopy boxes to fill dsitransc TODO optimize
6423        dsitransc(:,:) = 0._wp
6424        az0 = 0._wp
6425        naz = raytrace_discrete_azims
6426        azs = 2._wp * pi / REAL(naz, wp)
6427        zn0 = 0._wp
6428        nzn = raytrace_discrete_elevs / 2
6429        zns = pi / 2._wp / REAL(nzn, wp)
6430        ALLOCATE ( zdirs(1:nzn), vffrac(1:nzn), ztransp(1:nzn), &
6431               itarget(1:nzn) )
6432        zdirs(:) = (/( TAN(pi/2 - (zn0+(REAL(izn,wp)-.5_wp)*zns)), izn=1, nzn )/)
6433        vffrac(:) = 0._wp
6434
6435        DO  ipcgb = 1, npcbl
6436           ta = (/ REAL(pcbl(iz, ipcgb), wp),  &
6437                   REAL(pcbl(iy, ipcgb), wp),  &
6438                   REAL(pcbl(ix, ipcgb), wp) /)
6439!--        Calculate direct solar visibility using 2D raytracing
6440           DO  iaz = 1, naz
6441              azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
6442              yxdir = (/ COS(azmid), SIN(azmid) /)
6443              CALL raytrace_2d(ta, yxdir, nzn, zdirs,                                &
6444                                   -999, -999._wp, vffrac, .FALSE., .FALSE., .TRUE., &
6445                                   lowest_free_ray, ztransp, itarget) !FIXME unit vect in grid units + zdirs
6446
6447!--           Save direct solar transparency
6448              j = MODULO(NINT(azmid/                                         &
6449                             (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
6450                         raytrace_discrete_azims)
6451              DO  k = 1, raytrace_discrete_elevs/2
6452                 i = dsidir_rev(k-1, j)
6453                 IF ( i /= -1  .AND.  k <= lowest_free_ray ) &
6454                    dsitransc(ipcgb, i) = ztransp(k)
6455              ENDDO
6456           ENDDO
6457        ENDDO
6458        DEALLOCATE ( zdirs, vffrac, ztransp, itarget )
6459!--
6460!--     Raytrace to MRT boxes
6461        IF ( nmrtbl > 0 )  THEN
6462           mrtdsit(:,:) = 0._wp
6463           mrtsky(:) = 0._wp
6464           mrtskyt(:) = 0._wp
6465           az0 = 0._wp
6466           naz = raytrace_discrete_azims
6467           azs = 2._wp * pi / REAL(naz, wp)
6468           zn0 = 0._wp
6469           nzn = raytrace_discrete_elevs
6470           zns = pi / REAL(nzn, wp)
6471           ALLOCATE ( zdirs(1:nzn), zbdry(0:nzn), vffrac(1:nzn*naz), vffrac0(1:nzn), &
6472                      ztransp(1:nzn*naz), itarget(1:nzn*naz) )   !FIXME allocate itarget only
6473                                                                 !in case of rad_angular_discretization
6474
6475           zdirs(:) = (/( TAN(pi/2 - (zn0+(REAL(izn,wp)-.5_wp)*zns)), izn=1, nzn )/)
6476           zbdry(:) = (/( zn0+REAL(izn,wp)*zns, izn=0, nzn )/)
6477           vffrac0(:) = (COS(zbdry(0:nzn-1)) - COS(zbdry(1:nzn))) / 2._wp / REAL(naz, wp)
6478
6479           DO  imrt = 1, nmrtbl
6480              ta = (/ REAL(mrtbl(iz, imrt), wp),  &
6481                      REAL(mrtbl(iy, imrt), wp),  &
6482                      REAL(mrtbl(ix, imrt), wp) /)
6483!
6484!--           vf fractions are constant per azimuth
6485              DO iaz = 0, naz-1
6486                 vffrac(iaz*nzn+1:(iaz+1)*nzn) = vffrac0(:)
6487              ENDDO
6488!--           sum of whole vffrac equals 1, verified
6489              itarg0 = 1
6490              itarg1 = nzn
6491!
6492!--           Calculate sky-view factor and direct solar visibility using 2D raytracing
6493              DO  iaz = 1, naz
6494                 azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
6495                 CALL raytrace_2d(ta, (/ COS(azmid), SIN(azmid) /), nzn, zdirs,  &
6496                                  -999, -999._wp, vffrac(itarg0:itarg1), .TRUE., &
6497                                  .FALSE., .TRUE., lowest_free_ray,              &
6498                                  ztransp(itarg0:itarg1),                        &
6499                                  itarget(itarg0:itarg1))   !FIXME unit vect in grid units + zdirs
6500                                                            !FIXME itarget available only in
6501                                                            !case of rad_angular_discretization
6502
6503!--              Sky view factors for MRT
6504                 mrtsky(imrt) = mrtsky(imrt) + &
6505                                  SUM(vffrac(itarg0:itarg0+lowest_free_ray-1))
6506                 mrtskyt(imrt) = mrtskyt(imrt) + &
6507                                   SUM(ztransp(itarg0:itarg0+lowest_free_ray-1) &
6508                                               * vffrac(itarg0:itarg0+lowest_free_ray-1))
6509!--              Direct solar transparency for MRT
6510                 j = MODULO(NINT(azmid/                                         &
6511                                (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
6512                            raytrace_discrete_azims)
6513                 DO  k = 1, raytrace_discrete_elevs/2
6514                    i = dsidir_rev(k-1, j)
6515                    IF ( i /= -1  .AND.  k <= lowest_free_ray ) &
6516                       mrtdsit(imrt, i) = ztransp(itarg0+k-1)
6517                 ENDDO
6518!
6519!--              Advance itarget indices
6520                 itarg0 = itarg1 + 1
6521                 itarg1 = itarg1 + nzn
6522              ENDDO
6523
6524!--           sort itarget by face id
6525              CALL quicksort_itarget(itarget,vffrac,ztransp,1,nzn*naz)
6526!
6527!--           find the first valid position
6528              itarg0 = 1
6529              DO WHILE ( itarg0 <= nzn*naz )
6530                 IF ( itarget(itarg0) /= -1 )  EXIT
6531                 itarg0 = itarg0 + 1
6532              ENDDO
6533
6534              DO  i = itarg0, nzn*naz
6535!
6536!--              For duplicate values, only sum up vf fraction value
6537                 IF ( i < nzn*naz )  THEN
6538                    IF ( itarget(i+1) == itarget(i) )  THEN
6539                       vffrac(i+1) = vffrac(i+1) + vffrac(i)
6540                       CYCLE
6541                    ENDIF
6542                 ENDIF
6543!
6544!--              write to the mrtf array
6545                 nmrtf = nmrtf + 1
6546!--              check dimmension of mrtf array and enlarge it if needed
6547                 IF ( nmrtfa < nmrtf )  THEN
6548                    k = CEILING(REAL(nmrtfa, kind=wp) * grow_factor)
6549                    IF ( mmrtf == 0 )  THEN
6550                       mmrtf = 1
6551                       ALLOCATE( amrtf1(k) )
6552                       amrtf => amrtf1
6553                       amrtf1(1:nmrtfa) = amrtf2
6554                       DEALLOCATE( amrtf2 )
6555                    ELSE
6556                       mmrtf = 0
6557                       ALLOCATE( amrtf2(k) )
6558                       amrtf => amrtf2
6559                       amrtf2(1:nmrtfa) = amrtf1
6560                       DEALLOCATE( amrtf1 )
6561                    ENDIF
6562
6563                    WRITE (msg,'(A,3I12)') 'Grow amrtf:', nmrtf, nmrtfa, k
6564                    CALL radiation_write_debug_log( msg )
6565
6566                    nmrtfa = k
6567                 ENDIF
6568!--              write mrtf values into the array
6569                 amrtf(nmrtf)%isurflt = imrt
6570                 amrtf(nmrtf)%isurfs = itarget(i)
6571                 amrtf(nmrtf)%rsvf = vffrac(i)
6572                 amrtf(nmrtf)%rtransp = ztransp(i)
6573              ENDDO ! itarg
6574
6575           ENDDO ! imrt
6576           DEALLOCATE ( zdirs, zbdry, vffrac, vffrac0, ztransp, itarget )
6577!
6578!--        Move MRT factors to final arrays
6579           ALLOCATE ( mrtf(nmrtf), mrtft(nmrtf), mrtfsurf(2,nmrtf) )
6580           DO  imrtf = 1, nmrtf
6581              mrtf(imrtf) = amrtf(imrtf)%rsvf
6582              mrtft(imrtf) = amrtf(imrtf)%rsvf * amrtf(imrtf)%rtransp
6583              mrtfsurf(:,imrtf) = (/amrtf(imrtf)%isurflt, amrtf(imrtf)%isurfs /)
6584           ENDDO
6585           IF ( ALLOCATED(amrtf1) )  DEALLOCATE( amrtf1 )
6586           IF ( ALLOCATED(amrtf2) )  DEALLOCATE( amrtf2 )
6587        ENDIF ! nmrtbl > 0
6588
6589        IF ( rad_angular_discretization )  THEN
6590#if defined( __parallel )
6591!--        finalize MPI_RMA communication established to get global index of the surface from grid indices
6592!--        flush all MPI window pending requests
6593           CALL MPI_Win_flush_all(win_gridsurf, ierr)
6594           IF ( ierr /= 0 ) THEN
6595               WRITE(9,*) 'Error MPI_Win_flush_all1:', ierr, win_gridsurf
6596               FLUSH(9)
6597           ENDIF
6598!--        unlock MPI window
6599           CALL MPI_Win_unlock_all(win_gridsurf, ierr)
6600           IF ( ierr /= 0 ) THEN
6601               WRITE(9,*) 'Error MPI_Win_unlock_all1:', ierr, win_gridsurf
6602               FLUSH(9)
6603           ENDIF
6604!--        free MPI window
6605           CALL MPI_Win_free(win_gridsurf, ierr)
6606           IF ( ierr /= 0 ) THEN
6607               WRITE(9,*) 'Error MPI_Win_free1:', ierr, win_gridsurf
6608               FLUSH(9)
6609           ENDIF
6610#else
6611           DEALLOCATE ( gridsurf )
6612#endif
6613        ENDIF
6614
6615        CALL radiation_write_debug_log( 'End of calculation SVF' )
6616        WRITE(msg, *) 'Raytracing skipped for maximum distance of ', &
6617           max_raytracing_dist, ' m on ', ray_skip_maxdist, ' pairs.'
6618        CALL radiation_write_debug_log( msg )
6619        WRITE(msg, *) 'Raytracing skipped for minimum potential value of ', &
6620           min_irrf_value , ' on ', ray_skip_minval, ' pairs.'
6621        CALL radiation_write_debug_log( msg )
6622
6623        CALL location_message( '    waiting for completion of SVF and CSF calculation in all processes', .TRUE. )
6624!--     deallocate temporary global arrays
6625        DEALLOCATE(nzterr)
6626       
6627        IF ( plant_canopy )  THEN
6628!--         finalize mpi_rma communication and deallocate temporary arrays
6629#if defined( __parallel )
6630            IF ( raytrace_mpi_rma )  THEN
6631                CALL MPI_Win_flush_all(win_lad, ierr)
6632                IF ( ierr /= 0 ) THEN
6633                    WRITE(9,*) 'Error MPI_Win_flush_all2:', ierr, win_lad
6634                    FLUSH(9)
6635                ENDIF
6636!--             unlock MPI window
6637                CALL MPI_Win_unlock_all(win_lad, ierr)
6638                IF ( ierr /= 0 ) THEN
6639                    WRITE(9,*) 'Error MPI_Win_unlock_all2:', ierr, win_lad
6640                    FLUSH(9)
6641                ENDIF
6642!--             free MPI window
6643                CALL MPI_Win_free(win_lad, ierr)
6644                IF ( ierr /= 0 ) THEN
6645                    WRITE(9,*) 'Error MPI_Win_free2:', ierr, win_lad
6646                    FLUSH(9)
6647                ENDIF
6648!--             deallocate temporary arrays storing values for csf calculation during raytracing
6649                DEALLOCATE( lad_s_ray )
6650!--             sub_lad is the pointer to lad_s_rma in case of raytrace_mpi_rma
6651!--             and must not be deallocated here
6652            ELSE
6653                DEALLOCATE(sub_lad)
6654                DEALLOCATE(sub_lad_g)
6655            ENDIF
6656#else
6657            DEALLOCATE(sub_lad)
6658#endif
6659            DEALLOCATE( boxes )
6660            DEALLOCATE( crlens )
6661            DEALLOCATE( plantt )
6662            DEALLOCATE( rt2_track, rt2_track_lad, rt2_track_dist, rt2_dist )
6663        ENDIF
6664
6665        CALL location_message( '    calculation of the complete SVF array', .TRUE. )
6666
6667        IF ( rad_angular_discretization )  THEN
6668           CALL radiation_write_debug_log( 'Load svf from the structure array to plain arrays' )
6669           ALLOCATE( svf(ndsvf,nsvfl) )
6670           ALLOCATE( svfsurf(idsvf,nsvfl) )
6671
6672           DO isvf = 1, nsvfl
6673               svf(:, isvf) = (/ asvf(isvf)%rsvf, asvf(isvf)%rtransp /)
6674               svfsurf(:, isvf) = (/ asvf(isvf)%isurflt, asvf(isvf)%isurfs /)
6675           ENDDO
6676        ELSE
6677           CALL radiation_write_debug_log( 'Start SVF sort' )
6678!--        sort svf ( a version of quicksort )
6679           CALL quicksort_svf(asvf,1,nsvfl)
6680
6681           !< load svf from the structure array to plain arrays
6682           CALL radiation_write_debug_log( 'Load svf from the structure array to plain arrays' )
6683           ALLOCATE( svf(ndsvf,nsvfl) )
6684           ALLOCATE( svfsurf(idsvf,nsvfl) )
6685           svfnorm_counts(:) = 0._wp
6686           isurflt_prev = -1
6687           ksvf = 1
6688           svfsum = 0._wp
6689           DO isvf = 1, nsvfl
6690!--            normalize svf per target face
6691               IF ( asvf(ksvf)%isurflt /= isurflt_prev )  THEN
6692                   IF ( isurflt_prev /= -1  .AND.  svfsum /= 0._wp )  THEN
6693                       !< update histogram of logged svf normalization values
6694                       i = searchsorted(svfnorm_report_thresh, svfsum / (1._wp-skyvf(isurflt_prev)))
6695                       svfnorm_counts(i) = svfnorm_counts(i) + 1
6696
6697                       svf(1, isvf_surflt:isvf-1) = svf(1, isvf_surflt:isvf-1) / svfsum * (1._wp-skyvf(isurflt_prev))
6698                   ENDIF
6699                   isurflt_prev = asvf(ksvf)%isurflt
6700                   isvf_surflt = isvf
6701                   svfsum = asvf(ksvf)%rsvf !?? / asvf(ksvf)%rtransp
6702               ELSE
6703                   svfsum = svfsum + asvf(ksvf)%rsvf !?? / asvf(ksvf)%rtransp
6704               ENDIF
6705
6706               svf(:, isvf) = (/ asvf(ksvf)%rsvf, asvf(ksvf)%rtransp /)
6707               svfsurf(:, isvf) = (/ asvf(ksvf)%isurflt, asvf(ksvf)%isurfs /)
6708
6709!--            next element
6710               ksvf = ksvf + 1
6711           ENDDO
6712
6713           IF ( isurflt_prev /= -1  .AND.  svfsum /= 0._wp )  THEN
6714               i = searchsorted(svfnorm_report_thresh, svfsum / (1._wp-skyvf(isurflt_prev)))
6715               svfnorm_counts(i) = svfnorm_counts(i) + 1
6716
6717               svf(1, isvf_surflt:nsvfl) = svf(1, isvf_surflt:nsvfl) / svfsum * (1._wp-skyvf(isurflt_prev))
6718           ENDIF
6719           WRITE(9, *) 'SVF normalization histogram:', svfnorm_counts,  &
6720                       'on thresholds:', svfnorm_report_thresh(1:svfnorm_report_num), '(val < thresh <= val)'
6721           !TODO we should be able to deallocate skyvf, from now on we only need skyvft
6722        ENDIF ! rad_angular_discretization
6723
6724!--     deallocate temporary asvf array
6725!--     DEALLOCATE(asvf) - ifort has a problem with deallocation of allocatable target
6726!--     via pointing pointer - we need to test original targets
6727        IF ( ALLOCATED(asvf1) )  THEN
6728            DEALLOCATE(asvf1)
6729        ENDIF
6730        IF ( ALLOCATED(asvf2) )  THEN
6731            DEALLOCATE(asvf2)
6732        ENDIF
6733
6734        npcsfl = 0
6735        IF ( plant_canopy )  THEN
6736
6737            CALL location_message( '    calculation of the complete CSF array', .TRUE. )
6738            CALL radiation_write_debug_log( 'Calculation of the complete CSF array' )
6739!--         sort and merge csf for the last time, keeping the array size to minimum
6740            CALL merge_and_grow_csf(-1)
6741           
6742!--         aggregate csb among processors
6743!--         allocate necessary arrays
6744            udim = max(ncsfl,1)
6745            ALLOCATE( csflt_l(ndcsf*udim) )
6746            csflt(1:ndcsf,1:udim) => csflt_l(1:ndcsf*udim)
6747            ALLOCATE( kcsflt_l(kdcsf*udim) )
6748            kcsflt(1:kdcsf,1:udim) => kcsflt_l(1:kdcsf*udim)
6749            ALLOCATE( icsflt(0:numprocs-1) )
6750            ALLOCATE( dcsflt(0:numprocs-1) )
6751            ALLOCATE( ipcsflt(0:numprocs-1) )
6752            ALLOCATE( dpcsflt(0:numprocs-1) )
6753           
6754!--         fill out arrays of csf values and
6755!--         arrays of number of elements and displacements
6756!--         for particular precessors
6757            icsflt = 0
6758            dcsflt = 0
6759            ip = -1
6760            j = -1
6761            d = 0
6762            DO kcsf = 1, ncsfl
6763                j = j+1
6764                IF ( acsf(kcsf)%ip /= ip )  THEN
6765!--                 new block of the processor
6766!--                 number of elements of previous block
6767                    IF ( ip>=0) icsflt(ip) = j
6768                    d = d+j
6769!--                 blank blocks
6770                    DO jp = ip+1, acsf(kcsf)%ip-1
6771!--                     number of elements is zero, displacement is equal to previous
6772                        icsflt(jp) = 0
6773                        dcsflt(jp) = d
6774                    ENDDO
6775!--                 the actual block
6776                    ip = acsf(kcsf)%ip
6777                    dcsflt(ip) = d
6778                    j = 0
6779                ENDIF
6780!--             fill out real values of rsvf, rtransp
6781                csflt(1,kcsf) = acsf(kcsf)%rsvf
6782!--             fill out integer values of itz,ity,itx,isurfs
6783                kcsflt(1,kcsf) = acsf(kcsf)%itz
6784                kcsflt(2,kcsf) = acsf(kcsf)%ity
6785                kcsflt(3,kcsf) = acsf(kcsf)%itx
6786                kcsflt(4,kcsf) = acsf(kcsf)%isurfs
6787            ENDDO
6788!--         last blank blocks at the end of array
6789            j = j+1
6790            IF ( ip>=0 ) icsflt(ip) = j
6791            d = d+j
6792            DO jp = ip+1, numprocs-1
6793!--             number of elements is zero, displacement is equal to previous
6794                icsflt(jp) = 0
6795                dcsflt(jp) = d
6796            ENDDO
6797           
6798!--         deallocate temporary acsf array
6799!--         DEALLOCATE(acsf) - ifort has a problem with deallocation of allocatable target
6800!--         via pointing pointer - we need to test original targets
6801            IF ( ALLOCATED(acsf1) )  THEN
6802                DEALLOCATE(acsf1)
6803            ENDIF
6804            IF ( ALLOCATED(acsf2) )  THEN
6805                DEALLOCATE(acsf2)
6806            ENDIF
6807                   
6808#if defined( __parallel )
6809!--         scatter and gather the number of elements to and from all processor
6810!--         and calculate displacements
6811            CALL radiation_write_debug_log( 'Scatter and gather the number of elements to and from all processor' )
6812            CALL MPI_AlltoAll(icsflt,1,MPI_INTEGER,ipcsflt,1,MPI_INTEGER,comm2d, ierr)
6813            IF ( ierr /= 0 ) THEN
6814                WRITE(9,*) 'Error MPI_AlltoAll1:', ierr, SIZE(icsflt), SIZE(ipcsflt)
6815                FLUSH(9)
6816            ENDIF
6817
6818            npcsfl = SUM(ipcsflt)
6819            d = 0
6820            DO i = 0, numprocs-1
6821                dpcsflt(i) = d
6822                d = d + ipcsflt(i)
6823            ENDDO
6824
6825!--         exchange csf fields between processors
6826            CALL radiation_write_debug_log( 'Exchange csf fields between processors' )
6827            udim = max(npcsfl,1)
6828            ALLOCATE( pcsflt_l(ndcsf*udim) )
6829            pcsflt(1:ndcsf,1:udim) => pcsflt_l(1:ndcsf*udim)
6830            ALLOCATE( kpcsflt_l(kdcsf*udim) )
6831            kpcsflt(1:kdcsf,1:udim) => kpcsflt_l(1:kdcsf*udim)
6832            CALL MPI_AlltoAllv(csflt_l, ndcsf*icsflt, ndcsf*dcsflt, MPI_REAL, &
6833                pcsflt_l, ndcsf*ipcsflt, ndcsf*dpcsflt, MPI_REAL, comm2d, ierr)
6834            IF ( ierr /= 0 ) THEN
6835                WRITE(9,*) 'Error MPI_AlltoAllv1:', ierr, SIZE(ipcsflt), ndcsf*icsflt, &
6836                            ndcsf*dcsflt, SIZE(pcsflt_l),ndcsf*ipcsflt, ndcsf*dpcsflt
6837                FLUSH(9)
6838            ENDIF
6839
6840            CALL MPI_AlltoAllv(kcsflt_l, kdcsf*icsflt, kdcsf*dcsflt, MPI_INTEGER, &
6841                kpcsflt_l, kdcsf*ipcsflt, kdcsf*dpcsflt, MPI_INTEGER, comm2d, ierr)
6842            IF ( ierr /= 0 ) THEN
6843                WRITE(9,*) 'Error MPI_AlltoAllv2:', ierr, SIZE(kcsflt_l),kdcsf*icsflt, &
6844                           kdcsf*dcsflt, SIZE(kpcsflt_l), kdcsf*ipcsflt, kdcsf*dpcsflt
6845                FLUSH(9)
6846            ENDIF
6847           
6848#else
6849            npcsfl = ncsfl
6850            ALLOCATE( pcsflt(ndcsf,max(npcsfl,ndcsf)) )
6851            ALLOCATE( kpcsflt(kdcsf,max(npcsfl,kdcsf)) )
6852            pcsflt = csflt
6853            kpcsflt = kcsflt
6854#endif
6855
6856!--         deallocate temporary arrays
6857            DEALLOCATE( csflt_l )
6858            DEALLOCATE( kcsflt_l )
6859            DEALLOCATE( icsflt )
6860            DEALLOCATE( dcsflt )
6861            DEALLOCATE( ipcsflt )
6862            DEALLOCATE( dpcsflt )
6863
6864!--         sort csf ( a version of quicksort )
6865            CALL radiation_write_debug_log( 'Sort csf' )
6866            CALL quicksort_csf2(kpcsflt, pcsflt, 1, npcsfl)
6867
6868!--         aggregate canopy sink factor records with identical box & source
6869!--         againg across all values from all processors
6870            CALL radiation_write_debug_log( 'Aggregate canopy sink factor records with identical box' )
6871
6872            IF ( npcsfl > 0 )  THEN
6873                icsf = 1 !< reading index
6874                kcsf = 1 !< writing index
6875                DO while (icsf < npcsfl)
6876!--                 here kpcsf(kcsf) already has values from kpcsf(icsf)
6877                    IF ( kpcsflt(3,icsf) == kpcsflt(3,icsf+1)  .AND.  &
6878                         kpcsflt(2,icsf) == kpcsflt(2,icsf+1)  .AND.  &
6879                         kpcsflt(1,icsf) == kpcsflt(1,icsf+1)  .AND.  &
6880                         kpcsflt(4,icsf) == kpcsflt(4,icsf+1) )  THEN
6881
6882                        pcsflt(1,kcsf) = pcsflt(1,kcsf) + pcsflt(1,icsf+1)
6883
6884!--                     advance reading index, keep writing index
6885                        icsf = icsf + 1
6886                    ELSE
6887!--                     not identical, just advance and copy
6888                        icsf = icsf + 1
6889                        kcsf = kcsf + 1
6890                        kpcsflt(:,kcsf) = kpcsflt(:,icsf)
6891                        pcsflt(:,kcsf) = pcsflt(:,icsf)
6892                    ENDIF
6893                ENDDO
6894!--             last written item is now also the last item in valid part of array
6895                npcsfl = kcsf
6896            ENDIF
6897
6898            ncsfl = npcsfl
6899            IF ( ncsfl > 0 )  THEN
6900                ALLOCATE( csf(ndcsf,ncsfl) )
6901                ALLOCATE( csfsurf(idcsf,ncsfl) )
6902                DO icsf = 1, ncsfl
6903                    csf(:,icsf) = pcsflt(:,icsf)
6904                    csfsurf(1,icsf) =  gridpcbl(kpcsflt(1,icsf),kpcsflt(2,icsf),kpcsflt(3,icsf))
6905                    csfsurf(2,icsf) =  kpcsflt(4,icsf)
6906                ENDDO
6907            ENDIF
6908           
6909!--         deallocation of temporary arrays
6910            IF ( npcbl > 0 )  DEALLOCATE( gridpcbl )
6911            DEALLOCATE( pcsflt_l )
6912            DEALLOCATE( kpcsflt_l )
6913            CALL radiation_write_debug_log( 'End of aggregate csf' )
6914           
6915        ENDIF
6916
6917#if defined( __parallel )
6918        CALL MPI_BARRIER( comm2d, ierr )
6919#endif
6920        CALL radiation_write_debug_log( 'End of radiation_calc_svf (after mpi_barrier)' )
6921
6922        RETURN
6923       
6924!        WRITE( message_string, * )  &
6925!            'I/O error when processing shape view factors / ',  &
6926!            'plant canopy sink factors / direct irradiance factors.'
6927!        CALL message( 'init_urban_surface', 'PA0502', 2, 2, 0, 6, 0 )
6928       
6929    END SUBROUTINE radiation_calc_svf
6930
6931   
6932!------------------------------------------------------------------------------!
6933! Description:
6934! ------------
6935!> Raytracing for detecting obstacles and calculating compound canopy sink
6936!> factors. (A simple obstacle detection would only need to process faces in
6937!> 3 dimensions without any ordering.)
6938!> Assumtions:
6939!> -----------
6940!> 1. The ray always originates from a face midpoint (only one coordinate equals
6941!>    *.5, i.e. wall) and doesn't travel parallel to the surface (that would mean
6942!>    shape factor=0). Therefore, the ray may never travel exactly along a face
6943!>    or an edge.
6944!> 2. From grid bottom to urban surface top the grid has to be *equidistant*
6945!>    within each of the dimensions, including vertical (but the resolution
6946!>    doesn't need to be the same in all three dimensions).
6947!------------------------------------------------------------------------------!
6948    SUBROUTINE raytrace(src, targ, isrc, rirrf, atarg, create_csf, visible, transparency)
6949        IMPLICIT NONE
6950
6951        REAL(wp), DIMENSION(3), INTENT(in)     :: src, targ    !< real coordinates z,y,x
6952        INTEGER(iwp), INTENT(in)               :: isrc         !< index of source face for csf
6953        REAL(wp), INTENT(in)                   :: rirrf        !< irradiance factor for csf
6954        REAL(wp), INTENT(in)                   :: atarg        !< target surface area for csf
6955        LOGICAL, INTENT(in)                    :: create_csf   !< whether to generate new CSFs during raytracing
6956        LOGICAL, INTENT(out)                   :: visible
6957        REAL(wp), INTENT(out)                  :: transparency !< along whole path
6958        INTEGER(iwp)                           :: i, k, d
6959        INTEGER(iwp)                           :: seldim       !< dimension to be incremented
6960        INTEGER(iwp)                           :: ncsb         !< no of written plant canopy sinkboxes
6961        INTEGER(iwp)                           :: maxboxes     !< max no of gridboxes visited
6962        REAL(wp)                               :: distance     !< euclidean along path
6963        REAL(wp)                               :: crlen        !< length of gridbox crossing
6964        REAL(wp)                               :: lastdist     !< beginning of current crossing
6965        REAL(wp)                               :: nextdist     !< end of current crossing
6966        REAL(wp)                               :: realdist     !< distance in meters per unit distance
6967        REAL(wp)                               :: crmid        !< midpoint of crossing
6968        REAL(wp)                               :: cursink      !< sink factor for current canopy box
6969        REAL(wp), DIMENSION(3)                 :: delta        !< path vector
6970        REAL(wp), DIMENSION(3)                 :: uvect        !< unit vector
6971        REAL(wp), DIMENSION(3)                 :: dimnextdist  !< distance for each dimension increments
6972        INTEGER(iwp), DIMENSION(3)             :: box          !< gridbox being crossed
6973        INTEGER(iwp), DIMENSION(3)             :: dimnext      !< next dimension increments along path
6974        INTEGER(iwp), DIMENSION(3)             :: dimdelta     !< dimension direction = +- 1
6975        INTEGER(iwp)                           :: px, py       !< number of processors in x and y dir before
6976                                                               !< the processor in the question
6977        INTEGER(iwp)                           :: ip           !< number of processor where gridbox reside
6978        INTEGER(iwp)                           :: ig           !< 1D index of gridbox in global 2D array
6979        REAL(wp)                               :: lad_s_target !< recieved lad_s of particular grid box
6980
6981!
6982!--     Maximum number of gridboxes visited equals to maximum number of boundaries crossed in each dimension plus one. That's also
6983!--     the maximum number of plant canopy boxes written. We grow the acsf array accordingly using exponential factor.
6984        maxboxes = SUM(ABS(NINT(targ, iwp) - NINT(src, iwp))) + 1
6985        IF ( plant_canopy  .AND.  ncsfl + maxboxes > ncsfla )  THEN
6986!--         use this code for growing by fixed exponential increments (equivalent to case where ncsfl always increases by 1)
6987!--         k = CEILING(grow_factor ** real(CEILING(log(real(ncsfl + maxboxes, kind=wp)) &
6988!--                                                / log(grow_factor)), kind=wp))
6989!--         or use this code to simply always keep some extra space after growing
6990            k = CEILING(REAL(ncsfl + maxboxes, kind=wp) * grow_factor)
6991
6992            CALL merge_and_grow_csf(k)
6993        ENDIF
6994       
6995        transparency = 1._wp
6996        ncsb = 0
6997
6998        delta(:) = targ(:) - src(:)
6999        distance = SQRT(SUM(delta(:)**2))
7000        IF ( distance == 0._wp )  THEN
7001            visible = .TRUE.
7002            RETURN
7003        ENDIF
7004        uvect(:) = delta(:) / distance
7005        realdist = SQRT(SUM( (uvect(:)*(/dz(1),dy,dx/))**2 ))
7006
7007        lastdist = 0._wp
7008
7009!--     Since all face coordinates have values *.5 and we'd like to use
7010!--     integers, all these have .5 added
7011        DO d = 1, 3
7012            IF ( uvect(d) == 0._wp )  THEN
7013                dimnext(d) = 999999999
7014                dimdelta(d) = 999999999
7015                dimnextdist(d) = 1.0E20_wp
7016            ELSE IF ( uvect(d) > 0._wp )  THEN
7017                dimnext(d) = CEILING(src(d) + .5_wp)
7018                dimdelta(d) = 1
7019                dimnextdist(d) = (dimnext(d) - .5_wp - src(d)) / uvect(d)
7020            ELSE
7021                dimnext(d) = FLOOR(src(d) + .5_wp)
7022                dimdelta(d) = -1
7023                dimnextdist(d) = (dimnext(d) - .5_wp - src(d)) / uvect(d)
7024            ENDIF
7025        ENDDO
7026
7027        DO
7028!--         along what dimension will the next wall crossing be?
7029            seldim = minloc(dimnextdist, 1)
7030            nextdist = dimnextdist(seldim)
7031            IF ( nextdist > distance ) nextdist = distance
7032
7033            crlen = nextdist - lastdist
7034            IF ( crlen > .001_wp )  THEN
7035                crmid = (lastdist + nextdist) * .5_wp
7036                box = NINT(src(:) + uvect(:) * crmid, iwp)
7037
7038!--             calculate index of the grid with global indices (box(2),box(3))
7039!--             in the array nzterr and plantt and id of the coresponding processor
7040                px = box(3)/nnx
7041                py = box(2)/nny
7042                ip = px*pdims(2)+py
7043                ig = ip*nnx*nny + (box(3)-px*nnx)*nny + box(2)-py*nny
7044                IF ( box(1) <= nzterr(ig) )  THEN
7045                    visible = .FALSE.
7046                    RETURN
7047                ENDIF
7048
7049                IF ( plant_canopy )  THEN
7050                    IF ( box(1) <= plantt(ig) )  THEN
7051                        ncsb = ncsb + 1
7052                        boxes(:,ncsb) = box
7053                        crlens(ncsb) = crlen
7054#if defined( __parallel )
7055                        lad_ip(ncsb) = ip
7056                        lad_disp(ncsb) = (box(3)-px*nnx)*(nny*nzp) + (box(2)-py*nny)*nzp + box(1)-nzub
7057#endif
7058                    ENDIF
7059                ENDIF
7060            ENDIF
7061
7062            IF ( nextdist >= distance ) EXIT
7063            lastdist = nextdist
7064            dimnext(seldim) = dimnext(seldim) + dimdelta(seldim)
7065            dimnextdist(seldim) = (dimnext(seldim) - .5_wp - src(seldim)) / uvect(seldim)
7066        ENDDO
7067       
7068        IF ( plant_canopy )  THEN
7069#if defined( __parallel )
7070            IF ( raytrace_mpi_rma )  THEN
7071!--             send requests for lad_s to appropriate processor
7072                CALL cpu_log( log_point_s(77), 'rad_rma_lad', 'start' )
7073                DO i = 1, ncsb
7074                    CALL MPI_Get(lad_s_ray(i), 1, MPI_REAL, lad_ip(i), lad_disp(i), &
7075                                 1, MPI_REAL, win_lad, ierr)
7076                    IF ( ierr /= 0 )  THEN
7077                        WRITE(9,*) 'Error MPI_Get1:', ierr, lad_s_ray(i), &
7078                                   lad_ip(i), lad_disp(i), win_lad
7079                        FLUSH(9)
7080                    ENDIF
7081                ENDDO
7082               
7083!--             wait for all pending local requests complete
7084                CALL MPI_Win_flush_local_all(win_lad, ierr)
7085                IF ( ierr /= 0 )  THEN
7086                    WRITE(9,*) 'Error MPI_Win_flush_local_all1:', ierr, win_lad
7087                    FLUSH(9)
7088                ENDIF
7089                CALL cpu_log( log_point_s(77), 'rad_rma_lad', 'stop' )
7090               
7091            ENDIF
7092#endif
7093
7094!--         calculate csf and transparency
7095            DO i = 1, ncsb
7096#if defined( __parallel )
7097                IF ( raytrace_mpi_rma )  THEN
7098                    lad_s_target = lad_s_ray(i)
7099                ELSE
7100                    lad_s_target = sub_lad_g(lad_ip(i)*nnx*nny*nzp + lad_disp(i))
7101                ENDIF
7102#else
7103                lad_s_target = sub_lad(boxes(1,i),boxes(2,i),boxes(3,i))
7104#endif
7105                cursink = 1._wp - exp(-ext_coef * lad_s_target * crlens(i)*realdist)
7106
7107                IF ( create_csf )  THEN
7108!--                 write svf values into the array
7109                    ncsfl = ncsfl + 1
7110                    acsf(ncsfl)%ip = lad_ip(i)
7111                    acsf(ncsfl)%itx = boxes(3,i)
7112                    acsf(ncsfl)%ity = boxes(2,i)
7113                    acsf(ncsfl)%itz = boxes(1,i)
7114                    acsf(ncsfl)%isurfs = isrc
7115                    acsf(ncsfl)%rsvf = cursink*transparency*rirrf*atarg
7116                ENDIF  !< create_csf
7117
7118                transparency = transparency * (1._wp - cursink)
7119               
7120            ENDDO
7121        ENDIF
7122       
7123        visible = .TRUE.
7124
7125    END SUBROUTINE raytrace
7126   
7127 
7128!------------------------------------------------------------------------------!
7129! Description:
7130! ------------
7131!> A new, more efficient version of ray tracing algorithm that processes a whole
7132!> arc instead of a single ray.
7133!>
7134!> In all comments, horizon means tangent of horizon angle, i.e.
7135!> vertical_delta / horizontal_distance
7136!------------------------------------------------------------------------------!
7137   SUBROUTINE raytrace_2d(origin, yxdir, nrays, zdirs, iorig, aorig, vffrac,  &
7138                              calc_svf, create_csf, skip_1st_pcb,             &
7139                              lowest_free_ray, transparency, itarget)
7140      IMPLICIT NONE
7141
7142      REAL(wp), DIMENSION(3), INTENT(IN)     ::  origin        !< z,y,x coordinates of ray origin
7143      REAL(wp), DIMENSION(2), INTENT(IN)     ::  yxdir         !< y,x *unit* vector of ray direction (in grid units)
7144      INTEGER(iwp)                           ::  nrays         !< number of rays (z directions) to raytrace
7145      REAL(wp), DIMENSION(nrays), INTENT(IN) ::  zdirs         !< list of z directions to raytrace (z/hdist, grid, zenith->nadir)
7146      INTEGER(iwp), INTENT(in)               ::  iorig         !< index of origin face for csf
7147      REAL(wp), INTENT(in)                   ::  aorig         !< origin face area for csf
7148      REAL(wp), DIMENSION(nrays), INTENT(in) ::  vffrac        !< view factor fractions of each ray for csf
7149      LOGICAL, INTENT(in)                    ::  calc_svf      !< whether to calculate SFV (identify obstacle surfaces)
7150      LOGICAL, INTENT(in)                    ::  create_csf    !< whether to create canopy sink factors
7151      LOGICAL, INTENT(in)                    ::  skip_1st_pcb  !< whether to skip first plant canopy box during raytracing
7152      INTEGER(iwp), INTENT(out)              ::  lowest_free_ray !< index into zdirs
7153      REAL(wp), DIMENSION(nrays), INTENT(OUT) ::  transparency !< transparencies of zdirs paths
7154      INTEGER(iwp), DIMENSION(nrays), INTENT(OUT) ::  itarget  !< global indices of target faces for zdirs
7155
7156      INTEGER(iwp), DIMENSION(nrays)         ::  target_procs
7157      REAL(wp)                               ::  horizon       !< highest horizon found after raytracing (z/hdist)
7158      INTEGER(iwp)                           ::  i, k, l, d
7159      INTEGER(iwp)                           ::  seldim       !< dimension to be incremented
7160      REAL(wp), DIMENSION(2)                 ::  yxorigin     !< horizontal copy of origin (y,x)
7161      REAL(wp)                               ::  distance     !< euclidean along path
7162      REAL(wp)                               ::  lastdist     !< beginning of current crossing
7163      REAL(wp)                               ::  nextdist     !< end of current crossing
7164      REAL(wp)                               ::  crmid        !< midpoint of crossing
7165      REAL(wp)                               ::  horz_entry   !< horizon at entry to column
7166      REAL(wp)                               ::  horz_exit    !< horizon at exit from column
7167      REAL(wp)                               ::  bdydim       !< boundary for current dimension
7168      REAL(wp), DIMENSION(2)                 ::  crossdist    !< distances to boundary for dimensions
7169      REAL(wp), DIMENSION(2)                 ::  dimnextdist  !< distance for each dimension increments
7170      INTEGER(iwp), DIMENSION(2)             ::  column       !< grid column being crossed
7171      INTEGER(iwp), DIMENSION(2)             ::  dimnext      !< next dimension increments along path
7172      INTEGER(iwp), DIMENSION(2)             ::  dimdelta     !< dimension direction = +- 1
7173      INTEGER(iwp)                           ::  px, py       !< number of processors in x and y dir before
7174                                                              !< the processor in the question
7175      INTEGER(iwp)                           ::  ip           !< number of processor where gridbox reside
7176      INTEGER(iwp)                           ::  ig           !< 1D index of gridbox in global 2D array
7177      INTEGER(iwp)                           ::  wcount       !< RMA window item count
7178      INTEGER(iwp)                           ::  maxboxes     !< max no of CSF created
7179      INTEGER(iwp)                           ::  nly          !< maximum  plant canopy height
7180      INTEGER(iwp)                           ::  ntrack
7181      REAL(wp)                               ::  zbottom, ztop !< urban surface boundary in real numbers
7182      REAL(wp)                               ::  zorig        !< z coordinate of ray column entry
7183      REAL(wp)                               ::  zexit        !< z coordinate of ray column exit
7184      REAL(wp)                               ::  qdist        !< ratio of real distance to z coord difference
7185      REAL(wp)                               ::  dxxyy        !< square of real horizontal distance
7186      REAL(wp)                               ::  curtrans     !< transparency of current PC box crossing
7187      INTEGER(iwp)                           ::  zb0
7188      INTEGER(iwp)                           ::  zb1
7189      INTEGER(iwp)                           ::  nz
7190      INTEGER(iwp)                           ::  iz
7191      INTEGER(iwp)                           ::  zsgn
7192      INTEGER(iwp)                           ::  lowest_lad   !< lowest column cell for which we need LAD
7193      INTEGER(iwp)                           ::  lastdir      !< wall direction before hitting this column
7194      INTEGER(iwp), DIMENSION(2)             ::  lastcolumn
7195
7196#if defined( __parallel )
7197      INTEGER(MPI_ADDRESS_KIND)              ::  wdisp        !< RMA window displacement
7198#endif
7199     
7200      yxorigin(:) = origin(2:3)
7201      transparency(:) = 1._wp !-- Pre-set the all rays to transparent before reducing
7202      horizon = -HUGE(1._wp)
7203      lowest_free_ray = nrays
7204      IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7205         ALLOCATE(target_surfl(nrays))
7206         target_surfl(:) = -1
7207         lastdir = -999
7208         lastcolumn(:) = -999
7209      ENDIF
7210
7211!--   Determine distance to boundary (in 2D xy)
7212      IF ( yxdir(1) > 0._wp )  THEN
7213         bdydim = ny + .5_wp !< north global boundary
7214         crossdist(1) = (bdydim - yxorigin(1)) / yxdir(1)
7215      ELSEIF ( yxdir(1) == 0._wp )  THEN
7216         crossdist(1) = HUGE(1._wp)
7217      ELSE
7218          bdydim = -.5_wp !< south global boundary
7219          crossdist(1) = (bdydim - yxorigin(1)) / yxdir(1)
7220      ENDIF
7221
7222      IF ( yxdir(2) >= 0._wp )  THEN
7223          bdydim = nx + .5_wp !< east global boundary
7224          crossdist(2) = (bdydim - yxorigin(2)) / yxdir(2)
7225      ELSEIF ( yxdir(2) == 0._wp )  THEN
7226         crossdist(2) = HUGE(1._wp)
7227      ELSE
7228          bdydim = -.5_wp !< west global boundary
7229          crossdist(2) = (bdydim - yxorigin(2)) / yxdir(2)
7230      ENDIF
7231      distance = minval(crossdist, 1)
7232
7233      IF ( plant_canopy )  THEN
7234         rt2_track_dist(0) = 0._wp
7235         rt2_track_lad(:,:) = 0._wp
7236         nly = plantt_max - nzub + 1
7237      ENDIF
7238
7239      lastdist = 0._wp
7240
7241!--   Since all face coordinates have values *.5 and we'd like to use
7242!--   integers, all these have .5 added
7243      DO  d = 1, 2
7244          IF ( yxdir(d) == 0._wp )  THEN
7245              dimnext(d) = HUGE(1_iwp)
7246              dimdelta(d) = HUGE(1_iwp)
7247              dimnextdist(d) = HUGE(1._wp)
7248          ELSE IF ( yxdir(d) > 0._wp )  THEN
7249              dimnext(d) = FLOOR(yxorigin(d) + .5_wp) + 1
7250              dimdelta(d) = 1
7251              dimnextdist(d) = (dimnext(d) - .5_wp - yxorigin(d)) / yxdir(d)
7252          ELSE
7253              dimnext(d) = CEILING(yxorigin(d) + .5_wp) - 1
7254              dimdelta(d) = -1
7255              dimnextdist(d) = (dimnext(d) - .5_wp - yxorigin(d)) / yxdir(d)
7256          ENDIF
7257      ENDDO
7258
7259      ntrack = 0
7260      DO
7261!--      along what dimension will the next wall crossing be?
7262         seldim = minloc(dimnextdist, 1)
7263         nextdist = dimnextdist(seldim)
7264         IF ( nextdist > distance )  nextdist = distance
7265
7266         IF ( nextdist > lastdist )  THEN
7267            ntrack = ntrack + 1
7268            crmid = (lastdist + nextdist) * .5_wp
7269            column = NINT(yxorigin(:) + yxdir(:) * crmid, iwp)
7270
7271!--         calculate index of the grid with global indices (column(1),column(2))
7272!--         in the array nzterr and plantt and id of the coresponding processor
7273            px = column(2)/nnx
7274            py = column(1)/nny
7275            ip = px*pdims(2)+py
7276            ig = ip*nnx*nny + (column(2)-px*nnx)*nny + column(1)-py*nny
7277
7278            IF ( lastdist == 0._wp )  THEN
7279               horz_entry = -HUGE(1._wp)
7280            ELSE
7281               horz_entry = (REAL(nzterr(ig), wp) + .5_wp - origin(1)) / lastdist
7282            ENDIF
7283            horz_exit = (REAL(nzterr(ig), wp) + .5_wp - origin(1)) / nextdist
7284
7285            IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7286!
7287!--            Identify vertical obstacles hit by rays in current column
7288               DO WHILE ( lowest_free_ray > 0 )
7289                  IF ( zdirs(lowest_free_ray) > horz_entry )  EXIT
7290!
7291!--               This may only happen after 1st column, so lastdir and lastcolumn are valid
7292                  CALL request_itarget(lastdir,                                         &
7293                        CEILING(-0.5_wp + origin(1) + zdirs(lowest_free_ray)*lastdist), &
7294                        lastcolumn(1), lastcolumn(2),                                   &
7295                        target_surfl(lowest_free_ray), target_procs(lowest_free_ray))
7296                  lowest_free_ray = lowest_free_ray - 1
7297               ENDDO
7298!
7299!--            Identify horizontal obstacles hit by rays in current column
7300               DO WHILE ( lowest_free_ray > 0 )
7301                  IF ( zdirs(lowest_free_ray) > horz_exit )  EXIT
7302                  CALL request_itarget(iup_u, nzterr(ig)+1, column(1), column(2), &
7303                                       target_surfl(lowest_free_ray),           &
7304                                       target_procs(lowest_free_ray))
7305                  lowest_free_ray = lowest_free_ray - 1
7306               ENDDO
7307            ENDIF
7308
7309            horizon = MAX(horizon, horz_entry, horz_exit)
7310
7311            IF ( plant_canopy )  THEN
7312               rt2_track(:, ntrack) = column(:)
7313               rt2_track_dist(ntrack) = nextdist
7314            ENDIF
7315         ENDIF
7316
7317         IF ( nextdist >= distance )  EXIT
7318
7319         IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7320!
7321!--         Save wall direction of coming building column (= this air column)
7322            IF ( seldim == 1 )  THEN
7323               IF ( dimdelta(seldim) == 1 )  THEN
7324                  lastdir = isouth_u
7325               ELSE
7326                  lastdir = inorth_u
7327               ENDIF
7328            ELSE
7329               IF ( dimdelta(seldim) == 1 )  THEN
7330                  lastdir = iwest_u
7331               ELSE
7332                  lastdir = ieast_u
7333               ENDIF
7334            ENDIF
7335            lastcolumn = column
7336         ENDIF
7337         lastdist = nextdist
7338         dimnext(seldim) = dimnext(seldim) + dimdelta(seldim)
7339         dimnextdist(seldim) = (dimnext(seldim) - .5_wp - yxorigin(seldim)) / yxdir(seldim)
7340      ENDDO
7341
7342      IF ( plant_canopy )  THEN
7343!--      Request LAD WHERE applicable
7344!--     
7345#if defined( __parallel )
7346         IF ( raytrace_mpi_rma )  THEN
7347!--         send requests for lad_s to appropriate processor
7348            !CALL cpu_log( log_point_s(77), 'usm_init_rma', 'start' )
7349            DO  i = 1, ntrack
7350               px = rt2_track(2,i)/nnx
7351               py = rt2_track(1,i)/nny
7352               ip = px*pdims(2)+py
7353               ig = ip*nnx*nny + (rt2_track(2,i)-px*nnx)*nny + rt2_track(1,i)-py*nny
7354
7355               IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7356!
7357!--               For fixed view resolution, we need plant canopy even for rays
7358!--               to opposing surfaces
7359                  lowest_lad = nzterr(ig) + 1
7360               ELSE
7361!
7362!--               We only need LAD for rays directed above horizon (to sky)
7363                  lowest_lad = CEILING( -0.5_wp + origin(1) +            &
7364                                    MIN( horizon * rt2_track_dist(i-1),  & ! entry
7365                                         horizon * rt2_track_dist(i)   ) ) ! exit
7366               ENDIF
7367!
7368!--            Skip asking for LAD where all plant canopy is under requested level
7369               IF ( plantt(ig) < lowest_lad )  CYCLE
7370
7371               wdisp = (rt2_track(2,i)-px*nnx)*(nny*nzp) + (rt2_track(1,i)-py*nny)*nzp + lowest_lad-nzub
7372               wcount = plantt(ig)-lowest_lad+1
7373               ! TODO send request ASAP - even during raytracing
7374               CALL MPI_Get(rt2_track_lad(lowest_lad:plantt(ig), i), wcount, MPI_REAL, ip,    &
7375                            wdisp, wcount, MPI_REAL, win_lad, ierr)
7376               IF ( ierr /= 0 )  THEN
7377                  WRITE(9,*) 'Error MPI_Get2:', ierr, rt2_track_lad(lowest_lad:plantt(ig), i), &
7378                             wcount, ip, wdisp, win_lad
7379                  FLUSH(9)
7380               ENDIF
7381            ENDDO
7382
7383!--         wait for all pending local requests complete
7384            ! TODO WAIT selectively for each column later when needed
7385            CALL MPI_Win_flush_local_all(win_lad, ierr)
7386            IF ( ierr /= 0 )  THEN
7387               WRITE(9,*) 'Error MPI_Win_flush_local_all2:', ierr, win_lad
7388               FLUSH(9)
7389            ENDIF
7390            !CALL cpu_log( log_point_s(77), 'usm_init_rma', 'stop' )
7391
7392         ELSE ! raytrace_mpi_rma = .F.
7393            DO  i = 1, ntrack
7394               px = rt2_track(2,i)/nnx
7395               py = rt2_track(1,i)/nny
7396               ip = px*pdims(2)+py
7397               ig = ip*nnx*nny*nzp + (rt2_track(2,i)-px*nnx)*(nny*nzp) + (rt2_track(1,i)-py*nny)*nzp
7398               rt2_track_lad(nzub:plantt_max, i) = sub_lad_g(ig:ig+nly-1)
7399            ENDDO
7400         ENDIF
7401#else
7402         DO  i = 1, ntrack
7403            rt2_track_lad(nzub:plantt_max, i) = sub_lad(rt2_track(1,i), rt2_track(2,i), nzub:plantt_max)
7404         ENDDO
7405#endif
7406      ENDIF ! plant_canopy
7407
7408      IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7409#if defined( __parallel )
7410!--      wait for all gridsurf requests to complete
7411         CALL MPI_Win_flush_local_all(win_gridsurf, ierr)
7412         IF ( ierr /= 0 )  THEN
7413            WRITE(9,*) 'Error MPI_Win_flush_local_all3:', ierr, win_gridsurf
7414            FLUSH(9)
7415         ENDIF
7416#endif
7417!
7418!--      recalculate local surf indices into global ones
7419         DO i = 1, nrays
7420            IF ( target_surfl(i) == -1 )  THEN
7421               itarget(i) = -1
7422            ELSE
7423               itarget(i) = target_surfl(i) + surfstart(target_procs(i))
7424            ENDIF
7425         ENDDO
7426         
7427         DEALLOCATE( target_surfl )
7428         
7429      ELSE
7430         itarget(:) = -1
7431      ENDIF ! rad_angular_discretization
7432
7433      IF ( plant_canopy )  THEN
7434!--      Skip the PCB around origin if requested (for MRT, the PCB might not be there)
7435!--     
7436         IF ( skip_1st_pcb  .AND.  NINT(origin(1)) <= plantt_max )  THEN
7437            rt2_track_lad(NINT(origin(1), iwp), 1) = 0._wp
7438         ENDIF
7439
7440!--      Assert that we have space allocated for CSFs
7441!--     
7442         maxboxes = (ntrack + MAX(CEILING(origin(1)-.5_wp) - nzub,          &
7443                                  nzut - CEILING(origin(1)-.5_wp))) * nrays
7444         IF ( ncsfl + maxboxes > ncsfla )  THEN
7445!--         use this code for growing by fixed exponential increments (equivalent to case where ncsfl always increases by 1)
7446!--         k = CEILING(grow_factor ** real(CEILING(log(real(ncsfl + maxboxes, kind=wp)) &
7447!--                                                / log(grow_factor)), kind=wp))
7448!--         or use this code to simply always keep some extra space after growing
7449            k = CEILING(REAL(ncsfl + maxboxes, kind=wp) * grow_factor)
7450            CALL merge_and_grow_csf(k)
7451         ENDIF
7452
7453!--      Calculate transparencies and store new CSFs
7454!--     
7455         zbottom = REAL(nzub, wp) - .5_wp
7456         ztop = REAL(plantt_max, wp) + .5_wp
7457
7458!--      Reverse direction of radiation (face->sky), only when calc_svf
7459!--     
7460         IF ( calc_svf )  THEN
7461            DO  i = 1, ntrack ! for each column
7462               dxxyy = ((dy*yxdir(1))**2 + (dx*yxdir(2))**2) * (rt2_track_dist(i)-rt2_track_dist(i-1))**2
7463               px = rt2_track(2,i)/nnx
7464               py = rt2_track(1,i)/nny
7465               ip = px*pdims(2)+py
7466
7467               DO  k = 1, nrays ! for each ray
7468!
7469!--               NOTE 6778:
7470!--               With traditional svf discretization, CSFs under the horizon
7471!--               (i.e. for surface to surface radiation)  are created in
7472!--               raytrace(). With rad_angular_discretization, we must create
7473!--               CSFs under horizon only for one direction, otherwise we would
7474!--               have duplicate amount of energy. Although we could choose
7475!--               either of the two directions (they differ only by
7476!--               discretization error with no bias), we choose the the backward
7477!--               direction, because it tends to cumulate high canopy sink
7478!--               factors closer to raytrace origin, i.e. it should potentially
7479!--               cause less moiree.
7480                  IF ( .NOT. rad_angular_discretization )  THEN
7481                     IF ( zdirs(k) <= horizon )  CYCLE
7482                  ENDIF
7483
7484                  zorig = origin(1) + zdirs(k) * rt2_track_dist(i-1)
7485                  IF ( zorig <= zbottom  .OR.  zorig >= ztop )  CYCLE
7486
7487                  zsgn = INT(SIGN(1._wp, zdirs(k)), iwp)
7488                  rt2_dist(1) = 0._wp
7489                  IF ( zdirs(k) == 0._wp )  THEN ! ray is exactly horizontal
7490                     nz = 2
7491                     rt2_dist(nz) = SQRT(dxxyy)
7492                     iz = CEILING(-.5_wp + zorig, iwp)
7493                  ELSE
7494                     zexit = MIN(MAX(origin(1) + zdirs(k) * rt2_track_dist(i), zbottom), ztop)
7495
7496                     zb0 = FLOOR(  zorig * zsgn - .5_wp) + 1  ! because it must be greater than orig
7497                     zb1 = CEILING(zexit * zsgn - .5_wp) - 1  ! because it must be smaller than exit
7498                     nz = MAX(zb1 - zb0 + 3, 2)
7499                     rt2_dist(nz) = SQRT(((zexit-zorig)*dz(1))**2 + dxxyy)
7500                     qdist = rt2_dist(nz) / (zexit-zorig)
7501                     rt2_dist(2:nz-1) = (/( ((REAL(l, wp) + .5_wp) * zsgn - zorig) * qdist , l = zb0, zb1 )/)
7502                     iz = zb0 * zsgn
7503                  ENDIF
7504
7505                  DO  l = 2, nz
7506                     IF ( rt2_track_lad(iz, i) > 0._wp )  THEN
7507                        curtrans = exp(-ext_coef * rt2_track_lad(iz, i) * (rt2_dist(l)-rt2_dist(l-1)))
7508
7509                        IF ( create_csf )  THEN
7510                           ncsfl = ncsfl + 1
7511                           acsf(ncsfl)%ip = ip
7512                           acsf(ncsfl)%itx = rt2_track(2,i)
7513                           acsf(ncsfl)%ity = rt2_track(1,i)
7514                           acsf(ncsfl)%itz = iz
7515                           acsf(ncsfl)%isurfs = iorig
7516                           acsf(ncsfl)%rsvf = (1._wp - curtrans)*transparency(k)*aorig*vffrac(k)
7517                        ENDIF
7518
7519                        transparency(k) = transparency(k) * curtrans
7520                     ENDIF
7521                     iz = iz + zsgn
7522                  ENDDO ! l = 1, nz - 1
7523               ENDDO ! k = 1, nrays
7524            ENDDO ! i = 1, ntrack
7525
7526            transparency(1:lowest_free_ray) = 1._wp !-- Reset rays above horizon to transparent (see NOTE 6778)
7527         ENDIF
7528
7529!--      Forward direction of radiation (sky->face), always
7530!--     
7531         DO  i = ntrack, 1, -1 ! for each column backwards
7532            dxxyy = ((dy*yxdir(1))**2 + (dx*yxdir(2))**2) * (rt2_track_dist(i)-rt2_track_dist(i-1))**2
7533            px = rt2_track(2,i)/nnx
7534            py = rt2_track(1,i)/nny
7535            ip = px*pdims(2)+py
7536
7537            DO  k = 1, nrays ! for each ray
7538!
7539!--            See NOTE 6778 above
7540               IF ( zdirs(k) <= horizon )  CYCLE
7541
7542               zexit = origin(1) + zdirs(k) * rt2_track_dist(i-1)
7543               IF ( zexit <= zbottom  .OR.  zexit >= ztop )  CYCLE
7544
7545               zsgn = -INT(SIGN(1._wp, zdirs(k)), iwp)
7546               rt2_dist(1) = 0._wp
7547               IF ( zdirs(k) == 0._wp )  THEN ! ray is exactly horizontal
7548                  nz = 2
7549                  rt2_dist(nz) = SQRT(dxxyy)
7550                  iz = NINT(zexit, iwp)
7551               ELSE
7552                  zorig = MIN(MAX(origin(1) + zdirs(k) * rt2_track_dist(i), zbottom), ztop)
7553
7554                  zb0 = FLOOR(  zorig * zsgn - .5_wp) + 1  ! because it must be greater than orig
7555                  zb1 = CEILING(zexit * zsgn - .5_wp) - 1  ! because it must be smaller than exit
7556                  nz = MAX(zb1 - zb0 + 3, 2)
7557                  rt2_dist(nz) = SQRT(((zexit-zorig)*dz(1))**2 + dxxyy)
7558                  qdist = rt2_dist(nz) / (zexit-zorig)
7559                  rt2_dist(2:nz-1) = (/( ((REAL(l, wp) + .5_wp) * zsgn - zorig) * qdist , l = zb0, zb1 )/)
7560                  iz = zb0 * zsgn
7561               ENDIF
7562
7563               DO  l = 2, nz
7564                  IF ( rt2_track_lad(iz, i) > 0._wp )  THEN
7565                     curtrans = exp(-ext_coef * rt2_track_lad(iz, i) * (rt2_dist(l)-rt2_dist(l-1)))
7566
7567                     IF ( create_csf )  THEN
7568                        ncsfl = ncsfl + 1
7569                        acsf(ncsfl)%ip = ip
7570                        acsf(ncsfl)%itx = rt2_track(2,i)
7571                        acsf(ncsfl)%ity = rt2_track(1,i)
7572                        acsf(ncsfl)%itz = iz
7573                        acsf(ncsfl)%isurfs = itarget(k) !if above horizon, then itarget(k)==-1, which
7574                                                        !is also a special ID indicating sky
7575                        acsf(ncsfl)%rsvf = (1._wp - curtrans)*transparency(k)*aorig*vffrac(k)
7576                     ENDIF  ! create_csf
7577
7578                     transparency(k) = transparency(k) * curtrans
7579                  ENDIF
7580                  iz = iz + zsgn
7581               ENDDO ! l = 1, nz - 1
7582            ENDDO ! k = 1, nrays
7583         ENDDO ! i = 1, ntrack
7584      ENDIF ! plant_canopy
7585
7586      IF ( .NOT. (rad_angular_discretization  .AND.  calc_svf) )  THEN
7587!
7588!--      Just update lowest_free_ray according to horizon
7589         DO WHILE ( lowest_free_ray > 0 )
7590            IF ( zdirs(lowest_free_ray) > horizon )  EXIT
7591            lowest_free_ray = lowest_free_ray - 1
7592         ENDDO
7593      ENDIF
7594
7595   CONTAINS
7596
7597      SUBROUTINE request_itarget( d, z, y, x, isurfl, iproc )
7598
7599         INTEGER(iwp), INTENT(in)            ::  d, z, y, x
7600         INTEGER(iwp), TARGET, INTENT(out)   ::  isurfl
7601         INTEGER(iwp), INTENT(out)           ::  iproc
7602         INTEGER(iwp)                        ::  px, py        !< number of processors in x and y direction
7603                                                               !< before the processor in the question
7604#if defined( __parallel )
7605         INTEGER(KIND=MPI_ADDRESS_KIND)      ::  target_displ  !< index of the grid in the local gridsurf array
7606
7607!
7608!--      Calculate target processor and index in the remote local target gridsurf array
7609         px = x / nnx
7610         py = y / nny
7611         iproc = px * pdims(2) + py
7612         target_displ = ((x-px*nnx) * nny + y - py*nny ) * nzu * nsurf_type_u +&
7613                        ( z-nzub ) * nsurf_type_u + d
7614!
7615!--      Send MPI_Get request to obtain index target_surfl(i)
7616         CALL MPI_GET( isurfl, 1, MPI_INTEGER, iproc, target_displ,            &
7617                       1, MPI_INTEGER, win_gridsurf, ierr)
7618         IF ( ierr /= 0 )  THEN
7619            WRITE( 9,* ) 'Error MPI_Get3:', ierr, isurfl, iproc, target_displ, &
7620                         win_gridsurf
7621            FLUSH( 9 )
7622         ENDIF
7623#else
7624!--      set index target_surfl(i)
7625         isurfl = gridsurf(d,z,y,x)
7626#endif
7627
7628      END SUBROUTINE request_itarget
7629
7630   END SUBROUTINE raytrace_2d
7631 
7632
7633!------------------------------------------------------------------------------!
7634!
7635! Description:
7636! ------------
7637!> Calculates apparent solar positions for all timesteps and stores discretized
7638!> positions.
7639!------------------------------------------------------------------------------!
7640   SUBROUTINE radiation_presimulate_solar_pos
7641      IMPLICIT NONE
7642
7643      INTEGER(iwp)                              ::  it, i, j
7644      REAL(wp)                                  ::  tsrp_prev
7645      REAL(wp), DIMENSION(:,:), ALLOCATABLE     ::  dsidir_tmp       !< dsidir_tmp[:,i] = unit vector of i-th
7646                                                                     !< appreant solar direction
7647
7648      ALLOCATE ( dsidir_rev(0:raytrace_discrete_elevs/2-1,                 &
7649                            0:raytrace_discrete_azims-1) )
7650      dsidir_rev(:,:) = -1
7651      ALLOCATE ( dsidir_tmp(3,                                             &
7652                     raytrace_discrete_elevs/2*raytrace_discrete_azims) )
7653      ndsidir = 0
7654
7655!
7656!--   We will artificialy update time_since_reference_point and return to
7657!--   true value later
7658      tsrp_prev = time_since_reference_point
7659      sun_direction = .TRUE.
7660
7661!
7662!--   Process spinup time if configured
7663      IF ( spinup_time > 0._wp )  THEN
7664         DO  it = 0, CEILING(spinup_time / dt_spinup)
7665            time_since_reference_point = -spinup_time + REAL(it, wp) * dt_spinup
7666            CALL simulate_pos
7667         ENDDO
7668      ENDIF
7669!
7670!--   Process simulation time
7671      DO  it = 0, CEILING(( end_time - spinup_time ) / dt_radiation)
7672         time_since_reference_point = REAL(it, wp) * dt_radiation
7673         CALL simulate_pos
7674      ENDDO
7675
7676      time_since_reference_point = tsrp_prev
7677
7678!--   Allocate global vars which depend on ndsidir
7679      ALLOCATE ( dsidir ( 3, ndsidir ) )
7680      dsidir(:,:) = dsidir_tmp(:, 1:ndsidir)
7681      DEALLOCATE ( dsidir_tmp )
7682
7683      ALLOCATE ( dsitrans(nsurfl, ndsidir) )
7684      ALLOCATE ( dsitransc(npcbl, ndsidir) )
7685      IF ( nmrtbl > 0 )  ALLOCATE ( mrtdsit(nmrtbl, ndsidir) )
7686
7687      WRITE ( message_string, * ) 'Precalculated', ndsidir, ' solar positions', &
7688                                  'from', it, ' timesteps.'
7689      CALL message( 'radiation_presimulate_solar_pos', 'UI0013', 0, 0, 0, 6, 0 )
7690
7691      CONTAINS
7692
7693      !------------------------------------------------------------------------!
7694      ! Description:
7695      ! ------------
7696      !> Simuates a single position
7697      !------------------------------------------------------------------------!
7698      SUBROUTINE simulate_pos
7699         IMPLICIT NONE
7700!
7701!--      Update apparent solar position based on modified t_s_r_p
7702         CALL calc_zenith
7703         IF ( zenith(0) > 0 )  THEN
7704!--         
7705!--         Identify solar direction vector (discretized number) 1)
7706            i = MODULO(NINT(ATAN2(sun_dir_lon(0), sun_dir_lat(0))               &
7707                            / (2._wp*pi) * raytrace_discrete_azims-.5_wp, iwp), &
7708                       raytrace_discrete_azims)
7709            j = FLOOR(ACOS(zenith(0)) / pi * raytrace_discrete_elevs)
7710            IF ( dsidir_rev(j, i) == -1 )  THEN
7711               ndsidir = ndsidir + 1
7712               dsidir_tmp(:, ndsidir) =                                              &
7713                     (/ COS((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs), &
7714                        SIN((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs)  &
7715                      * COS((REAL(i,wp)+.5_wp) * 2_wp*pi / raytrace_discrete_azims), &
7716                        SIN((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs)  &
7717                      * SIN((REAL(i,wp)+.5_wp) * 2_wp*pi / raytrace_discrete_azims) /)
7718               dsidir_rev(j, i) = ndsidir
7719            ENDIF
7720         ENDIF
7721      END SUBROUTINE simulate_pos
7722
7723   END SUBROUTINE radiation_presimulate_solar_pos
7724
7725
7726
7727!------------------------------------------------------------------------------!
7728! Description:
7729! ------------
7730!> Determines whether two faces are oriented towards each other. Since the
7731!> surfaces follow the gird box surfaces, it checks first whether the two surfaces
7732!> are directed in the same direction, then it checks if the two surfaces are
7733!> located in confronted direction but facing away from each other, e.g. <--| |-->
7734!------------------------------------------------------------------------------!
7735    PURE LOGICAL FUNCTION surface_facing(x, y, z, d, x2, y2, z2, d2)
7736        IMPLICIT NONE
7737        INTEGER(iwp),   INTENT(in)  :: x, y, z, d, x2, y2, z2, d2
7738     
7739        surface_facing = .FALSE.
7740
7741!-- first check: are the two surfaces directed in the same direction
7742        IF ( (d==iup_u  .OR.  d==iup_l )                             &
7743             .AND. (d2==iup_u  .OR. d2==iup_l) ) RETURN
7744        IF ( (d==isouth_u  .OR.  d==isouth_l ) &
7745             .AND.  (d2==isouth_u  .OR.  d2==isouth_l) ) RETURN
7746        IF ( (d==inorth_u  .OR.  d==inorth_l ) &
7747             .AND.  (d2==inorth_u  .OR.  d2==inorth_l) ) RETURN
7748        IF ( (d==iwest_u  .OR.  d==iwest_l )     &
7749             .AND.  (d2==iwest_u  .OR.  d2==iwest_l ) ) RETURN
7750        IF ( (d==ieast_u  .OR.  d==ieast_l )     &
7751             .AND.  (d2==ieast_u  .OR.  d2==ieast_l ) ) RETURN
7752
7753!-- second check: are surfaces facing away from each other
7754        SELECT CASE (d)
7755            CASE (iup_u, iup_l)                     !< upward facing surfaces
7756                IF ( z2 < z ) RETURN
7757            CASE (isouth_u, isouth_l)               !< southward facing surfaces
7758                IF ( y2 > y ) RETURN
7759            CASE (inorth_u, inorth_l)               !< northward facing surfaces
7760                IF ( y2 < y ) RETURN
7761            CASE (iwest_u, iwest_l)                 !< westward facing surfaces
7762                IF ( x2 > x ) RETURN
7763            CASE (ieast_u, ieast_l)                 !< eastward facing surfaces
7764                IF ( x2 < x ) RETURN
7765        END SELECT
7766
7767        SELECT CASE (d2)
7768            CASE (iup_u)                            !< ground, roof
7769                IF ( z < z2 ) RETURN
7770            CASE (isouth_u, isouth_l)               !< south facing
7771                IF ( y > y2 ) RETURN
7772            CASE (inorth_u, inorth_l)               !< north facing
7773                IF ( y < y2 ) RETURN
7774            CASE (iwest_u, iwest_l)                 !< west facing
7775                IF ( x > x2 ) RETURN
7776            CASE (ieast_u, ieast_l)                 !< east facing
7777                IF ( x < x2 ) RETURN
7778            CASE (-1)
7779                CONTINUE
7780        END SELECT
7781
7782        surface_facing = .TRUE.
7783       
7784    END FUNCTION surface_facing
7785
7786
7787!------------------------------------------------------------------------------!
7788!
7789! Description:
7790! ------------
7791!> Soubroutine reads svf and svfsurf data from saved file
7792!> SVF means sky view factors and CSF means canopy sink factors
7793!------------------------------------------------------------------------------!
7794    SUBROUTINE radiation_read_svf
7795
7796       IMPLICIT NONE
7797       
7798       CHARACTER(rad_version_len)   :: rad_version_field
7799       
7800       INTEGER(iwp)                 :: i
7801       INTEGER(iwp)                 :: ndsidir_from_file = 0
7802       INTEGER(iwp)                 :: npcbl_from_file = 0
7803       INTEGER(iwp)                 :: nsurfl_from_file = 0
7804       
7805       DO  i = 0, io_blocks-1
7806          IF ( i == io_group )  THEN
7807
7808!
7809!--          numprocs_previous_run is only known in case of reading restart
7810!--          data. If a new initial run which reads svf data is started the
7811!--          following query will be skipped
7812             IF ( initializing_actions == 'read_restart_data' ) THEN
7813
7814                IF ( numprocs_previous_run /= numprocs ) THEN
7815                   WRITE( message_string, * ) 'A different number of ',        &
7816                                              'processors between the run ',   &
7817                                              'that has written the svf data ',&
7818                                              'and the one that will read it ',&
7819                                              'is not allowed' 
7820                   CALL message( 'check_open', 'PA0491', 1, 2, 0, 6, 0 )
7821                ENDIF
7822
7823             ENDIF
7824             
7825!
7826!--          Open binary file
7827             CALL check_open( 88 )
7828
7829!
7830!--          read and check version
7831             READ ( 88 ) rad_version_field
7832             IF ( TRIM(rad_version_field) /= TRIM(rad_version) )  THEN
7833                 WRITE( message_string, * ) 'Version of binary SVF file "',    &
7834                             TRIM(rad_version_field), '" does not match ',     &
7835                             'the version of model "', TRIM(rad_version), '"'
7836                 CALL message( 'radiation_read_svf', 'PA0482', 1, 2, 0, 6, 0 )
7837             ENDIF
7838             
7839!
7840!--          read nsvfl, ncsfl, nsurfl
7841             READ ( 88 ) nsvfl, ncsfl, nsurfl_from_file, npcbl_from_file,      &
7842                         ndsidir_from_file
7843             
7844             IF ( nsvfl < 0  .OR.  ncsfl < 0 )  THEN
7845                 WRITE( message_string, * ) 'Wrong number of SVF or CSF'
7846                 CALL message( 'radiation_read_svf', 'PA0483', 1, 2, 0, 6, 0 )
7847             ELSE
7848                 WRITE(message_string,*) '    Number of SVF, CSF, and nsurfl ',&
7849                                         'to read', nsvfl, ncsfl,              &
7850                                         nsurfl_from_file
7851                 CALL location_message( message_string, .TRUE. )
7852             ENDIF
7853             
7854             IF ( nsurfl_from_file /= nsurfl )  THEN
7855                 WRITE( message_string, * ) 'nsurfl from SVF file does not ',  &
7856                                            'match calculated nsurfl from ',   &
7857                                            'radiation_interaction_init'
7858                 CALL message( 'radiation_read_svf', 'PA0490', 1, 2, 0, 6, 0 )
7859             ENDIF
7860             
7861             IF ( npcbl_from_file /= npcbl )  THEN
7862                 WRITE( message_string, * ) 'npcbl from SVF file does not ',   &
7863                                            'match calculated npcbl from ',    &
7864                                            'radiation_interaction_init'
7865                 CALL message( 'radiation_read_svf', 'PA0493', 1, 2, 0, 6, 0 )
7866             ENDIF
7867             
7868             IF ( ndsidir_from_file /= ndsidir )  THEN
7869                 WRITE( message_string, * ) 'ndsidir from SVF file does not ', &
7870                                            'match calculated ndsidir from ',  &
7871                                            'radiation_presimulate_solar_pos'
7872                 CALL message( 'radiation_read_svf', 'PA0494', 1, 2, 0, 6, 0 )
7873             ENDIF
7874             
7875!
7876!--          Arrays skyvf, skyvft, dsitrans and dsitransc are allready
7877!--          allocated in radiation_interaction_init and
7878!--          radiation_presimulate_solar_pos
7879             IF ( nsurfl > 0 )  THEN
7880                READ(88) skyvf
7881                READ(88) skyvft
7882                READ(88) dsitrans 
7883             ENDIF
7884             
7885             IF ( plant_canopy  .AND.  npcbl > 0 ) THEN
7886                READ ( 88 )  dsitransc
7887             ENDIF
7888             
7889!
7890!--          The allocation of svf, svfsurf, csf and csfsurf happens in routine
7891!--          radiation_calc_svf which is not called if the program enters
7892!--          radiation_read_svf. Therefore these arrays has to allocate in the
7893!--          following
7894             IF ( nsvfl > 0 )  THEN
7895                ALLOCATE( svf(ndsvf,nsvfl) )
7896                ALLOCATE( svfsurf(idsvf,nsvfl) )
7897                READ(88) svf
7898                READ(88) svfsurf
7899             ENDIF
7900
7901             IF ( plant_canopy  .AND.  ncsfl > 0 )  THEN
7902                ALLOCATE( csf(ndcsf,ncsfl) )
7903                ALLOCATE( csfsurf(idcsf,ncsfl) )
7904                READ(88) csf
7905                READ(88) csfsurf
7906             ENDIF
7907             
7908!
7909!--          Close binary file                 
7910             CALL close_file( 88 )
7911               
7912          ENDIF
7913#if defined( __parallel )
7914          CALL MPI_BARRIER( comm2d, ierr )
7915#endif
7916       ENDDO
7917
7918    END SUBROUTINE radiation_read_svf
7919
7920
7921!------------------------------------------------------------------------------!
7922!
7923! Description:
7924! ------------
7925!> Subroutine stores svf, svfsurf, csf and csfsurf data to a file.
7926!------------------------------------------------------------------------------!
7927    SUBROUTINE radiation_write_svf
7928
7929       IMPLICIT NONE
7930       
7931       INTEGER(iwp)        :: i
7932
7933       DO  i = 0, io_blocks-1
7934          IF ( i == io_group )  THEN
7935!
7936!--          Open binary file
7937             CALL check_open( 89 )
7938
7939             WRITE ( 89 )  rad_version
7940             WRITE ( 89 )  nsvfl, ncsfl, nsurfl, npcbl, ndsidir
7941             IF ( nsurfl > 0 ) THEN
7942                WRITE ( 89 )  skyvf
7943                WRITE ( 89 )  skyvft
7944                WRITE ( 89 )  dsitrans
7945             ENDIF
7946             IF ( npcbl > 0 ) THEN
7947                WRITE ( 89 )  dsitransc
7948             ENDIF
7949             IF ( nsvfl > 0 ) THEN
7950                WRITE ( 89 )  svf
7951                WRITE ( 89 )  svfsurf
7952             ENDIF
7953             IF ( plant_canopy  .AND.  ncsfl > 0 )  THEN
7954                 WRITE ( 89 )  csf
7955                 WRITE ( 89 )  csfsurf
7956             ENDIF
7957
7958!
7959!--          Close binary file                 
7960             CALL close_file( 89 )
7961
7962          ENDIF
7963#if defined( __parallel )
7964          CALL MPI_BARRIER( comm2d, ierr )
7965#endif
7966       ENDDO
7967    END SUBROUTINE radiation_write_svf
7968
7969!------------------------------------------------------------------------------!
7970!
7971! Description:
7972! ------------
7973!> Block of auxiliary subroutines:
7974!> 1. quicksort and corresponding comparison
7975!> 2. merge_and_grow_csf for implementation of "dynamical growing"
7976!>    array for csf
7977!------------------------------------------------------------------------------!
7978!-- quicksort.f -*-f90-*-
7979!-- Author: t-nissie, adaptation J.Resler
7980!-- License: GPLv3
7981!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
7982    RECURSIVE SUBROUTINE quicksort_itarget(itarget, vffrac, ztransp, first, last)
7983        IMPLICIT NONE
7984        INTEGER(iwp), DIMENSION(:), INTENT(INOUT)   :: itarget
7985        REAL(wp), DIMENSION(:), INTENT(INOUT)       :: vffrac, ztransp
7986        INTEGER(iwp), INTENT(IN)                    :: first, last
7987        INTEGER(iwp)                                :: x, t
7988        INTEGER(iwp)                                :: i, j
7989        REAL(wp)                                    :: tr
7990
7991        IF ( first>=last ) RETURN
7992        x = itarget((first+last)/2)
7993        i = first
7994        j = last
7995        DO
7996            DO WHILE ( itarget(i) < x )
7997               i=i+1
7998            ENDDO
7999            DO WHILE ( x < itarget(j) )
8000                j=j-1
8001            ENDDO
8002            IF ( i >= j ) EXIT
8003            t = itarget(i);  itarget(i) = itarget(j);  itarget(j) = t
8004            tr = vffrac(i);  vffrac(i) = vffrac(j);  vffrac(j) = tr
8005            tr = ztransp(i);  ztransp(i) = ztransp(j);  ztransp(j) = tr
8006            i=i+1
8007            j=j-1
8008        ENDDO
8009        IF ( first < i-1 ) CALL quicksort_itarget(itarget, vffrac, ztransp, first, i-1)
8010        IF ( j+1 < last )  CALL quicksort_itarget(itarget, vffrac, ztransp, j+1, last)
8011    END SUBROUTINE quicksort_itarget
8012
8013    PURE FUNCTION svf_lt(svf1,svf2) result (res)
8014      TYPE (t_svf), INTENT(in) :: svf1,svf2
8015      LOGICAL                  :: res
8016      IF ( svf1%isurflt < svf2%isurflt  .OR.    &
8017          (svf1%isurflt == svf2%isurflt  .AND.  svf1%isurfs < svf2%isurfs) )  THEN
8018          res = .TRUE.
8019      ELSE
8020          res = .FALSE.
8021      ENDIF
8022    END FUNCTION svf_lt
8023
8024
8025!-- quicksort.f -*-f90-*-
8026!-- Author: t-nissie, adaptation J.Resler
8027!-- License: GPLv3
8028!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8029    RECURSIVE SUBROUTINE quicksort_svf(svfl, first, last)
8030        IMPLICIT NONE
8031        TYPE(t_svf), DIMENSION(:), INTENT(INOUT)  :: svfl
8032        INTEGER(iwp), INTENT(IN)                  :: first, last
8033        TYPE(t_svf)                               :: x, t
8034        INTEGER(iwp)                              :: i, j
8035
8036        IF ( first>=last ) RETURN
8037        x = svfl( (first+last) / 2 )
8038        i = first
8039        j = last
8040        DO
8041            DO while ( svf_lt(svfl(i),x) )
8042               i=i+1
8043            ENDDO
8044            DO while ( svf_lt(x,svfl(j)) )
8045                j=j-1
8046            ENDDO
8047            IF ( i >= j ) EXIT
8048            t = svfl(i);  svfl(i) = svfl(j);  svfl(j) = t
8049            i=i+1
8050            j=j-1
8051        ENDDO
8052        IF ( first < i-1 ) CALL quicksort_svf(svfl, first, i-1)
8053        IF ( j+1 < last )  CALL quicksort_svf(svfl, j+1, last)
8054    END SUBROUTINE quicksort_svf
8055
8056    PURE FUNCTION csf_lt(csf1,csf2) result (res)
8057      TYPE (t_csf), INTENT(in) :: csf1,csf2
8058      LOGICAL                  :: res
8059      IF ( csf1%ip < csf2%ip  .OR.    &
8060           (csf1%ip == csf2%ip  .AND.  csf1%itx < csf2%itx)  .OR.  &
8061           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity < csf2%ity)  .OR.  &
8062           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity == csf2%ity  .AND.   &
8063            csf1%itz < csf2%itz)  .OR.  &
8064           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity == csf2%ity  .AND.   &
8065            csf1%itz == csf2%itz  .AND.  csf1%isurfs < csf2%isurfs) )  THEN
8066          res = .TRUE.
8067      ELSE
8068          res = .FALSE.
8069      ENDIF
8070    END FUNCTION csf_lt
8071
8072
8073!-- quicksort.f -*-f90-*-
8074!-- Author: t-nissie, adaptation J.Resler
8075!-- License: GPLv3
8076!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8077    RECURSIVE SUBROUTINE quicksort_csf(csfl, first, last)
8078        IMPLICIT NONE
8079        TYPE(t_csf), DIMENSION(:), INTENT(INOUT)  :: csfl
8080        INTEGER(iwp), INTENT(IN)                  :: first, last
8081        TYPE(t_csf)                               :: x, t
8082        INTEGER(iwp)                              :: i, j
8083
8084        IF ( first>=last ) RETURN
8085        x = csfl( (first+last)/2 )
8086        i = first
8087        j = last
8088        DO
8089            DO while ( csf_lt(csfl(i),x) )
8090                i=i+1
8091            ENDDO
8092            DO while ( csf_lt(x,csfl(j)) )
8093                j=j-1
8094            ENDDO
8095            IF ( i >= j ) EXIT
8096            t = csfl(i);  csfl(i) = csfl(j);  csfl(j) = t
8097            i=i+1
8098            j=j-1
8099        ENDDO
8100        IF ( first < i-1 ) CALL quicksort_csf(csfl, first, i-1)
8101        IF ( j+1 < last )  CALL quicksort_csf(csfl, j+1, last)
8102    END SUBROUTINE quicksort_csf
8103
8104   
8105    SUBROUTINE merge_and_grow_csf(newsize)
8106        INTEGER(iwp), INTENT(in)                :: newsize  !< new array size after grow, must be >= ncsfl
8107                                                            !< or -1 to shrink to minimum
8108        INTEGER(iwp)                            :: iread, iwrite
8109        TYPE(t_csf), DIMENSION(:), POINTER      :: acsfnew
8110        CHARACTER(100)                          :: msg
8111
8112        IF ( newsize == -1 )  THEN
8113!--         merge in-place
8114            acsfnew => acsf
8115        ELSE
8116!--         allocate new array
8117            IF ( mcsf == 0 )  THEN
8118                ALLOCATE( acsf1(newsize) )
8119                acsfnew => acsf1
8120            ELSE
8121                ALLOCATE( acsf2(newsize) )
8122                acsfnew => acsf2
8123            ENDIF
8124        ENDIF
8125
8126        IF ( ncsfl >= 1 )  THEN
8127!--         sort csf in place (quicksort)
8128            CALL quicksort_csf(acsf,1,ncsfl)
8129
8130!--         while moving to a new array, aggregate canopy sink factor records with identical box & source
8131            acsfnew(1) = acsf(1)
8132            iwrite = 1
8133            DO iread = 2, ncsfl
8134!--             here acsf(kcsf) already has values from acsf(icsf)
8135                IF ( acsfnew(iwrite)%itx == acsf(iread)%itx &
8136                         .AND.  acsfnew(iwrite)%ity == acsf(iread)%ity &
8137                         .AND.  acsfnew(iwrite)%itz == acsf(iread)%itz &
8138                         .AND.  acsfnew(iwrite)%isurfs == acsf(iread)%isurfs )  THEN
8139
8140                    acsfnew(iwrite)%rsvf = acsfnew(iwrite)%rsvf + acsf(iread)%rsvf
8141!--                 advance reading index, keep writing index
8142                ELSE
8143!--                 not identical, just advance and copy
8144                    iwrite = iwrite + 1
8145                    acsfnew(iwrite) = acsf(iread)
8146                ENDIF
8147            ENDDO
8148            ncsfl = iwrite
8149        ENDIF
8150
8151        IF ( newsize == -1 )  THEN
8152!--         allocate new array and copy shrinked data
8153            IF ( mcsf == 0 )  THEN
8154                ALLOCATE( acsf1(ncsfl) )
8155                acsf1(1:ncsfl) = acsf2(1:ncsfl)
8156            ELSE
8157                ALLOCATE( acsf2(ncsfl) )
8158                acsf2(1:ncsfl) = acsf1(1:ncsfl)
8159            ENDIF
8160        ENDIF
8161
8162!--     deallocate old array
8163        IF ( mcsf == 0 )  THEN
8164            mcsf = 1
8165            acsf => acsf1
8166            DEALLOCATE( acsf2 )
8167        ELSE
8168            mcsf = 0
8169            acsf => acsf2
8170            DEALLOCATE( acsf1 )
8171        ENDIF
8172        ncsfla = newsize
8173
8174        WRITE(msg,'(A,2I12)') 'Grow acsf2:',ncsfl,ncsfla
8175        CALL radiation_write_debug_log( msg )
8176
8177    END SUBROUTINE merge_and_grow_csf
8178
8179   
8180!-- quicksort.f -*-f90-*-
8181!-- Author: t-nissie, adaptation J.Resler
8182!-- License: GPLv3
8183!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8184    RECURSIVE SUBROUTINE quicksort_csf2(kpcsflt, pcsflt, first, last)
8185        IMPLICIT NONE
8186        INTEGER(iwp), DIMENSION(:,:), INTENT(INOUT)  :: kpcsflt
8187        REAL(wp), DIMENSION(:,:), INTENT(INOUT)      :: pcsflt
8188        INTEGER(iwp), INTENT(IN)                     :: first, last
8189        REAL(wp), DIMENSION(ndcsf)                   :: t2
8190        INTEGER(iwp), DIMENSION(kdcsf)               :: x, t1
8191        INTEGER(iwp)                                 :: i, j
8192
8193        IF ( first>=last ) RETURN
8194        x = kpcsflt(:, (first+last)/2 )
8195        i = first
8196        j = last
8197        DO
8198            DO while ( csf_lt2(kpcsflt(:,i),x) )
8199                i=i+1
8200            ENDDO
8201            DO while ( csf_lt2(x,kpcsflt(:,j)) )
8202                j=j-1
8203            ENDDO
8204            IF ( i >= j ) EXIT
8205            t1 = kpcsflt(:,i);  kpcsflt(:,i) = kpcsflt(:,j);  kpcsflt(:,j) = t1
8206            t2 = pcsflt(:,i);  pcsflt(:,i) = pcsflt(:,j);  pcsflt(:,j) = t2
8207            i=i+1
8208            j=j-1
8209        ENDDO
8210        IF ( first < i-1 ) CALL quicksort_csf2(kpcsflt, pcsflt, first, i-1)
8211        IF ( j+1 < last )  CALL quicksort_csf2(kpcsflt, pcsflt, j+1, last)
8212    END SUBROUTINE quicksort_csf2
8213   
8214
8215    PURE FUNCTION csf_lt2(item1, item2) result(res)
8216        INTEGER(iwp), DIMENSION(kdcsf), INTENT(in)  :: item1, item2
8217        LOGICAL                                     :: res
8218        res = ( (item1(3) < item2(3))                                                        &
8219             .OR.  (item1(3) == item2(3)  .AND.  item1(2) < item2(2))                            &
8220             .OR.  (item1(3) == item2(3)  .AND.  item1(2) == item2(2)  .AND.  item1(1) < item2(1)) &
8221             .OR.  (item1(3) == item2(3)  .AND.  item1(2) == item2(2)  .AND.  item1(1) == item2(1) &
8222                 .AND.  item1(4) < item2(4)) )
8223    END FUNCTION csf_lt2
8224
8225    PURE FUNCTION searchsorted(athresh, val) result(ind)
8226        REAL(wp), DIMENSION(:), INTENT(IN)  :: athresh
8227        REAL(wp), INTENT(IN)                :: val
8228        INTEGER(iwp)                        :: ind
8229        INTEGER(iwp)                        :: i
8230
8231        DO i = LBOUND(athresh, 1), UBOUND(athresh, 1)
8232            IF ( val < athresh(i) ) THEN
8233                ind = i - 1
8234                RETURN
8235            ENDIF
8236        ENDDO
8237        ind = UBOUND(athresh, 1)
8238    END FUNCTION searchsorted
8239
8240!------------------------------------------------------------------------------!
8241! Description:
8242! ------------
8243!
8244!> radiation_radflux_gridbox subroutine gives the sw and lw radiation fluxes at the
8245!> faces of a gridbox defined at i,j,k and located in the urban layer.
8246!> The total sw and the diffuse sw radiation as well as the lw radiation fluxes at
8247!> the gridbox 6 faces are stored in sw_gridbox, swd_gridbox, and lw_gridbox arrays,
8248!> respectively, in the following order:
8249!>  up_face, down_face, north_face, south_face, east_face, west_face
8250!>
8251!> The subroutine reports also how successful was the search process via the parameter
8252!> i_feedback as follow:
8253!> - i_feedback =  1 : successful
8254!> - i_feedback = -1 : unsuccessful; the requisted point is outside the urban domain
8255!> - i_feedback =  0 : uncomplete; some gridbox faces fluxes are missing
8256!>
8257!>
8258!> It is called outside from usm_urban_surface_mod whenever the radiation fluxes
8259!> are needed.
8260!>
8261!> This routine is not used so far. However, it may serve as an interface for radiation
8262!> fluxes of urban and land surfaces
8263!>
8264!> TODO:
8265!>    - Compare performance when using some combination of the Fortran intrinsic
8266!>      functions, e.g. MINLOC, MAXLOC, ALL, ANY and COUNT functions, which search
8267!>      surfl array for elements meeting user-specified criterion, i.e. i,j,k
8268!>    - Report non-found or incomplete radiation fluxes arrays , if any, at the
8269!>      gridbox faces in an error message form
8270!>
8271!------------------------------------------------------------------------------!
8272    SUBROUTINE radiation_radflux_gridbox(i,j,k,sw_gridbox,swd_gridbox,lw_gridbox,i_feedback)
8273       
8274        IMPLICIT NONE
8275
8276        INTEGER(iwp),                 INTENT(in)  :: i,j,k                 !< gridbox indices at which fluxes are required
8277        INTEGER(iwp)                              :: ii,jj,kk,d            !< surface indices and type
8278        INTEGER(iwp)                              :: l                     !< surface id
8279        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
8280        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
8281        INTEGER(iwp),                 INTENT(out) :: i_feedback            !< feedback to report how the search was successful
8282
8283
8284!-- initialize variables
8285        i_feedback  = -999999
8286        sw_gridbox  = -999999.9_wp
8287        lw_gridbox  = -999999.9_wp
8288        swd_gridbox = -999999.9_wp
8289       
8290!-- check the requisted grid indices
8291        IF ( k < nzb   .OR.  k > nzut  .OR.   &
8292             j < nysg  .OR.  j > nyng  .OR.   &
8293             i < nxlg  .OR.  i > nxrg         &
8294             ) THEN
8295           i_feedback = -1
8296           RETURN
8297        ENDIF
8298
8299!-- search for the required grid and formulate the fluxes at the 6 gridbox faces
8300        DO l = 1, nsurfl
8301            ii = surfl(ix,l)
8302            jj = surfl(iy,l)
8303            kk = surfl(iz,l)
8304
8305            IF ( ii == i  .AND.  jj == j  .AND.  kk == k ) THEN
8306               d = surfl(id,l)
8307
8308               SELECT CASE ( d )
8309
8310               CASE (iup_u,iup_l)                          !- gridbox up_facing face
8311                  sw_gridbox(1) = surfinsw(l)
8312                  lw_gridbox(1) = surfinlw(l)
8313                  swd_gridbox(1) = surfinswdif(l)
8314
8315               CASE (inorth_u,inorth_l)                    !- gridbox north_facing face
8316                  sw_gridbox(3) = surfinsw(l)
8317                  lw_gridbox(3) = surfinlw(l)
8318                  swd_gridbox(3) = surfinswdif(l)
8319
8320               CASE (isouth_u,isouth_l)                    !- gridbox south_facing face
8321                  sw_gridbox(4) = surfinsw(l)
8322                  lw_gridbox(4) = surfinlw(l)
8323                  swd_gridbox(4) = surfinswdif(l)
8324
8325               CASE (ieast_u,ieast_l)                      !- gridbox east_facing face
8326                  sw_gridbox(5) = surfinsw(l)
8327                  lw_gridbox(5) = surfinlw(l)
8328                  swd_gridbox(5) = surfinswdif(l)
8329
8330               CASE (iwest_u,iwest_l)                      !- gridbox west_facing face
8331                  sw_gridbox(6) = surfinsw(l)
8332                  lw_gridbox(6) = surfinlw(l)
8333                  swd_gridbox(6) = surfinswdif(l)
8334
8335               END SELECT
8336
8337            ENDIF
8338
8339        IF ( ALL( sw_gridbox(:)  /= -999999.9_wp )  ) EXIT
8340        ENDDO
8341
8342!-- check the completeness of the fluxes at all gidbox faces       
8343!-- TODO: report non-found or incomplete rad fluxes arrays in an error message form
8344        IF ( ANY( sw_gridbox(:)  <= -999999.9_wp )  .OR.   &
8345             ANY( swd_gridbox(:) <= -999999.9_wp )  .OR.   &
8346             ANY( lw_gridbox(:)  <= -999999.9_wp ) ) THEN
8347           i_feedback = 0
8348        ELSE
8349           i_feedback = 1
8350        ENDIF
8351       
8352        RETURN
8353       
8354    END SUBROUTINE radiation_radflux_gridbox
8355
8356!------------------------------------------------------------------------------!
8357!
8358! Description:
8359! ------------
8360!> Subroutine for averaging 3D data
8361!------------------------------------------------------------------------------!
8362SUBROUTINE radiation_3d_data_averaging( mode, variable )
8363 
8364
8365    USE control_parameters
8366
8367    USE indices
8368
8369    USE kinds
8370
8371    IMPLICIT NONE
8372
8373    CHARACTER (LEN=*) ::  mode    !<
8374    CHARACTER (LEN=*) :: variable !<
8375
8376    LOGICAL      ::  match_lsm !< flag indicating natural-type surface
8377    LOGICAL      ::  match_usm !< flag indicating urban-type surface
8378   
8379    INTEGER(iwp) ::  i !<
8380    INTEGER(iwp) ::  j !<
8381    INTEGER(iwp) ::  k !<
8382    INTEGER(iwp) ::  l, m !< index of current surface element
8383
8384    IF ( mode == 'allocate' )  THEN
8385
8386       SELECT CASE ( TRIM( variable ) )
8387
8388             CASE ( 'rad_net*' )
8389                IF ( .NOT. ALLOCATED( rad_net_av ) )  THEN
8390                   ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
8391                ENDIF
8392                rad_net_av = 0.0_wp
8393             
8394             CASE ( 'rad_lw_in*' )
8395                IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) )  THEN
8396                   ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
8397                ENDIF
8398                rad_lw_in_xy_av = 0.0_wp
8399               
8400             CASE ( 'rad_lw_out*' )
8401                IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) )  THEN
8402                   ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
8403                ENDIF
8404                rad_lw_out_xy_av = 0.0_wp
8405               
8406             CASE ( 'rad_sw_in*' )
8407                IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) )  THEN
8408                   ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
8409                ENDIF
8410                rad_sw_in_xy_av = 0.0_wp
8411               
8412             CASE ( 'rad_sw_out*' )
8413                IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) )  THEN
8414                   ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
8415                ENDIF
8416                rad_sw_out_xy_av = 0.0_wp               
8417
8418             CASE ( 'rad_lw_in' )
8419                IF ( .NOT. ALLOCATED( rad_lw_in_av ) )  THEN
8420                   ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8421                ENDIF
8422                rad_lw_in_av = 0.0_wp
8423
8424             CASE ( 'rad_lw_out' )
8425                IF ( .NOT. ALLOCATED( rad_lw_out_av ) )  THEN
8426                   ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8427                ENDIF
8428                rad_lw_out_av = 0.0_wp
8429
8430             CASE ( 'rad_lw_cs_hr' )
8431                IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) )  THEN
8432                   ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8433                ENDIF
8434                rad_lw_cs_hr_av = 0.0_wp
8435
8436             CASE ( 'rad_lw_hr' )
8437                IF ( .NOT. ALLOCATED( rad_lw_hr_av ) )  THEN
8438                   ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8439                ENDIF
8440                rad_lw_hr_av = 0.0_wp
8441
8442             CASE ( 'rad_sw_in' )
8443                IF ( .NOT. ALLOCATED( rad_sw_in_av ) )  THEN
8444                   ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8445                ENDIF
8446                rad_sw_in_av = 0.0_wp
8447
8448             CASE ( 'rad_sw_out' )
8449                IF ( .NOT. ALLOCATED( rad_sw_out_av ) )  THEN
8450                   ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8451                ENDIF
8452                rad_sw_out_av = 0.0_wp
8453
8454             CASE ( 'rad_sw_cs_hr' )
8455                IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) )  THEN
8456                   ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8457                ENDIF
8458                rad_sw_cs_hr_av = 0.0_wp
8459
8460             CASE ( 'rad_sw_hr' )
8461                IF ( .NOT. ALLOCATED( rad_sw_hr_av ) )  THEN
8462                   ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8463                ENDIF
8464                rad_sw_hr_av = 0.0_wp
8465
8466             CASE ( 'rad_mrt_sw' )
8467                IF ( .NOT. ALLOCATED( mrtinsw_av ) )  THEN
8468                   ALLOCATE( mrtinsw_av(nmrtbl) )
8469                ENDIF
8470                mrtinsw_av = 0.0_wp
8471
8472             CASE ( 'rad_mrt_lw' )
8473                IF ( .NOT. ALLOCATED( mrtinlw_av ) )  THEN
8474                   ALLOCATE( mrtinlw_av(nmrtbl) )
8475                ENDIF
8476                mrtinlw_av = 0.0_wp
8477
8478             CASE ( 'rad_mrt' )
8479                IF ( .NOT. ALLOCATED( mrt_av ) )  THEN
8480                   ALLOCATE( mrt_av(nmrtbl) )
8481                ENDIF
8482                mrt_av = 0.0_wp
8483
8484          CASE DEFAULT
8485             CONTINUE
8486
8487       END SELECT
8488
8489    ELSEIF ( mode == 'sum' )  THEN
8490
8491       SELECT CASE ( TRIM( variable ) )
8492
8493          CASE ( 'rad_net*' )
8494             IF ( ALLOCATED( rad_net_av ) ) THEN
8495                DO  i = nxl, nxr
8496                   DO  j = nys, nyn
8497                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
8498                                  surf_lsm_h%end_index(j,i)
8499                      match_usm = surf_usm_h%start_index(j,i) <=               &
8500                                  surf_usm_h%end_index(j,i)
8501
8502                     IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
8503                         m = surf_lsm_h%end_index(j,i)
8504                         rad_net_av(j,i) = rad_net_av(j,i) +                   &
8505                                         surf_lsm_h%rad_net(m)
8506                      ELSEIF ( match_usm )  THEN
8507                         m = surf_usm_h%end_index(j,i)
8508                         rad_net_av(j,i) = rad_net_av(j,i) +                   &
8509                                         surf_usm_h%rad_net(m)
8510                      ENDIF
8511                   ENDDO
8512                ENDDO
8513             ENDIF
8514
8515          CASE ( 'rad_lw_in*' )
8516             IF ( ALLOCATED( rad_lw_in_xy_av ) ) THEN
8517                DO  i = nxl, nxr
8518                   DO  j = nys, nyn
8519                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
8520                                  surf_lsm_h%end_index(j,i)
8521                      match_usm = surf_usm_h%start_index(j,i) <=               &
8522                                  surf_usm_h%end_index(j,i)
8523
8524                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
8525                         m = surf_lsm_h%end_index(j,i)
8526                         rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i) +         &
8527                                         surf_lsm_h%rad_lw_in(m)
8528                      ELSEIF ( match_usm )  THEN
8529                         m = surf_usm_h%end_index(j,i)
8530                         rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i) +         &
8531                                         surf_usm_h%rad_lw_in(m)
8532                      ENDIF
8533                   ENDDO
8534                ENDDO
8535             ENDIF
8536             
8537          CASE ( 'rad_lw_out*' )
8538             IF ( ALLOCATED( rad_lw_out_xy_av ) ) THEN
8539                DO  i = nxl, nxr
8540                   DO  j = nys, nyn
8541                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
8542                                  surf_lsm_h%end_index(j,i)
8543                      match_usm = surf_usm_h%start_index(j,i) <=               &
8544                                  surf_usm_h%end_index(j,i)
8545
8546                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
8547                         m = surf_lsm_h%end_index(j,i)
8548                         rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i) +       &
8549                                                 surf_lsm_h%rad_lw_out(m)
8550                      ELSEIF ( match_usm )  THEN
8551                         m = surf_usm_h%end_index(j,i)
8552                         rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i) +       &
8553                                                 surf_usm_h%rad_lw_out(m)
8554                      ENDIF
8555                   ENDDO
8556                ENDDO
8557             ENDIF
8558             
8559          CASE ( 'rad_sw_in*' )
8560             IF ( ALLOCATED( rad_sw_in_xy_av ) ) THEN
8561                DO  i = nxl, nxr
8562                   DO  j = nys, nyn
8563                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
8564                                  surf_lsm_h%end_index(j,i)
8565                      match_usm = surf_usm_h%start_index(j,i) <=               &
8566                                  surf_usm_h%end_index(j,i)
8567
8568                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
8569                         m = surf_lsm_h%end_index(j,i)
8570                         rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i) +         &
8571                                                surf_lsm_h%rad_sw_in(m)
8572                      ELSEIF ( match_usm )  THEN
8573                         m = surf_usm_h%end_index(j,i)
8574                         rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i) +         &
8575                                                surf_usm_h%rad_sw_in(m)
8576                      ENDIF
8577                   ENDDO
8578                ENDDO
8579             ENDIF
8580             
8581          CASE ( 'rad_sw_out*' )
8582             IF ( ALLOCATED( rad_sw_out_xy_av ) ) THEN
8583                DO  i = nxl, nxr
8584                   DO  j = nys, nyn
8585                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
8586                                  surf_lsm_h%end_index(j,i)
8587                      match_usm = surf_usm_h%start_index(j,i) <=               &
8588                                  surf_usm_h%end_index(j,i)
8589
8590                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
8591                         m = surf_lsm_h%end_index(j,i)
8592                         rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i) +       &
8593                                                 surf_lsm_h%rad_sw_out(m)
8594                      ELSEIF ( match_usm )  THEN
8595                         m = surf_usm_h%end_index(j,i)
8596                         rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i) +       &
8597                                                 surf_usm_h%rad_sw_out(m)
8598                      ENDIF
8599                   ENDDO
8600                ENDDO
8601             ENDIF
8602             
8603          CASE ( 'rad_lw_in' )
8604             IF ( ALLOCATED( rad_lw_in_av ) ) THEN
8605                DO  i = nxlg, nxrg
8606                   DO  j = nysg, nyng
8607                      DO  k = nzb, nzt+1
8608                         rad_lw_in_av(k,j,i) = rad_lw_in_av(k,j,i)             &
8609                                               + rad_lw_in(k,j,i)
8610                      ENDDO
8611                   ENDDO
8612                ENDDO
8613             ENDIF
8614
8615          CASE ( 'rad_lw_out' )
8616             IF ( ALLOCATED( rad_lw_out_av ) ) THEN
8617                DO  i = nxlg, nxrg
8618                   DO  j = nysg, nyng
8619                      DO  k = nzb, nzt+1
8620                         rad_lw_out_av(k,j,i) = rad_lw_out_av(k,j,i)           &
8621                                                + rad_lw_out(k,j,i)
8622                      ENDDO
8623                   ENDDO
8624                ENDDO
8625             ENDIF
8626
8627          CASE ( 'rad_lw_cs_hr' )
8628             IF ( ALLOCATED( rad_lw_cs_hr_av ) ) THEN
8629                DO  i = nxlg, nxrg
8630                   DO  j = nysg, nyng
8631                      DO  k = nzb, nzt+1
8632                         rad_lw_cs_hr_av(k,j,i) = rad_lw_cs_hr_av(k,j,i)       &
8633                                                  + rad_lw_cs_hr(k,j,i)
8634                      ENDDO
8635                   ENDDO
8636                ENDDO
8637             ENDIF
8638
8639          CASE ( 'rad_lw_hr' )
8640             IF ( ALLOCATED( rad_lw_hr_av ) ) THEN
8641                DO  i = nxlg, nxrg
8642                   DO  j = nysg, nyng
8643                      DO  k = nzb, nzt+1
8644                         rad_lw_hr_av(k,j,i) = rad_lw_hr_av(k,j,i)             &
8645                                               + rad_lw_hr(k,j,i)
8646                      ENDDO
8647                   ENDDO
8648                ENDDO
8649             ENDIF
8650
8651          CASE ( 'rad_sw_in' )
8652             IF ( ALLOCATED( rad_sw_in_av ) ) THEN
8653                DO  i = nxlg, nxrg
8654                   DO  j = nysg, nyng
8655                      DO  k = nzb, nzt+1
8656                         rad_sw_in_av(k,j,i) = rad_sw_in_av(k,j,i)             &
8657                                               + rad_sw_in(k,j,i)
8658                      ENDDO
8659                   ENDDO
8660                ENDDO
8661             ENDIF
8662
8663          CASE ( 'rad_sw_out' )
8664             IF ( ALLOCATED( rad_sw_out_av ) ) THEN
8665                DO  i = nxlg, nxrg
8666                   DO  j = nysg, nyng
8667                      DO  k = nzb, nzt+1
8668                         rad_sw_out_av(k,j,i) = rad_sw_out_av(k,j,i)           &
8669                                                + rad_sw_out(k,j,i)
8670                      ENDDO
8671                   ENDDO
8672                ENDDO
8673             ENDIF
8674
8675          CASE ( 'rad_sw_cs_hr' )
8676             IF ( ALLOCATED( rad_sw_cs_hr_av ) ) THEN
8677                DO  i = nxlg, nxrg
8678                   DO  j = nysg, nyng
8679                      DO  k = nzb, nzt+1
8680                         rad_sw_cs_hr_av(k,j,i) = rad_sw_cs_hr_av(k,j,i)       &
8681                                                  + rad_sw_cs_hr(k,j,i)
8682                      ENDDO
8683                   ENDDO
8684                ENDDO
8685             ENDIF
8686
8687          CASE ( 'rad_sw_hr' )
8688             IF ( ALLOCATED( rad_sw_hr_av ) ) THEN
8689                DO  i = nxlg, nxrg
8690                   DO  j = nysg, nyng
8691                      DO  k = nzb, nzt+1
8692                         rad_sw_hr_av(k,j,i) = rad_sw_hr_av(k,j,i)             &
8693                                               + rad_sw_hr(k,j,i)
8694                      ENDDO
8695                   ENDDO
8696                ENDDO
8697             ENDIF
8698
8699          CASE ( 'rad_mrt_sw' )
8700             IF ( ALLOCATED( mrtinsw_av ) )  THEN
8701                mrtinsw_av(:) = mrtinsw_av(:) + mrtinsw(:)
8702             ENDIF
8703
8704          CASE ( 'rad_mrt_lw' )
8705             IF ( ALLOCATED( mrtinlw_av ) )  THEN
8706                mrtinlw_av(:) = mrtinlw_av(:) + mrtinlw(:)
8707             ENDIF
8708
8709          CASE ( 'rad_mrt' )
8710             IF ( ALLOCATED( mrt_av ) )  THEN
8711                mrt_av(:) = mrt_av(:) + mrt(:)
8712             ENDIF
8713
8714          CASE DEFAULT
8715             CONTINUE
8716
8717       END SELECT
8718
8719    ELSEIF ( mode == 'average' )  THEN
8720
8721       SELECT CASE ( TRIM( variable ) )
8722
8723          CASE ( 'rad_net*' )
8724             IF ( ALLOCATED( rad_net_av ) ) THEN
8725                DO  i = nxlg, nxrg
8726                   DO  j = nysg, nyng
8727                      rad_net_av(j,i) = rad_net_av(j,i)                        &
8728                                        / REAL( average_count_3d, KIND=wp )
8729                   ENDDO
8730                ENDDO
8731             ENDIF
8732             
8733          CASE ( 'rad_lw_in*' )
8734             IF ( ALLOCATED( rad_lw_in_xy_av ) ) THEN
8735                DO  i = nxlg, nxrg
8736                   DO  j = nysg, nyng
8737                      rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i)              &
8738                                        / REAL( average_count_3d, KIND=wp )
8739                   ENDDO
8740                ENDDO
8741             ENDIF
8742             
8743          CASE ( 'rad_lw_out*' )
8744             IF ( ALLOCATED( rad_lw_out_xy_av ) ) THEN
8745                DO  i = nxlg, nxrg
8746                   DO  j = nysg, nyng
8747                      rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i)            &
8748                                        / REAL( average_count_3d, KIND=wp )
8749                   ENDDO
8750                ENDDO
8751             ENDIF
8752             
8753          CASE ( 'rad_sw_in*' )
8754             IF ( ALLOCATED( rad_sw_in_xy_av ) ) THEN
8755                DO  i = nxlg, nxrg
8756                   DO  j = nysg, nyng
8757                      rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i)              &
8758                                        / REAL( average_count_3d, KIND=wp )
8759                   ENDDO
8760                ENDDO
8761             ENDIF
8762             
8763          CASE ( 'rad_sw_out*' )
8764             IF ( ALLOCATED( rad_sw_out_xy_av ) ) THEN
8765                DO  i = nxlg, nxrg
8766                   DO  j = nysg, nyng
8767                      rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i)             &
8768                                        / REAL( average_count_3d, KIND=wp )
8769                   ENDDO
8770                ENDDO
8771             ENDIF
8772
8773          CASE ( 'rad_lw_in' )
8774             IF ( ALLOCATED( rad_lw_in_av ) ) THEN
8775                DO  i = nxlg, nxrg
8776                   DO  j = nysg, nyng
8777                      DO  k = nzb, nzt+1
8778                         rad_lw_in_av(k,j,i) = rad_lw_in_av(k,j,i)             &
8779                                               / REAL( average_count_3d, KIND=wp )
8780                      ENDDO
8781                   ENDDO
8782                ENDDO
8783             ENDIF
8784
8785          CASE ( 'rad_lw_out' )
8786             IF ( ALLOCATED( rad_lw_out_av ) ) THEN
8787                DO  i = nxlg, nxrg
8788                   DO  j = nysg, nyng
8789                      DO  k = nzb, nzt+1
8790                         rad_lw_out_av(k,j,i) = rad_lw_out_av(k,j,i)           &
8791                                                / REAL( average_count_3d, KIND=wp )
8792                      ENDDO
8793                   ENDDO
8794                ENDDO
8795             ENDIF
8796
8797          CASE ( 'rad_lw_cs_hr' )
8798             IF ( ALLOCATED( rad_lw_cs_hr_av ) ) THEN
8799                DO  i = nxlg, nxrg
8800                   DO  j = nysg, nyng
8801                      DO  k = nzb, nzt+1
8802                         rad_lw_cs_hr_av(k,j,i) = rad_lw_cs_hr_av(k,j,i)       &
8803                                                / REAL( average_count_3d, KIND=wp )
8804                      ENDDO
8805                   ENDDO
8806                ENDDO
8807             ENDIF
8808
8809          CASE ( 'rad_lw_hr' )
8810             IF ( ALLOCATED( rad_lw_hr_av ) ) THEN
8811                DO  i = nxlg, nxrg
8812                   DO  j = nysg, nyng
8813                      DO  k = nzb, nzt+1
8814                         rad_lw_hr_av(k,j,i) = rad_lw_hr_av(k,j,i)             &
8815                                               / REAL( average_count_3d, KIND=wp )
8816                      ENDDO
8817                   ENDDO
8818                ENDDO
8819             ENDIF
8820
8821          CASE ( 'rad_sw_in' )
8822             IF ( ALLOCATED( rad_sw_in_av ) ) THEN
8823                DO  i = nxlg, nxrg
8824                   DO  j = nysg, nyng
8825                      DO  k = nzb, nzt+1
8826                         rad_sw_in_av(k,j,i) = rad_sw_in_av(k,j,i)             &
8827                                               / REAL( average_count_3d, KIND=wp )
8828                      ENDDO
8829                   ENDDO
8830                ENDDO
8831             ENDIF
8832
8833          CASE ( 'rad_sw_out' )
8834             IF ( ALLOCATED( rad_sw_out_av ) ) THEN
8835                DO  i = nxlg, nxrg
8836                   DO  j = nysg, nyng
8837                      DO  k = nzb, nzt+1
8838                         rad_sw_out_av(k,j,i) = rad_sw_out_av(k,j,i)           &
8839                                                / REAL( average_count_3d, KIND=wp )
8840                      ENDDO
8841                   ENDDO
8842                ENDDO
8843             ENDIF
8844
8845          CASE ( 'rad_sw_cs_hr' )
8846             IF ( ALLOCATED( rad_sw_cs_hr_av ) ) THEN
8847                DO  i = nxlg, nxrg
8848                   DO  j = nysg, nyng
8849                      DO  k = nzb, nzt+1
8850                         rad_sw_cs_hr_av(k,j,i) = rad_sw_cs_hr_av(k,j,i)       &
8851                                                / REAL( average_count_3d, KIND=wp )
8852                      ENDDO
8853                   ENDDO
8854                ENDDO
8855             ENDIF
8856
8857          CASE ( 'rad_sw_hr' )
8858             IF ( ALLOCATED( rad_sw_hr_av ) ) THEN
8859                DO  i = nxlg, nxrg
8860                   DO  j = nysg, nyng
8861                      DO  k = nzb, nzt+1
8862                         rad_sw_hr_av(k,j,i) = rad_sw_hr_av(k,j,i)             &
8863                                               / REAL( average_count_3d, KIND=wp )
8864                      ENDDO
8865                   ENDDO
8866                ENDDO
8867             ENDIF
8868
8869          CASE ( 'rad_mrt_sw' )
8870             IF ( ALLOCATED( mrtinsw_av ) )  THEN
8871                mrtinsw_av(:) = mrtinsw_av(:)  / REAL( average_count_3d, KIND=wp )
8872             ENDIF
8873
8874          CASE ( 'rad_mrt_lw' )
8875             IF ( ALLOCATED( mrtinlw_av ) )  THEN
8876                mrtinlw_av(:) = mrtinlw_av(:) / REAL( average_count_3d, KIND=wp )
8877             ENDIF
8878
8879          CASE ( 'rad_mrt' )
8880             IF ( ALLOCATED( mrt_av ) )  THEN
8881                mrt_av(:) = mrt_av(:) / REAL( average_count_3d, KIND=wp )
8882             ENDIF
8883
8884       END SELECT
8885
8886    ENDIF
8887
8888END SUBROUTINE radiation_3d_data_averaging
8889
8890
8891!------------------------------------------------------------------------------!
8892!
8893! Description:
8894! ------------
8895!> Subroutine defining appropriate grid for netcdf variables.
8896!> It is called out from subroutine netcdf.
8897!------------------------------------------------------------------------------!
8898SUBROUTINE radiation_define_netcdf_grid( var, found, grid_x, grid_y, grid_z )
8899   
8900    IMPLICIT NONE
8901
8902    CHARACTER (LEN=*), INTENT(IN)  ::  var         !<
8903    LOGICAL, INTENT(OUT)           ::  found       !<
8904    CHARACTER (LEN=*), INTENT(OUT) ::  grid_x      !<
8905    CHARACTER (LEN=*), INTENT(OUT) ::  grid_y      !<
8906    CHARACTER (LEN=*), INTENT(OUT) ::  grid_z      !<
8907
8908    found  = .TRUE.
8909
8910!
8911!-- Check for the grid
8912    SELECT CASE ( TRIM( var ) )
8913
8914       CASE ( 'rad_lw_cs_hr', 'rad_lw_hr', 'rad_sw_cs_hr', 'rad_sw_hr',        &
8915              'rad_lw_cs_hr_xy', 'rad_lw_hr_xy', 'rad_sw_cs_hr_xy',            &
8916              'rad_sw_hr_xy', 'rad_lw_cs_hr_xz', 'rad_lw_hr_xz',               &
8917              'rad_sw_cs_hr_xz', 'rad_sw_hr_xz', 'rad_lw_cs_hr_yz',            &
8918              'rad_lw_hr_yz', 'rad_sw_cs_hr_yz', 'rad_sw_hr_yz',               &
8919              'rad_mrt', 'rad_mrt_sw', 'rad_mrt_lw' )
8920          grid_x = 'x'
8921          grid_y = 'y'
8922          grid_z = 'zu'
8923
8924       CASE ( 'rad_lw_in', 'rad_lw_out', 'rad_sw_in', 'rad_sw_out',            &
8925              'rad_lw_in_xy', 'rad_lw_out_xy', 'rad_sw_in_xy','rad_sw_out_xy', &
8926              'rad_lw_in_xz', 'rad_lw_out_xz', 'rad_sw_in_xz','rad_sw_out_xz', &
8927              'rad_lw_in_yz', 'rad_lw_out_yz', 'rad_sw_in_yz','rad_sw_out_yz' )
8928          grid_x = 'x'
8929          grid_y = 'y'
8930          grid_z = 'zw'
8931
8932
8933       CASE DEFAULT
8934          found  = .FALSE.
8935          grid_x = 'none'
8936          grid_y = 'none'
8937          grid_z = 'none'
8938
8939        END SELECT
8940
8941    END SUBROUTINE radiation_define_netcdf_grid
8942
8943!------------------------------------------------------------------------------!
8944!
8945! Description:
8946! ------------
8947!> Subroutine defining 2D output variables
8948!------------------------------------------------------------------------------!
8949 SUBROUTINE radiation_data_output_2d( av, variable, found, grid, mode,         &
8950                                      local_pf, two_d, nzb_do, nzt_do )
8951 
8952    USE indices
8953
8954    USE kinds
8955
8956
8957    IMPLICIT NONE
8958
8959    CHARACTER (LEN=*) ::  grid     !<
8960    CHARACTER (LEN=*) ::  mode     !<
8961    CHARACTER (LEN=*) ::  variable !<
8962
8963    INTEGER(iwp) ::  av !<
8964    INTEGER(iwp) ::  i  !<
8965    INTEGER(iwp) ::  j  !<
8966    INTEGER(iwp) ::  k  !<
8967    INTEGER(iwp) ::  m  !< index of surface element at grid point (j,i)
8968    INTEGER(iwp) ::  nzb_do   !<
8969    INTEGER(iwp) ::  nzt_do   !<
8970
8971    LOGICAL      ::  found !<
8972    LOGICAL      ::  two_d !< flag parameter that indicates 2D variables (horizontal cross sections)
8973
8974    REAL(wp) ::  fill_value = -999.0_wp    !< value for the _FillValue attribute
8975
8976    REAL(wp), DIMENSION(nxl:nxr,nys:nyn,nzb_do:nzt_do) ::  local_pf !<
8977
8978    found = .TRUE.
8979
8980    SELECT CASE ( TRIM( variable ) )
8981
8982       CASE ( 'rad_net*_xy' )        ! 2d-array
8983          IF ( av == 0 ) THEN
8984             DO  i = nxl, nxr
8985                DO  j = nys, nyn
8986!
8987!--                Obtain rad_net from its respective surface type
8988!--                Natural-type surfaces
8989                   DO  m = surf_lsm_h%start_index(j,i),                        &
8990                           surf_lsm_h%end_index(j,i) 
8991                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_net(m)
8992                   ENDDO
8993!
8994!--                Urban-type surfaces
8995                   DO  m = surf_usm_h%start_index(j,i),                        &
8996                           surf_usm_h%end_index(j,i) 
8997                      local_pf(i,j,nzb+1) = surf_usm_h%rad_net(m)
8998                   ENDDO
8999                ENDDO
9000             ENDDO
9001          ELSE
9002             IF ( .NOT. ALLOCATED( rad_net_av ) ) THEN
9003                ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
9004                rad_net_av = REAL( fill_value, KIND = wp )
9005             ENDIF
9006             DO  i = nxl, nxr
9007                DO  j = nys, nyn 
9008                   local_pf(i,j,nzb+1) = rad_net_av(j,i)
9009                ENDDO
9010             ENDDO
9011          ENDIF
9012          two_d = .TRUE.
9013          grid = 'zu1'
9014         
9015       CASE ( 'rad_lw_in*_xy' )        ! 2d-array
9016          IF ( av == 0 ) THEN
9017             DO  i = nxl, nxr
9018                DO  j = nys, nyn
9019!
9020!--                Obtain rad_net from its respective surface type
9021!--                Natural-type surfaces
9022                   DO  m = surf_lsm_h%start_index(j,i),                        &
9023                           surf_lsm_h%end_index(j,i) 
9024                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_lw_in(m)
9025                   ENDDO
9026!
9027!--                Urban-type surfaces
9028                   DO  m = surf_usm_h%start_index(j,i),                        &
9029                           surf_usm_h%end_index(j,i) 
9030                      local_pf(i,j,nzb+1) = surf_usm_h%rad_lw_in(m)
9031                   ENDDO
9032                ENDDO
9033             ENDDO
9034          ELSE
9035             IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) ) THEN
9036                ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
9037                rad_lw_in_xy_av = REAL( fill_value, KIND = wp )
9038             ENDIF
9039             DO  i = nxl, nxr
9040                DO  j = nys, nyn 
9041                   local_pf(i,j,nzb+1) = rad_lw_in_xy_av(j,i)
9042                ENDDO
9043             ENDDO
9044          ENDIF
9045          two_d = .TRUE.
9046          grid = 'zu1'
9047         
9048       CASE ( 'rad_lw_out*_xy' )        ! 2d-array
9049          IF ( av == 0 ) THEN
9050             DO  i = nxl, nxr
9051                DO  j = nys, nyn
9052!
9053!--                Obtain rad_net from its respective surface type
9054!--                Natural-type surfaces
9055                   DO  m = surf_lsm_h%start_index(j,i),                        &
9056                           surf_lsm_h%end_index(j,i) 
9057                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_lw_out(m)
9058                   ENDDO
9059!
9060!--                Urban-type surfaces
9061                   DO  m = surf_usm_h%start_index(j,i),                        &
9062                           surf_usm_h%end_index(j,i) 
9063                      local_pf(i,j,nzb+1) = surf_usm_h%rad_lw_out(m)
9064                   ENDDO
9065                ENDDO
9066             ENDDO
9067          ELSE
9068             IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) ) THEN
9069                ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
9070                rad_lw_out_xy_av = REAL( fill_value, KIND = wp )
9071             ENDIF
9072             DO  i = nxl, nxr
9073                DO  j = nys, nyn 
9074                   local_pf(i,j,nzb+1) = rad_lw_out_xy_av(j,i)
9075                ENDDO
9076             ENDDO
9077          ENDIF
9078          two_d = .TRUE.
9079          grid = 'zu1'
9080         
9081       CASE ( 'rad_sw_in*_xy' )        ! 2d-array
9082          IF ( av == 0 ) THEN
9083             DO  i = nxl, nxr
9084                DO  j = nys, nyn
9085!
9086!--                Obtain rad_net from its respective surface type
9087!--                Natural-type surfaces
9088                   DO  m = surf_lsm_h%start_index(j,i),                        &
9089                           surf_lsm_h%end_index(j,i) 
9090                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_sw_in(m)
9091                   ENDDO
9092!
9093!--                Urban-type surfaces
9094                   DO  m = surf_usm_h%start_index(j,i),                        &
9095                           surf_usm_h%end_index(j,i) 
9096                      local_pf(i,j,nzb+1) = surf_usm_h%rad_sw_in(m)
9097                   ENDDO
9098                ENDDO
9099             ENDDO
9100          ELSE
9101             IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) ) THEN
9102                ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
9103                rad_sw_in_xy_av = REAL( fill_value, KIND = wp )
9104             ENDIF
9105             DO  i = nxl, nxr
9106                DO  j = nys, nyn 
9107                   local_pf(i,j,nzb+1) = rad_sw_in_xy_av(j,i)
9108                ENDDO
9109             ENDDO
9110          ENDIF
9111          two_d = .TRUE.
9112          grid = 'zu1'
9113         
9114       CASE ( 'rad_sw_out*_xy' )        ! 2d-array
9115          IF ( av == 0 ) THEN
9116             DO  i = nxl, nxr
9117                DO  j = nys, nyn
9118!
9119!--                Obtain rad_net from its respective surface type
9120!--                Natural-type surfaces
9121                   DO  m = surf_lsm_h%start_index(j,i),                        &
9122                           surf_lsm_h%end_index(j,i) 
9123                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_sw_out(m)
9124                   ENDDO
9125!
9126!--                Urban-type surfaces
9127                   DO  m = surf_usm_h%start_index(j,i),                        &
9128                           surf_usm_h%end_index(j,i) 
9129                      local_pf(i,j,nzb+1) = surf_usm_h%rad_sw_out(m)
9130                   ENDDO
9131                ENDDO
9132             ENDDO
9133          ELSE
9134             IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) ) THEN
9135                ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
9136                rad_sw_out_xy_av = REAL( fill_value, KIND = wp )
9137             ENDIF
9138             DO  i = nxl, nxr
9139                DO  j = nys, nyn 
9140                   local_pf(i,j,nzb+1) = rad_sw_out_xy_av(j,i)
9141                ENDDO
9142             ENDDO
9143          ENDIF
9144          two_d = .TRUE.
9145          grid = 'zu1'         
9146         
9147       CASE ( 'rad_lw_in_xy', 'rad_lw_in_xz', 'rad_lw_in_yz' )
9148          IF ( av == 0 ) THEN
9149             DO  i = nxl, nxr
9150                DO  j = nys, nyn
9151                   DO  k = nzb_do, nzt_do
9152                      local_pf(i,j,k) = rad_lw_in(k,j,i)
9153                   ENDDO
9154                ENDDO
9155             ENDDO
9156          ELSE
9157            IF ( .NOT. ALLOCATED( rad_lw_in_av ) ) THEN
9158               ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9159               rad_lw_in_av = REAL( fill_value, KIND = wp )
9160            ENDIF
9161             DO  i = nxl, nxr
9162                DO  j = nys, nyn 
9163                   DO  k = nzb_do, nzt_do
9164                      local_pf(i,j,k) = rad_lw_in_av(k,j,i)
9165                   ENDDO
9166                ENDDO
9167             ENDDO
9168          ENDIF
9169          IF ( mode == 'xy' )  grid = 'zu'
9170
9171       CASE ( 'rad_lw_out_xy', 'rad_lw_out_xz', 'rad_lw_out_yz' )
9172          IF ( av == 0 ) THEN
9173             DO  i = nxl, nxr
9174                DO  j = nys, nyn
9175                   DO  k = nzb_do, nzt_do
9176                      local_pf(i,j,k) = rad_lw_out(k,j,i)
9177                   ENDDO
9178                ENDDO
9179             ENDDO
9180          ELSE
9181            IF ( .NOT. ALLOCATED( rad_lw_out_av ) ) THEN
9182               ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9183               rad_lw_out_av = REAL( fill_value, KIND = wp )
9184            ENDIF
9185             DO  i = nxl, nxr
9186                DO  j = nys, nyn 
9187                   DO  k = nzb_do, nzt_do
9188                      local_pf(i,j,k) = rad_lw_out_av(k,j,i)
9189                   ENDDO
9190                ENDDO
9191             ENDDO
9192          ENDIF   
9193          IF ( mode == 'xy' )  grid = 'zu'
9194
9195       CASE ( 'rad_lw_cs_hr_xy', 'rad_lw_cs_hr_xz', 'rad_lw_cs_hr_yz' )
9196          IF ( av == 0 ) THEN
9197             DO  i = nxl, nxr
9198                DO  j = nys, nyn
9199                   DO  k = nzb_do, nzt_do
9200                      local_pf(i,j,k) = rad_lw_cs_hr(k,j,i)
9201                   ENDDO
9202                ENDDO
9203             ENDDO
9204          ELSE
9205            IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) ) THEN
9206               ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9207               rad_lw_cs_hr_av = REAL( fill_value, KIND = wp )
9208            ENDIF
9209             DO  i = nxl, nxr
9210                DO  j = nys, nyn 
9211                   DO  k = nzb_do, nzt_do
9212                      local_pf(i,j,k) = rad_lw_cs_hr_av(k,j,i)
9213                   ENDDO
9214                ENDDO
9215             ENDDO
9216          ENDIF
9217          IF ( mode == 'xy' )  grid = 'zw'
9218
9219       CASE ( 'rad_lw_hr_xy', 'rad_lw_hr_xz', 'rad_lw_hr_yz' )
9220          IF ( av == 0 ) THEN
9221             DO  i = nxl, nxr
9222                DO  j = nys, nyn
9223                   DO  k = nzb_do, nzt_do
9224                      local_pf(i,j,k) = rad_lw_hr(k,j,i)
9225                   ENDDO
9226                ENDDO
9227             ENDDO
9228          ELSE
9229            IF ( .NOT. ALLOCATED( rad_lw_hr_av ) ) THEN
9230               ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9231               rad_lw_hr_av= REAL( fill_value, KIND = wp )
9232            ENDIF
9233             DO  i = nxl, nxr
9234                DO  j = nys, nyn 
9235                   DO  k = nzb_do, nzt_do
9236                      local_pf(i,j,k) = rad_lw_hr_av(k,j,i)
9237                   ENDDO
9238                ENDDO
9239             ENDDO
9240          ENDIF
9241          IF ( mode == 'xy' )  grid = 'zw'
9242
9243       CASE ( 'rad_sw_in_xy', 'rad_sw_in_xz', 'rad_sw_in_yz' )
9244          IF ( av == 0 ) THEN
9245             DO  i = nxl, nxr
9246                DO  j = nys, nyn
9247                   DO  k = nzb_do, nzt_do
9248                      local_pf(i,j,k) = rad_sw_in(k,j,i)
9249                   ENDDO
9250                ENDDO
9251             ENDDO
9252          ELSE
9253            IF ( .NOT. ALLOCATED( rad_sw_in_av ) ) THEN
9254               ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9255               rad_sw_in_av = REAL( fill_value, KIND = wp )
9256            ENDIF
9257             DO  i = nxl, nxr
9258                DO  j = nys, nyn 
9259                   DO  k = nzb_do, nzt_do
9260                      local_pf(i,j,k) = rad_sw_in_av(k,j,i)
9261                   ENDDO
9262                ENDDO
9263             ENDDO
9264          ENDIF
9265          IF ( mode == 'xy' )  grid = 'zu'
9266
9267       CASE ( 'rad_sw_out_xy', 'rad_sw_out_xz', 'rad_sw_out_yz' )
9268          IF ( av == 0 ) THEN
9269             DO  i = nxl, nxr
9270                DO  j = nys, nyn
9271                   DO  k = nzb_do, nzt_do
9272                      local_pf(i,j,k) = rad_sw_out(k,j,i)
9273                   ENDDO
9274                ENDDO
9275             ENDDO
9276          ELSE
9277            IF ( .NOT. ALLOCATED( rad_sw_out_av ) ) THEN
9278               ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9279               rad_sw_out_av = REAL( fill_value, KIND = wp )
9280            ENDIF
9281             DO  i = nxl, nxr
9282                DO  j = nys, nyn 
9283                   DO  k = nzb, nzt+1
9284                      local_pf(i,j,k) = rad_sw_out_av(k,j,i)
9285                   ENDDO
9286                ENDDO
9287             ENDDO
9288          ENDIF
9289          IF ( mode == 'xy' )  grid = 'zu'
9290
9291       CASE ( 'rad_sw_cs_hr_xy', 'rad_sw_cs_hr_xz', 'rad_sw_cs_hr_yz' )
9292          IF ( av == 0 ) THEN
9293             DO  i = nxl, nxr
9294                DO  j = nys, nyn
9295                   DO  k = nzb_do, nzt_do
9296                      local_pf(i,j,k) = rad_sw_cs_hr(k,j,i)
9297                   ENDDO
9298                ENDDO
9299             ENDDO
9300          ELSE
9301            IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) ) THEN
9302               ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9303               rad_sw_cs_hr_av = REAL( fill_value, KIND = wp )
9304            ENDIF
9305             DO  i = nxl, nxr
9306                DO  j = nys, nyn 
9307                   DO  k = nzb_do, nzt_do
9308                      local_pf(i,j,k) = rad_sw_cs_hr_av(k,j,i)
9309                   ENDDO
9310                ENDDO
9311             ENDDO
9312          ENDIF
9313          IF ( mode == 'xy' )  grid = 'zw'
9314
9315       CASE ( 'rad_sw_hr_xy', 'rad_sw_hr_xz', 'rad_sw_hr_yz' )
9316          IF ( av == 0 ) THEN
9317             DO  i = nxl, nxr
9318                DO  j = nys, nyn
9319                   DO  k = nzb_do, nzt_do
9320                      local_pf(i,j,k) = rad_sw_hr(k,j,i)
9321                   ENDDO
9322                ENDDO
9323             ENDDO
9324          ELSE
9325            IF ( .NOT. ALLOCATED( rad_sw_hr_av ) ) THEN
9326               ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9327               rad_sw_hr_av = REAL( fill_value, KIND = wp )
9328            ENDIF
9329             DO  i = nxl, nxr
9330                DO  j = nys, nyn 
9331                   DO  k = nzb_do, nzt_do
9332                      local_pf(i,j,k) = rad_sw_hr_av(k,j,i)
9333                   ENDDO
9334                ENDDO
9335             ENDDO
9336          ENDIF
9337          IF ( mode == 'xy' )  grid = 'zw'
9338
9339       CASE DEFAULT
9340          found = .FALSE.
9341          grid  = 'none'
9342
9343    END SELECT
9344 
9345 END SUBROUTINE radiation_data_output_2d
9346
9347
9348!------------------------------------------------------------------------------!
9349!
9350! Description:
9351! ------------
9352!> Subroutine defining 3D output variables
9353!------------------------------------------------------------------------------!
9354 SUBROUTINE radiation_data_output_3d( av, variable, found, local_pf, nzb_do, nzt_do )
9355 
9356
9357    USE indices
9358
9359    USE kinds
9360
9361
9362    IMPLICIT NONE
9363
9364    CHARACTER (LEN=*) ::  variable !<
9365
9366    INTEGER(iwp) ::  av          !<
9367    INTEGER(iwp) ::  i, j, k, l  !<
9368    INTEGER(iwp) ::  nzb_do      !<
9369    INTEGER(iwp) ::  nzt_do      !<
9370
9371    LOGICAL      ::  found       !<
9372
9373    REAL(wp)     ::  fill_value = -999.0_wp    !< value for the _FillValue attribute
9374
9375    REAL(sp), DIMENSION(nxl:nxr,nys:nyn,nzb_do:nzt_do) ::  local_pf !<
9376
9377    found = .TRUE.
9378
9379
9380    SELECT CASE ( TRIM( variable ) )
9381
9382      CASE ( 'rad_sw_in' )
9383         IF ( av == 0 )  THEN
9384            DO  i = nxl, nxr
9385               DO  j = nys, nyn
9386                  DO  k = nzb_do, nzt_do
9387                     local_pf(i,j,k) = rad_sw_in(k,j,i)
9388                  ENDDO
9389               ENDDO
9390            ENDDO
9391         ELSE
9392            IF ( .NOT. ALLOCATED( rad_sw_in_av ) ) THEN
9393               ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9394               rad_sw_in_av = REAL( fill_value, KIND = wp )
9395            ENDIF
9396            DO  i = nxl, nxr
9397               DO  j = nys, nyn
9398                  DO  k = nzb_do, nzt_do
9399                     local_pf(i,j,k) = rad_sw_in_av(k,j,i)
9400                  ENDDO
9401               ENDDO
9402            ENDDO
9403         ENDIF
9404
9405      CASE ( 'rad_sw_out' )
9406         IF ( av == 0 )  THEN
9407            DO  i = nxl, nxr
9408               DO  j = nys, nyn
9409                  DO  k = nzb_do, nzt_do
9410                     local_pf(i,j,k) = rad_sw_out(k,j,i)
9411                  ENDDO
9412               ENDDO
9413            ENDDO
9414         ELSE
9415            IF ( .NOT. ALLOCATED( rad_sw_out_av ) ) THEN
9416               ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9417               rad_sw_out_av = REAL( fill_value, KIND = wp )
9418            ENDIF
9419            DO  i = nxl, nxr
9420               DO  j = nys, nyn
9421                  DO  k = nzb_do, nzt_do
9422                     local_pf(i,j,k) = rad_sw_out_av(k,j,i)
9423                  ENDDO
9424               ENDDO
9425            ENDDO
9426         ENDIF
9427
9428      CASE ( 'rad_sw_cs_hr' )
9429         IF ( av == 0 )  THEN
9430            DO  i = nxl, nxr
9431               DO  j = nys, nyn
9432                  DO  k = nzb_do, nzt_do
9433                     local_pf(i,j,k) = rad_sw_cs_hr(k,j,i)
9434                  ENDDO
9435               ENDDO
9436            ENDDO
9437         ELSE
9438            IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) ) THEN
9439               ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9440               rad_sw_cs_hr_av = REAL( fill_value, KIND = wp )
9441            ENDIF
9442            DO  i = nxl, nxr
9443               DO  j = nys, nyn
9444                  DO  k = nzb_do, nzt_do
9445                     local_pf(i,j,k) = rad_sw_cs_hr_av(k,j,i)
9446                  ENDDO
9447               ENDDO
9448            ENDDO
9449         ENDIF
9450
9451      CASE ( 'rad_sw_hr' )
9452         IF ( av == 0 )  THEN
9453            DO  i = nxl, nxr
9454               DO  j = nys, nyn
9455                  DO  k = nzb_do, nzt_do
9456                     local_pf(i,j,k) = rad_sw_hr(k,j,i)
9457                  ENDDO
9458               ENDDO
9459            ENDDO
9460         ELSE
9461            IF ( .NOT. ALLOCATED( rad_sw_hr_av ) ) THEN
9462               ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9463               rad_sw_hr_av = REAL( fill_value, KIND = wp )
9464            ENDIF
9465            DO  i = nxl, nxr
9466               DO  j = nys, nyn
9467                  DO  k = nzb_do, nzt_do
9468                     local_pf(i,j,k) = rad_sw_hr_av(k,j,i)
9469                  ENDDO
9470               ENDDO
9471            ENDDO
9472         ENDIF
9473
9474      CASE ( 'rad_lw_in' )
9475         IF ( av == 0 )  THEN
9476            DO  i = nxl, nxr
9477               DO  j = nys, nyn
9478                  DO  k = nzb_do, nzt_do
9479                     local_pf(i,j,k) = rad_lw_in(k,j,i)
9480                  ENDDO
9481               ENDDO
9482            ENDDO
9483         ELSE
9484            IF ( .NOT. ALLOCATED( rad_lw_in_av ) ) THEN
9485               ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9486               rad_lw_in_av = REAL( fill_value, KIND = wp )
9487            ENDIF
9488            DO  i = nxl, nxr
9489               DO  j = nys, nyn
9490                  DO  k = nzb_do, nzt_do
9491                     local_pf(i,j,k) = rad_lw_in_av(k,j,i)
9492                  ENDDO
9493               ENDDO
9494            ENDDO
9495         ENDIF
9496
9497      CASE ( 'rad_lw_out' )
9498         IF ( av == 0 )  THEN
9499            DO  i = nxl, nxr
9500               DO  j = nys, nyn
9501                  DO  k = nzb_do, nzt_do
9502                     local_pf(i,j,k) = rad_lw_out(k,j,i)
9503                  ENDDO
9504               ENDDO
9505            ENDDO
9506         ELSE
9507            IF ( .NOT. ALLOCATED( rad_lw_out_av ) ) THEN
9508               ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9509               rad_lw_out_av = REAL( fill_value, KIND = wp )
9510            ENDIF
9511            DO  i = nxl, nxr
9512               DO  j = nys, nyn
9513                  DO  k = nzb_do, nzt_do
9514                     local_pf(i,j,k) = rad_lw_out_av(k,j,i)
9515                  ENDDO
9516               ENDDO
9517            ENDDO
9518         ENDIF
9519
9520      CASE ( 'rad_lw_cs_hr' )
9521         IF ( av == 0 )  THEN
9522            DO  i = nxl, nxr
9523               DO  j = nys, nyn
9524                  DO  k = nzb_do, nzt_do
9525                     local_pf(i,j,k) = rad_lw_cs_hr(k,j,i)
9526                  ENDDO
9527               ENDDO
9528            ENDDO
9529         ELSE
9530            IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) ) THEN
9531               ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9532               rad_lw_cs_hr_av = REAL( fill_value, KIND = wp )
9533            ENDIF
9534            DO  i = nxl, nxr
9535               DO  j = nys, nyn
9536                  DO  k = nzb_do, nzt_do
9537                     local_pf(i,j,k) = rad_lw_cs_hr_av(k,j,i)
9538                  ENDDO
9539               ENDDO
9540            ENDDO
9541         ENDIF
9542
9543      CASE ( 'rad_lw_hr' )
9544         IF ( av == 0 )  THEN
9545            DO  i = nxl, nxr
9546               DO  j = nys, nyn
9547                  DO  k = nzb_do, nzt_do
9548                     local_pf(i,j,k) = rad_lw_hr(k,j,i)
9549                  ENDDO
9550               ENDDO
9551            ENDDO
9552         ELSE
9553            IF ( .NOT. ALLOCATED( rad_lw_hr_av ) ) THEN
9554               ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9555              rad_lw_hr_av = REAL( fill_value, KIND = wp )
9556            ENDIF
9557            DO  i = nxl, nxr
9558               DO  j = nys, nyn
9559                  DO  k = nzb_do, nzt_do
9560                     local_pf(i,j,k) = rad_lw_hr_av(k,j,i)
9561                  ENDDO
9562               ENDDO
9563            ENDDO
9564         ENDIF
9565
9566      CASE ( 'rad_mrt_sw' )
9567         local_pf = REAL( fill_value, KIND = wp )
9568         IF ( av == 0 )  THEN
9569            DO  l = 1, nmrtbl
9570               i = mrtbl(ix,l)
9571               j = mrtbl(iy,l)
9572               k = mrtbl(iz,l)
9573               local_pf(i,j,k) = mrtinsw(l)
9574            ENDDO
9575         ELSE
9576            IF ( ALLOCATED( mrtinsw_av ) ) THEN
9577               DO  l = 1, nmrtbl
9578                  i = mrtbl(ix,l)
9579                  j = mrtbl(iy,l)
9580                  k = mrtbl(iz,l)
9581                  local_pf(i,j,k) = mrtinsw_av(l)
9582               ENDDO
9583            ENDIF
9584         ENDIF
9585
9586      CASE ( 'rad_mrt_lw' )
9587         local_pf = REAL( fill_value, KIND = wp )
9588         IF ( av == 0 )  THEN
9589            DO  l = 1, nmrtbl
9590               i = mrtbl(ix,l)
9591               j = mrtbl(iy,l)
9592               k = mrtbl(iz,l)
9593               local_pf(i,j,k) = mrtinlw(l)
9594            ENDDO
9595         ELSE
9596            IF ( ALLOCATED( mrtinlw_av ) ) THEN
9597               DO  l = 1, nmrtbl
9598                  i = mrtbl(ix,l)
9599                  j = mrtbl(iy,l)
9600                  k = mrtbl(iz,l)
9601                  local_pf(i,j,k) = mrtinlw_av(l)
9602               ENDDO
9603            ENDIF
9604         ENDIF
9605
9606      CASE ( 'rad_mrt' )
9607         local_pf = REAL( fill_value, KIND = wp )
9608         IF ( av == 0 )  THEN
9609            DO  l = 1, nmrtbl
9610               i = mrtbl(ix,l)
9611               j = mrtbl(iy,l)
9612               k = mrtbl(iz,l)
9613               local_pf(i,j,k) = mrt(l)
9614            ENDDO
9615         ELSE
9616            IF ( ALLOCATED( mrt_av ) ) THEN
9617               DO  l = 1, nmrtbl
9618                  i = mrtbl(ix,l)
9619                  j = mrtbl(iy,l)
9620                  k = mrtbl(iz,l)
9621                  local_pf(i,j,k) = mrt_av(l)
9622               ENDDO
9623            ENDIF
9624         ENDIF
9625
9626       CASE DEFAULT
9627          found = .FALSE.
9628
9629    END SELECT
9630
9631
9632 END SUBROUTINE radiation_data_output_3d
9633
9634!------------------------------------------------------------------------------!
9635!
9636! Description:
9637! ------------
9638!> Subroutine defining masked data output
9639!------------------------------------------------------------------------------!
9640 SUBROUTINE radiation_data_output_mask( av, variable, found, local_pf )
9641 
9642    USE control_parameters
9643       
9644    USE indices
9645   
9646    USE kinds
9647   
9648
9649    IMPLICIT NONE
9650
9651    CHARACTER (LEN=*) ::  variable   !<
9652
9653    CHARACTER(LEN=5) ::  grid        !< flag to distinquish between staggered grids
9654
9655    INTEGER(iwp) ::  av              !<
9656    INTEGER(iwp) ::  i               !<
9657    INTEGER(iwp) ::  j               !<
9658    INTEGER(iwp) ::  k               !<
9659    INTEGER(iwp) ::  topo_top_ind    !< k index of highest horizontal surface
9660
9661    LOGICAL ::  found                !< true if output array was found
9662    LOGICAL ::  resorted             !< true if array is resorted
9663
9664
9665    REAL(wp),                                                                  &
9666       DIMENSION(mask_size_l(mid,1),mask_size_l(mid,2),mask_size_l(mid,3)) ::  &
9667          local_pf   !<
9668
9669    REAL(wp), DIMENSION(:,:,:), POINTER ::  to_be_resorted  !< points to array which needs to be resorted for output
9670
9671
9672    found    = .TRUE.
9673    grid     = 's'
9674    resorted = .FALSE.
9675
9676    SELECT CASE ( TRIM( variable ) )
9677
9678
9679       CASE ( 'rad_lw_in' )
9680          IF ( av == 0 )  THEN
9681             to_be_resorted => rad_lw_in
9682          ELSE
9683             to_be_resorted => rad_lw_in_av
9684          ENDIF
9685
9686       CASE ( 'rad_lw_out' )
9687          IF ( av == 0 )  THEN
9688             to_be_resorted => rad_lw_out
9689          ELSE
9690             to_be_resorted => rad_lw_out_av
9691          ENDIF
9692
9693       CASE ( 'rad_lw_cs_hr' )
9694          IF ( av == 0 )  THEN
9695             to_be_resorted => rad_lw_cs_hr
9696          ELSE
9697             to_be_resorted => rad_lw_cs_hr_av
9698          ENDIF
9699
9700       CASE ( 'rad_lw_hr' )
9701          IF ( av == 0 )  THEN
9702             to_be_resorted => rad_lw_hr
9703          ELSE
9704             to_be_resorted => rad_lw_hr_av
9705          ENDIF
9706
9707       CASE ( 'rad_sw_in' )
9708          IF ( av == 0 )  THEN
9709             to_be_resorted => rad_sw_in
9710          ELSE
9711             to_be_resorted => rad_sw_in_av
9712          ENDIF
9713
9714       CASE ( 'rad_sw_out' )
9715          IF ( av == 0 )  THEN
9716             to_be_resorted => rad_sw_out
9717          ELSE
9718             to_be_resorted => rad_sw_out_av
9719          ENDIF
9720
9721       CASE ( 'rad_sw_cs_hr' )
9722          IF ( av == 0 )  THEN
9723             to_be_resorted => rad_sw_cs_hr
9724          ELSE
9725             to_be_resorted => rad_sw_cs_hr_av
9726          ENDIF
9727
9728       CASE ( 'rad_sw_hr' )
9729          IF ( av == 0 )  THEN
9730             to_be_resorted => rad_sw_hr
9731          ELSE
9732             to_be_resorted => rad_sw_hr_av
9733          ENDIF
9734
9735       CASE DEFAULT
9736          found = .FALSE.
9737
9738    END SELECT
9739
9740!
9741!-- Resort the array to be output, if not done above
9742    IF ( .NOT. resorted )  THEN
9743       IF ( .NOT. mask_surface(mid) )  THEN
9744!
9745!--       Default masked output
9746          DO  i = 1, mask_size_l(mid,1)
9747             DO  j = 1, mask_size_l(mid,2)
9748                DO  k = 1, mask_size_l(mid,3)
9749                   local_pf(i,j,k) =  to_be_resorted(mask_k(mid,k), &
9750                                      mask_j(mid,j),mask_i(mid,i))
9751                ENDDO
9752             ENDDO
9753          ENDDO
9754
9755       ELSE
9756!
9757!--       Terrain-following masked output
9758          DO  i = 1, mask_size_l(mid,1)
9759             DO  j = 1, mask_size_l(mid,2)
9760!
9761!--             Get k index of highest horizontal surface
9762                topo_top_ind = get_topography_top_index_ji( mask_j(mid,j), &
9763                                                            mask_i(mid,i), &
9764                                                            grid )
9765!
9766!--             Save output array
9767                DO  k = 1, mask_size_l(mid,3)
9768                   local_pf(i,j,k) = to_be_resorted(                       &
9769                                          MIN( topo_top_ind+mask_k(mid,k), &
9770                                               nzt+1 ),                    &
9771                                          mask_j(mid,j),                   &
9772                                          mask_i(mid,i)                     )
9773                ENDDO
9774             ENDDO
9775          ENDDO
9776
9777       ENDIF
9778    ENDIF
9779
9780
9781
9782 END SUBROUTINE radiation_data_output_mask
9783
9784
9785!------------------------------------------------------------------------------!
9786! Description:
9787! ------------
9788!> Subroutine writes local (subdomain) restart data
9789!------------------------------------------------------------------------------!
9790 SUBROUTINE radiation_wrd_local
9791
9792
9793    IMPLICIT NONE
9794
9795
9796    IF ( ALLOCATED( rad_net_av ) )  THEN
9797       CALL wrd_write_string( 'rad_net_av' )
9798       WRITE ( 14 )  rad_net_av
9799    ENDIF
9800   
9801    IF ( ALLOCATED( rad_lw_in_xy_av ) )  THEN
9802       CALL wrd_write_string( 'rad_lw_in_xy_av' )
9803       WRITE ( 14 )  rad_lw_in_xy_av
9804    ENDIF
9805   
9806    IF ( ALLOCATED( rad_lw_out_xy_av ) )  THEN
9807       CALL wrd_write_string( 'rad_lw_out_xy_av' )
9808       WRITE ( 14 )  rad_lw_out_xy_av
9809    ENDIF
9810   
9811    IF ( ALLOCATED( rad_sw_in_xy_av ) )  THEN
9812       CALL wrd_write_string( 'rad_sw_in_xy_av' )
9813       WRITE ( 14 )  rad_sw_in_xy_av
9814    ENDIF
9815   
9816    IF ( ALLOCATED( rad_sw_out_xy_av ) )  THEN
9817       CALL wrd_write_string( 'rad_sw_out_xy_av' )
9818       WRITE ( 14 )  rad_sw_out_xy_av
9819    ENDIF
9820
9821    IF ( ALLOCATED( rad_lw_in ) )  THEN
9822       CALL wrd_write_string( 'rad_lw_in' )
9823       WRITE ( 14 )  rad_lw_in
9824    ENDIF
9825
9826    IF ( ALLOCATED( rad_lw_in_av ) )  THEN
9827       CALL wrd_write_string( 'rad_lw_in_av' )
9828       WRITE ( 14 )  rad_lw_in_av
9829    ENDIF
9830
9831    IF ( ALLOCATED( rad_lw_out ) )  THEN
9832       CALL wrd_write_string( 'rad_lw_out' )
9833       WRITE ( 14 )  rad_lw_out
9834    ENDIF
9835
9836    IF ( ALLOCATED( rad_lw_out_av) )  THEN
9837       CALL wrd_write_string( 'rad_lw_out_av' )
9838       WRITE ( 14 )  rad_lw_out_av
9839    ENDIF
9840
9841    IF ( ALLOCATED( rad_lw_cs_hr) )  THEN
9842       CALL wrd_write_string( 'rad_lw_cs_hr' )
9843       WRITE ( 14 )  rad_lw_cs_hr
9844    ENDIF
9845
9846    IF ( ALLOCATED( rad_lw_cs_hr_av) )  THEN
9847       CALL wrd_write_string( 'rad_lw_cs_hr_av' )
9848       WRITE ( 14 )  rad_lw_cs_hr_av
9849    ENDIF
9850
9851    IF ( ALLOCATED( rad_lw_hr) )  THEN
9852       CALL wrd_write_string( 'rad_lw_hr' )
9853       WRITE ( 14 )  rad_lw_hr
9854    ENDIF
9855
9856    IF ( ALLOCATED( rad_lw_hr_av) )  THEN
9857       CALL wrd_write_string( 'rad_lw_hr_av' )
9858       WRITE ( 14 )  rad_lw_hr_av
9859    ENDIF
9860
9861    IF ( ALLOCATED( rad_sw_in) )  THEN
9862       CALL wrd_write_string( 'rad_sw_in' )
9863       WRITE ( 14 )  rad_sw_in
9864    ENDIF
9865
9866    IF ( ALLOCATED( rad_sw_in_av) )  THEN
9867       CALL wrd_write_string( 'rad_sw_in_av' )
9868       WRITE ( 14 )  rad_sw_in_av
9869    ENDIF
9870
9871    IF ( ALLOCATED( rad_sw_out) )  THEN
9872       CALL wrd_write_string( 'rad_sw_out' )
9873       WRITE ( 14 )  rad_sw_out
9874    ENDIF
9875
9876    IF ( ALLOCATED( rad_sw_out_av) )  THEN
9877       CALL wrd_write_string( 'rad_sw_out_av' )
9878       WRITE ( 14 )  rad_sw_out_av
9879    ENDIF
9880
9881    IF ( ALLOCATED( rad_sw_cs_hr) )  THEN
9882       CALL wrd_write_string( 'rad_sw_cs_hr' )
9883       WRITE ( 14 )  rad_sw_cs_hr
9884    ENDIF
9885
9886    IF ( ALLOCATED( rad_sw_cs_hr_av) )  THEN
9887       CALL wrd_write_string( 'rad_sw_cs_hr_av' )
9888       WRITE ( 14 )  rad_sw_cs_hr_av
9889    ENDIF
9890
9891    IF ( ALLOCATED( rad_sw_hr) )  THEN
9892       CALL wrd_write_string( 'rad_sw_hr' )
9893       WRITE ( 14 )  rad_sw_hr
9894    ENDIF
9895
9896    IF ( ALLOCATED( rad_sw_hr_av) )  THEN
9897       CALL wrd_write_string( 'rad_sw_hr_av' )
9898       WRITE ( 14 )  rad_sw_hr_av
9899    ENDIF
9900
9901
9902 END SUBROUTINE radiation_wrd_local
9903
9904!------------------------------------------------------------------------------!
9905! Description:
9906! ------------
9907!> Subroutine reads local (subdomain) restart data
9908!------------------------------------------------------------------------------!
9909 SUBROUTINE radiation_rrd_local( i, k, nxlf, nxlc, nxl_on_file, nxrf, nxrc,    &
9910                                nxr_on_file, nynf, nync, nyn_on_file, nysf,    &
9911                                nysc, nys_on_file, tmp_2d, tmp_3d, found )
9912 
9913
9914    USE control_parameters
9915       
9916    USE indices
9917   
9918    USE kinds
9919   
9920    USE pegrid
9921
9922
9923    IMPLICIT NONE
9924
9925    INTEGER(iwp) ::  i               !<
9926    INTEGER(iwp) ::  k               !<
9927    INTEGER(iwp) ::  nxlc            !<
9928    INTEGER(iwp) ::  nxlf            !<
9929    INTEGER(iwp) ::  nxl_on_file     !<
9930    INTEGER(iwp) ::  nxrc            !<
9931    INTEGER(iwp) ::  nxrf            !<
9932    INTEGER(iwp) ::  nxr_on_file     !<
9933    INTEGER(iwp) ::  nync            !<
9934    INTEGER(iwp) ::  nynf            !<
9935    INTEGER(iwp) ::  nyn_on_file     !<
9936    INTEGER(iwp) ::  nysc            !<
9937    INTEGER(iwp) ::  nysf            !<
9938    INTEGER(iwp) ::  nys_on_file     !<
9939
9940    LOGICAL, INTENT(OUT)  :: found
9941
9942    REAL(wp), DIMENSION(nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_2d   !<
9943
9944    REAL(wp), DIMENSION(nzb:nzt+1,nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_3d   !<
9945
9946    REAL(wp), DIMENSION(0:0,nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_3d2   !<
9947
9948
9949    found = .TRUE.
9950
9951
9952    SELECT CASE ( restart_string(1:length) )
9953
9954       CASE ( 'rad_net_av' )
9955          IF ( .NOT. ALLOCATED( rad_net_av ) )  THEN
9956             ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
9957          ENDIF 
9958          IF ( k == 1 )  READ ( 13 )  tmp_2d
9959          rad_net_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =           &
9960                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
9961                       
9962       CASE ( 'rad_lw_in_xy_av' )
9963          IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) )  THEN
9964             ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
9965          ENDIF 
9966          IF ( k == 1 )  READ ( 13 )  tmp_2d
9967          rad_lw_in_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =      &
9968                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
9969                       
9970       CASE ( 'rad_lw_out_xy_av' )
9971          IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) )  THEN
9972             ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
9973          ENDIF 
9974          IF ( k == 1 )  READ ( 13 )  tmp_2d
9975          rad_lw_out_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =     &
9976                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
9977                       
9978       CASE ( 'rad_sw_in_xy_av' )
9979          IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) )  THEN
9980             ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
9981          ENDIF 
9982          IF ( k == 1 )  READ ( 13 )  tmp_2d
9983          rad_sw_in_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =      &
9984                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
9985                       
9986       CASE ( 'rad_sw_out_xy_av' )
9987          IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) )  THEN
9988             ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
9989          ENDIF 
9990          IF ( k == 1 )  READ ( 13 )  tmp_2d
9991          rad_sw_out_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =     &
9992                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
9993                       
9994       CASE ( 'rad_lw_in' )
9995          IF ( .NOT. ALLOCATED( rad_lw_in ) )  THEN
9996             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
9997                  radiation_scheme == 'constant')  THEN
9998                ALLOCATE( rad_lw_in(0:0,nysg:nyng,nxlg:nxrg) )
9999             ELSE
10000                ALLOCATE( rad_lw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10001             ENDIF
10002          ENDIF 
10003          IF ( k == 1 )  THEN
10004             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
10005                  radiation_scheme == 'constant')  THEN
10006                READ ( 13 )  tmp_3d2
10007                rad_lw_in(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =   &
10008                   tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10009             ELSE
10010                READ ( 13 )  tmp_3d
10011                rad_lw_in(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
10012                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10013             ENDIF
10014          ENDIF
10015
10016       CASE ( 'rad_lw_in_av' )
10017          IF ( .NOT. ALLOCATED( rad_lw_in_av ) )  THEN
10018             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
10019                  radiation_scheme == 'constant')  THEN
10020                ALLOCATE( rad_lw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
10021             ELSE
10022                ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10023             ENDIF
10024          ENDIF 
10025          IF ( k == 1 )  THEN
10026             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
10027                  radiation_scheme == 'constant')  THEN
10028                READ ( 13 )  tmp_3d2
10029                rad_lw_in_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =&
10030                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10031             ELSE
10032                READ ( 13 )  tmp_3d
10033                rad_lw_in_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
10034                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10035             ENDIF
10036          ENDIF
10037
10038       CASE ( 'rad_lw_out' )
10039          IF ( .NOT. ALLOCATED( rad_lw_out ) )  THEN
10040             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
10041                  radiation_scheme == 'constant')  THEN
10042                ALLOCATE( rad_lw_out(0:0,nysg:nyng,nxlg:nxrg) )
10043             ELSE
10044                ALLOCATE( rad_lw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10045             ENDIF
10046          ENDIF 
10047          IF ( k == 1 )  THEN
10048             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
10049                  radiation_scheme == 'constant')  THEN
10050                READ ( 13 )  tmp_3d2
10051                rad_lw_out(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
10052                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10053             ELSE
10054                READ ( 13 )  tmp_3d
10055                rad_lw_out(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =    &
10056                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10057             ENDIF
10058          ENDIF
10059
10060       CASE ( 'rad_lw_out_av' )
10061          IF ( .NOT. ALLOCATED( rad_lw_out_av ) )  THEN
10062             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
10063                  radiation_scheme == 'constant')  THEN
10064                ALLOCATE( rad_lw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
10065             ELSE
10066                ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10067             ENDIF
10068          ENDIF 
10069          IF ( k == 1 )  THEN
10070             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
10071                  radiation_scheme == 'constant')  THEN
10072                READ ( 13 )  tmp_3d2
10073                rad_lw_out_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) &
10074                   = tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10075             ELSE
10076                READ ( 13 )  tmp_3d
10077                rad_lw_out_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &
10078                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10079             ENDIF
10080          ENDIF
10081
10082       CASE ( 'rad_lw_cs_hr' )
10083          IF ( .NOT. ALLOCATED( rad_lw_cs_hr ) )  THEN
10084             ALLOCATE( rad_lw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10085          ENDIF
10086          IF ( k == 1 )  READ ( 13 )  tmp_3d
10087          rad_lw_cs_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
10088                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10089
10090       CASE ( 'rad_lw_cs_hr_av' )
10091          IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) )  THEN
10092             ALLOCATE( rad_lw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10093          ENDIF
10094          IF ( k == 1 )  READ ( 13 )  tmp_3d
10095          rad_lw_cs_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
10096                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10097
10098       CASE ( 'rad_lw_hr' )
10099          IF ( .NOT. ALLOCATED( rad_lw_hr ) )  THEN
10100             ALLOCATE( rad_lw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10101          ENDIF
10102          IF ( k == 1 )  READ ( 13 )  tmp_3d
10103          rad_lw_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =           &
10104                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10105
10106       CASE ( 'rad_lw_hr_av' )
10107          IF ( .NOT. ALLOCATED( rad_lw_hr_av ) )  THEN
10108             ALLOCATE( rad_lw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10109          ENDIF
10110          IF ( k == 1 )  READ ( 13 )  tmp_3d
10111          rad_lw_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
10112                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10113
10114       CASE ( 'rad_sw_in' )
10115          IF ( .NOT. ALLOCATED( rad_sw_in ) )  THEN
10116             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
10117                  radiation_scheme == 'constant')  THEN
10118                ALLOCATE( rad_sw_in(0:0,nysg:nyng,nxlg:nxrg) )
10119             ELSE
10120                ALLOCATE( rad_sw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10121             ENDIF
10122          ENDIF 
10123          IF ( k == 1 )  THEN
10124             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
10125                  radiation_scheme == 'constant')  THEN
10126                READ ( 13 )  tmp_3d2
10127                rad_sw_in(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =   &
10128                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10129             ELSE
10130                READ ( 13 )  tmp_3d
10131                rad_sw_in(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
10132                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10133             ENDIF
10134          ENDIF
10135
10136       CASE ( 'rad_sw_in_av' )
10137          IF ( .NOT. ALLOCATED( rad_sw_in_av ) )  THEN
10138             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
10139                  radiation_scheme == 'constant')  THEN
10140                ALLOCATE( rad_sw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
10141             ELSE
10142                ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10143             ENDIF
10144          ENDIF 
10145          IF ( k == 1 )  THEN
10146             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
10147                  radiation_scheme == 'constant')  THEN
10148                READ ( 13 )  tmp_3d2
10149                rad_sw_in_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =&
10150                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10151             ELSE
10152                READ ( 13 )  tmp_3d
10153                rad_sw_in_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
10154                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10155             ENDIF
10156          ENDIF
10157
10158       CASE ( 'rad_sw_out' )
10159          IF ( .NOT. ALLOCATED( rad_sw_out ) )  THEN
10160             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
10161                  radiation_scheme == 'constant')  THEN
10162                ALLOCATE( rad_sw_out(0:0,nysg:nyng,nxlg:nxrg) )
10163             ELSE
10164                ALLOCATE( rad_sw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10165             ENDIF
10166          ENDIF 
10167          IF ( k == 1 )  THEN
10168             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
10169                  radiation_scheme == 'constant')  THEN
10170                READ ( 13 )  tmp_3d2
10171                rad_sw_out(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
10172                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10173             ELSE
10174                READ ( 13 )  tmp_3d
10175                rad_sw_out(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =    &
10176                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10177             ENDIF
10178          ENDIF
10179
10180       CASE ( 'rad_sw_out_av' )
10181          IF ( .NOT. ALLOCATED( rad_sw_out_av ) )  THEN
10182             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
10183                  radiation_scheme == 'constant')  THEN
10184                ALLOCATE( rad_sw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
10185             ELSE
10186                ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10187             ENDIF
10188          ENDIF 
10189          IF ( k == 1 )  THEN
10190             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
10191                  radiation_scheme == 'constant')  THEN
10192                READ ( 13 )  tmp_3d2
10193                rad_sw_out_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) &
10194                   = tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10195             ELSE
10196                READ ( 13 )  tmp_3d
10197                rad_sw_out_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &
10198                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10199             ENDIF
10200          ENDIF
10201
10202       CASE ( 'rad_sw_cs_hr' )
10203          IF ( .NOT. ALLOCATED( rad_sw_cs_hr ) )  THEN
10204             ALLOCATE( rad_sw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10205          ENDIF
10206          IF ( k == 1 )  READ ( 13 )  tmp_3d
10207          rad_sw_cs_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
10208                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10209
10210       CASE ( 'rad_sw_cs_hr_av' )
10211          IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) )  THEN
10212             ALLOCATE( rad_sw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10213          ENDIF
10214          IF ( k == 1 )  READ ( 13 )  tmp_3d
10215          rad_sw_cs_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
10216                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10217
10218       CASE ( 'rad_sw_hr' )
10219          IF ( .NOT. ALLOCATED( rad_sw_hr ) )  THEN
10220             ALLOCATE( rad_sw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10221          ENDIF
10222          IF ( k == 1 )  READ ( 13 )  tmp_3d
10223          rad_sw_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =           &
10224                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10225
10226       CASE ( 'rad_sw_hr_av' )
10227          IF ( .NOT. ALLOCATED( rad_sw_hr_av ) )  THEN
10228             ALLOCATE( rad_sw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10229          ENDIF
10230          IF ( k == 1 )  READ ( 13 )  tmp_3d
10231          rad_lw_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
10232                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10233
10234       CASE DEFAULT
10235
10236          found = .FALSE.
10237
10238    END SELECT
10239
10240 END SUBROUTINE radiation_rrd_local
10241
10242!------------------------------------------------------------------------------!
10243! Description:
10244! ------------
10245!> Subroutine writes debug information
10246!------------------------------------------------------------------------------!
10247 SUBROUTINE radiation_write_debug_log ( message )
10248    !> it writes debug log with time stamp
10249    CHARACTER(*)  :: message
10250    CHARACTER(15) :: dtc
10251    CHARACTER(8)  :: date
10252    CHARACTER(10) :: time
10253    CHARACTER(5)  :: zone
10254    CALL date_and_time(date, time, zone)
10255    dtc = date(7:8)//','//time(1:2)//':'//time(3:4)//':'//time(5:10)
10256    WRITE(9,'(2A)') dtc, TRIM(message)
10257    FLUSH(9)
10258 END SUBROUTINE radiation_write_debug_log
10259
10260 END MODULE radiation_model_mod
Note: See TracBrowser for help on using the repository browser.