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

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

Replace get_topography_top_index functions by pre-calculated arrays in order to save computational resources

  • Property svn:keywords set to Id
  • Property svn:mergeinfo set to (toggle deleted branches)
    /palm/branches/chemistry/SOURCE/radiation_model_mod.f902047-3190,​3218-3297
    /palm/branches/forwind/SOURCE/radiation_model_mod.f901564-1913
    /palm/branches/mosaik_M2/radiation_model_mod.f902360-3471
    /palm/branches/palm4u/SOURCE/radiation_model_mod.f902540-2692
    /palm/branches/radiation/SOURCE/radiation_model_mod.f902081-3493
    /palm/branches/rans/SOURCE/radiation_model_mod.f902078-3128
    /palm/branches/resler/SOURCE/radiation_model_mod.f902023-4166
    /palm/branches/salsa/SOURCE/radiation_model_mod.f902503-3460
    /palm/branches/fricke/SOURCE/radiation_model_mod.f90942-977
    /palm/branches/hoffmann/SOURCE/radiation_model_mod.f90989-1052
    /palm/branches/letzel/masked_output/SOURCE/radiation_model_mod.f90296-409
    /palm/branches/suehring/radiation_model_mod.f90423-666
File size: 513.8 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-2019 Institute of Computer Science of the
18!                     Czech Academy of Sciences, Prague
19! Copyright 2015-2019 Czech Technical University in Prague
20! Copyright 1997-2019 Leibniz Universitaet Hannover
21!------------------------------------------------------------------------------!
22!
23! Current revisions:
24! ------------------
25!
26!
27! Former revisions:
28! -----------------
29! $Id: radiation_model_mod.f90 4168 2019-08-16 13:50:17Z suehring $
30! Replace function get_topography_top_index by topo_top_ind
31!
32! 4157 2019-08-14 09:19:12Z suehring
33! Give informative message on raytracing distance only by core zero
34!
35! 4148 2019-08-08 11:26:00Z suehring
36! Comments added
37!
38! 4134 2019-08-02 18:39:57Z suehring
39! Bugfix in formatted write statement
40!
41! 4127 2019-07-30 14:47:10Z suehring
42! Remove unused pch_index (merge from branch resler)
43!
44! 4089 2019-07-11 14:30:27Z suehring
45! - Correct level 2 initialization of spectral albedos in rrtmg branch, long- and
46!   shortwave albedos were mixed-up.
47! - Change order of albedo_pars so that it is now consistent with the defined
48!   order of albedo_pars in PIDS
49!
50! 4069 2019-07-01 14:05:51Z Giersch
51! Masked output running index mid has been introduced as a local variable to
52! avoid runtime error (Loop variable has been modified) in time_integration
53!
54! 4067 2019-07-01 13:29:25Z suehring
55! Bugfix, pass dummy string to MPI_INFO_SET (J. Resler)
56!
57! 4039 2019-06-18 10:32:41Z suehring
58! Bugfix for masked data output
59!
60! 4008 2019-05-30 09:50:11Z moh.hefny
61! Bugfix in check variable when a variable's string is less than 3
62! characters is processed. All variables now are checked if they
63! belong to radiation
64!
65! 3992 2019-05-22 16:49:38Z suehring
66! Bugfix in rrtmg radiation branch in a nested run when the lowest prognistic
67! grid points in a child domain are all inside topography
68!
69! 3987 2019-05-22 09:52:13Z kanani
70! Introduce alternative switch for debug output during timestepping
71!
72! 3943 2019-05-02 09:50:41Z maronga
73! Missing blank characteer added.
74!
75! 3900 2019-04-16 15:17:43Z suehring
76! Fixed initialization problem
77!
78! 3885 2019-04-11 11:29:34Z kanani
79! Changes related to global restructuring of location messages and introduction
80! of additional debug messages
81!
82! 3881 2019-04-10 09:31:22Z suehring
83! Output of albedo and emissivity moved from USM, bugfixes in initialization
84! of albedo
85!
86! 3861 2019-04-04 06:27:41Z maronga
87! Bugfix: factor of 4.0 required instead of 3.0 in calculation of rad_lw_out_change_0
88!
89! 3859 2019-04-03 20:30:31Z maronga
90! Added some descriptions
91!
92! 3847 2019-04-01 14:51:44Z suehring
93! Implement check for dt_radiation (must be > 0)
94!
95! 3846 2019-04-01 13:55:30Z suehring
96! unused variable removed
97!
98! 3814 2019-03-26 08:40:31Z pavelkrc
99! Change zenith(0:0) and others to scalar.
100! Code review.
101! Rename exported nzu, nzp and related variables due to name conflict
102!
103! 3771 2019-02-28 12:19:33Z raasch
104! rrtmg preprocessor for directives moved/added, save attribute added to temporary
105! pointers to avoid compiler warnings about outlived pointer targets,
106! statement added to avoid compiler warning about unused variable
107!
108! 3769 2019-02-28 10:16:49Z moh.hefny
109! removed unused variables and subroutine radiation_radflux_gridbox
110!
111! 3767 2019-02-27 08:18:02Z raasch
112! unused variable for file index removed from rrd-subroutines parameter list
113!
114! 3760 2019-02-21 18:47:35Z moh.hefny
115! Bugfix: initialized simulated_time before calculating solar position
116! to enable restart option with reading in SVF from file(s).
117!
118! 3754 2019-02-19 17:02:26Z kanani
119! (resler, pavelkrc)
120! Bugfixes: add further required MRT factors to read/write_svf,
121! fix for aggregating view factors to eliminate local noise in reflected
122! irradiance at mutually close surfaces (corners, presence of trees) in the
123! angular discretization scheme.
124!
125! 3752 2019-02-19 09:37:22Z resler
126! added read/write number of MRT factors to the respective routines
127!
128! 3705 2019-01-29 19:56:39Z suehring
129! Make variables that are sampled in virtual measurement module public
130!
131! 3704 2019-01-29 19:51:41Z suehring
132! Some interface calls moved to module_interface + cleanup
133!
134! 3667 2019-01-10 14:26:24Z schwenkel
135! Modified check for rrtmg input files
136!
137! 3655 2019-01-07 16:51:22Z knoop
138! nopointer option removed
139!
140! 3633 2018-12-17 16:17:57Z schwenkel
141! Include check for rrtmg files
142!
143! 3630 2018-12-17 11:04:17Z knoop
144! - fix initialization of date and time after calling zenith
145! - fix a bug in radiation_solar_pos
146!
147! 3616 2018-12-10 09:44:36Z Salim
148! fix manipulation of time variables in radiation_presimulate_solar_pos
149!
150! 3608 2018-12-07 12:59:57Z suehring $
151! Bugfix radiation output
152!
153! 3607 2018-12-07 11:56:58Z suehring
154! Output of radiation-related quantities migrated to radiation_model_mod.
155!
156! 3589 2018-11-30 15:09:51Z suehring
157! Remove erroneous UTF encoding
158!
159! 3572 2018-11-28 11:40:28Z suehring
160! Add filling the short- and longwave radiation flux arrays (e.g. diffuse,
161! direct, reflected, resedual) for all surfaces. This is required to surface
162! outputs in suface_output_mod. (M. Salim)
163!
164! 3571 2018-11-28 09:24:03Z moh.hefny
165! Add an epsilon value to compare values in if statement to fix possible
166! precsion related errors in raytrace routines.
167!
168! 3524 2018-11-14 13:36:44Z raasch
169! missing cpp-directives added
170!
171! 3495 2018-11-06 15:22:17Z kanani
172! Resort control_parameters ONLY list,
173! From branch radiation@3491 moh.hefny:
174! bugfix in calculating the apparent solar positions by updating
175! the simulated time so that the actual time is correct.
176!
177! 3464 2018-10-30 18:08:55Z kanani
178! From branch resler@3462, pavelkrc:
179! add MRT shaping function for human
180!
181! 3449 2018-10-29 19:36:56Z suehring
182! New RTM version 3.0: (Pavel Krc, Jaroslav Resler, ICS, Prague)
183!   - Interaction of plant canopy with LW radiation
184!   - Transpiration from resolved plant canopy dependent on radiation
185!     called from RTM
186!
187!
188! 3435 2018-10-26 18:25:44Z gronemeier
189! - workaround: return unit=illegal in check_data_output for certain variables
190!   when check called from init_masks
191! - Use pointer in masked output to reduce code redundancies
192! - Add terrain-following masked output
193!
194! 3424 2018-10-25 07:29:10Z gronemeier
195! bugfix: add rad_lw_in, rad_lw_out, rad_sw_out to radiation_check_data_output
196!
197! 3378 2018-10-19 12:34:59Z kanani
198! merge from radiation branch (r3362) into trunk
199! (moh.hefny):
200! - removed read/write_svf_on_init and read_dist_max_svf (not used anymore)
201! - bugfix nzut > nzpt in calculating maxboxes
202!
203! 3372 2018-10-18 14:03:19Z raasch
204! bugfix: kind type of 2nd argument of mpi_win_allocate changed, misplaced
205!         __parallel directive
206!
207! 3351 2018-10-15 18:40:42Z suehring
208! Do not overwrite values of spectral and broadband albedo during initialization
209! if they are already initialized in the urban-surface model via ASCII input.
210!
211! 3337 2018-10-12 15:17:09Z kanani
212! - New RTM version 2.9: (Pavel Krc, Jaroslav Resler, ICS, Prague)
213!   added calculation of the MRT inside the RTM module
214!   MRT fluxes are consequently used in the new biometeorology module
215!   for calculation of biological indices (MRT, PET)
216!   Fixes of v. 2.5 and SVN trunk:
217!    - proper initialization of rad_net_l
218!    - make arrays nsurfs and surfstart TARGET to prevent some MPI problems
219!    - initialization of arrays used in MPI one-sided operation as 1-D arrays
220!      to prevent problems with some MPI/compiler combinations
221!    - fix indexing of target displacement in subroutine request_itarget to
222!      consider nzub
223!    - fix LAD dimmension range in PCB calculation
224!    - check ierr in all MPI calls
225!    - use proper per-gridbox sky and diffuse irradiance
226!    - fix shading for reflected irradiance
227!    - clear away the residuals of "atmospheric surfaces" implementation
228!    - fix rounding bug in raytrace_2d introduced in SVN trunk
229! - New RTM version 2.5: (Pavel Krc, Jaroslav Resler, ICS, Prague)
230!   can use angular discretization for all SVF
231!   (i.e. reflected and emitted radiation in addition to direct and diffuse),
232!   allowing for much better scaling wih high resoltion and/or complex terrain
233! - Unite array grow factors
234! - Fix slightly shifted terrain height in raytrace_2d
235! - Use more efficient MPI_Win_allocate for reverse gridsurf index
236! - Fix random MPI RMA bugs on Intel compilers
237! - Fix approx. double plant canopy sink values for reflected radiation
238! - Fix mostly missing plant canopy sinks for direct radiation
239! - Fix discretization errors for plant canopy sink in diffuse radiation
240! - Fix rounding errors in raytrace_2d
241!
242! 3274 2018-09-24 15:42:55Z knoop
243! Modularization of all bulk cloud physics code components
244!
245! 3272 2018-09-24 10:16:32Z suehring
246! - split direct and diffusion shortwave radiation using RRTMG rather than using
247!   calc_diffusion_radiation, in case of RRTMG
248! - removed the namelist variable split_diffusion_radiation. Now splitting depends
249!   on the choise of radiation radiation scheme
250! - removed calculating the rdiation flux for surfaces at the radiation scheme
251!   in case of using RTM since it will be calculated anyway in the radiation
252!   interaction routine.
253! - set SW radiation flux for surfaces to zero at night in case of no RTM is used
254! - precalculate the unit vector yxdir of ray direction to avoid the temporarly
255!   array allocation during the subroutine call
256! - fixed a bug in calculating the max number of boxes ray can cross in the domain
257!
258! 3264 2018-09-20 13:54:11Z moh.hefny
259! Bugfix in raytrace_2d calls
260!
261! 3248 2018-09-14 09:42:06Z sward
262! Minor formating changes
263!
264! 3246 2018-09-13 15:14:50Z sward
265! Added error handling for input namelist via parin_fail_message
266!
267! 3241 2018-09-12 15:02:00Z raasch
268! unused variables removed or commented
269!
270! 3233 2018-09-07 13:21:24Z schwenkel
271! Adapted for the use of cloud_droplets
272!
273! 3230 2018-09-05 09:29:05Z schwenkel
274! Bugfix in radiation_constant_surf: changed (10.0 - emissivity_urb) to
275! (1.0 - emissivity_urb)
276!
277! 3226 2018-08-31 12:27:09Z suehring
278! Bugfixes in calculation of sky-view factors and canopy-sink factors.
279!
280! 3186 2018-07-30 17:07:14Z suehring
281! Remove print statement
282!
283! 3180 2018-07-27 11:00:56Z suehring
284! Revise concept for calculation of effective radiative temperature and mapping
285! of radiative heating
286!
287! 3175 2018-07-26 14:07:38Z suehring
288! Bugfix for commit 3172
289!
290! 3173 2018-07-26 12:55:23Z suehring
291! Revise output of surface radiation quantities in case of overhanging
292! structures
293!
294! 3172 2018-07-26 12:06:06Z suehring
295! Bugfixes:
296!  - temporal work-around for calculation of effective radiative surface
297!    temperature
298!  - prevent positive solar radiation during nighttime
299!
300! 3170 2018-07-25 15:19:37Z suehring
301! Bugfix, map signle-column radiation forcing profiles on top of any topography
302!
303! 3156 2018-07-19 16:30:54Z knoop
304! Bugfix: replaced usage of the pt array with the surf%pt_surface array
305!
306! 3137 2018-07-17 06:44:21Z maronga
307! String length for trace_names fixed
308!
309! 3127 2018-07-15 08:01:25Z maronga
310! A few pavement parameters updated.
311!
312! 3123 2018-07-12 16:21:53Z suehring
313! Correct working precision for INTEGER number
314!
315! 3122 2018-07-11 21:46:41Z maronga
316! Bugfix: maximum distance for raytracing was set to  -999 m by default,
317! effectively switching off all surface reflections when max_raytracing_dist
318! was not explicitly set in namelist
319!
320! 3117 2018-07-11 09:59:11Z maronga
321! Bugfix: water vapor was not transfered to RRTMG when bulk_cloud_model = .F.
322! Bugfix: changed the calculation of RRTMG boundary conditions (Mohamed Salim)
323! Bugfix: dry residual atmosphere is replaced by standard RRTMG atmosphere
324!
325! 3116 2018-07-10 14:31:58Z suehring
326! Output of long/shortwave radiation at surface
327!
328! 3107 2018-07-06 15:55:51Z suehring
329! Bugfix, missing index for dz
330!
331! 3066 2018-06-12 08:55:55Z Giersch
332! Error message revised
333!
334! 3065 2018-06-12 07:03:02Z Giersch
335! dz was replaced by dz(1), error message concerning vertical stretching was
336! added 
337!
338! 3049 2018-05-29 13:52:36Z Giersch
339! Error messages revised
340!
341! 3045 2018-05-28 07:55:41Z Giersch
342! Error message revised
343!
344! 3026 2018-05-22 10:30:53Z schwenkel
345! Changed the name specific humidity to mixing ratio, since we are computing
346! mixing ratios.
347!
348! 3016 2018-05-09 10:53:37Z Giersch
349! Revised structure of reading svf data according to PALM coding standard:
350! svf_code_field/len and fsvf removed, error messages PA0493 and PA0494 added,
351! allocation status of output arrays checked.
352!
353! 3014 2018-05-09 08:42:38Z maronga
354! Introduced plant canopy height similar to urban canopy height to limit
355! the memory requirement to allocate lad.
356! Deactivated automatic setting of minimum raytracing distance.
357!
358! 3004 2018-04-27 12:33:25Z Giersch
359! Further allocation checks implemented (averaged data will be assigned to fill
360! values if no allocation happened so far)
361!
362! 2995 2018-04-19 12:13:16Z Giersch
363! IF-statement in radiation_init removed so that the calculation of radiative
364! fluxes at model start is done in any case, bugfix in
365! radiation_presimulate_solar_pos (end_time is the sum of end_time and the
366! spinup_time specified in the p3d_file ), list of variables/fields that have
367! to be written out or read in case of restarts has been extended
368!
369! 2977 2018-04-17 10:27:57Z kanani
370! Implement changes from branch radiation (r2948-2971) with minor modifications,
371! plus some formatting.
372! (moh.hefny):
373! - replaced plant_canopy by npcbl to check tree existence to avoid weird
374!   allocation of related arrays (after domain decomposition some domains
375!   contains no trees although plant_canopy (global parameter) is still TRUE).
376! - added a namelist parameter to force RTM settings
377! - enabled the option to switch radiation reflections off
378! - renamed surf_reflections to surface_reflections
379! - removed average_radiation flag from the namelist (now it is implicitly set
380!   in init_3d_model according to RTM)
381! - edited read and write sky view factors and CSF routines to account for
382!   the sub-domains which may not contain any of them
383!
384! 2967 2018-04-13 11:22:08Z raasch
385! bugfix: missing parallel cpp-directives added
386!
387! 2964 2018-04-12 16:04:03Z Giersch
388! Error message PA0491 has been introduced which could be previously found in
389! check_open. The variable numprocs_previous_run is only known in case of
390! initializing_actions == read_restart_data
391!
392! 2963 2018-04-12 14:47:44Z suehring
393! - Introduce index for vegetation/wall, pavement/green-wall and water/window
394!   surfaces, for clearer access of surface fraction, albedo, emissivity, etc. .
395! - Minor bugfix in initialization of albedo for window surfaces
396!
397! 2944 2018-04-03 16:20:18Z suehring
398! Fixed bad commit
399!
400! 2943 2018-04-03 16:17:10Z suehring
401! No read of nsurfl from SVF file since it is calculated in
402! radiation_interaction_init,
403! allocation of arrays in radiation_read_svf only if not yet allocated,
404! update of 2920 revision comment.
405!
406! 2932 2018-03-26 09:39:22Z maronga
407! renamed radiation_par to radiation_parameters
408!
409! 2930 2018-03-23 16:30:46Z suehring
410! Remove default surfaces from radiation model, does not make much sense to
411! apply radiation model without energy-balance solvers; Further, add check for
412! this.
413!
414! 2920 2018-03-22 11:22:01Z kanani
415! - Bugfix: Initialize pcbl array (=-1)
416! RTM version 2.0 (Jaroslav Resler, Pavel Krc, Mohamed Salim):
417! - new major version of radiation interactions
418! - substantially enhanced performance and scalability
419! - processing of direct and diffuse solar radiation separated from reflected
420!   radiation, removed virtual surfaces
421! - new type of sky discretization by azimuth and elevation angles
422! - diffuse radiation processed cumulatively using sky view factor
423! - used precalculated apparent solar positions for direct irradiance
424! - added new 2D raytracing process for processing whole vertical column at once
425!   to increase memory efficiency and decrease number of MPI RMA operations
426! - enabled limiting the number of view factors between surfaces by the distance
427!   and value
428! - fixing issues induced by transferring radiation interactions from
429!   urban_surface_mod to radiation_mod
430! - bugfixes and other minor enhancements
431!
432! 2906 2018-03-19 08:56:40Z Giersch
433! NAMELIST paramter read/write_svf_on_init have been removed, functions
434! check_open and close_file are used now for opening/closing files related to
435! svf data, adjusted unit number and error numbers
436!
437! 2894 2018-03-15 09:17:58Z Giersch
438! Calculations of the index range of the subdomain on file which overlaps with
439! the current subdomain are already done in read_restart_data_mod
440! radiation_read_restart_data was renamed to radiation_rrd_local and
441! radiation_last_actions was renamed to radiation_wrd_local, variable named
442! found has been introduced for checking if restart data was found, reading
443! of restart strings has been moved completely to read_restart_data_mod,
444! radiation_rrd_local is already inside the overlap loop programmed in
445! read_restart_data_mod, the marker *** end rad *** is not necessary anymore,
446! strings and their respective lengths are written out and read now in case of
447! restart runs to get rid of prescribed character lengths (Giersch)
448!
449! 2809 2018-02-15 09:55:58Z suehring
450! Bugfix for gfortran: Replace the function C_SIZEOF with STORAGE_SIZE
451!
452! 2753 2018-01-16 14:16:49Z suehring
453! Tile approach for spectral albedo implemented.
454!
455! 2746 2018-01-15 12:06:04Z suehring
456! Move flag plant canopy to modules
457!
458! 2724 2018-01-05 12:12:38Z maronga
459! Set default of average_radiation to .FALSE.
460!
461! 2723 2018-01-05 09:27:03Z maronga
462! Bugfix in calculation of rad_lw_out (clear-sky). First grid level was used
463! instead of the surface value
464!
465! 2718 2018-01-02 08:49:38Z maronga
466! Corrected "Former revisions" section
467!
468! 2707 2017-12-18 18:34:46Z suehring
469! Changes from last commit documented
470!
471! 2706 2017-12-18 18:33:49Z suehring
472! Bugfix, in average radiation case calculate exner function before using it.
473!
474! 2701 2017-12-15 15:40:50Z suehring
475! Changes from last commit documented
476!
477! 2698 2017-12-14 18:46:24Z suehring
478! Bugfix in get_topography_top_index
479!
480! 2696 2017-12-14 17:12:51Z kanani
481! - Change in file header (GPL part)
482! - Improved reading/writing of SVF from/to file (BM)
483! - Bugfixes concerning RRTMG as well as average_radiation options (M. Salim)
484! - Revised initialization of surface albedo and some minor bugfixes (MS)
485! - Update net radiation after running radiation interaction routine (MS)
486! - Revisions from M Salim included
487! - Adjustment to topography and surface structure (MS)
488! - Initialization of albedo and surface emissivity via input file (MS)
489! - albedo_pars extended (MS)
490!
491! 2604 2017-11-06 13:29:00Z schwenkel
492! bugfix for calculation of effective radius using morrison microphysics
493!
494! 2601 2017-11-02 16:22:46Z scharf
495! added emissivity to namelist
496!
497! 2575 2017-10-24 09:57:58Z maronga
498! Bugfix: calculation of shortwave and longwave albedos for RRTMG swapped
499!
500! 2547 2017-10-16 12:41:56Z schwenkel
501! extended by cloud_droplets option, minor bugfix and correct calculation of
502! cloud droplet number concentration
503!
504! 2544 2017-10-13 18:09:32Z maronga
505! Moved date and time quantitis to separate module date_and_time_mod
506!
507! 2512 2017-10-04 08:26:59Z raasch
508! upper bounds of cross section and 3d output changed from nx+1,ny+1 to nx,ny
509! no output of ghost layer data
510!
511! 2504 2017-09-27 10:36:13Z maronga
512! Updates pavement types and albedo parameters
513!
514! 2328 2017-08-03 12:34:22Z maronga
515! Emissivity can now be set individually for each pixel.
516! Albedo type can be inferred from land surface model.
517! Added default albedo type for bare soil
518!
519! 2318 2017-07-20 17:27:44Z suehring
520! Get topography top index via Function call
521!
522! 2317 2017-07-20 17:27:19Z suehring
523! Improved syntax layout
524!
525! 2298 2017-06-29 09:28:18Z raasch
526! type of write_binary changed from CHARACTER to LOGICAL
527!
528! 2296 2017-06-28 07:53:56Z maronga
529! Added output of rad_sw_out for radiation_scheme = 'constant'
530!
531! 2270 2017-06-09 12:18:47Z maronga
532! Numbering changed (2 timeseries removed)
533!
534! 2249 2017-06-06 13:58:01Z sward
535! Allow for RRTMG runs without humidity/cloud physics
536!
537! 2248 2017-06-06 13:52:54Z sward
538! Error no changed
539!
540! 2233 2017-05-30 18:08:54Z suehring
541!
542! 2232 2017-05-30 17:47:52Z suehring
543! Adjustments to new topography concept
544! Bugfix in read restart
545!
546! 2200 2017-04-11 11:37:51Z suehring
547! Bugfix in call of exchange_horiz_2d and read restart data
548!
549! 2163 2017-03-01 13:23:15Z schwenkel
550! Bugfix in radiation_check_data_output
551!
552! 2157 2017-02-22 15:10:35Z suehring
553! Bugfix in read_restart data
554!
555! 2011 2016-09-19 17:29:57Z kanani
556! Removed CALL of auxiliary SUBROUTINE get_usm_info,
557! flag urban_surface is now defined in module control_parameters.
558!
559! 2007 2016-08-24 15:47:17Z kanani
560! Added calculation of solar directional vector for new urban surface
561! model,
562! accounted for urban_surface model in radiation_check_parameters,
563! correction of comments for zenith angle.
564!
565! 2000 2016-08-20 18:09:15Z knoop
566! Forced header and separation lines into 80 columns
567!
568! 1976 2016-07-27 13:28:04Z maronga
569! Output of 2D/3D/masked data is now directly done within this module. The
570! radiation schemes have been simplified for better usability so that
571! rad_lw_in, rad_lw_out, rad_sw_in, and rad_sw_out are available independent of
572! the radiation code used.
573!
574! 1856 2016-04-13 12:56:17Z maronga
575! Bugfix: allocation of rad_lw_out for radiation_scheme = 'clear-sky'
576!
577! 1853 2016-04-11 09:00:35Z maronga
578! Added routine for radiation_scheme = constant.
579
580! 1849 2016-04-08 11:33:18Z hoffmann
581! Adapted for modularization of microphysics
582!
583! 1826 2016-04-07 12:01:39Z maronga
584! Further modularization.
585!
586! 1788 2016-03-10 11:01:04Z maronga
587! Added new albedo class for pavements / roads.
588!
589! 1783 2016-03-06 18:36:17Z raasch
590! palm-netcdf-module removed in order to avoid a circular module dependency,
591! netcdf-variables moved to netcdf-module, new routine netcdf_handle_error_rad
592! added
593!
594! 1757 2016-02-22 15:49:32Z maronga
595! Added parameter unscheduled_radiation_calls. Bugfix: interpolation of sounding
596! profiles for pressure and temperature above the LES domain.
597!
598! 1709 2015-11-04 14:47:01Z maronga
599! Bugfix: set initial value for rrtm_lwuflx_dt to zero, small formatting
600! corrections
601!
602! 1701 2015-11-02 07:43:04Z maronga
603! Bugfixes: wrong index for output of timeseries, setting of nz_snd_end
604!
605! 1691 2015-10-26 16:17:44Z maronga
606! Added option for spin-up runs without radiation (skip_time_do_radiation). Bugfix
607! in calculation of pressure profiles. Bugfix in calculation of trace gas profiles.
608! Added output of radiative heating rates.
609!
610! 1682 2015-10-07 23:56:08Z knoop
611! Code annotations made doxygen readable
612!
613! 1606 2015-06-29 10:43:37Z maronga
614! Added preprocessor directive __netcdf to allow for compiling without netCDF.
615! Note, however, that RRTMG cannot be used without netCDF.
616!
617! 1590 2015-05-08 13:56:27Z maronga
618! Bugfix: definition of character strings requires same length for all elements
619!
620! 1587 2015-05-04 14:19:01Z maronga
621! Added albedo class for snow
622!
623! 1585 2015-04-30 07:05:52Z maronga
624! Added support for RRTMG
625!
626! 1571 2015-03-12 16:12:49Z maronga
627! Added missing KIND attribute. Removed upper-case variable names
628!
629! 1551 2015-03-03 14:18:16Z maronga
630! Added support for data output. Various variables have been renamed. Added
631! interface for different radiation schemes (currently: clear-sky, constant, and
632! RRTM (not yet implemented).
633!
634! 1496 2014-12-02 17:25:50Z maronga
635! Initial revision
636!
637!
638! Description:
639! ------------
640!> Radiation models and interfaces
641!> @todo Replace dz(1) appropriatly to account for grid stretching
642!> @todo move variable definitions used in radiation_init only to the subroutine
643!>       as they are no longer required after initialization.
644!> @todo Output of full column vertical profiles used in RRTMG
645!> @todo Output of other rrtm arrays (such as volume mixing ratios)
646!> @todo Check for mis-used NINT() calls in raytrace_2d
647!>       RESULT: Original was correct (carefully verified formula), the change
648!>               to INT broke raytracing      -- P. Krc
649!> @todo Optimize radiation_tendency routines
650!>
651!> @note Many variables have a leading dummy dimension (0:0) in order to
652!>       match the assume-size shape expected by the RRTMG model.
653!------------------------------------------------------------------------------!
654 MODULE radiation_model_mod
655 
656    USE arrays_3d,                                                             &
657        ONLY:  dzw, hyp, nc, pt, p, q, ql, u, v, w, zu, zw, exner, d_exner
658
659    USE basic_constants_and_equations_mod,                                     &
660        ONLY:  c_p, g, lv_d_cp, l_v, pi, r_d, rho_l, solar_constant, sigma_sb, &
661               barometric_formula
662
663    USE calc_mean_profile_mod,                                                 &
664        ONLY:  calc_mean_profile
665
666    USE control_parameters,                                                    &
667        ONLY:  cloud_droplets, coupling_char,                                  &
668               debug_output, debug_output_timestep, debug_string,              &
669               dz, dt_spinup, end_time,                                        &
670               humidity,                                                       &
671               initializing_actions, io_blocks, io_group,                      &
672               land_surface, large_scale_forcing,                              &
673               latitude, longitude, lsf_surf,                                  &
674               message_string, plant_canopy, pt_surface,                       &
675               rho_surface, simulated_time, spinup_time, surface_pressure,     &
676               read_svf, write_svf,                                            &
677               time_since_reference_point, urban_surface, varnamelength
678
679    USE cpulog,                                                                &
680        ONLY:  cpu_log, log_point, log_point_s
681
682    USE grid_variables,                                                        &
683         ONLY:  ddx, ddy, dx, dy 
684
685    USE date_and_time_mod,                                                     &
686        ONLY:  calc_date_and_time, d_hours_day, d_seconds_hour, d_seconds_year,&
687               day_of_year, d_seconds_year, day_of_month, day_of_year_init,    &
688               init_date_and_time, month_of_year, time_utc_init, time_utc
689
690    USE indices,                                                               &
691        ONLY:  nnx, nny, nx, nxl, nxlg, nxr, nxrg, ny, nyn, nyng, nys, nysg,   &
692               nzb, nzt, topo_top_ind
693
694    USE, INTRINSIC :: iso_c_binding
695
696    USE kinds
697
698    USE bulk_cloud_model_mod,                                                  &
699        ONLY:  bulk_cloud_model, microphysics_morrison, na_init, nc_const, sigma_gc
700
701#if defined ( __netcdf )
702    USE NETCDF
703#endif
704
705    USE netcdf_data_input_mod,                                                 &
706        ONLY:  albedo_type_f, albedo_pars_f, building_type_f, pavement_type_f, &
707               vegetation_type_f, water_type_f
708
709    USE plant_canopy_model_mod,                                                &
710        ONLY:  lad_s, pc_heating_rate, pc_transpiration_rate, pc_latent_rate,  &
711               plant_canopy_transpiration, pcm_calc_transpiration_rate
712
713    USE pegrid
714
715#if defined ( __rrtmg )
716    USE parrrsw,                                                               &
717        ONLY:  naerec, nbndsw
718
719    USE parrrtm,                                                               &
720        ONLY:  nbndlw
721
722    USE rrtmg_lw_init,                                                         &
723        ONLY:  rrtmg_lw_ini
724
725    USE rrtmg_sw_init,                                                         &
726        ONLY:  rrtmg_sw_ini
727
728    USE rrtmg_lw_rad,                                                          &
729        ONLY:  rrtmg_lw
730
731    USE rrtmg_sw_rad,                                                          &
732        ONLY:  rrtmg_sw
733#endif
734    USE statistics,                                                            &
735        ONLY:  hom
736
737    USE surface_mod,                                                           &
738        ONLY:  ind_pav_green, ind_veg_wall, ind_wat_win,                       &
739               surf_lsm_h, surf_lsm_v, surf_type, surf_usm_h, surf_usm_v,      &
740               vertical_surfaces_exist
741
742    IMPLICIT NONE
743
744    CHARACTER(10) :: radiation_scheme = 'clear-sky' ! 'constant', 'clear-sky', or 'rrtmg'
745
746!
747!-- Predefined Land surface classes (albedo_type) after Briegleb (1992)
748    CHARACTER(37), DIMENSION(0:33), PARAMETER :: albedo_type_name = (/      &
749                                   'user defined                         ', & !  0
750                                   'ocean                                ', & !  1
751                                   'mixed farming, tall grassland        ', & !  2
752                                   'tall/medium grassland                ', & !  3
753                                   'evergreen shrubland                  ', & !  4
754                                   'short grassland/meadow/shrubland     ', & !  5
755                                   'evergreen needleleaf forest          ', & !  6
756                                   'mixed deciduous evergreen forest     ', & !  7
757                                   'deciduous forest                     ', & !  8
758                                   'tropical evergreen broadleaved forest', & !  9
759                                   'medium/tall grassland/woodland       ', & ! 10
760                                   'desert, sandy                        ', & ! 11
761                                   'desert, rocky                        ', & ! 12
762                                   'tundra                               ', & ! 13
763                                   'land ice                             ', & ! 14
764                                   'sea ice                              ', & ! 15
765                                   'snow                                 ', & ! 16
766                                   'bare soil                            ', & ! 17
767                                   'asphalt/concrete mix                 ', & ! 18
768                                   'asphalt (asphalt concrete)           ', & ! 19
769                                   'concrete (Portland concrete)         ', & ! 20
770                                   'sett                                 ', & ! 21
771                                   'paving stones                        ', & ! 22
772                                   'cobblestone                          ', & ! 23
773                                   'metal                                ', & ! 24
774                                   'wood                                 ', & ! 25
775                                   'gravel                               ', & ! 26
776                                   'fine gravel                          ', & ! 27
777                                   'pebblestone                          ', & ! 28
778                                   'woodchips                            ', & ! 29
779                                   'tartan (sports)                      ', & ! 30
780                                   'artifical turf (sports)              ', & ! 31
781                                   'clay (sports)                        ', & ! 32
782                                   'building (dummy)                     '  & ! 33
783                                                         /)
784
785    INTEGER(iwp) :: albedo_type  = 9999999_iwp, &     !< Albedo surface type
786                    dots_rad     = 0_iwp              !< starting index for timeseries output
787
788    LOGICAL ::  unscheduled_radiation_calls = .TRUE., & !< flag parameter indicating whether additional calls of the radiation code are allowed
789                constant_albedo = .FALSE.,            & !< flag parameter indicating whether the albedo may change depending on zenith
790                force_radiation_call = .FALSE.,       & !< flag parameter for unscheduled radiation calls
791                lw_radiation = .TRUE.,                & !< flag parameter indicating whether longwave radiation shall be calculated
792                radiation = .FALSE.,                  & !< flag parameter indicating whether the radiation model is used
793                sun_up    = .TRUE.,                   & !< flag parameter indicating whether the sun is up or down
794                sw_radiation = .TRUE.,                & !< flag parameter indicating whether shortwave radiation shall be calculated
795                sun_direction = .FALSE.,              & !< flag parameter indicating whether solar direction shall be calculated
796                average_radiation = .FALSE.,          & !< flag to set the calculation of radiation averaging for the domain
797                radiation_interactions = .FALSE.,     & !< flag to activiate RTM (TRUE only if vertical urban/land surface and trees exist)
798                surface_reflections = .TRUE.,         & !< flag to switch the calculation of radiation interaction between surfaces.
799                                                        !< When it switched off, only the effect of buildings and trees shadow
800                                                        !< will be considered. However fewer SVFs are expected.
801                radiation_interactions_on = .TRUE.      !< namelist flag to force RTM activiation regardless to vertical urban/land surface and trees
802
803    REAL(wp) :: albedo = 9999999.9_wp,           & !< NAMELIST alpha
804                albedo_lw_dif = 9999999.9_wp,    & !< NAMELIST aldif
805                albedo_lw_dir = 9999999.9_wp,    & !< NAMELIST aldir
806                albedo_sw_dif = 9999999.9_wp,    & !< NAMELIST asdif
807                albedo_sw_dir = 9999999.9_wp,    & !< NAMELIST asdir
808                decl_1,                          & !< declination coef. 1
809                decl_2,                          & !< declination coef. 2
810                decl_3,                          & !< declination coef. 3
811                dt_radiation = 0.0_wp,           & !< radiation model timestep
812                emissivity = 9999999.9_wp,       & !< NAMELIST surface emissivity
813                lon = 0.0_wp,                    & !< longitude in radians
814                lat = 0.0_wp,                    & !< latitude in radians
815                net_radiation = 0.0_wp,          & !< net radiation at surface
816                skip_time_do_radiation = 0.0_wp, & !< Radiation model is not called before this time
817                sky_trans,                       & !< sky transmissivity
818                time_radiation = 0.0_wp            !< time since last call of radiation code
819
820
821    REAL(wp) ::  cos_zenith        !< cosine of solar zenith angle, also z-coordinate of solar unit vector
822    REAL(wp) ::  sun_dir_lat       !< y-coordinate of solar unit vector
823    REAL(wp) ::  sun_dir_lon       !< x-coordinate of solar unit vector
824
825    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_net_av       !< average of net radiation (rad_net) at surface
826    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_lw_in_xy_av  !< average of incoming longwave radiation at surface
827    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_lw_out_xy_av !< average of outgoing longwave radiation at surface
828    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_sw_in_xy_av  !< average of incoming shortwave radiation at surface
829    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_sw_out_xy_av !< average of outgoing shortwave radiation at surface
830
831    REAL(wp), PARAMETER :: emissivity_atm_clsky = 0.8_wp       !< emissivity of the clear-sky atmosphere
832!
833!-- Land surface albedos for solar zenith angle of 60degree after Briegleb (1992)     
834!-- (broadband, longwave, shortwave ):   bb,      lw,      sw,
835    REAL(wp), DIMENSION(0:2,1:33), PARAMETER :: albedo_pars = RESHAPE( (/& 
836                                   0.06_wp, 0.06_wp, 0.06_wp,            & !  1
837                                   0.19_wp, 0.28_wp, 0.09_wp,            & !  2
838                                   0.23_wp, 0.33_wp, 0.11_wp,            & !  3
839                                   0.23_wp, 0.33_wp, 0.11_wp,            & !  4
840                                   0.25_wp, 0.34_wp, 0.14_wp,            & !  5
841                                   0.14_wp, 0.22_wp, 0.06_wp,            & !  6
842                                   0.17_wp, 0.27_wp, 0.06_wp,            & !  7
843                                   0.19_wp, 0.31_wp, 0.06_wp,            & !  8
844                                   0.14_wp, 0.22_wp, 0.06_wp,            & !  9
845                                   0.18_wp, 0.28_wp, 0.06_wp,            & ! 10
846                                   0.43_wp, 0.51_wp, 0.35_wp,            & ! 11
847                                   0.32_wp, 0.40_wp, 0.24_wp,            & ! 12
848                                   0.19_wp, 0.27_wp, 0.10_wp,            & ! 13
849                                   0.77_wp, 0.65_wp, 0.90_wp,            & ! 14
850                                   0.77_wp, 0.65_wp, 0.90_wp,            & ! 15
851                                   0.82_wp, 0.70_wp, 0.95_wp,            & ! 16
852                                   0.08_wp, 0.08_wp, 0.08_wp,            & ! 17
853                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 18
854                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 19
855                                   0.30_wp, 0.30_wp, 0.30_wp,            & ! 20
856                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 21
857                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 22
858                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 23
859                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 24
860                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 25
861                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 26
862                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 27
863                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 28
864                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 29
865                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 30
866                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 31
867                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 32
868                                   0.17_wp, 0.17_wp, 0.17_wp             & ! 33
869                                 /), (/ 3, 33 /) )
870
871    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE, TARGET :: &
872                        rad_lw_cs_hr,                  & !< longwave clear sky radiation heating rate (K/s)
873                        rad_lw_cs_hr_av,               & !< average of rad_lw_cs_hr
874                        rad_lw_hr,                     & !< longwave radiation heating rate (K/s)
875                        rad_lw_hr_av,                  & !< average of rad_sw_hr
876                        rad_lw_in,                     & !< incoming longwave radiation (W/m2)
877                        rad_lw_in_av,                  & !< average of rad_lw_in
878                        rad_lw_out,                    & !< outgoing longwave radiation (W/m2)
879                        rad_lw_out_av,                 & !< average of rad_lw_out
880                        rad_sw_cs_hr,                  & !< shortwave clear sky radiation heating rate (K/s)
881                        rad_sw_cs_hr_av,               & !< average of rad_sw_cs_hr
882                        rad_sw_hr,                     & !< shortwave radiation heating rate (K/s)
883                        rad_sw_hr_av,                  & !< average of rad_sw_hr
884                        rad_sw_in,                     & !< incoming shortwave radiation (W/m2)
885                        rad_sw_in_av,                  & !< average of rad_sw_in
886                        rad_sw_out,                    & !< outgoing shortwave radiation (W/m2)
887                        rad_sw_out_av                    !< average of rad_sw_out
888
889
890!
891!-- Variables and parameters used in RRTMG only
892#if defined ( __rrtmg )
893    CHARACTER(LEN=12) :: rrtm_input_file = "RAD_SND_DATA" !< name of the NetCDF input file (sounding data)
894
895
896!
897!-- Flag parameters to be passed to RRTMG (should not be changed until ice phase in clouds is allowed)
898    INTEGER(iwp), PARAMETER :: rrtm_idrv     = 1, & !< flag for longwave upward flux calculation option (0,1)
899                               rrtm_inflglw  = 2, & !< flag for lw cloud optical properties (0,1,2)
900                               rrtm_iceflglw = 0, & !< flag for lw ice particle specifications (0,1,2,3)
901                               rrtm_liqflglw = 1, & !< flag for lw liquid droplet specifications
902                               rrtm_inflgsw  = 2, & !< flag for sw cloud optical properties (0,1,2)
903                               rrtm_iceflgsw = 0, & !< flag for sw ice particle specifications (0,1,2,3)
904                               rrtm_liqflgsw = 1    !< flag for sw liquid droplet specifications
905
906!
907!-- The following variables should be only changed with care, as this will
908!-- require further setting of some variables, which is currently not
909!-- implemented (aerosols, ice phase).
910    INTEGER(iwp) :: nzt_rad,           & !< upper vertical limit for radiation calculations
911                    rrtm_icld = 0,     & !< cloud flag (0: clear sky column, 1: cloudy column)
912                    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)
913
914    INTEGER(iwp) :: nc_stat !< local variable for storin the result of netCDF calls for error message handling
915
916    LOGICAL :: snd_exists = .FALSE.      !< flag parameter to check whether a user-defined input files exists
917    LOGICAL :: sw_exists = .FALSE.       !< flag parameter to check whether that required rrtmg sw file exists
918    LOGICAL :: lw_exists = .FALSE.       !< flag parameter to check whether that required rrtmg lw file exists
919
920
921    REAL(wp), PARAMETER :: mol_mass_air_d_wv = 1.607793_wp !< molecular weight dry air / water vapor
922
923    REAL(wp), DIMENSION(:), ALLOCATABLE :: hyp_snd,     & !< hypostatic pressure from sounding data (hPa)
924                                           rrtm_tsfc,   & !< dummy array for storing surface temperature
925                                           t_snd          !< actual temperature from sounding data (hPa)
926
927    REAL(wp), DIMENSION(:,:), ALLOCATABLE :: rrtm_ccl4vmr,   & !< CCL4 volume mixing ratio (g/mol)
928                                             rrtm_cfc11vmr,  & !< CFC11 volume mixing ratio (g/mol)
929                                             rrtm_cfc12vmr,  & !< CFC12 volume mixing ratio (g/mol)
930                                             rrtm_cfc22vmr,  & !< CFC22 volume mixing ratio (g/mol)
931                                             rrtm_ch4vmr,    & !< CH4 volume mixing ratio
932                                             rrtm_cicewp,    & !< in-cloud ice water path (g/m2)
933                                             rrtm_cldfr,     & !< cloud fraction (0,1)
934                                             rrtm_cliqwp,    & !< in-cloud liquid water path (g/m2)
935                                             rrtm_co2vmr,    & !< CO2 volume mixing ratio (g/mol)
936                                             rrtm_emis,      & !< surface emissivity (0-1) 
937                                             rrtm_h2ovmr,    & !< H2O volume mixing ratio
938                                             rrtm_n2ovmr,    & !< N2O volume mixing ratio
939                                             rrtm_o2vmr,     & !< O2 volume mixing ratio
940                                             rrtm_o3vmr,     & !< O3 volume mixing ratio
941                                             rrtm_play,      & !< pressure layers (hPa, zu-grid)
942                                             rrtm_plev,      & !< pressure layers (hPa, zw-grid)
943                                             rrtm_reice,     & !< cloud ice effective radius (microns)
944                                             rrtm_reliq,     & !< cloud water drop effective radius (microns)
945                                             rrtm_tlay,      & !< actual temperature (K, zu-grid)
946                                             rrtm_tlev,      & !< actual temperature (K, zw-grid)
947                                             rrtm_lwdflx,    & !< RRTM output of incoming longwave radiation flux (W/m2)
948                                             rrtm_lwdflxc,   & !< RRTM output of outgoing clear sky longwave radiation flux (W/m2)
949                                             rrtm_lwuflx,    & !< RRTM output of outgoing longwave radiation flux (W/m2)
950                                             rrtm_lwuflxc,   & !< RRTM output of incoming clear sky longwave radiation flux (W/m2)
951                                             rrtm_lwuflx_dt, & !< RRTM output of incoming clear sky longwave radiation flux (W/m2)
952                                             rrtm_lwuflxc_dt,& !< RRTM output of outgoing clear sky longwave radiation flux (W/m2)
953                                             rrtm_lwhr,      & !< RRTM output of longwave radiation heating rate (K/d)
954                                             rrtm_lwhrc,     & !< RRTM output of incoming longwave clear sky radiation heating rate (K/d)
955                                             rrtm_swdflx,    & !< RRTM output of incoming shortwave radiation flux (W/m2)
956                                             rrtm_swdflxc,   & !< RRTM output of outgoing clear sky shortwave radiation flux (W/m2)
957                                             rrtm_swuflx,    & !< RRTM output of outgoing shortwave radiation flux (W/m2)
958                                             rrtm_swuflxc,   & !< RRTM output of incoming clear sky shortwave radiation flux (W/m2)
959                                             rrtm_swhr,      & !< RRTM output of shortwave radiation heating rate (K/d)
960                                             rrtm_swhrc,     & !< RRTM output of incoming shortwave clear sky radiation heating rate (K/d)
961                                             rrtm_dirdflux,  & !< RRTM output of incoming direct shortwave (W/m2)
962                                             rrtm_difdflux     !< RRTM output of incoming diffuse shortwave (W/m2)
963
964    REAL(wp), DIMENSION(1) ::                rrtm_aldif,     & !< surface albedo for longwave diffuse radiation
965                                             rrtm_aldir,     & !< surface albedo for longwave direct radiation
966                                             rrtm_asdif,     & !< surface albedo for shortwave diffuse radiation
967                                             rrtm_asdir        !< surface albedo for shortwave direct radiation
968
969!
970!-- Definition of arrays that are currently not used for calling RRTMG (due to setting of flag parameters)
971    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::  rad_lw_cs_in,   & !< incoming clear sky longwave radiation (W/m2) (not used)
972                                                rad_lw_cs_out,  & !< outgoing clear sky longwave radiation (W/m2) (not used)
973                                                rad_sw_cs_in,   & !< incoming clear sky shortwave radiation (W/m2) (not used)
974                                                rad_sw_cs_out,  & !< outgoing clear sky shortwave radiation (W/m2) (not used)
975                                                rrtm_lw_tauaer, & !< lw aerosol optical depth
976                                                rrtm_lw_taucld, & !< lw in-cloud optical depth
977                                                rrtm_sw_taucld, & !< sw in-cloud optical depth
978                                                rrtm_sw_ssacld, & !< sw in-cloud single scattering albedo
979                                                rrtm_sw_asmcld, & !< sw in-cloud asymmetry parameter
980                                                rrtm_sw_fsfcld, & !< sw in-cloud forward scattering fraction
981                                                rrtm_sw_tauaer, & !< sw aerosol optical depth
982                                                rrtm_sw_ssaaer, & !< sw aerosol single scattering albedo
983                                                rrtm_sw_asmaer, & !< sw aerosol asymmetry parameter
984                                                rrtm_sw_ecaer     !< sw aerosol optical detph at 0.55 microns (rrtm_iaer = 6 only)
985
986#endif
987!
988!-- Parameters of urban and land surface models
989    INTEGER(iwp)                                   ::  nz_urban                           !< number of layers of urban surface (will be calculated)
990    INTEGER(iwp)                                   ::  nz_plant                           !< number of layers of plant canopy (will be calculated)
991    INTEGER(iwp)                                   ::  nz_urban_b                         !< bottom layer of urban surface (will be calculated)
992    INTEGER(iwp)                                   ::  nz_urban_t                         !< top layer of urban surface (will be calculated)
993    INTEGER(iwp)                                   ::  nz_plant_t                         !< top layer of plant canopy (will be calculated)
994!-- parameters of urban and land surface models
995    INTEGER(iwp), PARAMETER                        ::  nzut_free = 3                      !< number of free layers above top of of topography
996    INTEGER(iwp), PARAMETER                        ::  ndsvf = 2                          !< number of dimensions of real values in SVF
997    INTEGER(iwp), PARAMETER                        ::  idsvf = 2                          !< number of dimensions of integer values in SVF
998    INTEGER(iwp), PARAMETER                        ::  ndcsf = 1                          !< number of dimensions of real values in CSF
999    INTEGER(iwp), PARAMETER                        ::  idcsf = 2                          !< number of dimensions of integer values in CSF
1000    INTEGER(iwp), PARAMETER                        ::  kdcsf = 4                          !< number of dimensions of integer values in CSF calculation array
1001    INTEGER(iwp), PARAMETER                        ::  id = 1                             !< position of d-index in surfl and surf
1002    INTEGER(iwp), PARAMETER                        ::  iz = 2                             !< position of k-index in surfl and surf
1003    INTEGER(iwp), PARAMETER                        ::  iy = 3                             !< position of j-index in surfl and surf
1004    INTEGER(iwp), PARAMETER                        ::  ix = 4                             !< position of i-index in surfl and surf
1005    INTEGER(iwp), PARAMETER                        ::  im = 5                             !< position of surface m-index in surfl and surf
1006    INTEGER(iwp), PARAMETER                        ::  nidx_surf = 5                      !< number of indices in surfl and surf
1007
1008    INTEGER(iwp), PARAMETER                        ::  nsurf_type = 10                    !< number of surf types incl. phys.(land+urban) & (atm.,sky,boundary) surfaces - 1
1009
1010    INTEGER(iwp), PARAMETER                        ::  iup_u    = 0                       !< 0 - index of urban upward surface (ground or roof)
1011    INTEGER(iwp), PARAMETER                        ::  idown_u  = 1                       !< 1 - index of urban downward surface (overhanging)
1012    INTEGER(iwp), PARAMETER                        ::  inorth_u = 2                       !< 2 - index of urban northward facing wall
1013    INTEGER(iwp), PARAMETER                        ::  isouth_u = 3                       !< 3 - index of urban southward facing wall
1014    INTEGER(iwp), PARAMETER                        ::  ieast_u  = 4                       !< 4 - index of urban eastward facing wall
1015    INTEGER(iwp), PARAMETER                        ::  iwest_u  = 5                       !< 5 - index of urban westward facing wall
1016
1017    INTEGER(iwp), PARAMETER                        ::  iup_l    = 6                       !< 6 - index of land upward surface (ground or roof)
1018    INTEGER(iwp), PARAMETER                        ::  inorth_l = 7                       !< 7 - index of land northward facing wall
1019    INTEGER(iwp), PARAMETER                        ::  isouth_l = 8                       !< 8 - index of land southward facing wall
1020    INTEGER(iwp), PARAMETER                        ::  ieast_l  = 9                       !< 9 - index of land eastward facing wall
1021    INTEGER(iwp), PARAMETER                        ::  iwest_l  = 10                      !< 10- index of land westward facing wall
1022
1023    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  idir = (/0, 0,0, 0,1,-1,0,0, 0,1,-1/)   !< surface normal direction x indices
1024    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  jdir = (/0, 0,1,-1,0, 0,0,1,-1,0, 0/)   !< surface normal direction y indices
1025    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  kdir = (/1,-1,0, 0,0, 0,1,0, 0,0, 0/)   !< surface normal direction z indices
1026    REAL(wp),     DIMENSION(0:nsurf_type)          :: facearea                            !< area of single face in respective
1027                                                                                          !< direction (will be calc'd)
1028
1029
1030!-- indices and sizes of urban and land surface models
1031    INTEGER(iwp)                                   ::  startland        !< start index of block of land and roof surfaces
1032    INTEGER(iwp)                                   ::  endland          !< end index of block of land and roof surfaces
1033    INTEGER(iwp)                                   ::  nlands           !< number of land and roof surfaces in local processor
1034    INTEGER(iwp)                                   ::  startwall        !< start index of block of wall surfaces
1035    INTEGER(iwp)                                   ::  endwall          !< end index of block of wall surfaces
1036    INTEGER(iwp)                                   ::  nwalls           !< number of wall surfaces in local processor
1037
1038!-- indices needed for RTM netcdf output subroutines
1039    INTEGER(iwp), PARAMETER                        :: nd = 5
1040    CHARACTER(LEN=6), DIMENSION(0:nd-1), PARAMETER :: dirname = (/ '_roof ', '_south', '_north', '_west ', '_east ' /)
1041    INTEGER(iwp), DIMENSION(0:nd-1), PARAMETER     :: dirint_u = (/ iup_u, isouth_u, inorth_u, iwest_u, ieast_u /)
1042    INTEGER(iwp), DIMENSION(0:nd-1), PARAMETER     :: dirint_l = (/ iup_l, isouth_l, inorth_l, iwest_l, ieast_l /)
1043    INTEGER(iwp), DIMENSION(0:nd-1)                :: dirstart
1044    INTEGER(iwp), DIMENSION(0:nd-1)                :: dirend
1045
1046!-- indices and sizes of urban and land surface models
1047    INTEGER(iwp), DIMENSION(:,:), POINTER          ::  surfl            !< coordinates of i-th local surface in local grid - surfl[:,k] = [d, z, y, x, m]
1048    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surfl_linear     !< dtto (linearly allocated array)
1049    INTEGER(iwp), DIMENSION(:,:), POINTER          ::  surf             !< coordinates of i-th surface in grid - surf[:,k] = [d, z, y, x, m]
1050    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surf_linear      !< dtto (linearly allocated array)
1051    INTEGER(iwp)                                   ::  nsurfl           !< number of all surfaces in local processor
1052    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  nsurfs           !< array of number of all surfaces in individual processors
1053    INTEGER(iwp)                                   ::  nsurf            !< global number of surfaces in index array of surfaces (nsurf = proc nsurfs)
1054    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surfstart        !< starts of blocks of surfaces for individual processors in array surf (indexed from 1)
1055                                                                        !< respective block for particular processor is surfstart[iproc+1]+1 : surfstart[iproc+1]+nsurfs[iproc+1]
1056
1057!-- block variables needed for calculation of the plant canopy model inside the urban surface model
1058    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pct              !< top layer of the plant canopy
1059    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pch              !< heights of the plant canopy
1060    INTEGER(iwp)                                   ::  npcbl = 0        !< number of the plant canopy gridboxes in local processor
1061    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pcbl             !< k,j,i coordinates of l-th local plant canopy box pcbl[:,l] = [k, j, i]
1062    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinsw          !< array of absorbed sw radiation for local plant canopy box
1063    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdir       !< array of absorbed direct sw radiation for local plant canopy box
1064    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdif       !< array of absorbed diffusion sw radiation for local plant canopy box
1065    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinlw          !< array of absorbed lw radiation for local plant canopy box
1066
1067!-- configuration parameters (they can be setup in PALM config)
1068    LOGICAL                                        ::  raytrace_mpi_rma = .TRUE.          !< use MPI RMA to access LAD and gridsurf from remote processes during raytracing
1069    LOGICAL                                        ::  rad_angular_discretization = .TRUE.!< whether to use fixed resolution discretization of view factors for
1070                                                                                          !< reflected radiation (as opposed to all mutually visible pairs)
1071    LOGICAL                                        ::  plant_lw_interact = .TRUE.         !< whether plant canopy interacts with LW radiation (in addition to SW)
1072    INTEGER(iwp)                                   ::  mrt_nlevels = 0                    !< number of vertical boxes above surface for which to calculate MRT
1073    LOGICAL                                        ::  mrt_skip_roof = .TRUE.             !< do not calculate MRT above roof surfaces
1074    LOGICAL                                        ::  mrt_include_sw = .TRUE.            !< should MRT calculation include SW radiation as well?
1075    LOGICAL                                        ::  mrt_geom_human = .TRUE.            !< MRT direction weights simulate human body instead of a sphere
1076    INTEGER(iwp)                                   ::  nrefsteps = 3                      !< number of reflection steps to perform
1077    REAL(wp), PARAMETER                            ::  ext_coef = 0.6_wp                  !< extinction coefficient (a.k.a. alpha)
1078    INTEGER(iwp), PARAMETER                        ::  rad_version_len = 10               !< length of identification string of rad version
1079    CHARACTER(rad_version_len), PARAMETER          ::  rad_version = 'RAD v. 3.0'         !< identification of version of binary svf and restart files
1080    INTEGER(iwp)                                   ::  raytrace_discrete_elevs = 40       !< number of discretization steps for elevation (nadir to zenith)
1081    INTEGER(iwp)                                   ::  raytrace_discrete_azims = 80       !< number of discretization steps for azimuth (out of 360 degrees)
1082    REAL(wp)                                       ::  max_raytracing_dist = -999.0_wp    !< maximum distance for raytracing (in metres)
1083    REAL(wp)                                       ::  min_irrf_value = 1e-6_wp           !< minimum potential irradiance factor value for raytracing
1084    REAL(wp), DIMENSION(1:30)                      ::  svfnorm_report_thresh = 1e21_wp    !< thresholds of SVF normalization values to report
1085    INTEGER(iwp)                                   ::  svfnorm_report_num                 !< number of SVF normalization thresholds to report
1086
1087!-- radiation related arrays to be used in radiation_interaction routine
1088    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_sw_in_dir    !< direct sw radiation
1089    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_sw_in_diff   !< diffusion sw radiation
1090    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_lw_in_diff   !< diffusion lw radiation
1091
1092!-- parameters required for RRTMG lower boundary condition
1093    REAL(wp)                   :: albedo_urb      !< albedo value retuned to RRTMG boundary cond.
1094    REAL(wp)                   :: emissivity_urb  !< emissivity value retuned to RRTMG boundary cond.
1095    REAL(wp)                   :: t_rad_urb       !< temperature value retuned to RRTMG boundary cond.
1096
1097!-- type for calculation of svf
1098    TYPE t_svf
1099        INTEGER(iwp)                               :: isurflt           !<
1100        INTEGER(iwp)                               :: isurfs            !<
1101        REAL(wp)                                   :: rsvf              !<
1102        REAL(wp)                                   :: rtransp           !<
1103    END TYPE
1104
1105!-- type for calculation of csf
1106    TYPE t_csf
1107        INTEGER(iwp)                               :: ip                !<
1108        INTEGER(iwp)                               :: itx               !<
1109        INTEGER(iwp)                               :: ity               !<
1110        INTEGER(iwp)                               :: itz               !<
1111        INTEGER(iwp)                               :: isurfs            !< Idx of source face / -1 for sky
1112        REAL(wp)                                   :: rcvf              !< Canopy view factor for faces /
1113                                                                        !< canopy sink factor for sky (-1)
1114    END TYPE
1115
1116!-- arrays storing the values of USM
1117    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  svfsurf          !< svfsurf[:,isvf] = index of target and source surface for svf[isvf]
1118    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  svf              !< array of shape view factors+direct irradiation factors for local surfaces
1119    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfins          !< array of sw radiation falling to local surface after i-th reflection
1120    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinl          !< array of lw radiation for local surface after i-th reflection
1121
1122    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  skyvf            !< array of sky view factor for each local surface
1123    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  skyvft           !< array of sky view factor including transparency for each local surface
1124    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsitrans         !< dsidir[isvfl,i] = path transmittance of i-th
1125                                                                        !< direction of direct solar irradiance per target surface
1126    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsitransc        !< dtto per plant canopy box
1127    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsidir           !< dsidir[:,i] = unit vector of i-th
1128                                                                        !< direction of direct solar irradiance
1129    INTEGER(iwp)                                   ::  ndsidir          !< number of apparent solar directions used
1130    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  dsidir_rev       !< dsidir_rev[ielev,iazim] = i for dsidir or -1 if not present
1131
1132    INTEGER(iwp)                                   ::  nmrtbl           !< No. of local grid boxes for which MRT is calculated
1133    INTEGER(iwp)                                   ::  nmrtf            !< number of MRT factors for local processor
1134    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  mrtbl            !< coordinates of i-th local MRT box - surfl[:,i] = [z, y, x]
1135    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  mrtfsurf         !< mrtfsurf[:,imrtf] = index of target MRT box and source surface for mrtf[imrtf]
1136    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtf             !< array of MRT factors for each local MRT box
1137    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtft            !< array of MRT factors including transparency for each local MRT box
1138    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtsky           !< array of sky view factor for each local MRT box
1139    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtskyt          !< array of sky view factor including transparency for each local MRT box
1140    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  mrtdsit          !< array of direct solar transparencies for each local MRT box
1141    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinsw          !< mean SW radiant flux for each MRT box
1142    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinlw          !< mean LW radiant flux for each MRT box
1143    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrt              !< mean radiant temperature for each MRT box
1144    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinsw_av       !< time average mean SW radiant flux for each MRT box
1145    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinlw_av       !< time average mean LW radiant flux for each MRT box
1146    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrt_av           !< time average mean radiant temperature for each MRT box
1147
1148    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinsw         !< array of sw radiation falling to local surface including radiation from reflections
1149    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlw         !< array of lw radiation falling to local surface including radiation from reflections
1150    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdir      !< array of direct sw radiation falling to local surface
1151    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdif      !< array of diffuse sw radiation from sky and model boundary falling to local surface
1152    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwdif      !< array of diffuse lw radiation from sky and model boundary falling to local surface
1153   
1154                                                                        !< Outward radiation is only valid for nonvirtual surfaces
1155    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsl        !< array of reflected sw radiation for local surface in i-th reflection
1156    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutll        !< array of reflected + emitted lw radiation for local surface in i-th reflection
1157    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfouts         !< array of reflected sw radiation for all surfaces in i-th reflection
1158    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutl         !< array of reflected + emitted lw radiation for all surfaces in i-th reflection
1159    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlg         !< global array of incoming lw radiation from plant canopy
1160    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsw        !< array of total sw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1161    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutlw        !< array of total lw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1162    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfemitlwl      !< array of emitted lw radiation for local surface used to calculate effective surface temperature for radiation model
1163
1164!-- block variables needed for calculation of the plant canopy model inside the urban surface model
1165    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  csfsurf          !< csfsurf[:,icsf] = index of target surface and csf grid index for csf[icsf]
1166    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  csf              !< array of plant canopy sink fators + direct irradiation factors (transparency)
1167    REAL(wp), DIMENSION(:,:,:), POINTER            ::  sub_lad          !< subset of lad_s within urban surface, transformed to plain Z coordinate
1168    REAL(wp), DIMENSION(:), POINTER                ::  sub_lad_g        !< sub_lad globalized (used to avoid MPI RMA calls in raytracing)
1169    REAL(wp)                                       ::  prototype_lad    !< prototype leaf area density for computing effective optical depth
1170    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  nzterr, plantt   !< temporary global arrays for raytracing
1171    INTEGER(iwp)                                   ::  plantt_max
1172
1173!-- arrays and variables for calculation of svf and csf
1174    TYPE(t_svf), DIMENSION(:), POINTER             ::  asvf             !< pointer to growing svc array
1175    TYPE(t_csf), DIMENSION(:), POINTER             ::  acsf             !< pointer to growing csf array
1176    TYPE(t_svf), DIMENSION(:), POINTER             ::  amrtf            !< pointer to growing mrtf array
1177    TYPE(t_svf), DIMENSION(:), ALLOCATABLE, TARGET ::  asvf1, asvf2     !< realizations of svf array
1178    TYPE(t_csf), DIMENSION(:), ALLOCATABLE, TARGET ::  acsf1, acsf2     !< realizations of csf array
1179    TYPE(t_svf), DIMENSION(:), ALLOCATABLE, TARGET ::  amrtf1, amrtf2   !< realizations of mftf array
1180    INTEGER(iwp)                                   ::  nsvfla           !< dimmension of array allocated for storage of svf in local processor
1181    INTEGER(iwp)                                   ::  ncsfla           !< dimmension of array allocated for storage of csf in local processor
1182    INTEGER(iwp)                                   ::  nmrtfa           !< dimmension of array allocated for storage of mrt
1183    INTEGER(iwp)                                   ::  msvf, mcsf, mmrtf!< mod for swapping the growing array
1184    INTEGER(iwp), PARAMETER                        ::  gasize = 100000_iwp  !< initial size of growing arrays
1185    REAL(wp), PARAMETER                            ::  grow_factor = 1.4_wp !< growth factor of growing arrays
1186    INTEGER(iwp)                                   ::  nsvfl            !< number of svf for local processor
1187    INTEGER(iwp)                                   ::  ncsfl            !< no. of csf in local processor
1188                                                                        !< needed only during calc_svf but must be here because it is
1189                                                                        !< shared between subroutines calc_svf and raytrace
1190    INTEGER(iwp), DIMENSION(:,:,:,:), POINTER      ::  gridsurf         !< reverse index of local surfl[d,k,j,i] (for case rad_angular_discretization)
1191    INTEGER(iwp), DIMENSION(:,:,:), ALLOCATABLE    ::  gridpcbl         !< reverse index of local pcbl[k,j,i]
1192    INTEGER(iwp), PARAMETER                        ::  nsurf_type_u = 6 !< number of urban surf types (used in gridsurf)
1193
1194!-- temporary arrays for calculation of csf in raytracing
1195    INTEGER(iwp)                                   ::  maxboxesg        !< max number of boxes ray can cross in the domain
1196    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  boxes            !< coordinates of gridboxes being crossed by ray
1197    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  crlens           !< array of crossing lengths of ray for particular grid boxes
1198    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  lad_ip           !< array of numbers of process where lad is stored
1199#if defined( __parallel )
1200    INTEGER(kind=MPI_ADDRESS_KIND), &
1201                  DIMENSION(:), ALLOCATABLE        ::  lad_disp         !< array of displaycements of lad in local array of proc lad_ip
1202    INTEGER(iwp)                                   ::  win_lad          !< MPI RMA window for leaf area density
1203    INTEGER(iwp)                                   ::  win_gridsurf     !< MPI RMA window for reverse grid surface index
1204#endif
1205    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  lad_s_ray        !< array of received lad_s for appropriate gridboxes crossed by ray
1206    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  target_surfl
1207    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  rt2_track
1208    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rt2_track_lad
1209    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  rt2_track_dist
1210    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  rt2_dist
1211
1212!-- arrays for time averages
1213    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfradnet_av    !< average of net radiation to local surface including radiation from reflections
1214    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinsw_av      !< average of sw radiation falling to local surface including radiation from reflections
1215    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlw_av      !< average of lw radiation falling to local surface including radiation from reflections
1216    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdir_av   !< average of direct sw radiation falling to local surface
1217    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdif_av   !< average of diffuse sw radiation from sky and model boundary falling to local surface
1218    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwdif_av   !< average of diffuse lw radiation from sky and model boundary falling to local surface
1219    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswref_av   !< average of sw radiation falling to surface from reflections
1220    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwref_av   !< average of lw radiation falling to surface from reflections
1221    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsw_av     !< average of total sw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1222    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutlw_av     !< average of total lw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1223    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfins_av       !< average of array of residua of sw radiation absorbed in surface after last reflection
1224    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinl_av       !< average of array of residua of lw radiation absorbed in surface after last reflection
1225    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinlw_av       !< Average of pcbinlw
1226    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinsw_av       !< Average of pcbinsw
1227    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdir_av    !< Average of pcbinswdir
1228    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdif_av    !< Average of pcbinswdif
1229    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswref_av    !< Average of pcbinswref
1230
1231
1232!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1233!-- Energy balance variables
1234!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1235!-- parameters of the land, roof and wall surfaces
1236    REAL(wp), DIMENSION(:), ALLOCATABLE            :: albedo_surf        !< albedo of the surface
1237    REAL(wp), DIMENSION(:), ALLOCATABLE            :: emiss_surf         !< emissivity of the wall surface
1238
1239
1240    INTERFACE radiation_check_data_output
1241       MODULE PROCEDURE radiation_check_data_output
1242    END INTERFACE radiation_check_data_output
1243
1244    INTERFACE radiation_check_data_output_ts
1245       MODULE PROCEDURE radiation_check_data_output_ts
1246    END INTERFACE radiation_check_data_output_ts
1247
1248    INTERFACE radiation_check_data_output_pr
1249       MODULE PROCEDURE radiation_check_data_output_pr
1250    END INTERFACE radiation_check_data_output_pr
1251 
1252    INTERFACE radiation_check_parameters
1253       MODULE PROCEDURE radiation_check_parameters
1254    END INTERFACE radiation_check_parameters
1255 
1256    INTERFACE radiation_clearsky
1257       MODULE PROCEDURE radiation_clearsky
1258    END INTERFACE radiation_clearsky
1259 
1260    INTERFACE radiation_constant
1261       MODULE PROCEDURE radiation_constant
1262    END INTERFACE radiation_constant
1263 
1264    INTERFACE radiation_control
1265       MODULE PROCEDURE radiation_control
1266    END INTERFACE radiation_control
1267
1268    INTERFACE radiation_3d_data_averaging
1269       MODULE PROCEDURE radiation_3d_data_averaging
1270    END INTERFACE radiation_3d_data_averaging
1271
1272    INTERFACE radiation_data_output_2d
1273       MODULE PROCEDURE radiation_data_output_2d
1274    END INTERFACE radiation_data_output_2d
1275
1276    INTERFACE radiation_data_output_3d
1277       MODULE PROCEDURE radiation_data_output_3d
1278    END INTERFACE radiation_data_output_3d
1279
1280    INTERFACE radiation_data_output_mask
1281       MODULE PROCEDURE radiation_data_output_mask
1282    END INTERFACE radiation_data_output_mask
1283
1284    INTERFACE radiation_define_netcdf_grid
1285       MODULE PROCEDURE radiation_define_netcdf_grid
1286    END INTERFACE radiation_define_netcdf_grid
1287
1288    INTERFACE radiation_header
1289       MODULE PROCEDURE radiation_header
1290    END INTERFACE radiation_header 
1291 
1292    INTERFACE radiation_init
1293       MODULE PROCEDURE radiation_init
1294    END INTERFACE radiation_init
1295
1296    INTERFACE radiation_parin
1297       MODULE PROCEDURE radiation_parin
1298    END INTERFACE radiation_parin
1299   
1300    INTERFACE radiation_rrtmg
1301       MODULE PROCEDURE radiation_rrtmg
1302    END INTERFACE radiation_rrtmg
1303
1304#if defined( __rrtmg )
1305    INTERFACE radiation_tendency
1306       MODULE PROCEDURE radiation_tendency
1307       MODULE PROCEDURE radiation_tendency_ij
1308    END INTERFACE radiation_tendency
1309#endif
1310
1311    INTERFACE radiation_rrd_local
1312       MODULE PROCEDURE radiation_rrd_local
1313    END INTERFACE radiation_rrd_local
1314
1315    INTERFACE radiation_wrd_local
1316       MODULE PROCEDURE radiation_wrd_local
1317    END INTERFACE radiation_wrd_local
1318
1319    INTERFACE radiation_interaction
1320       MODULE PROCEDURE radiation_interaction
1321    END INTERFACE radiation_interaction
1322
1323    INTERFACE radiation_interaction_init
1324       MODULE PROCEDURE radiation_interaction_init
1325    END INTERFACE radiation_interaction_init
1326 
1327    INTERFACE radiation_presimulate_solar_pos
1328       MODULE PROCEDURE radiation_presimulate_solar_pos
1329    END INTERFACE radiation_presimulate_solar_pos
1330
1331    INTERFACE radiation_calc_svf
1332       MODULE PROCEDURE radiation_calc_svf
1333    END INTERFACE radiation_calc_svf
1334
1335    INTERFACE radiation_write_svf
1336       MODULE PROCEDURE radiation_write_svf
1337    END INTERFACE radiation_write_svf
1338
1339    INTERFACE radiation_read_svf
1340       MODULE PROCEDURE radiation_read_svf
1341    END INTERFACE radiation_read_svf
1342
1343
1344    SAVE
1345
1346    PRIVATE
1347
1348!
1349!-- Public functions / NEEDS SORTING
1350    PUBLIC radiation_check_data_output, radiation_check_data_output_pr,        &
1351           radiation_check_data_output_ts,                                     &
1352           radiation_check_parameters, radiation_control,                      &
1353           radiation_header, radiation_init, radiation_parin,                  &
1354           radiation_3d_data_averaging,                                        &
1355           radiation_data_output_2d, radiation_data_output_3d,                 &
1356           radiation_define_netcdf_grid, radiation_wrd_local,                  &
1357           radiation_rrd_local, radiation_data_output_mask,                    &
1358           radiation_calc_svf, radiation_write_svf,                            &
1359           radiation_interaction, radiation_interaction_init,                  &
1360           radiation_read_svf, radiation_presimulate_solar_pos
1361
1362   
1363!
1364!-- Public variables and constants / NEEDS SORTING
1365    PUBLIC albedo, albedo_type, decl_1, decl_2, decl_3, dots_rad, dt_radiation,&
1366           emissivity, force_radiation_call, lat, lon, mrt_geom_human,         &
1367           mrt_include_sw, mrt_nlevels, mrtbl, mrtinsw, mrtinlw, nmrtbl,       &
1368           rad_net_av, radiation, radiation_scheme, rad_lw_in,                 &
1369           rad_lw_in_av, rad_lw_out, rad_lw_out_av,                            &
1370           rad_lw_cs_hr, rad_lw_cs_hr_av, rad_lw_hr, rad_lw_hr_av, rad_sw_in,  &
1371           rad_sw_in_av, rad_sw_out, rad_sw_out_av, rad_sw_cs_hr,              &
1372           rad_sw_cs_hr_av, rad_sw_hr, rad_sw_hr_av, solar_constant,           &
1373           skip_time_do_radiation, time_radiation, unscheduled_radiation_calls,&
1374           cos_zenith, calc_zenith, sun_direction, sun_dir_lat, sun_dir_lon,   &
1375           idir, jdir, kdir, id, iz, iy, ix,                                   &
1376           iup_u, inorth_u, isouth_u, ieast_u, iwest_u,                        &
1377           iup_l, inorth_l, isouth_l, ieast_l, iwest_l,                        &
1378           nsurf_type, nz_urban_b, nz_urban_t, nz_urban, pch, nsurf,                 &
1379           idsvf, ndsvf, idcsf, ndcsf, kdcsf, pct,                             &
1380           radiation_interactions, startwall, startland, endland, endwall,     &
1381           skyvf, skyvft, radiation_interactions_on, average_radiation,        &
1382           rad_sw_in_diff, rad_sw_in_dir
1383
1384
1385#if defined ( __rrtmg )
1386    PUBLIC radiation_tendency, rrtm_aldif, rrtm_aldir, rrtm_asdif, rrtm_asdir
1387#endif
1388
1389 CONTAINS
1390
1391
1392!------------------------------------------------------------------------------!
1393! Description:
1394! ------------
1395!> This subroutine controls the calls of the radiation schemes
1396!------------------------------------------------------------------------------!
1397    SUBROUTINE radiation_control
1398 
1399 
1400       IMPLICIT NONE
1401
1402
1403       IF ( debug_output_timestep )  CALL debug_message( 'radiation_control', 'start' )
1404
1405
1406       SELECT CASE ( TRIM( radiation_scheme ) )
1407
1408          CASE ( 'constant' )
1409             CALL radiation_constant
1410         
1411          CASE ( 'clear-sky' ) 
1412             CALL radiation_clearsky
1413       
1414          CASE ( 'rrtmg' )
1415             CALL radiation_rrtmg
1416
1417          CASE DEFAULT
1418
1419       END SELECT
1420
1421       IF ( debug_output_timestep )  CALL debug_message( 'radiation_control', 'end' )
1422
1423    END SUBROUTINE radiation_control
1424
1425!------------------------------------------------------------------------------!
1426! Description:
1427! ------------
1428!> Check data output for radiation model
1429!------------------------------------------------------------------------------!
1430    SUBROUTINE radiation_check_data_output( variable, unit, i, ilen, k )
1431 
1432 
1433       USE control_parameters,                                                 &
1434           ONLY: data_output, message_string
1435
1436       IMPLICIT NONE
1437
1438       CHARACTER (LEN=*) ::  unit          !<
1439       CHARACTER (LEN=*) ::  variable      !<
1440
1441       INTEGER(iwp) :: i, k
1442       INTEGER(iwp) :: ilen
1443       CHARACTER(LEN=varnamelength) :: var  !< TRIM(variable)
1444
1445       var = TRIM(variable)
1446
1447       IF ( len(var) < 3_iwp  )  THEN
1448          unit = 'illegal'
1449          RETURN
1450       ENDIF
1451
1452       IF ( var(1:3) /= 'rad'  .AND.  var(1:3) /= 'rtm' )  THEN
1453          unit = 'illegal'
1454          RETURN
1455       ENDIF
1456
1457!--    first process diractional variables
1458       IF ( var(1:12) == 'rtm_rad_net_'  .OR.  var(1:13) == 'rtm_rad_insw_'  .OR.        &
1459            var(1:13) == 'rtm_rad_inlw_'  .OR.  var(1:16) == 'rtm_rad_inswdir_'  .OR.    &
1460            var(1:16) == 'rtm_rad_inswdif_'  .OR.  var(1:16) == 'rtm_rad_inswref_'  .OR. &
1461            var(1:16) == 'rtm_rad_inlwdif_'  .OR.  var(1:16) == 'rtm_rad_inlwref_'  .OR. &
1462            var(1:14) == 'rtm_rad_outsw_'  .OR.  var(1:14) == 'rtm_rad_outlw_'  .OR.     &
1463            var(1:14) == 'rtm_rad_ressw_'  .OR.  var(1:14) == 'rtm_rad_reslw_'  ) THEN
1464          IF ( .NOT.  radiation ) THEN
1465                message_string = 'output of "' // TRIM( var ) // '" require'&
1466                                 // 's radiation = .TRUE.'
1467                CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1468          ENDIF
1469          unit = 'W/m2'
1470       ELSE IF ( var(1:7) == 'rtm_svf'  .OR.  var(1:7) == 'rtm_dif'  .OR.                &
1471                 var(1:9) == 'rtm_skyvf' .OR. var(1:9) == 'rtm_skyvft'  .OR.             &
1472                 var(1:12) == 'rtm_surfalb_'  .OR.  var(1:13) == 'rtm_surfemis_'  ) THEN
1473          IF ( .NOT.  radiation ) THEN
1474                message_string = 'output of "' // TRIM( var ) // '" require'&
1475                                 // 's radiation = .TRUE.'
1476                CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1477          ENDIF
1478          unit = '1'
1479       ELSE
1480!--       non-directional variables
1481          SELECT CASE ( TRIM( var ) )
1482             CASE ( 'rad_lw_cs_hr', 'rad_lw_hr', 'rad_lw_in', 'rad_lw_out', &
1483                    'rad_sw_cs_hr', 'rad_sw_hr', 'rad_sw_in', 'rad_sw_out'  )
1484                IF (  .NOT.  radiation  .OR.  radiation_scheme /= 'rrtmg' )  THEN
1485                   message_string = '"output of "' // TRIM( var ) // '" requi' // &
1486                                    'res radiation = .TRUE. and ' //              &
1487                                    'radiation_scheme = "rrtmg"'
1488                   CALL message( 'check_parameters', 'PA0406', 1, 2, 0, 6, 0 )
1489                ENDIF
1490                unit = 'K/h'
1491
1492             CASE ( 'rad_net*', 'rrtm_aldif*', 'rrtm_aldir*', 'rrtm_asdif*',      &
1493                    'rrtm_asdir*', 'rad_lw_in*', 'rad_lw_out*', 'rad_sw_in*',     &
1494                    'rad_sw_out*')
1495                IF ( i == 0 .AND. ilen == 0 .AND. k == 0)  THEN
1496                   ! Workaround for masked output (calls with i=ilen=k=0)
1497                   unit = 'illegal'
1498                   RETURN
1499                ENDIF
1500                IF ( k == 0  .OR.  data_output(i)(ilen-2:ilen) /= '_xy' )  THEN
1501                   message_string = 'illegal value for data_output: "' //         &
1502                                    TRIM( var ) // '" & only 2d-horizontal ' //   &
1503                                    'cross sections are allowed for this value'
1504                   CALL message( 'check_parameters', 'PA0111', 1, 2, 0, 6, 0 )
1505                ENDIF
1506                IF (  .NOT.  radiation  .OR.  radiation_scheme /= "rrtmg" )  THEN
1507                   IF ( TRIM( var ) == 'rrtm_aldif*'  .OR.                        &
1508                        TRIM( var ) == 'rrtm_aldir*'  .OR.                        &
1509                        TRIM( var ) == 'rrtm_asdif*'  .OR.                        &
1510                        TRIM( var ) == 'rrtm_asdir*'      )                       &
1511                   THEN
1512                      message_string = 'output of "' // TRIM( var ) // '" require'&
1513                                       // 's radiation = .TRUE. and radiation_sch'&
1514                                       // 'eme = "rrtmg"'
1515                      CALL message( 'check_parameters', 'PA0409', 1, 2, 0, 6, 0 )
1516                   ENDIF
1517                ENDIF
1518
1519                IF ( TRIM( var ) == 'rad_net*'      ) unit = 'W/m2'
1520                IF ( TRIM( var ) == 'rad_lw_in*'    ) unit = 'W/m2'
1521                IF ( TRIM( var ) == 'rad_lw_out*'   ) unit = 'W/m2'
1522                IF ( TRIM( var ) == 'rad_sw_in*'    ) unit = 'W/m2'
1523                IF ( TRIM( var ) == 'rad_sw_out*'   ) unit = 'W/m2'
1524                IF ( TRIM( var ) == 'rad_sw_in'     ) unit = 'W/m2'
1525                IF ( TRIM( var ) == 'rrtm_aldif*'   ) unit = ''
1526                IF ( TRIM( var ) == 'rrtm_aldir*'   ) unit = ''
1527                IF ( TRIM( var ) == 'rrtm_asdif*'   ) unit = ''
1528                IF ( TRIM( var ) == 'rrtm_asdir*'   ) unit = ''
1529
1530             CASE ( 'rtm_rad_pc_inlw', 'rtm_rad_pc_insw', 'rtm_rad_pc_inswdir', &
1531                    'rtm_rad_pc_inswdif', 'rtm_rad_pc_inswref')
1532                IF ( .NOT.  radiation ) THEN
1533                   message_string = 'output of "' // TRIM( var ) // '" require'&
1534                                    // 's radiation = .TRUE.'
1535                   CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1536                ENDIF
1537                unit = 'W'
1538
1539             CASE ( 'rtm_mrt', 'rtm_mrt_sw', 'rtm_mrt_lw'  )
1540                IF ( i == 0 .AND. ilen == 0 .AND. k == 0)  THEN
1541                   ! Workaround for masked output (calls with i=ilen=k=0)
1542                   unit = 'illegal'
1543                   RETURN
1544                ENDIF
1545
1546                IF ( .NOT.  radiation ) THEN
1547                   message_string = 'output of "' // TRIM( var ) // '" require'&
1548                                    // 's radiation = .TRUE.'
1549                   CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1550                ENDIF
1551                IF ( mrt_nlevels == 0 ) THEN
1552                   message_string = 'output of "' // TRIM( var ) // '" require'&
1553                                    // 's mrt_nlevels > 0'
1554                   CALL message( 'check_parameters', 'PA0510', 1, 2, 0, 6, 0 )
1555                ENDIF
1556                IF ( TRIM( var ) == 'rtm_mrt_sw'  .AND.  .NOT. mrt_include_sw ) THEN
1557                   message_string = 'output of "' // TRIM( var ) // '" require'&
1558                                    // 's rtm_mrt_sw = .TRUE.'
1559                   CALL message( 'check_parameters', 'PA0511', 1, 2, 0, 6, 0 )
1560                ENDIF
1561                IF ( TRIM( var ) == 'rtm_mrt' ) THEN
1562                   unit = 'K'
1563                ELSE
1564                   unit = 'W m-2'
1565                ENDIF
1566
1567             CASE DEFAULT
1568                unit = 'illegal'
1569
1570          END SELECT
1571       ENDIF
1572
1573    END SUBROUTINE radiation_check_data_output
1574
1575
1576!------------------------------------------------------------------------------!
1577! Description:
1578! ------------
1579!> Set module-specific timeseries units and labels
1580!------------------------------------------------------------------------------!
1581 SUBROUTINE radiation_check_data_output_ts( dots_max, dots_num )
1582
1583
1584    INTEGER(iwp),      INTENT(IN)     ::  dots_max
1585    INTEGER(iwp),      INTENT(INOUT)  ::  dots_num
1586
1587!
1588!-- Next line is just to avoid compiler warning about unused variable.
1589    IF ( dots_max == 0 )  CONTINUE
1590
1591!
1592!-- Temporary solution to add LSM and radiation time series to the default
1593!-- output
1594    IF ( land_surface  .OR.  radiation )  THEN
1595       IF ( TRIM( radiation_scheme ) == 'rrtmg' )  THEN
1596          dots_num = dots_num + 15
1597       ELSE
1598          dots_num = dots_num + 11
1599       ENDIF
1600    ENDIF
1601
1602
1603 END SUBROUTINE radiation_check_data_output_ts
1604
1605!------------------------------------------------------------------------------!
1606! Description:
1607! ------------
1608!> Check data output of profiles for radiation model
1609!------------------------------------------------------------------------------! 
1610    SUBROUTINE radiation_check_data_output_pr( variable, var_count, unit,      &
1611               dopr_unit )
1612 
1613       USE arrays_3d,                                                          &
1614           ONLY: zu
1615
1616       USE control_parameters,                                                 &
1617           ONLY: data_output_pr, message_string
1618
1619       USE indices
1620
1621       USE profil_parameter
1622
1623       USE statistics
1624
1625       IMPLICIT NONE
1626   
1627       CHARACTER (LEN=*) ::  unit      !<
1628       CHARACTER (LEN=*) ::  variable  !<
1629       CHARACTER (LEN=*) ::  dopr_unit !< local value of dopr_unit
1630 
1631       INTEGER(iwp) ::  var_count     !<
1632
1633       SELECT CASE ( TRIM( variable ) )
1634       
1635         CASE ( 'rad_net' )
1636             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme == 'constant' )&
1637             THEN
1638                message_string = 'data_output_pr = ' //                        &
1639                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1640                                 'not available for radiation = .FALSE. or ' //&
1641                                 'radiation_scheme = "constant"'
1642                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1643             ELSE
1644                dopr_index(var_count) = 99
1645                dopr_unit  = 'W/m2'
1646                hom(:,2,99,:)  = SPREAD( zw, 2, statistic_regions+1 )
1647                unit = dopr_unit
1648             ENDIF
1649
1650          CASE ( 'rad_lw_in' )
1651             IF ( (  .NOT.  radiation)  .OR.  radiation_scheme == 'constant' ) &
1652             THEN
1653                message_string = 'data_output_pr = ' //                        &
1654                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1655                                 'not available for radiation = .FALSE. or ' //&
1656                                 'radiation_scheme = "constant"'
1657                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1658             ELSE
1659                dopr_index(var_count) = 100
1660                dopr_unit  = 'W/m2'
1661                hom(:,2,100,:)  = SPREAD( zw, 2, statistic_regions+1 )
1662                unit = dopr_unit 
1663             ENDIF
1664
1665          CASE ( 'rad_lw_out' )
1666             IF ( (  .NOT. radiation )  .OR.  radiation_scheme == 'constant' ) &
1667             THEN
1668                message_string = 'data_output_pr = ' //                        &
1669                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1670                                 'not available for radiation = .FALSE. or ' //&
1671                                 'radiation_scheme = "constant"'
1672                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1673             ELSE
1674                dopr_index(var_count) = 101
1675                dopr_unit  = 'W/m2'
1676                hom(:,2,101,:)  = SPREAD( zw, 2, statistic_regions+1 )
1677                unit = dopr_unit   
1678             ENDIF
1679
1680          CASE ( 'rad_sw_in' )
1681             IF ( (  .NOT. radiation )  .OR.  radiation_scheme == 'constant' ) &
1682             THEN
1683                message_string = 'data_output_pr = ' //                        &
1684                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1685                                 'not available for radiation = .FALSE. or ' //&
1686                                 'radiation_scheme = "constant"'
1687                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1688             ELSE
1689                dopr_index(var_count) = 102
1690                dopr_unit  = 'W/m2'
1691                hom(:,2,102,:)  = SPREAD( zw, 2, statistic_regions+1 )
1692                unit = dopr_unit
1693             ENDIF
1694
1695          CASE ( 'rad_sw_out')
1696             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme == 'constant' )&
1697             THEN
1698                message_string = 'data_output_pr = ' //                        &
1699                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1700                                 'not available for radiation = .FALSE. or ' //&
1701                                 'radiation_scheme = "constant"'
1702                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1703             ELSE
1704                dopr_index(var_count) = 103
1705                dopr_unit  = 'W/m2'
1706                hom(:,2,103,:)  = SPREAD( zw, 2, statistic_regions+1 )
1707                unit = dopr_unit
1708             ENDIF
1709
1710          CASE ( 'rad_lw_cs_hr' )
1711             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1712             THEN
1713                message_string = 'data_output_pr = ' //                        &
1714                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1715                                 'not available for radiation = .FALSE. or ' //&
1716                                 'radiation_scheme /= "rrtmg"'
1717                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1718             ELSE
1719                dopr_index(var_count) = 104
1720                dopr_unit  = 'K/h'
1721                hom(:,2,104,:)  = SPREAD( zu, 2, statistic_regions+1 )
1722                unit = dopr_unit
1723             ENDIF
1724
1725          CASE ( 'rad_lw_hr' )
1726             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1727             THEN
1728                message_string = 'data_output_pr = ' //                        &
1729                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1730                                 'not available for radiation = .FALSE. or ' //&
1731                                 'radiation_scheme /= "rrtmg"'
1732                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1733             ELSE
1734                dopr_index(var_count) = 105
1735                dopr_unit  = 'K/h'
1736                hom(:,2,105,:)  = SPREAD( zu, 2, statistic_regions+1 )
1737                unit = dopr_unit
1738             ENDIF
1739
1740          CASE ( 'rad_sw_cs_hr' )
1741             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1742             THEN
1743                message_string = 'data_output_pr = ' //                        &
1744                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1745                                 'not available for radiation = .FALSE. or ' //&
1746                                 'radiation_scheme /= "rrtmg"'
1747                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1748             ELSE
1749                dopr_index(var_count) = 106
1750                dopr_unit  = 'K/h'
1751                hom(:,2,106,:)  = SPREAD( zu, 2, statistic_regions+1 )
1752                unit = dopr_unit
1753             ENDIF
1754
1755          CASE ( 'rad_sw_hr' )
1756             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1757             THEN
1758                message_string = 'data_output_pr = ' //                        &
1759                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1760                                 'not available for radiation = .FALSE. or ' //&
1761                                 'radiation_scheme /= "rrtmg"'
1762                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1763             ELSE
1764                dopr_index(var_count) = 107
1765                dopr_unit  = 'K/h'
1766                hom(:,2,107,:)  = SPREAD( zu, 2, statistic_regions+1 )
1767                unit = dopr_unit
1768             ENDIF
1769
1770
1771          CASE DEFAULT
1772             unit = 'illegal'
1773
1774       END SELECT
1775
1776
1777    END SUBROUTINE radiation_check_data_output_pr
1778 
1779 
1780!------------------------------------------------------------------------------!
1781! Description:
1782! ------------
1783!> Check parameters routine for radiation model
1784!------------------------------------------------------------------------------!
1785    SUBROUTINE radiation_check_parameters
1786
1787       USE control_parameters,                                                 &
1788           ONLY: land_surface, message_string, urban_surface
1789
1790       USE netcdf_data_input_mod,                                              &
1791           ONLY:  input_pids_static                 
1792   
1793       IMPLICIT NONE
1794       
1795!
1796!--    In case no urban-surface or land-surface model is applied, usage of
1797!--    a radiation model make no sense.         
1798       IF ( .NOT. land_surface  .AND.  .NOT. urban_surface )  THEN
1799          message_string = 'Usage of radiation module is only allowed if ' //  &
1800                           'land-surface and/or urban-surface model is applied.'
1801          CALL message( 'check_parameters', 'PA0486', 1, 2, 0, 6, 0 )
1802       ENDIF
1803
1804       IF ( radiation_scheme /= 'constant'   .AND.                             &
1805            radiation_scheme /= 'clear-sky'  .AND.                             &
1806            radiation_scheme /= 'rrtmg' )  THEN
1807          message_string = 'unknown radiation_scheme = '//                     &
1808                           TRIM( radiation_scheme )
1809          CALL message( 'check_parameters', 'PA0405', 1, 2, 0, 6, 0 )
1810       ELSEIF ( radiation_scheme == 'rrtmg' )  THEN
1811#if ! defined ( __rrtmg )
1812          message_string = 'radiation_scheme = "rrtmg" requires ' //           & 
1813                           'compilation of PALM with pre-processor ' //        &
1814                           'directive -D__rrtmg'
1815          CALL message( 'check_parameters', 'PA0407', 1, 2, 0, 6, 0 )
1816#endif
1817#if defined ( __rrtmg ) && ! defined( __netcdf )
1818          message_string = 'radiation_scheme = "rrtmg" requires ' //           & 
1819                           'the use of NetCDF (preprocessor directive ' //     &
1820                           '-D__netcdf'
1821          CALL message( 'check_parameters', 'PA0412', 1, 2, 0, 6, 0 )
1822#endif
1823
1824       ENDIF
1825!
1826!--    Checks performed only if data is given via namelist only.
1827       IF ( .NOT. input_pids_static )  THEN
1828          IF ( albedo_type == 0  .AND.  albedo == 9999999.9_wp  .AND.          &
1829               radiation_scheme == 'clear-sky')  THEN
1830             message_string = 'radiation_scheme = "clear-sky" in combination'//& 
1831                              'with albedo_type = 0 requires setting of'//     &
1832                              'albedo /= 9999999.9'
1833             CALL message( 'check_parameters', 'PA0410', 1, 2, 0, 6, 0 )
1834          ENDIF
1835
1836          IF ( albedo_type == 0  .AND.  radiation_scheme == 'rrtmg'  .AND.     &
1837             ( albedo_lw_dif == 9999999.9_wp .OR. albedo_lw_dir == 9999999.9_wp&
1838          .OR. albedo_sw_dif == 9999999.9_wp .OR. albedo_sw_dir == 9999999.9_wp& 
1839             ) ) THEN
1840             message_string = 'radiation_scheme = "rrtmg" in combination' //   & 
1841                              'with albedo_type = 0 requires setting of ' //   &
1842                              'albedo_lw_dif /= 9999999.9' //                  &
1843                              'albedo_lw_dir /= 9999999.9' //                  &
1844                              'albedo_sw_dif /= 9999999.9 and' //              &
1845                              'albedo_sw_dir /= 9999999.9'
1846             CALL message( 'check_parameters', 'PA0411', 1, 2, 0, 6, 0 )
1847          ENDIF
1848       ENDIF
1849!
1850!--    Parallel rad_angular_discretization without raytrace_mpi_rma is not implemented
1851#if defined( __parallel )     
1852       IF ( rad_angular_discretization  .AND.  .NOT. raytrace_mpi_rma )  THEN
1853          message_string = 'rad_angular_discretization can only be used ' //  &
1854                           'together with raytrace_mpi_rma or when ' //  &
1855                           'no parallelization is applied.'
1856          CALL message( 'check_parameters', 'PA0486', 1, 2, 0, 6, 0 )
1857       ENDIF
1858#endif
1859
1860       IF ( cloud_droplets  .AND.   radiation_scheme == 'rrtmg'  .AND.         &
1861            average_radiation ) THEN
1862          message_string = 'average_radiation = .T. with radiation_scheme'//   & 
1863                           '= "rrtmg" in combination cloud_droplets = .T.'//   &
1864                           'is not implementd'
1865          CALL message( 'check_parameters', 'PA0560', 1, 2, 0, 6, 0 )
1866       ENDIF
1867
1868!
1869!--    Incialize svf normalization reporting histogram
1870       svfnorm_report_num = 1
1871       DO WHILE ( svfnorm_report_thresh(svfnorm_report_num) < 1e20_wp          &
1872                   .AND. svfnorm_report_num <= 30 )
1873          svfnorm_report_num = svfnorm_report_num + 1
1874       ENDDO
1875       svfnorm_report_num = svfnorm_report_num - 1
1876!
1877!--    Check for dt_radiation
1878       IF ( dt_radiation <= 0.0 )  THEN
1879          message_string = 'dt_radiation must be > 0.0' 
1880          CALL message( 'check_parameters', 'PA0591', 1, 2, 0, 6, 0 ) 
1881       ENDIF
1882 
1883    END SUBROUTINE radiation_check_parameters 
1884 
1885 
1886!------------------------------------------------------------------------------!
1887! Description:
1888! ------------
1889!> Initialization of the radiation model
1890!------------------------------------------------------------------------------!
1891    SUBROUTINE radiation_init
1892   
1893       IMPLICIT NONE
1894
1895       INTEGER(iwp) ::  i         !< running index x-direction
1896       INTEGER(iwp) ::  ioff      !< offset in x between surface element reference grid point in atmosphere and actual surface
1897       INTEGER(iwp) ::  j         !< running index y-direction
1898       INTEGER(iwp) ::  joff      !< offset in y between surface element reference grid point in atmosphere and actual surface
1899       INTEGER(iwp) ::  l         !< running index for orientation of vertical surfaces
1900       INTEGER(iwp) ::  m         !< running index for surface elements
1901#if defined( __rrtmg )
1902       INTEGER(iwp) ::  ind_type  !< running index for subgrid-surface tiles
1903#endif
1904
1905
1906       IF ( debug_output )  CALL debug_message( 'radiation_init', 'start' )
1907!
1908!--    Activate radiation_interactions according to the existence of vertical surfaces and/or trees.
1909!--    The namelist parameter radiation_interactions_on can override this behavior.
1910!--    (This check cannot be performed in check_parameters, because vertical_surfaces_exist is first set in
1911!--    init_surface_arrays.)
1912       IF ( radiation_interactions_on )  THEN
1913          IF ( vertical_surfaces_exist  .OR.  plant_canopy )  THEN
1914             radiation_interactions    = .TRUE.
1915             average_radiation         = .TRUE.
1916          ELSE
1917             radiation_interactions_on = .FALSE.   !< reset namelist parameter: no interactions
1918                                                   !< calculations necessary in case of flat surface
1919          ENDIF
1920       ELSEIF ( vertical_surfaces_exist  .OR.  plant_canopy )  THEN
1921          message_string = 'radiation_interactions_on is set to .FALSE. although '     // &
1922                           'vertical surfaces and/or trees exist. The model will run ' // &
1923                           'without RTM (no shadows, no radiation reflections)'
1924          CALL message( 'init_3d_model', 'PA0348', 0, 1, 0, 6, 0 )
1925       ENDIF
1926!
1927!--    If required, initialize radiation interactions between surfaces
1928!--    via sky-view factors. This must be done before radiation is initialized.
1929       IF ( radiation_interactions )  CALL radiation_interaction_init
1930!
1931!--    Allocate array for storing the surface net radiation
1932       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_net )  .AND.                      &
1933                  surf_lsm_h%ns > 0  )   THEN
1934          ALLOCATE( surf_lsm_h%rad_net(1:surf_lsm_h%ns) )
1935          surf_lsm_h%rad_net = 0.0_wp 
1936       ENDIF
1937       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_net )  .AND.                      &
1938                  surf_usm_h%ns > 0  )  THEN
1939          ALLOCATE( surf_usm_h%rad_net(1:surf_usm_h%ns) )
1940          surf_usm_h%rad_net = 0.0_wp 
1941       ENDIF
1942       DO  l = 0, 3
1943          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_net )  .AND.                &
1944                     surf_lsm_v(l)%ns > 0  )  THEN
1945             ALLOCATE( surf_lsm_v(l)%rad_net(1:surf_lsm_v(l)%ns) )
1946             surf_lsm_v(l)%rad_net = 0.0_wp 
1947          ENDIF
1948          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_net )  .AND.                &
1949                     surf_usm_v(l)%ns > 0  )  THEN
1950             ALLOCATE( surf_usm_v(l)%rad_net(1:surf_usm_v(l)%ns) )
1951             surf_usm_v(l)%rad_net = 0.0_wp 
1952          ENDIF
1953       ENDDO
1954
1955
1956!
1957!--    Allocate array for storing the surface longwave (out) radiation change
1958       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_lw_out_change_0 )  .AND.          &
1959                  surf_lsm_h%ns > 0  )   THEN
1960          ALLOCATE( surf_lsm_h%rad_lw_out_change_0(1:surf_lsm_h%ns) )
1961          surf_lsm_h%rad_lw_out_change_0 = 0.0_wp 
1962       ENDIF
1963       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_lw_out_change_0 )  .AND.          &
1964                  surf_usm_h%ns > 0  )  THEN
1965          ALLOCATE( surf_usm_h%rad_lw_out_change_0(1:surf_usm_h%ns) )
1966          surf_usm_h%rad_lw_out_change_0 = 0.0_wp 
1967       ENDIF
1968       DO  l = 0, 3
1969          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_lw_out_change_0 )  .AND.    &
1970                     surf_lsm_v(l)%ns > 0  )  THEN
1971             ALLOCATE( surf_lsm_v(l)%rad_lw_out_change_0(1:surf_lsm_v(l)%ns) )
1972             surf_lsm_v(l)%rad_lw_out_change_0 = 0.0_wp 
1973          ENDIF
1974          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_lw_out_change_0 )  .AND.    &
1975                     surf_usm_v(l)%ns > 0  )  THEN
1976             ALLOCATE( surf_usm_v(l)%rad_lw_out_change_0(1:surf_usm_v(l)%ns) )
1977             surf_usm_v(l)%rad_lw_out_change_0 = 0.0_wp 
1978          ENDIF
1979       ENDDO
1980
1981!
1982!--    Allocate surface arrays for incoming/outgoing short/longwave radiation
1983       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_sw_in )  .AND.                    &
1984                  surf_lsm_h%ns > 0  )   THEN
1985          ALLOCATE( surf_lsm_h%rad_sw_in(1:surf_lsm_h%ns)  )
1986          ALLOCATE( surf_lsm_h%rad_sw_out(1:surf_lsm_h%ns) )
1987          ALLOCATE( surf_lsm_h%rad_sw_dir(1:surf_lsm_h%ns) )
1988          ALLOCATE( surf_lsm_h%rad_sw_dif(1:surf_lsm_h%ns) )
1989          ALLOCATE( surf_lsm_h%rad_sw_ref(1:surf_lsm_h%ns) )
1990          ALLOCATE( surf_lsm_h%rad_sw_res(1:surf_lsm_h%ns) )
1991          ALLOCATE( surf_lsm_h%rad_lw_in(1:surf_lsm_h%ns)  )
1992          ALLOCATE( surf_lsm_h%rad_lw_out(1:surf_lsm_h%ns) )
1993          ALLOCATE( surf_lsm_h%rad_lw_dif(1:surf_lsm_h%ns) )
1994          ALLOCATE( surf_lsm_h%rad_lw_ref(1:surf_lsm_h%ns) )
1995          ALLOCATE( surf_lsm_h%rad_lw_res(1:surf_lsm_h%ns) )
1996          surf_lsm_h%rad_sw_in  = 0.0_wp 
1997          surf_lsm_h%rad_sw_out = 0.0_wp 
1998          surf_lsm_h%rad_sw_dir = 0.0_wp 
1999          surf_lsm_h%rad_sw_dif = 0.0_wp 
2000          surf_lsm_h%rad_sw_ref = 0.0_wp 
2001          surf_lsm_h%rad_sw_res = 0.0_wp 
2002          surf_lsm_h%rad_lw_in  = 0.0_wp 
2003          surf_lsm_h%rad_lw_out = 0.0_wp 
2004          surf_lsm_h%rad_lw_dif = 0.0_wp 
2005          surf_lsm_h%rad_lw_ref = 0.0_wp 
2006          surf_lsm_h%rad_lw_res = 0.0_wp 
2007       ENDIF
2008       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_sw_in )  .AND.                    &
2009                  surf_usm_h%ns > 0  )  THEN
2010          ALLOCATE( surf_usm_h%rad_sw_in(1:surf_usm_h%ns)  )
2011          ALLOCATE( surf_usm_h%rad_sw_out(1:surf_usm_h%ns) )
2012          ALLOCATE( surf_usm_h%rad_sw_dir(1:surf_usm_h%ns) )
2013          ALLOCATE( surf_usm_h%rad_sw_dif(1:surf_usm_h%ns) )
2014          ALLOCATE( surf_usm_h%rad_sw_ref(1:surf_usm_h%ns) )
2015          ALLOCATE( surf_usm_h%rad_sw_res(1:surf_usm_h%ns) )
2016          ALLOCATE( surf_usm_h%rad_lw_in(1:surf_usm_h%ns)  )
2017          ALLOCATE( surf_usm_h%rad_lw_out(1:surf_usm_h%ns) )
2018          ALLOCATE( surf_usm_h%rad_lw_dif(1:surf_usm_h%ns) )
2019          ALLOCATE( surf_usm_h%rad_lw_ref(1:surf_usm_h%ns) )
2020          ALLOCATE( surf_usm_h%rad_lw_res(1:surf_usm_h%ns) )
2021          surf_usm_h%rad_sw_in  = 0.0_wp 
2022          surf_usm_h%rad_sw_out = 0.0_wp 
2023          surf_usm_h%rad_sw_dir = 0.0_wp 
2024          surf_usm_h%rad_sw_dif = 0.0_wp 
2025          surf_usm_h%rad_sw_ref = 0.0_wp 
2026          surf_usm_h%rad_sw_res = 0.0_wp 
2027          surf_usm_h%rad_lw_in  = 0.0_wp 
2028          surf_usm_h%rad_lw_out = 0.0_wp 
2029          surf_usm_h%rad_lw_dif = 0.0_wp 
2030          surf_usm_h%rad_lw_ref = 0.0_wp 
2031          surf_usm_h%rad_lw_res = 0.0_wp 
2032       ENDIF
2033       DO  l = 0, 3
2034          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_sw_in )  .AND.              &
2035                     surf_lsm_v(l)%ns > 0  )  THEN
2036             ALLOCATE( surf_lsm_v(l)%rad_sw_in(1:surf_lsm_v(l)%ns)  )
2037             ALLOCATE( surf_lsm_v(l)%rad_sw_out(1:surf_lsm_v(l)%ns) )
2038             ALLOCATE( surf_lsm_v(l)%rad_sw_dir(1:surf_lsm_v(l)%ns) )
2039             ALLOCATE( surf_lsm_v(l)%rad_sw_dif(1:surf_lsm_v(l)%ns) )
2040             ALLOCATE( surf_lsm_v(l)%rad_sw_ref(1:surf_lsm_v(l)%ns) )
2041             ALLOCATE( surf_lsm_v(l)%rad_sw_res(1:surf_lsm_v(l)%ns) )
2042
2043             ALLOCATE( surf_lsm_v(l)%rad_lw_in(1:surf_lsm_v(l)%ns)  )
2044             ALLOCATE( surf_lsm_v(l)%rad_lw_out(1:surf_lsm_v(l)%ns) )
2045             ALLOCATE( surf_lsm_v(l)%rad_lw_dif(1:surf_lsm_v(l)%ns) )
2046             ALLOCATE( surf_lsm_v(l)%rad_lw_ref(1:surf_lsm_v(l)%ns) )
2047             ALLOCATE( surf_lsm_v(l)%rad_lw_res(1:surf_lsm_v(l)%ns) )
2048
2049             surf_lsm_v(l)%rad_sw_in  = 0.0_wp 
2050             surf_lsm_v(l)%rad_sw_out = 0.0_wp
2051             surf_lsm_v(l)%rad_sw_dir = 0.0_wp
2052             surf_lsm_v(l)%rad_sw_dif = 0.0_wp
2053             surf_lsm_v(l)%rad_sw_ref = 0.0_wp
2054             surf_lsm_v(l)%rad_sw_res = 0.0_wp
2055
2056             surf_lsm_v(l)%rad_lw_in  = 0.0_wp 
2057             surf_lsm_v(l)%rad_lw_out = 0.0_wp 
2058             surf_lsm_v(l)%rad_lw_dif = 0.0_wp 
2059             surf_lsm_v(l)%rad_lw_ref = 0.0_wp 
2060             surf_lsm_v(l)%rad_lw_res = 0.0_wp 
2061          ENDIF
2062          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_sw_in )  .AND.              &
2063                     surf_usm_v(l)%ns > 0  )  THEN
2064             ALLOCATE( surf_usm_v(l)%rad_sw_in(1:surf_usm_v(l)%ns)  )
2065             ALLOCATE( surf_usm_v(l)%rad_sw_out(1:surf_usm_v(l)%ns) )
2066             ALLOCATE( surf_usm_v(l)%rad_sw_dir(1:surf_usm_v(l)%ns) )
2067             ALLOCATE( surf_usm_v(l)%rad_sw_dif(1:surf_usm_v(l)%ns) )
2068             ALLOCATE( surf_usm_v(l)%rad_sw_ref(1:surf_usm_v(l)%ns) )
2069             ALLOCATE( surf_usm_v(l)%rad_sw_res(1:surf_usm_v(l)%ns) )
2070             ALLOCATE( surf_usm_v(l)%rad_lw_in(1:surf_usm_v(l)%ns)  )
2071             ALLOCATE( surf_usm_v(l)%rad_lw_out(1:surf_usm_v(l)%ns) )
2072             ALLOCATE( surf_usm_v(l)%rad_lw_dif(1:surf_usm_v(l)%ns) )
2073             ALLOCATE( surf_usm_v(l)%rad_lw_ref(1:surf_usm_v(l)%ns) )
2074             ALLOCATE( surf_usm_v(l)%rad_lw_res(1:surf_usm_v(l)%ns) )
2075             surf_usm_v(l)%rad_sw_in  = 0.0_wp 
2076             surf_usm_v(l)%rad_sw_out = 0.0_wp
2077             surf_usm_v(l)%rad_sw_dir = 0.0_wp
2078             surf_usm_v(l)%rad_sw_dif = 0.0_wp
2079             surf_usm_v(l)%rad_sw_ref = 0.0_wp
2080             surf_usm_v(l)%rad_sw_res = 0.0_wp
2081             surf_usm_v(l)%rad_lw_in  = 0.0_wp 
2082             surf_usm_v(l)%rad_lw_out = 0.0_wp 
2083             surf_usm_v(l)%rad_lw_dif = 0.0_wp 
2084             surf_usm_v(l)%rad_lw_ref = 0.0_wp 
2085             surf_usm_v(l)%rad_lw_res = 0.0_wp 
2086          ENDIF
2087       ENDDO
2088!
2089!--    Fix net radiation in case of radiation_scheme = 'constant'
2090       IF ( radiation_scheme == 'constant' )  THEN
2091          IF ( ALLOCATED( surf_lsm_h%rad_net ) )                               &
2092             surf_lsm_h%rad_net    = net_radiation
2093          IF ( ALLOCATED( surf_usm_h%rad_net ) )                               &
2094             surf_usm_h%rad_net    = net_radiation
2095!
2096!--       Todo: weight with inclination angle
2097          DO  l = 0, 3
2098             IF ( ALLOCATED( surf_lsm_v(l)%rad_net ) )                         &
2099                surf_lsm_v(l)%rad_net = net_radiation
2100             IF ( ALLOCATED( surf_usm_v(l)%rad_net ) )                         &
2101                surf_usm_v(l)%rad_net = net_radiation
2102          ENDDO
2103!          radiation = .FALSE.
2104!
2105!--    Calculate orbital constants
2106       ELSE
2107          decl_1 = SIN(23.45_wp * pi / 180.0_wp)
2108          decl_2 = 2.0_wp * pi / 365.0_wp
2109          decl_3 = decl_2 * 81.0_wp
2110          lat    = latitude * pi / 180.0_wp
2111          lon    = longitude * pi / 180.0_wp
2112       ENDIF
2113
2114       IF ( radiation_scheme == 'clear-sky'  .OR.                              &
2115            radiation_scheme == 'constant')  THEN
2116
2117
2118!
2119!--       Allocate arrays for incoming/outgoing short/longwave radiation
2120          IF ( .NOT. ALLOCATED ( rad_sw_in ) )  THEN
2121             ALLOCATE ( rad_sw_in(0:0,nysg:nyng,nxlg:nxrg) )
2122          ENDIF
2123          IF ( .NOT. ALLOCATED ( rad_sw_out ) )  THEN
2124             ALLOCATE ( rad_sw_out(0:0,nysg:nyng,nxlg:nxrg) )
2125          ENDIF
2126
2127          IF ( .NOT. ALLOCATED ( rad_lw_in ) )  THEN
2128             ALLOCATE ( rad_lw_in(0:0,nysg:nyng,nxlg:nxrg) )
2129          ENDIF
2130          IF ( .NOT. ALLOCATED ( rad_lw_out ) )  THEN
2131             ALLOCATE ( rad_lw_out(0:0,nysg:nyng,nxlg:nxrg) )
2132          ENDIF
2133
2134!
2135!--       Allocate average arrays for incoming/outgoing short/longwave radiation
2136          IF ( .NOT. ALLOCATED ( rad_sw_in_av ) )  THEN
2137             ALLOCATE ( rad_sw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
2138          ENDIF
2139          IF ( .NOT. ALLOCATED ( rad_sw_out_av ) )  THEN
2140             ALLOCATE ( rad_sw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
2141          ENDIF
2142
2143          IF ( .NOT. ALLOCATED ( rad_lw_in_av ) )  THEN
2144             ALLOCATE ( rad_lw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
2145          ENDIF
2146          IF ( .NOT. ALLOCATED ( rad_lw_out_av ) )  THEN
2147             ALLOCATE ( rad_lw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
2148          ENDIF
2149!
2150!--       Allocate arrays for broadband albedo, and level 1 initialization
2151!--       via namelist paramter, unless not already allocated.
2152          IF ( .NOT. ALLOCATED(surf_lsm_h%albedo) )  THEN
2153             ALLOCATE( surf_lsm_h%albedo(0:2,1:surf_lsm_h%ns)     )
2154             surf_lsm_h%albedo    = albedo
2155          ENDIF
2156          IF ( .NOT. ALLOCATED(surf_usm_h%albedo) )  THEN
2157             ALLOCATE( surf_usm_h%albedo(0:2,1:surf_usm_h%ns)     )
2158             surf_usm_h%albedo    = albedo
2159          ENDIF
2160
2161          DO  l = 0, 3
2162             IF ( .NOT. ALLOCATED( surf_lsm_v(l)%albedo ) )  THEN
2163                ALLOCATE( surf_lsm_v(l)%albedo(0:2,1:surf_lsm_v(l)%ns) )
2164                surf_lsm_v(l)%albedo = albedo
2165             ENDIF
2166             IF ( .NOT. ALLOCATED( surf_usm_v(l)%albedo ) )  THEN
2167                ALLOCATE( surf_usm_v(l)%albedo(0:2,1:surf_usm_v(l)%ns) )
2168                surf_usm_v(l)%albedo = albedo
2169             ENDIF
2170          ENDDO
2171!
2172!--       Level 2 initialization of broadband albedo via given albedo_type.
2173!--       Only if albedo_type is non-zero. In case of urban surface and
2174!--       input data is read from ASCII file, albedo_type will be zero, so that
2175!--       albedo won't be overwritten.
2176          DO  m = 1, surf_lsm_h%ns
2177             IF ( surf_lsm_h%albedo_type(ind_veg_wall,m) /= 0 )                &
2178                surf_lsm_h%albedo(ind_veg_wall,m) =                            &
2179                           albedo_pars(0,surf_lsm_h%albedo_type(ind_veg_wall,m))
2180             IF ( surf_lsm_h%albedo_type(ind_pav_green,m) /= 0 )               &
2181                surf_lsm_h%albedo(ind_pav_green,m) =                           &
2182                           albedo_pars(0,surf_lsm_h%albedo_type(ind_pav_green,m))
2183             IF ( surf_lsm_h%albedo_type(ind_wat_win,m) /= 0 )                 &
2184                surf_lsm_h%albedo(ind_wat_win,m) =                             &
2185                           albedo_pars(0,surf_lsm_h%albedo_type(ind_wat_win,m))
2186          ENDDO
2187          DO  m = 1, surf_usm_h%ns
2188             IF ( surf_usm_h%albedo_type(ind_veg_wall,m) /= 0 )                &
2189                surf_usm_h%albedo(ind_veg_wall,m) =                            &
2190                           albedo_pars(0,surf_usm_h%albedo_type(ind_veg_wall,m))
2191             IF ( surf_usm_h%albedo_type(ind_pav_green,m) /= 0 )               &
2192                surf_usm_h%albedo(ind_pav_green,m) =                           &
2193                           albedo_pars(0,surf_usm_h%albedo_type(ind_pav_green,m))
2194             IF ( surf_usm_h%albedo_type(ind_wat_win,m) /= 0 )                 &
2195                surf_usm_h%albedo(ind_wat_win,m) =                             &
2196                           albedo_pars(0,surf_usm_h%albedo_type(ind_wat_win,m))
2197          ENDDO
2198
2199          DO  l = 0, 3
2200             DO  m = 1, surf_lsm_v(l)%ns
2201                IF ( surf_lsm_v(l)%albedo_type(ind_veg_wall,m) /= 0 )          &
2202                   surf_lsm_v(l)%albedo(ind_veg_wall,m) =                      &
2203                        albedo_pars(0,surf_lsm_v(l)%albedo_type(ind_veg_wall,m))
2204                IF ( surf_lsm_v(l)%albedo_type(ind_pav_green,m) /= 0 )         &
2205                   surf_lsm_v(l)%albedo(ind_pav_green,m) =                     &
2206                        albedo_pars(0,surf_lsm_v(l)%albedo_type(ind_pav_green,m))
2207                IF ( surf_lsm_v(l)%albedo_type(ind_wat_win,m) /= 0 )           &
2208                   surf_lsm_v(l)%albedo(ind_wat_win,m) =                       &
2209                        albedo_pars(0,surf_lsm_v(l)%albedo_type(ind_wat_win,m))
2210             ENDDO
2211             DO  m = 1, surf_usm_v(l)%ns
2212                IF ( surf_usm_v(l)%albedo_type(ind_veg_wall,m) /= 0 )          &
2213                   surf_usm_v(l)%albedo(ind_veg_wall,m) =                      &
2214                        albedo_pars(0,surf_usm_v(l)%albedo_type(ind_veg_wall,m))
2215                IF ( surf_usm_v(l)%albedo_type(ind_pav_green,m) /= 0 )         &
2216                   surf_usm_v(l)%albedo(ind_pav_green,m) =                     &
2217                        albedo_pars(0,surf_usm_v(l)%albedo_type(ind_pav_green,m))
2218                IF ( surf_usm_v(l)%albedo_type(ind_wat_win,m) /= 0 )           &
2219                   surf_usm_v(l)%albedo(ind_wat_win,m) =                       &
2220                        albedo_pars(0,surf_usm_v(l)%albedo_type(ind_wat_win,m))
2221             ENDDO
2222          ENDDO
2223
2224!
2225!--       Level 3 initialization at grid points where albedo type is zero.
2226!--       This case, albedo is taken from file. In case of constant radiation
2227!--       or clear sky, only broadband albedo is given.
2228          IF ( albedo_pars_f%from_file )  THEN
2229!
2230!--          Horizontal surfaces
2231             DO  m = 1, surf_lsm_h%ns
2232                i = surf_lsm_h%i(m)
2233                j = surf_lsm_h%j(m)
2234                IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2235                   IF ( surf_lsm_h%albedo_type(ind_veg_wall,m) == 0 )          &
2236                      surf_lsm_h%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2237                   IF ( surf_lsm_h%albedo_type(ind_pav_green,m) == 0 )         &
2238                      surf_lsm_h%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2239                   IF ( surf_lsm_h%albedo_type(ind_wat_win,m) == 0 )           &
2240                      surf_lsm_h%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2241                ENDIF
2242             ENDDO
2243             DO  m = 1, surf_usm_h%ns
2244                i = surf_usm_h%i(m)
2245                j = surf_usm_h%j(m)
2246                IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2247                   IF ( surf_usm_h%albedo_type(ind_veg_wall,m) == 0 )          &
2248                      surf_usm_h%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2249                   IF ( surf_usm_h%albedo_type(ind_pav_green,m) == 0 )         &
2250                      surf_usm_h%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2251                   IF ( surf_usm_h%albedo_type(ind_wat_win,m) == 0 )           &
2252                      surf_usm_h%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2253                ENDIF
2254             ENDDO 
2255!
2256!--          Vertical surfaces           
2257             DO  l = 0, 3
2258
2259                ioff = surf_lsm_v(l)%ioff
2260                joff = surf_lsm_v(l)%joff
2261                DO  m = 1, surf_lsm_v(l)%ns
2262                   i = surf_lsm_v(l)%i(m) + ioff
2263                   j = surf_lsm_v(l)%j(m) + joff
2264                   IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2265                      IF ( surf_lsm_v(l)%albedo_type(ind_veg_wall,m) == 0 )    &
2266                         surf_lsm_v(l)%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2267                      IF ( surf_lsm_v(l)%albedo_type(ind_pav_green,m) == 0 )   &
2268                         surf_lsm_v(l)%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2269                      IF ( surf_lsm_v(l)%albedo_type(ind_wat_win,m) == 0 )     &
2270                         surf_lsm_v(l)%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2271                   ENDIF
2272                ENDDO
2273
2274                ioff = surf_usm_v(l)%ioff
2275                joff = surf_usm_v(l)%joff
2276                DO  m = 1, surf_usm_v(l)%ns
2277                   i = surf_usm_v(l)%i(m) + joff
2278                   j = surf_usm_v(l)%j(m) + joff
2279                   IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2280                      IF ( surf_usm_v(l)%albedo_type(ind_veg_wall,m) == 0 )    &
2281                         surf_usm_v(l)%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2282                      IF ( surf_usm_v(l)%albedo_type(ind_pav_green,m) == 0 )   &
2283                         surf_usm_v(l)%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2284                      IF ( surf_usm_v(l)%albedo_type(ind_wat_win,m) == 0 )     &
2285                         surf_usm_v(l)%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2286                   ENDIF
2287                ENDDO
2288             ENDDO
2289
2290          ENDIF 
2291!
2292!--    Initialization actions for RRTMG
2293       ELSEIF ( radiation_scheme == 'rrtmg' )  THEN
2294#if defined ( __rrtmg )
2295!
2296!--       Allocate albedos for short/longwave radiation, horizontal surfaces
2297!--       for wall/green/window (USM) or vegetation/pavement/water surfaces
2298!--       (LSM).
2299          ALLOCATE ( surf_lsm_h%aldif(0:2,1:surf_lsm_h%ns)       )
2300          ALLOCATE ( surf_lsm_h%aldir(0:2,1:surf_lsm_h%ns)       )
2301          ALLOCATE ( surf_lsm_h%asdif(0:2,1:surf_lsm_h%ns)       )
2302          ALLOCATE ( surf_lsm_h%asdir(0:2,1:surf_lsm_h%ns)       )
2303          ALLOCATE ( surf_lsm_h%rrtm_aldif(0:2,1:surf_lsm_h%ns)  )
2304          ALLOCATE ( surf_lsm_h%rrtm_aldir(0:2,1:surf_lsm_h%ns)  )
2305          ALLOCATE ( surf_lsm_h%rrtm_asdif(0:2,1:surf_lsm_h%ns)  )
2306          ALLOCATE ( surf_lsm_h%rrtm_asdir(0:2,1:surf_lsm_h%ns)  )
2307
2308          ALLOCATE ( surf_usm_h%aldif(0:2,1:surf_usm_h%ns)       )
2309          ALLOCATE ( surf_usm_h%aldir(0:2,1:surf_usm_h%ns)       )
2310          ALLOCATE ( surf_usm_h%asdif(0:2,1:surf_usm_h%ns)       )
2311          ALLOCATE ( surf_usm_h%asdir(0:2,1:surf_usm_h%ns)       )
2312          ALLOCATE ( surf_usm_h%rrtm_aldif(0:2,1:surf_usm_h%ns)  )
2313          ALLOCATE ( surf_usm_h%rrtm_aldir(0:2,1:surf_usm_h%ns)  )
2314          ALLOCATE ( surf_usm_h%rrtm_asdif(0:2,1:surf_usm_h%ns)  )
2315          ALLOCATE ( surf_usm_h%rrtm_asdir(0:2,1:surf_usm_h%ns)  )
2316
2317!
2318!--       Allocate broadband albedo (temporary for the current radiation
2319!--       implementations)
2320          IF ( .NOT. ALLOCATED(surf_lsm_h%albedo) )                            &
2321             ALLOCATE( surf_lsm_h%albedo(0:2,1:surf_lsm_h%ns)     )
2322          IF ( .NOT. ALLOCATED(surf_usm_h%albedo) )                            &
2323             ALLOCATE( surf_usm_h%albedo(0:2,1:surf_usm_h%ns)     )
2324
2325!
2326!--       Allocate albedos for short/longwave radiation, vertical surfaces
2327          DO  l = 0, 3
2328
2329             ALLOCATE ( surf_lsm_v(l)%aldif(0:2,1:surf_lsm_v(l)%ns)      )
2330             ALLOCATE ( surf_lsm_v(l)%aldir(0:2,1:surf_lsm_v(l)%ns)      )
2331             ALLOCATE ( surf_lsm_v(l)%asdif(0:2,1:surf_lsm_v(l)%ns)      )
2332             ALLOCATE ( surf_lsm_v(l)%asdir(0:2,1:surf_lsm_v(l)%ns)      )
2333
2334             ALLOCATE ( surf_lsm_v(l)%rrtm_aldif(0:2,1:surf_lsm_v(l)%ns) )
2335             ALLOCATE ( surf_lsm_v(l)%rrtm_aldir(0:2,1:surf_lsm_v(l)%ns) )
2336             ALLOCATE ( surf_lsm_v(l)%rrtm_asdif(0:2,1:surf_lsm_v(l)%ns) )
2337             ALLOCATE ( surf_lsm_v(l)%rrtm_asdir(0:2,1:surf_lsm_v(l)%ns) )
2338
2339             ALLOCATE ( surf_usm_v(l)%aldif(0:2,1:surf_usm_v(l)%ns)      )
2340             ALLOCATE ( surf_usm_v(l)%aldir(0:2,1:surf_usm_v(l)%ns)      )
2341             ALLOCATE ( surf_usm_v(l)%asdif(0:2,1:surf_usm_v(l)%ns)      )
2342             ALLOCATE ( surf_usm_v(l)%asdir(0:2,1:surf_usm_v(l)%ns)      )
2343
2344             ALLOCATE ( surf_usm_v(l)%rrtm_aldif(0:2,1:surf_usm_v(l)%ns) )
2345             ALLOCATE ( surf_usm_v(l)%rrtm_aldir(0:2,1:surf_usm_v(l)%ns) )
2346             ALLOCATE ( surf_usm_v(l)%rrtm_asdif(0:2,1:surf_usm_v(l)%ns) )
2347             ALLOCATE ( surf_usm_v(l)%rrtm_asdir(0:2,1:surf_usm_v(l)%ns) )
2348!
2349!--          Allocate broadband albedo (temporary for the current radiation
2350!--          implementations)
2351             IF ( .NOT. ALLOCATED( surf_lsm_v(l)%albedo ) )                    &
2352                ALLOCATE( surf_lsm_v(l)%albedo(0:2,1:surf_lsm_v(l)%ns) )
2353             IF ( .NOT. ALLOCATED( surf_usm_v(l)%albedo ) )                    &
2354                ALLOCATE( surf_usm_v(l)%albedo(0:2,1:surf_usm_v(l)%ns) )
2355
2356          ENDDO
2357!
2358!--       Level 1 initialization of spectral albedos via namelist
2359!--       paramters. Please note, this case all surface tiles are initialized
2360!--       the same.
2361          IF ( surf_lsm_h%ns > 0 )  THEN
2362             surf_lsm_h%aldif  = albedo_lw_dif
2363             surf_lsm_h%aldir  = albedo_lw_dir
2364             surf_lsm_h%asdif  = albedo_sw_dif
2365             surf_lsm_h%asdir  = albedo_sw_dir
2366             surf_lsm_h%albedo = albedo_sw_dif
2367          ENDIF
2368          IF ( surf_usm_h%ns > 0 )  THEN
2369             IF ( surf_usm_h%albedo_from_ascii )  THEN
2370                surf_usm_h%aldif  = surf_usm_h%albedo
2371                surf_usm_h%aldir  = surf_usm_h%albedo
2372                surf_usm_h%asdif  = surf_usm_h%albedo
2373                surf_usm_h%asdir  = surf_usm_h%albedo
2374             ELSE
2375                surf_usm_h%aldif  = albedo_lw_dif
2376                surf_usm_h%aldir  = albedo_lw_dir
2377                surf_usm_h%asdif  = albedo_sw_dif
2378                surf_usm_h%asdir  = albedo_sw_dir
2379                surf_usm_h%albedo = albedo_sw_dif
2380             ENDIF
2381          ENDIF
2382
2383          DO  l = 0, 3
2384
2385             IF ( surf_lsm_v(l)%ns > 0 )  THEN
2386                surf_lsm_v(l)%aldif  = albedo_lw_dif
2387                surf_lsm_v(l)%aldir  = albedo_lw_dir
2388                surf_lsm_v(l)%asdif  = albedo_sw_dif
2389                surf_lsm_v(l)%asdir  = albedo_sw_dir
2390                surf_lsm_v(l)%albedo = albedo_sw_dif
2391             ENDIF
2392
2393             IF ( surf_usm_v(l)%ns > 0 )  THEN
2394                IF ( surf_usm_v(l)%albedo_from_ascii )  THEN
2395                   surf_usm_v(l)%aldif  = surf_usm_v(l)%albedo
2396                   surf_usm_v(l)%aldir  = surf_usm_v(l)%albedo
2397                   surf_usm_v(l)%asdif  = surf_usm_v(l)%albedo
2398                   surf_usm_v(l)%asdir  = surf_usm_v(l)%albedo
2399                ELSE
2400                   surf_usm_v(l)%aldif  = albedo_lw_dif
2401                   surf_usm_v(l)%aldir  = albedo_lw_dir
2402                   surf_usm_v(l)%asdif  = albedo_sw_dif
2403                   surf_usm_v(l)%asdir  = albedo_sw_dir
2404                ENDIF
2405             ENDIF
2406          ENDDO
2407
2408!
2409!--       Level 2 initialization of spectral albedos via albedo_type.
2410!--       Please note, for natural- and urban-type surfaces, a tile approach
2411!--       is applied so that the resulting albedo is calculated via the weighted
2412!--       average of respective surface fractions.
2413          DO  m = 1, surf_lsm_h%ns
2414!
2415!--          Spectral albedos for vegetation/pavement/water surfaces
2416             DO  ind_type = 0, 2
2417                IF ( surf_lsm_h%albedo_type(ind_type,m) /= 0 )  THEN
2418                   surf_lsm_h%aldif(ind_type,m) =                              &
2419                               albedo_pars(1,surf_lsm_h%albedo_type(ind_type,m))
2420                   surf_lsm_h%asdif(ind_type,m) =                              &
2421                               albedo_pars(2,surf_lsm_h%albedo_type(ind_type,m))
2422                   surf_lsm_h%aldir(ind_type,m) =                              &
2423                               albedo_pars(1,surf_lsm_h%albedo_type(ind_type,m))
2424                   surf_lsm_h%asdir(ind_type,m) =                              &
2425                               albedo_pars(2,surf_lsm_h%albedo_type(ind_type,m))
2426                   surf_lsm_h%albedo(ind_type,m) =                             &
2427                               albedo_pars(0,surf_lsm_h%albedo_type(ind_type,m))
2428                ENDIF
2429             ENDDO
2430
2431          ENDDO
2432!
2433!--       For urban surface only if albedo has not been already initialized
2434!--       in the urban-surface model via the ASCII file.
2435          IF ( .NOT. surf_usm_h%albedo_from_ascii )  THEN
2436             DO  m = 1, surf_usm_h%ns
2437!
2438!--             Spectral albedos for wall/green/window surfaces
2439                DO  ind_type = 0, 2
2440                   IF ( surf_usm_h%albedo_type(ind_type,m) /= 0 )  THEN
2441                      surf_usm_h%aldif(ind_type,m) =                           &
2442                               albedo_pars(1,surf_usm_h%albedo_type(ind_type,m))
2443                      surf_usm_h%asdif(ind_type,m) =                           &
2444                               albedo_pars(2,surf_usm_h%albedo_type(ind_type,m))
2445                      surf_usm_h%aldir(ind_type,m) =                           &
2446                               albedo_pars(1,surf_usm_h%albedo_type(ind_type,m))
2447                      surf_usm_h%asdir(ind_type,m) =                           &
2448                               albedo_pars(2,surf_usm_h%albedo_type(ind_type,m))
2449                      surf_usm_h%albedo(ind_type,m) =                          &
2450                               albedo_pars(0,surf_usm_h%albedo_type(ind_type,m))
2451                   ENDIF
2452                ENDDO
2453
2454             ENDDO
2455          ENDIF
2456
2457          DO l = 0, 3
2458
2459             DO  m = 1, surf_lsm_v(l)%ns
2460!
2461!--             Spectral albedos for vegetation/pavement/water surfaces
2462                DO  ind_type = 0, 2
2463                   IF ( surf_lsm_v(l)%albedo_type(ind_type,m) /= 0 )  THEN
2464                      surf_lsm_v(l)%aldif(ind_type,m) =                        &
2465                            albedo_pars(1,surf_lsm_v(l)%albedo_type(ind_type,m))
2466                      surf_lsm_v(l)%asdif(ind_type,m) =                        &
2467                            albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_type,m))
2468                      surf_lsm_v(l)%aldir(ind_type,m) =                        &
2469                            albedo_pars(1,surf_lsm_v(l)%albedo_type(ind_type,m))
2470                      surf_lsm_v(l)%asdir(ind_type,m) =                        &
2471                            albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_type,m))
2472                      surf_lsm_v(l)%albedo(ind_type,m) =                       &
2473                            albedo_pars(0,surf_lsm_v(l)%albedo_type(ind_type,m))
2474                   ENDIF
2475                ENDDO
2476             ENDDO
2477!
2478!--          For urban surface only if albedo has not been already initialized
2479!--          in the urban-surface model via the ASCII file.
2480             IF ( .NOT. surf_usm_v(l)%albedo_from_ascii )  THEN
2481                DO  m = 1, surf_usm_v(l)%ns
2482!
2483!--                Spectral albedos for wall/green/window surfaces
2484                   DO  ind_type = 0, 2
2485                      IF ( surf_usm_v(l)%albedo_type(ind_type,m) /= 0 )  THEN
2486                         surf_usm_v(l)%aldif(ind_type,m) =                     &
2487                            albedo_pars(1,surf_usm_v(l)%albedo_type(ind_type,m))
2488                         surf_usm_v(l)%asdif(ind_type,m) =                     &
2489                            albedo_pars(2,surf_usm_v(l)%albedo_type(ind_type,m))
2490                         surf_usm_v(l)%aldir(ind_type,m) =                     &
2491                            albedo_pars(1,surf_usm_v(l)%albedo_type(ind_type,m))
2492                         surf_usm_v(l)%asdir(ind_type,m) =                     &
2493                            albedo_pars(2,surf_usm_v(l)%albedo_type(ind_type,m))
2494                         surf_usm_v(l)%albedo(ind_type,m) =                    &
2495                            albedo_pars(0,surf_usm_v(l)%albedo_type(ind_type,m))
2496                      ENDIF
2497                   ENDDO
2498
2499                ENDDO
2500             ENDIF
2501          ENDDO
2502!
2503!--       Level 3 initialization at grid points where albedo type is zero.
2504!--       This case, spectral albedos are taken from file if available
2505          IF ( albedo_pars_f%from_file )  THEN
2506!
2507!--          Horizontal
2508             DO  m = 1, surf_lsm_h%ns
2509                i = surf_lsm_h%i(m)
2510                j = surf_lsm_h%j(m)
2511!
2512!--             Spectral albedos for vegetation/pavement/water surfaces
2513                DO  ind_type = 0, 2
2514                   IF ( surf_lsm_h%albedo_type(ind_type,m) == 0 )  THEN
2515                      IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )&
2516                         surf_lsm_h%albedo(ind_type,m) =                       &
2517                                                albedo_pars_f%pars_xy(0,j,i)
2518                      IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2519                         surf_lsm_h%aldir(ind_type,m) =                        &
2520                                                albedo_pars_f%pars_xy(1,j,i)
2521                      IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2522                         surf_lsm_h%aldif(ind_type,m) =                        &
2523                                                albedo_pars_f%pars_xy(1,j,i)
2524                      IF ( albedo_pars_f%pars_xy(2,j,i) /= albedo_pars_f%fill )&
2525                         surf_lsm_h%asdir(ind_type,m) =                        &
2526                                                albedo_pars_f%pars_xy(2,j,i)
2527                      IF ( albedo_pars_f%pars_xy(2,j,i) /= albedo_pars_f%fill )&
2528                         surf_lsm_h%asdif(ind_type,m) =                        &
2529                                                albedo_pars_f%pars_xy(2,j,i)
2530                   ENDIF
2531                ENDDO
2532             ENDDO
2533!
2534!--          For urban surface only if albedo has not been already initialized
2535!--          in the urban-surface model via the ASCII file.
2536             IF ( .NOT. surf_usm_h%albedo_from_ascii )  THEN
2537                DO  m = 1, surf_usm_h%ns
2538                   i = surf_usm_h%i(m)
2539                   j = surf_usm_h%j(m)
2540!
2541!--                Broadband albedos for wall/green/window surfaces
2542                   DO  ind_type = 0, 2
2543                      IF ( surf_usm_h%albedo_type(ind_type,m) == 0 )  THEN
2544                         IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )&
2545                            surf_usm_h%albedo(ind_type,m) =                       &
2546                                                albedo_pars_f%pars_xy(0,j,i)
2547                      ENDIF
2548                   ENDDO
2549!
2550!--                Spectral albedos especially for building wall surfaces
2551                   IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )  THEN
2552                      surf_usm_h%aldir(ind_veg_wall,m) =                       &
2553                                                albedo_pars_f%pars_xy(1,j,i)
2554                      surf_usm_h%aldif(ind_veg_wall,m) =                       &
2555                                                albedo_pars_f%pars_xy(1,j,i)
2556                   ENDIF
2557                   IF ( albedo_pars_f%pars_xy(2,j,i) /= albedo_pars_f%fill )  THEN
2558                      surf_usm_h%asdir(ind_veg_wall,m) =                       &
2559                                                albedo_pars_f%pars_xy(2,j,i)
2560                      surf_usm_h%asdif(ind_veg_wall,m) =                       &
2561                                                albedo_pars_f%pars_xy(2,j,i)
2562                   ENDIF
2563!
2564!--                Spectral albedos especially for building green surfaces
2565                   IF ( albedo_pars_f%pars_xy(3,j,i) /= albedo_pars_f%fill )  THEN
2566                      surf_usm_h%aldir(ind_pav_green,m) =                      &
2567                                                albedo_pars_f%pars_xy(3,j,i)
2568                      surf_usm_h%aldif(ind_pav_green,m) =                      &
2569                                                albedo_pars_f%pars_xy(3,j,i)
2570                   ENDIF
2571                   IF ( albedo_pars_f%pars_xy(4,j,i) /= albedo_pars_f%fill )  THEN
2572                      surf_usm_h%asdir(ind_pav_green,m) =                      &
2573                                                albedo_pars_f%pars_xy(4,j,i)
2574                      surf_usm_h%asdif(ind_pav_green,m) =                      &
2575                                                albedo_pars_f%pars_xy(4,j,i)
2576                   ENDIF
2577!
2578!--                Spectral albedos especially for building window surfaces
2579                   IF ( albedo_pars_f%pars_xy(5,j,i) /= albedo_pars_f%fill )  THEN
2580                      surf_usm_h%aldir(ind_wat_win,m) =                        &
2581                                                albedo_pars_f%pars_xy(5,j,i)
2582                      surf_usm_h%aldif(ind_wat_win,m) =                        &
2583                                                albedo_pars_f%pars_xy(5,j,i)
2584                   ENDIF
2585                   IF ( albedo_pars_f%pars_xy(6,j,i) /= albedo_pars_f%fill )  THEN
2586                      surf_usm_h%asdir(ind_wat_win,m) =                        &
2587                                                albedo_pars_f%pars_xy(6,j,i)
2588                      surf_usm_h%asdif(ind_wat_win,m) =                        &
2589                                                albedo_pars_f%pars_xy(6,j,i)
2590                   ENDIF
2591
2592                ENDDO
2593             ENDIF
2594!
2595!--          Vertical
2596             DO  l = 0, 3
2597                ioff = surf_lsm_v(l)%ioff
2598                joff = surf_lsm_v(l)%joff
2599
2600                DO  m = 1, surf_lsm_v(l)%ns
2601                   i = surf_lsm_v(l)%i(m)
2602                   j = surf_lsm_v(l)%j(m)
2603!
2604!--                Spectral albedos for vegetation/pavement/water surfaces
2605                   DO  ind_type = 0, 2
2606                      IF ( surf_lsm_v(l)%albedo_type(ind_type,m) == 0 )  THEN
2607                         IF ( albedo_pars_f%pars_xy(0,j+joff,i+ioff) /=        &
2608                              albedo_pars_f%fill )                             &
2609                            surf_lsm_v(l)%albedo(ind_type,m) =                 &
2610                                          albedo_pars_f%pars_xy(0,j+joff,i+ioff)
2611                         IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2612                              albedo_pars_f%fill )                             &
2613                            surf_lsm_v(l)%aldir(ind_type,m) =                  &
2614                                          albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2615                         IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2616                              albedo_pars_f%fill )                             &
2617                            surf_lsm_v(l)%aldif(ind_type,m) =                  &
2618                                          albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2619                         IF ( albedo_pars_f%pars_xy(2,j+joff,i+ioff) /=        &
2620                              albedo_pars_f%fill )                             &
2621                            surf_lsm_v(l)%asdir(ind_type,m) =                  &
2622                                          albedo_pars_f%pars_xy(2,j+joff,i+ioff)
2623                         IF ( albedo_pars_f%pars_xy(2,j+joff,i+ioff) /=        &
2624                              albedo_pars_f%fill )                             &
2625                            surf_lsm_v(l)%asdif(ind_type,m) =                  &
2626                                          albedo_pars_f%pars_xy(2,j+joff,i+ioff)
2627                      ENDIF
2628                   ENDDO
2629                ENDDO
2630!
2631!--             For urban surface only if albedo has not been already initialized
2632!--             in the urban-surface model via the ASCII file.
2633                IF ( .NOT. surf_usm_v(l)%albedo_from_ascii )  THEN
2634                   ioff = surf_usm_v(l)%ioff
2635                   joff = surf_usm_v(l)%joff
2636
2637                   DO  m = 1, surf_usm_v(l)%ns
2638                      i = surf_usm_v(l)%i(m)
2639                      j = surf_usm_v(l)%j(m)
2640!
2641!--                   Broadband albedos for wall/green/window surfaces
2642                      DO  ind_type = 0, 2
2643                         IF ( surf_usm_v(l)%albedo_type(ind_type,m) == 0 )  THEN
2644                            IF ( albedo_pars_f%pars_xy(0,j+joff,i+ioff) /=     &
2645                                 albedo_pars_f%fill )                          &
2646                               surf_usm_v(l)%albedo(ind_type,m) =              &
2647                                             albedo_pars_f%pars_xy(0,j+joff,i+ioff)
2648                         ENDIF
2649                      ENDDO
2650!
2651!--                   Spectral albedos especially for building wall surfaces
2652                      IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=           &
2653                           albedo_pars_f%fill )  THEN
2654                         surf_usm_v(l)%aldir(ind_veg_wall,m) =                 &
2655                                         albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2656                         surf_usm_v(l)%aldif(ind_veg_wall,m) =                 &
2657                                         albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2658                      ENDIF
2659                      IF ( albedo_pars_f%pars_xy(2,j+joff,i+ioff) /=           &
2660                           albedo_pars_f%fill )  THEN
2661                         surf_usm_v(l)%asdir(ind_veg_wall,m) =                 &
2662                                         albedo_pars_f%pars_xy(2,j+joff,i+ioff)
2663                         surf_usm_v(l)%asdif(ind_veg_wall,m) =                 &
2664                                         albedo_pars_f%pars_xy(2,j+joff,i+ioff)
2665                      ENDIF
2666!                     
2667!--                   Spectral albedos especially for building green surfaces
2668                      IF ( albedo_pars_f%pars_xy(3,j+joff,i+ioff) /=           &
2669                           albedo_pars_f%fill )  THEN
2670                         surf_usm_v(l)%aldir(ind_pav_green,m) =                &
2671                                         albedo_pars_f%pars_xy(3,j+joff,i+ioff)
2672                         surf_usm_v(l)%aldif(ind_pav_green,m) =                &
2673                                         albedo_pars_f%pars_xy(3,j+joff,i+ioff)
2674                      ENDIF
2675                      IF ( albedo_pars_f%pars_xy(4,j+joff,i+ioff) /=           &
2676                           albedo_pars_f%fill )  THEN
2677                         surf_usm_v(l)%asdir(ind_pav_green,m) =                &
2678                                         albedo_pars_f%pars_xy(4,j+joff,i+ioff)
2679                         surf_usm_v(l)%asdif(ind_pav_green,m) =                &
2680                                         albedo_pars_f%pars_xy(4,j+joff,i+ioff)
2681                      ENDIF
2682!                     
2683!--                   Spectral albedos especially for building window surfaces
2684                      IF ( albedo_pars_f%pars_xy(5,j+joff,i+ioff) /=           &
2685                           albedo_pars_f%fill )  THEN
2686                         surf_usm_v(l)%aldir(ind_wat_win,m) =                  &
2687                                         albedo_pars_f%pars_xy(5,j+joff,i+ioff)
2688                         surf_usm_v(l)%aldif(ind_wat_win,m) =                  &
2689                                         albedo_pars_f%pars_xy(5,j+joff,i+ioff)
2690                      ENDIF
2691                      IF ( albedo_pars_f%pars_xy(6,j+joff,i+ioff) /=           &
2692                           albedo_pars_f%fill )  THEN
2693                         surf_usm_v(l)%asdir(ind_wat_win,m) =                  &
2694                                         albedo_pars_f%pars_xy(6,j+joff,i+ioff)
2695                         surf_usm_v(l)%asdif(ind_wat_win,m) =                  &
2696                                         albedo_pars_f%pars_xy(6,j+joff,i+ioff)
2697                      ENDIF
2698                   ENDDO
2699                ENDIF
2700             ENDDO
2701
2702          ENDIF
2703
2704!
2705!--       Calculate initial values of current (cosine of) the zenith angle and
2706!--       whether the sun is up
2707          CALL calc_zenith
2708!
2709!--       readjust date and time to its initial value
2710          CALL init_date_and_time
2711!
2712!--       Calculate initial surface albedo for different surfaces
2713          IF ( .NOT. constant_albedo )  THEN
2714#if defined( __netcdf )
2715!
2716!--          Horizontally aligned natural and urban surfaces
2717             CALL calc_albedo( surf_lsm_h )
2718             CALL calc_albedo( surf_usm_h )
2719!
2720!--          Vertically aligned natural and urban surfaces
2721             DO  l = 0, 3
2722                CALL calc_albedo( surf_lsm_v(l) )
2723                CALL calc_albedo( surf_usm_v(l) )
2724             ENDDO
2725#endif
2726          ELSE
2727!
2728!--          Initialize sun-inclination independent spectral albedos
2729!--          Horizontal surfaces
2730             IF ( surf_lsm_h%ns > 0 )  THEN
2731                surf_lsm_h%rrtm_aldir = surf_lsm_h%aldir
2732                surf_lsm_h%rrtm_asdir = surf_lsm_h%asdir
2733                surf_lsm_h%rrtm_aldif = surf_lsm_h%aldif
2734                surf_lsm_h%rrtm_asdif = surf_lsm_h%asdif
2735             ENDIF
2736             IF ( surf_usm_h%ns > 0 )  THEN
2737                surf_usm_h%rrtm_aldir = surf_usm_h%aldir
2738                surf_usm_h%rrtm_asdir = surf_usm_h%asdir
2739                surf_usm_h%rrtm_aldif = surf_usm_h%aldif
2740                surf_usm_h%rrtm_asdif = surf_usm_h%asdif
2741             ENDIF
2742!
2743!--          Vertical surfaces
2744             DO  l = 0, 3
2745                IF ( surf_lsm_v(l)%ns > 0 )  THEN
2746                   surf_lsm_v(l)%rrtm_aldir = surf_lsm_v(l)%aldir
2747                   surf_lsm_v(l)%rrtm_asdir = surf_lsm_v(l)%asdir
2748                   surf_lsm_v(l)%rrtm_aldif = surf_lsm_v(l)%aldif
2749                   surf_lsm_v(l)%rrtm_asdif = surf_lsm_v(l)%asdif
2750                ENDIF
2751                IF ( surf_usm_v(l)%ns > 0 )  THEN
2752                   surf_usm_v(l)%rrtm_aldir = surf_usm_v(l)%aldir
2753                   surf_usm_v(l)%rrtm_asdir = surf_usm_v(l)%asdir
2754                   surf_usm_v(l)%rrtm_aldif = surf_usm_v(l)%aldif
2755                   surf_usm_v(l)%rrtm_asdif = surf_usm_v(l)%asdif
2756                ENDIF
2757             ENDDO
2758
2759          ENDIF
2760
2761!
2762!--       Allocate 3d arrays of radiative fluxes and heating rates
2763          IF ( .NOT. ALLOCATED ( rad_sw_in ) )  THEN
2764             ALLOCATE ( rad_sw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2765             rad_sw_in = 0.0_wp
2766          ENDIF
2767
2768          IF ( .NOT. ALLOCATED ( rad_sw_in_av ) )  THEN
2769             ALLOCATE ( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2770          ENDIF
2771
2772          IF ( .NOT. ALLOCATED ( rad_sw_out ) )  THEN
2773             ALLOCATE ( rad_sw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2774             rad_sw_out = 0.0_wp
2775          ENDIF
2776
2777          IF ( .NOT. ALLOCATED ( rad_sw_out_av ) )  THEN
2778             ALLOCATE ( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2779          ENDIF
2780
2781          IF ( .NOT. ALLOCATED ( rad_sw_hr ) )  THEN
2782             ALLOCATE ( rad_sw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2783             rad_sw_hr = 0.0_wp
2784          ENDIF
2785
2786          IF ( .NOT. ALLOCATED ( rad_sw_hr_av ) )  THEN
2787             ALLOCATE ( rad_sw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2788             rad_sw_hr_av = 0.0_wp
2789          ENDIF
2790
2791          IF ( .NOT. ALLOCATED ( rad_sw_cs_hr ) )  THEN
2792             ALLOCATE ( rad_sw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2793             rad_sw_cs_hr = 0.0_wp
2794          ENDIF
2795
2796          IF ( .NOT. ALLOCATED ( rad_sw_cs_hr_av ) )  THEN
2797             ALLOCATE ( rad_sw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2798             rad_sw_cs_hr_av = 0.0_wp
2799          ENDIF
2800
2801          IF ( .NOT. ALLOCATED ( rad_lw_in ) )  THEN
2802             ALLOCATE ( rad_lw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2803             rad_lw_in = 0.0_wp
2804          ENDIF
2805
2806          IF ( .NOT. ALLOCATED ( rad_lw_in_av ) )  THEN
2807             ALLOCATE ( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2808          ENDIF
2809
2810          IF ( .NOT. ALLOCATED ( rad_lw_out ) )  THEN
2811             ALLOCATE ( rad_lw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2812            rad_lw_out = 0.0_wp
2813          ENDIF
2814
2815          IF ( .NOT. ALLOCATED ( rad_lw_out_av ) )  THEN
2816             ALLOCATE ( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2817          ENDIF
2818
2819          IF ( .NOT. ALLOCATED ( rad_lw_hr ) )  THEN
2820             ALLOCATE ( rad_lw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2821             rad_lw_hr = 0.0_wp
2822          ENDIF
2823
2824          IF ( .NOT. ALLOCATED ( rad_lw_hr_av ) )  THEN
2825             ALLOCATE ( rad_lw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2826             rad_lw_hr_av = 0.0_wp
2827          ENDIF
2828
2829          IF ( .NOT. ALLOCATED ( rad_lw_cs_hr ) )  THEN
2830             ALLOCATE ( rad_lw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2831             rad_lw_cs_hr = 0.0_wp
2832          ENDIF
2833
2834          IF ( .NOT. ALLOCATED ( rad_lw_cs_hr_av ) )  THEN
2835             ALLOCATE ( rad_lw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2836             rad_lw_cs_hr_av = 0.0_wp
2837          ENDIF
2838
2839          ALLOCATE ( rad_sw_cs_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2840          ALLOCATE ( rad_sw_cs_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2841          rad_sw_cs_in  = 0.0_wp
2842          rad_sw_cs_out = 0.0_wp
2843
2844          ALLOCATE ( rad_lw_cs_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2845          ALLOCATE ( rad_lw_cs_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2846          rad_lw_cs_in  = 0.0_wp
2847          rad_lw_cs_out = 0.0_wp
2848
2849!
2850!--       Allocate 1-element array for surface temperature
2851!--       (RRTMG anticipates an array as passed argument).
2852          ALLOCATE ( rrtm_tsfc(1) )
2853!
2854!--       Allocate surface emissivity.
2855!--       Values will be given directly before calling rrtm_lw.
2856          ALLOCATE ( rrtm_emis(0:0,1:nbndlw+1) )
2857
2858!
2859!--       Initialize RRTMG, before check if files are existent
2860          INQUIRE( FILE='rrtmg_lw.nc', EXIST=lw_exists )
2861          IF ( .NOT. lw_exists )  THEN
2862             message_string = 'Input file rrtmg_lw.nc' //                &
2863                            '&for rrtmg missing. ' // &
2864                            '&Please provide <jobname>_lsw file in the INPUT directory.'
2865             CALL message( 'radiation_init', 'PA0583', 1, 2, 0, 6, 0 )
2866          ENDIF         
2867          INQUIRE( FILE='rrtmg_sw.nc', EXIST=sw_exists )
2868          IF ( .NOT. sw_exists )  THEN
2869             message_string = 'Input file rrtmg_sw.nc' //                &
2870                            '&for rrtmg missing. ' // &
2871                            '&Please provide <jobname>_rsw file in the INPUT directory.'
2872             CALL message( 'radiation_init', 'PA0584', 1, 2, 0, 6, 0 )
2873          ENDIF         
2874         
2875          IF ( lw_radiation )  CALL rrtmg_lw_ini ( c_p )
2876          IF ( sw_radiation )  CALL rrtmg_sw_ini ( c_p )
2877         
2878!
2879!--       Set input files for RRTMG
2880          INQUIRE(FILE="RAD_SND_DATA", EXIST=snd_exists) 
2881          IF ( .NOT. snd_exists )  THEN
2882             rrtm_input_file = "rrtmg_lw.nc"
2883          ENDIF
2884
2885!
2886!--       Read vertical layers for RRTMG from sounding data
2887!--       The routine provides nzt_rad, hyp_snd(1:nzt_rad),
2888!--       t_snd(nzt+2:nzt_rad), rrtm_play(1:nzt_rad), rrtm_plev(1_nzt_rad+1),
2889!--       rrtm_tlay(nzt+2:nzt_rad), rrtm_tlev(nzt+2:nzt_rad+1)
2890          CALL read_sounding_data
2891
2892!
2893!--       Read trace gas profiles from file. This routine provides
2894!--       the rrtm_ arrays (1:nzt_rad+1)
2895          CALL read_trace_gas_data
2896#endif
2897       ENDIF
2898
2899!
2900!--    Perform user actions if required
2901       CALL user_init_radiation
2902
2903!
2904!--    Calculate radiative fluxes at model start
2905       SELECT CASE ( TRIM( radiation_scheme ) )
2906
2907          CASE ( 'rrtmg' )
2908             CALL radiation_rrtmg
2909
2910          CASE ( 'clear-sky' )
2911             CALL radiation_clearsky
2912
2913          CASE ( 'constant' )
2914             CALL radiation_constant
2915
2916          CASE DEFAULT
2917
2918       END SELECT
2919
2920! readjust date and time to its initial value
2921       CALL init_date_and_time
2922
2923!
2924!--    Find all discretized apparent solar positions for radiation interaction.
2925       IF ( radiation_interactions )  CALL radiation_presimulate_solar_pos
2926
2927!
2928!--    If required, read or calculate and write out the SVF
2929       IF ( radiation_interactions .AND. read_svf)  THEN
2930!
2931!--       Read sky-view factors and further required data from file
2932          CALL radiation_read_svf()
2933
2934       ELSEIF ( radiation_interactions .AND. .NOT. read_svf)  THEN
2935!
2936!--       calculate SFV and CSF
2937          CALL radiation_calc_svf()
2938       ENDIF
2939
2940       IF ( radiation_interactions .AND. write_svf)  THEN
2941!
2942!--       Write svf, csf svfsurf and csfsurf data to file
2943          CALL radiation_write_svf()
2944       ENDIF
2945
2946!
2947!--    Adjust radiative fluxes. In case of urban and land surfaces, also
2948!--    call an initial interaction.
2949       IF ( radiation_interactions )  THEN
2950          CALL radiation_interaction
2951       ENDIF
2952
2953       IF ( debug_output )  CALL debug_message( 'radiation_init', 'end' )
2954
2955       RETURN !todo: remove, I don't see what we need this for here
2956
2957    END SUBROUTINE radiation_init
2958
2959
2960!------------------------------------------------------------------------------!
2961! Description:
2962! ------------
2963!> A simple clear sky radiation model
2964!------------------------------------------------------------------------------!
2965    SUBROUTINE radiation_clearsky
2966
2967
2968       IMPLICIT NONE
2969
2970       INTEGER(iwp) ::  l         !< running index for surface orientation
2971       REAL(wp)     ::  pt1       !< potential temperature at first grid level or mean value at urban layer top
2972       REAL(wp)     ::  pt1_l     !< potential temperature at first grid level or mean value at urban layer top at local subdomain
2973       REAL(wp)     ::  ql1       !< liquid water mixing ratio at first grid level or mean value at urban layer top
2974       REAL(wp)     ::  ql1_l     !< liquid water mixing ratio at first grid level or mean value at urban layer top at local subdomain
2975
2976       TYPE(surf_type), POINTER ::  surf !< pointer on respective surface type, used to generalize routine   
2977
2978!
2979!--    Calculate current zenith angle
2980       CALL calc_zenith
2981
2982!
2983!--    Calculate sky transmissivity
2984       sky_trans = 0.6_wp + 0.2_wp * cos_zenith
2985
2986!
2987!--    Calculate value of the Exner function at model surface
2988!
2989!--    In case averaged radiation is used, calculate mean temperature and
2990!--    liquid water mixing ratio at the urban-layer top.
2991       IF ( average_radiation ) THEN
2992          pt1   = 0.0_wp
2993          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1   = 0.0_wp
2994
2995          pt1_l = SUM( pt(nz_urban_t,nys:nyn,nxl:nxr) )
2996          IF ( bulk_cloud_model  .OR.  cloud_droplets  )  ql1_l = SUM( ql(nz_urban_t,nys:nyn,nxl:nxr) )
2997
2998#if defined( __parallel )     
2999          IF ( collective_wait )  CALL MPI_BARRIER( comm2d, ierr )
3000          CALL MPI_ALLREDUCE( pt1_l, pt1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
3001          IF ( ierr /= 0 ) THEN
3002              WRITE(9,*) 'Error MPI_AllReduce1:', ierr, pt1_l, pt1
3003              FLUSH(9)
3004          ENDIF
3005
3006          IF ( bulk_cloud_model  .OR.  cloud_droplets ) THEN
3007              CALL MPI_ALLREDUCE( ql1_l, ql1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
3008              IF ( ierr /= 0 ) THEN
3009                  WRITE(9,*) 'Error MPI_AllReduce2:', ierr, ql1_l, ql1
3010                  FLUSH(9)
3011              ENDIF
3012          ENDIF
3013#else
3014          pt1 = pt1_l 
3015          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1 = ql1_l
3016#endif
3017
3018          IF ( bulk_cloud_model  .OR.  cloud_droplets  )  pt1 = pt1 + lv_d_cp / exner(nz_urban_t) * ql1
3019!
3020!--       Finally, divide by number of grid points
3021          pt1 = pt1 / REAL( ( nx + 1 ) * ( ny + 1 ), KIND=wp )
3022       ENDIF
3023!
3024!--    Call clear-sky calculation for each surface orientation.
3025!--    First, horizontal surfaces
3026       surf => surf_lsm_h
3027       CALL radiation_clearsky_surf
3028       surf => surf_usm_h
3029       CALL radiation_clearsky_surf
3030!
3031!--    Vertical surfaces
3032       DO  l = 0, 3
3033          surf => surf_lsm_v(l)
3034          CALL radiation_clearsky_surf
3035          surf => surf_usm_v(l)
3036          CALL radiation_clearsky_surf
3037       ENDDO
3038
3039       CONTAINS
3040
3041          SUBROUTINE radiation_clearsky_surf
3042
3043             IMPLICIT NONE
3044
3045             INTEGER(iwp) ::  i         !< index x-direction
3046             INTEGER(iwp) ::  j         !< index y-direction
3047             INTEGER(iwp) ::  k         !< index z-direction
3048             INTEGER(iwp) ::  m         !< running index for surface elements
3049
3050             IF ( surf%ns < 1 )  RETURN
3051
3052!
3053!--          Calculate radiation fluxes and net radiation (rad_net) assuming
3054!--          homogeneous urban radiation conditions.
3055             IF ( average_radiation ) THEN       
3056
3057                k = nz_urban_t
3058
3059                surf%rad_sw_in  = solar_constant * sky_trans * cos_zenith
3060                surf%rad_sw_out = albedo_urb * surf%rad_sw_in
3061               
3062                surf%rad_lw_in  = emissivity_atm_clsky * sigma_sb * (pt1 * exner(k+1))**4
3063
3064                surf%rad_lw_out = emissivity_urb * sigma_sb * (t_rad_urb)**4   &
3065                                    + (1.0_wp - emissivity_urb) * surf%rad_lw_in
3066
3067                surf%rad_net = surf%rad_sw_in - surf%rad_sw_out                &
3068                             + surf%rad_lw_in - surf%rad_lw_out
3069
3070                surf%rad_lw_out_change_0 = 4.0_wp * emissivity_urb * sigma_sb  &
3071                                           * (t_rad_urb)**3
3072
3073!
3074!--          Calculate radiation fluxes and net radiation (rad_net) for each surface
3075!--          element.
3076             ELSE
3077
3078                DO  m = 1, surf%ns
3079                   i = surf%i(m)
3080                   j = surf%j(m)
3081                   k = surf%k(m)
3082
3083                   surf%rad_sw_in(m) = solar_constant * sky_trans * cos_zenith
3084
3085!
3086!--                Weighted average according to surface fraction.
3087!--                ATTENTION: when radiation interactions are switched on the
3088!--                calculated fluxes below are not actually used as they are
3089!--                overwritten in radiation_interaction.
3090                   surf%rad_sw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
3091                                          surf%albedo(ind_veg_wall,m)          &
3092                                        + surf%frac(ind_pav_green,m) *         &
3093                                          surf%albedo(ind_pav_green,m)         &
3094                                        + surf%frac(ind_wat_win,m)   *         &
3095                                          surf%albedo(ind_wat_win,m) )         &
3096                                        * surf%rad_sw_in(m)
3097
3098                   surf%rad_lw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
3099                                          surf%emissivity(ind_veg_wall,m)      &
3100                                        + surf%frac(ind_pav_green,m) *         &
3101                                          surf%emissivity(ind_pav_green,m)     &
3102                                        + surf%frac(ind_wat_win,m)   *         &
3103                                          surf%emissivity(ind_wat_win,m)       &
3104                                        )                                      &
3105                                        * sigma_sb                             &
3106                                        * ( surf%pt_surface(m) * exner(nzb) )**4
3107
3108                   surf%rad_lw_out_change_0(m) =                               &
3109                                      ( surf%frac(ind_veg_wall,m)  *           &
3110                                        surf%emissivity(ind_veg_wall,m)        &
3111                                      + surf%frac(ind_pav_green,m) *           &
3112                                        surf%emissivity(ind_pav_green,m)       &
3113                                      + surf%frac(ind_wat_win,m)   *           &
3114                                        surf%emissivity(ind_wat_win,m)         &
3115                                      ) * 4.0_wp * sigma_sb                    &
3116                                      * ( surf%pt_surface(m) * exner(nzb) )** 3
3117
3118
3119                   IF ( bulk_cloud_model  .OR.  cloud_droplets  )  THEN
3120                      pt1 = pt(k,j,i) + lv_d_cp / exner(k) * ql(k,j,i)
3121                      surf%rad_lw_in(m)  = emissivity_atm_clsky * sigma_sb * (pt1 * exner(k))**4
3122                   ELSE
3123                      surf%rad_lw_in(m)  = emissivity_atm_clsky * sigma_sb * (pt(k,j,i) * exner(k))**4
3124                   ENDIF
3125
3126                   surf%rad_net(m) = surf%rad_sw_in(m) - surf%rad_sw_out(m)    &
3127                                   + surf%rad_lw_in(m) - surf%rad_lw_out(m)
3128
3129                ENDDO
3130
3131             ENDIF
3132
3133!
3134!--          Fill out values in radiation arrays
3135             DO  m = 1, surf%ns
3136                i = surf%i(m)
3137                j = surf%j(m)
3138                rad_sw_in(0,j,i) = surf%rad_sw_in(m)
3139                rad_sw_out(0,j,i) = surf%rad_sw_out(m)
3140                rad_lw_in(0,j,i) = surf%rad_lw_in(m)
3141                rad_lw_out(0,j,i) = surf%rad_lw_out(m)
3142             ENDDO
3143 
3144          END SUBROUTINE radiation_clearsky_surf
3145
3146    END SUBROUTINE radiation_clearsky
3147
3148
3149!------------------------------------------------------------------------------!
3150! Description:
3151! ------------
3152!> This scheme keeps the prescribed net radiation constant during the run
3153!------------------------------------------------------------------------------!
3154    SUBROUTINE radiation_constant
3155
3156
3157       IMPLICIT NONE
3158
3159       INTEGER(iwp) ::  l         !< running index for surface orientation
3160
3161       REAL(wp)     ::  pt1       !< potential temperature at first grid level or mean value at urban layer top
3162       REAL(wp)     ::  pt1_l     !< potential temperature at first grid level or mean value at urban layer top at local subdomain
3163       REAL(wp)     ::  ql1       !< liquid water mixing ratio at first grid level or mean value at urban layer top
3164       REAL(wp)     ::  ql1_l     !< liquid water mixing ratio at first grid level or mean value at urban layer top at local subdomain
3165
3166       TYPE(surf_type), POINTER ::  surf !< pointer on respective surface type, used to generalize routine
3167
3168!
3169!--    In case averaged radiation is used, calculate mean temperature and
3170!--    liquid water mixing ratio at the urban-layer top.
3171       IF ( average_radiation ) THEN   
3172          pt1   = 0.0_wp
3173          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1   = 0.0_wp
3174
3175          pt1_l = SUM( pt(nz_urban_t,nys:nyn,nxl:nxr) )
3176          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1_l = SUM( ql(nz_urban_t,nys:nyn,nxl:nxr) )
3177
3178#if defined( __parallel )     
3179          IF ( collective_wait )  CALL MPI_BARRIER( comm2d, ierr )
3180          CALL MPI_ALLREDUCE( pt1_l, pt1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
3181          IF ( ierr /= 0 ) THEN
3182              WRITE(9,*) 'Error MPI_AllReduce3:', ierr, pt1_l, pt1
3183              FLUSH(9)
3184          ENDIF
3185          IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
3186             CALL MPI_ALLREDUCE( ql1_l, ql1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
3187             IF ( ierr /= 0 ) THEN
3188                 WRITE(9,*) 'Error MPI_AllReduce4:', ierr, ql1_l, ql1
3189                 FLUSH(9)
3190             ENDIF
3191          ENDIF
3192#else
3193          pt1 = pt1_l
3194          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1 = ql1_l
3195#endif
3196          IF ( bulk_cloud_model  .OR.  cloud_droplets )  pt1 = pt1 + lv_d_cp / exner(nz_urban_t+1) * ql1
3197!
3198!--       Finally, divide by number of grid points
3199          pt1 = pt1 / REAL( ( nx + 1 ) * ( ny + 1 ), KIND=wp )
3200       ENDIF
3201
3202!
3203!--    First, horizontal surfaces
3204       surf => surf_lsm_h
3205       CALL radiation_constant_surf
3206       surf => surf_usm_h
3207       CALL radiation_constant_surf
3208!
3209!--    Vertical surfaces
3210       DO  l = 0, 3
3211          surf => surf_lsm_v(l)
3212          CALL radiation_constant_surf
3213          surf => surf_usm_v(l)
3214          CALL radiation_constant_surf
3215       ENDDO
3216
3217       CONTAINS
3218
3219          SUBROUTINE radiation_constant_surf
3220
3221             IMPLICIT NONE
3222
3223             INTEGER(iwp) ::  i         !< index x-direction
3224             INTEGER(iwp) ::  ioff      !< offset between surface element and adjacent grid point along x
3225             INTEGER(iwp) ::  j         !< index y-direction
3226             INTEGER(iwp) ::  joff      !< offset between surface element and adjacent grid point along y
3227             INTEGER(iwp) ::  k         !< index z-direction
3228             INTEGER(iwp) ::  koff      !< offset between surface element and adjacent grid point along z
3229             INTEGER(iwp) ::  m         !< running index for surface elements
3230
3231             IF ( surf%ns < 1 )  RETURN
3232
3233!--          Calculate homogenoeus urban radiation fluxes
3234             IF ( average_radiation ) THEN
3235
3236                surf%rad_net = net_radiation
3237
3238                surf%rad_lw_in  = emissivity_atm_clsky * sigma_sb * (pt1 * exner(nz_urban_t+1))**4
3239
3240                surf%rad_lw_out = emissivity_urb * sigma_sb * (t_rad_urb)**4   &
3241                                    + ( 1.0_wp - emissivity_urb )             & ! shouldn't be this a bulk value -- emissivity_urb?
3242                                    * surf%rad_lw_in
3243
3244                surf%rad_lw_out_change_0 = 4.0_wp * emissivity_urb * sigma_sb  &
3245                                           * t_rad_urb**3
3246
3247                surf%rad_sw_in = ( surf%rad_net - surf%rad_lw_in               &
3248                                     + surf%rad_lw_out )                       &
3249                                     / ( 1.0_wp - albedo_urb )
3250
3251                surf%rad_sw_out =  albedo_urb * surf%rad_sw_in
3252
3253!
3254!--          Calculate radiation fluxes for each surface element
3255             ELSE
3256!
3257!--             Determine index offset between surface element and adjacent
3258!--             atmospheric grid point
3259                ioff = surf%ioff
3260                joff = surf%joff
3261                koff = surf%koff
3262
3263!
3264!--             Prescribe net radiation and estimate the remaining radiative fluxes
3265                DO  m = 1, surf%ns
3266                   i = surf%i(m)
3267                   j = surf%j(m)
3268                   k = surf%k(m)
3269
3270                   surf%rad_net(m) = net_radiation
3271
3272                   IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
3273                      pt1 = pt(k,j,i) + lv_d_cp / exner(k) * ql(k,j,i)
3274                      surf%rad_lw_in(m)  = emissivity_atm_clsky * sigma_sb * (pt1 * exner(k))**4
3275                   ELSE
3276                      surf%rad_lw_in(m)  = emissivity_atm_clsky * sigma_sb *                 &
3277                                             ( pt(k,j,i) * exner(k) )**4
3278                   ENDIF
3279
3280!
3281!--                Weighted average according to surface fraction.
3282                   surf%rad_lw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
3283                                          surf%emissivity(ind_veg_wall,m)      &
3284                                        + surf%frac(ind_pav_green,m) *         &
3285                                          surf%emissivity(ind_pav_green,m)     &
3286                                        + surf%frac(ind_wat_win,m)   *         &
3287                                          surf%emissivity(ind_wat_win,m)       &
3288                                        )                                      &
3289                                      * sigma_sb                               &
3290                                      * ( surf%pt_surface(m) * exner(nzb) )**4
3291
3292                   surf%rad_sw_in(m) = ( surf%rad_net(m) - surf%rad_lw_in(m)   &
3293                                       + surf%rad_lw_out(m) )                  &
3294                                       / ( 1.0_wp -                            &
3295                                          ( surf%frac(ind_veg_wall,m)  *       &
3296                                            surf%albedo(ind_veg_wall,m)        &
3297                                         +  surf%frac(ind_pav_green,m) *       &
3298                                            surf%albedo(ind_pav_green,m)       &
3299                                         +  surf%frac(ind_wat_win,m)   *       &
3300                                            surf%albedo(ind_wat_win,m) )       &
3301                                         )
3302
3303                   surf%rad_sw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
3304                                          surf%albedo(ind_veg_wall,m)          &
3305                                        + surf%frac(ind_pav_green,m) *         &
3306                                          surf%albedo(ind_pav_green,m)         &
3307                                        + surf%frac(ind_wat_win,m)   *         &
3308                                          surf%albedo(ind_wat_win,m) )         &
3309                                      * surf%rad_sw_in(m)
3310
3311                ENDDO
3312
3313             ENDIF
3314
3315!
3316!--          Fill out values in radiation arrays
3317             DO  m = 1, surf%ns
3318                i = surf%i(m)
3319                j = surf%j(m)
3320                rad_sw_in(0,j,i) = surf%rad_sw_in(m)
3321                rad_sw_out(0,j,i) = surf%rad_sw_out(m)
3322                rad_lw_in(0,j,i) = surf%rad_lw_in(m)
3323                rad_lw_out(0,j,i) = surf%rad_lw_out(m)
3324             ENDDO
3325
3326          END SUBROUTINE radiation_constant_surf
3327         
3328
3329    END SUBROUTINE radiation_constant
3330
3331!------------------------------------------------------------------------------!
3332! Description:
3333! ------------
3334!> Header output for radiation model
3335!------------------------------------------------------------------------------!
3336    SUBROUTINE radiation_header ( io )
3337
3338
3339       IMPLICIT NONE
3340 
3341       INTEGER(iwp), INTENT(IN) ::  io            !< Unit of the output file
3342   
3343
3344       
3345!
3346!--    Write radiation model header
3347       WRITE( io, 3 )
3348
3349       IF ( radiation_scheme == "constant" )  THEN
3350          WRITE( io, 4 ) net_radiation
3351       ELSEIF ( radiation_scheme == "clear-sky" )  THEN
3352          WRITE( io, 5 )
3353       ELSEIF ( radiation_scheme == "rrtmg" )  THEN
3354          WRITE( io, 6 )
3355          IF ( .NOT. lw_radiation )  WRITE( io, 10 )
3356          IF ( .NOT. sw_radiation )  WRITE( io, 11 )
3357       ENDIF
3358
3359       IF ( albedo_type_f%from_file  .OR.  vegetation_type_f%from_file  .OR.   &
3360            pavement_type_f%from_file  .OR.  water_type_f%from_file  .OR.      &
3361            building_type_f%from_file )  THEN
3362             WRITE( io, 13 )
3363       ELSE 
3364          IF ( albedo_type == 0 )  THEN
3365             WRITE( io, 7 ) albedo
3366          ELSE
3367             WRITE( io, 8 ) TRIM( albedo_type_name(albedo_type) )
3368          ENDIF
3369       ENDIF
3370       IF ( constant_albedo )  THEN
3371          WRITE( io, 9 )
3372       ENDIF
3373       
3374       WRITE( io, 12 ) dt_radiation
3375 
3376
3377 3 FORMAT (//' Radiation model information:'/                                  &
3378              ' ----------------------------'/)
3379 4 FORMAT ('    --> Using constant net radiation: net_radiation = ', F6.2,     &
3380           // 'W/m**2')
3381 5 FORMAT ('    --> Simple radiation scheme for clear sky is used (no clouds,',&
3382                   ' default)')
3383 6 FORMAT ('    --> RRTMG scheme is used')
3384 7 FORMAT (/'    User-specific surface albedo: albedo =', F6.3)
3385 8 FORMAT (/'    Albedo is set for land surface type: ', A)
3386 9 FORMAT (/'    --> Albedo is fixed during the run')
338710 FORMAT (/'    --> Longwave radiation is disabled')
338811 FORMAT (/'    --> Shortwave radiation is disabled.')
338912 FORMAT  ('    Timestep: dt_radiation = ', F6.2, '  s')
339013 FORMAT (/'    Albedo is set individually for each xy-location, according ', &
3391                 'to given surface type.')
3392
3393
3394    END SUBROUTINE radiation_header
3395   
3396
3397!------------------------------------------------------------------------------!
3398! Description:
3399! ------------
3400!> Parin for &radiation_parameters for radiation model
3401!------------------------------------------------------------------------------!
3402    SUBROUTINE radiation_parin
3403
3404
3405       IMPLICIT NONE
3406
3407       CHARACTER (LEN=80) ::  line  !< dummy string that contains the current line of the parameter file
3408       
3409       NAMELIST /radiation_par/   albedo, albedo_lw_dif, albedo_lw_dir,         &
3410                                  albedo_sw_dif, albedo_sw_dir, albedo_type,    &
3411                                  constant_albedo, dt_radiation, emissivity,    &
3412                                  lw_radiation, max_raytracing_dist,            &
3413                                  min_irrf_value, mrt_geom_human,               &
3414                                  mrt_include_sw, mrt_nlevels,                  &
3415                                  mrt_skip_roof, net_radiation, nrefsteps,      &
3416                                  plant_lw_interact, rad_angular_discretization,&
3417                                  radiation_interactions_on, radiation_scheme,  &
3418                                  raytrace_discrete_azims,                      &
3419                                  raytrace_discrete_elevs, raytrace_mpi_rma,    &
3420                                  skip_time_do_radiation, surface_reflections,  &
3421                                  svfnorm_report_thresh, sw_radiation,          &
3422                                  unscheduled_radiation_calls
3423
3424   
3425       NAMELIST /radiation_parameters/ albedo, albedo_lw_dif, albedo_lw_dir,    &
3426                                  albedo_sw_dif, albedo_sw_dir, albedo_type,    &
3427                                  constant_albedo, dt_radiation, emissivity,    &
3428                                  lw_radiation, max_raytracing_dist,            &
3429                                  min_irrf_value, mrt_geom_human,               &
3430                                  mrt_include_sw, mrt_nlevels,                  &
3431                                  mrt_skip_roof, net_radiation, nrefsteps,      &
3432                                  plant_lw_interact, rad_angular_discretization,&
3433                                  radiation_interactions_on, radiation_scheme,  &
3434                                  raytrace_discrete_azims,                      &
3435                                  raytrace_discrete_elevs, raytrace_mpi_rma,    &
3436                                  skip_time_do_radiation, surface_reflections,  &
3437                                  svfnorm_report_thresh, sw_radiation,          &
3438                                  unscheduled_radiation_calls
3439   
3440       line = ' '
3441       
3442!
3443!--    Try to find radiation model namelist
3444       REWIND ( 11 )
3445       line = ' '
3446       DO WHILE ( INDEX( line, '&radiation_parameters' ) == 0 )
3447          READ ( 11, '(A)', END=12 )  line
3448       ENDDO
3449       BACKSPACE ( 11 )
3450
3451!
3452!--    Read user-defined namelist
3453       READ ( 11, radiation_parameters, ERR = 10 )
3454
3455!
3456!--    Set flag that indicates that the radiation model is switched on
3457       radiation = .TRUE.
3458
3459       GOTO 14
3460
3461 10    BACKSPACE( 11 )
3462       READ( 11 , '(A)') line
3463       CALL parin_fail_message( 'radiation_parameters', line )
3464!
3465!--    Try to find old namelist
3466 12    REWIND ( 11 )
3467       line = ' '
3468       DO WHILE ( INDEX( line, '&radiation_par' ) == 0 )
3469          READ ( 11, '(A)', END=14 )  line
3470       ENDDO
3471       BACKSPACE ( 11 )
3472
3473!
3474!--    Read user-defined namelist
3475       READ ( 11, radiation_par, ERR = 13, END = 14 )
3476
3477       message_string = 'namelist radiation_par is deprecated and will be ' // &
3478                     'removed in near future. Please use namelist ' //         &
3479                     'radiation_parameters instead'
3480       CALL message( 'radiation_parin', 'PA0487', 0, 1, 0, 6, 0 )
3481
3482!
3483!--    Set flag that indicates that the radiation model is switched on
3484       radiation = .TRUE.
3485
3486       IF ( .NOT.  radiation_interactions_on  .AND.  surface_reflections )  THEN
3487          message_string = 'surface_reflections is allowed only when '      // &
3488               'radiation_interactions_on is set to TRUE'
3489          CALL message( 'radiation_parin', 'PA0293',1, 2, 0, 6, 0 )
3490       ENDIF
3491
3492       GOTO 14
3493
3494 13    BACKSPACE( 11 )
3495       READ( 11 , '(A)') line
3496       CALL parin_fail_message( 'radiation_par', line )
3497
3498 14    CONTINUE
3499       
3500    END SUBROUTINE radiation_parin
3501
3502
3503!------------------------------------------------------------------------------!
3504! Description:
3505! ------------
3506!> Implementation of the RRTMG radiation_scheme
3507!------------------------------------------------------------------------------!
3508    SUBROUTINE radiation_rrtmg
3509
3510#if defined ( __rrtmg )
3511       USE indices,                                                            &
3512           ONLY:  nbgp
3513
3514       USE particle_attributes,                                                &
3515           ONLY:  grid_particles, number_of_particles, particles, prt_count
3516
3517       IMPLICIT NONE
3518
3519
3520       INTEGER(iwp) ::  i, j, k, l, m, n !< loop indices
3521       INTEGER(iwp) ::  k_topo_l   !< topography top index
3522       INTEGER(iwp) ::  k_topo     !< topography top index
3523
3524       REAL(wp)     ::  nc_rad, &    !< number concentration of cloud droplets
3525                        s_r2,   &    !< weighted sum over all droplets with r^2
3526                        s_r3         !< weighted sum over all droplets with r^3
3527
3528       REAL(wp), DIMENSION(0:nzt+1) :: pt_av, q_av, ql_av
3529       REAL(wp), DIMENSION(0:0)     :: zenith   !< to provide indexed array
3530!
3531!--    Just dummy arguments
3532       REAL(wp), DIMENSION(:,:,:), ALLOCATABLE :: rrtm_lw_taucld_dum,          &
3533                                                  rrtm_lw_tauaer_dum,          &
3534                                                  rrtm_sw_taucld_dum,          &
3535                                                  rrtm_sw_ssacld_dum,          &
3536                                                  rrtm_sw_asmcld_dum,          &
3537                                                  rrtm_sw_fsfcld_dum,          &
3538                                                  rrtm_sw_tauaer_dum,          &
3539                                                  rrtm_sw_ssaaer_dum,          &
3540                                                  rrtm_sw_asmaer_dum,          &
3541                                                  rrtm_sw_ecaer_dum
3542
3543!
3544!--    Calculate current (cosine of) zenith angle and whether the sun is up
3545       CALL calc_zenith     
3546       zenith(0) = cos_zenith
3547!
3548!--    Calculate surface albedo. In case average radiation is applied,
3549!--    this is not required.
3550#if defined( __netcdf )
3551       IF ( .NOT. constant_albedo )  THEN
3552!
3553!--       Horizontally aligned default, natural and urban surfaces
3554          CALL calc_albedo( surf_lsm_h    )
3555          CALL calc_albedo( surf_usm_h    )
3556!
3557!--       Vertically aligned default, natural and urban surfaces
3558          DO  l = 0, 3
3559             CALL calc_albedo( surf_lsm_v(l) )
3560             CALL calc_albedo( surf_usm_v(l) )
3561          ENDDO
3562       ENDIF
3563#endif
3564
3565!
3566!--    Prepare input data for RRTMG
3567
3568!
3569!--    In case of large scale forcing with surface data, calculate new pressure
3570!--    profile. nzt_rad might be modified by these calls and all required arrays
3571!--    will then be re-allocated
3572       IF ( large_scale_forcing  .AND.  lsf_surf )  THEN
3573          CALL read_sounding_data
3574          CALL read_trace_gas_data
3575       ENDIF
3576
3577
3578       IF ( average_radiation ) THEN
3579!
3580!--       Determine minimum topography top index.
3581          k_topo_l = MINVAL( topo_top_ind(nys:nyn,nxl:nxr,0) )
3582#if defined( __parallel )
3583          CALL MPI_ALLREDUCE( k_topo_l, k_topo, 1, MPI_INTEGER, MPI_MIN, &
3584                              comm2d, ierr)
3585#else
3586          k_topo = k_topo_l
3587#endif
3588       
3589          rrtm_asdir(1)  = albedo_urb
3590          rrtm_asdif(1)  = albedo_urb
3591          rrtm_aldir(1)  = albedo_urb
3592          rrtm_aldif(1)  = albedo_urb
3593
3594          rrtm_emis = emissivity_urb
3595!
3596!--       Calculate mean pt profile.
3597          CALL calc_mean_profile( pt, 4 )
3598          pt_av = hom(:, 1, 4, 0)
3599         
3600          IF ( humidity )  THEN
3601             CALL calc_mean_profile( q, 41 )
3602             q_av  = hom(:, 1, 41, 0)
3603          ENDIF
3604!
3605!--       Prepare profiles of temperature and H2O volume mixing ratio
3606          rrtm_tlev(0,k_topo+1) = t_rad_urb
3607
3608          IF ( bulk_cloud_model )  THEN
3609
3610             CALL calc_mean_profile( ql, 54 )
3611             ! average ql is now in hom(:, 1, 54, 0)
3612             ql_av = hom(:, 1, 54, 0)
3613             
3614             DO k = nzb+1, nzt+1
3615                rrtm_tlay(0,k) = pt_av(k) * ( (hyp(k) ) / 100000._wp       &
3616                                 )**.286_wp + lv_d_cp * ql_av(k)
3617                rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * (q_av(k) - ql_av(k))
3618             ENDDO
3619          ELSE
3620             DO k = nzb+1, nzt+1
3621                rrtm_tlay(0,k) = pt_av(k) * ( (hyp(k) ) / 100000._wp       &
3622                                 )**.286_wp
3623             ENDDO
3624
3625             IF ( humidity )  THEN
3626                DO k = nzb+1, nzt+1
3627                   rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * q_av(k)
3628                ENDDO
3629             ELSE
3630                rrtm_h2ovmr(0,nzb+1:nzt+1) = 0.0_wp
3631             ENDIF
3632          ENDIF
3633
3634!
3635!--       Avoid temperature/humidity jumps at the top of the PALM domain by
3636!--       linear interpolation from nzt+2 to nzt+7. Jumps are induced by
3637!--       discrepancies between the values in the  domain and those above that
3638!--       are prescribed in RRTMG
3639          DO k = nzt+2, nzt+7
3640             rrtm_tlay(0,k) = rrtm_tlay(0,nzt+1)                            &
3641                           + ( rrtm_tlay(0,nzt+8) - rrtm_tlay(0,nzt+1) )    &
3642                           / ( rrtm_play(0,nzt+8) - rrtm_play(0,nzt+1) )    &
3643                           * ( rrtm_play(0,k) - rrtm_play(0,nzt+1) )
3644
3645             rrtm_h2ovmr(0,k) = rrtm_h2ovmr(0,nzt+1)                        &
3646                           + ( rrtm_h2ovmr(0,nzt+8) - rrtm_h2ovmr(0,nzt+1) )&
3647                           / ( rrtm_play(0,nzt+8)   - rrtm_play(0,nzt+1)   )&
3648                           * ( rrtm_play(0,k) - rrtm_play(0,nzt+1) )
3649
3650          ENDDO
3651
3652!--       Linear interpolate to zw grid. Loop reaches one level further up
3653!--       due to the staggered grid in RRTMG
3654          DO k = k_topo+2, nzt+8
3655             rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k) -        &
3656                                rrtm_tlay(0,k-1))                           &
3657                                / ( rrtm_play(0,k) - rrtm_play(0,k-1) )     &
3658                                * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
3659          ENDDO
3660!
3661!--       Calculate liquid water path and cloud fraction for each column.
3662!--       Note that LWP is required in g/m2 instead of kg/kg m.
3663          rrtm_cldfr  = 0.0_wp
3664          rrtm_reliq  = 0.0_wp
3665          rrtm_cliqwp = 0.0_wp
3666          rrtm_icld   = 0
3667
3668          IF ( bulk_cloud_model )  THEN
3669             DO k = nzb+1, nzt+1
3670                rrtm_cliqwp(0,k) =  ql_av(k) * 1000._wp *                   &
3671                                    (rrtm_plev(0,k) - rrtm_plev(0,k+1))     &
3672                                    * 100._wp / g 
3673
3674                IF ( rrtm_cliqwp(0,k) > 0._wp )  THEN
3675                   rrtm_cldfr(0,k) = 1._wp
3676                   IF ( rrtm_icld == 0 )  rrtm_icld = 1
3677
3678!
3679!--                Calculate cloud droplet effective radius
3680                   rrtm_reliq(0,k) = 1.0E6_wp * ( 3.0_wp * ql_av(k)         &
3681                                     * rho_surface                          &
3682                                     / ( 4.0_wp * pi * nc_const * rho_l )   &
3683                                     )**0.33333333333333_wp                 &
3684                                     * EXP( LOG( sigma_gc )**2 )
3685!
3686!--                Limit effective radius
3687                   IF ( rrtm_reliq(0,k) > 0.0_wp )  THEN
3688                      rrtm_reliq(0,k) = MAX(rrtm_reliq(0,k),2.5_wp)
3689                      rrtm_reliq(0,k) = MIN(rrtm_reliq(0,k),60.0_wp)
3690                   ENDIF
3691                ENDIF
3692             ENDDO
3693          ENDIF
3694
3695!
3696!--       Set surface temperature
3697          rrtm_tsfc = t_rad_urb
3698         
3699          IF ( lw_radiation )  THEN 
3700!
3701!--          Due to technical reasons, copy optical depth to dummy arguments
3702!--          which are allocated on the exact size as the rrtmg_lw is called.
3703!--          As one dimesion is allocated with zero size, compiler complains
3704!--          that rank of the array does not match that of the
3705!--          assumed-shaped arguments in the RRTMG library. In order to
3706!--          avoid this, write to dummy arguments and give pass the entire
3707!--          dummy array. Seems to be the only existing work-around. 
3708             ALLOCATE( rrtm_lw_taucld_dum(1:nbndlw+1,0:0,k_topo+1:nzt_rad+1) )
3709             ALLOCATE( rrtm_lw_tauaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndlw+1) )
3710
3711             rrtm_lw_taucld_dum =                                              &
3712                             rrtm_lw_taucld(1:nbndlw+1,0:0,k_topo+1:nzt_rad+1)
3713             rrtm_lw_tauaer_dum =                                              &
3714                             rrtm_lw_tauaer(0:0,k_topo+1:nzt_rad+1,1:nbndlw+1)
3715         
3716             CALL rrtmg_lw( 1,                                                 &                                       
3717                            nzt_rad-k_topo,                                    &
3718                            rrtm_icld,                                         &
3719                            rrtm_idrv,                                         &
3720                            rrtm_play(:,k_topo+1:),                   &
3721                            rrtm_plev(:,k_topo+1:),                   &
3722                            rrtm_tlay(:,k_topo+1:),                   &
3723                            rrtm_tlev(:,k_topo+1:),                   &
3724                            rrtm_tsfc,                                         &
3725                            rrtm_h2ovmr(:,k_topo+1:),                 &
3726                            rrtm_o3vmr(:,k_topo+1:),                  &
3727                            rrtm_co2vmr(:,k_topo+1:),                 &
3728                            rrtm_ch4vmr(:,k_topo+1:),                 &
3729                            rrtm_n2ovmr(:,k_topo+1:),                 &
3730                            rrtm_o2vmr(:,k_topo+1:),                  &
3731                            rrtm_cfc11vmr(:,k_topo+1:),               &
3732                            rrtm_cfc12vmr(:,k_topo+1:),               &
3733                            rrtm_cfc22vmr(:,k_topo+1:),               &
3734                            rrtm_ccl4vmr(:,k_topo+1:),                &
3735                            rrtm_emis,                                         &
3736                            rrtm_inflglw,                                      &
3737                            rrtm_iceflglw,                                     &
3738                            rrtm_liqflglw,                                     &
3739                            rrtm_cldfr(:,k_topo+1:),                  &
3740                            rrtm_lw_taucld_dum,                                &
3741                            rrtm_cicewp(:,k_topo+1:),                 &
3742                            rrtm_cliqwp(:,k_topo+1:),                 &
3743                            rrtm_reice(:,k_topo+1:),                  & 
3744                            rrtm_reliq(:,k_topo+1:),                  &
3745                            rrtm_lw_tauaer_dum,                                &
3746                            rrtm_lwuflx(:,k_topo:),                   &
3747                            rrtm_lwdflx(:,k_topo:),                   &
3748                            rrtm_lwhr(:,k_topo+1:),                   &
3749                            rrtm_lwuflxc(:,k_topo:),                  &
3750                            rrtm_lwdflxc(:,k_topo:),                  &
3751                            rrtm_lwhrc(:,k_topo+1:),                  &
3752                            rrtm_lwuflx_dt(:,k_topo:),                &
3753                            rrtm_lwuflxc_dt(:,k_topo:) )
3754                           
3755             DEALLOCATE ( rrtm_lw_taucld_dum )
3756             DEALLOCATE ( rrtm_lw_tauaer_dum )
3757!
3758!--          Save fluxes
3759             DO k = nzb, nzt+1
3760                rad_lw_in(k,:,:)  = rrtm_lwdflx(0,k)
3761                rad_lw_out(k,:,:) = rrtm_lwuflx(0,k)
3762             ENDDO
3763             rad_lw_in_diff(:,:) = rad_lw_in(k_topo,:,:)
3764!
3765!--          Save heating rates (convert from K/d to K/h).
3766!--          Further, even though an aggregated radiation is computed, map
3767!--          signle-column profiles on top of any topography, in order to
3768!--          obtain correct near surface radiation heating/cooling rates.
3769             DO  i = nxl, nxr
3770                DO  j = nys, nyn
3771                   k_topo_l = topo_top_ind(j,i,0)
3772                   DO k = k_topo_l+1, nzt+1
3773                      rad_lw_hr(k,j,i)     = rrtm_lwhr(0,k-k_topo_l)  * d_hours_day
3774                      rad_lw_cs_hr(k,j,i)  = rrtm_lwhrc(0,k-k_topo_l) * d_hours_day
3775                   ENDDO
3776                ENDDO
3777             ENDDO
3778
3779          ENDIF
3780
3781          IF ( sw_radiation .AND. sun_up )  THEN
3782!
3783!--          Due to technical reasons, copy optical depths and other
3784!--          to dummy arguments which are allocated on the exact size as the
3785!--          rrtmg_sw is called.
3786!--          As one dimesion is allocated with zero size, compiler complains
3787!--          that rank of the array does not match that of the
3788!--          assumed-shaped arguments in the RRTMG library. In order to
3789!--          avoid this, write to dummy arguments and give pass the entire
3790!--          dummy array. Seems to be the only existing work-around. 
3791             ALLOCATE( rrtm_sw_taucld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3792             ALLOCATE( rrtm_sw_ssacld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3793             ALLOCATE( rrtm_sw_asmcld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3794             ALLOCATE( rrtm_sw_fsfcld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3795             ALLOCATE( rrtm_sw_tauaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3796             ALLOCATE( rrtm_sw_ssaaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3797             ALLOCATE( rrtm_sw_asmaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3798             ALLOCATE( rrtm_sw_ecaer_dum(0:0,k_topo+1:nzt_rad+1,1:naerec+1)  )
3799     
3800             rrtm_sw_taucld_dum = rrtm_sw_taucld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3801             rrtm_sw_ssacld_dum = rrtm_sw_ssacld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3802             rrtm_sw_asmcld_dum = rrtm_sw_asmcld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3803             rrtm_sw_fsfcld_dum = rrtm_sw_fsfcld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3804             rrtm_sw_tauaer_dum = rrtm_sw_tauaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3805             rrtm_sw_ssaaer_dum = rrtm_sw_ssaaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3806             rrtm_sw_asmaer_dum = rrtm_sw_asmaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3807             rrtm_sw_ecaer_dum  = rrtm_sw_ecaer(0:0,k_topo+1:nzt_rad+1,1:naerec+1)
3808
3809             CALL rrtmg_sw( 1,                                                 &
3810                            nzt_rad-k_topo,                                    &
3811                            rrtm_icld,                                         &
3812                            rrtm_iaer,                                         &
3813                            rrtm_play(:,k_topo+1:nzt_rad+1),                   &
3814                            rrtm_plev(:,k_topo+1:nzt_rad+2),                   &
3815                            rrtm_tlay(:,k_topo+1:nzt_rad+1),                   &
3816                            rrtm_tlev(:,k_topo+1:nzt_rad+2),                   &
3817                            rrtm_tsfc,                                         &
3818                            rrtm_h2ovmr(:,k_topo+1:nzt_rad+1),                 &                               
3819                            rrtm_o3vmr(:,k_topo+1:nzt_rad+1),                  &       
3820                            rrtm_co2vmr(:,k_topo+1:nzt_rad+1),                 &
3821                            rrtm_ch4vmr(:,k_topo+1:nzt_rad+1),                 &
3822                            rrtm_n2ovmr(:,k_topo+1:nzt_rad+1),                 &
3823                            rrtm_o2vmr(:,k_topo+1:nzt_rad+1),                  &
3824                            rrtm_asdir,                                        & 
3825                            rrtm_asdif,                                        &
3826                            rrtm_aldir,                                        &
3827                            rrtm_aldif,                                        &
3828                            zenith,                                            &
3829                            0.0_wp,                                            &
3830                            day_of_year,                                       &
3831                            solar_constant,                                    &
3832                            rrtm_inflgsw,                                      &
3833                            rrtm_iceflgsw,                                     &
3834                            rrtm_liqflgsw,                                     &
3835                            rrtm_cldfr(:,k_topo+1:nzt_rad+1),                  &
3836                            rrtm_sw_taucld_dum,                                &
3837                            rrtm_sw_ssacld_dum,                                &
3838                            rrtm_sw_asmcld_dum,                                &
3839                            rrtm_sw_fsfcld_dum,                                &
3840                            rrtm_cicewp(:,k_topo+1:nzt_rad+1),                 &
3841                            rrtm_cliqwp(:,k_topo+1:nzt_rad+1),                 &
3842                            rrtm_reice(:,k_topo+1:nzt_rad+1),                  &
3843                            rrtm_reliq(:,k_topo+1:nzt_rad+1),                  &
3844                            rrtm_sw_tauaer_dum,                                &
3845                            rrtm_sw_ssaaer_dum,                                &
3846                            rrtm_sw_asmaer_dum,                                &
3847                            rrtm_sw_ecaer_dum,                                 &
3848                            rrtm_swuflx(:,k_topo:nzt_rad+1),                   & 
3849                            rrtm_swdflx(:,k_topo:nzt_rad+1),                   & 
3850                            rrtm_swhr(:,k_topo+1:nzt_rad+1),                   & 
3851                            rrtm_swuflxc(:,k_topo:nzt_rad+1),                  & 
3852                            rrtm_swdflxc(:,k_topo:nzt_rad+1),                  &
3853                            rrtm_swhrc(:,k_topo+1:nzt_rad+1),                  &
3854                            rrtm_dirdflux(:,k_topo:nzt_rad+1),                 &
3855                            rrtm_difdflux(:,k_topo:nzt_rad+1) )
3856                           
3857             DEALLOCATE( rrtm_sw_taucld_dum )
3858             DEALLOCATE( rrtm_sw_ssacld_dum )
3859             DEALLOCATE( rrtm_sw_asmcld_dum )
3860             DEALLOCATE( rrtm_sw_fsfcld_dum )
3861             DEALLOCATE( rrtm_sw_tauaer_dum )
3862             DEALLOCATE( rrtm_sw_ssaaer_dum )
3863             DEALLOCATE( rrtm_sw_asmaer_dum )
3864             DEALLOCATE( rrtm_sw_ecaer_dum )
3865 
3866!
3867!--          Save radiation fluxes for the entire depth of the model domain
3868             DO k = nzb, nzt+1
3869                rad_sw_in(k,:,:)  = rrtm_swdflx(0,k)
3870                rad_sw_out(k,:,:) = rrtm_swuflx(0,k)
3871             ENDDO
3872!--          Save direct and diffuse SW radiation at the surface (required by RTM)
3873             rad_sw_in_dir(:,:) = rrtm_dirdflux(0,k_topo)
3874             rad_sw_in_diff(:,:) = rrtm_difdflux(0,k_topo)
3875
3876!
3877!--          Save heating rates (convert from K/d to K/s)
3878             DO k = nzb+1, nzt+1
3879                rad_sw_hr(k,:,:)     = rrtm_swhr(0,k)  * d_hours_day
3880                rad_sw_cs_hr(k,:,:)  = rrtm_swhrc(0,k) * d_hours_day
3881             ENDDO
3882!
3883!--       Solar radiation is zero during night
3884          ELSE
3885             rad_sw_in  = 0.0_wp
3886             rad_sw_out = 0.0_wp
3887             rad_sw_in_dir(:,:) = 0.0_wp
3888             rad_sw_in_diff(:,:) = 0.0_wp
3889          ENDIF
3890!
3891!--    RRTMG is called for each (j,i) grid point separately, starting at the
3892!--    highest topography level. Here no RTM is used since average_radiation is false
3893       ELSE
3894!
3895!--       Loop over all grid points
3896          DO i = nxl, nxr
3897             DO j = nys, nyn
3898
3899!
3900!--             Prepare profiles of temperature and H2O volume mixing ratio
3901                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
3902                   rrtm_tlev(0,nzb+1) = surf_lsm_h%pt_surface(m) * exner(nzb)
3903                ENDDO
3904                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
3905                   rrtm_tlev(0,nzb+1) = surf_usm_h%pt_surface(m) * exner(nzb)
3906                ENDDO
3907
3908
3909                IF ( bulk_cloud_model )  THEN
3910                   DO k = nzb+1, nzt+1
3911                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)                    &
3912                                        + lv_d_cp * ql(k,j,i)
3913                      rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * (q(k,j,i) - ql(k,j,i))
3914                   ENDDO
3915                ELSEIF ( cloud_droplets )  THEN
3916                   DO k = nzb+1, nzt+1
3917                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)                     &
3918                                        + lv_d_cp * ql(k,j,i)
3919                      rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * q(k,j,i) 
3920                   ENDDO
3921                ELSE
3922                   DO k = nzb+1, nzt+1
3923                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)
3924                   ENDDO
3925
3926                   IF ( humidity )  THEN
3927                      DO k = nzb+1, nzt+1
3928                         rrtm_h2ovmr(0,k) =  mol_mass_air_d_wv * q(k,j,i)
3929                      ENDDO   
3930                   ELSE
3931                      rrtm_h2ovmr(0,nzb+1:nzt+1) = 0.0_wp
3932                   ENDIF
3933                ENDIF
3934
3935!
3936!--             Avoid temperature/humidity jumps at the top of the LES domain by
3937!--             linear interpolation from nzt+2 to nzt+7
3938                DO k = nzt+2, nzt+7
3939                   rrtm_tlay(0,k) = rrtm_tlay(0,nzt+1)                         &
3940                                 + ( rrtm_tlay(0,nzt+8) - rrtm_tlay(0,nzt+1) ) &
3941                                 / ( rrtm_play(0,nzt+8) - rrtm_play(0,nzt+1) ) &
3942                                 * ( rrtm_play(0,k)     - rrtm_play(0,nzt+1) )
3943
3944                   rrtm_h2ovmr(0,k) = rrtm_h2ovmr(0,nzt+1)                     &
3945                              + ( rrtm_h2ovmr(0,nzt+8) - rrtm_h2ovmr(0,nzt+1) )&
3946                              / ( rrtm_play(0,nzt+8)   - rrtm_play(0,nzt+1)   )&
3947                              * ( rrtm_play(0,k)       - rrtm_play(0,nzt+1) )
3948
3949                ENDDO
3950
3951!--             Linear interpolate to zw grid
3952                DO k = nzb+2, nzt+8
3953                   rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k) -     &
3954                                      rrtm_tlay(0,k-1))                        &
3955                                      / ( rrtm_play(0,k) - rrtm_play(0,k-1) )  &
3956                                      * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
3957                ENDDO
3958
3959
3960!
3961!--             Calculate liquid water path and cloud fraction for each column.
3962!--             Note that LWP is required in g/m2 instead of kg/kg m.
3963                rrtm_cldfr  = 0.0_wp
3964                rrtm_reliq  = 0.0_wp
3965                rrtm_cliqwp = 0.0_wp
3966                rrtm_icld   = 0
3967
3968                IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
3969                   DO k = nzb+1, nzt+1
3970                      rrtm_cliqwp(0,k) =  ql(k,j,i) * 1000.0_wp *              &
3971                                          (rrtm_plev(0,k) - rrtm_plev(0,k+1))  &
3972                                          * 100.0_wp / g 
3973
3974                      IF ( rrtm_cliqwp(0,k) > 0.0_wp )  THEN
3975                         rrtm_cldfr(0,k) = 1.0_wp
3976                         IF ( rrtm_icld == 0 )  rrtm_icld = 1
3977
3978!
3979!--                      Calculate cloud droplet effective radius
3980                         IF ( bulk_cloud_model )  THEN
3981!
3982!--                         Calculete effective droplet radius. In case of using
3983!--                         cloud_scheme = 'morrison' and a non reasonable number
3984!--                         of cloud droplets the inital aerosol number 
3985!--                         concentration is considered.
3986                            IF ( microphysics_morrison )  THEN
3987                               IF ( nc(k,j,i) > 1.0E-20_wp )  THEN
3988                                  nc_rad = nc(k,j,i)
3989                               ELSE
3990                                  nc_rad = na_init
3991                               ENDIF
3992                            ELSE
3993                               nc_rad = nc_const
3994                            ENDIF 
3995
3996                            rrtm_reliq(0,k) = 1.0E6_wp * ( 3.0_wp * ql(k,j,i)     &
3997                                              * rho_surface                       &
3998                                              / ( 4.0_wp * pi * nc_rad * rho_l )  &
3999                                              )**0.33333333333333_wp              &
4000                                              * EXP( LOG( sigma_gc )**2 )
4001
4002                         ELSEIF ( cloud_droplets )  THEN
4003                            number_of_particles = prt_count(k,j,i)
4004
4005                            IF (number_of_particles <= 0)  CYCLE
4006                            particles => grid_particles(k,j,i)%particles(1:number_of_particles)
4007                            s_r2 = 0.0_wp
4008                            s_r3 = 0.0_wp
4009
4010                            DO  n = 1, number_of_particles
4011                               IF ( particles(n)%particle_mask )  THEN
4012                                  s_r2 = s_r2 + particles(n)%radius**2 *       &
4013                                         particles(n)%weight_factor
4014                                  s_r3 = s_r3 + particles(n)%radius**3 *       &
4015                                         particles(n)%weight_factor
4016                               ENDIF
4017                            ENDDO
4018
4019                            IF ( s_r2 > 0.0_wp )  rrtm_reliq(0,k) = s_r3 / s_r2
4020
4021                         ENDIF
4022
4023!
4024!--                      Limit effective radius
4025                         IF ( rrtm_reliq(0,k) > 0.0_wp )  THEN
4026                            rrtm_reliq(0,k) = MAX(rrtm_reliq(0,k),2.5_wp)
4027                            rrtm_reliq(0,k) = MIN(rrtm_reliq(0,k),60.0_wp)
4028                        ENDIF
4029                      ENDIF
4030                   ENDDO
4031                ENDIF
4032
4033!
4034!--             Write surface emissivity and surface temperature at current
4035!--             surface element on RRTMG-shaped array.
4036!--             Please note, as RRTMG is a single column model, surface attributes
4037!--             are only obtained from horizontally aligned surfaces (for
4038!--             simplicity). Taking surface attributes from horizontal and
4039!--             vertical walls would lead to multiple solutions. 
4040!--             Moreover, for natural- and urban-type surfaces, several surface
4041!--             classes can exist at a surface element next to each other.
4042!--             To obtain bulk parameters, apply a weighted average for these
4043!--             surfaces.
4044                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
4045                   rrtm_emis = surf_lsm_h%frac(ind_veg_wall,m)  *              &
4046                               surf_lsm_h%emissivity(ind_veg_wall,m)  +        &
4047                               surf_lsm_h%frac(ind_pav_green,m) *              &
4048                               surf_lsm_h%emissivity(ind_pav_green,m) +        & 
4049                               surf_lsm_h%frac(ind_wat_win,m)   *              &
4050                               surf_lsm_h%emissivity(ind_wat_win,m)
4051                   rrtm_tsfc = surf_lsm_h%pt_surface(m) * exner(nzb)
4052                ENDDO             
4053                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
4054                   rrtm_emis = surf_usm_h%frac(ind_veg_wall,m)  *              &
4055                               surf_usm_h%emissivity(ind_veg_wall,m)  +        &
4056                               surf_usm_h%frac(ind_pav_green,m) *              &
4057                               surf_usm_h%emissivity(ind_pav_green,m) +        & 
4058                               surf_usm_h%frac(ind_wat_win,m)   *              &
4059                               surf_usm_h%emissivity(ind_wat_win,m)
4060                   rrtm_tsfc = surf_usm_h%pt_surface(m) * exner(nzb)
4061                ENDDO
4062!
4063!--             Obtain topography top index (lower bound of RRTMG)
4064                k_topo = topo_top_ind(j,i,0)
4065
4066                IF ( lw_radiation )  THEN
4067!
4068!--                Due to technical reasons, copy optical depth to dummy arguments
4069!--                which are allocated on the exact size as the rrtmg_lw is called.
4070!--                As one dimesion is allocated with zero size, compiler complains
4071!--                that rank of the array does not match that of the
4072!--                assumed-shaped arguments in the RRTMG library. In order to
4073!--                avoid this, write to dummy arguments and give pass the entire
4074!--                dummy array. Seems to be the only existing work-around. 
4075                   ALLOCATE( rrtm_lw_taucld_dum(1:nbndlw+1,0:0,k_topo+1:nzt_rad+1) )
4076                   ALLOCATE( rrtm_lw_tauaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndlw+1) )
4077
4078                   rrtm_lw_taucld_dum =                                        &
4079                               rrtm_lw_taucld(1:nbndlw+1,0:0,k_topo+1:nzt_rad+1)
4080                   rrtm_lw_tauaer_dum =                                        &
4081                               rrtm_lw_tauaer(0:0,k_topo+1:nzt_rad+1,1:nbndlw+1)
4082
4083                   CALL rrtmg_lw( 1,                                           &                                       
4084                                  nzt_rad-k_topo,                              &
4085                                  rrtm_icld,                                   &
4086                                  rrtm_idrv,                                   &
4087                                  rrtm_play(:,k_topo+1:nzt_rad+1),             &
4088                                  rrtm_plev(:,k_topo+1:nzt_rad+2),             &
4089                                  rrtm_tlay(:,k_topo+1:nzt_rad+1),             &
4090                                  rrtm_tlev(:,k_topo+1:nzt_rad+2),             &
4091                                  rrtm_tsfc,                                   &
4092                                  rrtm_h2ovmr(:,k_topo+1:nzt_rad+1),           &
4093                                  rrtm_o3vmr(:,k_topo+1:nzt_rad+1),            &
4094                                  rrtm_co2vmr(:,k_topo+1:nzt_rad+1),           &
4095                                  rrtm_ch4vmr(:,k_topo+1:nzt_rad+1),           &
4096                                  rrtm_n2ovmr(:,k_topo+1:nzt_rad+1),           &
4097                                  rrtm_o2vmr(:,k_topo+1:nzt_rad+1),            &
4098                                  rrtm_cfc11vmr(:,k_topo+1:nzt_rad+1),         &
4099                                  rrtm_cfc12vmr(:,k_topo+1:nzt_rad+1),         &
4100                                  rrtm_cfc22vmr(:,k_topo+1:nzt_rad+1),         &
4101                                  rrtm_ccl4vmr(:,k_topo+1:nzt_rad+1),          &
4102                                  rrtm_emis,                                   &
4103                                  rrtm_inflglw,                                &
4104                                  rrtm_iceflglw,                               &
4105                                  rrtm_liqflglw,                               &
4106                                  rrtm_cldfr(:,k_topo+1:nzt_rad+1),            &
4107                                  rrtm_lw_taucld_dum,                          &
4108                                  rrtm_cicewp(:,k_topo+1:nzt_rad+1),           &
4109                                  rrtm_cliqwp(:,k_topo+1:nzt_rad+1),           &
4110                                  rrtm_reice(:,k_topo+1:nzt_rad+1),            & 
4111                                  rrtm_reliq(:,k_topo+1:nzt_rad+1),            &
4112                                  rrtm_lw_tauaer_dum,                          &
4113                                  rrtm_lwuflx(:,k_topo:nzt_rad+1),             &
4114                                  rrtm_lwdflx(:,k_topo:nzt_rad+1),             &
4115                                  rrtm_lwhr(:,k_topo+1:nzt_rad+1),             &
4116                                  rrtm_lwuflxc(:,k_topo:nzt_rad+1),            &
4117                                  rrtm_lwdflxc(:,k_topo:nzt_rad+1),            &
4118                                  rrtm_lwhrc(:,k_topo+1:nzt_rad+1),            &
4119                                  rrtm_lwuflx_dt(:,k_topo:nzt_rad+1),          &
4120                                  rrtm_lwuflxc_dt(:,k_topo:nzt_rad+1) )
4121
4122                   DEALLOCATE ( rrtm_lw_taucld_dum )
4123                   DEALLOCATE ( rrtm_lw_tauaer_dum )
4124!
4125!--                Save fluxes
4126                   DO k = k_topo, nzt+1
4127                      rad_lw_in(k,j,i)  = rrtm_lwdflx(0,k)
4128                      rad_lw_out(k,j,i) = rrtm_lwuflx(0,k)
4129                   ENDDO
4130
4131!
4132!--                Save heating rates (convert from K/d to K/h)
4133                   DO k = k_topo+1, nzt+1
4134                      rad_lw_hr(k,j,i)     = rrtm_lwhr(0,k-k_topo)  * d_hours_day
4135                      rad_lw_cs_hr(k,j,i)  = rrtm_lwhrc(0,k-k_topo) * d_hours_day
4136                   ENDDO
4137
4138!
4139!--                Save surface radiative fluxes and change in LW heating rate
4140!--                onto respective surface elements
4141!--                Horizontal surfaces
4142                   DO  m = surf_lsm_h%start_index(j,i),                        &
4143                           surf_lsm_h%end_index(j,i)
4144                      surf_lsm_h%rad_lw_in(m)           = rrtm_lwdflx(0,k_topo)
4145                      surf_lsm_h%rad_lw_out(m)          = rrtm_lwuflx(0,k_topo)
4146                      surf_lsm_h%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k_topo)
4147                   ENDDO             
4148                   DO  m = surf_usm_h%start_index(j,i),                        &
4149                           surf_usm_h%end_index(j,i)
4150                      surf_usm_h%rad_lw_in(m)           = rrtm_lwdflx(0,k_topo)
4151                      surf_usm_h%rad_lw_out(m)          = rrtm_lwuflx(0,k_topo)
4152                      surf_usm_h%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k_topo)
4153                   ENDDO 
4154!
4155!--                Vertical surfaces. Fluxes are obtain at vertical level of the
4156!--                respective surface element
4157                   DO  l = 0, 3
4158                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
4159                              surf_lsm_v(l)%end_index(j,i)
4160                         k                                    = surf_lsm_v(l)%k(m)
4161                         surf_lsm_v(l)%rad_lw_in(m)           = rrtm_lwdflx(0,k)
4162                         surf_lsm_v(l)%rad_lw_out(m)          = rrtm_lwuflx(0,k)
4163                         surf_lsm_v(l)%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k)
4164                      ENDDO             
4165                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
4166                              surf_usm_v(l)%end_index(j,i)
4167                         k                                    = surf_usm_v(l)%k(m)
4168                         surf_usm_v(l)%rad_lw_in(m)           = rrtm_lwdflx(0,k)
4169                         surf_usm_v(l)%rad_lw_out(m)          = rrtm_lwuflx(0,k)
4170                         surf_usm_v(l)%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k)
4171                      ENDDO 
4172                   ENDDO
4173
4174                ENDIF
4175
4176                IF ( sw_radiation .AND. sun_up )  THEN
4177!
4178!--                Get albedo for direct/diffusive long/shortwave radiation at
4179!--                current (y,x)-location from surface variables.
4180!--                Only obtain it from horizontal surfaces, as RRTMG is a single
4181!--                column model
4182!--                (Please note, only one loop will entered, controlled by
4183!--                start-end index.)
4184                   DO  m = surf_lsm_h%start_index(j,i),                        &
4185                           surf_lsm_h%end_index(j,i)
4186                      rrtm_asdir(1)  = SUM( surf_lsm_h%frac(:,m) *             &
4187                                            surf_lsm_h%rrtm_asdir(:,m) )
4188                      rrtm_asdif(1)  = SUM( surf_lsm_h%frac(:,m) *             &
4189                                            surf_lsm_h%rrtm_asdif(:,m) )
4190                      rrtm_aldir(1)  = SUM( surf_lsm_h%frac(:,m) *             &
4191                                            surf_lsm_h%rrtm_aldir(:,m) )
4192                      rrtm_aldif(1)  = SUM( surf_lsm_h%frac(:,m) *             &
4193                                            surf_lsm_h%rrtm_aldif(:,m) )
4194                   ENDDO             
4195                   DO  m = surf_usm_h%start_index(j,i),                        &
4196                           surf_usm_h%end_index(j,i)
4197                      rrtm_asdir(1)  = SUM( surf_usm_h%frac(:,m) *             &
4198                                            surf_usm_h%rrtm_asdir(:,m) )
4199                      rrtm_asdif(1)  = SUM( surf_usm_h%frac(:,m) *             &
4200                                            surf_usm_h%rrtm_asdif(:,m) )
4201                      rrtm_aldir(1)  = SUM( surf_usm_h%frac(:,m) *             &
4202                                            surf_usm_h%rrtm_aldir(:,m) )
4203                      rrtm_aldif(1)  = SUM( surf_usm_h%frac(:,m) *             &
4204                                            surf_usm_h%rrtm_aldif(:,m) )
4205                   ENDDO
4206!
4207!--                Due to technical reasons, copy optical depths and other
4208!--                to dummy arguments which are allocated on the exact size as the
4209!--                rrtmg_sw is called.
4210!--                As one dimesion is allocated with zero size, compiler complains
4211!--                that rank of the array does not match that of the
4212!--                assumed-shaped arguments in the RRTMG library. In order to
4213!--                avoid this, write to dummy arguments and give pass the entire
4214!--                dummy array. Seems to be the only existing work-around. 
4215                   ALLOCATE( rrtm_sw_taucld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
4216                   ALLOCATE( rrtm_sw_ssacld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
4217                   ALLOCATE( rrtm_sw_asmcld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
4218                   ALLOCATE( rrtm_sw_fsfcld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
4219                   ALLOCATE( rrtm_sw_tauaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
4220                   ALLOCATE( rrtm_sw_ssaaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
4221                   ALLOCATE( rrtm_sw_asmaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
4222                   ALLOCATE( rrtm_sw_ecaer_dum(0:0,k_topo+1:nzt_rad+1,1:naerec+1)  )
4223     
4224                   rrtm_sw_taucld_dum = rrtm_sw_taucld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
4225                   rrtm_sw_ssacld_dum = rrtm_sw_ssacld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
4226                   rrtm_sw_asmcld_dum = rrtm_sw_asmcld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
4227                   rrtm_sw_fsfcld_dum = rrtm_sw_fsfcld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
4228                   rrtm_sw_tauaer_dum = rrtm_sw_tauaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
4229                   rrtm_sw_ssaaer_dum = rrtm_sw_ssaaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
4230                   rrtm_sw_asmaer_dum = rrtm_sw_asmaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
4231                   rrtm_sw_ecaer_dum  = rrtm_sw_ecaer(0:0,k_topo+1:nzt_rad+1,1:naerec+1)
4232
4233                   CALL rrtmg_sw( 1,                                           &
4234                                  nzt_rad-k_topo,                              &
4235                                  rrtm_icld,                                   &
4236                                  rrtm_iaer,                                   &
4237                                  rrtm_play(:,k_topo+1:nzt_rad+1),             &
4238                                  rrtm_plev(:,k_topo+1:nzt_rad+2),             &
4239                                  rrtm_tlay(:,k_topo+1:nzt_rad+1),             &
4240                                  rrtm_tlev(:,k_topo+1:nzt_rad+2),             &
4241                                  rrtm_tsfc,                                   &
4242                                  rrtm_h2ovmr(:,k_topo+1:nzt_rad+1),           &                               
4243                                  rrtm_o3vmr(:,k_topo+1:nzt_rad+1),            &       
4244                                  rrtm_co2vmr(:,k_topo+1:nzt_rad+1),           &
4245                                  rrtm_ch4vmr(:,k_topo+1:nzt_rad+1),           &
4246                                  rrtm_n2ovmr(:,k_topo+1:nzt_rad+1),           &
4247                                  rrtm_o2vmr(:,k_topo+1:nzt_rad+1),            &
4248                                  rrtm_asdir,                                  & 
4249                                  rrtm_asdif,                                  &
4250                                  rrtm_aldir,                                  &
4251                                  rrtm_aldif,                                  &
4252                                  zenith,                                      &
4253                                  0.0_wp,                                      &
4254                                  day_of_year,                                 &
4255                                  solar_constant,                              &
4256                                  rrtm_inflgsw,                                &
4257                                  rrtm_iceflgsw,                               &
4258                                  rrtm_liqflgsw,                               &
4259                                  rrtm_cldfr(:,k_topo+1:nzt_rad+1),            &
4260                                  rrtm_sw_taucld_dum,                          &
4261                                  rrtm_sw_ssacld_dum,                          &
4262                                  rrtm_sw_asmcld_dum,                          &
4263                                  rrtm_sw_fsfcld_dum,                          &
4264                                  rrtm_cicewp(:,k_topo+1:nzt_rad+1),           &
4265                                  rrtm_cliqwp(:,k_topo+1:nzt_rad+1),           &
4266                                  rrtm_reice(:,k_topo+1:nzt_rad+1),            &
4267                                  rrtm_reliq(:,k_topo+1:nzt_rad+1),            &
4268                                  rrtm_sw_tauaer_dum,                          &
4269                                  rrtm_sw_ssaaer_dum,                          &
4270                                  rrtm_sw_asmaer_dum,                          &
4271                                  rrtm_sw_ecaer_dum,                           &
4272                                  rrtm_swuflx(:,k_topo:nzt_rad+1),             & 
4273                                  rrtm_swdflx(:,k_topo:nzt_rad+1),             & 
4274                                  rrtm_swhr(:,k_topo+1:nzt_rad+1),             & 
4275                                  rrtm_swuflxc(:,k_topo:nzt_rad+1),            & 
4276                                  rrtm_swdflxc(:,k_topo:nzt_rad+1),            &
4277                                  rrtm_swhrc(:,k_topo+1:nzt_rad+1),            &
4278                                  rrtm_dirdflux(:,k_topo:nzt_rad+1),           &
4279                                  rrtm_difdflux(:,k_topo:nzt_rad+1) )
4280
4281                   DEALLOCATE( rrtm_sw_taucld_dum )
4282                   DEALLOCATE( rrtm_sw_ssacld_dum )
4283                   DEALLOCATE( rrtm_sw_asmcld_dum )
4284                   DEALLOCATE( rrtm_sw_fsfcld_dum )
4285                   DEALLOCATE( rrtm_sw_tauaer_dum )
4286                   DEALLOCATE( rrtm_sw_ssaaer_dum )
4287                   DEALLOCATE( rrtm_sw_asmaer_dum )
4288                   DEALLOCATE( rrtm_sw_ecaer_dum )
4289!
4290!--                Save fluxes
4291                   DO k = nzb, nzt+1
4292                      rad_sw_in(k,j,i)  = rrtm_swdflx(0,k)
4293                      rad_sw_out(k,j,i) = rrtm_swuflx(0,k)
4294                   ENDDO
4295!
4296!--                Save heating rates (convert from K/d to K/s)
4297                   DO k = nzb+1, nzt+1
4298                      rad_sw_hr(k,j,i)     = rrtm_swhr(0,k)  * d_hours_day
4299                      rad_sw_cs_hr(k,j,i)  = rrtm_swhrc(0,k) * d_hours_day
4300                   ENDDO
4301
4302!
4303!--                Save surface radiative fluxes onto respective surface elements
4304!--                Horizontal surfaces
4305                   DO  m = surf_lsm_h%start_index(j,i),                        &
4306                           surf_lsm_h%end_index(j,i)
4307                      surf_lsm_h%rad_sw_in(m)     = rrtm_swdflx(0,k_topo)
4308                      surf_lsm_h%rad_sw_out(m)    = rrtm_swuflx(0,k_topo)
4309                   ENDDO             
4310                   DO  m = surf_usm_h%start_index(j,i),                        &
4311                           surf_usm_h%end_index(j,i)
4312                      surf_usm_h%rad_sw_in(m)     = rrtm_swdflx(0,k_topo)
4313                      surf_usm_h%rad_sw_out(m)    = rrtm_swuflx(0,k_topo)
4314                   ENDDO 
4315!
4316!--                Vertical surfaces. Fluxes are obtain at respective vertical
4317!--                level of the surface element
4318                   DO  l = 0, 3
4319                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
4320                              surf_lsm_v(l)%end_index(j,i)
4321                         k                           = surf_lsm_v(l)%k(m)
4322                         surf_lsm_v(l)%rad_sw_in(m)  = rrtm_swdflx(0,k)
4323                         surf_lsm_v(l)%rad_sw_out(m) = rrtm_swuflx(0,k)
4324                      ENDDO             
4325                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
4326                              surf_usm_v(l)%end_index(j,i)
4327                         k                           = surf_usm_v(l)%k(m)
4328                         surf_usm_v(l)%rad_sw_in(m)  = rrtm_swdflx(0,k)
4329                         surf_usm_v(l)%rad_sw_out(m) = rrtm_swuflx(0,k)
4330                      ENDDO 
4331                   ENDDO
4332!
4333!--             Solar radiation is zero during night
4334                ELSE
4335                   rad_sw_in  = 0.0_wp
4336                   rad_sw_out = 0.0_wp
4337!--             !!!!!!!! ATTENSION !!!!!!!!!!!!!!!
4338!--             Surface radiative fluxes should be also set to zero here                 
4339!--                Save surface radiative fluxes onto respective surface elements
4340!--                Horizontal surfaces
4341                   DO  m = surf_lsm_h%start_index(j,i),                        &
4342                           surf_lsm_h%end_index(j,i)
4343                      surf_lsm_h%rad_sw_in(m)     = 0.0_wp
4344                      surf_lsm_h%rad_sw_out(m)    = 0.0_wp
4345                   ENDDO             
4346                   DO  m = surf_usm_h%start_index(j,i),                        &
4347                           surf_usm_h%end_index(j,i)
4348                      surf_usm_h%rad_sw_in(m)     = 0.0_wp
4349                      surf_usm_h%rad_sw_out(m)    = 0.0_wp
4350                   ENDDO 
4351!
4352!--                Vertical surfaces. Fluxes are obtain at respective vertical
4353!--                level of the surface element
4354                   DO  l = 0, 3
4355                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
4356                              surf_lsm_v(l)%end_index(j,i)
4357                         k                           = surf_lsm_v(l)%k(m)
4358                         surf_lsm_v(l)%rad_sw_in(m)  = 0.0_wp
4359                         surf_lsm_v(l)%rad_sw_out(m) = 0.0_wp
4360                      ENDDO             
4361                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
4362                              surf_usm_v(l)%end_index(j,i)
4363                         k                           = surf_usm_v(l)%k(m)
4364                         surf_usm_v(l)%rad_sw_in(m)  = 0.0_wp
4365                         surf_usm_v(l)%rad_sw_out(m) = 0.0_wp
4366                      ENDDO 
4367                   ENDDO
4368                ENDIF
4369
4370             ENDDO
4371          ENDDO
4372
4373       ENDIF
4374!
4375!--    Finally, calculate surface net radiation for surface elements.
4376       IF (  .NOT.  radiation_interactions  ) THEN
4377!--       First, for horizontal surfaces   
4378          DO  m = 1, surf_lsm_h%ns
4379             surf_lsm_h%rad_net(m) = surf_lsm_h%rad_sw_in(m)                   &
4380                                   - surf_lsm_h%rad_sw_out(m)                  &
4381                                   + surf_lsm_h%rad_lw_in(m)                   &
4382                                   - surf_lsm_h%rad_lw_out(m)
4383          ENDDO
4384          DO  m = 1, surf_usm_h%ns
4385             surf_usm_h%rad_net(m) = surf_usm_h%rad_sw_in(m)                   &
4386                                   - surf_usm_h%rad_sw_out(m)                  &
4387                                   + surf_usm_h%rad_lw_in(m)                   &
4388                                   - surf_usm_h%rad_lw_out(m)
4389          ENDDO
4390!
4391!--       Vertical surfaces.
4392!--       Todo: weight with azimuth and zenith angle according to their orientation!
4393          DO  l = 0, 3     
4394             DO  m = 1, surf_lsm_v(l)%ns
4395                surf_lsm_v(l)%rad_net(m) = surf_lsm_v(l)%rad_sw_in(m)          &
4396                                         - surf_lsm_v(l)%rad_sw_out(m)         &
4397                                         + surf_lsm_v(l)%rad_lw_in(m)          &
4398                                         - surf_lsm_v(l)%rad_lw_out(m)
4399             ENDDO
4400             DO  m = 1, surf_usm_v(l)%ns
4401                surf_usm_v(l)%rad_net(m) = surf_usm_v(l)%rad_sw_in(m)          &
4402                                         - surf_usm_v(l)%rad_sw_out(m)         &
4403                                         + surf_usm_v(l)%rad_lw_in(m)          &
4404                                         - surf_usm_v(l)%rad_lw_out(m)
4405             ENDDO
4406          ENDDO
4407       ENDIF
4408
4409
4410       CALL exchange_horiz( rad_lw_in,  nbgp )
4411       CALL exchange_horiz( rad_lw_out, nbgp )
4412       CALL exchange_horiz( rad_lw_hr,    nbgp )
4413       CALL exchange_horiz( rad_lw_cs_hr, nbgp )
4414
4415       CALL exchange_horiz( rad_sw_in,  nbgp )
4416       CALL exchange_horiz( rad_sw_out, nbgp ) 
4417       CALL exchange_horiz( rad_sw_hr,    nbgp )
4418       CALL exchange_horiz( rad_sw_cs_hr, nbgp )
4419
4420#endif
4421
4422    END SUBROUTINE radiation_rrtmg
4423
4424
4425!------------------------------------------------------------------------------!
4426! Description:
4427! ------------
4428!> Calculate the cosine of the zenith angle (variable is called zenith)
4429!------------------------------------------------------------------------------!
4430    SUBROUTINE calc_zenith
4431
4432       IMPLICIT NONE
4433
4434       REAL(wp) ::  declination,  & !< solar declination angle
4435                    hour_angle      !< solar hour angle
4436!
4437!--    Calculate current day and time based on the initial values and simulation
4438!--    time
4439       CALL calc_date_and_time
4440
4441!
4442!--    Calculate solar declination and hour angle   
4443       declination = ASIN( decl_1 * SIN(decl_2 * REAL(day_of_year, KIND=wp) - decl_3) )
4444       hour_angle  = 2.0_wp * pi * (time_utc / 86400.0_wp) + lon - pi
4445
4446!
4447!--    Calculate cosine of solar zenith angle
4448       cos_zenith = SIN(lat) * SIN(declination) + COS(lat) * COS(declination)   &
4449                                            * COS(hour_angle)
4450       cos_zenith = MAX(0.0_wp,cos_zenith)
4451
4452!
4453!--    Calculate solar directional vector
4454       IF ( sun_direction )  THEN
4455
4456!
4457!--       Direction in longitudes equals to sin(solar_azimuth) * sin(zenith)
4458          sun_dir_lon = -SIN(hour_angle) * COS(declination)
4459
4460!
4461!--       Direction in latitues equals to cos(solar_azimuth) * sin(zenith)
4462          sun_dir_lat = SIN(declination) * COS(lat) - COS(hour_angle) &
4463                              * COS(declination) * SIN(lat)
4464       ENDIF
4465
4466!
4467!--    Check if the sun is up (otheriwse shortwave calculations can be skipped)
4468       IF ( cos_zenith > 0.0_wp )  THEN
4469          sun_up = .TRUE.
4470       ELSE
4471          sun_up = .FALSE.
4472       END IF
4473
4474    END SUBROUTINE calc_zenith
4475
4476#if defined ( __rrtmg ) && defined ( __netcdf )
4477!------------------------------------------------------------------------------!
4478! Description:
4479! ------------
4480!> Calculates surface albedo components based on Briegleb (1992) and
4481!> Briegleb et al. (1986)
4482!------------------------------------------------------------------------------!
4483    SUBROUTINE calc_albedo( surf )
4484
4485        IMPLICIT NONE
4486
4487        INTEGER(iwp)    ::  ind_type !< running index surface tiles
4488        INTEGER(iwp)    ::  m        !< running index surface elements
4489
4490        TYPE(surf_type) ::  surf !< treated surfaces
4491
4492        IF ( sun_up  .AND.  .NOT. average_radiation )  THEN
4493
4494           DO  m = 1, surf%ns
4495!
4496!--           Loop over surface elements
4497              DO  ind_type = 0, SIZE( surf%albedo_type, 1 ) - 1
4498           
4499!
4500!--              Ocean
4501                 IF ( surf%albedo_type(ind_type,m) == 1 )  THEN
4502                    surf%rrtm_aldir(ind_type,m) = 0.026_wp /                    &
4503                                                ( cos_zenith**1.7_wp + 0.065_wp )&
4504                                     + 0.15_wp * ( cos_zenith - 0.1_wp )         &
4505                                               * ( cos_zenith - 0.5_wp )         &
4506                                               * ( cos_zenith - 1.0_wp )
4507                    surf%rrtm_asdir(ind_type,m) = surf%rrtm_aldir(ind_type,m)
4508!
4509!--              Snow
4510                 ELSEIF ( surf%albedo_type(ind_type,m) == 16 )  THEN
4511                    IF ( cos_zenith < 0.5_wp )  THEN
4512                       surf%rrtm_aldir(ind_type,m) =                           &
4513                                 0.5_wp * ( 1.0_wp - surf%aldif(ind_type,m) )  &
4514                                        * ( 3.0_wp / ( 1.0_wp + 4.0_wp         &
4515                                        * cos_zenith ) ) - 1.0_wp
4516                       surf%rrtm_asdir(ind_type,m) =                           &
4517                                 0.5_wp * ( 1.0_wp - surf%asdif(ind_type,m) )  &
4518                                        * ( 3.0_wp / ( 1.0_wp + 4.0_wp         &
4519                                        * cos_zenith ) ) - 1.0_wp
4520
4521                       surf%rrtm_aldir(ind_type,m) =                           &
4522                                       MIN(0.98_wp, surf%rrtm_aldir(ind_type,m))
4523                       surf%rrtm_asdir(ind_type,m) =                           &
4524                                       MIN(0.98_wp, surf%rrtm_asdir(ind_type,m))
4525                    ELSE
4526                       surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4527                       surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4528                    ENDIF
4529!
4530!--              Sea ice
4531                 ELSEIF ( surf%albedo_type(ind_type,m) == 15 )  THEN
4532                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4533                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4534
4535!
4536!--              Asphalt
4537                 ELSEIF ( surf%albedo_type(ind_type,m) == 17 )  THEN
4538                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4539                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4540
4541
4542!
4543!--              Bare soil
4544                 ELSEIF ( surf%albedo_type(ind_type,m) == 18 )  THEN
4545                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4546                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4547
4548!
4549!--              Land surfaces
4550                 ELSE
4551                    SELECT CASE ( surf%albedo_type(ind_type,m) )
4552
4553!
4554!--                    Surface types with strong zenith dependence
4555                       CASE ( 1, 2, 3, 4, 11, 12, 13 )
4556                          surf%rrtm_aldir(ind_type,m) =                        &
4557                                surf%aldif(ind_type,m) * 1.4_wp /              &
4558                                           ( 1.0_wp + 0.8_wp * cos_zenith )
4559                          surf%rrtm_asdir(ind_type,m) =                        &
4560                                surf%asdif(ind_type,m) * 1.4_wp /              &
4561                                           ( 1.0_wp + 0.8_wp * cos_zenith )
4562!
4563!--                    Surface types with weak zenith dependence
4564                       CASE ( 5, 6, 7, 8, 9, 10, 14 )
4565                          surf%rrtm_aldir(ind_type,m) =                        &
4566                                surf%aldif(ind_type,m) * 1.1_wp /              &
4567                                           ( 1.0_wp + 0.2_wp * cos_zenith )
4568                          surf%rrtm_asdir(ind_type,m) =                        &
4569                                surf%asdif(ind_type,m) * 1.1_wp /              &
4570                                           ( 1.0_wp + 0.2_wp * cos_zenith )
4571
4572                       CASE DEFAULT
4573
4574                    END SELECT
4575                 ENDIF
4576!
4577!--              Diffusive albedo is taken from Table 2
4578                 surf%rrtm_aldif(ind_type,m) = surf%aldif(ind_type,m)
4579                 surf%rrtm_asdif(ind_type,m) = surf%asdif(ind_type,m)
4580              ENDDO
4581           ENDDO
4582!
4583!--     Set albedo in case of average radiation
4584        ELSEIF ( sun_up  .AND.  average_radiation )  THEN
4585           surf%rrtm_asdir = albedo_urb
4586           surf%rrtm_asdif = albedo_urb
4587           surf%rrtm_aldir = albedo_urb
4588           surf%rrtm_aldif = albedo_urb 
4589!
4590!--     Darkness
4591        ELSE
4592           surf%rrtm_aldir = 0.0_wp
4593           surf%rrtm_asdir = 0.0_wp
4594           surf%rrtm_aldif = 0.0_wp
4595           surf%rrtm_asdif = 0.0_wp
4596        ENDIF
4597
4598    END SUBROUTINE calc_albedo
4599
4600!------------------------------------------------------------------------------!
4601! Description:
4602! ------------
4603!> Read sounding data (pressure and temperature) from RADIATION_DATA.
4604!------------------------------------------------------------------------------!
4605    SUBROUTINE read_sounding_data
4606
4607       IMPLICIT NONE
4608
4609       INTEGER(iwp) :: id,           & !< NetCDF id of input file
4610                       id_dim_zrad,  & !< pressure level id in the NetCDF file
4611                       id_var,       & !< NetCDF variable id
4612                       k,            & !< loop index
4613                       nz_snd,       & !< number of vertical levels in the sounding data
4614                       nz_snd_start, & !< start vertical index for sounding data to be used
4615                       nz_snd_end      !< end vertical index for souding data to be used
4616
4617       REAL(wp) :: t_surface           !< actual surface temperature
4618
4619       REAL(wp), DIMENSION(:), ALLOCATABLE ::  hyp_snd_tmp, & !< temporary hydrostatic pressure profile (sounding)
4620                                               t_snd_tmp      !< temporary temperature profile (sounding)
4621
4622!
4623!--    In case of updates, deallocate arrays first (sufficient to check one
4624!--    array as the others are automatically allocated). This is required
4625!--    because nzt_rad might change during the update
4626       IF ( ALLOCATED ( hyp_snd ) )  THEN
4627          DEALLOCATE( hyp_snd )
4628          DEALLOCATE( t_snd )
4629          DEALLOCATE ( rrtm_play )
4630          DEALLOCATE ( rrtm_plev )
4631          DEALLOCATE ( rrtm_tlay )
4632          DEALLOCATE ( rrtm_tlev )
4633
4634          DEALLOCATE ( rrtm_cicewp )
4635          DEALLOCATE ( rrtm_cldfr )
4636          DEALLOCATE ( rrtm_cliqwp )
4637          DEALLOCATE ( rrtm_reice )
4638          DEALLOCATE ( rrtm_reliq )
4639          DEALLOCATE ( rrtm_lw_taucld )
4640          DEALLOCATE ( rrtm_lw_tauaer )
4641
4642          DEALLOCATE ( rrtm_lwdflx  )
4643          DEALLOCATE ( rrtm_lwdflxc )
4644          DEALLOCATE ( rrtm_lwuflx  )
4645          DEALLOCATE ( rrtm_lwuflxc )
4646          DEALLOCATE ( rrtm_lwuflx_dt )
4647          DEALLOCATE ( rrtm_lwuflxc_dt )
4648          DEALLOCATE ( rrtm_lwhr  )
4649          DEALLOCATE ( rrtm_lwhrc )
4650
4651          DEALLOCATE ( rrtm_sw_taucld )
4652          DEALLOCATE ( rrtm_sw_ssacld )
4653          DEALLOCATE ( rrtm_sw_asmcld )
4654          DEALLOCATE ( rrtm_sw_fsfcld )
4655          DEALLOCATE ( rrtm_sw_tauaer )
4656          DEALLOCATE ( rrtm_sw_ssaaer )
4657          DEALLOCATE ( rrtm_sw_asmaer ) 
4658          DEALLOCATE ( rrtm_sw_ecaer )   
4659 
4660          DEALLOCATE ( rrtm_swdflx  )
4661          DEALLOCATE ( rrtm_swdflxc )
4662          DEALLOCATE ( rrtm_swuflx  )
4663          DEALLOCATE ( rrtm_swuflxc )
4664          DEALLOCATE ( rrtm_swhr  )
4665          DEALLOCATE ( rrtm_swhrc )
4666          DEALLOCATE ( rrtm_dirdflux )
4667          DEALLOCATE ( rrtm_difdflux )
4668
4669       ENDIF
4670
4671!
4672!--    Open file for reading
4673       nc_stat = NF90_OPEN( rrtm_input_file, NF90_NOWRITE, id )
4674       CALL netcdf_handle_error_rad( 'read_sounding_data', 549 )
4675
4676!
4677!--    Inquire dimension of z axis and save in nz_snd
4678       nc_stat = NF90_INQ_DIMID( id, "Pressure", id_dim_zrad )
4679       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim_zrad, len = nz_snd )
4680       CALL netcdf_handle_error_rad( 'read_sounding_data', 551 )
4681
4682!
4683! !--    Allocate temporary array for storing pressure data
4684       ALLOCATE( hyp_snd_tmp(1:nz_snd) )
4685       hyp_snd_tmp = 0.0_wp
4686
4687
4688!--    Read pressure from file
4689       nc_stat = NF90_INQ_VARID( id, "Pressure", id_var )
4690       nc_stat = NF90_GET_VAR( id, id_var, hyp_snd_tmp(:), start = (/1/),      &
4691                               count = (/nz_snd/) )
4692       CALL netcdf_handle_error_rad( 'read_sounding_data', 552 )
4693
4694!
4695!--    Allocate temporary array for storing temperature data
4696       ALLOCATE( t_snd_tmp(1:nz_snd) )
4697       t_snd_tmp = 0.0_wp
4698
4699!
4700!--    Read temperature from file
4701       nc_stat = NF90_INQ_VARID( id, "ReferenceTemperature", id_var )
4702       nc_stat = NF90_GET_VAR( id, id_var, t_snd_tmp(:), start = (/1/),        &
4703                               count = (/nz_snd/) )
4704       CALL netcdf_handle_error_rad( 'read_sounding_data', 553 )
4705
4706!
4707!--    Calculate start of sounding data
4708       nz_snd_start = nz_snd + 1
4709       nz_snd_end   = nz_snd + 1
4710
4711!
4712!--    Start filling vertical dimension at 10hPa above the model domain (hyp is
4713!--    in Pa, hyp_snd in hPa).
4714       DO  k = 1, nz_snd
4715          IF ( hyp_snd_tmp(k) < ( hyp(nzt+1) - 1000.0_wp) * 0.01_wp )  THEN
4716             nz_snd_start = k
4717             EXIT
4718          END IF
4719       END DO
4720
4721       IF ( nz_snd_start <= nz_snd )  THEN
4722          nz_snd_end = nz_snd
4723       END IF
4724
4725
4726!
4727!--    Calculate of total grid points for RRTMG calculations
4728       nzt_rad = nzt + nz_snd_end - nz_snd_start + 1
4729
4730!
4731!--    Save data above LES domain in hyp_snd, t_snd
4732       ALLOCATE( hyp_snd(nzb+1:nzt_rad) )
4733       ALLOCATE( t_snd(nzb+1:nzt_rad)   )
4734       hyp_snd = 0.0_wp
4735       t_snd = 0.0_wp
4736
4737       hyp_snd(nzt+2:nzt_rad) = hyp_snd_tmp(nz_snd_start+1:nz_snd_end)
4738       t_snd(nzt+2:nzt_rad)   = t_snd_tmp(nz_snd_start+1:nz_snd_end)
4739
4740       nc_stat = NF90_CLOSE( id )
4741
4742!
4743!--    Calculate pressure levels on zu and zw grid. Sounding data is added at
4744!--    top of the LES domain. This routine does not consider horizontal or
4745!--    vertical variability of pressure and temperature
4746       ALLOCATE ( rrtm_play(0:0,nzb+1:nzt_rad+1)   )
4747       ALLOCATE ( rrtm_plev(0:0,nzb+1:nzt_rad+2)   )
4748
4749       t_surface = pt_surface * exner(nzb)
4750       DO k = nzb+1, nzt+1
4751          rrtm_play(0,k) = hyp(k) * 0.01_wp
4752          rrtm_plev(0,k) = barometric_formula(zw(k-1),                         &
4753                              pt_surface * exner(nzb), &
4754                              surface_pressure )
4755       ENDDO
4756
4757       DO k = nzt+2, nzt_rad
4758          rrtm_play(0,k) = hyp_snd(k)
4759          rrtm_plev(0,k) = 0.5_wp * ( rrtm_play(0,k) + rrtm_play(0,k-1) )
4760       ENDDO
4761       rrtm_plev(0,nzt_rad+1) = MAX( 0.5 * hyp_snd(nzt_rad),                   &
4762                                   1.5 * hyp_snd(nzt_rad)                      &
4763                                 - 0.5 * hyp_snd(nzt_rad-1) )
4764       rrtm_plev(0,nzt_rad+2)  = MIN( 1.0E-4_wp,                               &
4765                                      0.25_wp * rrtm_plev(0,nzt_rad+1) )
4766
4767       rrtm_play(0,nzt_rad+1) = 0.5 * rrtm_plev(0,nzt_rad+1)
4768
4769!
4770!--    Calculate temperature/humidity levels at top of the LES domain.
4771!--    Currently, the temperature is taken from sounding data (might lead to a
4772!--    temperature jump at interface. To do: Humidity is currently not
4773!--    calculated above the LES domain.
4774       ALLOCATE ( rrtm_tlay(0:0,nzb+1:nzt_rad+1)   )
4775       ALLOCATE ( rrtm_tlev(0:0,nzb+1:nzt_rad+2)   )
4776
4777       DO k = nzt+8, nzt_rad
4778          rrtm_tlay(0,k)   = t_snd(k)
4779       ENDDO
4780       rrtm_tlay(0,nzt_rad+1) = 2.0_wp * rrtm_tlay(0,nzt_rad)                  &
4781                                - rrtm_tlay(0,nzt_rad-1)
4782       DO k = nzt+9, nzt_rad+1
4783          rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k)                &
4784                             - rrtm_tlay(0,k-1))                               &
4785                             / ( rrtm_play(0,k) - rrtm_play(0,k-1) )           &
4786                             * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
4787       ENDDO
4788
4789       rrtm_tlev(0,nzt_rad+2)   = 2.0_wp * rrtm_tlay(0,nzt_rad+1)              &
4790                                  - rrtm_tlev(0,nzt_rad)
4791!
4792!--    Allocate remaining RRTMG arrays
4793       ALLOCATE ( rrtm_cicewp(0:0,nzb+1:nzt_rad+1) )
4794       ALLOCATE ( rrtm_cldfr(0:0,nzb+1:nzt_rad+1) )
4795       ALLOCATE ( rrtm_cliqwp(0:0,nzb+1:nzt_rad+1) )
4796       ALLOCATE ( rrtm_reice(0:0,nzb+1:nzt_rad+1) )
4797       ALLOCATE ( rrtm_reliq(0:0,nzb+1:nzt_rad+1) )
4798       ALLOCATE ( rrtm_lw_taucld(1:nbndlw+1,0:0,nzb+1:nzt_rad+1) )
4799       ALLOCATE ( rrtm_lw_tauaer(0:0,nzb+1:nzt_rad+1,1:nbndlw+1) )
4800       ALLOCATE ( rrtm_sw_taucld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4801       ALLOCATE ( rrtm_sw_ssacld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4802       ALLOCATE ( rrtm_sw_asmcld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4803       ALLOCATE ( rrtm_sw_fsfcld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4804       ALLOCATE ( rrtm_sw_tauaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) )
4805       ALLOCATE ( rrtm_sw_ssaaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) )
4806       ALLOCATE ( rrtm_sw_asmaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) ) 
4807       ALLOCATE ( rrtm_sw_ecaer(0:0,nzb+1:nzt_rad+1,1:naerec+1) )   
4808
4809!
4810!--    The ice phase is currently not considered in PALM
4811       rrtm_cicewp = 0.0_wp
4812       rrtm_reice  = 0.0_wp
4813
4814!
4815!--    Set other parameters (move to NAMELIST parameters in the future)
4816       rrtm_lw_tauaer = 0.0_wp
4817       rrtm_lw_taucld = 0.0_wp
4818       rrtm_sw_taucld = 0.0_wp
4819       rrtm_sw_ssacld = 0.0_wp
4820       rrtm_sw_asmcld = 0.0_wp
4821       rrtm_sw_fsfcld = 0.0_wp
4822       rrtm_sw_tauaer = 0.0_wp
4823       rrtm_sw_ssaaer = 0.0_wp
4824       rrtm_sw_asmaer = 0.0_wp
4825       rrtm_sw_ecaer  = 0.0_wp
4826
4827
4828       ALLOCATE ( rrtm_swdflx(0:0,nzb:nzt_rad+1)  )
4829       ALLOCATE ( rrtm_swuflx(0:0,nzb:nzt_rad+1)  )
4830       ALLOCATE ( rrtm_swhr(0:0,nzb+1:nzt_rad+1)  )
4831       ALLOCATE ( rrtm_swuflxc(0:0,nzb:nzt_rad+1) )
4832       ALLOCATE ( rrtm_swdflxc(0:0,nzb:nzt_rad+1) )
4833       ALLOCATE ( rrtm_swhrc(0:0,nzb+1:nzt_rad+1) )
4834       ALLOCATE ( rrtm_dirdflux(0:0,nzb:nzt_rad+1) )
4835       ALLOCATE ( rrtm_difdflux(0:0,nzb:nzt_rad+1) )
4836
4837       rrtm_swdflx  = 0.0_wp
4838       rrtm_swuflx  = 0.0_wp
4839       rrtm_swhr    = 0.0_wp 
4840       rrtm_swuflxc = 0.0_wp
4841       rrtm_swdflxc = 0.0_wp
4842       rrtm_swhrc   = 0.0_wp
4843       rrtm_dirdflux = 0.0_wp
4844       rrtm_difdflux = 0.0_wp
4845
4846       ALLOCATE ( rrtm_lwdflx(0:0,nzb:nzt_rad+1)  )
4847       ALLOCATE ( rrtm_lwuflx(0:0,nzb:nzt_rad+1)  )
4848       ALLOCATE ( rrtm_lwhr(0:0,nzb+1:nzt_rad+1)  )
4849       ALLOCATE ( rrtm_lwuflxc(0:0,nzb:nzt_rad+1) )
4850       ALLOCATE ( rrtm_lwdflxc(0:0,nzb:nzt_rad+1) )
4851       ALLOCATE ( rrtm_lwhrc(0:0,nzb+1:nzt_rad+1) )
4852
4853       rrtm_lwdflx  = 0.0_wp
4854       rrtm_lwuflx  = 0.0_wp
4855       rrtm_lwhr    = 0.0_wp 
4856       rrtm_lwuflxc = 0.0_wp
4857       rrtm_lwdflxc = 0.0_wp
4858       rrtm_lwhrc   = 0.0_wp
4859
4860       ALLOCATE ( rrtm_lwuflx_dt(0:0,nzb:nzt_rad+1) )
4861       ALLOCATE ( rrtm_lwuflxc_dt(0:0,nzb:nzt_rad+1) )
4862
4863       rrtm_lwuflx_dt = 0.0_wp
4864       rrtm_lwuflxc_dt = 0.0_wp
4865
4866    END SUBROUTINE read_sounding_data
4867
4868
4869!------------------------------------------------------------------------------!
4870! Description:
4871! ------------
4872!> Read trace gas data from file and convert into trace gas paths / volume
4873!> mixing ratios. If a user-defined input file is provided it needs to follow
4874!> the convections used in RRTMG (see respective netCDF files shipped with
4875!> RRTMG)
4876!------------------------------------------------------------------------------!
4877    SUBROUTINE read_trace_gas_data
4878
4879       USE rrsw_ncpar
4880
4881       IMPLICIT NONE
4882
4883       INTEGER(iwp), PARAMETER :: num_trace_gases = 10 !< number of trace gases (absorbers)
4884
4885       CHARACTER(LEN=5), DIMENSION(num_trace_gases), PARAMETER ::              & !< trace gas names
4886           trace_names = (/'O3   ', 'CO2  ', 'CH4  ', 'N2O  ', 'O2   ',        &
4887                           'CFC11', 'CFC12', 'CFC22', 'CCL4 ', 'H2O  '/)
4888
4889       INTEGER(iwp) :: id,     & !< NetCDF id
4890                       k,      & !< loop index
4891                       m,      & !< loop index
4892                       n,      & !< loop index
4893                       nabs,   & !< number of absorbers
4894                       np,     & !< number of pressure levels
4895                       id_abs, & !< NetCDF id of the respective absorber
4896                       id_dim, & !< NetCDF id of asborber's dimension
4897                       id_var    !< NetCDf id ot the absorber
4898
4899       REAL(wp) :: p_mls_l, &    !< pressure lower limit for interpolation
4900                   p_mls_u, &    !< pressure upper limit for interpolation
4901                   p_wgt_l, &    !< pressure weight lower limit for interpolation
4902                   p_wgt_u, &    !< pressure weight upper limit for interpolation
4903                   p_mls_m       !< mean pressure between upper and lower limits
4904
4905
4906       REAL(wp), DIMENSION(:), ALLOCATABLE   ::  p_mls,          & !< pressure levels for the absorbers
4907                                                 rrtm_play_tmp,  & !< temporary array for pressure zu-levels
4908                                                 rrtm_plev_tmp,  & !< temporary array for pressure zw-levels
4909                                                 trace_path_tmp    !< temporary array for storing trace gas path data
4910
4911       REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  trace_mls,      & !< array for storing the absorber amounts
4912                                                 trace_mls_path, & !< array for storing trace gas path data
4913                                                 trace_mls_tmp     !< temporary array for storing trace gas data
4914
4915
4916!
4917!--    In case of updates, deallocate arrays first (sufficient to check one
4918!--    array as the others are automatically allocated)
4919       IF ( ALLOCATED ( rrtm_o3vmr ) )  THEN
4920          DEALLOCATE ( rrtm_o3vmr  )
4921          DEALLOCATE ( rrtm_co2vmr )
4922          DEALLOCATE ( rrtm_ch4vmr )
4923          DEALLOCATE ( rrtm_n2ovmr )
4924          DEALLOCATE ( rrtm_o2vmr  )
4925          DEALLOCATE ( rrtm_cfc11vmr )
4926          DEALLOCATE ( rrtm_cfc12vmr )
4927          DEALLOCATE ( rrtm_cfc22vmr )
4928          DEALLOCATE ( rrtm_ccl4vmr  )
4929          DEALLOCATE ( rrtm_h2ovmr  )     
4930       ENDIF
4931
4932!
4933!--    Allocate trace gas profiles
4934       ALLOCATE ( rrtm_o3vmr(0:0,1:nzt_rad+1)  )
4935       ALLOCATE ( rrtm_co2vmr(0:0,1:nzt_rad+1) )
4936       ALLOCATE ( rrtm_ch4vmr(0:0,1:nzt_rad+1) )
4937       ALLOCATE ( rrtm_n2ovmr(0:0,1:nzt_rad+1) )
4938       ALLOCATE ( rrtm_o2vmr(0:0,1:nzt_rad+1)  )
4939       ALLOCATE ( rrtm_cfc11vmr(0:0,1:nzt_rad+1) )
4940       ALLOCATE ( rrtm_cfc12vmr(0:0,1:nzt_rad+1) )
4941       ALLOCATE ( rrtm_cfc22vmr(0:0,1:nzt_rad+1) )
4942       ALLOCATE ( rrtm_ccl4vmr(0:0,1:nzt_rad+1)  )
4943       ALLOCATE ( rrtm_h2ovmr(0:0,1:nzt_rad+1)  )
4944
4945!
4946!--    Open file for reading
4947       nc_stat = NF90_OPEN( rrtm_input_file, NF90_NOWRITE, id )
4948       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 549 )
4949!
4950!--    Inquire dimension ids and dimensions
4951       nc_stat = NF90_INQ_DIMID( id, "Pressure", id_dim )
4952       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4953       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim, len = np) 
4954       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4955
4956       nc_stat = NF90_INQ_DIMID( id, "Absorber", id_dim )
4957       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4958       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim, len = nabs ) 
4959       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4960   
4961
4962!
4963!--    Allocate pressure, and trace gas arrays     
4964       ALLOCATE( p_mls(1:np) )
4965       ALLOCATE( trace_mls(1:num_trace_gases,1:np) ) 
4966       ALLOCATE( trace_mls_tmp(1:nabs,1:np) ) 
4967
4968
4969       nc_stat = NF90_INQ_VARID( id, "Pressure", id_var )
4970       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4971       nc_stat = NF90_GET_VAR( id, id_var, p_mls )
4972       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4973
4974       nc_stat = NF90_INQ_VARID( id, "AbsorberAmountMLS", id_var )
4975       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4976       nc_stat = NF90_GET_VAR( id, id_var, trace_mls_tmp )
4977       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4978
4979
4980!
4981!--    Write absorber amounts (mls) to trace_mls
4982       DO n = 1, num_trace_gases
4983          CALL getAbsorberIndex( TRIM( trace_names(n) ), id_abs )
4984
4985          trace_mls(n,1:np) = trace_mls_tmp(id_abs,1:np)
4986
4987!
4988!--       Replace missing values by zero
4989          WHERE ( trace_mls(n,:) > 2.0_wp ) 
4990             trace_mls(n,:) = 0.0_wp
4991          END WHERE
4992       END DO
4993
4994       DEALLOCATE ( trace_mls_tmp )
4995
4996       nc_stat = NF90_CLOSE( id )
4997       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 551 )
4998
4999!
5000!--    Add extra pressure level for calculations of the trace gas paths
5001       ALLOCATE ( rrtm_play_tmp(1:nzt_rad+1) )
5002       ALLOCATE ( rrtm_plev_tmp(1:nzt_rad+2) )
5003
5004       rrtm_play_tmp(1:nzt_rad)   = rrtm_play(0,1:nzt_rad) 
5005       rrtm_plev_tmp(1:nzt_rad+1) = rrtm_plev(0,1:nzt_rad+1)
5006       rrtm_play_tmp(nzt_rad+1)   = rrtm_plev(0,nzt_rad+1) * 0.5_wp
5007       rrtm_plev_tmp(nzt_rad+2)   = MIN( 1.0E-4_wp, 0.25_wp                    &
5008                                         * rrtm_plev(0,nzt_rad+1) )
5009 
5010!
5011!--    Calculate trace gas path (zero at surface) with interpolation to the
5012!--    sounding levels
5013       ALLOCATE ( trace_mls_path(1:nzt_rad+2,1:num_trace_gases) )
5014
5015       trace_mls_path(nzb+1,:) = 0.0_wp
5016       
5017       DO k = nzb+2, nzt_rad+2
5018          DO m = 1, num_trace_gases
5019             trace_mls_path(k,m) = trace_mls_path(k-1,m)
5020
5021!
5022!--          When the pressure level is higher than the trace gas pressure
5023!--          level, assume that
5024             IF ( rrtm_plev_tmp(k-1) > p_mls(1) )  THEN             
5025               
5026                trace_mls_path(k,m) = trace_mls_path(k,m) + trace_mls(m,1)     &
5027                                      * ( rrtm_plev_tmp(k-1)                   &
5028                                          - MAX( p_mls(1), rrtm_plev_tmp(k) )  &
5029                                        ) / g
5030             ENDIF
5031
5032!
5033!--          Integrate for each sounding level from the contributing p_mls
5034!--          levels
5035             DO n = 2, np
5036!
5037!--             Limit p_mls so that it is within the model level
5038                p_mls_u = MIN( rrtm_plev_tmp(k-1),                             &
5039                          MAX( rrtm_plev_tmp(k), p_mls(n) ) )
5040                p_mls_l = MIN( rrtm_plev_tmp(k-1),                             &
5041                          MAX( rrtm_plev_tmp(k), p_mls(n-1) ) )
5042
5043                IF ( p_mls_l > p_mls_u )  THEN
5044
5045!
5046!--                Calculate weights for interpolation
5047                   p_mls_m = 0.5_wp * (p_mls_l + p_mls_u)
5048                   p_wgt_u = (p_mls(n-1) - p_mls_m) / (p_mls(n-1) - p_mls(n))
5049                   p_wgt_l = (p_mls_m - p_mls(n))   / (p_mls(n-1) - p_mls(n))
5050
5051!
5052!--                Add level to trace gas path
5053                   trace_mls_path(k,m) = trace_mls_path(k,m)                   &
5054                                         +  ( p_wgt_u * trace_mls(m,n)         &
5055                                            + p_wgt_l * trace_mls(m,n-1) )     &
5056                                         * (p_mls_l - p_mls_u) / g
5057                ENDIF
5058             ENDDO
5059
5060             IF ( rrtm_plev_tmp(k) < p_mls(np) )  THEN
5061                trace_mls_path(k,m) = trace_mls_path(k,m) + trace_mls(m,np)    &
5062                                      * ( MIN( rrtm_plev_tmp(k-1), p_mls(np) ) &
5063                                          - rrtm_plev_tmp(k)                   &
5064                                        ) / g 
5065             ENDIF 
5066          ENDDO
5067       ENDDO
5068
5069
5070!
5071!--    Prepare trace gas path profiles
5072       ALLOCATE ( trace_path_tmp(1:nzt_rad+1) )
5073
5074       DO m = 1, num_trace_gases
5075
5076          trace_path_tmp(1:nzt_rad+1) = ( trace_mls_path(2:nzt_rad+2,m)        &
5077                                       - trace_mls_path(1:nzt_rad+1,m) ) * g   &
5078                                       / ( rrtm_plev_tmp(1:nzt_rad+1)          &
5079                                       - rrtm_plev_tmp(2:nzt_rad+2) )
5080
5081!
5082!--       Save trace gas paths to the respective arrays
5083          SELECT CASE ( TRIM( trace_names(m) ) )
5084
5085             CASE ( 'O3' )
5086
5087                rrtm_o3vmr(0,:) = trace_path_tmp(:)
5088
5089             CASE ( 'CO2' )
5090
5091                rrtm_co2vmr(0,:) = trace_path_tmp(:)
5092
5093             CASE ( 'CH4' )
5094
5095                rrtm_ch4vmr(0,:) = trace_path_tmp(:)
5096
5097             CASE ( 'N2O' )
5098
5099                rrtm_n2ovmr(0,:) = trace_path_tmp(:)
5100
5101             CASE ( 'O2' )
5102
5103                rrtm_o2vmr(0,:) = trace_path_tmp(:)
5104
5105             CASE ( 'CFC11' )
5106
5107                rrtm_cfc11vmr(0,:) = trace_path_tmp(:)
5108
5109             CASE ( 'CFC12' )
5110
5111                rrtm_cfc12vmr(0,:) = trace_path_tmp(:)
5112
5113             CASE ( 'CFC22' )
5114
5115                rrtm_cfc22vmr(0,:) = trace_path_tmp(:)
5116
5117             CASE ( 'CCL4' )
5118
5119                rrtm_ccl4vmr(0,:) = trace_path_tmp(:)
5120
5121             CASE ( 'H2O' )
5122
5123                rrtm_h2ovmr(0,:) = trace_path_tmp(:)
5124               
5125             CASE DEFAULT
5126
5127          END SELECT
5128
5129       ENDDO
5130
5131       DEALLOCATE ( trace_path_tmp )
5132       DEALLOCATE ( trace_mls_path )
5133       DEALLOCATE ( rrtm_play_tmp )
5134       DEALLOCATE ( rrtm_plev_tmp )
5135       DEALLOCATE ( trace_mls )
5136       DEALLOCATE ( p_mls )
5137
5138    END SUBROUTINE read_trace_gas_data
5139
5140
5141    SUBROUTINE netcdf_handle_error_rad( routine_name, errno )
5142
5143       USE control_parameters,                                                 &
5144           ONLY:  message_string
5145
5146       USE NETCDF
5147
5148       USE pegrid
5149
5150       IMPLICIT NONE
5151
5152       CHARACTER(LEN=6) ::  message_identifier
5153       CHARACTER(LEN=*) ::  routine_name
5154
5155       INTEGER(iwp) ::  errno
5156
5157       IF ( nc_stat /= NF90_NOERR )  THEN
5158
5159          WRITE( message_identifier, '(''NC'',I4.4)' )  errno
5160          message_string = TRIM( NF90_STRERROR( nc_stat ) )
5161
5162          CALL message( routine_name, message_identifier, 2, 2, 0, 6, 1 )
5163
5164       ENDIF
5165
5166    END SUBROUTINE netcdf_handle_error_rad
5167#endif
5168
5169
5170!------------------------------------------------------------------------------!
5171! Description:
5172! ------------
5173!> Calculate temperature tendency due to radiative cooling/heating.
5174!> Cache-optimized version.
5175!------------------------------------------------------------------------------!
5176#if defined( __rrtmg )
5177 SUBROUTINE radiation_tendency_ij ( i, j, tend )
5178
5179    IMPLICIT NONE
5180
5181    INTEGER(iwp) :: i, j, k !< loop indices
5182
5183    REAL(wp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg) :: tend !< pt tendency term
5184
5185    IF ( radiation_scheme == 'rrtmg' )  THEN
5186!
5187!--    Calculate tendency based on heating rate
5188       DO k = nzb+1, nzt+1
5189          tend(k,j,i) = tend(k,j,i) + (rad_lw_hr(k,j,i) + rad_sw_hr(k,j,i))    &
5190                                         * d_exner(k) * d_seconds_hour
5191       ENDDO
5192
5193    ENDIF
5194
5195 END SUBROUTINE radiation_tendency_ij
5196#endif
5197
5198
5199!------------------------------------------------------------------------------!
5200! Description:
5201! ------------
5202!> Calculate temperature tendency due to radiative cooling/heating.
5203!> Vector-optimized version
5204!------------------------------------------------------------------------------!
5205#if defined( __rrtmg )
5206 SUBROUTINE radiation_tendency ( tend )
5207
5208    USE indices,                                                               &
5209        ONLY:  nxl, nxr, nyn, nys
5210
5211    IMPLICIT NONE
5212
5213    INTEGER(iwp) :: i, j, k !< loop indices
5214
5215    REAL(wp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg) :: tend !< pt tendency term
5216
5217    IF ( radiation_scheme == 'rrtmg' )  THEN
5218!
5219!--    Calculate tendency based on heating rate
5220       DO  i = nxl, nxr
5221          DO  j = nys, nyn
5222             DO k = nzb+1, nzt+1
5223                tend(k,j,i) = tend(k,j,i) + ( rad_lw_hr(k,j,i)                 &
5224                                          +  rad_sw_hr(k,j,i) ) * d_exner(k)   &
5225                                          * d_seconds_hour
5226             ENDDO
5227          ENDDO
5228       ENDDO
5229    ENDIF
5230
5231 END SUBROUTINE radiation_tendency
5232#endif
5233
5234!------------------------------------------------------------------------------!
5235! Description:
5236! ------------
5237!> This subroutine calculates interaction of the solar radiation
5238!> with urban and land surfaces and updates all surface heatfluxes.
5239!> It calculates also the required parameters for RRTMG lower BC.
5240!>
5241!> For more info. see Resler et al. 2017
5242!>
5243!> The new version 2.0 was radically rewriten, the discretization scheme
5244!> has been changed. This new version significantly improves effectivity
5245!> of the paralelization and the scalability of the model.
5246!------------------------------------------------------------------------------!
5247
5248 SUBROUTINE radiation_interaction
5249
5250     IMPLICIT NONE
5251
5252     INTEGER(iwp)                      :: i, j, k, kk, d, refstep, m, mm, l, ll
5253     INTEGER(iwp)                      :: isurf, isurfsrc, isvf, icsf, ipcgb
5254     INTEGER(iwp)                      :: imrt, imrtf
5255     INTEGER(iwp)                      :: isd                !< solar direction number
5256     INTEGER(iwp)                      :: pc_box_dimshift    !< transform for best accuracy
5257     INTEGER(iwp), DIMENSION(0:3)      :: reorder = (/ 1, 0, 3, 2 /)
5258     
5259     REAL(wp), DIMENSION(3,3)          :: mrot               !< grid rotation matrix (zyx)
5260     REAL(wp), DIMENSION(3,0:nsurf_type):: vnorm             !< face direction normal vectors (zyx)
5261     REAL(wp), DIMENSION(3)            :: sunorig            !< grid rotated solar direction unit vector (zyx)
5262     REAL(wp), DIMENSION(3)            :: sunorig_grid       !< grid squashed solar direction unit vector (zyx)
5263     REAL(wp), DIMENSION(0:nsurf_type) :: costheta           !< direct irradiance factor of solar angle
5264     REAL(wp), DIMENSION(nz_urban_b:nz_urban_t)    :: pchf_prep          !< precalculated factor for canopy temperature tendency
5265     REAL(wp), PARAMETER               :: alpha = 0._wp      !< grid rotation (TODO: synchronize with rotation_angle
5266                                                             !< from netcdf_data_input_mod)
5267     REAL(wp)                          :: pc_box_area, pc_abs_frac, pc_abs_eff
5268     REAL(wp)                          :: asrc               !< area of source face
5269     REAL(wp)                          :: pcrad              !< irradiance from plant canopy
5270     REAL(wp)                          :: pabsswl  = 0.0_wp  !< total absorbed SW radiation energy in local processor (W)
5271     REAL(wp)                          :: pabssw   = 0.0_wp  !< total absorbed SW radiation energy in all processors (W)
5272     REAL(wp)                          :: pabslwl  = 0.0_wp  !< total absorbed LW radiation energy in local processor (W)
5273     REAL(wp)                          :: pabslw   = 0.0_wp  !< total absorbed LW radiation energy in all processors (W)
5274     REAL(wp)                          :: pemitlwl = 0.0_wp  !< total emitted LW radiation energy in all processors (W)
5275     REAL(wp)                          :: pemitlw  = 0.0_wp  !< total emitted LW radiation energy in all processors (W)
5276     REAL(wp)                          :: pinswl   = 0.0_wp  !< total received SW radiation energy in local processor (W)
5277     REAL(wp)                          :: pinsw    = 0.0_wp  !< total received SW radiation energy in all processor (W)
5278     REAL(wp)                          :: pinlwl   = 0.0_wp  !< total received LW radiation energy in local processor (W)
5279     REAL(wp)                          :: pinlw    = 0.0_wp  !< total received LW radiation energy in all processor (W)
5280     REAL(wp)                          :: emiss_sum_surfl    !< sum of emissisivity of surfaces in local processor
5281     REAL(wp)                          :: emiss_sum_surf     !< sum of emissisivity of surfaces in all processor
5282     REAL(wp)                          :: area_surfl         !< total area of surfaces in local processor
5283     REAL(wp)                          :: area_surf          !< total area of surfaces in all processor
5284     REAL(wp)                          :: area_hor           !< total horizontal area of domain in all processor
5285
5286
5287     IF ( debug_output_timestep )  CALL debug_message( 'radiation_interaction', 'start' )
5288
5289     IF ( plant_canopy )  THEN
5290         pchf_prep(:) = r_d * exner(nz_urban_b:nz_urban_t)                                 &
5291                     / (c_p * hyp(nz_urban_b:nz_urban_t) * dx*dy*dz(1)) !< equals to 1 / (rho * c_p * Vbox * T)
5292     ENDIF
5293
5294     sun_direction = .TRUE.
5295     CALL calc_zenith  !< required also for diffusion radiation
5296
5297!--     prepare rotated normal vectors and irradiance factor
5298     vnorm(1,:) = kdir(:)
5299     vnorm(2,:) = jdir(:)
5300     vnorm(3,:) = idir(:)
5301     mrot(1, :) = (/ 1._wp,  0._wp,      0._wp      /)
5302     mrot(2, :) = (/ 0._wp,  COS(alpha), SIN(alpha) /)
5303     mrot(3, :) = (/ 0._wp, -SIN(alpha), COS(alpha) /)
5304     sunorig = (/ cos_zenith, sun_dir_lat, sun_dir_lon /)
5305     sunorig = MATMUL(mrot, sunorig)
5306     DO d = 0, nsurf_type
5307         costheta(d) = DOT_PRODUCT(sunorig, vnorm(:,d))
5308     ENDDO
5309
5310     IF ( cos_zenith > 0 )  THEN
5311!--      now we will "squash" the sunorig vector by grid box size in
5312!--      each dimension, so that this new direction vector will allow us
5313!--      to traverse the ray path within grid coordinates directly
5314         sunorig_grid = (/ sunorig(1)/dz(1), sunorig(2)/dy, sunorig(3)/dx /)
5315!--      sunorig_grid = sunorig_grid / norm2(sunorig_grid)
5316         sunorig_grid = sunorig_grid / SQRT(SUM(sunorig_grid**2))
5317
5318         IF ( npcbl > 0 )  THEN
5319!--         precompute effective box depth with prototype Leaf Area Density
5320            pc_box_dimshift = MAXLOC(ABS(sunorig), 1) - 1
5321            CALL box_absorb(CSHIFT((/dz(1),dy,dx/), pc_box_dimshift),       &
5322                                60, prototype_lad,                          &
5323                                CSHIFT(ABS(sunorig), pc_box_dimshift),      &
5324                                pc_box_area, pc_abs_frac)
5325            pc_box_area = pc_box_area * ABS(sunorig(pc_box_dimshift+1)      &
5326                          / sunorig(1))
5327            pc_abs_eff = LOG(1._wp - pc_abs_frac) / prototype_lad
5328         ENDIF
5329     ENDIF
5330
5331!--  if radiation scheme is not RRTMG, split diffusion and direct part of the solar downward radiation
5332!--  comming from radiation model and store it in 2D arrays
5333     IF (  radiation_scheme /= 'rrtmg'  )  CALL calc_diffusion_radiation
5334
5335!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5336!--     First pass: direct + diffuse irradiance + thermal
5337!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5338     surfinswdir   = 0._wp !nsurfl
5339     surfins       = 0._wp !nsurfl
5340     surfinl       = 0._wp !nsurfl
5341     surfoutsl(:)  = 0.0_wp !start-end
5342     surfoutll(:)  = 0.0_wp !start-end
5343     IF ( nmrtbl > 0 )  THEN
5344        mrtinsw(:) = 0._wp
5345        mrtinlw(:) = 0._wp
5346     ENDIF
5347     surfinlg(:)  = 0._wp !global
5348
5349
5350!--  Set up thermal radiation from surfaces
5351!--  emiss_surf is defined only for surfaces for which energy balance is calculated
5352!--  Workaround: reorder surface data type back on 1D array including all surfaces,
5353!--  which implies to reorder horizontal and vertical surfaces
5354!
5355!--  Horizontal walls
5356     mm = 1
5357     DO  i = nxl, nxr
5358        DO  j = nys, nyn
5359!--           urban
5360           DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
5361              surfoutll(mm) = SUM ( surf_usm_h%frac(:,m) *                  &
5362                                    surf_usm_h%emissivity(:,m) )            &
5363                                  * sigma_sb                                &
5364                                  * surf_usm_h%pt_surface(m)**4
5365              albedo_surf(mm) = SUM ( surf_usm_h%frac(:,m) *                &
5366                                      surf_usm_h%albedo(:,m) )
5367              emiss_surf(mm)  = SUM ( surf_usm_h%frac(:,m) *                &
5368                                      surf_usm_h%emissivity(:,m) )
5369              mm = mm + 1
5370           ENDDO
5371!--           land
5372           DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
5373              surfoutll(mm) = SUM ( surf_lsm_h%frac(:,m) *                  &
5374                                    surf_lsm_h%emissivity(:,m) )            &
5375                                  * sigma_sb                                &
5376                                  * surf_lsm_h%pt_surface(m)**4
5377              albedo_surf(mm) = SUM ( surf_lsm_h%frac(:,m) *                &
5378                                      surf_lsm_h%albedo(:,m) )
5379              emiss_surf(mm)  = SUM ( surf_lsm_h%frac(:,m) *                &
5380                                      surf_lsm_h%emissivity(:,m) )
5381              mm = mm + 1
5382           ENDDO
5383        ENDDO
5384     ENDDO
5385!
5386!--     Vertical walls
5387     DO  i = nxl, nxr
5388        DO  j = nys, nyn
5389           DO  ll = 0, 3
5390              l = reorder(ll)
5391!--              urban
5392              DO  m = surf_usm_v(l)%start_index(j,i),                       &
5393                      surf_usm_v(l)%end_index(j,i)
5394                 surfoutll(mm) = SUM ( surf_usm_v(l)%frac(:,m) *            &
5395                                       surf_usm_v(l)%emissivity(:,m) )      &
5396                                  * sigma_sb                                &
5397                                  * surf_usm_v(l)%pt_surface(m)**4
5398                 albedo_surf(mm) = SUM ( surf_usm_v(l)%frac(:,m) *          &
5399                                         surf_usm_v(l)%albedo(:,m) )
5400                 emiss_surf(mm)  = SUM ( surf_usm_v(l)%frac(:,m) *          &
5401                                         surf_usm_v(l)%emissivity(:,m) )
5402                 mm = mm + 1
5403              ENDDO
5404!--              land
5405              DO  m = surf_lsm_v(l)%start_index(j,i),                       &
5406                      surf_lsm_v(l)%end_index(j,i)
5407                 surfoutll(mm) = SUM ( surf_lsm_v(l)%frac(:,m) *            &
5408                                       surf_lsm_v(l)%emissivity(:,m) )      &
5409                                  * sigma_sb                                &
5410                                  * surf_lsm_v(l)%pt_surface(m)**4
5411                 albedo_surf(mm) = SUM ( surf_lsm_v(l)%frac(:,m) *          &
5412                                         surf_lsm_v(l)%albedo(:,m) )
5413                 emiss_surf(mm)  = SUM ( surf_lsm_v(l)%frac(:,m) *          &
5414                                         surf_lsm_v(l)%emissivity(:,m) )
5415                 mm = mm + 1
5416              ENDDO
5417           ENDDO
5418        ENDDO
5419     ENDDO
5420
5421#if defined( __parallel )
5422!--     might be optimized and gather only values relevant for current processor
5423     CALL MPI_AllGatherv(surfoutll, nsurfl, MPI_REAL, &
5424                         surfoutl, nsurfs, surfstart, MPI_REAL, comm2d, ierr) !nsurf global
5425     IF ( ierr /= 0 ) THEN
5426         WRITE(9,*) 'Error MPI_AllGatherv1:', ierr, SIZE(surfoutll), nsurfl, &
5427                     SIZE(surfoutl), nsurfs, surfstart
5428         FLUSH(9)
5429     ENDIF
5430#else
5431     surfoutl(:) = surfoutll(:) !nsurf global
5432#endif
5433
5434     IF ( surface_reflections)  THEN
5435        DO  isvf = 1, nsvfl
5436           isurf = svfsurf(1, isvf)
5437           k     = surfl(iz, isurf)
5438           j     = surfl(iy, isurf)
5439           i     = surfl(ix, isurf)
5440           isurfsrc = svfsurf(2, isvf)
5441!
5442!--        For surface-to-surface factors we calculate thermal radiation in 1st pass
5443           IF ( plant_lw_interact )  THEN
5444              surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * svf(2,isvf) * surfoutl(isurfsrc)
5445           ELSE
5446              surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * surfoutl(isurfsrc)
5447           ENDIF
5448        ENDDO
5449     ENDIF
5450!
5451!--  diffuse radiation using sky view factor
5452     DO isurf = 1, nsurfl
5453        j = surfl(iy, isurf)
5454        i = surfl(ix, isurf)
5455        surfinswdif(isurf) = rad_sw_in_diff(j,i) * skyvft(isurf)
5456        IF ( plant_lw_interact )  THEN
5457           surfinlwdif(isurf) = rad_lw_in_diff(j,i) * skyvft(isurf)
5458        ELSE
5459           surfinlwdif(isurf) = rad_lw_in_diff(j,i) * skyvf(isurf)
5460        ENDIF
5461     ENDDO
5462!
5463!--  MRT diffuse irradiance
5464     DO  imrt = 1, nmrtbl
5465        j = mrtbl(iy, imrt)
5466        i = mrtbl(ix, imrt)
5467        mrtinsw(imrt) = mrtskyt(imrt) * rad_sw_in_diff(j,i)
5468        mrtinlw(imrt) = mrtsky(imrt) * rad_lw_in_diff(j,i)
5469     ENDDO
5470
5471     !-- direct radiation
5472     IF ( cos_zenith > 0 )  THEN
5473        !--Identify solar direction vector (discretized number) 1)
5474        !--
5475        j = FLOOR(ACOS(cos_zenith) / pi * raytrace_discrete_elevs)
5476        i = MODULO(NINT(ATAN2(sun_dir_lon, sun_dir_lat)               &
5477                        / (2._wp*pi) * raytrace_discrete_azims-.5_wp, iwp), &
5478                   raytrace_discrete_azims)
5479        isd = dsidir_rev(j, i)
5480!-- TODO: check if isd = -1 to report that this solar position is not precalculated
5481        DO isurf = 1, nsurfl
5482           j = surfl(iy, isurf)
5483           i = surfl(ix, isurf)
5484           surfinswdir(isurf) = rad_sw_in_dir(j,i) *                        &
5485                costheta(surfl(id, isurf)) * dsitrans(isurf, isd) / cos_zenith
5486        ENDDO
5487!
5488!--     MRT direct irradiance
5489        DO  imrt = 1, nmrtbl
5490           j = mrtbl(iy, imrt)
5491           i = mrtbl(ix, imrt)
5492           mrtinsw(imrt) = mrtinsw(imrt) + mrtdsit(imrt, isd) * rad_sw_in_dir(j,i) &
5493                                     / cos_zenith / 4._wp ! normal to sphere
5494        ENDDO
5495     ENDIF
5496!
5497!--  MRT first pass thermal
5498     DO  imrtf = 1, nmrtf
5499        imrt = mrtfsurf(1, imrtf)
5500        isurfsrc = mrtfsurf(2, imrtf)
5501        mrtinlw(imrt) = mrtinlw(imrt) + mrtf(imrtf) * surfoutl(isurfsrc)
5502     ENDDO
5503!
5504!--  Absorption in each local plant canopy grid box from the first atmospheric
5505!--  pass of radiation
5506     IF ( npcbl > 0 )  THEN
5507
5508         pcbinswdir(:) = 0._wp
5509         pcbinswdif(:) = 0._wp
5510         pcbinlw(:) = 0._wp
5511
5512         DO icsf = 1, ncsfl
5513             ipcgb = csfsurf(1, icsf)
5514             i = pcbl(ix,ipcgb)
5515             j = pcbl(iy,ipcgb)
5516             k = pcbl(iz,ipcgb)
5517             isurfsrc = csfsurf(2, icsf)
5518
5519             IF ( isurfsrc == -1 )  THEN
5520!
5521!--             Diffuse radiation from sky
5522                pcbinswdif(ipcgb) = csf(1,icsf) * rad_sw_in_diff(j,i)
5523!
5524!--             Absorbed diffuse LW radiation from sky minus emitted to sky
5525                IF ( plant_lw_interact )  THEN
5526                   pcbinlw(ipcgb) = csf(1,icsf)                                  &
5527                                       * (rad_lw_in_diff(j, i)                   &
5528                                          - sigma_sb * (pt(k,j,i)*exner(k))**4)
5529                ENDIF
5530!
5531!--             Direct solar radiation
5532                IF ( cos_zenith > 0 )  THEN
5533!--                Estimate directed box absorption
5534                   pc_abs_frac = 1._wp - exp(pc_abs_eff * lad_s(k,j,i))
5535!
5536!--                isd has already been established, see 1)
5537                   pcbinswdir(ipcgb) = rad_sw_in_dir(j, i) * pc_box_area &
5538                                       * pc_abs_frac * dsitransc(ipcgb, isd)
5539                ENDIF
5540             ELSE
5541                IF ( plant_lw_interact )  THEN
5542!
5543!--                Thermal emission from plan canopy towards respective face
5544                   pcrad = sigma_sb * (pt(k,j,i) * exner(k))**4 * csf(1,icsf)
5545                   surfinlg(isurfsrc) = surfinlg(isurfsrc) + pcrad
5546!
5547!--                Remove the flux above + absorb LW from first pass from surfaces
5548                   asrc = facearea(surf(id, isurfsrc))
5549                   pcbinlw(ipcgb) = pcbinlw(ipcgb)                      &
5550                                    + (csf(1,icsf) * surfoutl(isurfsrc) & ! Absorb from first pass surf emit
5551                                       - pcrad)                         & ! Remove emitted heatflux
5552                                    * asrc
5553                ENDIF
5554             ENDIF
5555         ENDDO
5556
5557         pcbinsw(:) = pcbinswdir(:) + pcbinswdif(:)
5558     ENDIF
5559
5560     IF ( plant_lw_interact )  THEN
5561!
5562!--     Exchange incoming lw radiation from plant canopy
5563#if defined( __parallel )
5564        CALL MPI_Allreduce(MPI_IN_PLACE, surfinlg, nsurf, MPI_REAL, MPI_SUM, comm2d, ierr)
5565        IF ( ierr /= 0 )  THEN
5566           WRITE (9,*) 'Error MPI_Allreduce:', ierr
5567           FLUSH(9)
5568        ENDIF
5569        surfinl(:) = surfinl(:) + surfinlg(surfstart(myid)+1:surfstart(myid+1))
5570#else
5571        surfinl(:) = surfinl(:) + surfinlg(:)
5572#endif
5573     ENDIF
5574
5575     surfins = surfinswdir + surfinswdif
5576     surfinl = surfinl + surfinlwdif
5577     surfinsw = surfins
5578     surfinlw = surfinl
5579     surfoutsw = 0.0_wp
5580     surfoutlw = surfoutll
5581     surfemitlwl = surfoutll
5582
5583     IF ( .NOT.  surface_reflections )  THEN
5584!
5585!--     Set nrefsteps to 0 to disable reflections       
5586        nrefsteps = 0
5587        surfoutsl = albedo_surf * surfins
5588        surfoutll = (1._wp - emiss_surf) * surfinl
5589        surfoutsw = surfoutsw + surfoutsl
5590        surfoutlw = surfoutlw + surfoutll
5591     ENDIF
5592
5593!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5594!--     Next passes - reflections
5595!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5596     DO refstep = 1, nrefsteps
5597
5598         surfoutsl = albedo_surf * surfins
5599!
5600!--      for non-transparent surfaces, longwave albedo is 1 - emissivity
5601         surfoutll = (1._wp - emiss_surf) * surfinl
5602
5603#if defined( __parallel )
5604         CALL MPI_AllGatherv(surfoutsl, nsurfl, MPI_REAL, &
5605             surfouts, nsurfs, surfstart, MPI_REAL, comm2d, ierr)
5606         IF ( ierr /= 0 )  THEN
5607             WRITE(9,*) 'Error MPI_AllGatherv2:', ierr, SIZE(surfoutsl), nsurfl, &
5608                        SIZE(surfouts), nsurfs, surfstart
5609             FLUSH(9)
5610         ENDIF
5611
5612         CALL MPI_AllGatherv(surfoutll, nsurfl, MPI_REAL, &
5613             surfoutl, nsurfs, surfstart, MPI_REAL, comm2d, ierr)
5614         IF ( ierr /= 0 )  THEN
5615             WRITE(9,*) 'Error MPI_AllGatherv3:', ierr, SIZE(surfoutll), nsurfl, &
5616                        SIZE(surfoutl), nsurfs, surfstart
5617             FLUSH(9)
5618         ENDIF
5619
5620#else
5621         surfouts = surfoutsl
5622         surfoutl = surfoutll
5623#endif
5624!
5625!--      Reset for the input from next reflective pass
5626         surfins = 0._wp
5627         surfinl = 0._wp
5628!
5629!--      Reflected radiation
5630         DO isvf = 1, nsvfl
5631             isurf = svfsurf(1, isvf)
5632             isurfsrc = svfsurf(2, isvf)
5633             surfins(isurf) = surfins(isurf) + svf(1,isvf) * svf(2,isvf) * surfouts(isurfsrc)
5634             IF ( plant_lw_interact )  THEN
5635                surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * svf(2,isvf) * surfoutl(isurfsrc)
5636             ELSE
5637                surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * surfoutl(isurfsrc)
5638             ENDIF
5639         ENDDO
5640!
5641!--      NOTE: PC absorbtion and MRT from reflected can both be done at once
5642!--      after all reflections if we do one more MPI_ALLGATHERV on surfout.
5643!--      Advantage: less local computation. Disadvantage: one more collective
5644!--      MPI call.
5645!
5646!--      Radiation absorbed by plant canopy
5647         DO  icsf = 1, ncsfl
5648             ipcgb = csfsurf(1, icsf)
5649             isurfsrc = csfsurf(2, icsf)
5650             IF ( isurfsrc == -1 )  CYCLE ! sky->face only in 1st pass, not here
5651!
5652!--          Calculate source surface area. If the `surf' array is removed
5653!--          before timestepping starts (future version), then asrc must be
5654!--          stored within `csf'
5655             asrc = facearea(surf(id, isurfsrc))
5656             pcbinsw(ipcgb) = pcbinsw(ipcgb) + csf(1,icsf) * surfouts(isurfsrc) * asrc
5657             IF ( plant_lw_interact )  THEN
5658                pcbinlw(ipcgb) = pcbinlw(ipcgb) + csf(1,icsf) * surfoutl(isurfsrc) * asrc
5659             ENDIF
5660         ENDDO
5661!
5662!--      MRT reflected
5663         DO  imrtf = 1, nmrtf
5664            imrt = mrtfsurf(1, imrtf)
5665            isurfsrc = mrtfsurf(2, imrtf)
5666            mrtinsw(imrt) = mrtinsw(imrt) + mrtft(imrtf) * surfouts(isurfsrc)
5667            mrtinlw(imrt) = mrtinlw(imrt) + mrtf(imrtf) * surfoutl(isurfsrc)
5668         ENDDO
5669
5670         surfinsw = surfinsw  + surfins
5671         surfinlw = surfinlw  + surfinl
5672         surfoutsw = surfoutsw + surfoutsl
5673         surfoutlw = surfoutlw + surfoutll
5674
5675     ENDDO ! refstep
5676
5677!--  push heat flux absorbed by plant canopy to respective 3D arrays
5678     IF ( npcbl > 0 )  THEN
5679         pc_heating_rate(:,:,:) = 0.0_wp
5680         DO ipcgb = 1, npcbl
5681             j = pcbl(iy, ipcgb)
5682             i = pcbl(ix, ipcgb)
5683             k = pcbl(iz, ipcgb)
5684!
5685!--          Following expression equals former kk = k - nzb_s_inner(j,i)
5686             kk = k - topo_top_ind(j,i,0)  !- lad arrays are defined flat
5687             pc_heating_rate(kk, j, i) = (pcbinsw(ipcgb) + pcbinlw(ipcgb)) &
5688                 * pchf_prep(k) * pt(k, j, i) !-- = dT/dt
5689         ENDDO
5690
5691         IF ( humidity .AND. plant_canopy_transpiration ) THEN
5692!--          Calculation of plant canopy transpiration rate and correspondidng latent heat rate
5693             pc_transpiration_rate(:,:,:) = 0.0_wp
5694             pc_latent_rate(:,:,:) = 0.0_wp
5695             DO ipcgb = 1, npcbl
5696                 i = pcbl(ix, ipcgb)
5697                 j = pcbl(iy, ipcgb)
5698                 k = pcbl(iz, ipcgb)
5699                 kk = k - topo_top_ind(j,i,0)  !- lad arrays are defined flat
5700                 CALL pcm_calc_transpiration_rate( i, j, k, kk, pcbinsw(ipcgb), pcbinlw(ipcgb), &
5701                                                   pc_transpiration_rate(kk,j,i), pc_latent_rate(kk,j,i) )
5702              ENDDO
5703         ENDIF
5704     ENDIF
5705!
5706!--  Calculate black body MRT (after all reflections)
5707     IF ( nmrtbl > 0 )  THEN
5708        IF ( mrt_include_sw )  THEN
5709           mrt(:) = ((mrtinsw(:) + mrtinlw(:)) / sigma_sb) ** .25_wp
5710        ELSE
5711           mrt(:) = (mrtinlw(:) / sigma_sb) ** .25_wp
5712        ENDIF
5713     ENDIF
5714!
5715!--     Transfer radiation arrays required for energy balance to the respective data types
5716     DO  i = 1, nsurfl
5717        m  = surfl(im,i)
5718!
5719!--     (1) Urban surfaces
5720!--     upward-facing
5721        IF ( surfl(1,i) == iup_u )  THEN
5722           surf_usm_h%rad_sw_in(m)  = surfinsw(i)
5723           surf_usm_h%rad_sw_out(m) = surfoutsw(i)
5724           surf_usm_h%rad_sw_dir(m) = surfinswdir(i)
5725           surf_usm_h%rad_sw_dif(m) = surfinswdif(i)
5726           surf_usm_h%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -        &
5727                                      surfinswdif(i)
5728           surf_usm_h%rad_sw_res(m) = surfins(i)
5729           surf_usm_h%rad_lw_in(m)  = surfinlw(i)
5730           surf_usm_h%rad_lw_out(m) = surfoutlw(i)
5731           surf_usm_h%rad_net(m)    = surfinsw(i) - surfoutsw(i) +          &
5732                                      surfinlw(i) - surfoutlw(i)
5733           surf_usm_h%rad_net_l(m)  = surf_usm_h%rad_net(m)
5734           surf_usm_h%rad_lw_dif(m) = surfinlwdif(i)
5735           surf_usm_h%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5736           surf_usm_h%rad_lw_res(m) = surfinl(i)
5737!
5738!--     northward-facding
5739        ELSEIF ( surfl(1,i) == inorth_u )  THEN
5740           surf_usm_v(0)%rad_sw_in(m)  = surfinsw(i)
5741           surf_usm_v(0)%rad_sw_out(m) = surfoutsw(i)
5742           surf_usm_v(0)%rad_sw_dir(m) = surfinswdir(i)
5743           surf_usm_v(0)%rad_sw_dif(m) = surfinswdif(i)
5744           surf_usm_v(0)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5745                                         surfinswdif(i)
5746           surf_usm_v(0)%rad_sw_res(m) = surfins(i)
5747           surf_usm_v(0)%rad_lw_in(m)  = surfinlw(i)
5748           surf_usm_v(0)%rad_lw_out(m) = surfoutlw(i)
5749           surf_usm_v(0)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5750                                         surfinlw(i) - surfoutlw(i)
5751           surf_usm_v(0)%rad_net_l(m)  = surf_usm_v(0)%rad_net(m)
5752           surf_usm_v(0)%rad_lw_dif(m) = surfinlwdif(i)
5753           surf_usm_v(0)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5754           surf_usm_v(0)%rad_lw_res(m) = surfinl(i)
5755!
5756!--     southward-facding
5757        ELSEIF ( surfl(1,i) == isouth_u )  THEN
5758           surf_usm_v(1)%rad_sw_in(m)  = surfinsw(i)
5759           surf_usm_v(1)%rad_sw_out(m) = surfoutsw(i)
5760           surf_usm_v(1)%rad_sw_dir(m) = surfinswdir(i)
5761           surf_usm_v(1)%rad_sw_dif(m) = surfinswdif(i)
5762           surf_usm_v(1)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5763                                         surfinswdif(i)
5764           surf_usm_v(1)%rad_sw_res(m) = surfins(i)
5765           surf_usm_v(1)%rad_lw_in(m)  = surfinlw(i)
5766           surf_usm_v(1)%rad_lw_out(m) = surfoutlw(i)
5767           surf_usm_v(1)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5768                                         surfinlw(i) - surfoutlw(i)
5769           surf_usm_v(1)%rad_net_l(m)  = surf_usm_v(1)%rad_net(m)
5770           surf_usm_v(1)%rad_lw_dif(m) = surfinlwdif(i)
5771           surf_usm_v(1)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5772           surf_usm_v(1)%rad_lw_res(m) = surfinl(i)
5773!
5774!--     eastward-facing
5775        ELSEIF ( surfl(1,i) == ieast_u )  THEN
5776           surf_usm_v(2)%rad_sw_in(m)  = surfinsw(i)
5777           surf_usm_v(2)%rad_sw_out(m) = surfoutsw(i)
5778           surf_usm_v(2)%rad_sw_dir(m) = surfinswdir(i)
5779           surf_usm_v(2)%rad_sw_dif(m) = surfinswdif(i)
5780           surf_usm_v(2)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5781                                         surfinswdif(i)
5782           surf_usm_v(2)%rad_sw_res(m) = surfins(i)
5783           surf_usm_v(2)%rad_lw_in(m)  = surfinlw(i)
5784           surf_usm_v(2)%rad_lw_out(m) = surfoutlw(i)
5785           surf_usm_v(2)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5786                                         surfinlw(i) - surfoutlw(i)
5787           surf_usm_v(2)%rad_net_l(m)  = surf_usm_v(2)%rad_net(m)
5788           surf_usm_v(2)%rad_lw_dif(m) = surfinlwdif(i)
5789           surf_usm_v(2)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5790           surf_usm_v(2)%rad_lw_res(m) = surfinl(i)
5791!
5792!--     westward-facding
5793        ELSEIF ( surfl(1,i) == iwest_u )  THEN
5794           surf_usm_v(3)%rad_sw_in(m)  = surfinsw(i)
5795           surf_usm_v(3)%rad_sw_out(m) = surfoutsw(i)
5796           surf_usm_v(3)%rad_sw_dir(m) = surfinswdir(i)
5797           surf_usm_v(3)%rad_sw_dif(m) = surfinswdif(i)
5798           surf_usm_v(3)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5799                                         surfinswdif(i)
5800           surf_usm_v(3)%rad_sw_res(m) = surfins(i)
5801           surf_usm_v(3)%rad_lw_in(m)  = surfinlw(i)
5802           surf_usm_v(3)%rad_lw_out(m) = surfoutlw(i)
5803           surf_usm_v(3)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5804                                         surfinlw(i) - surfoutlw(i)
5805           surf_usm_v(3)%rad_net_l(m)  = surf_usm_v(3)%rad_net(m)
5806           surf_usm_v(3)%rad_lw_dif(m) = surfinlwdif(i)
5807           surf_usm_v(3)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5808           surf_usm_v(3)%rad_lw_res(m) = surfinl(i)
5809!
5810!--     (2) land surfaces
5811!--     upward-facing
5812        ELSEIF ( surfl(1,i) == iup_l )  THEN
5813           surf_lsm_h%rad_sw_in(m)  = surfinsw(i)
5814           surf_lsm_h%rad_sw_out(m) = surfoutsw(i)
5815           surf_lsm_h%rad_sw_dir(m) = surfinswdir(i)
5816           surf_lsm_h%rad_sw_dif(m) = surfinswdif(i)
5817           surf_lsm_h%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -        &
5818                                         surfinswdif(i)
5819           surf_lsm_h%rad_sw_res(m) = surfins(i)
5820           surf_lsm_h%rad_lw_in(m)  = surfinlw(i)
5821           surf_lsm_h%rad_lw_out(m) = surfoutlw(i)
5822           surf_lsm_h%rad_net(m)    = surfinsw(i) - surfoutsw(i) +          &
5823                                      surfinlw(i) - surfoutlw(i)
5824           surf_lsm_h%rad_lw_dif(m) = surfinlwdif(i)
5825           surf_lsm_h%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5826           surf_lsm_h%rad_lw_res(m) = surfinl(i)
5827!
5828!--     northward-facding
5829        ELSEIF ( surfl(1,i) == inorth_l )  THEN
5830           surf_lsm_v(0)%rad_sw_in(m)  = surfinsw(i)
5831           surf_lsm_v(0)%rad_sw_out(m) = surfoutsw(i)
5832           surf_lsm_v(0)%rad_sw_dir(m) = surfinswdir(i)
5833           surf_lsm_v(0)%rad_sw_dif(m) = surfinswdif(i)
5834           surf_lsm_v(0)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5835                                         surfinswdif(i)
5836           surf_lsm_v(0)%rad_sw_res(m) = surfins(i)
5837           surf_lsm_v(0)%rad_lw_in(m)  = surfinlw(i)
5838           surf_lsm_v(0)%rad_lw_out(m) = surfoutlw(i)
5839           surf_lsm_v(0)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5840                                         surfinlw(i) - surfoutlw(i)
5841           surf_lsm_v(0)%rad_lw_dif(m) = surfinlwdif(i)
5842           surf_lsm_v(0)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5843           surf_lsm_v(0)%rad_lw_res(m) = surfinl(i)
5844!
5845!--     southward-facding
5846        ELSEIF ( surfl(1,i) == isouth_l )  THEN
5847           surf_lsm_v(1)%rad_sw_in(m)  = surfinsw(i)
5848           surf_lsm_v(1)%rad_sw_out(m) = surfoutsw(i)
5849           surf_lsm_v(1)%rad_sw_dir(m) = surfinswdir(i)
5850           surf_lsm_v(1)%rad_sw_dif(m) = surfinswdif(i)
5851           surf_lsm_v(1)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5852                                         surfinswdif(i)
5853           surf_lsm_v(1)%rad_sw_res(m) = surfins(i)
5854           surf_lsm_v(1)%rad_lw_in(m)  = surfinlw(i)
5855           surf_lsm_v(1)%rad_lw_out(m) = surfoutlw(i)
5856           surf_lsm_v(1)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5857                                         surfinlw(i) - surfoutlw(i)
5858           surf_lsm_v(1)%rad_lw_dif(m) = surfinlwdif(i)
5859           surf_lsm_v(1)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5860           surf_lsm_v(1)%rad_lw_res(m) = surfinl(i)
5861!
5862!--     eastward-facing
5863        ELSEIF ( surfl(1,i) == ieast_l )  THEN
5864           surf_lsm_v(2)%rad_sw_in(m)  = surfinsw(i)
5865           surf_lsm_v(2)%rad_sw_out(m) = surfoutsw(i)
5866           surf_lsm_v(2)%rad_sw_dir(m) = surfinswdir(i)
5867           surf_lsm_v(2)%rad_sw_dif(m) = surfinswdif(i)
5868           surf_lsm_v(2)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5869                                         surfinswdif(i)
5870           surf_lsm_v(2)%rad_sw_res(m) = surfins(i)
5871           surf_lsm_v(2)%rad_lw_in(m)  = surfinlw(i)
5872           surf_lsm_v(2)%rad_lw_out(m) = surfoutlw(i)
5873           surf_lsm_v(2)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5874                                         surfinlw(i) - surfoutlw(i)
5875           surf_lsm_v(2)%rad_lw_dif(m) = surfinlwdif(i)
5876           surf_lsm_v(2)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5877           surf_lsm_v(2)%rad_lw_res(m) = surfinl(i)
5878!
5879!--     westward-facing
5880        ELSEIF ( surfl(1,i) == iwest_l )  THEN
5881           surf_lsm_v(3)%rad_sw_in(m)  = surfinsw(i)
5882           surf_lsm_v(3)%rad_sw_out(m) = surfoutsw(i)
5883           surf_lsm_v(3)%rad_sw_dir(m) = surfinswdir(i)
5884           surf_lsm_v(3)%rad_sw_dif(m) = surfinswdif(i)
5885           surf_lsm_v(3)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5886                                         surfinswdif(i)
5887           surf_lsm_v(3)%rad_sw_res(m) = surfins(i)
5888           surf_lsm_v(3)%rad_lw_in(m)  = surfinlw(i)
5889           surf_lsm_v(3)%rad_lw_out(m) = surfoutlw(i)
5890           surf_lsm_v(3)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5891                                         surfinlw(i) - surfoutlw(i)
5892           surf_lsm_v(3)%rad_lw_dif(m) = surfinlwdif(i)
5893           surf_lsm_v(3)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5894           surf_lsm_v(3)%rad_lw_res(m) = surfinl(i)
5895        ENDIF
5896
5897     ENDDO
5898
5899     DO  m = 1, surf_usm_h%ns
5900        surf_usm_h%surfhf(m) = surf_usm_h%rad_sw_in(m)  +                   &
5901                               surf_usm_h%rad_lw_in(m)  -                   &
5902                               surf_usm_h%rad_sw_out(m) -                   &
5903                               surf_usm_h%rad_lw_out(m)
5904     ENDDO
5905     DO  m = 1, surf_lsm_h%ns
5906        surf_lsm_h%surfhf(m) = surf_lsm_h%rad_sw_in(m)  +                   &
5907                               surf_lsm_h%rad_lw_in(m)  -                   &
5908                               surf_lsm_h%rad_sw_out(m) -                   &
5909                               surf_lsm_h%rad_lw_out(m)
5910     ENDDO
5911
5912     DO  l = 0, 3
5913!--     urban
5914        DO  m = 1, surf_usm_v(l)%ns
5915           surf_usm_v(l)%surfhf(m) = surf_usm_v(l)%rad_sw_in(m)  +          &
5916                                     surf_usm_v(l)%rad_lw_in(m)  -          &
5917                                     surf_usm_v(l)%rad_sw_out(m) -          &
5918                                     surf_usm_v(l)%rad_lw_out(m)
5919        ENDDO
5920!--     land
5921        DO  m = 1, surf_lsm_v(l)%ns
5922           surf_lsm_v(l)%surfhf(m) = surf_lsm_v(l)%rad_sw_in(m)  +          &
5923                                     surf_lsm_v(l)%rad_lw_in(m)  -          &
5924                                     surf_lsm_v(l)%rad_sw_out(m) -          &
5925                                     surf_lsm_v(l)%rad_lw_out(m)
5926
5927        ENDDO
5928     ENDDO
5929!
5930!--  Calculate the average temperature, albedo, and emissivity for urban/land
5931!--  domain when using average_radiation in the respective radiation model
5932
5933!--  calculate horizontal area
5934! !!! ATTENTION!!! uniform grid is assumed here
5935     area_hor = (nx+1) * (ny+1) * dx * dy
5936!
5937!--  absorbed/received SW & LW and emitted LW energy of all physical
5938!--  surfaces (land and urban) in local processor
5939     pinswl = 0._wp
5940     pinlwl = 0._wp
5941     pabsswl = 0._wp
5942     pabslwl = 0._wp
5943     pemitlwl = 0._wp
5944     emiss_sum_surfl = 0._wp
5945     area_surfl = 0._wp
5946     DO  i = 1, nsurfl
5947        d = surfl(id, i)
5948!--  received SW & LW
5949        pinswl = pinswl + (surfinswdir(i) + surfinswdif(i)) * facearea(d)
5950        pinlwl = pinlwl + surfinlwdif(i) * facearea(d)
5951!--   absorbed SW & LW
5952        pabsswl = pabsswl + (1._wp - albedo_surf(i)) *                   &
5953                                                surfinsw(i) * facearea(d)
5954        pabslwl = pabslwl + emiss_surf(i) * surfinlw(i) * facearea(d)
5955!--   emitted LW
5956        pemitlwl = pemitlwl + surfemitlwl(i) * facearea(d)
5957!--   emissivity and area sum
5958        emiss_sum_surfl = emiss_sum_surfl + emiss_surf(i) * facearea(d)
5959        area_surfl = area_surfl + facearea(d)
5960     END DO
5961!
5962!--  add the absorbed SW energy by plant canopy
5963     IF ( npcbl > 0 )  THEN
5964        pabsswl = pabsswl + SUM(pcbinsw)
5965        pabslwl = pabslwl + SUM(pcbinlw)
5966        pinswl = pinswl + SUM(pcbinswdir) + SUM(pcbinswdif)
5967     ENDIF
5968!
5969!--  gather all rad flux energy in all processors
5970#if defined( __parallel )
5971     CALL MPI_ALLREDUCE( pinswl, pinsw, 1, MPI_REAL, MPI_SUM, comm2d, ierr)
5972     IF ( ierr /= 0 ) THEN
5973         WRITE(9,*) 'Error MPI_AllReduce5:', ierr, pinswl, pinsw
5974         FLUSH(9)
5975     ENDIF
5976     CALL MPI_ALLREDUCE( pinlwl, pinlw, 1, MPI_REAL, MPI_SUM, comm2d, ierr)
5977     IF ( ierr /= 0 ) THEN
5978         WRITE(9,*) 'Error MPI_AllReduce6:', ierr, pinlwl, pinlw
5979         FLUSH(9)
5980     ENDIF
5981     CALL MPI_ALLREDUCE( pabsswl, pabssw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5982     IF ( ierr /= 0 ) THEN
5983         WRITE(9,*) 'Error MPI_AllReduce7:', ierr, pabsswl, pabssw
5984         FLUSH(9)
5985     ENDIF
5986     CALL MPI_ALLREDUCE( pabslwl, pabslw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5987     IF ( ierr /= 0 ) THEN
5988         WRITE(9,*) 'Error MPI_AllReduce8:', ierr, pabslwl, pabslw
5989         FLUSH(9)
5990     ENDIF
5991     CALL MPI_ALLREDUCE( pemitlwl, pemitlw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5992     IF ( ierr /= 0 ) THEN
5993         WRITE(9,*) 'Error MPI_AllReduce8:', ierr, pemitlwl, pemitlw
5994         FLUSH(9)
5995     ENDIF
5996     CALL MPI_ALLREDUCE( emiss_sum_surfl, emiss_sum_surf, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5997     IF ( ierr /= 0 ) THEN
5998         WRITE(9,*) 'Error MPI_AllReduce9:', ierr, emiss_sum_surfl, emiss_sum_surf
5999         FLUSH(9)
6000     ENDIF
6001     CALL MPI_ALLREDUCE( area_surfl, area_surf, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
6002     IF ( ierr /= 0 ) THEN
6003         WRITE(9,*) 'Error MPI_AllReduce10:', ierr, area_surfl, area_surf
6004         FLUSH(9)
6005     ENDIF
6006#else
6007     pinsw = pinswl
6008     pinlw = pinlwl
6009     pabssw = pabsswl
6010     pabslw = pabslwl
6011     pemitlw = pemitlwl
6012     emiss_sum_surf = emiss_sum_surfl
6013     area_surf = area_surfl
6014#endif
6015
6016!--  (1) albedo
6017     IF ( pinsw /= 0.0_wp )  &
6018          albedo_urb = (pinsw - pabssw) / pinsw
6019!--  (2) average emmsivity
6020     IF ( area_surf /= 0.0_wp ) &
6021          emissivity_urb = emiss_sum_surf / area_surf
6022!
6023!--  Temporally comment out calculation of effective radiative temperature.
6024!--  See below for more explanation.
6025!--  (3) temperature
6026!--   first we calculate an effective horizontal area to account for
6027!--   the effect of vertical surfaces (which contributes to LW emission)
6028!--   We simply use the ratio of the total LW to the incoming LW flux
6029      area_hor = pinlw/rad_lw_in_diff(nyn,nxl)
6030      t_rad_urb = ( (pemitlw - pabslw + emissivity_urb*pinlw) / &
6031           (emissivity_urb*sigma_sb * area_hor) )**0.25_wp
6032
6033     IF ( debug_output_timestep )  CALL debug_message( 'radiation_interaction', 'end' )
6034
6035
6036    CONTAINS
6037
6038!------------------------------------------------------------------------------!
6039!> Calculates radiation absorbed by box with given size and LAD.
6040!>
6041!> Simulates resol**2 rays (by equally spacing a bounding horizontal square
6042!> conatining all possible rays that would cross the box) and calculates
6043!> average transparency per ray. Returns fraction of absorbed radiation flux
6044!> and area for which this fraction is effective.
6045!------------------------------------------------------------------------------!
6046    PURE SUBROUTINE box_absorb(boxsize, resol, dens, uvec, area, absorb)
6047       IMPLICIT NONE
6048
6049       REAL(wp), DIMENSION(3), INTENT(in) :: &
6050            boxsize, &      !< z, y, x size of box in m
6051            uvec            !< z, y, x unit vector of incoming flux
6052       INTEGER(iwp), INTENT(in) :: &
6053            resol           !< No. of rays in x and y dimensions
6054       REAL(wp), INTENT(in) :: &
6055            dens            !< box density (e.g. Leaf Area Density)
6056       REAL(wp), INTENT(out) :: &
6057            area, &         !< horizontal area for flux absorbtion
6058            absorb          !< fraction of absorbed flux
6059       REAL(wp) :: &
6060            xshift, yshift, &
6061            xmin, xmax, ymin, ymax, &
6062            xorig, yorig, &
6063            dx1, dy1, dz1, dx2, dy2, dz2, &
6064            crdist, &
6065            transp
6066       INTEGER(iwp) :: &
6067            i, j
6068
6069       xshift = uvec(3) / uvec(1) * boxsize(1)
6070       xmin = min(0._wp, -xshift)
6071       xmax = boxsize(3) + max(0._wp, -xshift)
6072       yshift = uvec(2) / uvec(1) * boxsize(1)
6073       ymin = min(0._wp, -yshift)
6074       ymax = boxsize(2) + max(0._wp, -yshift)
6075
6076       transp = 0._wp
6077       DO i = 1, resol
6078          xorig = xmin + (xmax-xmin) * (i-.5_wp) / resol
6079          DO j = 1, resol
6080             yorig = ymin + (ymax-ymin) * (j-.5_wp) / resol
6081
6082             dz1 = 0._wp
6083             dz2 = boxsize(1)/uvec(1)
6084
6085             IF ( uvec(2) > 0._wp )  THEN
6086                dy1 = -yorig             / uvec(2) !< crossing with y=0
6087                dy2 = (boxsize(2)-yorig) / uvec(2) !< crossing with y=boxsize(2)
6088             ELSE !uvec(2)==0
6089                dy1 = -huge(1._wp)
6090                dy2 = huge(1._wp)
6091             ENDIF
6092
6093             IF ( uvec(3) > 0._wp )  THEN
6094                dx1 = -xorig             / uvec(3) !< crossing with x=0
6095                dx2 = (boxsize(3)-xorig) / uvec(3) !< crossing with x=boxsize(3)
6096             ELSE !uvec(3)==0
6097                dx1 = -huge(1._wp)
6098                dx2 = huge(1._wp)
6099             ENDIF
6100
6101             crdist = max(0._wp, (min(dz2, dy2, dx2) - max(dz1, dy1, dx1)))
6102             transp = transp + exp(-ext_coef * dens * crdist)
6103          ENDDO
6104       ENDDO
6105       transp = transp / resol**2
6106       area = (boxsize(3)+xshift)*(boxsize(2)+yshift)
6107       absorb = 1._wp - transp
6108
6109    END SUBROUTINE box_absorb
6110
6111!------------------------------------------------------------------------------!
6112! Description:
6113! ------------
6114!> This subroutine splits direct and diffusion dw radiation
6115!> It sould not be called in case the radiation model already does it
6116!> It follows Boland, Ridley & Brown (2008)
6117!------------------------------------------------------------------------------!
6118    SUBROUTINE calc_diffusion_radiation 
6119   
6120        REAL(wp), PARAMETER                          :: lowest_solarUp = 0.1_wp  !< limit the sun elevation to protect stability of the calculation
6121        INTEGER(iwp)                                 :: i, j
6122        REAL(wp)                                     ::  year_angle              !< angle
6123        REAL(wp)                                     ::  etr                     !< extraterestrial radiation
6124        REAL(wp)                                     ::  corrected_solarUp       !< corrected solar up radiation
6125        REAL(wp)                                     ::  horizontalETR           !< horizontal extraterestrial radiation
6126        REAL(wp)                                     ::  clearnessIndex          !< clearness index
6127        REAL(wp)                                     ::  diff_frac               !< diffusion fraction of the radiation
6128
6129       
6130!--     Calculate current day and time based on the initial values and simulation time
6131        year_angle = ( (day_of_year_init * 86400) + time_utc_init              &
6132                        + time_since_reference_point )  * d_seconds_year       &
6133                        * 2.0_wp * pi
6134       
6135        etr = solar_constant * (1.00011_wp +                                   &
6136                          0.034221_wp * cos(year_angle) +                      &
6137                          0.001280_wp * sin(year_angle) +                      &
6138                          0.000719_wp * cos(2.0_wp * year_angle) +             &
6139                          0.000077_wp * sin(2.0_wp * year_angle))
6140       
6141!--   
6142!--     Under a very low angle, we keep extraterestrial radiation at
6143!--     the last small value, therefore the clearness index will be pushed
6144!--     towards 0 while keeping full continuity.
6145!--   
6146        IF ( cos_zenith <= lowest_solarUp )  THEN
6147            corrected_solarUp = lowest_solarUp
6148        ELSE
6149            corrected_solarUp = cos_zenith
6150        ENDIF
6151       
6152        horizontalETR = etr * corrected_solarUp
6153       
6154        DO i = nxl, nxr
6155            DO j = nys, nyn
6156                clearnessIndex = rad_sw_in(0,j,i) / horizontalETR
6157                diff_frac = 1.0_wp / (1.0_wp + exp(-5.0033_wp + 8.6025_wp * clearnessIndex))
6158                rad_sw_in_diff(j,i) = rad_sw_in(0,j,i) * diff_frac
6159                rad_sw_in_dir(j,i)  = rad_sw_in(0,j,i) * (1.0_wp - diff_frac)
6160                rad_lw_in_diff(j,i) = rad_lw_in(0,j,i)
6161            ENDDO
6162        ENDDO
6163       
6164    END SUBROUTINE calc_diffusion_radiation
6165
6166 END SUBROUTINE radiation_interaction
6167   
6168!------------------------------------------------------------------------------!
6169! Description:
6170! ------------
6171!> This subroutine initializes structures needed for radiative transfer
6172!> model. This model calculates transformation processes of the
6173!> radiation inside urban and land canopy layer. The module includes also
6174!> the interaction of the radiation with the resolved plant canopy.
6175!>
6176!> For more info. see Resler et al. 2017
6177!>
6178!> The new version 2.0 was radically rewriten, the discretization scheme
6179!> has been changed. This new version significantly improves effectivity
6180!> of the paralelization and the scalability of the model.
6181!>
6182!------------------------------------------------------------------------------!
6183    SUBROUTINE radiation_interaction_init
6184
6185       USE control_parameters,                                                 &
6186           ONLY:  dz_stretch_level_start
6187
6188       USE plant_canopy_model_mod,                                             &
6189           ONLY:  lad_s
6190
6191       IMPLICIT NONE
6192
6193       INTEGER(iwp) :: i, j, k, l, m, d
6194       INTEGER(iwp) :: k_topo     !< vertical index indicating topography top for given (j,i)
6195       INTEGER(iwp) :: nzptl, nzubl, nzutl, isurf, ipcgb, imrt
6196       REAL(wp)     :: mrl
6197#if defined( __parallel )
6198       INTEGER(iwp), DIMENSION(:), POINTER, SAVE ::  gridsurf_rma   !< fortran pointer, but lower bounds are 1
6199       TYPE(c_ptr)                               ::  gridsurf_rma_p !< allocated c pointer
6200       INTEGER(iwp)                              ::  minfo          !< MPI RMA window info handle
6201#endif
6202
6203!
6204!--     precalculate face areas for different face directions using normal vector
6205        DO d = 0, nsurf_type
6206            facearea(d) = 1._wp
6207            IF ( idir(d) == 0 ) facearea(d) = facearea(d) * dx
6208            IF ( jdir(d) == 0 ) facearea(d) = facearea(d) * dy
6209            IF ( kdir(d) == 0 ) facearea(d) = facearea(d) * dz(1)
6210        ENDDO
6211!
6212!--    Find nz_urban_b, nz_urban_t, nz_urban via wall_flag_0 array (nzb_s_inner will be
6213!--    removed later). The following contruct finds the lowest / largest index
6214!--    for any upward-facing wall (see bit 12).
6215       nzubl = MINVAL( topo_top_ind(nys:nyn,nxl:nxr,0) )
6216       nzutl = MAXVAL( topo_top_ind(nys:nyn,nxl:nxr,0) )
6217
6218       nzubl = MAX( nzubl, nzb )
6219
6220       IF ( plant_canopy )  THEN
6221!--        allocate needed arrays
6222           ALLOCATE( pct(nys:nyn,nxl:nxr) )
6223           ALLOCATE( pch(nys:nyn,nxl:nxr) )
6224
6225!--        calculate plant canopy height
6226           npcbl = 0
6227           pct   = 0
6228           pch   = 0
6229           DO i = nxl, nxr
6230               DO j = nys, nyn
6231!
6232!--                Find topography top index
6233                   k_topo = topo_top_ind(j,i,0)
6234
6235                   DO k = nzt+1, 0, -1
6236                       IF ( lad_s(k,j,i) /= 0.0_wp )  THEN
6237!--                        we are at the top of the pcs
6238                           pct(j,i) = k + k_topo
6239                           pch(j,i) = k
6240                           npcbl = npcbl + pch(j,i)
6241                           EXIT
6242                       ENDIF
6243                   ENDDO
6244               ENDDO
6245           ENDDO
6246
6247           nzutl = MAX( nzutl, MAXVAL( pct ) )
6248           nzptl = MAXVAL( pct )
6249
6250           prototype_lad = MAXVAL( lad_s ) * .9_wp  !< better be *1.0 if lad is either 0 or maxval(lad) everywhere
6251           IF ( prototype_lad <= 0._wp ) prototype_lad = .3_wp
6252           !WRITE(message_string, '(a,f6.3)') 'Precomputing effective box optical ' &
6253           !    // 'depth using prototype leaf area density = ', prototype_lad
6254           !CALL message('radiation_interaction_init', 'PA0520', 0, 0, -1, 6, 0)
6255       ENDIF
6256
6257       nzutl = MIN( nzutl + nzut_free, nzt )
6258
6259#if defined( __parallel )
6260       CALL MPI_AllReduce(nzubl, nz_urban_b, 1, MPI_INTEGER, MPI_MIN, comm2d, ierr )
6261       IF ( ierr /= 0 ) THEN
6262           WRITE(9,*) 'Error MPI_AllReduce11:', ierr, nzubl, nz_urban_b
6263           FLUSH(9)
6264       ENDIF
6265       CALL MPI_AllReduce(nzutl, nz_urban_t, 1, MPI_INTEGER, MPI_MAX, comm2d, ierr )
6266       IF ( ierr /= 0 ) THEN
6267           WRITE(9,*) 'Error MPI_AllReduce12:', ierr, nzutl, nz_urban_t
6268           FLUSH(9)
6269       ENDIF
6270       CALL MPI_AllReduce(nzptl, nz_plant_t, 1, MPI_INTEGER, MPI_MAX, comm2d, ierr )
6271       IF ( ierr /= 0 ) THEN
6272           WRITE(9,*) 'Error MPI_AllReduce13:', ierr, nzptl, nz_plant_t
6273           FLUSH(9)
6274       ENDIF
6275#else
6276       nz_urban_b = nzubl
6277       nz_urban_t = nzutl
6278       nz_plant_t = nzptl
6279#endif
6280!
6281!--    Stretching (non-uniform grid spacing) is not considered in the radiation
6282!--    model. Therefore, vertical stretching has to be applied above the area
6283!--    where the parts of the radiation model which assume constant grid spacing
6284!--    are active. ABS (...) is required because the default value of
6285!--    dz_stretch_level_start is -9999999.9_wp (negative).
6286       IF ( ABS( dz_stretch_level_start(1) ) <= zw(nz_urban_t) ) THEN
6287          WRITE( message_string, * ) 'The lowest level where vertical ',       &
6288                                     'stretching is applied have to be ',      &
6289                                     'greater than ', zw(nz_urban_t)
6290          CALL message( 'radiation_interaction_init', 'PA0496', 1, 2, 0, 6, 0 )
6291       ENDIF 
6292!
6293!--    global number of urban and plant layers
6294       nz_urban = nz_urban_t - nz_urban_b + 1
6295       nz_plant = nz_plant_t - nz_urban_b + 1
6296!
6297!--    check max_raytracing_dist relative to urban surface layer height
6298       mrl = 2.0_wp * nz_urban * dz(1)
6299!--    set max_raytracing_dist to double the urban surface layer height, if not set
6300       IF ( max_raytracing_dist == -999.0_wp ) THEN
6301          max_raytracing_dist = mrl
6302       ENDIF
6303!--    check if max_raytracing_dist set too low (here we only warn the user. Other
6304!      option is to correct the value again to double the urban surface layer height)
6305       IF ( max_raytracing_dist  <  mrl ) THEN
6306          WRITE(message_string, '(a,f6.1)') 'Max_raytracing_dist is set less than ' // &
6307               'double the urban surface layer height, i.e. ', mrl
6308          CALL message('radiation_interaction_init', 'PA0521', 0, 0, 0, 6, 0 )
6309       ENDIF
6310!        IF ( max_raytracing_dist <= mrl ) THEN
6311!           IF ( max_raytracing_dist /= -999.0_wp ) THEN
6312! !--          max_raytracing_dist too low
6313!              WRITE(message_string, '(a,f6.1)') 'Max_raytracing_dist too low, ' &
6314!                    // 'override to value ', mrl
6315!              CALL message('radiation_interaction_init', 'PA0521', 0, 0, -1, 6, 0)
6316!           ENDIF
6317!           max_raytracing_dist = mrl
6318!        ENDIF
6319!
6320!--    allocate urban surfaces grid
6321!--    calc number of surfaces in local proc
6322       IF ( debug_output )  CALL debug_message( 'calculation of indices for surfaces', 'info' )
6323
6324       nsurfl = 0
6325!
6326!--    Number of horizontal surfaces including land- and roof surfaces in both USM and LSM. Note that
6327!--    All horizontal surface elements are already counted in surface_mod.
6328       startland = 1
6329       nsurfl    = surf_usm_h%ns + surf_lsm_h%ns
6330       endland   = nsurfl
6331       nlands    = endland - startland + 1
6332
6333!
6334!--    Number of vertical surfaces in both USM and LSM. Note that all vertical surface elements are
6335!--    already counted in surface_mod.
6336       startwall = nsurfl+1
6337       DO  i = 0,3
6338          nsurfl = nsurfl + surf_usm_v(i)%ns + surf_lsm_v(i)%ns
6339       ENDDO
6340       endwall = nsurfl
6341       nwalls  = endwall - startwall + 1
6342       dirstart = (/ startland, startwall, startwall, startwall, startwall /)
6343       dirend = (/ endland, endwall, endwall, endwall, endwall /)
6344
6345!--    fill gridpcbl and pcbl
6346       IF ( npcbl > 0 )  THEN
6347           ALLOCATE( pcbl(iz:ix, 1:npcbl) )
6348           ALLOCATE( gridpcbl(nz_urban_b:nz_plant_t,nys:nyn,nxl:nxr) )
6349           pcbl = -1
6350           gridpcbl(:,:,:) = 0
6351           ipcgb = 0
6352           DO i = nxl, nxr
6353               DO j = nys, nyn
6354!
6355!--                Find topography top index
6356                   k_topo = topo_top_ind(j,i,0)
6357
6358                   DO k = k_topo + 1, pct(j,i)
6359                       ipcgb = ipcgb + 1
6360                       gridpcbl(k,j,i) = ipcgb
6361                       pcbl(:,ipcgb) = (/ k, j, i /)
6362                   ENDDO
6363               ENDDO
6364           ENDDO
6365           ALLOCATE( pcbinsw( 1:npcbl ) )
6366           ALLOCATE( pcbinswdir( 1:npcbl ) )
6367           ALLOCATE( pcbinswdif( 1:npcbl ) )
6368           ALLOCATE( pcbinlw( 1:npcbl ) )
6369       ENDIF
6370
6371!
6372!--    Fill surfl (the ordering of local surfaces given by the following
6373!--    cycles must not be altered, certain file input routines may depend
6374!--    on it).
6375!
6376!--    We allocate the array as linear and then use a two-dimensional pointer
6377!--    into it, because some MPI implementations crash with 2D-allocated arrays.
6378       ALLOCATE(surfl_linear(nidx_surf*nsurfl))
6379       surfl(1:nidx_surf,1:nsurfl) => surfl_linear(1:nidx_surf*nsurfl)
6380       isurf = 0
6381       IF ( rad_angular_discretization )  THEN
6382!
6383!--       Allocate and fill the reverse indexing array gridsurf
6384#if defined( __parallel )
6385!
6386!--       raytrace_mpi_rma is asserted
6387
6388          CALL MPI_Info_create(minfo, ierr)
6389          IF ( ierr /= 0 ) THEN
6390              WRITE(9,*) 'Error MPI_Info_create1:', ierr
6391              FLUSH(9)
6392          ENDIF
6393          CALL MPI_Info_set(minfo, 'accumulate_ordering', 'none', ierr)
6394          IF ( ierr /= 0 ) THEN
6395              WRITE(9,*) 'Error MPI_Info_set1:', ierr
6396              FLUSH(9)
6397          ENDIF
6398          CALL MPI_Info_set(minfo, 'accumulate_ops', 'same_op', ierr)
6399          IF ( ierr /= 0 ) THEN
6400              WRITE(9,*) 'Error MPI_Info_set2:', ierr
6401              FLUSH(9)
6402          ENDIF
6403          CALL MPI_Info_set(minfo, 'same_size', 'true', ierr)
6404          IF ( ierr /= 0 ) THEN
6405              WRITE(9,*) 'Error MPI_Info_set3:', ierr
6406              FLUSH(9)
6407          ENDIF
6408          CALL MPI_Info_set(minfo, 'same_disp_unit', 'true', ierr)
6409          IF ( ierr /= 0 ) THEN
6410              WRITE(9,*) 'Error MPI_Info_set4:', ierr
6411              FLUSH(9)
6412          ENDIF
6413
6414          CALL MPI_Win_allocate(INT(STORAGE_SIZE(1_iwp)/8*nsurf_type_u*nz_urban*nny*nnx, &
6415                                    kind=MPI_ADDRESS_KIND), STORAGE_SIZE(1_iwp)/8,  &
6416                                minfo, comm2d, gridsurf_rma_p, win_gridsurf, ierr)
6417          IF ( ierr /= 0 ) THEN
6418              WRITE(9,*) 'Error MPI_Win_allocate1:', ierr, &
6419                 INT(STORAGE_SIZE(1_iwp)/8*nsurf_type_u*nz_urban*nny*nnx,kind=MPI_ADDRESS_KIND), &
6420                 STORAGE_SIZE(1_iwp)/8, win_gridsurf
6421              FLUSH(9)
6422          ENDIF
6423
6424          CALL MPI_Info_free(minfo, ierr)
6425          IF ( ierr /= 0 ) THEN
6426              WRITE(9,*) 'Error MPI_Info_free1:', ierr
6427              FLUSH(9)
6428          ENDIF
6429
6430!
6431!--       On Intel compilers, calling c_f_pointer to transform a C pointer
6432!--       directly to a multi-dimensional Fotran pointer leads to strange
6433!--       errors on dimension boundaries. However, transforming to a 1D
6434!--       pointer and then redirecting a multidimensional pointer to it works
6435!--       fine.
6436          CALL c_f_pointer(gridsurf_rma_p, gridsurf_rma, (/ nsurf_type_u*nz_urban*nny*nnx /))
6437          gridsurf(0:nsurf_type_u-1, nz_urban_b:nz_urban_t, nys:nyn, nxl:nxr) =>                &
6438                     gridsurf_rma(1:nsurf_type_u*nz_urban*nny*nnx)
6439#else
6440          ALLOCATE(gridsurf(0:nsurf_type_u-1,nz_urban_b:nz_urban_t,nys:nyn,nxl:nxr) )
6441#endif
6442          gridsurf(:,:,:,:) = -999
6443       ENDIF
6444
6445!--    add horizontal surface elements (land and urban surfaces)
6446!--    TODO: add urban overhanging surfaces (idown_u)
6447       DO i = nxl, nxr
6448           DO j = nys, nyn
6449              DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
6450                 k = surf_usm_h%k(m)
6451                 isurf = isurf + 1
6452                 surfl(:,isurf) = (/iup_u,k,j,i,m/)
6453                 IF ( rad_angular_discretization ) THEN
6454                    gridsurf(iup_u,k,j,i) = isurf
6455                 ENDIF
6456              ENDDO
6457
6458              DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6459                 k = surf_lsm_h%k(m)
6460                 isurf = isurf + 1
6461                 surfl(:,isurf) = (/iup_l,k,j,i,m/)
6462                 IF ( rad_angular_discretization ) THEN
6463                    gridsurf(iup_u,k,j,i) = isurf
6464                 ENDIF
6465              ENDDO
6466
6467           ENDDO
6468       ENDDO
6469
6470!--    add vertical surface elements (land and urban surfaces)
6471!--    TODO: remove the hard coding of l = 0 to l = idirection
6472       DO i = nxl, nxr
6473           DO j = nys, nyn
6474              l = 0
6475              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6476                 k = surf_usm_v(l)%k(m)
6477                 isurf = isurf + 1
6478                 surfl(:,isurf) = (/inorth_u,k,j,i,m/)
6479                 IF ( rad_angular_discretization ) THEN
6480                    gridsurf(inorth_u,k,j,i) = isurf
6481                 ENDIF
6482              ENDDO
6483              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6484                 k = surf_lsm_v(l)%k(m)
6485                 isurf = isurf + 1
6486                 surfl(:,isurf) = (/inorth_l,k,j,i,m/)
6487                 IF ( rad_angular_discretization ) THEN
6488                    gridsurf(inorth_u,k,j,i) = isurf
6489                 ENDIF
6490              ENDDO
6491
6492              l = 1
6493              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6494                 k = surf_usm_v(l)%k(m)
6495                 isurf = isurf + 1
6496                 surfl(:,isurf) = (/isouth_u,k,j,i,m/)
6497                 IF ( rad_angular_discretization ) THEN
6498                    gridsurf(isouth_u,k,j,i) = isurf
6499                 ENDIF
6500              ENDDO
6501              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6502                 k = surf_lsm_v(l)%k(m)
6503                 isurf = isurf + 1
6504                 surfl(:,isurf) = (/isouth_l,k,j,i,m/)
6505                 IF ( rad_angular_discretization ) THEN
6506                    gridsurf(isouth_u,k,j,i) = isurf
6507                 ENDIF
6508              ENDDO
6509
6510              l = 2
6511              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6512                 k = surf_usm_v(l)%k(m)
6513                 isurf = isurf + 1
6514                 surfl(:,isurf) = (/ieast_u,k,j,i,m/)
6515                 IF ( rad_angular_discretization ) THEN
6516                    gridsurf(ieast_u,k,j,i) = isurf
6517                 ENDIF
6518              ENDDO
6519              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6520                 k = surf_lsm_v(l)%k(m)
6521                 isurf = isurf + 1
6522                 surfl(:,isurf) = (/ieast_l,k,j,i,m/)
6523                 IF ( rad_angular_discretization ) THEN
6524                    gridsurf(ieast_u,k,j,i) = isurf
6525                 ENDIF
6526              ENDDO
6527
6528              l = 3
6529              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6530                 k = surf_usm_v(l)%k(m)
6531                 isurf = isurf + 1
6532                 surfl(:,isurf) = (/iwest_u,k,j,i,m/)
6533                 IF ( rad_angular_discretization ) THEN
6534                    gridsurf(iwest_u,k,j,i) = isurf
6535                 ENDIF
6536              ENDDO
6537              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6538                 k = surf_lsm_v(l)%k(m)
6539                 isurf = isurf + 1
6540                 surfl(:,isurf) = (/iwest_l,k,j,i,m/)
6541                 IF ( rad_angular_discretization ) THEN
6542                    gridsurf(iwest_u,k,j,i) = isurf
6543                 ENDIF
6544              ENDDO
6545           ENDDO
6546       ENDDO
6547!
6548!--    Add local MRT boxes for specified number of levels
6549       nmrtbl = 0
6550       IF ( mrt_nlevels > 0 )  THEN
6551          DO  i = nxl, nxr
6552             DO  j = nys, nyn
6553                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
6554!
6555!--                Skip roof if requested
6556                   IF ( mrt_skip_roof  .AND.  surf_usm_h%isroof_surf(m) )  CYCLE
6557!
6558!--                Cycle over specified no of levels
6559                   nmrtbl = nmrtbl + mrt_nlevels
6560                ENDDO
6561!
6562!--             Dtto for LSM
6563                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6564                   nmrtbl = nmrtbl + mrt_nlevels
6565                ENDDO
6566             ENDDO
6567          ENDDO
6568
6569          ALLOCATE( mrtbl(iz:ix,nmrtbl), mrtsky(nmrtbl), mrtskyt(nmrtbl), &
6570                    mrtinsw(nmrtbl), mrtinlw(nmrtbl), mrt(nmrtbl) )
6571
6572          imrt = 0
6573          DO  i = nxl, nxr
6574             DO  j = nys, nyn
6575                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
6576!
6577!--                Skip roof if requested
6578                   IF ( mrt_skip_roof  .AND.  surf_usm_h%isroof_surf(m) )  CYCLE
6579!
6580!--                Cycle over specified no of levels
6581                   l = surf_usm_h%k(m)
6582                   DO  k = l, l + mrt_nlevels - 1
6583                      imrt = imrt + 1
6584                      mrtbl(:,imrt) = (/k,j,i/)
6585                   ENDDO
6586                ENDDO
6587!
6588!--             Dtto for LSM
6589                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6590                   l = surf_lsm_h%k(m)
6591                   DO  k = l, l + mrt_nlevels - 1
6592                      imrt = imrt + 1
6593                      mrtbl(:,imrt) = (/k,j,i/)
6594                   ENDDO
6595                ENDDO
6596             ENDDO
6597          ENDDO
6598       ENDIF
6599
6600!
6601!--    broadband albedo of the land, roof and wall surface
6602!--    for domain border and sky set artifically to 1.0
6603!--    what allows us to calculate heat flux leaving over
6604!--    side and top borders of the domain
6605       ALLOCATE ( albedo_surf(nsurfl) )
6606       albedo_surf = 1.0_wp
6607!
6608!--    Also allocate further array for emissivity with identical order of
6609!--    surface elements as radiation arrays.
6610       ALLOCATE ( emiss_surf(nsurfl)  )
6611
6612
6613!
6614!--    global array surf of indices of surfaces and displacement index array surfstart
6615       ALLOCATE(nsurfs(0:numprocs-1))
6616
6617#if defined( __parallel )
6618       CALL MPI_Allgather(nsurfl,1,MPI_INTEGER,nsurfs,1,MPI_INTEGER,comm2d,ierr)
6619       IF ( ierr /= 0 ) THEN
6620         WRITE(9,*) 'Error MPI_AllGather1:', ierr, nsurfl, nsurfs
6621         FLUSH(9)
6622     ENDIF
6623
6624#else
6625       nsurfs(0) = nsurfl
6626#endif
6627       ALLOCATE(surfstart(0:numprocs))
6628       k = 0
6629       DO i=0,numprocs-1
6630           surfstart(i) = k
6631           k = k+nsurfs(i)
6632       ENDDO
6633       surfstart(numprocs) = k
6634       nsurf = k
6635!
6636!--    We allocate the array as linear and then use a two-dimensional pointer
6637!--    into it, because some MPI implementations crash with 2D-allocated arrays.
6638       ALLOCATE(surf_linear(nidx_surf*nsurf))
6639       surf(1:nidx_surf,1:nsurf) => surf_linear(1:nidx_surf*nsurf)
6640
6641#if defined( __parallel )
6642       CALL MPI_AllGatherv(surfl_linear, nsurfl*nidx_surf, MPI_INTEGER,    &
6643                           surf_linear, nsurfs*nidx_surf,                  &
6644                           surfstart(0:numprocs-1)*nidx_surf, MPI_INTEGER, &
6645                           comm2d, ierr)
6646       IF ( ierr /= 0 ) THEN
6647           WRITE(9,*) 'Error MPI_AllGatherv4:', ierr, SIZE(surfl_linear),    &
6648                      nsurfl*nidx_surf, SIZE(surf_linear), nsurfs*nidx_surf, &
6649                      surfstart(0:numprocs-1)*nidx_surf
6650           FLUSH(9)
6651       ENDIF
6652#else
6653       surf = surfl
6654#endif
6655
6656!--
6657!--    allocation of the arrays for direct and diffusion radiation
6658       IF ( debug_output )  CALL debug_message( 'allocation of radiation arrays', 'info' )
6659!--    rad_sw_in, rad_lw_in are computed in radiation model,
6660!--    splitting of direct and diffusion part is done
6661!--    in calc_diffusion_radiation for now
6662
6663       ALLOCATE( rad_sw_in_dir(nysg:nyng,nxlg:nxrg) )
6664       ALLOCATE( rad_sw_in_diff(nysg:nyng,nxlg:nxrg) )
6665       ALLOCATE( rad_lw_in_diff(nysg:nyng,nxlg:nxrg) )
6666       rad_sw_in_dir  = 0.0_wp
6667       rad_sw_in_diff = 0.0_wp
6668       rad_lw_in_diff = 0.0_wp
6669
6670!--    allocate radiation arrays
6671       ALLOCATE( surfins(nsurfl) )
6672       ALLOCATE( surfinl(nsurfl) )
6673       ALLOCATE( surfinsw(nsurfl) )
6674       ALLOCATE( surfinlw(nsurfl) )
6675       ALLOCATE( surfinswdir(nsurfl) )
6676       ALLOCATE( surfinswdif(nsurfl) )
6677       ALLOCATE( surfinlwdif(nsurfl) )
6678       ALLOCATE( surfoutsl(nsurfl) )
6679       ALLOCATE( surfoutll(nsurfl) )
6680       ALLOCATE( surfoutsw(nsurfl) )
6681       ALLOCATE( surfoutlw(nsurfl) )
6682       ALLOCATE( surfouts(nsurf) )
6683       ALLOCATE( surfoutl(nsurf) )
6684       ALLOCATE( surfinlg(nsurf) )
6685       ALLOCATE( skyvf(nsurfl) )
6686       ALLOCATE( skyvft(nsurfl) )
6687       ALLOCATE( surfemitlwl(nsurfl) )
6688
6689!
6690!--    In case of average_radiation, aggregated surface albedo and emissivity,
6691!--    also set initial value for t_rad_urb.
6692!--    For now set an arbitrary initial value.
6693       IF ( average_radiation )  THEN
6694          albedo_urb = 0.1_wp
6695          emissivity_urb = 0.9_wp
6696          t_rad_urb = pt_surface
6697       ENDIF
6698
6699    END SUBROUTINE radiation_interaction_init
6700
6701!------------------------------------------------------------------------------!
6702! Description:
6703! ------------
6704!> Calculates shape view factors (SVF), plant sink canopy factors (PCSF),
6705!> sky-view factors, discretized path for direct solar radiation, MRT factors
6706!> and other preprocessed data needed for radiation_interaction.
6707!------------------------------------------------------------------------------!
6708    SUBROUTINE radiation_calc_svf
6709   
6710        IMPLICIT NONE
6711       
6712        INTEGER(iwp)                                  :: i, j, k, d, ip, jp
6713        INTEGER(iwp)                                  :: isvf, ksvf, icsf, kcsf, npcsfl, isvf_surflt, imrt, imrtf, ipcgb
6714        INTEGER(iwp)                                  :: sd, td
6715        INTEGER(iwp)                                  :: iaz, izn      !< azimuth, zenith counters
6716        INTEGER(iwp)                                  :: naz, nzn      !< azimuth, zenith num of steps
6717        REAL(wp)                                      :: az0, zn0      !< starting azimuth/zenith
6718        REAL(wp)                                      :: azs, zns      !< azimuth/zenith cycle step
6719        REAL(wp)                                      :: az1, az2      !< relative azimuth of section borders
6720        REAL(wp)                                      :: azmid         !< ray (center) azimuth
6721        REAL(wp)                                      :: yxlen         !< |yxdir|
6722        REAL(wp), DIMENSION(2)                        :: yxdir         !< y,x *unit* vector of ray direction (in grid units)
6723        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zdirs         !< directions in z (tangent of elevation)
6724        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zcent         !< zenith angle centers
6725        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zbdry         !< zenith angle boundaries
6726        REAL(wp), DIMENSION(:), ALLOCATABLE           :: vffrac        !< view factor fractions for individual rays
6727        REAL(wp), DIMENSION(:), ALLOCATABLE           :: vffrac0       !< dtto (original values)
6728        REAL(wp), DIMENSION(:), ALLOCATABLE           :: ztransp       !< array of transparency in z steps
6729        INTEGER(iwp)                                  :: lowest_free_ray !< index into zdirs
6730        INTEGER(iwp), DIMENSION(:), ALLOCATABLE       :: itarget       !< face indices of detected obstacles
6731        INTEGER(iwp)                                  :: itarg0, itarg1
6732
6733        INTEGER(iwp)                                  :: udim
6734        INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET:: nzterrl_l
6735        INTEGER(iwp), DIMENSION(:,:), POINTER         :: nzterrl
6736        REAL(wp),     DIMENSION(:), ALLOCATABLE,TARGET:: csflt_l, pcsflt_l
6737        REAL(wp),     DIMENSION(:,:), POINTER         :: csflt, pcsflt
6738        INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET:: kcsflt_l,kpcsflt_l
6739        INTEGER(iwp), DIMENSION(:,:), POINTER         :: kcsflt,kpcsflt
6740        INTEGER(iwp), DIMENSION(:), ALLOCATABLE       :: icsflt,dcsflt,ipcsflt,dpcsflt
6741        REAL(wp), DIMENSION(3)                        :: uv
6742        LOGICAL                                       :: visible
6743        REAL(wp), DIMENSION(3)                        :: sa, ta          !< real coordinates z,y,x of source and target
6744        REAL(wp)                                      :: difvf           !< differential view factor
6745        REAL(wp)                                      :: transparency, rirrf, sqdist, svfsum
6746        INTEGER(iwp)                                  :: isurflt, isurfs, isurflt_prev
6747        INTEGER(idp)                                  :: ray_skip_maxdist, ray_skip_minval !< skipped raytracing counts
6748        INTEGER(iwp)                                  :: max_track_len !< maximum 2d track length
6749        INTEGER(iwp)                                  :: minfo
6750        REAL(wp), DIMENSION(:), POINTER, SAVE         :: lad_s_rma       !< fortran 1D pointer
6751        TYPE(c_ptr)                                   :: lad_s_rma_p     !< allocated c pointer
6752#if defined( __parallel )
6753        INTEGER(kind=MPI_ADDRESS_KIND)                :: size_lad_rma
6754#endif
6755!   
6756        INTEGER(iwp), DIMENSION(0:svfnorm_report_num) :: svfnorm_counts
6757
6758
6759!--     calculation of the SVF
6760        CALL location_message( 'calculating view factors for radiation interaction', 'start' )
6761
6762!--     initialize variables and temporary arrays for calculation of svf and csf
6763        nsvfl  = 0
6764        ncsfl  = 0
6765        nsvfla = gasize
6766        msvf   = 1
6767        ALLOCATE( asvf1(nsvfla) )
6768        asvf => asvf1
6769        IF ( plant_canopy )  THEN
6770            ncsfla = gasize
6771            mcsf   = 1
6772            ALLOCATE( acsf1(ncsfla) )
6773            acsf => acsf1
6774        ENDIF
6775        nmrtf = 0
6776        IF ( mrt_nlevels > 0 )  THEN
6777           nmrtfa = gasize
6778           mmrtf = 1
6779           ALLOCATE ( amrtf1(nmrtfa) )
6780           amrtf => amrtf1
6781        ENDIF
6782        ray_skip_maxdist = 0
6783        ray_skip_minval = 0
6784       
6785!--     initialize temporary terrain and plant canopy height arrays (global 2D array!)
6786        ALLOCATE( nzterr(0:(nx+1)*(ny+1)-1) )
6787#if defined( __parallel )
6788        !ALLOCATE( nzterrl(nys:nyn,nxl:nxr) )
6789        ALLOCATE( nzterrl_l((nyn-nys+1)*(nxr-nxl+1)) )
6790        nzterrl(nys:nyn,nxl:nxr) => nzterrl_l(1:(nyn-nys+1)*(nxr-nxl+1))
6791        nzterrl = topo_top_ind(nys:nyn,nxl:nxr,0)
6792        CALL MPI_AllGather( nzterrl_l, nnx*nny, MPI_INTEGER, &
6793                            nzterr, nnx*nny, MPI_INTEGER, comm2d, ierr )
6794        IF ( ierr /= 0 ) THEN
6795            WRITE(9,*) 'Error MPI_AllGather1:', ierr, SIZE(nzterrl_l), nnx*nny, &
6796                       SIZE(nzterr), nnx*nny
6797            FLUSH(9)
6798        ENDIF
6799        DEALLOCATE(nzterrl_l)
6800#else
6801        nzterr = RESHAPE( topo_top_ind(nys:nyn,nxl:nxr,0), (/(nx+1)*(ny+1)/) )
6802#endif
6803        IF ( plant_canopy )  THEN
6804            ALLOCATE( plantt(0:(nx+1)*(ny+1)-1) )
6805            maxboxesg = nx + ny + nz_plant + 1
6806            max_track_len = nx + ny + 1
6807!--         temporary arrays storing values for csf calculation during raytracing
6808            ALLOCATE( boxes(3, maxboxesg) )
6809            ALLOCATE( crlens(maxboxesg) )
6810
6811#if defined( __parallel )
6812            CALL MPI_AllGather( pct, nnx*nny, MPI_INTEGER, &
6813                                plantt, nnx*nny, MPI_INTEGER, comm2d, ierr )
6814            IF ( ierr /= 0 ) THEN
6815                WRITE(9,*) 'Error MPI_AllGather2:', ierr, SIZE(pct), nnx*nny, &
6816                           SIZE(plantt), nnx*nny
6817                FLUSH(9)
6818            ENDIF
6819
6820!--         temporary arrays storing values for csf calculation during raytracing
6821            ALLOCATE( lad_ip(maxboxesg) )
6822            ALLOCATE( lad_disp(maxboxesg) )
6823
6824            IF ( raytrace_mpi_rma )  THEN
6825                ALLOCATE( lad_s_ray(maxboxesg) )
6826               
6827                ! set conditions for RMA communication
6828                CALL MPI_Info_create(minfo, ierr)
6829                IF ( ierr /= 0 ) THEN
6830                    WRITE(9,*) 'Error MPI_Info_create2:', ierr
6831                    FLUSH(9)
6832                ENDIF
6833                CALL MPI_Info_set(minfo, 'accumulate_ordering', 'none', ierr)
6834                IF ( ierr /= 0 ) THEN
6835                    WRITE(9,*) 'Error MPI_Info_set5:', ierr
6836                    FLUSH(9)
6837                ENDIF
6838                CALL MPI_Info_set(minfo, 'accumulate_ops', 'same_op', ierr)
6839                IF ( ierr /= 0 ) THEN
6840                    WRITE(9,*) 'Error MPI_Info_set6:', ierr
6841                    FLUSH(9)
6842                ENDIF
6843                CALL MPI_Info_set(minfo, 'same_size', 'true', ierr)
6844                IF ( ierr /= 0 ) THEN
6845                    WRITE(9,*) 'Error MPI_Info_set7:', ierr
6846                    FLUSH(9)
6847                ENDIF
6848                CALL MPI_Info_set(minfo, 'same_disp_unit', 'true', ierr)
6849                IF ( ierr /= 0 ) THEN
6850                    WRITE(9,*) 'Error MPI_Info_set8:', ierr
6851                    FLUSH(9)
6852                ENDIF
6853
6854!--             Allocate and initialize the MPI RMA window
6855!--             must be in accordance with allocation of lad_s in plant_canopy_model
6856!--             optimization of memory should be done
6857!--             Argument X of function STORAGE_SIZE(X) needs arbitrary REAL(wp) value, set to 1.0_wp for now
6858                size_lad_rma = STORAGE_SIZE(1.0_wp)/8*nnx*nny*nz_plant
6859                CALL MPI_Win_allocate(size_lad_rma, STORAGE_SIZE(1.0_wp)/8, minfo, comm2d, &
6860                                        lad_s_rma_p, win_lad, ierr)
6861                IF ( ierr /= 0 ) THEN
6862                    WRITE(9,*) 'Error MPI_Win_allocate2:', ierr, size_lad_rma, &
6863                                STORAGE_SIZE(1.0_wp)/8, win_lad
6864                    FLUSH(9)
6865                ENDIF
6866                CALL c_f_pointer(lad_s_rma_p, lad_s_rma, (/ nz_plant*nny*nnx /))
6867                sub_lad(nz_urban_b:nz_plant_t, nys:nyn, nxl:nxr) => lad_s_rma(1:nz_plant*nny*nnx)
6868            ELSE
6869                ALLOCATE(sub_lad(nz_urban_b:nz_plant_t, nys:nyn, nxl:nxr))
6870            ENDIF
6871#else
6872            plantt = RESHAPE( pct(nys:nyn,nxl:nxr), (/(nx+1)*(ny+1)/) )
6873            ALLOCATE(sub_lad(nz_urban_b:nz_plant_t, nys:nyn, nxl:nxr))
6874#endif
6875            plantt_max = MAXVAL(plantt)
6876            ALLOCATE( rt2_track(2, max_track_len), rt2_track_lad(nz_urban_b:plantt_max, max_track_len), &
6877                      rt2_track_dist(0:max_track_len), rt2_dist(plantt_max-nz_urban_b+2) )
6878
6879            sub_lad(:,:,:) = 0._wp
6880            DO i = nxl, nxr
6881                DO j = nys, nyn
6882                    k = topo_top_ind(j,i,0)
6883
6884                    sub_lad(k:nz_plant_t, j, i) = lad_s(0:nz_plant_t-k, j, i)
6885                ENDDO
6886            ENDDO
6887
6888#if defined( __parallel )
6889            IF ( raytrace_mpi_rma )  THEN
6890                CALL MPI_Info_free(minfo, ierr)
6891                IF ( ierr /= 0 ) THEN
6892                    WRITE(9,*) 'Error MPI_Info_free2:', ierr
6893                    FLUSH(9)
6894                ENDIF
6895                CALL MPI_Win_lock_all(0, win_lad, ierr)
6896                IF ( ierr /= 0 ) THEN
6897                    WRITE(9,*) 'Error MPI_Win_lock_all1:', ierr, win_lad
6898                    FLUSH(9)
6899                ENDIF
6900               
6901            ELSE
6902                ALLOCATE( sub_lad_g(0:(nx+1)*(ny+1)*nz_plant-1) )
6903                CALL MPI_AllGather( sub_lad, nnx*nny*nz_plant, MPI_REAL, &
6904                                    sub_lad_g, nnx*nny*nz_plant, MPI_REAL, comm2d, ierr )
6905                IF ( ierr /= 0 ) THEN
6906                    WRITE(9,*) 'Error MPI_AllGather3:', ierr, SIZE(sub_lad), &
6907                                nnx*nny*nz_plant, SIZE(sub_lad_g), nnx*nny*nz_plant
6908                    FLUSH(9)
6909                ENDIF
6910            ENDIF
6911#endif
6912        ENDIF
6913
6914!--     prepare the MPI_Win for collecting the surface indices
6915!--     from the reverse index arrays gridsurf from processors of target surfaces
6916#if defined( __parallel )
6917        IF ( rad_angular_discretization )  THEN
6918!
6919!--         raytrace_mpi_rma is asserted
6920            CALL MPI_Win_lock_all(0, win_gridsurf, ierr)
6921            IF ( ierr /= 0 ) THEN
6922                WRITE(9,*) 'Error MPI_Win_lock_all2:', ierr, win_gridsurf
6923                FLUSH(9)
6924            ENDIF
6925        ENDIF
6926#endif
6927
6928
6929        !--Directions opposite to face normals are not even calculated,
6930        !--they must be preset to 0
6931        !--
6932        dsitrans(:,:) = 0._wp
6933       
6934        DO isurflt = 1, nsurfl
6935!--         determine face centers
6936            td = surfl(id, isurflt)
6937            ta = (/ REAL(surfl(iz, isurflt), wp) - 0.5_wp * kdir(td),  &
6938                      REAL(surfl(iy, isurflt), wp) - 0.5_wp * jdir(td),  &
6939                      REAL(surfl(ix, isurflt), wp) - 0.5_wp * idir(td)  /)
6940
6941            !--Calculate sky view factor and raytrace DSI paths
6942            skyvf(isurflt) = 0._wp
6943            skyvft(isurflt) = 0._wp
6944
6945            !--Select a proper half-sphere for 2D raytracing
6946            SELECT CASE ( td )
6947               CASE ( iup_u, iup_l )
6948                  az0 = 0._wp
6949                  naz = raytrace_discrete_azims
6950                  azs = 2._wp * pi / REAL(naz, wp)
6951                  zn0 = 0._wp
6952                  nzn = raytrace_discrete_elevs / 2
6953                  zns = pi / 2._wp / REAL(nzn, wp)
6954               CASE ( isouth_u, isouth_l )
6955                  az0 = pi / 2._wp
6956                  naz = raytrace_discrete_azims / 2
6957                  azs = pi / REAL(naz, wp)
6958                  zn0 = 0._wp
6959                  nzn = raytrace_discrete_elevs
6960                  zns = pi / REAL(nzn, wp)
6961               CASE ( inorth_u, inorth_l )
6962                  az0 = - pi / 2._wp
6963                  naz = raytrace_discrete_azims / 2
6964                  azs = pi / REAL(naz, wp)
6965                  zn0 = 0._wp
6966                  nzn = raytrace_discrete_elevs
6967                  zns = pi / REAL(nzn, wp)
6968               CASE ( iwest_u, iwest_l )
6969                  az0 = pi
6970                  naz = raytrace_discrete_azims / 2
6971                  azs = pi / REAL(naz, wp)
6972                  zn0 = 0._wp
6973                  nzn = raytrace_discrete_elevs
6974                  zns = pi / REAL(nzn, wp)
6975               CASE ( ieast_u, ieast_l )
6976                  az0 = 0._wp
6977                  naz = raytrace_discrete_azims / 2
6978                  azs = pi / REAL(naz, wp)
6979                  zn0 = 0._wp
6980                  nzn = raytrace_discrete_elevs
6981                  zns = pi / REAL(nzn, wp)
6982               CASE DEFAULT
6983                  WRITE(message_string, *) 'ERROR: the surface type ', td,     &
6984                                           ' is not supported for calculating',&
6985                                           ' SVF'
6986                  CALL message( 'radiation_calc_svf', 'PA0488', 1, 2, 0, 6, 0 )
6987            END SELECT
6988
6989            ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), zbdry(0:nzn), vffrac(1:nzn*naz), &
6990                       ztransp(1:nzn*naz), itarget(1:nzn*naz) )   !FIXME allocate itarget only
6991                                                                  !in case of rad_angular_discretization
6992
6993            itarg0 = 1
6994            itarg1 = nzn
6995            zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
6996            zbdry(:) = (/( zn0+REAL(izn,wp)*zns, izn=0, nzn )/)
6997            IF ( td == iup_u  .OR.  td == iup_l )  THEN
6998               vffrac(1:nzn) = (COS(2 * zbdry(0:nzn-1)) - COS(2 * zbdry(1:nzn))) / 2._wp / REAL(naz, wp)
6999!
7000!--            For horizontal target, vf fractions are constant per azimuth
7001               DO iaz = 1, naz-1
7002                  vffrac(iaz*nzn+1:(iaz+1)*nzn) = vffrac(1:nzn)
7003               ENDDO
7004!--            sum of whole vffrac equals 1, verified
7005            ENDIF
7006!
7007!--         Calculate sky-view factor and direct solar visibility using 2D raytracing
7008            DO iaz = 1, naz
7009               azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
7010               IF ( td /= iup_u  .AND.  td /= iup_l )  THEN
7011                  az2 = REAL(iaz, wp) * azs - pi/2._wp
7012                  az1 = az2 - azs
7013                  !TODO precalculate after 1st line
7014                  vffrac(itarg0:itarg1) = (SIN(az2) - SIN(az1))               &
7015                              * (zbdry(1:nzn) - zbdry(0:nzn-1)                &
7016                                 + SIN(zbdry(0:nzn-1))*COS(zbdry(0:nzn-1))    &
7017                                 - SIN(zbdry(1:nzn))*COS(zbdry(1:nzn)))       &
7018                              / (2._wp * pi)
7019!--               sum of whole vffrac equals 1, verified
7020               ENDIF
7021               yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
7022               yxlen = SQRT(SUM(yxdir(:)**2))
7023               zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
7024               yxdir(:) = yxdir(:) / yxlen
7025
7026               CALL raytrace_2d(ta, yxdir, nzn, zdirs,                        &
7027                                    surfstart(myid) + isurflt, facearea(td),  &
7028                                    vffrac(itarg0:itarg1), .TRUE., .TRUE.,    &
7029                                    .FALSE., lowest_free_ray,                 &
7030                                    ztransp(itarg0:itarg1),                   &
7031                                    itarget(itarg0:itarg1))
7032
7033               skyvf(isurflt) = skyvf(isurflt) + &
7034                                SUM(vffrac(itarg0:itarg0+lowest_free_ray-1))
7035               skyvft(isurflt) = skyvft(isurflt) + &
7036                                 SUM(ztransp(itarg0:itarg0+lowest_free_ray-1) &
7037                                             * vffrac(itarg0:itarg0+lowest_free_ray-1))
7038 
7039!--            Save direct solar transparency
7040               j = MODULO(NINT(azmid/                                          &
7041                               (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
7042                          raytrace_discrete_azims)
7043
7044               DO k = 1, raytrace_discrete_elevs/2
7045                  i = dsidir_rev(k-1, j)
7046                  IF ( i /= -1  .AND.  k <= lowest_free_ray )  &
7047                     dsitrans(isurflt, i) = ztransp(itarg0+k-1)
7048               ENDDO
7049
7050!
7051!--            Advance itarget indices
7052               itarg0 = itarg1 + 1
7053               itarg1 = itarg1 + nzn
7054            ENDDO
7055
7056            IF ( rad_angular_discretization )  THEN
7057!--            sort itarget by face id
7058               CALL quicksort_itarget(itarget,vffrac,ztransp,1,nzn*naz)
7059!
7060!--            For aggregation, we need fractions multiplied by transmissivities
7061               ztransp(:) = vffrac(:) * ztransp(:)
7062!
7063!--            find the first valid position
7064               itarg0 = 1
7065               DO WHILE ( itarg0 <= nzn*naz )
7066                  IF ( itarget(itarg0) /= -1 )  EXIT
7067                  itarg0 = itarg0 + 1
7068               ENDDO
7069
7070               DO  i = itarg0, nzn*naz
7071!
7072!--               For duplicate values, only sum up vf fraction value
7073                  IF ( i < nzn*naz )  THEN
7074                     IF ( itarget(i+1) == itarget(i) )  THEN
7075                        vffrac(i+1) = vffrac(i+1) + vffrac(i)
7076                        ztransp(i+1) = ztransp(i+1) + ztransp(i)
7077                        CYCLE
7078                     ENDIF
7079                  ENDIF
7080!
7081!--               write to the svf array
7082                  nsvfl = nsvfl + 1
7083!--               check dimmension of asvf array and enlarge it if needed
7084                  IF ( nsvfla < nsvfl )  THEN
7085                     k = CEILING(REAL(nsvfla, kind=wp) * grow_factor)
7086                     IF ( msvf == 0 )  THEN
7087                        msvf = 1
7088                        ALLOCATE( asvf1(k) )
7089                        asvf => asvf1
7090                        asvf1(1:nsvfla) = asvf2
7091                        DEALLOCATE( asvf2 )
7092                     ELSE
7093                        msvf = 0
7094                        ALLOCATE( asvf2(k) )
7095                        asvf => asvf2
7096                        asvf2(1:nsvfla) = asvf1
7097                        DEALLOCATE( asvf1 )
7098                     ENDIF
7099
7100                     IF ( debug_output )  THEN
7101                        WRITE( debug_string, '(A,3I12)' ) 'Grow asvf:', nsvfl, nsvfla, k
7102                        CALL debug_message( debug_string, 'info' )
7103                     ENDIF
7104                     
7105                     nsvfla = k
7106                  ENDIF
7107!--               write svf values into the array
7108                  asvf(nsvfl)%isurflt = isurflt
7109                  asvf(nsvfl)%isurfs = itarget(i)
7110                  asvf(nsvfl)%rsvf = vffrac(i)
7111                  asvf(nsvfl)%rtransp = ztransp(i) / vffrac(i)
7112               END DO
7113
7114            ENDIF ! rad_angular_discretization
7115
7116            DEALLOCATE ( zdirs, zcent, zbdry, vffrac, ztransp, itarget ) !FIXME itarget shall be allocated only
7117                                                                  !in case of rad_angular_discretization
7118!
7119!--         Following calculations only required for surface_reflections
7120            IF ( surface_reflections  .AND.  .NOT. rad_angular_discretization )  THEN
7121
7122               DO  isurfs = 1, nsurf
7123                  IF ( .NOT.  surface_facing(surfl(ix, isurflt), surfl(iy, isurflt), &
7124                     surfl(iz, isurflt), surfl(id, isurflt), &
7125                     surf(ix, isurfs), surf(iy, isurfs), &
7126                     surf(iz, isurfs), surf(id, isurfs)) )  THEN
7127                     CYCLE
7128                  ENDIF
7129                 
7130                  sd = surf(id, isurfs)
7131                  sa = (/ REAL(surf(iz, isurfs), wp) - 0.5_wp * kdir(sd),  &
7132                          REAL(surf(iy, isurfs), wp) - 0.5_wp * jdir(sd),  &
7133                          REAL(surf(ix, isurfs), wp) - 0.5_wp * idir(sd)  /)
7134
7135!--               unit vector source -> target
7136                  uv = (/ (ta(1)-sa(1))*dz(1), (ta(2)-sa(2))*dy, (ta(3)-sa(3))*dx /)
7137                  sqdist = SUM(uv(:)**2)
7138                  uv = uv / SQRT(sqdist)
7139
7140!--               reject raytracing above max distance
7141                  IF ( SQRT(sqdist) > max_raytracing_dist ) THEN
7142                     ray_skip_maxdist = ray_skip_maxdist + 1
7143                     CYCLE
7144                  ENDIF
7145                 
7146                  difvf = dot_product((/ kdir(sd), jdir(sd), idir(sd) /), uv) & ! cosine of source normal and direction
7147                      * dot_product((/ kdir(td), jdir(td), idir(td) /), -uv) &  ! cosine of target normal and reverse direction
7148                      / (pi * sqdist) ! square of distance between centers
7149!
7150!--               irradiance factor (our unshaded shape view factor) = view factor per differential target area * source area
7151                  rirrf = difvf * facearea(sd)
7152
7153!--               reject raytracing for potentially too small view factor values
7154                  IF ( rirrf < min_irrf_value ) THEN
7155                      ray_skip_minval = ray_skip_minval + 1
7156                      CYCLE
7157                  ENDIF
7158
7159!--               raytrace + process plant canopy sinks within
7160                  CALL raytrace(sa, ta, isurfs, difvf, facearea(td), .TRUE., &
7161                                visible, transparency)
7162
7163                  IF ( .NOT.  visible ) CYCLE
7164                 ! rsvf = rirrf * transparency
7165
7166!--               write to the svf array
7167                  nsvfl = nsvfl + 1
7168!--               check dimmension of asvf array and enlarge it if needed
7169                  IF ( nsvfla < nsvfl )  THEN
7170                     k = CEILING(REAL(nsvfla, kind=wp) * grow_factor)
7171                     IF ( msvf == 0 )  THEN
7172                        msvf = 1
7173                        ALLOCATE( asvf1(k) )
7174                        asvf => asvf1
7175                        asvf1(1:nsvfla) = asvf2
7176                        DEALLOCATE( asvf2 )
7177                     ELSE
7178                        msvf = 0
7179                        ALLOCATE( asvf2(k) )
7180                        asvf => asvf2
7181                        asvf2(1:nsvfla) = asvf1
7182                        DEALLOCATE( asvf1 )
7183                     ENDIF
7184
7185                     IF ( debug_output )  THEN
7186                        WRITE( debug_string, '(A,3I12)' ) 'Grow asvf:', nsvfl, nsvfla, k
7187                        CALL debug_message( debug_string, 'info' )
7188                     ENDIF
7189                     
7190                     nsvfla = k
7191                  ENDIF
7192!--               write svf values into the array
7193                  asvf(nsvfl)%isurflt = isurflt
7194                  asvf(nsvfl)%isurfs = isurfs
7195                  asvf(nsvfl)%rsvf = rirrf !we postopne multiplication by transparency
7196                  asvf(nsvfl)%rtransp = transparency !a.k.a. Direct Irradiance Factor
7197               ENDDO
7198            ENDIF
7199        ENDDO
7200
7201!--
7202!--     Raytrace to canopy boxes to fill dsitransc TODO optimize
7203        dsitransc(:,:) = 0._wp
7204        az0 = 0._wp
7205        naz = raytrace_discrete_azims
7206        azs = 2._wp * pi / REAL(naz, wp)
7207        zn0 = 0._wp
7208        nzn = raytrace_discrete_elevs / 2
7209        zns = pi / 2._wp / REAL(nzn, wp)
7210        ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), vffrac(1:nzn), ztransp(1:nzn), &
7211               itarget(1:nzn) )
7212        zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
7213        vffrac(:) = 0._wp
7214
7215        DO  ipcgb = 1, npcbl
7216           ta = (/ REAL(pcbl(iz, ipcgb), wp),  &
7217                   REAL(pcbl(iy, ipcgb), wp),  &
7218                   REAL(pcbl(ix, ipcgb), wp) /)
7219!--        Calculate direct solar visibility using 2D raytracing
7220           DO  iaz = 1, naz
7221              azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
7222              yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
7223              yxlen = SQRT(SUM(yxdir(:)**2))
7224              zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
7225              yxdir(:) = yxdir(:) / yxlen
7226              CALL raytrace_2d(ta, yxdir, nzn, zdirs,                                &
7227                                   -999, -999._wp, vffrac, .FALSE., .FALSE., .TRUE., &
7228                                   lowest_free_ray, ztransp, itarget)
7229
7230!--           Save direct solar transparency
7231              j = MODULO(NINT(azmid/                                         &
7232                             (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
7233                         raytrace_discrete_azims)
7234              DO  k = 1, raytrace_discrete_elevs/2
7235                 i = dsidir_rev(k-1, j)
7236                 IF ( i /= -1  .AND.  k <= lowest_free_ray ) &
7237                    dsitransc(ipcgb, i) = ztransp(k)
7238              ENDDO
7239           ENDDO
7240        ENDDO
7241        DEALLOCATE ( zdirs, zcent, vffrac, ztransp, itarget )
7242!--
7243!--     Raytrace to MRT boxes
7244        IF ( nmrtbl > 0 )  THEN
7245           mrtdsit(:,:) = 0._wp
7246           mrtsky(:) = 0._wp
7247           mrtskyt(:) = 0._wp
7248           az0 = 0._wp
7249           naz = raytrace_discrete_azims
7250           azs = 2._wp * pi / REAL(naz, wp)
7251           zn0 = 0._wp
7252           nzn = raytrace_discrete_elevs
7253           zns = pi / REAL(nzn, wp)
7254           ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), zbdry(0:nzn), vffrac(1:nzn*naz), vffrac0(1:nzn), &
7255                      ztransp(1:nzn*naz), itarget(1:nzn*naz) )   !FIXME allocate itarget only
7256                                                                 !in case of rad_angular_discretization
7257
7258           zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
7259           zbdry(:) = (/( zn0+REAL(izn,wp)*zns, izn=0, nzn )/)
7260           vffrac0(:) = (COS(zbdry(0:nzn-1)) - COS(zbdry(1:nzn))) / 2._wp / REAL(naz, wp)
7261           !
7262           !--Modify direction weights to simulate human body (lower weight for top-down)
7263           IF ( mrt_geom_human )  THEN
7264              vffrac0(:) = vffrac0(:) * MAX(0._wp, SIN(zcent(:))*0.88_wp + COS(zcent(:))*0.12_wp)
7265              vffrac0(:) = vffrac0(:) / (SUM(vffrac0) * REAL(naz, wp))
7266           ENDIF
7267
7268           DO  imrt = 1, nmrtbl
7269              ta = (/ REAL(mrtbl(iz, imrt), wp),  &
7270                      REAL(mrtbl(iy, imrt), wp),  &
7271                      REAL(mrtbl(ix, imrt), wp) /)
7272!
7273!--           vf fractions are constant per azimuth
7274              DO iaz = 0, naz-1
7275                 vffrac(iaz*nzn+1:(iaz+1)*nzn) = vffrac0(:)
7276              ENDDO
7277!--           sum of whole vffrac equals 1, verified
7278              itarg0 = 1
7279              itarg1 = nzn
7280!
7281!--           Calculate sky-view factor and direct solar visibility using 2D raytracing
7282              DO  iaz = 1, naz
7283                 azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
7284                 yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
7285                 yxlen = SQRT(SUM(yxdir(:)**2))
7286                 zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
7287                 yxdir(:) = yxdir(:) / yxlen
7288
7289                 CALL raytrace_2d(ta, yxdir, nzn, zdirs,                         &
7290                                  -999, -999._wp, vffrac(itarg0:itarg1), .TRUE., &
7291                                  .FALSE., .TRUE., lowest_free_ray,              &
7292                                  ztransp(itarg0:itarg1),                        &
7293                                  itarget(itarg0:itarg1))
7294
7295!--              Sky view factors for MRT
7296                 mrtsky(imrt) = mrtsky(imrt) + &
7297                                  SUM(vffrac(itarg0:itarg0+lowest_free_ray-1))
7298                 mrtskyt(imrt) = mrtskyt(imrt) + &
7299                                   SUM(ztransp(itarg0:itarg0+lowest_free_ray-1) &
7300                                               * vffrac(itarg0:itarg0+lowest_free_ray-1))
7301!--              Direct solar transparency for MRT
7302                 j = MODULO(NINT(azmid/                                         &
7303                                (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
7304                            raytrace_discrete_azims)
7305                 DO  k = 1, raytrace_discrete_elevs/2
7306                    i = dsidir_rev(k-1, j)
7307                    IF ( i /= -1  .AND.  k <= lowest_free_ray ) &
7308                       mrtdsit(imrt, i) = ztransp(itarg0+k-1)
7309                 ENDDO
7310!
7311!--              Advance itarget indices
7312                 itarg0 = itarg1 + 1
7313                 itarg1 = itarg1 + nzn
7314              ENDDO
7315
7316!--           sort itarget by face id
7317              CALL quicksort_itarget(itarget,vffrac,ztransp,1,nzn*naz)
7318!
7319!--           find the first valid position
7320              itarg0 = 1
7321              DO WHILE ( itarg0 <= nzn*naz )
7322                 IF ( itarget(itarg0) /= -1 )  EXIT
7323                 itarg0 = itarg0 + 1
7324              ENDDO
7325
7326              DO  i = itarg0, nzn*naz
7327!
7328!--              For duplicate values, only sum up vf fraction value
7329                 IF ( i < nzn*naz )  THEN
7330                    IF ( itarget(i+1) == itarget(i) )  THEN
7331                       vffrac(i+1) = vffrac(i+1) + vffrac(i)
7332                       CYCLE
7333                    ENDIF
7334                 ENDIF
7335!
7336!--              write to the mrtf array
7337                 nmrtf = nmrtf + 1
7338!--              check dimmension of mrtf array and enlarge it if needed
7339                 IF ( nmrtfa < nmrtf )  THEN
7340                    k = CEILING(REAL(nmrtfa, kind=wp) * grow_factor)
7341                    IF ( mmrtf == 0 )  THEN
7342                       mmrtf = 1
7343                       ALLOCATE( amrtf1(k) )
7344                       amrtf => amrtf1
7345                       amrtf1(1:nmrtfa) = amrtf2
7346                       DEALLOCATE( amrtf2 )
7347                    ELSE
7348                       mmrtf = 0
7349                       ALLOCATE( amrtf2(k) )
7350                       amrtf => amrtf2
7351                       amrtf2(1:nmrtfa) = amrtf1
7352                       DEALLOCATE( amrtf1 )
7353                    ENDIF
7354
7355                    IF ( debug_output )  THEN
7356                       WRITE( debug_string, '(A,3I12)' ) 'Grow amrtf:', nmrtf, nmrtfa, k
7357                       CALL debug_message( debug_string, 'info' )
7358                    ENDIF
7359
7360                    nmrtfa = k
7361                 ENDIF
7362!--              write mrtf values into the array
7363                 amrtf(nmrtf)%isurflt = imrt
7364                 amrtf(nmrtf)%isurfs = itarget(i)
7365                 amrtf(nmrtf)%rsvf = vffrac(i)
7366                 amrtf(nmrtf)%rtransp = ztransp(i)
7367              ENDDO ! itarg
7368
7369           ENDDO ! imrt
7370           DEALLOCATE ( zdirs, zcent, zbdry, vffrac, vffrac0, ztransp, itarget )
7371!
7372!--        Move MRT factors to final arrays
7373           ALLOCATE ( mrtf(nmrtf), mrtft(nmrtf), mrtfsurf(2,nmrtf) )
7374           DO  imrtf = 1, nmrtf
7375              mrtf(imrtf) = amrtf(imrtf)%rsvf
7376              mrtft(imrtf) = amrtf(imrtf)%rsvf * amrtf(imrtf)%rtransp
7377              mrtfsurf(:,imrtf) = (/amrtf(imrtf)%isurflt, amrtf(imrtf)%isurfs /)
7378           ENDDO
7379           IF ( ALLOCATED(amrtf1) )  DEALLOCATE( amrtf1 )
7380           IF ( ALLOCATED(amrtf2) )  DEALLOCATE( amrtf2 )
7381        ENDIF ! nmrtbl > 0
7382
7383        IF ( rad_angular_discretization )  THEN
7384#if defined( __parallel )
7385!--        finalize MPI_RMA communication established to get global index of the surface from grid indices
7386!--        flush all MPI window pending requests
7387           CALL MPI_Win_flush_all(win_gridsurf, ierr)
7388           IF ( ierr /= 0 ) THEN
7389               WRITE(9,*) 'Error MPI_Win_flush_all1:', ierr, win_gridsurf
7390               FLUSH(9)
7391           ENDIF
7392!--        unlock MPI window
7393           CALL MPI_Win_unlock_all(win_gridsurf, ierr)
7394           IF ( ierr /= 0 ) THEN
7395               WRITE(9,*) 'Error MPI_Win_unlock_all1:', ierr, win_gridsurf
7396               FLUSH(9)
7397           ENDIF
7398!--        free MPI window
7399           CALL MPI_Win_free(win_gridsurf, ierr)
7400           IF ( ierr /= 0 ) THEN
7401               WRITE(9,*) 'Error MPI_Win_free1:', ierr, win_gridsurf
7402               FLUSH(9)
7403           ENDIF
7404#else
7405           DEALLOCATE ( gridsurf )
7406#endif
7407        ENDIF
7408
7409        IF ( debug_output )  CALL debug_message( 'waiting for completion of SVF and CSF calculation in all processes', 'info' )
7410
7411!--     deallocate temporary global arrays
7412        DEALLOCATE(nzterr)
7413       
7414        IF ( plant_canopy )  THEN
7415!--         finalize mpi_rma communication and deallocate temporary arrays
7416#if defined( __parallel )
7417            IF ( raytrace_mpi_rma )  THEN
7418                CALL MPI_Win_flush_all(win_lad, ierr)
7419                IF ( ierr /= 0 ) THEN
7420                    WRITE(9,*) 'Error MPI_Win_flush_all2:', ierr, win_lad
7421                    FLUSH(9)
7422                ENDIF
7423!--             unlock MPI window
7424                CALL MPI_Win_unlock_all(win_lad, ierr)
7425                IF ( ierr /= 0 ) THEN
7426                    WRITE(9,*) 'Error MPI_Win_unlock_all2:', ierr, win_lad
7427                    FLUSH(9)
7428                ENDIF
7429!--             free MPI window
7430                CALL MPI_Win_free(win_lad, ierr)
7431                IF ( ierr /= 0 ) THEN
7432                    WRITE(9,*) 'Error MPI_Win_free2:', ierr, win_lad
7433                    FLUSH(9)
7434                ENDIF
7435!--             deallocate temporary arrays storing values for csf calculation during raytracing
7436                DEALLOCATE( lad_s_ray )
7437!--             sub_lad is the pointer to lad_s_rma in case of raytrace_mpi_rma
7438!--             and must not be deallocated here
7439            ELSE
7440                DEALLOCATE(sub_lad)
7441                DEALLOCATE(sub_lad_g)
7442            ENDIF
7443#else
7444            DEALLOCATE(sub_lad)
7445#endif
7446            DEALLOCATE( boxes )
7447            DEALLOCATE( crlens )
7448            DEALLOCATE( plantt )
7449            DEALLOCATE( rt2_track, rt2_track_lad, rt2_track_dist, rt2_dist )
7450        ENDIF
7451
7452        IF ( debug_output )  CALL debug_message( 'calculation of the complete SVF array', 'info' )
7453
7454        IF ( rad_angular_discretization )  THEN
7455           IF ( debug_output )  CALL debug_message( 'Load svf from the structure array to plain arrays', 'info' )
7456           ALLOCATE( svf(ndsvf,nsvfl) )
7457           ALLOCATE( svfsurf(idsvf,nsvfl) )
7458
7459           DO isvf = 1, nsvfl
7460               svf(:, isvf) = (/ asvf(isvf)%rsvf, asvf(isvf)%rtransp /)
7461               svfsurf(:, isvf) = (/ asvf(isvf)%isurflt, asvf(isvf)%isurfs /)
7462           ENDDO
7463        ELSE
7464           IF ( debug_output )  CALL debug_message( 'Start SVF sort', 'info' )
7465!--        sort svf ( a version of quicksort )
7466           CALL quicksort_svf(asvf,1,nsvfl)
7467
7468           !< load svf from the structure array to plain arrays
7469           IF ( debug_output )  CALL debug_message( 'Load svf from the structure array to plain arrays', 'info' )
7470           ALLOCATE( svf(ndsvf,nsvfl) )
7471           ALLOCATE( svfsurf(idsvf,nsvfl) )
7472           svfnorm_counts(:) = 0._wp
7473           isurflt_prev = -1
7474           ksvf = 1
7475           svfsum = 0._wp
7476           DO isvf = 1, nsvfl
7477!--            normalize svf per target face
7478               IF ( asvf(ksvf)%isurflt /= isurflt_prev )  THEN
7479                   IF ( isurflt_prev /= -1  .AND.  svfsum /= 0._wp )  THEN
7480                       !< update histogram of logged svf normalization values
7481                       i = searchsorted(svfnorm_report_thresh, svfsum / (1._wp-skyvf(isurflt_prev)))
7482                       svfnorm_counts(i) = svfnorm_counts(i) + 1
7483
7484                       svf(1, isvf_surflt:isvf-1) = svf(1, isvf_surflt:isvf-1) / svfsum * (1._wp-skyvf(isurflt_prev))
7485                   ENDIF
7486                   isurflt_prev = asvf(ksvf)%isurflt
7487                   isvf_surflt = isvf
7488                   svfsum = asvf(ksvf)%rsvf !?? / asvf(ksvf)%rtransp
7489               ELSE
7490                   svfsum = svfsum + asvf(ksvf)%rsvf !?? / asvf(ksvf)%rtransp
7491               ENDIF
7492
7493               svf(:, isvf) = (/ asvf(ksvf)%rsvf, asvf(ksvf)%rtransp /)
7494               svfsurf(:, isvf) = (/ asvf(ksvf)%isurflt, asvf(ksvf)%isurfs /)
7495
7496!--            next element
7497               ksvf = ksvf + 1
7498           ENDDO
7499
7500           IF ( isurflt_prev /= -1  .AND.  svfsum /= 0._wp )  THEN
7501               i = searchsorted(svfnorm_report_thresh, svfsum / (1._wp-skyvf(isurflt_prev)))
7502               svfnorm_counts(i) = svfnorm_counts(i) + 1
7503
7504               svf(1, isvf_surflt:nsvfl) = svf(1, isvf_surflt:nsvfl) / svfsum * (1._wp-skyvf(isurflt_prev))
7505           ENDIF
7506           WRITE(9, *) 'SVF normalization histogram:', svfnorm_counts,  &
7507                       'on thresholds:', svfnorm_report_thresh(1:svfnorm_report_num), '(val < thresh <= val)'
7508           !TODO we should be able to deallocate skyvf, from now on we only need skyvft
7509        ENDIF ! rad_angular_discretization
7510
7511!--     deallocate temporary asvf array
7512!--     DEALLOCATE(asvf) - ifort has a problem with deallocation of allocatable target
7513!--     via pointing pointer - we need to test original targets
7514        IF ( ALLOCATED(asvf1) )  THEN
7515            DEALLOCATE(asvf1)
7516        ENDIF
7517        IF ( ALLOCATED(asvf2) )  THEN
7518            DEALLOCATE(asvf2)
7519        ENDIF
7520
7521        npcsfl = 0
7522        IF ( plant_canopy )  THEN
7523
7524            IF ( debug_output )  CALL debug_message( 'Calculation of the complete CSF array', 'info' )
7525!--         sort and merge csf for the last time, keeping the array size to minimum
7526            CALL merge_and_grow_csf(-1)
7527           
7528!--         aggregate csb among processors
7529!--         allocate necessary arrays
7530            udim = max(ncsfl,1)
7531            ALLOCATE( csflt_l(ndcsf*udim) )
7532            csflt(1:ndcsf,1:udim) => csflt_l(1:ndcsf*udim)
7533            ALLOCATE( kcsflt_l(kdcsf*udim) )
7534            kcsflt(1:kdcsf,1:udim) => kcsflt_l(1:kdcsf*udim)
7535            ALLOCATE( icsflt(0:numprocs-1) )
7536            ALLOCATE( dcsflt(0:numprocs-1) )
7537            ALLOCATE( ipcsflt(0:numprocs-1) )
7538            ALLOCATE( dpcsflt(0:numprocs-1) )
7539           
7540!--         fill out arrays of csf values and
7541!--         arrays of number of elements and displacements
7542!--         for particular precessors
7543            icsflt = 0
7544            dcsflt = 0
7545            ip = -1
7546            j = -1
7547            d = 0
7548            DO kcsf = 1, ncsfl
7549                j = j+1
7550                IF ( acsf(kcsf)%ip /= ip )  THEN
7551!--                 new block of the processor
7552!--                 number of elements of previous block
7553                    IF ( ip>=0) icsflt(ip) = j
7554                    d = d+j
7555!--                 blank blocks
7556                    DO jp = ip+1, acsf(kcsf)%ip-1
7557!--                     number of elements is zero, displacement is equal to previous
7558                        icsflt(jp) = 0
7559                        dcsflt(jp) = d
7560                    ENDDO
7561!--                 the actual block
7562                    ip = acsf(kcsf)%ip
7563                    dcsflt(ip) = d
7564                    j = 0
7565                ENDIF
7566                csflt(1,kcsf) = acsf(kcsf)%rcvf
7567!--             fill out integer values of itz,ity,itx,isurfs
7568                kcsflt(1,kcsf) = acsf(kcsf)%itz
7569                kcsflt(2,kcsf) = acsf(kcsf)%ity
7570                kcsflt(3,kcsf) = acsf(kcsf)%itx
7571                kcsflt(4,kcsf) = acsf(kcsf)%isurfs
7572            ENDDO
7573!--         last blank blocks at the end of array
7574            j = j+1
7575            IF ( ip>=0 ) icsflt(ip) = j
7576            d = d+j
7577            DO jp = ip+1, numprocs-1
7578!--             number of elements is zero, displacement is equal to previous
7579                icsflt(jp) = 0
7580                dcsflt(jp) = d
7581            ENDDO
7582           
7583!--         deallocate temporary acsf array
7584!--         DEALLOCATE(acsf) - ifort has a problem with deallocation of allocatable target
7585!--         via pointing pointer - we need to test original targets
7586            IF ( ALLOCATED(acsf1) )  THEN
7587                DEALLOCATE(acsf1)
7588            ENDIF
7589            IF ( ALLOCATED(acsf2) )  THEN
7590                DEALLOCATE(acsf2)
7591            ENDIF
7592                   
7593#if defined( __parallel )
7594!--         scatter and gather the number of elements to and from all processor
7595!--         and calculate displacements
7596            IF ( debug_output )  CALL debug_message( 'Scatter and gather the number of elements to and from all processor', 'info' )
7597
7598            CALL MPI_AlltoAll(icsflt,1,MPI_INTEGER,ipcsflt,1,MPI_INTEGER,comm2d, ierr)
7599
7600            IF ( ierr /= 0 ) THEN
7601                WRITE(9,*) 'Error MPI_AlltoAll1:', ierr, SIZE(icsflt), SIZE(ipcsflt)
7602                FLUSH(9)
7603            ENDIF
7604
7605            npcsfl = SUM(ipcsflt)
7606            d = 0
7607            DO i = 0, numprocs-1
7608                dpcsflt(i) = d
7609                d = d + ipcsflt(i)
7610            ENDDO
7611
7612!--         exchange csf fields between processors
7613            IF ( debug_output )  CALL debug_message( 'Exchange csf fields between processors', 'info' )
7614            udim = max(npcsfl,1)
7615            ALLOCATE( pcsflt_l(ndcsf*udim) )
7616            pcsflt(1:ndcsf,1:udim) => pcsflt_l(1:ndcsf*udim)
7617            ALLOCATE( kpcsflt_l(kdcsf*udim) )
7618            kpcsflt(1:kdcsf,1:udim) => kpcsflt_l(1:kdcsf*udim)
7619            CALL MPI_AlltoAllv(csflt_l, ndcsf*icsflt, ndcsf*dcsflt, MPI_REAL, &
7620                pcsflt_l, ndcsf*ipcsflt, ndcsf*dpcsflt, MPI_REAL, comm2d, ierr)
7621            IF ( ierr /= 0 ) THEN
7622                WRITE(9,*) 'Error MPI_AlltoAllv1:', ierr, SIZE(ipcsflt), ndcsf*icsflt, &
7623                            ndcsf*dcsflt, SIZE(pcsflt_l),ndcsf*ipcsflt, ndcsf*dpcsflt
7624                FLUSH(9)
7625            ENDIF
7626
7627            CALL MPI_AlltoAllv(kcsflt_l, kdcsf*icsflt, kdcsf*dcsflt, MPI_INTEGER, &
7628                kpcsflt_l, kdcsf*ipcsflt, kdcsf*dpcsflt, MPI_INTEGER, comm2d, ierr)
7629            IF ( ierr /= 0 ) THEN
7630                WRITE(9,*) 'Error MPI_AlltoAllv2:', ierr, SIZE(kcsflt_l),kdcsf*icsflt, &
7631                           kdcsf*dcsflt, SIZE(kpcsflt_l), kdcsf*ipcsflt, kdcsf*dpcsflt
7632                FLUSH(9)
7633            ENDIF
7634           
7635#else
7636            npcsfl = ncsfl
7637            ALLOCATE( pcsflt(ndcsf,max(npcsfl,ndcsf)) )
7638            ALLOCATE( kpcsflt(kdcsf,max(npcsfl,kdcsf)) )
7639            pcsflt = csflt
7640            kpcsflt = kcsflt
7641#endif
7642
7643!--         deallocate temporary arrays
7644            DEALLOCATE( csflt_l )
7645            DEALLOCATE( kcsflt_l )
7646            DEALLOCATE( icsflt )
7647            DEALLOCATE( dcsflt )
7648            DEALLOCATE( ipcsflt )
7649            DEALLOCATE( dpcsflt )
7650
7651!--         sort csf ( a version of quicksort )
7652            IF ( debug_output )  CALL debug_message( 'Sort csf', 'info' )
7653            CALL quicksort_csf2(kpcsflt, pcsflt, 1, npcsfl)
7654
7655!--         aggregate canopy sink factor records with identical box & source
7656!--         againg across all values from all processors
7657            IF ( debug_output )  CALL debug_message( 'Aggregate canopy sink factor records with identical box', 'info' )
7658
7659            IF ( npcsfl > 0 )  THEN
7660                icsf = 1 !< reading index
7661                kcsf = 1 !< writing index
7662                DO WHILE (icsf < npcsfl)
7663!--                 here kpcsf(kcsf) already has values from kpcsf(icsf)
7664                    IF ( kpcsflt(3,icsf) == kpcsflt(3,icsf+1)  .AND.  &
7665                         kpcsflt(2,icsf) == kpcsflt(2,icsf+1)  .AND.  &
7666                         kpcsflt(1,icsf) == kpcsflt(1,icsf+1)  .AND.  &
7667                         kpcsflt(4,icsf) == kpcsflt(4,icsf+1) )  THEN
7668
7669                        pcsflt(1,kcsf) = pcsflt(1,kcsf) + pcsflt(1,icsf+1)
7670
7671!--                     advance reading index, keep writing index
7672                        icsf = icsf + 1
7673                    ELSE
7674!--                     not identical, just advance and copy
7675                        icsf = icsf + 1
7676                        kcsf = kcsf + 1
7677                        kpcsflt(:,kcsf) = kpcsflt(:,icsf)
7678                        pcsflt(:,kcsf) = pcsflt(:,icsf)
7679                    ENDIF
7680                ENDDO
7681!--             last written item is now also the last item in valid part of array
7682                npcsfl = kcsf
7683            ENDIF
7684
7685            ncsfl = npcsfl
7686            IF ( ncsfl > 0 )  THEN
7687                ALLOCATE( csf(ndcsf,ncsfl) )
7688                ALLOCATE( csfsurf(idcsf,ncsfl) )
7689                DO icsf = 1, ncsfl
7690                    csf(:,icsf) = pcsflt(:,icsf)
7691                    csfsurf(1,icsf) =  gridpcbl(kpcsflt(1,icsf),kpcsflt(2,icsf),kpcsflt(3,icsf))
7692                    csfsurf(2,icsf) =  kpcsflt(4,icsf)
7693                ENDDO
7694            ENDIF
7695           
7696!--         deallocation of temporary arrays
7697            IF ( npcbl > 0 )  DEALLOCATE( gridpcbl )
7698            DEALLOCATE( pcsflt_l )
7699            DEALLOCATE( kpcsflt_l )
7700            IF ( debug_output )  CALL debug_message( 'End of aggregate csf', 'info' )
7701           
7702        ENDIF
7703
7704#if defined( __parallel )
7705        CALL MPI_BARRIER( comm2d, ierr )
7706#endif
7707        CALL location_message( 'calculating view factors for radiation interaction', 'finished' )
7708
7709        RETURN  !todo: remove
7710       
7711!        WRITE( message_string, * )  &
7712!            'I/O error when processing shape view factors / ',  &
7713!            'plant canopy sink factors / direct irradiance factors.'
7714!        CALL message( 'init_urban_surface', 'PA0502', 2, 2, 0, 6, 0 )
7715       
7716    END SUBROUTINE radiation_calc_svf
7717
7718   
7719!------------------------------------------------------------------------------!
7720! Description:
7721! ------------
7722!> Raytracing for detecting obstacles and calculating compound canopy sink
7723!> factors. (A simple obstacle detection would only need to process faces in
7724!> 3 dimensions without any ordering.)
7725!> Assumtions:
7726!> -----------
7727!> 1. The ray always originates from a face midpoint (only one coordinate equals
7728!>    *.5, i.e. wall) and doesn't travel parallel to the surface (that would mean
7729!>    shape factor=0). Therefore, the ray may never travel exactly along a face
7730!>    or an edge.
7731!> 2. From grid bottom to urban surface top the grid has to be *equidistant*
7732!>    within each of the dimensions, including vertical (but the resolution
7733!>    doesn't need to be the same in all three dimensions).
7734!------------------------------------------------------------------------------!
7735    SUBROUTINE raytrace(src, targ, isrc, difvf, atarg, create_csf, visible, transparency)
7736        IMPLICIT NONE
7737
7738        REAL(wp), DIMENSION(3), INTENT(in)     :: src, targ    !< real coordinates z,y,x
7739        INTEGER(iwp), INTENT(in)               :: isrc         !< index of source face for csf
7740        REAL(wp), INTENT(in)                   :: difvf        !< differential view factor for csf
7741        REAL(wp), INTENT(in)                   :: atarg        !< target surface area for csf
7742        LOGICAL, INTENT(in)                    :: create_csf   !< whether to generate new CSFs during raytracing
7743        LOGICAL, INTENT(out)                   :: visible
7744        REAL(wp), INTENT(out)                  :: transparency !< along whole path
7745        INTEGER(iwp)                           :: i, k, d
7746        INTEGER(iwp)                           :: seldim       !< dimension to be incremented
7747        INTEGER(iwp)                           :: ncsb         !< no of written plant canopy sinkboxes
7748        INTEGER(iwp)                           :: maxboxes     !< max no of gridboxes visited
7749        REAL(wp)                               :: distance     !< euclidean along path
7750        REAL(wp)                               :: crlen        !< length of gridbox crossing
7751        REAL(wp)                               :: lastdist     !< beginning of current crossing
7752        REAL(wp)                               :: nextdist     !< end of current crossing
7753        REAL(wp)                               :: realdist     !< distance in meters per unit distance
7754        REAL(wp)                               :: crmid        !< midpoint of crossing
7755        REAL(wp)                               :: cursink      !< sink factor for current canopy box
7756        REAL(wp), DIMENSION(3)                 :: delta        !< path vector
7757        REAL(wp), DIMENSION(3)                 :: uvect        !< unit vector
7758        REAL(wp), DIMENSION(3)                 :: dimnextdist  !< distance for each dimension increments
7759        INTEGER(iwp), DIMENSION(3)             :: box          !< gridbox being crossed
7760        INTEGER(iwp), DIMENSION(3)             :: dimnext      !< next dimension increments along path
7761        INTEGER(iwp), DIMENSION(3)             :: dimdelta     !< dimension direction = +- 1
7762        INTEGER(iwp)                           :: px, py       !< number of processors in x and y dir before
7763                                                               !< the processor in the question
7764        INTEGER(iwp)                           :: ip           !< number of processor where gridbox reside
7765        INTEGER(iwp)                           :: ig           !< 1D index of gridbox in global 2D array
7766       
7767        REAL(wp)                               :: eps = 1E-10_wp !< epsilon for value comparison
7768        REAL(wp)                               :: lad_s_target   !< recieved lad_s of particular grid box
7769
7770!
7771!--     Maximum number of gridboxes visited equals to maximum number of boundaries crossed in each dimension plus one. That's also
7772!--     the maximum number of plant canopy boxes written. We grow the acsf array accordingly using exponential factor.
7773        maxboxes = SUM(ABS(NINT(targ, iwp) - NINT(src, iwp))) + 1
7774        IF ( plant_canopy  .AND.  ncsfl + maxboxes > ncsfla )  THEN
7775!--         use this code for growing by fixed exponential increments (equivalent to case where ncsfl always increases by 1)
7776!--         k = CEILING(grow_factor ** real(CEILING(log(real(ncsfl + maxboxes, kind=wp)) &
7777!--                                                / log(grow_factor)), kind=wp))
7778!--         or use this code to simply always keep some extra space after growing
7779            k = CEILING(REAL(ncsfl + maxboxes, kind=wp) * grow_factor)
7780
7781            CALL merge_and_grow_csf(k)
7782        ENDIF
7783       
7784        transparency = 1._wp
7785        ncsb = 0
7786
7787        delta(:) = targ(:) - src(:)
7788        distance = SQRT(SUM(delta(:)**2))
7789        IF ( distance == 0._wp )  THEN
7790            visible = .TRUE.
7791            RETURN
7792        ENDIF
7793        uvect(:) = delta(:) / distance
7794        realdist = SQRT(SUM( (uvect(:)*(/dz(1),dy,dx/))**2 ))
7795
7796        lastdist = 0._wp
7797
7798!--     Since all face coordinates have values *.5 and we'd like to use
7799!--     integers, all these have .5 added
7800        DO d = 1, 3
7801            IF ( uvect(d) == 0._wp )  THEN
7802                dimnext(d) = 999999999
7803                dimdelta(d) = 999999999
7804                dimnextdist(d) = 1.0E20_wp
7805            ELSE IF ( uvect(d) > 0._wp )  THEN
7806                dimnext(d) = CEILING(src(d) + .5_wp)
7807                dimdelta(d) = 1
7808                dimnextdist(d) = (dimnext(d) - .5_wp - src(d)) / uvect(d)
7809            ELSE
7810                dimnext(d) = FLOOR(src(d) + .5_wp)
7811                dimdelta(d) = -1
7812                dimnextdist(d) = (dimnext(d) - .5_wp - src(d)) / uvect(d)
7813            ENDIF
7814        ENDDO
7815
7816        DO
7817!--         along what dimension will the next wall crossing be?
7818            seldim = minloc(dimnextdist, 1)
7819            nextdist = dimnextdist(seldim)
7820            IF ( nextdist > distance ) nextdist = distance
7821
7822            crlen = nextdist - lastdist
7823            IF ( crlen > .001_wp )  THEN
7824                crmid = (lastdist + nextdist) * .5_wp
7825                box = NINT(src(:) + uvect(:) * crmid, iwp)
7826
7827!--             calculate index of the grid with global indices (box(2),box(3))
7828!--             in the array nzterr and plantt and id of the coresponding processor
7829                px = box(3)/nnx
7830                py = box(2)/nny
7831                ip = px*pdims(2)+py
7832                ig = ip*nnx*nny + (box(3)-px*nnx)*nny + box(2)-py*nny
7833                IF ( box(1) <= nzterr(ig) )  THEN
7834                    visible = .FALSE.
7835                    RETURN
7836                ENDIF
7837
7838                IF ( plant_canopy )  THEN
7839                    IF ( box(1) <= plantt(ig) )  THEN
7840                        ncsb = ncsb + 1
7841                        boxes(:,ncsb) = box
7842                        crlens(ncsb) = crlen
7843#if defined( __parallel )
7844                        lad_ip(ncsb) = ip
7845                        lad_disp(ncsb) = (box(3)-px*nnx)*(nny*nz_plant) + (box(2)-py*nny)*nz_plant + box(1)-nz_urban_b
7846#endif
7847                    ENDIF
7848                ENDIF
7849            ENDIF
7850
7851            IF ( ABS(distance - nextdist) < eps )  EXIT
7852            lastdist = nextdist
7853            dimnext(seldim) = dimnext(seldim) + dimdelta(seldim)
7854            dimnextdist(seldim) = (dimnext(seldim) - .5_wp - src(seldim)) / uvect(seldim)
7855        ENDDO
7856       
7857        IF ( plant_canopy )  THEN
7858#if defined( __parallel )
7859            IF ( raytrace_mpi_rma )  THEN
7860!--             send requests for lad_s to appropriate processor
7861                CALL cpu_log( log_point_s(77), 'rad_rma_lad', 'start' )
7862                DO i = 1, ncsb
7863                    CALL MPI_Get(lad_s_ray(i), 1, MPI_REAL, lad_ip(i), lad_disp(i), &
7864                                 1, MPI_REAL, win_lad, ierr)
7865                    IF ( ierr /= 0 )  THEN
7866                        WRITE(9,*) 'Error MPI_Get1:', ierr, lad_s_ray(i), &
7867                                   lad_ip(i), lad_disp(i), win_lad
7868                        FLUSH(9)
7869                    ENDIF
7870                ENDDO
7871               
7872!--             wait for all pending local requests complete
7873                CALL MPI_Win_flush_local_all(win_lad, ierr)
7874                IF ( ierr /= 0 )  THEN
7875                    WRITE(9,*) 'Error MPI_Win_flush_local_all1:', ierr, win_lad
7876                    FLUSH(9)
7877                ENDIF
7878                CALL cpu_log( log_point_s(77), 'rad_rma_lad', 'stop' )
7879               
7880            ENDIF
7881#endif
7882
7883!--         calculate csf and transparency
7884            DO i = 1, ncsb
7885#if defined( __parallel )
7886                IF ( raytrace_mpi_rma )  THEN
7887                    lad_s_target = lad_s_ray(i)
7888                ELSE
7889                    lad_s_target = sub_lad_g(lad_ip(i)*nnx*nny*nz_plant + lad_disp(i))
7890                ENDIF
7891#else
7892                lad_s_target = sub_lad(boxes(1,i),boxes(2,i),boxes(3,i))
7893#endif
7894                cursink = 1._wp - exp(-ext_coef * lad_s_target * crlens(i)*realdist)
7895
7896                IF ( create_csf )  THEN
7897!--                 write svf values into the array
7898                    ncsfl = ncsfl + 1
7899                    acsf(ncsfl)%ip = lad_ip(i)
7900                    acsf(ncsfl)%itx = boxes(3,i)
7901                    acsf(ncsfl)%ity = boxes(2,i)
7902                    acsf(ncsfl)%itz = boxes(1,i)
7903                    acsf(ncsfl)%isurfs = isrc
7904                    acsf(ncsfl)%rcvf = cursink*transparency*difvf*atarg
7905                ENDIF  !< create_csf
7906
7907                transparency = transparency * (1._wp - cursink)
7908               
7909            ENDDO
7910        ENDIF
7911       
7912        visible = .TRUE.
7913
7914    END SUBROUTINE raytrace
7915   
7916 
7917!------------------------------------------------------------------------------!
7918! Description:
7919! ------------
7920!> A new, more efficient version of ray tracing algorithm that processes a whole
7921!> arc instead of a single ray.
7922!>
7923!> In all comments, horizon means tangent of horizon angle, i.e.
7924!> vertical_delta / horizontal_distance
7925!------------------------------------------------------------------------------!
7926   SUBROUTINE raytrace_2d(origin, yxdir, nrays, zdirs, iorig, aorig, vffrac,  &
7927                              calc_svf, create_csf, skip_1st_pcb,             &
7928                              lowest_free_ray, transparency, itarget)
7929      IMPLICIT NONE
7930
7931      REAL(wp), DIMENSION(3), INTENT(IN)     ::  origin        !< z,y,x coordinates of ray origin
7932      REAL(wp), DIMENSION(2), INTENT(IN)     ::  yxdir         !< y,x *unit* vector of ray direction (in grid units)
7933      INTEGER(iwp)                           ::  nrays         !< number of rays (z directions) to raytrace
7934      REAL(wp), DIMENSION(nrays), INTENT(IN) ::  zdirs         !< list of z directions to raytrace (z/hdist, grid, zenith->nadir)
7935      INTEGER(iwp), INTENT(in)               ::  iorig         !< index of origin face for csf
7936      REAL(wp), INTENT(in)                   ::  aorig         !< origin face area for csf
7937      REAL(wp), DIMENSION(nrays), INTENT(in) ::  vffrac        !< view factor fractions of each ray for csf
7938      LOGICAL, INTENT(in)                    ::  calc_svf      !< whether to calculate SFV (identify obstacle surfaces)
7939      LOGICAL, INTENT(in)                    ::  create_csf    !< whether to create canopy sink factors
7940      LOGICAL, INTENT(in)                    ::  skip_1st_pcb  !< whether to skip first plant canopy box during raytracing
7941      INTEGER(iwp), INTENT(out)              ::  lowest_free_ray !< index into zdirs
7942      REAL(wp), DIMENSION(nrays), INTENT(OUT) ::  transparency !< transparencies of zdirs paths
7943      INTEGER(iwp), DIMENSION(nrays), INTENT(OUT) ::  itarget  !< global indices of target faces for zdirs
7944
7945      INTEGER(iwp), DIMENSION(nrays)         ::  target_procs
7946      REAL(wp)                               ::  horizon       !< highest horizon found after raytracing (z/hdist)
7947      INTEGER(iwp)                           ::  i, k, l, d
7948      INTEGER(iwp)                           ::  seldim       !< dimension to be incremented
7949      REAL(wp), DIMENSION(2)                 ::  yxorigin     !< horizontal copy of origin (y,x)
7950      REAL(wp)                               ::  distance     !< euclidean along path
7951      REAL(wp)                               ::  lastdist     !< beginning of current crossing
7952      REAL(wp)                               ::  nextdist     !< end of current crossing
7953      REAL(wp)                               ::  crmid        !< midpoint of crossing
7954      REAL(wp)                               ::  horz_entry   !< horizon at entry to column
7955      REAL(wp)                               ::  horz_exit    !< horizon at exit from column
7956      REAL(wp)                               ::  bdydim       !< boundary for current dimension
7957      REAL(wp), DIMENSION(2)                 ::  crossdist    !< distances to boundary for dimensions
7958      REAL(wp), DIMENSION(2)                 ::  dimnextdist  !< distance for each dimension increments
7959      INTEGER(iwp), DIMENSION(2)             ::  column       !< grid column being crossed
7960      INTEGER(iwp), DIMENSION(2)             ::  dimnext      !< next dimension increments along path
7961      INTEGER(iwp), DIMENSION(2)             ::  dimdelta     !< dimension direction = +- 1
7962      INTEGER(iwp)                           ::  px, py       !< number of processors in x and y dir before
7963                                                              !< the processor in the question
7964      INTEGER(iwp)                           ::  ip           !< number of processor where gridbox reside
7965      INTEGER(iwp)                           ::  ig           !< 1D index of gridbox in global 2D array
7966      INTEGER(iwp)                           ::  wcount       !< RMA window item count
7967      INTEGER(iwp)                           ::  maxboxes     !< max no of CSF created
7968      INTEGER(iwp)                           ::  nly          !< maximum  plant canopy height
7969      INTEGER(iwp)                           ::  ntrack
7970     
7971      INTEGER(iwp)                           ::  zb0
7972      INTEGER(iwp)                           ::  zb1
7973      INTEGER(iwp)                           ::  nz
7974      INTEGER(iwp)                           ::  iz
7975      INTEGER(iwp)                           ::  zsgn
7976      INTEGER(iwp)                           ::  lowest_lad   !< lowest column cell for which we need LAD
7977      INTEGER(iwp)                           ::  lastdir      !< wall direction before hitting this column
7978      INTEGER(iwp), DIMENSION(2)             ::  lastcolumn
7979
7980#if defined( __parallel )
7981      INTEGER(MPI_ADDRESS_KIND)              ::  wdisp        !< RMA window displacement
7982#endif
7983     
7984      REAL(wp)                               ::  eps = 1E-10_wp !< epsilon for value comparison
7985      REAL(wp)                               ::  zbottom, ztop !< urban surface boundary in real numbers
7986      REAL(wp)                               ::  zorig         !< z coordinate of ray column entry
7987      REAL(wp)                               ::  zexit         !< z coordinate of ray column exit
7988      REAL(wp)                               ::  qdist         !< ratio of real distance to z coord difference
7989      REAL(wp)                               ::  dxxyy         !< square of real horizontal distance
7990      REAL(wp)                               ::  curtrans      !< transparency of current PC box crossing
7991     
7992
7993     
7994      yxorigin(:) = origin(2:3)
7995      transparency(:) = 1._wp !-- Pre-set the all rays to transparent before reducing
7996      horizon = -HUGE(1._wp)
7997      lowest_free_ray = nrays
7998      IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7999         ALLOCATE(target_surfl(nrays))
8000         target_surfl(:) = -1
8001         lastdir = -999
8002         lastcolumn(:) = -999
8003      ENDIF
8004
8005!--   Determine distance to boundary (in 2D xy)
8006      IF ( yxdir(1) > 0._wp )  THEN
8007         bdydim = ny + .5_wp !< north global boundary
8008         crossdist(1) = (bdydim - yxorigin(1)) / yxdir(1)
8009      ELSEIF ( yxdir(1) == 0._wp )  THEN
8010         crossdist(1) = HUGE(1._wp)
8011      ELSE
8012          bdydim = -.5_wp !< south global boundary
8013          crossdist(1) = (bdydim - yxorigin(1)) / yxdir(1)
8014      ENDIF
8015
8016      IF ( yxdir(2) > 0._wp )  THEN
8017          bdydim = nx + .5_wp !< east global boundary
8018          crossdist(2) = (bdydim - yxorigin(2)) / yxdir(2)
8019      ELSEIF ( yxdir(2) == 0._wp )  THEN
8020         crossdist(2) = HUGE(1._wp)
8021      ELSE
8022          bdydim = -.5_wp !< west global boundary
8023          crossdist(2) = (bdydim - yxorigin(2)) / yxdir(2)
8024      ENDIF
8025      distance = minval(crossdist, 1)
8026
8027      IF ( plant_canopy )  THEN
8028         rt2_track_dist(0) = 0._wp
8029         rt2_track_lad(:,:) = 0._wp
8030         nly = plantt_max - nz_urban_b + 1
8031      ENDIF
8032
8033      lastdist = 0._wp
8034
8035!--   Since all face coordinates have values *.5 and we'd like to use
8036!--   integers, all these have .5 added
8037      DO  d = 1, 2
8038          IF ( yxdir(d) == 0._wp )  THEN
8039              dimnext(d) = HUGE(1_iwp)
8040              dimdelta(d) = HUGE(1_iwp)
8041              dimnextdist(d) = HUGE(1._wp)
8042          ELSE IF ( yxdir(d) > 0._wp )  THEN
8043              dimnext(d) = FLOOR(yxorigin(d) + .5_wp) + 1
8044              dimdelta(d) = 1
8045              dimnextdist(d) = (dimnext(d) - .5_wp - yxorigin(d)) / yxdir(d)
8046          ELSE
8047              dimnext(d) = CEILING(yxorigin(d) + .5_wp) - 1
8048              dimdelta(d) = -1
8049              dimnextdist(d) = (dimnext(d) - .5_wp - yxorigin(d)) / yxdir(d)
8050          ENDIF
8051      ENDDO
8052
8053      ntrack = 0
8054      DO
8055!--      along what dimension will the next wall crossing be?
8056         seldim = minloc(dimnextdist, 1)
8057         nextdist = dimnextdist(seldim)
8058         IF ( nextdist > distance )  nextdist = distance
8059
8060         IF ( nextdist > lastdist )  THEN
8061            ntrack = ntrack + 1
8062            crmid = (lastdist + nextdist) * .5_wp
8063            column = NINT(yxorigin(:) + yxdir(:) * crmid, iwp)
8064
8065!--         calculate index of the grid with global indices (column(1),column(2))
8066!--         in the array nzterr and plantt and id of the coresponding processor
8067            px = column(2)/nnx
8068            py = column(1)/nny
8069            ip = px*pdims(2)+py
8070            ig = ip*nnx*nny + (column(2)-px*nnx)*nny + column(1)-py*nny
8071
8072            IF ( lastdist == 0._wp )  THEN
8073               horz_entry = -HUGE(1._wp)
8074            ELSE
8075               horz_entry = (REAL(nzterr(ig), wp) + .5_wp - origin(1)) / lastdist
8076            ENDIF
8077            horz_exit = (REAL(nzterr(ig), wp) + .5_wp - origin(1)) / nextdist
8078
8079            IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
8080!
8081!--            Identify vertical obstacles hit by rays in current column
8082               DO WHILE ( lowest_free_ray > 0 )
8083                  IF ( zdirs(lowest_free_ray) > horz_entry )  EXIT
8084!
8085!--               This may only happen after 1st column, so lastdir and lastcolumn are valid
8086                  CALL request_itarget(lastdir,                                         &
8087                        CEILING(-0.5_wp + origin(1) + zdirs(lowest_free_ray)*lastdist), &
8088                        lastcolumn(1), lastcolumn(2),                                   &
8089                        target_surfl(lowest_free_ray), target_procs(lowest_free_ray))
8090                  lowest_free_ray = lowest_free_ray - 1
8091               ENDDO
8092!
8093!--            Identify horizontal obstacles hit by rays in current column
8094               DO WHILE ( lowest_free_ray > 0 )
8095                  IF ( zdirs(lowest_free_ray) > horz_exit )  EXIT
8096                  CALL request_itarget(iup_u, nzterr(ig)+1, column(1), column(2), &
8097                                       target_surfl(lowest_free_ray),           &
8098                                       target_procs(lowest_free_ray))
8099                  lowest_free_ray = lowest_free_ray - 1
8100               ENDDO
8101            ENDIF
8102
8103            horizon = MAX(horizon, horz_entry, horz_exit)
8104
8105            IF ( plant_canopy )  THEN
8106               rt2_track(:, ntrack) = column(:)
8107               rt2_track_dist(ntrack) = nextdist
8108            ENDIF
8109         ENDIF
8110
8111         IF ( nextdist + eps >= distance )  EXIT
8112
8113         IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
8114!
8115!--         Save wall direction of coming building column (= this air column)
8116            IF ( seldim == 1 )  THEN
8117               IF ( dimdelta(seldim) == 1 )  THEN
8118                  lastdir = isouth_u
8119               ELSE
8120                  lastdir = inorth_u
8121               ENDIF
8122            ELSE
8123               IF ( dimdelta(seldim) == 1 )  THEN
8124                  lastdir = iwest_u
8125               ELSE
8126                  lastdir = ieast_u
8127               ENDIF
8128            ENDIF
8129            lastcolumn = column
8130         ENDIF
8131         lastdist = nextdist
8132         dimnext(seldim) = dimnext(seldim) + dimdelta(seldim)
8133         dimnextdist(seldim) = (dimnext(seldim) - .5_wp - yxorigin(seldim)) / yxdir(seldim)
8134      ENDDO
8135
8136      IF ( plant_canopy )  THEN
8137!--      Request LAD WHERE applicable
8138!--     
8139#if defined( __parallel )
8140         IF ( raytrace_mpi_rma )  THEN
8141!--         send requests for lad_s to appropriate processor
8142            !CALL cpu_log( log_point_s(77), 'usm_init_rma', 'start' )
8143            DO  i = 1, ntrack
8144               px = rt2_track(2,i)/nnx
8145               py = rt2_track(1,i)/nny
8146               ip = px*pdims(2)+py
8147               ig = ip*nnx*nny + (rt2_track(2,i)-px*nnx)*nny + rt2_track(1,i)-py*nny
8148
8149               IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
8150!
8151!--               For fixed view resolution, we need plant canopy even for rays
8152!--               to opposing surfaces
8153                  lowest_lad = nzterr(ig) + 1
8154               ELSE
8155!
8156!--               We only need LAD for rays directed above horizon (to sky)
8157                  lowest_lad = CEILING( -0.5_wp + origin(1) +            &
8158                                    MIN( horizon * rt2_track_dist(i-1),  & ! entry
8159                                         horizon * rt2_track_dist(i)   ) ) ! exit
8160               ENDIF
8161!
8162!--            Skip asking for LAD where all plant canopy is under requested level
8163               IF ( plantt(ig) < lowest_lad )  CYCLE
8164
8165               wdisp = (rt2_track(2,i)-px*nnx)*(nny*nz_plant) + (rt2_track(1,i)-py*nny)*nz_plant + lowest_lad-nz_urban_b
8166               wcount = plantt(ig)-lowest_lad+1
8167               ! TODO send request ASAP - even during raytracing
8168               CALL MPI_Get(rt2_track_lad(lowest_lad:plantt(ig), i), wcount, MPI_REAL, ip,    &
8169                            wdisp, wcount, MPI_REAL, win_lad, ierr)
8170               IF ( ierr /= 0 )  THEN
8171                  WRITE(9,*) 'Error MPI_Get2:', ierr, rt2_track_lad(lowest_lad:plantt(ig), i), &
8172                             wcount, ip, wdisp, win_lad
8173                  FLUSH(9)
8174               ENDIF
8175            ENDDO
8176
8177!--         wait for all pending local requests complete
8178            ! TODO WAIT selectively for each column later when needed
8179            CALL MPI_Win_flush_local_all(win_lad, ierr)
8180            IF ( ierr /= 0 )  THEN
8181               WRITE(9,*) 'Error MPI_Win_flush_local_all2:', ierr, win_lad
8182               FLUSH(9)
8183            ENDIF
8184            !CALL cpu_log( log_point_s(77), 'usm_init_rma', 'stop' )
8185
8186         ELSE ! raytrace_mpi_rma = .F.
8187            DO  i = 1, ntrack
8188               px = rt2_track(2,i)/nnx
8189               py = rt2_track(1,i)/nny
8190               ip = px*pdims(2)+py
8191               ig = ip*nnx*nny*nz_plant + (rt2_track(2,i)-px*nnx)*(nny*nz_plant) + (rt2_track(1,i)-py*nny)*nz_plant
8192               rt2_track_lad(nz_urban_b:plantt_max, i) = sub_lad_g(ig:ig+nly-1)
8193            ENDDO
8194         ENDIF
8195#else
8196         DO  i = 1, ntrack
8197            rt2_track_lad(nz_urban_b:plantt_max, i) = sub_lad(rt2_track(1,i), rt2_track(2,i), nz_urban_b:plantt_max)
8198         ENDDO
8199#endif
8200      ENDIF ! plant_canopy
8201
8202      IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
8203#if defined( __parallel )
8204!--      wait for all gridsurf requests to complete
8205         CALL MPI_Win_flush_local_all(win_gridsurf, ierr)
8206         IF ( ierr /= 0 )  THEN
8207            WRITE(9,*) 'Error MPI_Win_flush_local_all3:', ierr, win_gridsurf
8208            FLUSH(9)
8209         ENDIF
8210#endif
8211!
8212!--      recalculate local surf indices into global ones
8213         DO i = 1, nrays
8214            IF ( target_surfl(i) == -1 )  THEN
8215               itarget(i) = -1
8216            ELSE
8217               itarget(i) = target_surfl(i) + surfstart(target_procs(i))
8218            ENDIF
8219         ENDDO
8220         
8221         DEALLOCATE( target_surfl )
8222         
8223      ELSE
8224         itarget(:) = -1
8225      ENDIF ! rad_angular_discretization
8226
8227      IF ( plant_canopy )  THEN
8228!--      Skip the PCB around origin if requested (for MRT, the PCB might not be there)
8229!--     
8230         IF ( skip_1st_pcb  .AND.  NINT(origin(1)) <= plantt_max )  THEN
8231            rt2_track_lad(NINT(origin(1), iwp), 1) = 0._wp
8232         ENDIF
8233
8234!--      Assert that we have space allocated for CSFs
8235!--     
8236         maxboxes = (ntrack + MAX(CEILING(origin(1)-.5_wp) - nz_urban_b,          &
8237                                  nz_urban_t - CEILING(origin(1)-.5_wp))) * nrays
8238         IF ( ncsfl + maxboxes > ncsfla )  THEN
8239!--         use this code for growing by fixed exponential increments (equivalent to case where ncsfl always increases by 1)
8240!--         k = CEILING(grow_factor ** real(CEILING(log(real(ncsfl + maxboxes, kind=wp)) &
8241!--                                                / log(grow_factor)), kind=wp))
8242!--         or use this code to simply always keep some extra space after growing
8243            k = CEILING(REAL(ncsfl + maxboxes, kind=wp) * grow_factor)
8244            CALL merge_and_grow_csf(k)
8245         ENDIF
8246
8247!--      Calculate transparencies and store new CSFs
8248!--     
8249         zbottom = REAL(nz_urban_b, wp) - .5_wp
8250         ztop = REAL(plantt_max, wp) + .5_wp
8251
8252!--      Reverse direction of radiation (face->sky), only when calc_svf
8253!--     
8254         IF ( calc_svf )  THEN
8255            DO  i = 1, ntrack ! for each column
8256               dxxyy = ((dy*yxdir(1))**2 + (dx*yxdir(2))**2) * (rt2_track_dist(i)-rt2_track_dist(i-1))**2
8257               px = rt2_track(2,i)/nnx
8258               py = rt2_track(1,i)/nny
8259               ip = px*pdims(2)+py
8260
8261               DO  k = 1, nrays ! for each ray
8262!
8263!--               NOTE 6778:
8264!--               With traditional svf discretization, CSFs under the horizon
8265!--               (i.e. for surface to surface radiation)  are created in
8266!--               raytrace(). With rad_angular_discretization, we must create
8267!--               CSFs under horizon only for one direction, otherwise we would
8268!--               have duplicate amount of energy. Although we could choose
8269!--               either of the two directions (they differ only by
8270!--               discretization error with no bias), we choose the the backward
8271!--               direction, because it tends to cumulate high canopy sink
8272!--               factors closer to raytrace origin, i.e. it should potentially
8273!--               cause less moiree.
8274                  IF ( .NOT. rad_angular_discretization )  THEN
8275                     IF ( zdirs(k) <= horizon )  CYCLE
8276                  ENDIF
8277
8278                  zorig = origin(1) + zdirs(k) * rt2_track_dist(i-1)
8279                  IF ( zorig <= zbottom  .OR.  zorig >= ztop )  CYCLE
8280
8281                  zsgn = INT(SIGN(1._wp, zdirs(k)), iwp)
8282                  rt2_dist(1) = 0._wp
8283                  IF ( zdirs(k) == 0._wp )  THEN ! ray is exactly horizontal
8284                     nz = 2
8285                     rt2_dist(nz) = SQRT(dxxyy)
8286                     iz = CEILING(-.5_wp + zorig, iwp)
8287                  ELSE
8288                     zexit = MIN(MAX(origin(1) + zdirs(k) * rt2_track_dist(i), zbottom), ztop)
8289
8290                     zb0 = FLOOR(  zorig * zsgn - .5_wp) + 1  ! because it must be greater than orig
8291                     zb1 = CEILING(zexit * zsgn - .5_wp) - 1  ! because it must be smaller than exit
8292                     nz = MAX(zb1 - zb0 + 3, 2)
8293                     rt2_dist(nz) = SQRT(((zexit-zorig)*dz(1))**2 + dxxyy)
8294                     qdist = rt2_dist(nz) / (zexit-zorig)
8295                     rt2_dist(2:nz-1) = (/( ((REAL(l, wp) + .5_wp) * zsgn - zorig) * qdist , l = zb0, zb1 )/)
8296                     iz = zb0 * zsgn
8297                  ENDIF
8298
8299                  DO  l = 2, nz
8300                     IF ( rt2_track_lad(iz, i) > 0._wp )  THEN
8301                        curtrans = exp(-ext_coef * rt2_track_lad(iz, i) * (rt2_dist(l)-rt2_dist(l-1)))
8302
8303                        IF ( create_csf )  THEN
8304                           ncsfl = ncsfl + 1
8305                           acsf(ncsfl)%ip = ip
8306                           acsf(ncsfl)%itx = rt2_track(2,i)
8307                           acsf(ncsfl)%ity = rt2_track(1,i)
8308                           acsf(ncsfl)%itz = iz
8309                           acsf(ncsfl)%isurfs = iorig
8310                           acsf(ncsfl)%rcvf = (1._wp - curtrans)*transparency(k)*vffrac(k)
8311                        ENDIF
8312
8313                        transparency(k) = transparency(k) * curtrans
8314                     ENDIF
8315                     iz = iz + zsgn
8316                  ENDDO ! l = 1, nz - 1
8317               ENDDO ! k = 1, nrays
8318            ENDDO ! i = 1, ntrack
8319
8320            transparency(1:lowest_free_ray) = 1._wp !-- Reset rays above horizon to transparent (see NOTE 6778)
8321         ENDIF
8322
8323!--      Forward direction of radiation (sky->face), always
8324!--     
8325         DO  i = ntrack, 1, -1 ! for each column backwards
8326            dxxyy = ((dy*yxdir(1))**2 + (dx*yxdir(2))**2) * (rt2_track_dist(i)-rt2_track_dist(i-1))**2
8327            px = rt2_track(2,i)/nnx
8328            py = rt2_track(1,i)/nny
8329            ip = px*pdims(2)+py
8330
8331            DO  k = 1, nrays ! for each ray
8332!
8333!--            See NOTE 6778 above
8334               IF ( zdirs(k) <= horizon )  CYCLE
8335
8336               zexit = origin(1) + zdirs(k) * rt2_track_dist(i-1)
8337               IF ( zexit <= zbottom  .OR.  zexit >= ztop )  CYCLE
8338
8339               zsgn = -INT(SIGN(1._wp, zdirs(k)), iwp)
8340               rt2_dist(1) = 0._wp
8341               IF ( zdirs(k) == 0._wp )  THEN ! ray is exactly horizontal
8342                  nz = 2
8343                  rt2_dist(nz) = SQRT(dxxyy)
8344                  iz = NINT(zexit, iwp)
8345               ELSE
8346                  zorig = MIN(MAX(origin(1) + zdirs(k) * rt2_track_dist(i), zbottom), ztop)
8347
8348                  zb0 = FLOOR(  zorig * zsgn - .5_wp) + 1  ! because it must be greater than orig
8349                  zb1 = CEILING(zexit * zsgn - .5_wp) - 1  ! because it must be smaller than exit
8350                  nz = MAX(zb1 - zb0 + 3, 2)
8351                  rt2_dist(nz) = SQRT(((zexit-zorig)*dz(1))**2 + dxxyy)
8352                  qdist = rt2_dist(nz) / (zexit-zorig)
8353                  rt2_dist(2:nz-1) = (/( ((REAL(l, wp) + .5_wp) * zsgn - zorig) * qdist , l = zb0, zb1 )/)
8354                  iz = zb0 * zsgn
8355               ENDIF
8356
8357               DO  l = 2, nz
8358                  IF ( rt2_track_lad(iz, i) > 0._wp )  THEN
8359                     curtrans = exp(-ext_coef * rt2_track_lad(iz, i) * (rt2_dist(l)-rt2_dist(l-1)))
8360
8361                     IF ( create_csf )  THEN
8362                        ncsfl = ncsfl + 1
8363                        acsf(ncsfl)%ip = ip
8364                        acsf(ncsfl)%itx = rt2_track(2,i)
8365                        acsf(ncsfl)%ity = rt2_track(1,i)
8366                        acsf(ncsfl)%itz = iz
8367                        IF ( itarget(k) /= -1 ) STOP 1 !FIXME remove after test
8368                        acsf(ncsfl)%isurfs = -1
8369                        acsf(ncsfl)%rcvf = (1._wp - curtrans)*transparency(k)*aorig*vffrac(k)
8370                     ENDIF  ! create_csf
8371
8372                     transparency(k) = transparency(k) * curtrans
8373                  ENDIF
8374                  iz = iz + zsgn
8375               ENDDO ! l = 1, nz - 1
8376            ENDDO ! k = 1, nrays
8377         ENDDO ! i = 1, ntrack
8378      ENDIF ! plant_canopy
8379
8380      IF ( .NOT. (rad_angular_discretization  .AND.  calc_svf) )  THEN
8381!
8382!--      Just update lowest_free_ray according to horizon
8383         DO WHILE ( lowest_free_ray > 0 )
8384            IF ( zdirs(lowest_free_ray) > horizon )  EXIT
8385            lowest_free_ray = lowest_free_ray - 1
8386         ENDDO
8387      ENDIF
8388
8389   CONTAINS
8390
8391      SUBROUTINE request_itarget( d, z, y, x, isurfl, iproc )
8392
8393         INTEGER(iwp), INTENT(in)            ::  d, z, y, x
8394         INTEGER(iwp), TARGET, INTENT(out)   ::  isurfl
8395         INTEGER(iwp), INTENT(out)           ::  iproc
8396#if defined( __parallel )
8397#else
8398         INTEGER(iwp)                        ::  target_displ  !< index of the grid in the local gridsurf array
8399#endif
8400         INTEGER(iwp)                        ::  px, py        !< number of processors in x and y direction
8401                                                               !< before the processor in the question
8402#if defined( __parallel )
8403         INTEGER(KIND=MPI_ADDRESS_KIND)      ::  target_displ  !< index of the grid in the local gridsurf array
8404
8405!
8406!--      Calculate target processor and index in the remote local target gridsurf array
8407         px = x / nnx
8408         py = y / nny
8409         iproc = px * pdims(2) + py
8410         target_displ = ((x-px*nnx) * nny + y - py*nny ) * nz_urban * nsurf_type_u +&
8411                        ( z-nz_urban_b ) * nsurf_type_u + d
8412!
8413!--      Send MPI_Get request to obtain index target_surfl(i)
8414         CALL MPI_GET( isurfl, 1, MPI_INTEGER, iproc, target_displ,            &
8415                       1, MPI_INTEGER, win_gridsurf, ierr)
8416         IF ( ierr /= 0 )  THEN
8417            WRITE( 9,* ) 'Error MPI_Get3:', ierr, isurfl, iproc, target_displ, &
8418                         win_gridsurf
8419            FLUSH( 9 )
8420         ENDIF
8421#else
8422!--      set index target_surfl(i)
8423         isurfl = gridsurf(d,z,y,x)
8424#endif
8425
8426      END SUBROUTINE request_itarget
8427
8428   END SUBROUTINE raytrace_2d
8429 
8430
8431!------------------------------------------------------------------------------!
8432!
8433! Description:
8434! ------------
8435!> Calculates apparent solar positions for all timesteps and stores discretized
8436!> positions.
8437!------------------------------------------------------------------------------!
8438   SUBROUTINE radiation_presimulate_solar_pos
8439
8440      IMPLICIT NONE
8441
8442      INTEGER(iwp)                              ::  it, i, j
8443      INTEGER(iwp)                              ::  day_of_month_prev,month_of_year_prev
8444      REAL(wp)                                  ::  tsrp_prev
8445      REAL(wp)                                  ::  simulated_time_prev
8446      REAL(wp), DIMENSION(:,:), ALLOCATABLE     ::  dsidir_tmp       !< dsidir_tmp[:,i] = unit vector of i-th
8447                                                                     !< appreant solar direction
8448
8449      ALLOCATE ( dsidir_rev(0:raytrace_discrete_elevs/2-1,                 &
8450                            0:raytrace_discrete_azims-1) )
8451      dsidir_rev(:,:) = -1
8452      ALLOCATE ( dsidir_tmp(3,                                             &
8453                     raytrace_discrete_elevs/2*raytrace_discrete_azims) )
8454      ndsidir = 0
8455
8456!
8457!--   We will artificialy update time_since_reference_point and return to
8458!--   true value later
8459      tsrp_prev = time_since_reference_point
8460      simulated_time_prev = simulated_time
8461      day_of_month_prev = day_of_month
8462      month_of_year_prev = month_of_year
8463      sun_direction = .TRUE.
8464
8465!
8466!--   initialize the simulated_time
8467      simulated_time = 0._wp
8468!
8469!--   Process spinup time if configured
8470      IF ( spinup_time > 0._wp )  THEN
8471         DO  it = 0, CEILING(spinup_time / dt_spinup)
8472            time_since_reference_point = -spinup_time + REAL(it, wp) * dt_spinup
8473            simulated_time = simulated_time + dt_spinup
8474            CALL simulate_pos
8475         ENDDO
8476      ENDIF
8477!
8478!--   Process simulation time
8479      DO  it = 0, CEILING(( end_time - spinup_time ) / dt_radiation)
8480         time_since_reference_point = REAL(it, wp) * dt_radiation
8481         simulated_time = simulated_time + dt_radiation
8482         CALL simulate_pos
8483      ENDDO
8484!
8485!--   Return date and time to its original values
8486      time_since_reference_point = tsrp_prev
8487      simulated_time = simulated_time_prev
8488      day_of_month = day_of_month_prev
8489      month_of_year = month_of_year_prev
8490      CALL init_date_and_time
8491
8492!--   Allocate global vars which depend on ndsidir
8493      ALLOCATE ( dsidir ( 3, ndsidir ) )
8494      dsidir(:,:) = dsidir_tmp(:, 1:ndsidir)
8495      DEALLOCATE ( dsidir_tmp )
8496
8497      ALLOCATE ( dsitrans(nsurfl, ndsidir) )
8498      ALLOCATE ( dsitransc(npcbl, ndsidir) )
8499      IF ( nmrtbl > 0 )  ALLOCATE ( mrtdsit(nmrtbl, ndsidir) )
8500
8501      WRITE ( message_string, * ) 'Precalculated', ndsidir, ' solar positions', &
8502                                  ' from', it, ' timesteps.'
8503      CALL message( 'radiation_presimulate_solar_pos', 'UI0013', 0, 0, 0, 6, 0 )
8504
8505      CONTAINS
8506
8507      !------------------------------------------------------------------------!
8508      ! Description:
8509      ! ------------
8510      !> Simuates a single position
8511      !------------------------------------------------------------------------!
8512      SUBROUTINE simulate_pos
8513         IMPLICIT NONE
8514!
8515!--      Update apparent solar position based on modified t_s_r_p
8516         CALL calc_zenith
8517         IF ( cos_zenith > 0 )  THEN
8518!--         
8519!--         Identify solar direction vector (discretized number) 1)
8520            i = MODULO(NINT(ATAN2(sun_dir_lon, sun_dir_lat)               &
8521                            / (2._wp*pi) * raytrace_discrete_azims-.5_wp, iwp), &
8522                       raytrace_discrete_azims)
8523            j = FLOOR(ACOS(cos_zenith) / pi * raytrace_discrete_elevs)
8524            IF ( dsidir_rev(j, i) == -1 )  THEN
8525               ndsidir = ndsidir + 1
8526               dsidir_tmp(:, ndsidir) =                                              &
8527                     (/ COS((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs), &
8528                        SIN((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs)  &
8529                      * COS((REAL(i,wp)+.5_wp) * 2_wp*pi / raytrace_discrete_azims), &
8530                        SIN((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs)  &
8531                      * SIN((REAL(i,wp)+.5_wp) * 2_wp*pi / raytrace_discrete_azims) /)
8532               dsidir_rev(j, i) = ndsidir
8533            ENDIF
8534         ENDIF
8535      END SUBROUTINE simulate_pos
8536
8537   END SUBROUTINE radiation_presimulate_solar_pos
8538
8539
8540
8541!------------------------------------------------------------------------------!
8542! Description:
8543! ------------
8544!> Determines whether two faces are oriented towards each other. Since the
8545!> surfaces follow the gird box surfaces, it checks first whether the two surfaces
8546!> are directed in the same direction, then it checks if the two surfaces are
8547!> located in confronted direction but facing away from each other, e.g. <--| |-->
8548!------------------------------------------------------------------------------!
8549    PURE LOGICAL FUNCTION surface_facing(x, y, z, d, x2, y2, z2, d2)
8550        IMPLICIT NONE
8551        INTEGER(iwp),   INTENT(in)  :: x, y, z, d, x2, y2, z2, d2
8552     
8553        surface_facing = .FALSE.
8554
8555!-- first check: are the two surfaces directed in the same direction
8556        IF ( (d==iup_u  .OR.  d==iup_l )                             &
8557             .AND. (d2==iup_u  .OR. d2==iup_l) ) RETURN
8558        IF ( (d==isouth_u  .OR.  d==isouth_l ) &
8559             .AND.  (d2==isouth_u  .OR.  d2==isouth_l) ) RETURN
8560        IF ( (d==inorth_u  .OR.  d==inorth_l ) &
8561             .AND.  (d2==inorth_u  .OR.  d2==inorth_l) ) RETURN
8562        IF ( (d==iwest_u  .OR.  d==iwest_l )     &
8563             .AND.  (d2==iwest_u  .OR.  d2==iwest_l ) ) RETURN
8564        IF ( (d==ieast_u  .OR.  d==ieast_l )     &
8565             .AND.  (d2==ieast_u  .OR.  d2==ieast_l ) ) RETURN
8566
8567!-- second check: are surfaces facing away from each other
8568        SELECT CASE (d)
8569            CASE (iup_u, iup_l)                     !< upward facing surfaces
8570                IF ( z2 < z ) RETURN
8571            CASE (isouth_u, isouth_l)               !< southward facing surfaces
8572                IF ( y2 > y ) RETURN
8573            CASE (inorth_u, inorth_l)               !< northward facing surfaces
8574                IF ( y2 < y ) RETURN
8575            CASE (iwest_u, iwest_l)                 !< westward facing surfaces
8576                IF ( x2 > x ) RETURN
8577            CASE (ieast_u, ieast_l)                 !< eastward facing surfaces
8578                IF ( x2 < x ) RETURN
8579        END SELECT
8580
8581        SELECT CASE (d2)
8582            CASE (iup_u)                            !< ground, roof
8583                IF ( z < z2 ) RETURN
8584            CASE (isouth_u, isouth_l)               !< south facing
8585                IF ( y > y2 ) RETURN
8586            CASE (inorth_u, inorth_l)               !< north facing
8587                IF ( y < y2 ) RETURN
8588            CASE (iwest_u, iwest_l)                 !< west facing
8589                IF ( x > x2 ) RETURN
8590            CASE (ieast_u, ieast_l)                 !< east facing
8591                IF ( x < x2 ) RETURN
8592            CASE (-1)
8593                CONTINUE
8594        END SELECT
8595
8596        surface_facing = .TRUE.
8597       
8598    END FUNCTION surface_facing
8599
8600
8601!------------------------------------------------------------------------------!
8602!
8603! Description:
8604! ------------
8605!> Reads svf, svfsurf, csf, csfsurf and mrt factors data from saved file
8606!> SVF means sky view factors and CSF means canopy sink factors
8607!------------------------------------------------------------------------------!
8608    SUBROUTINE radiation_read_svf
8609
8610       IMPLICIT NONE
8611       
8612       CHARACTER(rad_version_len)   :: rad_version_field
8613       
8614       INTEGER(iwp)                 :: i
8615       INTEGER(iwp)                 :: ndsidir_from_file = 0
8616       INTEGER(iwp)                 :: npcbl_from_file = 0
8617       INTEGER(iwp)                 :: nsurfl_from_file = 0
8618       INTEGER(iwp)                 :: nmrtbl_from_file = 0
8619
8620
8621       CALL location_message( 'reading view factors for radiation interaction', 'start' )
8622
8623       DO  i = 0, io_blocks-1
8624          IF ( i == io_group )  THEN
8625
8626!
8627!--          numprocs_previous_run is only known in case of reading restart
8628!--          data. If a new initial run which reads svf data is started the
8629!--          following query will be skipped
8630             IF ( initializing_actions == 'read_restart_data' ) THEN
8631
8632                IF ( numprocs_previous_run /= numprocs ) THEN
8633                   WRITE( message_string, * ) 'A different number of ',        &
8634                                              'processors between the run ',   &
8635                                              'that has written the svf data ',&
8636                                              'and the one that will read it ',&
8637                                              'is not allowed' 
8638                   CALL message( 'check_open', 'PA0491', 1, 2, 0, 6, 0 )
8639                ENDIF
8640
8641             ENDIF
8642             
8643!
8644!--          Open binary file
8645             CALL check_open( 88 )
8646
8647!
8648!--          read and check version
8649             READ ( 88 ) rad_version_field
8650             IF ( TRIM(rad_version_field) /= TRIM(rad_version) )  THEN
8651                 WRITE( message_string, * ) 'Version of binary SVF file "',    &
8652                             TRIM(rad_version_field), '" does not match ',     &
8653                             'the version of model "', TRIM(rad_version), '"'
8654                 CALL message( 'radiation_read_svf', 'PA0482', 1, 2, 0, 6, 0 )
8655             ENDIF
8656             
8657!
8658!--          read nsvfl, ncsfl, nsurfl, nmrtf
8659             READ ( 88 ) nsvfl, ncsfl, nsurfl_from_file, npcbl_from_file,      &
8660                         ndsidir_from_file, nmrtbl_from_file, nmrtf
8661             
8662             IF ( nsvfl < 0  .OR.  ncsfl < 0 )  THEN
8663                 WRITE( message_string, * ) 'Wrong number of SVF or CSF'
8664                 CALL message( 'radiation_read_svf', 'PA0483', 1, 2, 0, 6, 0 )
8665             ELSE
8666                 WRITE(debug_string,*)   'Number of SVF, CSF, and nsurfl ',    &
8667                                         'to read', nsvfl, ncsfl,              &
8668                                         nsurfl_from_file
8669                 IF ( debug_output )  CALL debug_message( debug_string, 'info' )
8670             ENDIF
8671             
8672             IF ( nsurfl_from_file /= nsurfl )  THEN
8673                 WRITE( message_string, * ) 'nsurfl from SVF file does not ',  &
8674                                            'match calculated nsurfl from ',   &
8675                                            'radiation_interaction_init'
8676                 CALL message( 'radiation_read_svf', 'PA0490', 1, 2, 0, 6, 0 )
8677             ENDIF
8678             
8679             IF ( npcbl_from_file /= npcbl )  THEN
8680                 WRITE( message_string, * ) 'npcbl from SVF file does not ',   &
8681                                            'match calculated npcbl from ',    &
8682                                            'radiation_interaction_init'
8683                 CALL message( 'radiation_read_svf', 'PA0493', 1, 2, 0, 6, 0 )
8684             ENDIF
8685             
8686             IF ( ndsidir_from_file /= ndsidir )  THEN
8687                 WRITE( message_string, * ) 'ndsidir from SVF file does not ', &
8688                                            'match calculated ndsidir from ',  &
8689                                            'radiation_presimulate_solar_pos'
8690                 CALL message( 'radiation_read_svf', 'PA0494', 1, 2, 0, 6, 0 )
8691             ENDIF
8692             IF ( nmrtbl_from_file /= nmrtbl )  THEN
8693                 WRITE( message_string, * ) 'nmrtbl from SVF file does not ',  &
8694                                            'match calculated nmrtbl from ',   &
8695                                            'radiation_interaction_init'
8696                 CALL message( 'radiation_read_svf', 'PA0494', 1, 2, 0, 6, 0 )
8697             ELSE
8698                 WRITE(debug_string,*) 'Number of nmrtf to read ', nmrtf
8699                 IF ( debug_output )  CALL debug_message( debug_string, 'info' )
8700             ENDIF
8701             
8702!
8703!--          Arrays skyvf, skyvft, dsitrans and dsitransc are allready
8704!--          allocated in radiation_interaction_init and
8705!--          radiation_presimulate_solar_pos
8706             IF ( nsurfl > 0 )  THEN
8707                READ(88) skyvf
8708                READ(88) skyvft
8709                READ(88) dsitrans 
8710             ENDIF
8711             
8712             IF ( plant_canopy  .AND.  npcbl > 0 ) THEN
8713                READ ( 88 )  dsitransc
8714             ENDIF
8715             
8716!
8717!--          The allocation of svf, svfsurf, csf, csfsurf, mrtf, mrtft, and
8718!--          mrtfsurf happens in routine radiation_calc_svf which is not
8719!--          called if the program enters radiation_read_svf. Therefore
8720!--          these arrays has to allocate in the following
8721             IF ( nsvfl > 0 )  THEN
8722                ALLOCATE( svf(ndsvf,nsvfl) )
8723                ALLOCATE( svfsurf(idsvf,nsvfl) )
8724                READ(88) svf
8725                READ(88) svfsurf
8726             ENDIF
8727
8728             IF ( plant_canopy  .AND.  ncsfl > 0 )  THEN
8729                ALLOCATE( csf(ndcsf,ncsfl) )
8730                ALLOCATE( csfsurf(idcsf,ncsfl) )
8731                READ(88) csf
8732                READ(88) csfsurf
8733             ENDIF
8734
8735             IF ( nmrtbl > 0 )  THEN
8736                READ(88) mrtsky
8737                READ(88) mrtskyt
8738                READ(88) mrtdsit
8739             ENDIF
8740
8741             IF ( nmrtf > 0 )  THEN
8742                ALLOCATE ( mrtf(nmrtf) )
8743                ALLOCATE ( mrtft(nmrtf) )
8744                ALLOCATE ( mrtfsurf(2,nmrtf) )
8745                READ(88) mrtf
8746                READ(88) mrtft
8747                READ(88) mrtfsurf
8748             ENDIF
8749             
8750!
8751!--          Close binary file                 
8752             CALL close_file( 88 )
8753               
8754          ENDIF
8755#if defined( __parallel )
8756          CALL MPI_BARRIER( comm2d, ierr )
8757#endif
8758       ENDDO
8759
8760       CALL location_message( 'reading view factors for radiation interaction', 'finished' )
8761
8762
8763    END SUBROUTINE radiation_read_svf
8764
8765
8766!------------------------------------------------------------------------------!
8767!
8768! Description:
8769! ------------
8770!> Subroutine stores svf, svfsurf, csf, csfsurf and mrt data to a file.
8771!------------------------------------------------------------------------------!
8772    SUBROUTINE radiation_write_svf
8773
8774       IMPLICIT NONE
8775       
8776       INTEGER(iwp)        :: i
8777
8778
8779       CALL location_message( 'writing view factors for radiation interaction', 'start' )
8780
8781       DO  i = 0, io_blocks-1
8782          IF ( i == io_group )  THEN
8783!
8784!--          Open binary file
8785             CALL check_open( 89 )
8786
8787             WRITE ( 89 )  rad_version
8788             WRITE ( 89 )  nsvfl, ncsfl, nsurfl, npcbl, ndsidir, nmrtbl, nmrtf
8789             IF ( nsurfl > 0 ) THEN
8790                WRITE ( 89 )  skyvf
8791                WRITE ( 89 )  skyvft
8792                WRITE ( 89 )  dsitrans
8793             ENDIF
8794             IF ( npcbl > 0 ) THEN
8795                WRITE ( 89 )  dsitransc
8796             ENDIF
8797             IF ( nsvfl > 0 ) THEN
8798                WRITE ( 89 )  svf
8799                WRITE ( 89 )  svfsurf
8800             ENDIF
8801             IF ( plant_canopy  .AND.  ncsfl > 0 )  THEN
8802                 WRITE ( 89 )  csf
8803                 WRITE ( 89 )  csfsurf
8804             ENDIF
8805             IF ( nmrtbl > 0 )  THEN
8806                WRITE ( 89 ) mrtsky
8807                WRITE ( 89 ) mrtskyt
8808                WRITE ( 89 ) mrtdsit
8809             ENDIF
8810             IF ( nmrtf > 0 )  THEN
8811                 WRITE ( 89 )  mrtf
8812                 WRITE ( 89 )  mrtft               
8813                 WRITE ( 89 )  mrtfsurf
8814             ENDIF
8815!
8816!--          Close binary file                 
8817             CALL close_file( 89 )
8818
8819          ENDIF
8820#if defined( __parallel )
8821          CALL MPI_BARRIER( comm2d, ierr )
8822#endif
8823       ENDDO
8824
8825       CALL location_message( 'writing view factors for radiation interaction', 'finished' )
8826
8827
8828    END SUBROUTINE radiation_write_svf
8829
8830
8831!------------------------------------------------------------------------------!
8832!
8833! Description:
8834! ------------
8835!> Block of auxiliary subroutines:
8836!> 1. quicksort and corresponding comparison
8837!> 2. merge_and_grow_csf for implementation of "dynamical growing"
8838!>    array for csf
8839!------------------------------------------------------------------------------!
8840!-- quicksort.f -*-f90-*-
8841!-- Author: t-nissie, adaptation J.Resler
8842!-- License: GPLv3
8843!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8844    RECURSIVE SUBROUTINE quicksort_itarget(itarget, vffrac, ztransp, first, last)
8845        IMPLICIT NONE
8846        INTEGER(iwp), DIMENSION(:), INTENT(INOUT)   :: itarget
8847        REAL(wp), DIMENSION(:), INTENT(INOUT)       :: vffrac, ztransp
8848        INTEGER(iwp), INTENT(IN)                    :: first, last
8849        INTEGER(iwp)                                :: x, t
8850        INTEGER(iwp)                                :: i, j
8851        REAL(wp)                                    :: tr
8852
8853        IF ( first>=last ) RETURN
8854        x = itarget((first+last)/2)
8855        i = first
8856        j = last
8857        DO
8858            DO WHILE ( itarget(i) < x )
8859               i=i+1
8860            ENDDO
8861            DO WHILE ( x < itarget(j) )
8862                j=j-1
8863            ENDDO
8864            IF ( i >= j ) EXIT
8865            t = itarget(i);  itarget(i) = itarget(j);  itarget(j) = t
8866            tr = vffrac(i);  vffrac(i) = vffrac(j);  vffrac(j) = tr
8867            tr = ztransp(i);  ztransp(i) = ztransp(j);  ztransp(j) = tr
8868            i=i+1
8869            j=j-1
8870        ENDDO
8871        IF ( first < i-1 ) CALL quicksort_itarget(itarget, vffrac, ztransp, first, i-1)
8872        IF ( j+1 < last )  CALL quicksort_itarget(itarget, vffrac, ztransp, j+1, last)
8873    END SUBROUTINE quicksort_itarget
8874
8875    PURE FUNCTION svf_lt(svf1,svf2) result (res)
8876      TYPE (t_svf), INTENT(in) :: svf1,svf2
8877      LOGICAL                  :: res
8878      IF ( svf1%isurflt < svf2%isurflt  .OR.    &
8879          (svf1%isurflt == svf2%isurflt  .AND.  svf1%isurfs < svf2%isurfs) )  THEN
8880          res = .TRUE.
8881      ELSE
8882          res = .FALSE.
8883      ENDIF
8884    END FUNCTION svf_lt
8885
8886
8887!-- quicksort.f -*-f90-*-
8888!-- Author: t-nissie, adaptation J.Resler
8889!-- License: GPLv3
8890!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8891    RECURSIVE SUBROUTINE quicksort_svf(svfl, first, last)
8892        IMPLICIT NONE
8893        TYPE(t_svf), DIMENSION(:), INTENT(INOUT)  :: svfl
8894        INTEGER(iwp), INTENT(IN)                  :: first, last
8895        TYPE(t_svf)                               :: x, t
8896        INTEGER(iwp)                              :: i, j
8897
8898        IF ( first>=last ) RETURN
8899        x = svfl( (first+last) / 2 )
8900        i = first
8901        j = last
8902        DO
8903            DO while ( svf_lt(svfl(i),x) )
8904               i=i+1
8905            ENDDO
8906            DO while ( svf_lt(x,svfl(j)) )
8907                j=j-1
8908            ENDDO
8909            IF ( i >= j ) EXIT
8910            t = svfl(i);  svfl(i) = svfl(j);  svfl(j) = t
8911            i=i+1
8912            j=j-1
8913        ENDDO
8914        IF ( first < i-1 ) CALL quicksort_svf(svfl, first, i-1)
8915        IF ( j+1 < last )  CALL quicksort_svf(svfl, j+1, last)
8916    END SUBROUTINE quicksort_svf
8917
8918    PURE FUNCTION csf_lt(csf1,csf2) result (res)
8919      TYPE (t_csf), INTENT(in) :: csf1,csf2
8920      LOGICAL                  :: res
8921      IF ( csf1%ip < csf2%ip  .OR.    &
8922           (csf1%ip == csf2%ip  .AND.  csf1%itx < csf2%itx)  .OR.  &
8923           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity < csf2%ity)  .OR.  &
8924           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity == csf2%ity  .AND.   &
8925            csf1%itz < csf2%itz)  .OR.  &
8926           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity == csf2%ity  .AND.   &
8927            csf1%itz == csf2%itz  .AND.  csf1%isurfs < csf2%isurfs) )  THEN
8928          res = .TRUE.
8929      ELSE
8930          res = .FALSE.
8931      ENDIF
8932    END FUNCTION csf_lt
8933
8934
8935!-- quicksort.f -*-f90-*-
8936!-- Author: t-nissie, adaptation J.Resler
8937!-- License: GPLv3
8938!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8939    RECURSIVE SUBROUTINE quicksort_csf(csfl, first, last)
8940        IMPLICIT NONE
8941        TYPE(t_csf), DIMENSION(:), INTENT(INOUT)  :: csfl
8942        INTEGER(iwp), INTENT(IN)                  :: first, last
8943        TYPE(t_csf)                               :: x, t
8944        INTEGER(iwp)                              :: i, j
8945
8946        IF ( first>=last ) RETURN
8947        x = csfl( (first+last)/2 )
8948        i = first
8949        j = last
8950        DO
8951            DO while ( csf_lt(csfl(i),x) )
8952                i=i+1
8953            ENDDO
8954            DO while ( csf_lt(x,csfl(j)) )
8955                j=j-1
8956            ENDDO
8957            IF ( i >= j ) EXIT
8958            t = csfl(i);  csfl(i) = csfl(j);  csfl(j) = t
8959            i=i+1
8960            j=j-1
8961        ENDDO
8962        IF ( first < i-1 ) CALL quicksort_csf(csfl, first, i-1)
8963        IF ( j+1 < last )  CALL quicksort_csf(csfl, j+1, last)
8964    END SUBROUTINE quicksort_csf
8965
8966   
8967!------------------------------------------------------------------------------!
8968!
8969! Description:
8970! ------------
8971!> Grows the CSF array exponentially after it is full. During that, the ray
8972!> canopy sink factors with common source face and target plant canopy grid
8973!> cell are merged together so that the size doesn't grow out of control.
8974!------------------------------------------------------------------------------!
8975    SUBROUTINE merge_and_grow_csf(newsize)
8976        INTEGER(iwp), INTENT(in)                :: newsize  !< new array size after grow, must be >= ncsfl
8977                                                            !< or -1 to shrink to minimum
8978        INTEGER(iwp)                            :: iread, iwrite
8979        TYPE(t_csf), DIMENSION(:), POINTER      :: acsfnew
8980
8981
8982        IF ( newsize == -1 )  THEN
8983!--         merge in-place
8984            acsfnew => acsf
8985        ELSE
8986!--         allocate new array
8987            IF ( mcsf == 0 )  THEN
8988                ALLOCATE( acsf1(newsize) )
8989                acsfnew => acsf1
8990            ELSE
8991                ALLOCATE( acsf2(newsize) )
8992                acsfnew => acsf2
8993            ENDIF
8994        ENDIF
8995
8996        IF ( ncsfl >= 1 )  THEN
8997!--         sort csf in place (quicksort)
8998            CALL quicksort_csf(acsf,1,ncsfl)
8999
9000!--         while moving to a new array, aggregate canopy sink factor records with identical box & source
9001            acsfnew(1) = acsf(1)
9002            iwrite = 1
9003            DO iread = 2, ncsfl
9004!--             here acsf(kcsf) already has values from acsf(icsf)
9005                IF ( acsfnew(iwrite)%itx == acsf(iread)%itx &
9006                         .AND.  acsfnew(iwrite)%ity == acsf(iread)%ity &
9007                         .AND.  acsfnew(iwrite)%itz == acsf(iread)%itz &
9008                         .AND.  acsfnew(iwrite)%isurfs == acsf(iread)%isurfs )  THEN
9009
9010                    acsfnew(iwrite)%rcvf = acsfnew(iwrite)%rcvf + acsf(iread)%rcvf
9011!--                 advance reading index, keep writing index
9012                ELSE
9013!--                 not identical, just advance and copy
9014                    iwrite = iwrite + 1
9015                    acsfnew(iwrite) = acsf(iread)
9016                ENDIF
9017            ENDDO
9018            ncsfl = iwrite
9019        ENDIF
9020
9021        IF ( newsize == -1 )  THEN
9022!--         allocate new array and copy shrinked data
9023            IF ( mcsf == 0 )  THEN
9024                ALLOCATE( acsf1(ncsfl) )
9025                acsf1(1:ncsfl) = acsf2(1:ncsfl)
9026            ELSE
9027                ALLOCATE( acsf2(ncsfl) )
9028                acsf2(1:ncsfl) = acsf1(1:ncsfl)
9029            ENDIF
9030        ENDIF
9031
9032!--     deallocate old array
9033        IF ( mcsf == 0 )  THEN
9034            mcsf = 1
9035            acsf => acsf1
9036            DEALLOCATE( acsf2 )
9037        ELSE
9038            mcsf = 0
9039            acsf => acsf2
9040            DEALLOCATE( acsf1 )
9041        ENDIF
9042        ncsfla = newsize
9043
9044        IF ( debug_output )  THEN
9045           WRITE( debug_string, '(A,2I12)' ) 'Grow acsf2:', ncsfl, ncsfla
9046           CALL debug_message( debug_string, 'info' )
9047        ENDIF
9048
9049    END SUBROUTINE merge_and_grow_csf
9050
9051   
9052!-- quicksort.f -*-f90-*-
9053!-- Author: t-nissie, adaptation J.Resler
9054!-- License: GPLv3
9055!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
9056    RECURSIVE SUBROUTINE quicksort_csf2(kpcsflt, pcsflt, first, last)
9057        IMPLICIT NONE
9058        INTEGER(iwp), DIMENSION(:,:), INTENT(INOUT)  :: kpcsflt
9059        REAL(wp), DIMENSION(:,:), INTENT(INOUT)      :: pcsflt
9060        INTEGER(iwp), INTENT(IN)                     :: first, last
9061        REAL(wp), DIMENSION(ndcsf)                   :: t2
9062        INTEGER(iwp), DIMENSION(kdcsf)               :: x, t1
9063        INTEGER(iwp)                                 :: i, j
9064
9065        IF ( first>=last ) RETURN
9066        x = kpcsflt(:, (first+last)/2 )
9067        i = first
9068        j = last
9069        DO
9070            DO while ( csf_lt2(kpcsflt(:,i),x) )
9071                i=i+1
9072            ENDDO
9073            DO while ( csf_lt2(x,kpcsflt(:,j)) )
9074                j=j-1
9075            ENDDO
9076            IF ( i >= j ) EXIT
9077            t1 = kpcsflt(:,i);  kpcsflt(:,i) = kpcsflt(:,j);  kpcsflt(:,j) = t1
9078            t2 = pcsflt(:,i);  pcsflt(:,i) = pcsflt(:,j);  pcsflt(:,j) = t2
9079            i=i+1
9080            j=j-1
9081        ENDDO
9082        IF ( first < i-1 ) CALL quicksort_csf2(kpcsflt, pcsflt, first, i-1)
9083        IF ( j+1 < last )  CALL quicksort_csf2(kpcsflt, pcsflt, j+1, last)
9084    END SUBROUTINE quicksort_csf2
9085   
9086
9087    PURE FUNCTION csf_lt2(item1, item2) result(res)
9088        INTEGER(iwp), DIMENSION(kdcsf), INTENT(in)  :: item1, item2
9089        LOGICAL                                     :: res
9090        res = ( (item1(3) < item2(3))                                                        &
9091             .OR.  (item1(3) == item2(3)  .AND.  item1(2) < item2(2))                            &
9092             .OR.  (item1(3) == item2(3)  .AND.  item1(2) == item2(2)  .AND.  item1(1) < item2(1)) &
9093             .OR.  (item1(3) == item2(3)  .AND.  item1(2) == item2(2)  .AND.  item1(1) == item2(1) &
9094                 .AND.  item1(4) < item2(4)) )
9095    END FUNCTION csf_lt2
9096
9097    PURE FUNCTION searchsorted(athresh, val) result(ind)
9098        REAL(wp), DIMENSION(:), INTENT(IN)  :: athresh
9099        REAL(wp), INTENT(IN)                :: val
9100        INTEGER(iwp)                        :: ind
9101        INTEGER(iwp)                        :: i
9102
9103        DO i = LBOUND(athresh, 1), UBOUND(athresh, 1)
9104            IF ( val < athresh(i) ) THEN
9105                ind = i - 1
9106                RETURN
9107            ENDIF
9108        ENDDO
9109        ind = UBOUND(athresh, 1)
9110    END FUNCTION searchsorted
9111
9112
9113!------------------------------------------------------------------------------!
9114!
9115! Description:
9116! ------------
9117!> Subroutine for averaging 3D data
9118!------------------------------------------------------------------------------!
9119SUBROUTINE radiation_3d_data_averaging( mode, variable )
9120 
9121
9122    USE control_parameters
9123
9124    USE indices
9125
9126    USE kinds
9127
9128    IMPLICIT NONE
9129
9130    CHARACTER (LEN=*) ::  mode    !<
9131    CHARACTER (LEN=*) :: variable !<
9132
9133    LOGICAL      ::  match_lsm !< flag indicating natural-type surface
9134    LOGICAL      ::  match_usm !< flag indicating urban-type surface
9135   
9136    INTEGER(iwp) ::  i !<
9137    INTEGER(iwp) ::  j !<
9138    INTEGER(iwp) ::  k !<
9139    INTEGER(iwp) ::  l, m !< index of current surface element
9140
9141    INTEGER(iwp)                                       :: ids, idsint_u, idsint_l, isurf
9142    CHARACTER(LEN=varnamelength)                       :: var
9143
9144!-- find the real name of the variable
9145    ids = -1
9146    l = -1
9147    var = TRIM(variable)
9148    DO i = 0, nd-1
9149        k = len(TRIM(var))
9150        j = len(TRIM(dirname(i)))
9151        IF ( k-j+1 >= 1_iwp ) THEN
9152           IF ( TRIM(var(k-j+1:k)) == TRIM(dirname(i)) )  THEN
9153               ids = i
9154               idsint_u = dirint_u(ids)
9155               idsint_l = dirint_l(ids)
9156               var = var(:k-j)
9157               EXIT
9158           ENDIF
9159        ENDIF
9160    ENDDO
9161    IF ( ids == -1 )  THEN
9162        var = TRIM(variable)
9163    ENDIF
9164
9165    IF ( mode == 'allocate' )  THEN
9166
9167       SELECT CASE ( TRIM( var ) )
9168!--          block of large scale (e.g. RRTMG) radiation output variables
9169             CASE ( 'rad_net*' )
9170                IF ( .NOT. ALLOCATED( rad_net_av ) )  THEN
9171                   ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
9172                ENDIF
9173                rad_net_av = 0.0_wp
9174             
9175             CASE ( 'rad_lw_in*' )
9176                IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) )  THEN
9177                   ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
9178                ENDIF
9179                rad_lw_in_xy_av = 0.0_wp
9180               
9181             CASE ( 'rad_lw_out*' )
9182                IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) )  THEN
9183                   ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
9184                ENDIF
9185                rad_lw_out_xy_av = 0.0_wp
9186               
9187             CASE ( 'rad_sw_in*' )
9188                IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) )  THEN
9189                   ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
9190                ENDIF
9191                rad_sw_in_xy_av = 0.0_wp
9192               
9193             CASE ( 'rad_sw_out*' )
9194                IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) )  THEN
9195                   ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
9196                ENDIF
9197                rad_sw_out_xy_av = 0.0_wp               
9198
9199             CASE ( 'rad_lw_in' )
9200                IF ( .NOT. ALLOCATED( rad_lw_in_av ) )  THEN
9201                   ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9202                ENDIF
9203                rad_lw_in_av = 0.0_wp
9204
9205             CASE ( 'rad_lw_out' )
9206                IF ( .NOT. ALLOCATED( rad_lw_out_av ) )  THEN
9207                   ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9208                ENDIF
9209                rad_lw_out_av = 0.0_wp
9210
9211             CASE ( 'rad_lw_cs_hr' )
9212                IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) )  THEN
9213                   ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9214                ENDIF
9215                rad_lw_cs_hr_av = 0.0_wp
9216
9217             CASE ( 'rad_lw_hr' )
9218                IF ( .NOT. ALLOCATED( rad_lw_hr_av ) )  THEN
9219                   ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9220                ENDIF
9221                rad_lw_hr_av = 0.0_wp
9222
9223             CASE ( 'rad_sw_in' )
9224                IF ( .NOT. ALLOCATED( rad_sw_in_av ) )  THEN
9225                   ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9226                ENDIF
9227                rad_sw_in_av = 0.0_wp
9228
9229             CASE ( 'rad_sw_out' )
9230                IF ( .NOT. ALLOCATED( rad_sw_out_av ) )  THEN
9231                   ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9232                ENDIF
9233                rad_sw_out_av = 0.0_wp
9234
9235             CASE ( 'rad_sw_cs_hr' )
9236                IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) )  THEN
9237                   ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9238                ENDIF
9239                rad_sw_cs_hr_av = 0.0_wp
9240
9241             CASE ( 'rad_sw_hr' )
9242                IF ( .NOT. ALLOCATED( rad_sw_hr_av ) )  THEN
9243                   ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9244                ENDIF
9245                rad_sw_hr_av = 0.0_wp
9246
9247!--          block of RTM output variables
9248             CASE ( 'rtm_rad_net' )
9249!--              array of complete radiation balance
9250                 IF ( .NOT.  ALLOCATED(surfradnet_av) )  THEN
9251                     ALLOCATE( surfradnet_av(nsurfl) )
9252                     surfradnet_av = 0.0_wp
9253                 ENDIF
9254
9255             CASE ( 'rtm_rad_insw' )
9256!--                 array of sw radiation falling to surface after i-th reflection
9257                 IF ( .NOT.  ALLOCATED(surfinsw_av) )  THEN
9258                     ALLOCATE( surfinsw_av(nsurfl) )
9259                     surfinsw_av = 0.0_wp
9260                 ENDIF
9261
9262             CASE ( 'rtm_rad_inlw' )
9263!--                 array of lw radiation falling to surface after i-th reflection
9264                 IF ( .NOT.  ALLOCATED(surfinlw_av) )  THEN
9265                     ALLOCATE( surfinlw_av(nsurfl) )
9266                     surfinlw_av = 0.0_wp
9267                 ENDIF
9268
9269             CASE ( 'rtm_rad_inswdir' )
9270!--                 array of direct sw radiation falling to surface from sun
9271                 IF ( .NOT.  ALLOCATED(surfinswdir_av) )  THEN
9272                     ALLOCATE( surfinswdir_av(nsurfl) )
9273                     surfinswdir_av = 0.0_wp
9274                 ENDIF
9275
9276             CASE ( 'rtm_rad_inswdif' )
9277!--                 array of difusion sw radiation falling to surface from sky and borders of the domain
9278                 IF ( .NOT.  ALLOCATED(surfinswdif_av) )  THEN
9279                     ALLOCATE( surfinswdif_av(nsurfl) )
9280                     surfinswdif_av = 0.0_wp
9281                 ENDIF
9282
9283             CASE ( 'rtm_rad_inswref' )
9284!--                 array of sw radiation falling to surface from reflections
9285                 IF ( .NOT.  ALLOCATED(surfinswref_av) )  THEN
9286                     ALLOCATE( surfinswref_av(nsurfl) )
9287                     surfinswref_av = 0.0_wp
9288                 ENDIF
9289
9290             CASE ( 'rtm_rad_inlwdif' )
9291!--                 array of sw radiation falling to surface after i-th reflection
9292                IF ( .NOT.  ALLOCATED(surfinlwdif_av) )  THEN
9293                     ALLOCATE( surfinlwdif_av(nsurfl) )
9294                     surfinlwdif_av = 0.0_wp
9295                 ENDIF
9296
9297             CASE ( 'rtm_rad_inlwref' )
9298!--                 array of lw radiation falling to surface from reflections
9299                 IF ( .NOT.  ALLOCATED(surfinlwref_av) )  THEN
9300                     ALLOCATE( surfinlwref_av(nsurfl) )
9301                     surfinlwref_av = 0.0_wp
9302                 ENDIF
9303
9304             CASE ( 'rtm_rad_outsw' )
9305!--                 array of sw radiation emitted from surface after i-th reflection
9306                 IF ( .NOT.  ALLOCATED(surfoutsw_av) )  THEN
9307                     ALLOCATE( surfoutsw_av(nsurfl) )
9308                     surfoutsw_av = 0.0_wp
9309                 ENDIF
9310
9311             CASE ( 'rtm_rad_outlw' )
9312!--                 array of lw radiation emitted from surface after i-th reflection
9313                 IF ( .NOT.  ALLOCATED(surfoutlw_av) )  THEN
9314                     ALLOCATE( surfoutlw_av(nsurfl) )
9315                     surfoutlw_av = 0.0_wp
9316                 ENDIF
9317             CASE ( 'rtm_rad_ressw' )
9318!--                 array of residua of sw radiation absorbed in surface after last reflection
9319                 IF ( .NOT.  ALLOCATED(surfins_av) )  THEN
9320                     ALLOCATE( surfins_av(nsurfl) )
9321                     surfins_av = 0.0_wp
9322                 ENDIF
9323
9324             CASE ( 'rtm_rad_reslw' )
9325!--                 array of residua of lw radiation absorbed in surface after last reflection
9326                 IF ( .NOT.  ALLOCATED(surfinl_av) )  THEN
9327                     ALLOCATE( surfinl_av(nsurfl) )
9328                     surfinl_av = 0.0_wp
9329                 ENDIF
9330
9331             CASE ( 'rtm_rad_pc_inlw' )
9332!--                 array of of lw radiation absorbed in plant canopy
9333                 IF ( .NOT.  ALLOCATED(pcbinlw_av) )  THEN
9334                     ALLOCATE( pcbinlw_av(1:npcbl) )
9335                     pcbinlw_av = 0.0_wp
9336                 ENDIF
9337
9338             CASE ( 'rtm_rad_pc_insw' )
9339!--                 array of of sw radiation absorbed in plant canopy
9340                 IF ( .NOT.  ALLOCATED(pcbinsw_av) )  THEN
9341                     ALLOCATE( pcbinsw_av(1:npcbl) )
9342                     pcbinsw_av = 0.0_wp
9343                 ENDIF
9344
9345             CASE ( 'rtm_rad_pc_inswdir' )
9346!--                 array of of direct sw radiation absorbed in plant canopy
9347                 IF ( .NOT.  ALLOCATED(pcbinswdir_av) )  THEN
9348                     ALLOCATE( pcbinswdir_av(1:npcbl) )
9349                     pcbinswdir_av = 0.0_wp
9350                 ENDIF
9351
9352             CASE ( 'rtm_rad_pc_inswdif' )
9353!--                 array of of diffuse sw radiation absorbed in plant canopy
9354                 IF ( .NOT.  ALLOCATED(pcbinswdif_av) )  THEN
9355                     ALLOCATE( pcbinswdif_av(1:npcbl) )
9356                     pcbinswdif_av = 0.0_wp
9357                 ENDIF
9358
9359             CASE ( 'rtm_rad_pc_inswref' )
9360!--                 array of of reflected sw radiation absorbed in plant canopy
9361                 IF ( .NOT.  ALLOCATED(pcbinswref_av) )  THEN
9362                     ALLOCATE( pcbinswref_av(1:npcbl) )
9363                     pcbinswref_av = 0.0_wp
9364                 ENDIF
9365
9366             CASE ( 'rtm_mrt_sw' )
9367                IF ( .NOT. ALLOCATED( mrtinsw_av ) )  THEN
9368                   ALLOCATE( mrtinsw_av(nmrtbl) )
9369                ENDIF
9370                mrtinsw_av = 0.0_wp
9371
9372             CASE ( 'rtm_mrt_lw' )
9373                IF ( .NOT. ALLOCATED( mrtinlw_av ) )  THEN
9374                   ALLOCATE( mrtinlw_av(nmrtbl) )
9375                ENDIF
9376                mrtinlw_av = 0.0_wp
9377
9378             CASE ( 'rtm_mrt' )
9379                IF ( .NOT. ALLOCATED( mrt_av ) )  THEN
9380                   ALLOCATE( mrt_av(nmrtbl) )
9381                ENDIF
9382                mrt_av = 0.0_wp
9383
9384          CASE DEFAULT
9385             CONTINUE
9386
9387       END SELECT
9388
9389    ELSEIF ( mode == 'sum' )  THEN
9390
9391       SELECT CASE ( TRIM( var ) )
9392!--       block of large scale (e.g. RRTMG) radiation output variables
9393          CASE ( 'rad_net*' )
9394             IF ( ALLOCATED( rad_net_av ) ) THEN
9395                DO  i = nxl, nxr
9396                   DO  j = nys, nyn
9397                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9398                                  surf_lsm_h%end_index(j,i)
9399                      match_usm = surf_usm_h%start_index(j,i) <=               &
9400                                  surf_usm_h%end_index(j,i)
9401
9402                     IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9403                         m = surf_lsm_h%end_index(j,i)
9404                         rad_net_av(j,i) = rad_net_av(j,i) +                   &
9405                                         surf_lsm_h%rad_net(m)
9406                      ELSEIF ( match_usm )  THEN
9407                         m = surf_usm_h%end_index(j,i)
9408                         rad_net_av(j,i) = rad_net_av(j,i) +                   &
9409                                         surf_usm_h%rad_net(m)
9410                      ENDIF
9411                   ENDDO
9412                ENDDO
9413             ENDIF
9414
9415          CASE ( 'rad_lw_in*' )
9416             IF ( ALLOCATED( rad_lw_in_xy_av ) ) THEN
9417                DO  i = nxl, nxr
9418                   DO  j = nys, nyn
9419                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9420                                  surf_lsm_h%end_index(j,i)
9421                      match_usm = surf_usm_h%start_index(j,i) <=               &
9422                                  surf_usm_h%end_index(j,i)
9423
9424                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9425                         m = surf_lsm_h%end_index(j,i)
9426                         rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i) +         &
9427                                         surf_lsm_h%rad_lw_in(m)
9428                      ELSEIF ( match_usm )  THEN
9429                         m = surf_usm_h%end_index(j,i)
9430                         rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i) +         &
9431                                         surf_usm_h%rad_lw_in(m)
9432                      ENDIF
9433                   ENDDO
9434                ENDDO
9435             ENDIF
9436             
9437          CASE ( 'rad_lw_out*' )
9438             IF ( ALLOCATED( rad_lw_out_xy_av ) ) THEN
9439                DO  i = nxl, nxr
9440                   DO  j = nys, nyn
9441                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9442                                  surf_lsm_h%end_index(j,i)
9443                      match_usm = surf_usm_h%start_index(j,i) <=               &
9444                                  surf_usm_h%end_index(j,i)
9445
9446                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9447                         m = surf_lsm_h%end_index(j,i)
9448                         rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i) +       &
9449                                                 surf_lsm_h%rad_lw_out(m)
9450                      ELSEIF ( match_usm )  THEN
9451                         m = surf_usm_h%end_index(j,i)
9452                         rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i) +       &
9453                                                 surf_usm_h%rad_lw_out(m)
9454                      ENDIF
9455                   ENDDO
9456                ENDDO
9457             ENDIF
9458             
9459          CASE ( 'rad_sw_in*' )
9460             IF ( ALLOCATED( rad_sw_in_xy_av ) ) THEN
9461                DO  i = nxl, nxr
9462                   DO  j = nys, nyn
9463                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9464                                  surf_lsm_h%end_index(j,i)
9465                      match_usm = surf_usm_h%start_index(j,i) <=               &
9466                                  surf_usm_h%end_index(j,i)
9467
9468                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9469                         m = surf_lsm_h%end_index(j,i)
9470                         rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i) +         &
9471                                                surf_lsm_h%rad_sw_in(m)
9472                      ELSEIF ( match_usm )  THEN
9473                         m = surf_usm_h%end_index(j,i)
9474                         rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i) +         &
9475                                                surf_usm_h%rad_sw_in(m)
9476                      ENDIF
9477                   ENDDO
9478                ENDDO
9479             ENDIF
9480             
9481          CASE ( 'rad_sw_out*' )
9482             IF ( ALLOCATED( rad_sw_out_xy_av ) ) THEN
9483                DO  i = nxl, nxr
9484                   DO  j = nys, nyn
9485                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9486                                  surf_lsm_h%end_index(j,i)
9487                      match_usm = surf_usm_h%start_index(j,i) <=               &
9488                                  surf_usm_h%end_index(j,i)
9489
9490                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9491                         m = surf_lsm_h%end_index(j,i)
9492                         rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i) +       &
9493                                                 surf_lsm_h%rad_sw_out(m)
9494                      ELSEIF ( match_usm )  THEN
9495                         m = surf_usm_h%end_index(j,i)
9496                         rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i) +       &
9497                                                 surf_usm_h%rad_sw_out(m)
9498                      ENDIF
9499                   ENDDO
9500                ENDDO
9501             ENDIF
9502             
9503          CASE ( 'rad_lw_in' )
9504             IF ( ALLOCATED( rad_lw_in_av ) ) THEN
9505                DO  i = nxlg, nxrg
9506                   DO  j = nysg, nyng
9507                      DO  k = nzb, nzt+1
9508                         rad_lw_in_av(k,j,i) = rad_lw_in_av(k,j,i)             &
9509                                               + rad_lw_in(k,j,i)
9510                      ENDDO
9511                   ENDDO
9512                ENDDO
9513             ENDIF
9514
9515          CASE ( 'rad_lw_out' )
9516             IF ( ALLOCATED( rad_lw_out_av ) ) THEN
9517                DO  i = nxlg, nxrg
9518                   DO  j = nysg, nyng
9519                      DO  k = nzb, nzt+1
9520                         rad_lw_out_av(k,j,i) = rad_lw_out_av(k,j,i)           &
9521                                                + rad_lw_out(k,j,i)
9522                      ENDDO
9523                   ENDDO
9524                ENDDO
9525             ENDIF
9526
9527          CASE ( 'rad_lw_cs_hr' )
9528             IF ( ALLOCATED( rad_lw_cs_hr_av ) ) THEN
9529                DO  i = nxlg, nxrg
9530                   DO  j = nysg, nyng
9531                      DO  k = nzb, nzt+1
9532                         rad_lw_cs_hr_av(k,j,i) = rad_lw_cs_hr_av(k,j,i)       &
9533                                                  + rad_lw_cs_hr(k,j,i)
9534                      ENDDO
9535                   ENDDO
9536                ENDDO
9537             ENDIF
9538
9539          CASE ( 'rad_lw_hr' )
9540             IF ( ALLOCATED( rad_lw_hr_av ) ) THEN
9541                DO  i = nxlg, nxrg
9542                   DO  j = nysg, nyng
9543                      DO  k = nzb, nzt+1
9544                         rad_lw_hr_av(k,j,i) = rad_lw_hr_av(k,j,i)             &
9545                                               + rad_lw_hr(k,j,i)
9546                      ENDDO
9547                   ENDDO
9548                ENDDO
9549             ENDIF
9550
9551          CASE ( 'rad_sw_in' )
9552             IF ( ALLOCATED( rad_sw_in_av ) ) THEN
9553                DO  i = nxlg, nxrg
9554                   DO  j = nysg, nyng
9555                      DO  k = nzb, nzt+1
9556                         rad_sw_in_av(k,j,i) = rad_sw_in_av(k,j,i)             &
9557                                               + rad_sw_in(k,j,i)
9558                      ENDDO
9559                   ENDDO
9560                ENDDO
9561             ENDIF
9562
9563          CASE ( 'rad_sw_out' )
9564             IF ( ALLOCATED( rad_sw_out_av ) ) THEN
9565                DO  i = nxlg, nxrg
9566                   DO  j = nysg, nyng
9567                      DO  k = nzb, nzt+1
9568                         rad_sw_out_av(k,j,i) = rad_sw_out_av(k,j,i)           &
9569                                                + rad_sw_out(k,j,i)
9570                      ENDDO
9571                   ENDDO
9572                ENDDO
9573             ENDIF
9574
9575          CASE ( 'rad_sw_cs_hr' )
9576             IF ( ALLOCATED( rad_sw_cs_hr_av ) ) THEN
9577                DO  i = nxlg, nxrg
9578                   DO  j = nysg, nyng
9579                      DO  k = nzb, nzt+1
9580                         rad_sw_cs_hr_av(k,j,i) = rad_sw_cs_hr_av(k,j,i)       &
9581                                                  + rad_sw_cs_hr(k,j,i)
9582                      ENDDO
9583                   ENDDO
9584                ENDDO
9585             ENDIF
9586
9587          CASE ( 'rad_sw_hr' )
9588             IF ( ALLOCATED( rad_sw_hr_av ) ) THEN
9589                DO  i = nxlg, nxrg
9590                   DO  j = nysg, nyng
9591                      DO  k = nzb, nzt+1
9592                         rad_sw_hr_av(k,j,i) = rad_sw_hr_av(k,j,i)             &
9593                                               + rad_sw_hr(k,j,i)
9594                      ENDDO
9595                   ENDDO
9596                ENDDO
9597             ENDIF
9598
9599!--       block of RTM output variables
9600          CASE ( 'rtm_rad_net' )
9601!--           array of complete radiation balance
9602              DO isurf = dirstart(ids), dirend(ids)
9603                 IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9604                    surfradnet_av(isurf) = surfinsw(isurf) - surfoutsw(isurf) +  surfinlw(isurf) - surfoutlw(isurf)
9605                 ENDIF
9606              ENDDO
9607
9608          CASE ( 'rtm_rad_insw' )
9609!--           array of sw radiation falling to surface after i-th reflection
9610              DO isurf = dirstart(ids), dirend(ids)
9611                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9612                      surfinsw_av(isurf) = surfinsw_av(isurf) + surfinsw(isurf)
9613                  ENDIF
9614              ENDDO
9615
9616          CASE ( 'rtm_rad_inlw' )
9617!--           array of lw radiation falling to surface after i-th reflection
9618              DO isurf = dirstart(ids), dirend(ids)
9619                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9620                      surfinlw_av(isurf) = surfinlw_av(isurf) + surfinlw(isurf)
9621                  ENDIF
9622              ENDDO
9623
9624          CASE ( 'rtm_rad_inswdir' )
9625!--           array of direct sw radiation falling to surface from sun
9626              DO isurf = dirstart(ids), dirend(ids)
9627                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9628                      surfinswdir_av(isurf) = surfinswdir_av(isurf) + surfinswdir(isurf)
9629                  ENDIF
9630              ENDDO
9631
9632          CASE ( 'rtm_rad_inswdif' )
9633!--           array of difusion sw radiation falling to surface from sky and borders of the domain
9634              DO isurf = dirstart(ids), dirend(ids)
9635                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9636                      surfinswdif_av(isurf) = surfinswdif_av(isurf) + surfinswdif(isurf)
9637                  ENDIF
9638              ENDDO
9639
9640          CASE ( 'rtm_rad_inswref' )
9641!--           array of sw radiation falling to surface from reflections
9642              DO isurf = dirstart(ids), dirend(ids)
9643                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9644                      surfinswref_av(isurf) = surfinswref_av(isurf) + surfinsw(isurf) - &
9645                                          surfinswdir(isurf) - surfinswdif(isurf)
9646                  ENDIF
9647              ENDDO
9648
9649
9650          CASE ( 'rtm_rad_inlwdif' )
9651!--           array of sw radiation falling to surface after i-th reflection
9652              DO isurf = dirstart(ids), dirend(ids)
9653                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9654                      surfinlwdif_av(isurf) = surfinlwdif_av(isurf) + surfinlwdif(isurf)
9655                  ENDIF
9656              ENDDO
9657!
9658          CASE ( 'rtm_rad_inlwref' )
9659!--           array of lw radiation falling to surface from reflections
9660              DO isurf = dirstart(ids), dirend(ids)
9661                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9662                      surfinlwref_av(isurf) = surfinlwref_av(isurf) + &
9663                                          surfinlw(isurf) - surfinlwdif(isurf)
9664                  ENDIF
9665              ENDDO
9666
9667          CASE ( 'rtm_rad_outsw' )
9668!--           array of sw radiation emitted from surface after i-th reflection
9669              DO isurf = dirstart(ids), dirend(ids)
9670                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9671                      surfoutsw_av(isurf) = surfoutsw_av(isurf) + surfoutsw(isurf)
9672                  ENDIF
9673              ENDDO
9674
9675          CASE ( 'rtm_rad_outlw' )
9676!--           array of lw radiation emitted from surface after i-th reflection
9677              DO isurf = dirstart(ids), dirend(ids)
9678                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9679                      surfoutlw_av(isurf) = surfoutlw_av(isurf) + surfoutlw(isurf)
9680                  ENDIF
9681              ENDDO
9682
9683          CASE ( 'rtm_rad_ressw' )
9684!--           array of residua of sw radiation absorbed in surface after last reflection
9685              DO isurf = dirstart(ids), dirend(ids)
9686                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9687                      surfins_av(isurf) = surfins_av(isurf) + surfins(isurf)
9688                  ENDIF
9689              ENDDO
9690
9691          CASE ( 'rtm_rad_reslw' )
9692!--           array of residua of lw radiation absorbed in surface after last reflection
9693              DO isurf = dirstart(ids), dirend(ids)
9694                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9695                      surfinl_av(isurf) = surfinl_av(isurf) + surfinl(isurf)
9696                  ENDIF
9697              ENDDO
9698
9699          CASE ( 'rtm_rad_pc_inlw' )
9700              DO l = 1, npcbl
9701                 pcbinlw_av(l) = pcbinlw_av(l) + pcbinlw(l)
9702              ENDDO
9703
9704          CASE ( 'rtm_rad_pc_insw' )
9705              DO l = 1, npcbl
9706                 pcbinsw_av(l) = pcbinsw_av(l) + pcbinsw(l)
9707              ENDDO
9708
9709          CASE ( 'rtm_rad_pc_inswdir' )
9710              DO l = 1, npcbl
9711                 pcbinswdir_av(l) = pcbinswdir_av(l) + pcbinswdir(l)
9712              ENDDO
9713
9714          CASE ( 'rtm_rad_pc_inswdif' )
9715              DO l = 1, npcbl
9716                 pcbinswdif_av(l) = pcbinswdif_av(l) + pcbinswdif(l)
9717              ENDDO
9718
9719          CASE ( 'rtm_rad_pc_inswref' )
9720              DO l = 1, npcbl
9721                 pcbinswref_av(l) = pcbinswref_av(l) + pcbinsw(l) - pcbinswdir(l) - pcbinswdif(l)
9722              ENDDO
9723
9724          CASE ( 'rad_mrt_sw' )
9725             IF ( ALLOCATED( mrtinsw_av ) )  THEN
9726                mrtinsw_av(:) = mrtinsw_av(:) + mrtinsw(:)
9727             ENDIF
9728
9729          CASE ( 'rad_mrt_lw' )
9730             IF ( ALLOCATED( mrtinlw_av ) )  THEN
9731                mrtinlw_av(:) = mrtinlw_av(:) + mrtinlw(:)
9732             ENDIF
9733
9734          CASE ( 'rad_mrt' )
9735             IF ( ALLOCATED( mrt_av ) )  THEN
9736                mrt_av(:) = mrt_av(:) + mrt(:)
9737             ENDIF
9738
9739          CASE DEFAULT
9740             CONTINUE
9741
9742       END SELECT
9743
9744    ELSEIF ( mode == 'average' )  THEN
9745
9746       SELECT CASE ( TRIM( var ) )
9747!--       block of large scale (e.g. RRTMG) radiation output variables
9748          CASE ( 'rad_net*' )
9749             IF ( ALLOCATED( rad_net_av ) ) THEN
9750                DO  i = nxlg, nxrg
9751                   DO  j = nysg, nyng
9752                      rad_net_av(j,i) = rad_net_av(j,i)                        &
9753                                        / REAL( average_count_3d, KIND=wp )
9754                   ENDDO
9755                ENDDO
9756             ENDIF
9757             
9758          CASE ( 'rad_lw_in*' )
9759             IF ( ALLOCATED( rad_lw_in_xy_av ) ) THEN
9760                DO  i = nxlg, nxrg
9761                   DO  j = nysg, nyng
9762                      rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i)              &
9763                                        / REAL( average_count_3d, KIND=wp )
9764                   ENDDO
9765                ENDDO
9766             ENDIF
9767             
9768          CASE ( 'rad_lw_out*' )
9769             IF ( ALLOCATED( rad_lw_out_xy_av ) ) THEN
9770                DO  i = nxlg, nxrg
9771                   DO  j = nysg, nyng
9772                      rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i)            &
9773                                        / REAL( average_count_3d, KIND=wp )
9774                   ENDDO
9775                ENDDO
9776             ENDIF
9777             
9778          CASE ( 'rad_sw_in*' )
9779             IF ( ALLOCATED( rad_sw_in_xy_av ) ) THEN
9780                DO  i = nxlg, nxrg
9781                   DO  j = nysg, nyng
9782                      rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i)              &
9783                                        / REAL( average_count_3d, KIND=wp )
9784                   ENDDO
9785                ENDDO
9786             ENDIF
9787             
9788          CASE ( 'rad_sw_out*' )
9789             IF ( ALLOCATED( rad_sw_out_xy_av ) ) THEN
9790                DO  i = nxlg, nxrg
9791                   DO  j = nysg, nyng
9792                      rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i)             &
9793                                        / REAL( average_count_3d, KIND=wp )
9794                   ENDDO
9795                ENDDO
9796             ENDIF
9797
9798          CASE ( 'rad_lw_in' )
9799             IF ( ALLOCATED( rad_lw_in_av ) ) THEN
9800                DO  i = nxlg, nxrg
9801                   DO  j = nysg, nyng
9802                      DO  k = nzb, nzt+1
9803                         rad_lw_in_av(k,j,i) = rad_lw_in_av(k,j,i)             &
9804                                               / REAL( average_count_3d, KIND=wp )
9805                      ENDDO
9806                   ENDDO
9807                ENDDO
9808             ENDIF
9809
9810          CASE ( 'rad_lw_out' )
9811             IF ( ALLOCATED( rad_lw_out_av ) ) THEN
9812                DO  i = nxlg, nxrg
9813                   DO  j = nysg, nyng
9814                      DO  k = nzb, nzt+1
9815                         rad_lw_out_av(k,j,i) = rad_lw_out_av(k,j,i)           &
9816                                                / REAL( average_count_3d, KIND=wp )
9817                      ENDDO
9818                   ENDDO
9819                ENDDO
9820             ENDIF
9821
9822          CASE ( 'rad_lw_cs_hr' )
9823             IF ( ALLOCATED( rad_lw_cs_hr_av ) ) THEN
9824                DO  i = nxlg, nxrg
9825                   DO  j = nysg, nyng
9826                      DO  k = nzb, nzt+1
9827                         rad_lw_cs_hr_av(k,j,i) = rad_lw_cs_hr_av(k,j,i)       &
9828                                                / REAL( average_count_3d, KIND=wp )
9829                      ENDDO
9830                   ENDDO
9831                ENDDO
9832             ENDIF
9833
9834          CASE ( 'rad_lw_hr' )
9835             IF ( ALLOCATED( rad_lw_hr_av ) ) THEN
9836                DO  i = nxlg, nxrg
9837                   DO  j = nysg, nyng
9838                      DO  k = nzb, nzt+1
9839                         rad_lw_hr_av(k,j,i) = rad_lw_hr_av(k,j,i)             &
9840                                               / REAL( average_count_3d, KIND=wp )
9841                      ENDDO
9842                   ENDDO
9843                ENDDO
9844             ENDIF
9845
9846          CASE ( 'rad_sw_in' )
9847             IF ( ALLOCATED( rad_sw_in_av ) ) THEN
9848                DO  i = nxlg, nxrg
9849                   DO  j = nysg, nyng
9850                      DO  k = nzb, nzt+1
9851                         rad_sw_in_av(k,j,i) = rad_sw_in_av(k,j,i)             &
9852                                               / REAL( average_count_3d, KIND=wp )
9853                      ENDDO
9854                   ENDDO
9855                ENDDO
9856             ENDIF
9857
9858          CASE ( 'rad_sw_out' )
9859             IF ( ALLOCATED( rad_sw_out_av ) ) THEN
9860                DO  i = nxlg, nxrg
9861                   DO  j = nysg, nyng
9862                      DO  k = nzb, nzt+1
9863                         rad_sw_out_av(k,j,i) = rad_sw_out_av(k,j,i)           &
9864                                                / REAL( average_count_3d, KIND=wp )
9865                      ENDDO
9866                   ENDDO
9867                ENDDO
9868             ENDIF
9869
9870          CASE ( 'rad_sw_cs_hr' )
9871             IF ( ALLOCATED( rad_sw_cs_hr_av ) ) THEN
9872                DO  i = nxlg, nxrg
9873                   DO  j = nysg, nyng
9874                      DO  k = nzb, nzt+1
9875                         rad_sw_cs_hr_av(k,j,i) = rad_sw_cs_hr_av(k,j,i)       &
9876                                                / REAL( average_count_3d, KIND=wp )
9877                      ENDDO
9878                   ENDDO
9879                ENDDO
9880             ENDIF
9881
9882          CASE ( 'rad_sw_hr' )
9883             IF ( ALLOCATED( rad_sw_hr_av ) ) THEN
9884                DO  i = nxlg, nxrg
9885                   DO  j = nysg, nyng
9886                      DO  k = nzb, nzt+1
9887                         rad_sw_hr_av(k,j,i) = rad_sw_hr_av(k,j,i)             &
9888                                               / REAL( average_count_3d, KIND=wp )
9889                      ENDDO
9890                   ENDDO
9891                ENDDO
9892             ENDIF
9893
9894!--       block of RTM output variables
9895          CASE ( 'rtm_rad_net' )
9896!--           array of complete radiation balance
9897              DO isurf = dirstart(ids), dirend(ids)
9898                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9899                      surfradnet_av(isurf) = surfinsw_av(isurf) / REAL( average_count_3d, kind=wp )
9900                  ENDIF
9901              ENDDO
9902
9903          CASE ( 'rtm_rad_insw' )
9904!--           array of sw radiation falling to surface after i-th reflection
9905              DO isurf = dirstart(ids), dirend(ids)
9906                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9907                      surfinsw_av(isurf) = surfinsw_av(isurf) / REAL( average_count_3d, kind=wp )
9908                  ENDIF
9909              ENDDO
9910
9911          CASE ( 'rtm_rad_inlw' )
9912!--           array of lw radiation falling to surface after i-th reflection
9913              DO isurf = dirstart(ids), dirend(ids)
9914                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9915                      surfinlw_av(isurf) = surfinlw_av(isurf) / REAL( average_count_3d, kind=wp )
9916                  ENDIF
9917              ENDDO
9918
9919          CASE ( 'rtm_rad_inswdir' )
9920!--           array of direct sw radiation falling to surface from sun
9921              DO isurf = dirstart(ids), dirend(ids)
9922                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9923                      surfinswdir_av(isurf) = surfinswdir_av(isurf) / REAL( average_count_3d, kind=wp )
9924                  ENDIF
9925              ENDDO
9926
9927          CASE ( 'rtm_rad_inswdif' )
9928!--           array of difusion sw radiation falling to surface from sky and borders of the domain
9929              DO isurf = dirstart(ids), dirend(ids)
9930                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9931                      surfinswdif_av(isurf) = surfinswdif_av(isurf) / REAL( average_count_3d, kind=wp )
9932                  ENDIF
9933              ENDDO
9934
9935          CASE ( 'rtm_rad_inswref' )
9936!--           array of sw radiation falling to surface from reflections
9937              DO isurf = dirstart(ids), dirend(ids)
9938                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9939                      surfinswref_av(isurf) = surfinswref_av(isurf) / REAL( average_count_3d, kind=wp )
9940                  ENDIF
9941              ENDDO
9942
9943          CASE ( 'rtm_rad_inlwdif' )
9944!--           array of sw radiation falling to surface after i-th reflection
9945              DO isurf = dirstart(ids), dirend(ids)
9946                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9947                      surfinlwdif_av(isurf) = surfinlwdif_av(isurf) / REAL( average_count_3d, kind=wp )
9948                  ENDIF
9949              ENDDO
9950
9951          CASE ( 'rtm_rad_inlwref' )
9952!--           array of lw radiation falling to surface from reflections
9953              DO isurf = dirstart(ids), dirend(ids)
9954                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9955                      surfinlwref_av(isurf) = surfinlwref_av(isurf) / REAL( average_count_3d, kind=wp )
9956                  ENDIF
9957              ENDDO
9958
9959          CASE ( 'rtm_rad_outsw' )
9960!--           array of sw radiation emitted from surface after i-th reflection
9961              DO isurf = dirstart(ids), dirend(ids)
9962                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9963                      surfoutsw_av(isurf) = surfoutsw_av(isurf) / REAL( average_count_3d, kind=wp )
9964                  ENDIF
9965              ENDDO
9966
9967          CASE ( 'rtm_rad_outlw' )
9968!--           array of lw radiation emitted from surface after i-th reflection
9969              DO isurf = dirstart(ids), dirend(ids)
9970                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9971                      surfoutlw_av(isurf) = surfoutlw_av(isurf) / REAL( average_count_3d, kind=wp )
9972                  ENDIF
9973              ENDDO
9974
9975          CASE ( 'rtm_rad_ressw' )
9976!--           array of residua of sw radiation absorbed in surface after last reflection
9977              DO isurf = dirstart(ids), dirend(ids)
9978                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9979                      surfins_av(isurf) = surfins_av(isurf) / REAL( average_count_3d, kind=wp )
9980                  ENDIF
9981              ENDDO
9982
9983          CASE ( 'rtm_rad_reslw' )
9984!--           array of residua of lw radiation absorbed in surface after last reflection
9985              DO isurf = dirstart(ids), dirend(ids)
9986                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9987                      surfinl_av(isurf) = surfinl_av(isurf) / REAL( average_count_3d, kind=wp )
9988                  ENDIF
9989              ENDDO
9990
9991          CASE ( 'rtm_rad_pc_inlw' )
9992              DO l = 1, npcbl
9993                 pcbinlw_av(:) = pcbinlw_av(:) / REAL( average_count_3d, kind=wp )
9994              ENDDO
9995
9996          CASE ( 'rtm_rad_pc_insw' )
9997              DO l = 1, npcbl
9998                 pcbinsw_av(:) = pcbinsw_av(:) / REAL( average_count_3d, kind=wp )
9999              ENDDO
10000
10001          CASE ( 'rtm_rad_pc_inswdir' )
10002              DO l = 1, npcbl
10003                 pcbinswdir_av(:) = pcbinswdir_av(:) / REAL( average_count_3d, kind=wp )
10004              ENDDO
10005
10006          CASE ( 'rtm_rad_pc_inswdif' )
10007              DO l = 1, npcbl
10008                 pcbinswdif_av(:) = pcbinswdif_av(:) / REAL( average_count_3d, kind=wp )
10009              ENDDO
10010
10011          CASE ( 'rtm_rad_pc_inswref' )
10012              DO l = 1, npcbl
10013                 pcbinswref_av(:) = pcbinswref_av(:) / REAL( average_count_3d, kind=wp )
10014              ENDDO
10015
10016          CASE ( 'rad_mrt_lw' )
10017             IF ( ALLOCATED( mrtinlw_av ) )  THEN
10018                mrtinlw_av(:) = mrtinlw_av(:) / REAL( average_count_3d, KIND=wp )
10019             ENDIF
10020
10021          CASE ( 'rad_mrt' )
10022             IF ( ALLOCATED( mrt_av ) )  THEN
10023                mrt_av(:) = mrt_av(:) / REAL( average_count_3d, KIND=wp )
10024             ENDIF
10025
10026       END SELECT
10027
10028    ENDIF
10029
10030END SUBROUTINE radiation_3d_data_averaging
10031
10032
10033!------------------------------------------------------------------------------!
10034!
10035! Description:
10036! ------------
10037!> Subroutine defining appropriate grid for netcdf variables.
10038!> It is called out from subroutine netcdf.
10039!------------------------------------------------------------------------------!
10040SUBROUTINE radiation_define_netcdf_grid( variable, found, grid_x, grid_y, grid_z )
10041   
10042    IMPLICIT NONE
10043
10044    CHARACTER (LEN=*), INTENT(IN)  ::  variable    !<
10045    LOGICAL, INTENT(OUT)           ::  found       !<
10046    CHARACTER (LEN=*), INTENT(OUT) ::  grid_x      !<
10047    CHARACTER (LEN=*), INTENT(OUT) ::  grid_y      !<
10048    CHARACTER (LEN=*), INTENT(OUT) ::  grid_z      !<
10049
10050    CHARACTER (len=varnamelength)  :: var
10051
10052    found  = .TRUE.
10053
10054!
10055!-- Check for the grid
10056    var = TRIM(variable)
10057!-- RTM directional variables
10058    IF ( var(1:12) == 'rtm_rad_net_'  .OR.  var(1:13) == 'rtm_rad_insw_'  .OR.          &
10059         var(1:13) == 'rtm_rad_inlw_'  .OR.  var(1:16) == 'rtm_rad_inswdir_'  .OR.      &
10060         var(1:16) == 'rtm_rad_inswdif_'  .OR.  var(1:16) == 'rtm_rad_inswref_'  .OR.   &
10061         var(1:16) == 'rtm_rad_inlwdif_'  .OR.  var(1:16) == 'rtm_rad_inlwref_'  .OR.   &
10062         var(1:14) == 'rtm_rad_outsw_'  .OR.  var(1:14) == 'rtm_rad_outlw_'  .OR.       &
10063         var(1:14) == 'rtm_rad_ressw_'  .OR.  var(1:14) == 'rtm_rad_reslw_'  .OR.       &
10064         var == 'rtm_rad_pc_inlw'  .OR.                                                 &
10065         var == 'rtm_rad_pc_insw'  .OR.  var == 'rtm_rad_pc_inswdir'  .OR.              &
10066         var == 'rtm_rad_pc_inswdif'  .OR.  var == 'rtm_rad_pc_inswref'  .OR.           &
10067         var(1:7) == 'rtm_svf'  .OR.  var(1:7) == 'rtm_dif'  .OR.                       &
10068         var(1:9) == 'rtm_skyvf' .OR. var(1:10) == 'rtm_skyvft'  .OR.                   &
10069         var(1:12) == 'rtm_surfalb_'  .OR.  var(1:13) == 'rtm_surfemis_'  .OR.          &
10070         var == 'rtm_mrt'  .OR.  var ==  'rtm_mrt_sw'  .OR.  var == 'rtm_mrt_lw' )  THEN
10071
10072         found = .TRUE.
10073         grid_x = 'x'
10074         grid_y = 'y'
10075         grid_z = 'zu'
10076    ELSE
10077
10078       SELECT CASE ( TRIM( var ) )
10079
10080          CASE ( 'rad_lw_cs_hr', 'rad_lw_hr', 'rad_sw_cs_hr', 'rad_sw_hr',        &
10081                 'rad_lw_cs_hr_xy', 'rad_lw_hr_xy', 'rad_sw_cs_hr_xy',            &
10082                 'rad_sw_hr_xy', 'rad_lw_cs_hr_xz', 'rad_lw_hr_xz',               &
10083                 'rad_sw_cs_hr_xz', 'rad_sw_hr_xz', 'rad_lw_cs_hr_yz',            &
10084                 'rad_lw_hr_yz', 'rad_sw_cs_hr_yz', 'rad_sw_hr_yz',               &
10085                 'rad_mrt', 'rad_mrt_sw', 'rad_mrt_lw' )
10086             grid_x = 'x'
10087             grid_y = 'y'
10088             grid_z = 'zu'
10089
10090          CASE ( 'rad_lw_in', 'rad_lw_out', 'rad_sw_in', 'rad_sw_out',            &
10091                 'rad_lw_in_xy', 'rad_lw_out_xy', 'rad_sw_in_xy','rad_sw_out_xy', &
10092                 'rad_lw_in_xz', 'rad_lw_out_xz', 'rad_sw_in_xz','rad_sw_out_xz', &
10093                 'rad_lw_in_yz', 'rad_lw_out_yz', 'rad_sw_in_yz','rad_sw_out_yz' )
10094             grid_x = 'x'
10095             grid_y = 'y'
10096             grid_z = 'zw'
10097
10098
10099          CASE DEFAULT
10100             found  = .FALSE.
10101             grid_x = 'none'
10102             grid_y = 'none'
10103             grid_z = 'none'
10104
10105           END SELECT
10106       ENDIF
10107
10108    END SUBROUTINE radiation_define_netcdf_grid
10109
10110!------------------------------------------------------------------------------!
10111!
10112! Description:
10113! ------------
10114!> Subroutine defining 2D output variables
10115!------------------------------------------------------------------------------!
10116 SUBROUTINE radiation_data_output_2d( av, variable, found, grid, mode,         &
10117                                      local_pf, two_d, nzb_do, nzt_do )
10118 
10119    USE indices
10120
10121    USE kinds
10122
10123
10124    IMPLICIT NONE
10125
10126    CHARACTER (LEN=*) ::  grid     !<
10127    CHARACTER (LEN=*) ::  mode     !<
10128    CHARACTER (LEN=*) ::  variable !<
10129
10130    INTEGER(iwp) ::  av !<
10131    INTEGER(iwp) ::  i  !<
10132    INTEGER(iwp) ::  j  !<
10133    INTEGER(iwp) ::  k  !<
10134    INTEGER(iwp) ::  m  !< index of surface element at grid point (j,i)
10135    INTEGER(iwp) ::  nzb_do   !<
10136    INTEGER(iwp) ::  nzt_do   !<
10137
10138    LOGICAL      ::  found !<
10139    LOGICAL      ::  two_d !< flag parameter that indicates 2D variables (horizontal cross sections)
10140
10141    REAL(wp) ::  fill_value = -999.0_wp    !< value for the _FillValue attribute
10142
10143    REAL(wp), DIMENSION(nxl:nxr,nys:nyn,nzb_do:nzt_do) ::  local_pf !<
10144
10145    found = .TRUE.
10146
10147    SELECT CASE ( TRIM( variable ) )
10148
10149       CASE ( 'rad_net*_xy' )        ! 2d-array
10150          IF ( av == 0 ) THEN
10151             DO  i = nxl, nxr
10152                DO  j = nys, nyn
10153!
10154!--                Obtain rad_net from its respective surface type
10155!--                Natural-type surfaces
10156                   DO  m = surf_lsm_h%start_index(j,i),                        &
10157                           surf_lsm_h%end_index(j,i) 
10158                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_net(m)
10159                   ENDDO
10160!
10161!--                Urban-type surfaces
10162                   DO  m = surf_usm_h%start_index(j,i),                        &
10163                           surf_usm_h%end_index(j,i) 
10164                      local_pf(i,j,nzb+1) = surf_usm_h%rad_net(m)
10165                   ENDDO
10166                ENDDO
10167             ENDDO
10168          ELSE
10169             IF ( .NOT. ALLOCATED( rad_net_av ) ) THEN
10170                ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
10171                rad_net_av = REAL( fill_value, KIND = wp )
10172             ENDIF
10173             DO  i = nxl, nxr
10174                DO  j = nys, nyn 
10175                   local_pf(i,j,nzb+1) = rad_net_av(j,i)
10176                ENDDO
10177             ENDDO
10178          ENDIF
10179          two_d = .TRUE.
10180          grid = 'zu1'
10181         
10182       CASE ( 'rad_lw_in*_xy' )        ! 2d-array
10183          IF ( av == 0 ) THEN
10184             DO  i = nxl, nxr
10185                DO  j = nys, nyn
10186!
10187!--                Obtain rad_net from its respective surface type
10188!--                Natural-type surfaces
10189                   DO  m = surf_lsm_h%start_index(j,i),                        &
10190                           surf_lsm_h%end_index(j,i) 
10191                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_lw_in(m)
10192                   ENDDO
10193!
10194!--                Urban-type surfaces
10195                   DO  m = surf_usm_h%start_index(j,i),                        &
10196                           surf_usm_h%end_index(j,i) 
10197                      local_pf(i,j,nzb+1) = surf_usm_h%rad_lw_in(m)
10198                   ENDDO
10199                ENDDO
10200             ENDDO
10201          ELSE
10202             IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) ) THEN
10203                ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
10204                rad_lw_in_xy_av = REAL( fill_value, KIND = wp )
10205             ENDIF
10206             DO  i = nxl, nxr
10207                DO  j = nys, nyn 
10208                   local_pf(i,j,nzb+1) = rad_lw_in_xy_av(j,i)
10209                ENDDO
10210             ENDDO
10211          ENDIF
10212          two_d = .TRUE.
10213          grid = 'zu1'
10214         
10215       CASE ( 'rad_lw_out*_xy' )        ! 2d-array
10216          IF ( av == 0 ) THEN
10217             DO  i = nxl, nxr
10218                DO  j = nys, nyn
10219!
10220!--                Obtain rad_net from its respective surface type
10221!--                Natural-type surfaces
10222                   DO  m = surf_lsm_h%start_index(j,i),                        &
10223                           surf_lsm_h%end_index(j,i) 
10224                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_lw_out(m)
10225                   ENDDO
10226!
10227!--                Urban-type surfaces
10228                   DO  m = surf_usm_h%start_index(j,i),                        &
10229                           surf_usm_h%end_index(j,i) 
10230                      local_pf(i,j,nzb+1) = surf_usm_h%rad_lw_out(m)
10231                   ENDDO
10232                ENDDO
10233             ENDDO
10234          ELSE
10235             IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) ) THEN
10236                ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
10237                rad_lw_out_xy_av = REAL( fill_value, KIND = wp )
10238             ENDIF
10239             DO  i = nxl, nxr
10240                DO  j = nys, nyn 
10241                   local_pf(i,j,nzb+1) = rad_lw_out_xy_av(j,i)
10242                ENDDO
10243             ENDDO
10244          ENDIF
10245          two_d = .TRUE.
10246          grid = 'zu1'
10247         
10248       CASE ( 'rad_sw_in*_xy' )        ! 2d-array
10249          IF ( av == 0 ) THEN
10250             DO  i = nxl, nxr
10251                DO  j = nys, nyn
10252!
10253!--                Obtain rad_net from its respective surface type
10254!--                Natural-type surfaces
10255                   DO  m = surf_lsm_h%start_index(j,i),                        &
10256                           surf_lsm_h%end_index(j,i) 
10257                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_sw_in(m)
10258                   ENDDO
10259!
10260!--                Urban-type surfaces
10261                   DO  m = surf_usm_h%start_index(j,i),                        &
10262                           surf_usm_h%end_index(j,i) 
10263                      local_pf(i,j,nzb+1) = surf_usm_h%rad_sw_in(m)
10264                   ENDDO
10265                ENDDO
10266             ENDDO
10267          ELSE
10268             IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) ) THEN
10269                ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
10270                rad_sw_in_xy_av = REAL( fill_value, KIND = wp )
10271             ENDIF
10272             DO  i = nxl, nxr
10273                DO  j = nys, nyn 
10274                   local_pf(i,j,nzb+1) = rad_sw_in_xy_av(j,i)
10275                ENDDO
10276             ENDDO
10277          ENDIF
10278          two_d = .TRUE.
10279          grid = 'zu1'
10280         
10281       CASE ( 'rad_sw_out*_xy' )        ! 2d-array
10282          IF ( av == 0 ) THEN
10283             DO  i = nxl, nxr
10284                DO  j = nys, nyn
10285!
10286!--                Obtain rad_net from its respective surface type
10287!--                Natural-type surfaces
10288                   DO  m = surf_lsm_h%start_index(j,i),                        &
10289                           surf_lsm_h%end_index(j,i) 
10290                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_sw_out(m)
10291                   ENDDO
10292!
10293!--                Urban-type surfaces
10294                   DO  m = surf_usm_h%start_index(j,i),                        &
10295                           surf_usm_h%end_index(j,i) 
10296                      local_pf(i,j,nzb+1) = surf_usm_h%rad_sw_out(m)
10297                   ENDDO
10298                ENDDO
10299             ENDDO
10300          ELSE
10301             IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) ) THEN
10302                ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
10303                rad_sw_out_xy_av = REAL( fill_value, KIND = wp )
10304             ENDIF
10305             DO  i = nxl, nxr
10306                DO  j = nys, nyn 
10307                   local_pf(i,j,nzb+1) = rad_sw_out_xy_av(j,i)
10308                ENDDO
10309             ENDDO
10310          ENDIF
10311          two_d = .TRUE.
10312          grid = 'zu1'         
10313         
10314       CASE ( 'rad_lw_in_xy', 'rad_lw_in_xz', 'rad_lw_in_yz' )
10315          IF ( av == 0 ) THEN
10316             DO  i = nxl, nxr
10317                DO  j = nys, nyn
10318                   DO  k = nzb_do, nzt_do
10319                      local_pf(i,j,k) = rad_lw_in(k,j,i)
10320                   ENDDO
10321                ENDDO
10322             ENDDO
10323          ELSE
10324            IF ( .NOT. ALLOCATED( rad_lw_in_av ) ) THEN
10325               ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10326               rad_lw_in_av = REAL( fill_value, KIND = wp )
10327            ENDIF
10328             DO  i = nxl, nxr
10329                DO  j = nys, nyn 
10330                   DO  k = nzb_do, nzt_do
10331                      local_pf(i,j,k) = rad_lw_in_av(k,j,i)
10332                   ENDDO
10333                ENDDO
10334             ENDDO
10335          ENDIF
10336          IF ( mode == 'xy' )  grid = 'zu'
10337
10338       CASE ( 'rad_lw_out_xy', 'rad_lw_out_xz', 'rad_lw_out_yz' )
10339          IF ( av == 0 ) THEN
10340             DO  i = nxl, nxr
10341                DO  j = nys, nyn
10342                   DO  k = nzb_do, nzt_do
10343                      local_pf(i,j,k) = rad_lw_out(k,j,i)
10344                   ENDDO
10345                ENDDO
10346             ENDDO
10347          ELSE
10348            IF ( .NOT. ALLOCATED( rad_lw_out_av ) ) THEN
10349               ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10350               rad_lw_out_av = REAL( fill_value, KIND = wp )
10351            ENDIF
10352             DO  i = nxl, nxr
10353                DO  j = nys, nyn 
10354                   DO  k = nzb_do, nzt_do
10355                      local_pf(i,j,k) = rad_lw_out_av(k,j,i)
10356                   ENDDO
10357                ENDDO
10358             ENDDO
10359          ENDIF   
10360          IF ( mode == 'xy' )  grid = 'zu'
10361
10362       CASE ( 'rad_lw_cs_hr_xy', 'rad_lw_cs_hr_xz', 'rad_lw_cs_hr_yz' )
10363          IF ( av == 0 ) THEN
10364             DO  i = nxl, nxr
10365                DO  j = nys, nyn
10366                   DO  k = nzb_do, nzt_do
10367                      local_pf(i,j,k) = rad_lw_cs_hr(k,j,i)
10368                   ENDDO
10369                ENDDO
10370             ENDDO
10371          ELSE
10372            IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) ) THEN
10373               ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10374               rad_lw_cs_hr_av = REAL( fill_value, KIND = wp )
10375            ENDIF
10376             DO  i = nxl, nxr
10377                DO  j = nys, nyn 
10378                   DO  k = nzb_do, nzt_do
10379                      local_pf(i,j,k) = rad_lw_cs_hr_av(k,j,i)
10380                   ENDDO
10381                ENDDO
10382             ENDDO
10383          ENDIF
10384          IF ( mode == 'xy' )  grid = 'zw'
10385
10386       CASE ( 'rad_lw_hr_xy', 'rad_lw_hr_xz', 'rad_lw_hr_yz' )
10387          IF ( av == 0 ) THEN
10388             DO  i = nxl, nxr
10389                DO  j = nys, nyn
10390                   DO  k = nzb_do, nzt_do
10391                      local_pf(i,j,k) = rad_lw_hr(k,j,i)
10392                   ENDDO
10393                ENDDO
10394             ENDDO
10395          ELSE
10396            IF ( .NOT. ALLOCATED( rad_lw_hr_av ) ) THEN
10397               ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10398               rad_lw_hr_av= REAL( fill_value, KIND = wp )
10399            ENDIF
10400             DO  i = nxl, nxr
10401                DO  j = nys, nyn 
10402                   DO  k = nzb_do, nzt_do
10403                      local_pf(i,j,k) = rad_lw_hr_av(k,j,i)
10404                   ENDDO
10405                ENDDO
10406             ENDDO
10407          ENDIF
10408          IF ( mode == 'xy' )  grid = 'zw'
10409
10410       CASE ( 'rad_sw_in_xy', 'rad_sw_in_xz', 'rad_sw_in_yz' )
10411          IF ( av == 0 ) THEN
10412             DO  i = nxl, nxr
10413                DO  j = nys, nyn
10414                   DO  k = nzb_do, nzt_do
10415                      local_pf(i,j,k) = rad_sw_in(k,j,i)
10416                   ENDDO
10417                ENDDO
10418             ENDDO
10419          ELSE
10420            IF ( .NOT. ALLOCATED( rad_sw_in_av ) ) THEN
10421               ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10422               rad_sw_in_av = REAL( fill_value, KIND = wp )
10423            ENDIF
10424             DO  i = nxl, nxr
10425                DO  j = nys, nyn 
10426                   DO  k = nzb_do, nzt_do
10427                      local_pf(i,j,k) = rad_sw_in_av(k,j,i)
10428                   ENDDO
10429                ENDDO
10430             ENDDO
10431          ENDIF
10432          IF ( mode == 'xy' )  grid = 'zu'
10433
10434       CASE ( 'rad_sw_out_xy', 'rad_sw_out_xz', 'rad_sw_out_yz' )
10435          IF ( av == 0 ) THEN
10436             DO  i = nxl, nxr
10437                DO  j = nys, nyn
10438                   DO  k = nzb_do, nzt_do
10439                      local_pf(i,j,k) = rad_sw_out(k,j,i)
10440                   ENDDO
10441                ENDDO
10442             ENDDO
10443          ELSE
10444            IF ( .NOT. ALLOCATED( rad_sw_out_av ) ) THEN
10445               ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10446               rad_sw_out_av = REAL( fill_value, KIND = wp )
10447            ENDIF
10448             DO  i = nxl, nxr
10449                DO  j = nys, nyn 
10450                   DO  k = nzb, nzt+1
10451                      local_pf(i,j,k) = rad_sw_out_av(k,j,i)
10452                   ENDDO
10453                ENDDO
10454             ENDDO
10455          ENDIF
10456          IF ( mode == 'xy' )  grid = 'zu'
10457
10458       CASE ( 'rad_sw_cs_hr_xy', 'rad_sw_cs_hr_xz', 'rad_sw_cs_hr_yz' )
10459          IF ( av == 0 ) THEN
10460             DO  i = nxl, nxr
10461                DO  j = nys, nyn
10462                   DO  k = nzb_do, nzt_do
10463                      local_pf(i,j,k) = rad_sw_cs_hr(k,j,i)
10464                   ENDDO
10465                ENDDO
10466             ENDDO
10467          ELSE
10468            IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) ) THEN
10469               ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10470               rad_sw_cs_hr_av = REAL( fill_value, KIND = wp )
10471            ENDIF
10472             DO  i = nxl, nxr
10473                DO  j = nys, nyn 
10474                   DO  k = nzb_do, nzt_do
10475                      local_pf(i,j,k) = rad_sw_cs_hr_av(k,j,i)
10476                   ENDDO
10477                ENDDO
10478             ENDDO
10479          ENDIF
10480          IF ( mode == 'xy' )  grid = 'zw'
10481
10482       CASE ( 'rad_sw_hr_xy', 'rad_sw_hr_xz', 'rad_sw_hr_yz' )
10483          IF ( av == 0 ) THEN
10484             DO  i = nxl, nxr
10485                DO  j = nys, nyn
10486                   DO  k = nzb_do, nzt_do
10487                      local_pf(i,j,k) = rad_sw_hr(k,j,i)
10488                   ENDDO
10489                ENDDO
10490             ENDDO
10491          ELSE
10492            IF ( .NOT. ALLOCATED( rad_sw_hr_av ) ) THEN
10493               ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10494               rad_sw_hr_av = REAL( fill_value, KIND = wp )
10495            ENDIF
10496             DO  i = nxl, nxr
10497                DO  j = nys, nyn 
10498                   DO  k = nzb_do, nzt_do
10499                      local_pf(i,j,k) = rad_sw_hr_av(k,j,i)
10500                   ENDDO
10501                ENDDO
10502             ENDDO
10503          ENDIF
10504          IF ( mode == 'xy' )  grid = 'zw'
10505
10506       CASE DEFAULT
10507          found = .FALSE.
10508          grid  = 'none'
10509
10510    END SELECT
10511 
10512 END SUBROUTINE radiation_data_output_2d
10513
10514
10515!------------------------------------------------------------------------------!
10516!
10517! Description:
10518! ------------
10519!> Subroutine defining 3D output variables
10520!------------------------------------------------------------------------------!
10521 SUBROUTINE radiation_data_output_3d( av, variable, found, local_pf, nzb_do, nzt_do )
10522 
10523
10524    USE indices
10525
10526    USE kinds
10527
10528
10529    IMPLICIT NONE
10530
10531    CHARACTER (LEN=*) ::  variable !<
10532
10533    INTEGER(iwp) ::  av          !<
10534    INTEGER(iwp) ::  i, j, k, l  !<
10535    INTEGER(iwp) ::  nzb_do      !<
10536    INTEGER(iwp) ::  nzt_do      !<
10537
10538    LOGICAL      ::  found       !<
10539
10540    REAL(wp)     ::  fill_value = -999.0_wp    !< value for the _FillValue attribute
10541
10542    REAL(sp), DIMENSION(nxl:nxr,nys:nyn,nzb_do:nzt_do) ::  local_pf !<
10543
10544    CHARACTER (len=varnamelength)                   :: var, surfid
10545    INTEGER(iwp)                                    :: ids,idsint_u,idsint_l,isurf,isvf,isurfs,isurflt,ipcgb
10546    INTEGER(iwp)                                    :: is, js, ks, istat
10547
10548    found = .TRUE.
10549    var = TRIM(variable)
10550
10551!-- check if variable belongs to radiation related variables (starts with rad or rtm)
10552    IF ( len(var) < 3_iwp  )  THEN
10553       found = .FALSE.
10554       RETURN
10555    ENDIF
10556   
10557    IF ( var(1:3) /= 'rad'  .AND.  var(1:3) /= 'rtm' )  THEN
10558       found = .FALSE.
10559       RETURN
10560    ENDIF
10561
10562    ids = -1
10563    DO i = 0, nd-1
10564        k = len(TRIM(var))
10565        j = len(TRIM(dirname(i)))
10566        IF ( k-j+1 >= 1_iwp ) THEN
10567           IF ( TRIM(var(k-j+1:k)) == TRIM(dirname(i)) )  THEN
10568              ids = i
10569              idsint_u = dirint_u(ids)
10570              idsint_l = dirint_l(ids)
10571              var = var(:k-j)
10572              EXIT
10573           ENDIF
10574        ENDIF
10575    ENDDO
10576    IF ( ids == -1 )  THEN
10577        var = TRIM(variable)
10578    ENDIF
10579
10580    IF ( (var(1:8) == 'rtm_svf_'  .OR.  var(1:8) == 'rtm_dif_')  .AND.  len(TRIM(var)) >= 13 )  THEN
10581!--     svf values to particular surface
10582        surfid = var(9:)
10583        i = index(surfid,'_')
10584        j = index(surfid(i+1:),'_')
10585        READ(surfid(1:i-1),*, iostat=istat ) is
10586        IF ( istat == 0 )  THEN
10587            READ(surfid(i+1:i+j-1),*, iostat=istat ) js
10588        ENDIF
10589        IF ( istat == 0 )  THEN
10590            READ(surfid(i+j+1:),*, iostat=istat ) ks
10591        ENDIF
10592        IF ( istat == 0 )  THEN
10593            var = var(1:7)
10594        ENDIF
10595    ENDIF
10596
10597    local_pf = fill_value
10598
10599    SELECT CASE ( TRIM( var ) )
10600!--   block of large scale radiation model (e.g. RRTMG) output variables
10601      CASE ( 'rad_sw_in' )
10602         IF ( av == 0 )  THEN
10603            DO  i = nxl, nxr
10604               DO  j = nys, nyn
10605                  DO  k = nzb_do, nzt_do
10606                     local_pf(i,j,k) = rad_sw_in(k,j,i)
10607                  ENDDO
10608               ENDDO
10609            ENDDO
10610         ELSE
10611            IF ( .NOT. ALLOCATED( rad_sw_in_av ) ) THEN
10612               ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10613               rad_sw_in_av = REAL( fill_value, KIND = wp )
10614            ENDIF
10615            DO  i = nxl, nxr
10616               DO  j = nys, nyn
10617                  DO  k = nzb_do, nzt_do
10618                     local_pf(i,j,k) = rad_sw_in_av(k,j,i)
10619                  ENDDO
10620               ENDDO
10621            ENDDO
10622         ENDIF
10623
10624      CASE ( 'rad_sw_out' )
10625         IF ( av == 0 )  THEN
10626            DO  i = nxl, nxr
10627               DO  j = nys, nyn
10628                  DO  k = nzb_do, nzt_do
10629                     local_pf(i,j,k) = rad_sw_out(k,j,i)
10630                  ENDDO
10631               ENDDO
10632            ENDDO
10633         ELSE
10634            IF ( .NOT. ALLOCATED( rad_sw_out_av ) ) THEN
10635               ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10636               rad_sw_out_av = REAL( fill_value, KIND = wp )
10637            ENDIF
10638            DO  i = nxl, nxr
10639               DO  j = nys, nyn
10640                  DO  k = nzb_do, nzt_do
10641                     local_pf(i,j,k) = rad_sw_out_av(k,j,i)
10642                  ENDDO
10643               ENDDO
10644            ENDDO
10645         ENDIF
10646
10647      CASE ( 'rad_sw_cs_hr' )
10648         IF ( av == 0 )  THEN
10649            DO  i = nxl, nxr
10650               DO  j = nys, nyn
10651                  DO  k = nzb_do, nzt_do
10652                     local_pf(i,j,k) = rad_sw_cs_hr(k,j,i)
10653                  ENDDO
10654               ENDDO
10655            ENDDO
10656         ELSE
10657            IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) ) THEN
10658               ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10659               rad_sw_cs_hr_av = REAL( fill_value, KIND = wp )
10660            ENDIF
10661            DO  i = nxl, nxr
10662               DO  j = nys, nyn
10663                  DO  k = nzb_do, nzt_do
10664                     local_pf(i,j,k) = rad_sw_cs_hr_av(k,j,i)
10665                  ENDDO
10666               ENDDO
10667            ENDDO
10668         ENDIF
10669
10670      CASE ( 'rad_sw_hr' )
10671         IF ( av == 0 )  THEN
10672            DO  i = nxl, nxr
10673               DO  j = nys, nyn
10674                  DO  k = nzb_do, nzt_do
10675                     local_pf(i,j,k) = rad_sw_hr(k,j,i)
10676                  ENDDO
10677               ENDDO
10678            ENDDO
10679         ELSE
10680            IF ( .NOT. ALLOCATED( rad_sw_hr_av ) ) THEN
10681               ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10682               rad_sw_hr_av = REAL( fill_value, KIND = wp )
10683            ENDIF
10684            DO  i = nxl, nxr
10685               DO  j = nys, nyn
10686                  DO  k = nzb_do, nzt_do
10687                     local_pf(i,j,k) = rad_sw_hr_av(k,j,i)
10688                  ENDDO
10689               ENDDO
10690            ENDDO
10691         ENDIF
10692
10693      CASE ( 'rad_lw_in' )
10694         IF ( av == 0 )  THEN
10695            DO  i = nxl, nxr
10696               DO  j = nys, nyn
10697                  DO  k = nzb_do, nzt_do
10698                     local_pf(i,j,k) = rad_lw_in(k,j,i)
10699                  ENDDO
10700               ENDDO
10701            ENDDO
10702         ELSE
10703            IF ( .NOT. ALLOCATED( rad_lw_in_av ) ) THEN
10704               ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10705               rad_lw_in_av = REAL( fill_value, KIND = wp )
10706            ENDIF
10707            DO  i = nxl, nxr
10708               DO  j = nys, nyn
10709                  DO  k = nzb_do, nzt_do
10710                     local_pf(i,j,k) = rad_lw_in_av(k,j,i)
10711                  ENDDO
10712               ENDDO
10713            ENDDO
10714         ENDIF
10715
10716      CASE ( 'rad_lw_out' )
10717         IF ( av == 0 )  THEN
10718            DO  i = nxl, nxr
10719               DO  j = nys, nyn
10720                  DO  k = nzb_do, nzt_do
10721                     local_pf(i,j,k) = rad_lw_out(k,j,i)
10722                  ENDDO
10723               ENDDO
10724            ENDDO
10725         ELSE
10726            IF ( .NOT. ALLOCATED( rad_lw_out_av ) ) THEN
10727               ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10728               rad_lw_out_av = REAL( fill_value, KIND = wp )
10729            ENDIF
10730            DO  i = nxl, nxr
10731               DO  j = nys, nyn
10732                  DO  k = nzb_do, nzt_do
10733                     local_pf(i,j,k) = rad_lw_out_av(k,j,i)
10734                  ENDDO
10735               ENDDO
10736            ENDDO
10737         ENDIF
10738
10739      CASE ( 'rad_lw_cs_hr' )
10740         IF ( av == 0 )  THEN
10741            DO  i = nxl, nxr
10742               DO  j = nys, nyn
10743                  DO  k = nzb_do, nzt_do
10744                     local_pf(i,j,k) = rad_lw_cs_hr(k,j,i)
10745                  ENDDO
10746               ENDDO
10747            ENDDO
10748         ELSE
10749            IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) ) THEN
10750               ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10751               rad_lw_cs_hr_av = REAL( fill_value, KIND = wp )
10752            ENDIF
10753            DO  i = nxl, nxr
10754               DO  j = nys, nyn
10755                  DO  k = nzb_do, nzt_do
10756                     local_pf(i,j,k) = rad_lw_cs_hr_av(k,j,i)
10757                  ENDDO
10758               ENDDO
10759            ENDDO
10760         ENDIF
10761
10762      CASE ( 'rad_lw_hr' )
10763         IF ( av == 0 )  THEN
10764            DO  i = nxl, nxr
10765               DO  j = nys, nyn
10766                  DO  k = nzb_do, nzt_do
10767                     local_pf(i,j,k) = rad_lw_hr(k,j,i)
10768                  ENDDO
10769               ENDDO
10770            ENDDO
10771         ELSE
10772            IF ( .NOT. ALLOCATED( rad_lw_hr_av ) ) THEN
10773               ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10774              rad_lw_hr_av = REAL( fill_value, KIND = wp )
10775            ENDIF
10776            DO  i = nxl, nxr
10777               DO  j = nys, nyn
10778                  DO  k = nzb_do, nzt_do
10779                     local_pf(i,j,k) = rad_lw_hr_av(k,j,i)
10780                  ENDDO
10781               ENDDO
10782            ENDDO
10783         ENDIF
10784
10785      CASE ( 'rtm_rad_net' )
10786!--     array of complete radiation balance
10787         DO isurf = dirstart(ids), dirend(ids)
10788            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10789               IF ( av == 0 )  THEN
10790                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = &
10791                         surfinsw(isurf) - surfoutsw(isurf) +  surfinlw(isurf) - surfoutlw(isurf)
10792               ELSE
10793                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfradnet_av(isurf)
10794               ENDIF
10795            ENDIF
10796         ENDDO
10797
10798      CASE ( 'rtm_rad_insw' )
10799!--      array of sw radiation falling to surface after i-th reflection
10800         DO isurf = dirstart(ids), dirend(ids)
10801            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10802               IF ( av == 0 )  THEN
10803                 local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinsw(isurf)
10804               ELSE
10805                 local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinsw_av(isurf)
10806               ENDIF
10807            ENDIF
10808         ENDDO
10809
10810      CASE ( 'rtm_rad_inlw' )
10811!--      array of lw radiation falling to surface after i-th reflection
10812         DO isurf = dirstart(ids), dirend(ids)
10813            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10814               IF ( av == 0 )  THEN
10815                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlw(isurf)
10816               ELSE
10817                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlw_av(isurf)
10818               ENDIF
10819             ENDIF
10820         ENDDO
10821
10822      CASE ( 'rtm_rad_inswdir' )
10823!--      array of direct sw radiation falling to surface from sun
10824         DO isurf = dirstart(ids), dirend(ids)
10825            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10826               IF ( av == 0 )  THEN
10827                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdir(isurf)
10828               ELSE
10829                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdir_av(isurf)
10830               ENDIF
10831            ENDIF
10832         ENDDO
10833
10834      CASE ( 'rtm_rad_inswdif' )
10835!--      array of difusion sw radiation falling to surface from sky and borders of the domain
10836         DO isurf = dirstart(ids), dirend(ids)
10837            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10838               IF ( av == 0 )  THEN
10839                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdif(isurf)
10840               ELSE
10841                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdif_av(isurf)
10842               ENDIF
10843            ENDIF
10844         ENDDO
10845
10846      CASE ( 'rtm_rad_inswref' )
10847!--      array of sw radiation falling to surface from reflections
10848         DO isurf = dirstart(ids), dirend(ids)
10849            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10850               IF ( av == 0 )  THEN
10851                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = &
10852                    surfinsw(isurf) - surfinswdir(isurf) - surfinswdif(isurf)
10853               ELSE
10854                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswref_av(isurf)
10855               ENDIF
10856            ENDIF
10857         ENDDO
10858
10859      CASE ( 'rtm_rad_inlwdif' )
10860!--      array of difusion lw radiation falling to surface from sky and borders of the domain
10861         DO isurf = dirstart(ids), dirend(ids)
10862            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10863               IF ( av == 0 )  THEN
10864                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlwdif(isurf)
10865               ELSE
10866                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlwdif_av(isurf)
10867               ENDIF
10868            ENDIF
10869         ENDDO
10870
10871      CASE ( 'rtm_rad_inlwref' )
10872!--      array of lw radiation falling to surface from reflections
10873         DO isurf = dirstart(ids), dirend(ids)
10874            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10875               IF ( av == 0 )  THEN
10876                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlw(isurf) - surfinlwdif(isurf)
10877               ELSE
10878                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlwref_av(isurf)
10879               ENDIF
10880            ENDIF
10881         ENDDO
10882
10883      CASE ( 'rtm_rad_outsw' )
10884!--      array of sw radiation emitted from surface after i-th reflection
10885         DO isurf = dirstart(ids), dirend(ids)
10886            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10887               IF ( av == 0 )  THEN
10888                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutsw(isurf)
10889               ELSE
10890                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutsw_av(isurf)
10891               ENDIF
10892            ENDIF
10893         ENDDO
10894
10895      CASE ( 'rtm_rad_outlw' )
10896!--      array of lw radiation emitted from surface after i-th reflection
10897         DO isurf = dirstart(ids), dirend(ids)
10898            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10899               IF ( av == 0 )  THEN
10900                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutlw(isurf)
10901               ELSE
10902                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutlw_av(isurf)
10903               ENDIF
10904            ENDIF
10905         ENDDO
10906
10907      CASE ( 'rtm_rad_ressw' )
10908!--      average of array of residua of sw radiation absorbed in surface after last reflection
10909         DO isurf = dirstart(ids), dirend(ids)
10910            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10911               IF ( av == 0 )  THEN
10912                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfins(isurf)
10913               ELSE
10914                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfins_av(isurf)
10915               ENDIF
10916            ENDIF
10917         ENDDO
10918
10919      CASE ( 'rtm_rad_reslw' )
10920!--      average of array of residua of lw radiation absorbed in surface after last reflection
10921         DO isurf = dirstart(ids), dirend(ids)
10922            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10923               IF ( av == 0 )  THEN
10924                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinl(isurf)
10925               ELSE
10926                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinl_av(isurf)
10927               ENDIF
10928            ENDIF
10929         ENDDO
10930
10931      CASE ( 'rtm_rad_pc_inlw' )
10932!--      array of lw radiation absorbed by plant canopy
10933         DO ipcgb = 1, npcbl
10934            IF ( av == 0 )  THEN
10935               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinlw(ipcgb)
10936            ELSE
10937               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinlw_av(ipcgb)
10938            ENDIF
10939         ENDDO
10940
10941      CASE ( 'rtm_rad_pc_insw' )
10942!--      array of sw radiation absorbed by plant canopy
10943         DO ipcgb = 1, npcbl
10944            IF ( av == 0 )  THEN
10945              local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinsw(ipcgb)
10946            ELSE
10947              local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinsw_av(ipcgb)
10948            ENDIF
10949         ENDDO
10950
10951      CASE ( 'rtm_rad_pc_inswdir' )
10952!--      array of direct sw radiation absorbed by plant canopy
10953         DO ipcgb = 1, npcbl
10954            IF ( av == 0 )  THEN
10955               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdir(ipcgb)
10956            ELSE
10957               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdir_av(ipcgb)
10958            ENDIF
10959         ENDDO
10960
10961      CASE ( 'rtm_rad_pc_inswdif' )
10962!--      array of diffuse sw radiation absorbed by plant canopy
10963         DO ipcgb = 1, npcbl
10964            IF ( av == 0 )  THEN
10965               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdif(ipcgb)
10966            ELSE
10967               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdif_av(ipcgb)
10968            ENDIF
10969         ENDDO
10970
10971      CASE ( 'rtm_rad_pc_inswref' )
10972!--      array of reflected sw radiation absorbed by plant canopy
10973         DO ipcgb = 1, npcbl
10974            IF ( av == 0 )  THEN
10975               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = &
10976                                    pcbinsw(ipcgb) - pcbinswdir(ipcgb) - pcbinswdif(ipcgb)
10977            ELSE
10978               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswref_av(ipcgb)
10979            ENDIF
10980         ENDDO
10981
10982      CASE ( 'rtm_mrt_sw' )
10983         local_pf = REAL( fill_value, KIND = wp )
10984         IF ( av == 0 )  THEN
10985            DO  l = 1, nmrtbl
10986               local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinsw(l)
10987            ENDDO
10988         ELSE
10989            IF ( ALLOCATED( mrtinsw_av ) ) THEN
10990               DO  l = 1, nmrtbl
10991                  local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinsw_av(l)
10992               ENDDO
10993            ENDIF
10994         ENDIF
10995
10996      CASE ( 'rtm_mrt_lw' )
10997         local_pf = REAL( fill_value, KIND = wp )
10998         IF ( av == 0 )  THEN
10999            DO  l = 1, nmrtbl
11000               local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinlw(l)
11001            ENDDO
11002         ELSE
11003            IF ( ALLOCATED( mrtinlw_av ) ) THEN
11004               DO  l = 1, nmrtbl
11005                  local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinlw_av(l)
11006               ENDDO
11007            ENDIF
11008         ENDIF
11009
11010      CASE ( 'rtm_mrt' )
11011         local_pf = REAL( fill_value, KIND = wp )
11012         IF ( av == 0 )  THEN
11013            DO  l = 1, nmrtbl
11014               local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrt(l)
11015            ENDDO
11016         ELSE
11017            IF ( ALLOCATED( mrt_av ) ) THEN
11018               DO  l = 1, nmrtbl
11019                  local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrt_av(l)
11020               ENDDO
11021            ENDIF
11022         ENDIF
11023!         
11024!--   block of RTM output variables
11025!--   variables are intended mainly for debugging and detailed analyse purposes
11026      CASE ( 'rtm_skyvf' )
11027!     
11028!--      sky view factor
11029         DO isurf = dirstart(ids), dirend(ids)
11030            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
11031               local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = skyvf(isurf)
11032            ENDIF
11033         ENDDO
11034
11035      CASE ( 'rtm_skyvft' )
11036!
11037!--      sky view factor
11038         DO isurf = dirstart(ids), dirend(ids)
11039            IF ( surfl(id,isurf) == ids )  THEN
11040               local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = skyvft(isurf)
11041            ENDIF
11042         ENDDO
11043
11044      CASE ( 'rtm_svf', 'rtm_dif' )
11045!
11046!--      shape view factors or iradiance factors to selected surface
11047         IF ( TRIM(var)=='rtm_svf' )  THEN
11048             k = 1
11049         ELSE
11050             k = 2
11051         ENDIF
11052         DO isvf = 1, nsvfl
11053            isurflt = svfsurf(1, isvf)
11054            isurfs = svfsurf(2, isvf)
11055
11056            IF ( surf(ix,isurfs) == is  .AND.  surf(iy,isurfs) == js  .AND. surf(iz,isurfs) == ks  .AND. &
11057                 (surf(id,isurfs) == idsint_u .OR. surfl(id,isurfs) == idsint_l ) ) THEN
11058!
11059!--            correct source surface
11060               local_pf(surfl(ix,isurflt),surfl(iy,isurflt),surfl(iz,isurflt)) = svf(k,isvf)
11061            ENDIF
11062         ENDDO
11063
11064      CASE ( 'rtm_surfalb' )
11065!
11066!--      surface albedo
11067         DO isurf = dirstart(ids), dirend(ids)
11068            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
11069               local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = albedo_surf(isurf)
11070            ENDIF
11071         ENDDO
11072
11073      CASE ( 'rtm_surfemis' )
11074!
11075!--      surface emissivity, weighted average
11076         DO isurf = dirstart(ids), dirend(ids)
11077            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
11078               local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = emiss_surf(isurf)
11079            ENDIF
11080         ENDDO
11081
11082      CASE DEFAULT
11083         found = .FALSE.
11084
11085    END SELECT
11086
11087
11088 END SUBROUTINE radiation_data_output_3d
11089
11090!------------------------------------------------------------------------------!
11091!
11092! Description:
11093! ------------
11094!> Subroutine defining masked data output
11095!------------------------------------------------------------------------------!
11096 SUBROUTINE radiation_data_output_mask( av, variable, found, local_pf, mid )
11097 
11098    USE control_parameters
11099       
11100    USE indices
11101   
11102    USE kinds
11103   
11104
11105    IMPLICIT NONE
11106
11107    CHARACTER (LEN=*) ::  variable   !<
11108
11109    CHARACTER(LEN=5) ::  grid        !< flag to distinquish between staggered grids
11110
11111    INTEGER(iwp) ::  av              !<
11112    INTEGER(iwp) ::  i               !<
11113    INTEGER(iwp) ::  j               !<
11114    INTEGER(iwp) ::  k               !<
11115    INTEGER(iwp) ::  mid             !< masked output running index
11116    INTEGER(iwp) ::  topo_top_index  !< k index of highest horizontal surface
11117
11118    LOGICAL ::  found                !< true if output array was found
11119    LOGICAL ::  resorted             !< true if array is resorted
11120
11121
11122    REAL(wp),                                                                  &
11123       DIMENSION(mask_size_l(mid,1),mask_size_l(mid,2),mask_size_l(mid,3)) ::  &
11124          local_pf   !<
11125
11126    REAL(wp), DIMENSION(:,:,:), POINTER ::  to_be_resorted  !< points to array which needs to be resorted for output
11127
11128
11129    found    = .TRUE.
11130    grid     = 's'
11131    resorted = .FALSE.
11132
11133    SELECT CASE ( TRIM( variable ) )
11134
11135
11136       CASE ( 'rad_lw_in' )
11137          IF ( av == 0 )  THEN
11138             to_be_resorted => rad_lw_in
11139          ELSE
11140             to_be_resorted => rad_lw_in_av
11141          ENDIF
11142
11143       CASE ( 'rad_lw_out' )
11144          IF ( av == 0 )  THEN
11145             to_be_resorted => rad_lw_out
11146          ELSE
11147             to_be_resorted => rad_lw_out_av
11148          ENDIF
11149
11150       CASE ( 'rad_lw_cs_hr' )
11151          IF ( av == 0 )  THEN
11152             to_be_resorted => rad_lw_cs_hr
11153          ELSE
11154             to_be_resorted => rad_lw_cs_hr_av
11155          ENDIF
11156
11157       CASE ( 'rad_lw_hr' )
11158          IF ( av == 0 )  THEN
11159             to_be_resorted => rad_lw_hr
11160          ELSE
11161             to_be_resorted => rad_lw_hr_av
11162          ENDIF
11163
11164       CASE ( 'rad_sw_in' )
11165          IF ( av == 0 )  THEN
11166             to_be_resorted => rad_sw_in
11167          ELSE
11168             to_be_resorted => rad_sw_in_av
11169          ENDIF
11170
11171       CASE ( 'rad_sw_out' )
11172          IF ( av == 0 )  THEN
11173             to_be_resorted => rad_sw_out
11174          ELSE
11175             to_be_resorted => rad_sw_out_av
11176          ENDIF
11177
11178       CASE ( 'rad_sw_cs_hr' )
11179          IF ( av == 0 )  THEN
11180             to_be_resorted => rad_sw_cs_hr
11181          ELSE
11182             to_be_resorted => rad_sw_cs_hr_av
11183          ENDIF
11184
11185       CASE ( 'rad_sw_hr' )
11186          IF ( av == 0 )  THEN
11187             to_be_resorted => rad_sw_hr
11188          ELSE
11189             to_be_resorted => rad_sw_hr_av
11190          ENDIF
11191
11192       CASE DEFAULT
11193          found = .FALSE.
11194
11195    END SELECT
11196
11197!
11198!-- Resort the array to be output, if not done above
11199    IF ( found  .AND.  .NOT. resorted )  THEN
11200       IF ( .NOT. mask_surface(mid) )  THEN
11201!
11202!--       Default masked output
11203          DO  i = 1, mask_size_l(mid,1)
11204             DO  j = 1, mask_size_l(mid,2)
11205                DO  k = 1, mask_size_l(mid,3)
11206                   local_pf(i,j,k) =  to_be_resorted(mask_k(mid,k), &
11207                                      mask_j(mid,j),mask_i(mid,i))
11208                ENDDO
11209             ENDDO
11210          ENDDO
11211
11212       ELSE
11213!
11214!--       Terrain-following masked output
11215          DO  i = 1, mask_size_l(mid,1)
11216             DO  j = 1, mask_size_l(mid,2)
11217!
11218!--             Get k index of highest horizontal surface
11219                topo_top_index = topo_top_ind(mask_j(mid,j), &
11220                                              mask_i(mid,i),   &
11221                                              0 )
11222!
11223!--             Save output array
11224                DO  k = 1, mask_size_l(mid,3)
11225                   local_pf(i,j,k) = to_be_resorted(                         &
11226                                          MIN( topo_top_index+mask_k(mid,k), &
11227                                               nzt+1 ),                      &
11228                                          mask_j(mid,j),                     &
11229                                          mask_i(mid,i)                     )
11230                ENDDO
11231             ENDDO
11232          ENDDO
11233
11234       ENDIF
11235    ENDIF
11236
11237
11238
11239 END SUBROUTINE radiation_data_output_mask
11240
11241
11242!------------------------------------------------------------------------------!
11243! Description:
11244! ------------
11245!> Subroutine writes local (subdomain) restart data
11246!------------------------------------------------------------------------------!
11247 SUBROUTINE radiation_wrd_local
11248
11249
11250    IMPLICIT NONE
11251
11252
11253    IF ( ALLOCATED( rad_net_av ) )  THEN
11254       CALL wrd_write_string( 'rad_net_av' )
11255       WRITE ( 14 )  rad_net_av
11256    ENDIF
11257   
11258    IF ( ALLOCATED( rad_lw_in_xy_av ) )  THEN
11259       CALL wrd_write_string( 'rad_lw_in_xy_av' )
11260       WRITE ( 14 )  rad_lw_in_xy_av
11261    ENDIF
11262   
11263    IF ( ALLOCATED( rad_lw_out_xy_av ) )  THEN
11264       CALL wrd_write_string( 'rad_lw_out_xy_av' )
11265       WRITE ( 14 )  rad_lw_out_xy_av
11266    ENDIF
11267   
11268    IF ( ALLOCATED( rad_sw_in_xy_av ) )  THEN
11269       CALL wrd_write_string( 'rad_sw_in_xy_av' )
11270       WRITE ( 14 )  rad_sw_in_xy_av
11271    ENDIF
11272   
11273    IF ( ALLOCATED( rad_sw_out_xy_av ) )  THEN
11274       CALL wrd_write_string( 'rad_sw_out_xy_av' )
11275       WRITE ( 14 )  rad_sw_out_xy_av
11276    ENDIF
11277
11278    IF ( ALLOCATED( rad_lw_in ) )  THEN
11279       CALL wrd_write_string( 'rad_lw_in' )
11280       WRITE ( 14 )  rad_lw_in
11281    ENDIF
11282
11283    IF ( ALLOCATED( rad_lw_in_av ) )  THEN
11284       CALL wrd_write_string( 'rad_lw_in_av' )
11285       WRITE ( 14 )  rad_lw_in_av
11286    ENDIF
11287
11288    IF ( ALLOCATED( rad_lw_out ) )  THEN
11289       CALL wrd_write_string( 'rad_lw_out' )
11290       WRITE ( 14 )  rad_lw_out
11291    ENDIF
11292
11293    IF ( ALLOCATED( rad_lw_out_av) )  THEN
11294       CALL wrd_write_string( 'rad_lw_out_av' )
11295       WRITE ( 14 )  rad_lw_out_av
11296    ENDIF
11297
11298    IF ( ALLOCATED( rad_lw_cs_hr) )  THEN
11299       CALL wrd_write_string( 'rad_lw_cs_hr' )
11300       WRITE ( 14 )  rad_lw_cs_hr
11301    ENDIF
11302
11303    IF ( ALLOCATED( rad_lw_cs_hr_av) )  THEN
11304       CALL wrd_write_string( 'rad_lw_cs_hr_av' )
11305       WRITE ( 14 )  rad_lw_cs_hr_av
11306    ENDIF
11307
11308    IF ( ALLOCATED( rad_lw_hr) )  THEN
11309       CALL wrd_write_string( 'rad_lw_hr' )
11310       WRITE ( 14 )  rad_lw_hr
11311    ENDIF
11312
11313    IF ( ALLOCATED( rad_lw_hr_av) )  THEN
11314       CALL wrd_write_string( 'rad_lw_hr_av' )
11315       WRITE ( 14 )  rad_lw_hr_av
11316    ENDIF
11317
11318    IF ( ALLOCATED( rad_sw_in) )  THEN
11319       CALL wrd_write_string( 'rad_sw_in' )
11320       WRITE ( 14 )  rad_sw_in
11321    ENDIF
11322
11323    IF ( ALLOCATED( rad_sw_in_av) )  THEN
11324       CALL wrd_write_string( 'rad_sw_in_av' )
11325       WRITE ( 14 )  rad_sw_in_av
11326    ENDIF
11327
11328    IF ( ALLOCATED( rad_sw_out) )  THEN
11329       CALL wrd_write_string( 'rad_sw_out' )
11330       WRITE ( 14 )  rad_sw_out
11331    ENDIF
11332
11333    IF ( ALLOCATED( rad_sw_out_av) )  THEN
11334       CALL wrd_write_string( 'rad_sw_out_av' )
11335       WRITE ( 14 )  rad_sw_out_av
11336    ENDIF
11337
11338    IF ( ALLOCATED( rad_sw_cs_hr) )  THEN
11339       CALL wrd_write_string( 'rad_sw_cs_hr' )
11340       WRITE ( 14 )  rad_sw_cs_hr
11341    ENDIF
11342
11343    IF ( ALLOCATED( rad_sw_cs_hr_av) )  THEN
11344       CALL wrd_write_string( 'rad_sw_cs_hr_av' )
11345       WRITE ( 14 )  rad_sw_cs_hr_av
11346    ENDIF
11347
11348    IF ( ALLOCATED( rad_sw_hr) )  THEN
11349       CALL wrd_write_string( 'rad_sw_hr' )
11350       WRITE ( 14 )  rad_sw_hr
11351    ENDIF
11352
11353    IF ( ALLOCATED( rad_sw_hr_av) )  THEN
11354       CALL wrd_write_string( 'rad_sw_hr_av' )
11355       WRITE ( 14 )  rad_sw_hr_av
11356    ENDIF
11357
11358
11359 END SUBROUTINE radiation_wrd_local
11360
11361!------------------------------------------------------------------------------!
11362! Description:
11363! ------------
11364!> Subroutine reads local (subdomain) restart data
11365!------------------------------------------------------------------------------!
11366 SUBROUTINE radiation_rrd_local( k, nxlf, nxlc, nxl_on_file, nxrf, nxrc,       &
11367                                nxr_on_file, nynf, nync, nyn_on_file, nysf,    &
11368                                nysc, nys_on_file, tmp_2d, tmp_3d, found )
11369 
11370
11371    USE control_parameters
11372       
11373    USE indices
11374   
11375    USE kinds
11376   
11377    USE pegrid
11378
11379
11380    IMPLICIT NONE
11381
11382    INTEGER(iwp) ::  k               !<
11383    INTEGER(iwp) ::  nxlc            !<
11384    INTEGER(iwp) ::  nxlf            !<
11385    INTEGER(iwp) ::  nxl_on_file     !<
11386    INTEGER(iwp) ::  nxrc            !<
11387    INTEGER(iwp) ::  nxrf            !<
11388    INTEGER(iwp) ::  nxr_on_file     !<
11389    INTEGER(iwp) ::  nync            !<
11390    INTEGER(iwp) ::  nynf            !<
11391    INTEGER(iwp) ::  nyn_on_file     !<
11392    INTEGER(iwp) ::  nysc            !<
11393    INTEGER(iwp) ::  nysf            !<
11394    INTEGER(iwp) ::  nys_on_file     !<
11395
11396    LOGICAL, INTENT(OUT)  :: found
11397
11398    REAL(wp), DIMENSION(nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_2d   !<
11399
11400    REAL(wp), DIMENSION(nzb:nzt+1,nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_3d   !<
11401
11402    REAL(wp), DIMENSION(0:0,nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_3d2   !<
11403
11404
11405    found = .TRUE.
11406
11407
11408    SELECT CASE ( restart_string(1:length) )
11409
11410       CASE ( 'rad_net_av' )
11411          IF ( .NOT. ALLOCATED( rad_net_av ) )  THEN
11412             ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
11413          ENDIF 
11414          IF ( k == 1 )  READ ( 13 )  tmp_2d
11415          rad_net_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =           &
11416                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11417                       
11418       CASE ( 'rad_lw_in_xy_av' )
11419          IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) )  THEN
11420             ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
11421          ENDIF 
11422          IF ( k == 1 )  READ ( 13 )  tmp_2d
11423          rad_lw_in_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =      &
11424                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11425                       
11426       CASE ( 'rad_lw_out_xy_av' )
11427          IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) )  THEN
11428             ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
11429          ENDIF 
11430          IF ( k == 1 )  READ ( 13 )  tmp_2d
11431          rad_lw_out_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =     &
11432                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11433                       
11434       CASE ( 'rad_sw_in_xy_av' )
11435          IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) )  THEN
11436             ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
11437          ENDIF 
11438          IF ( k == 1 )  READ ( 13 )  tmp_2d
11439          rad_sw_in_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =      &
11440                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11441                       
11442       CASE ( 'rad_sw_out_xy_av' )
11443          IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) )  THEN
11444             ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
11445          ENDIF 
11446          IF ( k == 1 )  READ ( 13 )  tmp_2d
11447          rad_sw_out_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =     &
11448                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11449                       
11450       CASE ( 'rad_lw_in' )
11451          IF ( .NOT. ALLOCATED( rad_lw_in ) )  THEN
11452             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11453                  radiation_scheme == 'constant')  THEN
11454                ALLOCATE( rad_lw_in(0:0,nysg:nyng,nxlg:nxrg) )
11455             ELSE
11456                ALLOCATE( rad_lw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11457             ENDIF
11458          ENDIF 
11459          IF ( k == 1 )  THEN
11460             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11461                  radiation_scheme == 'constant')  THEN
11462                READ ( 13 )  tmp_3d2
11463                rad_lw_in(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =   &
11464                   tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11465             ELSE
11466                READ ( 13 )  tmp_3d
11467                rad_lw_in(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11468                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11469             ENDIF
11470          ENDIF
11471
11472       CASE ( 'rad_lw_in_av' )
11473          IF ( .NOT. ALLOCATED( rad_lw_in_av ) )  THEN
11474             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11475                  radiation_scheme == 'constant')  THEN
11476                ALLOCATE( rad_lw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
11477             ELSE
11478                ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11479             ENDIF
11480          ENDIF 
11481          IF ( k == 1 )  THEN
11482             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11483                  radiation_scheme == 'constant')  THEN
11484                READ ( 13 )  tmp_3d2
11485                rad_lw_in_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =&
11486                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11487             ELSE
11488                READ ( 13 )  tmp_3d
11489                rad_lw_in_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11490                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11491             ENDIF
11492          ENDIF
11493
11494       CASE ( 'rad_lw_out' )
11495          IF ( .NOT. ALLOCATED( rad_lw_out ) )  THEN
11496             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11497                  radiation_scheme == 'constant')  THEN
11498                ALLOCATE( rad_lw_out(0:0,nysg:nyng,nxlg:nxrg) )
11499             ELSE
11500                ALLOCATE( rad_lw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11501             ENDIF
11502          ENDIF 
11503          IF ( k == 1 )  THEN
11504             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11505                  radiation_scheme == 'constant')  THEN
11506                READ ( 13 )  tmp_3d2
11507                rad_lw_out(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11508                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11509             ELSE
11510                READ ( 13 )  tmp_3d
11511                rad_lw_out(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =    &
11512                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11513             ENDIF
11514          ENDIF
11515
11516       CASE ( 'rad_lw_out_av' )
11517          IF ( .NOT. ALLOCATED( rad_lw_out_av ) )  THEN
11518             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11519                  radiation_scheme == 'constant')  THEN
11520                ALLOCATE( rad_lw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
11521             ELSE
11522                ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11523             ENDIF
11524          ENDIF 
11525          IF ( k == 1 )  THEN
11526             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11527                  radiation_scheme == 'constant')  THEN
11528                READ ( 13 )  tmp_3d2
11529                rad_lw_out_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) &
11530                   = tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11531             ELSE
11532                READ ( 13 )  tmp_3d
11533                rad_lw_out_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &
11534                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11535             ENDIF
11536          ENDIF
11537
11538       CASE ( 'rad_lw_cs_hr' )
11539          IF ( .NOT. ALLOCATED( rad_lw_cs_hr ) )  THEN
11540             ALLOCATE( rad_lw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11541          ENDIF
11542          IF ( k == 1 )  READ ( 13 )  tmp_3d
11543          rad_lw_cs_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11544                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11545
11546       CASE ( 'rad_lw_cs_hr_av' )
11547          IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) )  THEN
11548             ALLOCATE( rad_lw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11549          ENDIF
11550          IF ( k == 1 )  READ ( 13 )  tmp_3d
11551          rad_lw_cs_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11552                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11553
11554       CASE ( 'rad_lw_hr' )
11555          IF ( .NOT. ALLOCATED( rad_lw_hr ) )  THEN
11556             ALLOCATE( rad_lw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11557          ENDIF
11558          IF ( k == 1 )  READ ( 13 )  tmp_3d
11559          rad_lw_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =           &
11560                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11561
11562       CASE ( 'rad_lw_hr_av' )
11563          IF ( .NOT. ALLOCATED( rad_lw_hr_av ) )  THEN
11564             ALLOCATE( rad_lw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11565          ENDIF
11566          IF ( k == 1 )  READ ( 13 )  tmp_3d
11567          rad_lw_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11568                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11569
11570       CASE ( 'rad_sw_in' )
11571          IF ( .NOT. ALLOCATED( rad_sw_in ) )  THEN
11572             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11573                  radiation_scheme == 'constant')  THEN
11574                ALLOCATE( rad_sw_in(0:0,nysg:nyng,nxlg:nxrg) )
11575             ELSE
11576                ALLOCATE( rad_sw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11577             ENDIF
11578          ENDIF 
11579          IF ( k == 1 )  THEN
11580             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11581                  radiation_scheme == 'constant')  THEN
11582                READ ( 13 )  tmp_3d2
11583                rad_sw_in(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =   &
11584                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11585             ELSE
11586                READ ( 13 )  tmp_3d
11587                rad_sw_in(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11588                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11589             ENDIF
11590          ENDIF
11591
11592       CASE ( 'rad_sw_in_av' )
11593          IF ( .NOT. ALLOCATED( rad_sw_in_av ) )  THEN
11594             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11595                  radiation_scheme == 'constant')  THEN
11596                ALLOCATE( rad_sw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
11597             ELSE
11598                ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11599             ENDIF
11600          ENDIF 
11601          IF ( k == 1 )  THEN
11602             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11603                  radiation_scheme == 'constant')  THEN
11604                READ ( 13 )  tmp_3d2
11605                rad_sw_in_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =&
11606                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11607             ELSE
11608                READ ( 13 )  tmp_3d
11609                rad_sw_in_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11610                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11611             ENDIF
11612          ENDIF
11613
11614       CASE ( 'rad_sw_out' )
11615          IF ( .NOT. ALLOCATED( rad_sw_out ) )  THEN
11616             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11617                  radiation_scheme == 'constant')  THEN
11618                ALLOCATE( rad_sw_out(0:0,nysg:nyng,nxlg:nxrg) )
11619             ELSE
11620                ALLOCATE( rad_sw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11621             ENDIF
11622          ENDIF 
11623          IF ( k == 1 )  THEN
11624             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11625                  radiation_scheme == 'constant')  THEN
11626                READ ( 13 )  tmp_3d2
11627                rad_sw_out(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11628                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11629             ELSE
11630                READ ( 13 )  tmp_3d
11631                rad_sw_out(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =    &
11632                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11633             ENDIF
11634          ENDIF
11635
11636       CASE ( 'rad_sw_out_av' )
11637          IF ( .NOT. ALLOCATED( rad_sw_out_av ) )  THEN
11638             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11639                  radiation_scheme == 'constant')  THEN
11640                ALLOCATE( rad_sw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
11641             ELSE
11642                ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11643             ENDIF
11644          ENDIF 
11645          IF ( k == 1 )  THEN
11646             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11647                  radiation_scheme == 'constant')  THEN
11648                READ ( 13 )  tmp_3d2
11649                rad_sw_out_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) &
11650                   = tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11651             ELSE
11652                READ ( 13 )  tmp_3d
11653                rad_sw_out_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &
11654                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11655             ENDIF
11656          ENDIF
11657
11658       CASE ( 'rad_sw_cs_hr' )
11659          IF ( .NOT. ALLOCATED( rad_sw_cs_hr ) )  THEN
11660             ALLOCATE( rad_sw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11661          ENDIF
11662          IF ( k == 1 )  READ ( 13 )  tmp_3d
11663          rad_sw_cs_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11664                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11665
11666       CASE ( 'rad_sw_cs_hr_av' )
11667          IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) )  THEN
11668             ALLOCATE( rad_sw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11669          ENDIF
11670          IF ( k == 1 )  READ ( 13 )  tmp_3d
11671          rad_sw_cs_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11672                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11673
11674       CASE ( 'rad_sw_hr' )
11675          IF ( .NOT. ALLOCATED( rad_sw_hr ) )  THEN
11676             ALLOCATE( rad_sw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11677          ENDIF
11678          IF ( k == 1 )  READ ( 13 )  tmp_3d
11679          rad_sw_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =           &
11680                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11681
11682       CASE ( 'rad_sw_hr_av' )
11683          IF ( .NOT. ALLOCATED( rad_sw_hr_av ) )  THEN
11684             ALLOCATE( rad_sw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11685          ENDIF
11686          IF ( k == 1 )  READ ( 13 )  tmp_3d
11687          rad_lw_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11688                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11689
11690       CASE DEFAULT
11691
11692          found = .FALSE.
11693
11694    END SELECT
11695
11696 END SUBROUTINE radiation_rrd_local
11697
11698
11699 END MODULE radiation_model_mod
Note: See TracBrowser for help on using the repository browser.