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

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

indoor_model_mod: Revision of indoor model; urban_surface_mod: parameters for waste heat from cooling and heating are introduced to building data base; initialization of building data base moved to an earlier point of time before indoor model will be initialized; radiation_model_mod: minor improvement in some comments; synthetic_turbulence_generator: unused variable removed

  • Property svn:keywords set to Id
  • Property svn:mergeinfo set to (toggle deleted branches)
    /palm/branches/chemistry/SOURCE/radiation_model_mod.f902047-3190,​3218-3297
    /palm/branches/forwind/SOURCE/radiation_model_mod.f901564-1913
    /palm/branches/mosaik_M2/radiation_model_mod.f902360-3471
    /palm/branches/palm4u/SOURCE/radiation_model_mod.f902540-2692
    /palm/branches/radiation/SOURCE/radiation_model_mod.f902081-3493
    /palm/branches/rans/SOURCE/radiation_model_mod.f902078-3128
    /palm/branches/resler/SOURCE/radiation_model_mod.f902023-3605
    /palm/branches/salsa/SOURCE/radiation_model_mod.f902503-3460
    /palm/branches/fricke/SOURCE/radiation_model_mod.f90942-977
    /palm/branches/hoffmann/SOURCE/radiation_model_mod.f90989-1052
    /palm/branches/letzel/masked_output/SOURCE/radiation_model_mod.f90296-409
    /palm/branches/suehring/radiation_model_mod.f90423-666
File size: 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 4148 2019-08-08 11:26:00Z suehring $
30! Comments added
31!
32! 4134 2019-08-02 18:39:57Z suehring
33! Bugfix in formatted write statement
34!
35! 4127 2019-07-30 14:47:10Z suehring
36! Remove unused pch_index (merge from branch resler)
37!
38! 4089 2019-07-11 14:30:27Z suehring
39! - Correct level 2 initialization of spectral albedos in rrtmg branch, long- and
40!   shortwave albedos were mixed-up.
41! - Change order of albedo_pars so that it is now consistent with the defined
42!   order of albedo_pars in PIDS
43!
44! 4069 2019-07-01 14:05:51Z Giersch
45! Masked output running index mid has been introduced as a local variable to
46! avoid runtime error (Loop variable has been modified) in time_integration
47!
48! 4067 2019-07-01 13:29:25Z suehring
49! Bugfix, pass dummy string to MPI_INFO_SET (J. Resler)
50!
51! 4039 2019-06-18 10:32:41Z suehring
52! Bugfix for masked data output
53!
54! 4008 2019-05-30 09:50:11Z moh.hefny
55! Bugfix in check variable when a variable's string is less than 3
56! characters is processed. All variables now are checked if they
57! belong to radiation
58!
59! 3992 2019-05-22 16:49:38Z suehring
60! Bugfix in rrtmg radiation branch in a nested run when the lowest prognistic
61! grid points in a child domain are all inside topography
62!
63! 3987 2019-05-22 09:52:13Z kanani
64! Introduce alternative switch for debug output during timestepping
65!
66! 3943 2019-05-02 09:50:41Z maronga
67! Missing blank characteer added.
68!
69! 3900 2019-04-16 15:17:43Z suehring
70! Fixed initialization problem
71!
72! 3885 2019-04-11 11:29:34Z kanani
73! Changes related to global restructuring of location messages and introduction
74! of additional debug messages
75!
76! 3881 2019-04-10 09:31:22Z suehring
77! Output of albedo and emissivity moved from USM, bugfixes in initialization
78! of albedo
79!
80! 3861 2019-04-04 06:27:41Z maronga
81! Bugfix: factor of 4.0 required instead of 3.0 in calculation of rad_lw_out_change_0
82!
83! 3859 2019-04-03 20:30:31Z maronga
84! Added some descriptions
85!
86! 3847 2019-04-01 14:51:44Z suehring
87! Implement check for dt_radiation (must be > 0)
88!
89! 3846 2019-04-01 13:55:30Z suehring
90! unused variable removed
91!
92! 3814 2019-03-26 08:40:31Z pavelkrc
93! Change zenith(0:0) and others to scalar.
94! Code review.
95! Rename exported nzu, nzp and related variables due to name conflict
96!
97! 3771 2019-02-28 12:19:33Z raasch
98! rrtmg preprocessor for directives moved/added, save attribute added to temporary
99! pointers to avoid compiler warnings about outlived pointer targets,
100! statement added to avoid compiler warning about unused variable
101!
102! 3769 2019-02-28 10:16:49Z moh.hefny
103! removed unused variables and subroutine radiation_radflux_gridbox
104!
105! 3767 2019-02-27 08:18:02Z raasch
106! unused variable for file index removed from rrd-subroutines parameter list
107!
108! 3760 2019-02-21 18:47:35Z moh.hefny
109! Bugfix: initialized simulated_time before calculating solar position
110! to enable restart option with reading in SVF from file(s).
111!
112! 3754 2019-02-19 17:02:26Z kanani
113! (resler, pavelkrc)
114! Bugfixes: add further required MRT factors to read/write_svf,
115! fix for aggregating view factors to eliminate local noise in reflected
116! irradiance at mutually close surfaces (corners, presence of trees) in the
117! angular discretization scheme.
118!
119! 3752 2019-02-19 09:37:22Z resler
120! added read/write number of MRT factors to the respective routines
121!
122! 3705 2019-01-29 19:56:39Z suehring
123! Make variables that are sampled in virtual measurement module public
124!
125! 3704 2019-01-29 19:51:41Z suehring
126! Some interface calls moved to module_interface + cleanup
127!
128! 3667 2019-01-10 14:26:24Z schwenkel
129! Modified check for rrtmg input files
130!
131! 3655 2019-01-07 16:51:22Z knoop
132! nopointer option removed
133!
134! 3633 2018-12-17 16:17:57Z schwenkel
135! Include check for rrtmg files
136!
137! 3630 2018-12-17 11:04:17Z knoop
138! - fix initialization of date and time after calling zenith
139! - fix a bug in radiation_solar_pos
140!
141! 3616 2018-12-10 09:44:36Z Salim
142! fix manipulation of time variables in radiation_presimulate_solar_pos
143!
144! 3608 2018-12-07 12:59:57Z suehring $
145! Bugfix radiation output
146!
147! 3607 2018-12-07 11:56:58Z suehring
148! Output of radiation-related quantities migrated to radiation_model_mod.
149!
150! 3589 2018-11-30 15:09:51Z suehring
151! Remove erroneous UTF encoding
152!
153! 3572 2018-11-28 11:40:28Z suehring
154! Add filling the short- and longwave radiation flux arrays (e.g. diffuse,
155! direct, reflected, resedual) for all surfaces. This is required to surface
156! outputs in suface_output_mod. (M. Salim)
157!
158! 3571 2018-11-28 09:24:03Z moh.hefny
159! Add an epsilon value to compare values in if statement to fix possible
160! precsion related errors in raytrace routines.
161!
162! 3524 2018-11-14 13:36:44Z raasch
163! missing cpp-directives added
164!
165! 3495 2018-11-06 15:22:17Z kanani
166! Resort control_parameters ONLY list,
167! From branch radiation@3491 moh.hefny:
168! bugfix in calculating the apparent solar positions by updating
169! the simulated time so that the actual time is correct.
170!
171! 3464 2018-10-30 18:08:55Z kanani
172! From branch resler@3462, pavelkrc:
173! add MRT shaping function for human
174!
175! 3449 2018-10-29 19:36:56Z suehring
176! New RTM version 3.0: (Pavel Krc, Jaroslav Resler, ICS, Prague)
177!   - Interaction of plant canopy with LW radiation
178!   - Transpiration from resolved plant canopy dependent on radiation
179!     called from RTM
180!
181!
182! 3435 2018-10-26 18:25:44Z gronemeier
183! - workaround: return unit=illegal in check_data_output for certain variables
184!   when check called from init_masks
185! - Use pointer in masked output to reduce code redundancies
186! - Add terrain-following masked output
187!
188! 3424 2018-10-25 07:29:10Z gronemeier
189! bugfix: add rad_lw_in, rad_lw_out, rad_sw_out to radiation_check_data_output
190!
191! 3378 2018-10-19 12:34:59Z kanani
192! merge from radiation branch (r3362) into trunk
193! (moh.hefny):
194! - removed read/write_svf_on_init and read_dist_max_svf (not used anymore)
195! - bugfix nzut > nzpt in calculating maxboxes
196!
197! 3372 2018-10-18 14:03:19Z raasch
198! bugfix: kind type of 2nd argument of mpi_win_allocate changed, misplaced
199!         __parallel directive
200!
201! 3351 2018-10-15 18:40:42Z suehring
202! Do not overwrite values of spectral and broadband albedo during initialization
203! if they are already initialized in the urban-surface model via ASCII input.
204!
205! 3337 2018-10-12 15:17:09Z kanani
206! - New RTM version 2.9: (Pavel Krc, Jaroslav Resler, ICS, Prague)
207!   added calculation of the MRT inside the RTM module
208!   MRT fluxes are consequently used in the new biometeorology module
209!   for calculation of biological indices (MRT, PET)
210!   Fixes of v. 2.5 and SVN trunk:
211!    - proper initialization of rad_net_l
212!    - make arrays nsurfs and surfstart TARGET to prevent some MPI problems
213!    - initialization of arrays used in MPI one-sided operation as 1-D arrays
214!      to prevent problems with some MPI/compiler combinations
215!    - fix indexing of target displacement in subroutine request_itarget to
216!      consider nzub
217!    - fix LAD dimmension range in PCB calculation
218!    - check ierr in all MPI calls
219!    - use proper per-gridbox sky and diffuse irradiance
220!    - fix shading for reflected irradiance
221!    - clear away the residuals of "atmospheric surfaces" implementation
222!    - fix rounding bug in raytrace_2d introduced in SVN trunk
223! - New RTM version 2.5: (Pavel Krc, Jaroslav Resler, ICS, Prague)
224!   can use angular discretization for all SVF
225!   (i.e. reflected and emitted radiation in addition to direct and diffuse),
226!   allowing for much better scaling wih high resoltion and/or complex terrain
227! - Unite array grow factors
228! - Fix slightly shifted terrain height in raytrace_2d
229! - Use more efficient MPI_Win_allocate for reverse gridsurf index
230! - Fix random MPI RMA bugs on Intel compilers
231! - Fix approx. double plant canopy sink values for reflected radiation
232! - Fix mostly missing plant canopy sinks for direct radiation
233! - Fix discretization errors for plant canopy sink in diffuse radiation
234! - Fix rounding errors in raytrace_2d
235!
236! 3274 2018-09-24 15:42:55Z knoop
237! Modularization of all bulk cloud physics code components
238!
239! 3272 2018-09-24 10:16:32Z suehring
240! - split direct and diffusion shortwave radiation using RRTMG rather than using
241!   calc_diffusion_radiation, in case of RRTMG
242! - removed the namelist variable split_diffusion_radiation. Now splitting depends
243!   on the choise of radiation radiation scheme
244! - removed calculating the rdiation flux for surfaces at the radiation scheme
245!   in case of using RTM since it will be calculated anyway in the radiation
246!   interaction routine.
247! - set SW radiation flux for surfaces to zero at night in case of no RTM is used
248! - precalculate the unit vector yxdir of ray direction to avoid the temporarly
249!   array allocation during the subroutine call
250! - fixed a bug in calculating the max number of boxes ray can cross in the domain
251!
252! 3264 2018-09-20 13:54:11Z moh.hefny
253! Bugfix in raytrace_2d calls
254!
255! 3248 2018-09-14 09:42:06Z sward
256! Minor formating changes
257!
258! 3246 2018-09-13 15:14:50Z sward
259! Added error handling for input namelist via parin_fail_message
260!
261! 3241 2018-09-12 15:02:00Z raasch
262! unused variables removed or commented
263!
264! 3233 2018-09-07 13:21:24Z schwenkel
265! Adapted for the use of cloud_droplets
266!
267! 3230 2018-09-05 09:29:05Z schwenkel
268! Bugfix in radiation_constant_surf: changed (10.0 - emissivity_urb) to
269! (1.0 - emissivity_urb)
270!
271! 3226 2018-08-31 12:27:09Z suehring
272! Bugfixes in calculation of sky-view factors and canopy-sink factors.
273!
274! 3186 2018-07-30 17:07:14Z suehring
275! Remove print statement
276!
277! 3180 2018-07-27 11:00:56Z suehring
278! Revise concept for calculation of effective radiative temperature and mapping
279! of radiative heating
280!
281! 3175 2018-07-26 14:07:38Z suehring
282! Bugfix for commit 3172
283!
284! 3173 2018-07-26 12:55:23Z suehring
285! Revise output of surface radiation quantities in case of overhanging
286! structures
287!
288! 3172 2018-07-26 12:06:06Z suehring
289! Bugfixes:
290!  - temporal work-around for calculation of effective radiative surface
291!    temperature
292!  - prevent positive solar radiation during nighttime
293!
294! 3170 2018-07-25 15:19:37Z suehring
295! Bugfix, map signle-column radiation forcing profiles on top of any topography
296!
297! 3156 2018-07-19 16:30:54Z knoop
298! Bugfix: replaced usage of the pt array with the surf%pt_surface array
299!
300! 3137 2018-07-17 06:44:21Z maronga
301! String length for trace_names fixed
302!
303! 3127 2018-07-15 08:01:25Z maronga
304! A few pavement parameters updated.
305!
306! 3123 2018-07-12 16:21:53Z suehring
307! Correct working precision for INTEGER number
308!
309! 3122 2018-07-11 21:46:41Z maronga
310! Bugfix: maximum distance for raytracing was set to  -999 m by default,
311! effectively switching off all surface reflections when max_raytracing_dist
312! was not explicitly set in namelist
313!
314! 3117 2018-07-11 09:59:11Z maronga
315! Bugfix: water vapor was not transfered to RRTMG when bulk_cloud_model = .F.
316! Bugfix: changed the calculation of RRTMG boundary conditions (Mohamed Salim)
317! Bugfix: dry residual atmosphere is replaced by standard RRTMG atmosphere
318!
319! 3116 2018-07-10 14:31:58Z suehring
320! Output of long/shortwave radiation at surface
321!
322! 3107 2018-07-06 15:55:51Z suehring
323! Bugfix, missing index for dz
324!
325! 3066 2018-06-12 08:55:55Z Giersch
326! Error message revised
327!
328! 3065 2018-06-12 07:03:02Z Giersch
329! dz was replaced by dz(1), error message concerning vertical stretching was
330! added 
331!
332! 3049 2018-05-29 13:52:36Z Giersch
333! Error messages revised
334!
335! 3045 2018-05-28 07:55:41Z Giersch
336! Error message revised
337!
338! 3026 2018-05-22 10:30:53Z schwenkel
339! Changed the name specific humidity to mixing ratio, since we are computing
340! mixing ratios.
341!
342! 3016 2018-05-09 10:53:37Z Giersch
343! Revised structure of reading svf data according to PALM coding standard:
344! svf_code_field/len and fsvf removed, error messages PA0493 and PA0494 added,
345! allocation status of output arrays checked.
346!
347! 3014 2018-05-09 08:42:38Z maronga
348! Introduced plant canopy height similar to urban canopy height to limit
349! the memory requirement to allocate lad.
350! Deactivated automatic setting of minimum raytracing distance.
351!
352! 3004 2018-04-27 12:33:25Z Giersch
353! Further allocation checks implemented (averaged data will be assigned to fill
354! values if no allocation happened so far)
355!
356! 2995 2018-04-19 12:13:16Z Giersch
357! IF-statement in radiation_init removed so that the calculation of radiative
358! fluxes at model start is done in any case, bugfix in
359! radiation_presimulate_solar_pos (end_time is the sum of end_time and the
360! spinup_time specified in the p3d_file ), list of variables/fields that have
361! to be written out or read in case of restarts has been extended
362!
363! 2977 2018-04-17 10:27:57Z kanani
364! Implement changes from branch radiation (r2948-2971) with minor modifications,
365! plus some formatting.
366! (moh.hefny):
367! - replaced plant_canopy by npcbl to check tree existence to avoid weird
368!   allocation of related arrays (after domain decomposition some domains
369!   contains no trees although plant_canopy (global parameter) is still TRUE).
370! - added a namelist parameter to force RTM settings
371! - enabled the option to switch radiation reflections off
372! - renamed surf_reflections to surface_reflections
373! - removed average_radiation flag from the namelist (now it is implicitly set
374!   in init_3d_model according to RTM)
375! - edited read and write sky view factors and CSF routines to account for
376!   the sub-domains which may not contain any of them
377!
378! 2967 2018-04-13 11:22:08Z raasch
379! bugfix: missing parallel cpp-directives added
380!
381! 2964 2018-04-12 16:04:03Z Giersch
382! Error message PA0491 has been introduced which could be previously found in
383! check_open. The variable numprocs_previous_run is only known in case of
384! initializing_actions == read_restart_data
385!
386! 2963 2018-04-12 14:47:44Z suehring
387! - Introduce index for vegetation/wall, pavement/green-wall and water/window
388!   surfaces, for clearer access of surface fraction, albedo, emissivity, etc. .
389! - Minor bugfix in initialization of albedo for window surfaces
390!
391! 2944 2018-04-03 16:20:18Z suehring
392! Fixed bad commit
393!
394! 2943 2018-04-03 16:17:10Z suehring
395! No read of nsurfl from SVF file since it is calculated in
396! radiation_interaction_init,
397! allocation of arrays in radiation_read_svf only if not yet allocated,
398! update of 2920 revision comment.
399!
400! 2932 2018-03-26 09:39:22Z maronga
401! renamed radiation_par to radiation_parameters
402!
403! 2930 2018-03-23 16:30:46Z suehring
404! Remove default surfaces from radiation model, does not make much sense to
405! apply radiation model without energy-balance solvers; Further, add check for
406! this.
407!
408! 2920 2018-03-22 11:22:01Z kanani
409! - Bugfix: Initialize pcbl array (=-1)
410! RTM version 2.0 (Jaroslav Resler, Pavel Krc, Mohamed Salim):
411! - new major version of radiation interactions
412! - substantially enhanced performance and scalability
413! - processing of direct and diffuse solar radiation separated from reflected
414!   radiation, removed virtual surfaces
415! - new type of sky discretization by azimuth and elevation angles
416! - diffuse radiation processed cumulatively using sky view factor
417! - used precalculated apparent solar positions for direct irradiance
418! - added new 2D raytracing process for processing whole vertical column at once
419!   to increase memory efficiency and decrease number of MPI RMA operations
420! - enabled limiting the number of view factors between surfaces by the distance
421!   and value
422! - fixing issues induced by transferring radiation interactions from
423!   urban_surface_mod to radiation_mod
424! - bugfixes and other minor enhancements
425!
426! 2906 2018-03-19 08:56:40Z Giersch
427! NAMELIST paramter read/write_svf_on_init have been removed, functions
428! check_open and close_file are used now for opening/closing files related to
429! svf data, adjusted unit number and error numbers
430!
431! 2894 2018-03-15 09:17:58Z Giersch
432! Calculations of the index range of the subdomain on file which overlaps with
433! the current subdomain are already done in read_restart_data_mod
434! radiation_read_restart_data was renamed to radiation_rrd_local and
435! radiation_last_actions was renamed to radiation_wrd_local, variable named
436! found has been introduced for checking if restart data was found, reading
437! of restart strings has been moved completely to read_restart_data_mod,
438! radiation_rrd_local is already inside the overlap loop programmed in
439! read_restart_data_mod, the marker *** end rad *** is not necessary anymore,
440! strings and their respective lengths are written out and read now in case of
441! restart runs to get rid of prescribed character lengths (Giersch)
442!
443! 2809 2018-02-15 09:55:58Z suehring
444! Bugfix for gfortran: Replace the function C_SIZEOF with STORAGE_SIZE
445!
446! 2753 2018-01-16 14:16:49Z suehring
447! Tile approach for spectral albedo implemented.
448!
449! 2746 2018-01-15 12:06:04Z suehring
450! Move flag plant canopy to modules
451!
452! 2724 2018-01-05 12:12:38Z maronga
453! Set default of average_radiation to .FALSE.
454!
455! 2723 2018-01-05 09:27:03Z maronga
456! Bugfix in calculation of rad_lw_out (clear-sky). First grid level was used
457! instead of the surface value
458!
459! 2718 2018-01-02 08:49:38Z maronga
460! Corrected "Former revisions" section
461!
462! 2707 2017-12-18 18:34:46Z suehring
463! Changes from last commit documented
464!
465! 2706 2017-12-18 18:33:49Z suehring
466! Bugfix, in average radiation case calculate exner function before using it.
467!
468! 2701 2017-12-15 15:40:50Z suehring
469! Changes from last commit documented
470!
471! 2698 2017-12-14 18:46:24Z suehring
472! Bugfix in get_topography_top_index
473!
474! 2696 2017-12-14 17:12:51Z kanani
475! - Change in file header (GPL part)
476! - Improved reading/writing of SVF from/to file (BM)
477! - Bugfixes concerning RRTMG as well as average_radiation options (M. Salim)
478! - Revised initialization of surface albedo and some minor bugfixes (MS)
479! - Update net radiation after running radiation interaction routine (MS)
480! - Revisions from M Salim included
481! - Adjustment to topography and surface structure (MS)
482! - Initialization of albedo and surface emissivity via input file (MS)
483! - albedo_pars extended (MS)
484!
485! 2604 2017-11-06 13:29:00Z schwenkel
486! bugfix for calculation of effective radius using morrison microphysics
487!
488! 2601 2017-11-02 16:22:46Z scharf
489! added emissivity to namelist
490!
491! 2575 2017-10-24 09:57:58Z maronga
492! Bugfix: calculation of shortwave and longwave albedos for RRTMG swapped
493!
494! 2547 2017-10-16 12:41:56Z schwenkel
495! extended by cloud_droplets option, minor bugfix and correct calculation of
496! cloud droplet number concentration
497!
498! 2544 2017-10-13 18:09:32Z maronga
499! Moved date and time quantitis to separate module date_and_time_mod
500!
501! 2512 2017-10-04 08:26:59Z raasch
502! upper bounds of cross section and 3d output changed from nx+1,ny+1 to nx,ny
503! no output of ghost layer data
504!
505! 2504 2017-09-27 10:36:13Z maronga
506! Updates pavement types and albedo parameters
507!
508! 2328 2017-08-03 12:34:22Z maronga
509! Emissivity can now be set individually for each pixel.
510! Albedo type can be inferred from land surface model.
511! Added default albedo type for bare soil
512!
513! 2318 2017-07-20 17:27:44Z suehring
514! Get topography top index via Function call
515!
516! 2317 2017-07-20 17:27:19Z suehring
517! Improved syntax layout
518!
519! 2298 2017-06-29 09:28:18Z raasch
520! type of write_binary changed from CHARACTER to LOGICAL
521!
522! 2296 2017-06-28 07:53:56Z maronga
523! Added output of rad_sw_out for radiation_scheme = 'constant'
524!
525! 2270 2017-06-09 12:18:47Z maronga
526! Numbering changed (2 timeseries removed)
527!
528! 2249 2017-06-06 13:58:01Z sward
529! Allow for RRTMG runs without humidity/cloud physics
530!
531! 2248 2017-06-06 13:52:54Z sward
532! Error no changed
533!
534! 2233 2017-05-30 18:08:54Z suehring
535!
536! 2232 2017-05-30 17:47:52Z suehring
537! Adjustments to new topography concept
538! Bugfix in read restart
539!
540! 2200 2017-04-11 11:37:51Z suehring
541! Bugfix in call of exchange_horiz_2d and read restart data
542!
543! 2163 2017-03-01 13:23:15Z schwenkel
544! Bugfix in radiation_check_data_output
545!
546! 2157 2017-02-22 15:10:35Z suehring
547! Bugfix in read_restart data
548!
549! 2011 2016-09-19 17:29:57Z kanani
550! Removed CALL of auxiliary SUBROUTINE get_usm_info,
551! flag urban_surface is now defined in module control_parameters.
552!
553! 2007 2016-08-24 15:47:17Z kanani
554! Added calculation of solar directional vector for new urban surface
555! model,
556! accounted for urban_surface model in radiation_check_parameters,
557! correction of comments for zenith angle.
558!
559! 2000 2016-08-20 18:09:15Z knoop
560! Forced header and separation lines into 80 columns
561!
562! 1976 2016-07-27 13:28:04Z maronga
563! Output of 2D/3D/masked data is now directly done within this module. The
564! radiation schemes have been simplified for better usability so that
565! rad_lw_in, rad_lw_out, rad_sw_in, and rad_sw_out are available independent of
566! the radiation code used.
567!
568! 1856 2016-04-13 12:56:17Z maronga
569! Bugfix: allocation of rad_lw_out for radiation_scheme = 'clear-sky'
570!
571! 1853 2016-04-11 09:00:35Z maronga
572! Added routine for radiation_scheme = constant.
573
574! 1849 2016-04-08 11:33:18Z hoffmann
575! Adapted for modularization of microphysics
576!
577! 1826 2016-04-07 12:01:39Z maronga
578! Further modularization.
579!
580! 1788 2016-03-10 11:01:04Z maronga
581! Added new albedo class for pavements / roads.
582!
583! 1783 2016-03-06 18:36:17Z raasch
584! palm-netcdf-module removed in order to avoid a circular module dependency,
585! netcdf-variables moved to netcdf-module, new routine netcdf_handle_error_rad
586! added
587!
588! 1757 2016-02-22 15:49:32Z maronga
589! Added parameter unscheduled_radiation_calls. Bugfix: interpolation of sounding
590! profiles for pressure and temperature above the LES domain.
591!
592! 1709 2015-11-04 14:47:01Z maronga
593! Bugfix: set initial value for rrtm_lwuflx_dt to zero, small formatting
594! corrections
595!
596! 1701 2015-11-02 07:43:04Z maronga
597! Bugfixes: wrong index for output of timeseries, setting of nz_snd_end
598!
599! 1691 2015-10-26 16:17:44Z maronga
600! Added option for spin-up runs without radiation (skip_time_do_radiation). Bugfix
601! in calculation of pressure profiles. Bugfix in calculation of trace gas profiles.
602! Added output of radiative heating rates.
603!
604! 1682 2015-10-07 23:56:08Z knoop
605! Code annotations made doxygen readable
606!
607! 1606 2015-06-29 10:43:37Z maronga
608! Added preprocessor directive __netcdf to allow for compiling without netCDF.
609! Note, however, that RRTMG cannot be used without netCDF.
610!
611! 1590 2015-05-08 13:56:27Z maronga
612! Bugfix: definition of character strings requires same length for all elements
613!
614! 1587 2015-05-04 14:19:01Z maronga
615! Added albedo class for snow
616!
617! 1585 2015-04-30 07:05:52Z maronga
618! Added support for RRTMG
619!
620! 1571 2015-03-12 16:12:49Z maronga
621! Added missing KIND attribute. Removed upper-case variable names
622!
623! 1551 2015-03-03 14:18:16Z maronga
624! Added support for data output. Various variables have been renamed. Added
625! interface for different radiation schemes (currently: clear-sky, constant, and
626! RRTM (not yet implemented).
627!
628! 1496 2014-12-02 17:25:50Z maronga
629! Initial revision
630!
631!
632! Description:
633! ------------
634!> Radiation models and interfaces
635!> @todo Replace dz(1) appropriatly to account for grid stretching
636!> @todo move variable definitions used in radiation_init only to the subroutine
637!>       as they are no longer required after initialization.
638!> @todo Output of full column vertical profiles used in RRTMG
639!> @todo Output of other rrtm arrays (such as volume mixing ratios)
640!> @todo Check for mis-used NINT() calls in raytrace_2d
641!>       RESULT: Original was correct (carefully verified formula), the change
642!>               to INT broke raytracing      -- P. Krc
643!> @todo Optimize radiation_tendency routines
644!>
645!> @note Many variables have a leading dummy dimension (0:0) in order to
646!>       match the assume-size shape expected by the RRTMG model.
647!------------------------------------------------------------------------------!
648 MODULE radiation_model_mod
649 
650    USE arrays_3d,                                                             &
651        ONLY:  dzw, hyp, nc, pt, p, q, ql, u, v, w, zu, zw, exner, d_exner
652
653    USE basic_constants_and_equations_mod,                                     &
654        ONLY:  c_p, g, lv_d_cp, l_v, pi, r_d, rho_l, solar_constant, sigma_sb, &
655               barometric_formula
656
657    USE calc_mean_profile_mod,                                                 &
658        ONLY:  calc_mean_profile
659
660    USE control_parameters,                                                    &
661        ONLY:  cloud_droplets, coupling_char,                                  &
662               debug_output, debug_output_timestep, debug_string,              &
663               dz, dt_spinup, end_time,                                        &
664               humidity,                                                       &
665               initializing_actions, io_blocks, io_group,                      &
666               land_surface, large_scale_forcing,                              &
667               latitude, longitude, lsf_surf,                                  &
668               message_string, plant_canopy, pt_surface,                       &
669               rho_surface, simulated_time, spinup_time, surface_pressure,     &
670               read_svf, write_svf,                                            &
671               time_since_reference_point, urban_surface, varnamelength
672
673    USE cpulog,                                                                &
674        ONLY:  cpu_log, log_point, log_point_s
675
676    USE grid_variables,                                                        &
677         ONLY:  ddx, ddy, dx, dy 
678
679    USE date_and_time_mod,                                                     &
680        ONLY:  calc_date_and_time, d_hours_day, d_seconds_hour, d_seconds_year,&
681               day_of_year, d_seconds_year, day_of_month, day_of_year_init,    &
682               init_date_and_time, month_of_year, time_utc_init, time_utc
683
684    USE indices,                                                               &
685        ONLY:  nnx, nny, nx, nxl, nxlg, nxr, nxrg, ny, nyn, nyng, nys, nysg,   &
686               nzb, nzt
687
688    USE, INTRINSIC :: iso_c_binding
689
690    USE kinds
691
692    USE bulk_cloud_model_mod,                                                  &
693        ONLY:  bulk_cloud_model, microphysics_morrison, na_init, nc_const, sigma_gc
694
695#if defined ( __netcdf )
696    USE NETCDF
697#endif
698
699    USE netcdf_data_input_mod,                                                 &
700        ONLY:  albedo_type_f, albedo_pars_f, building_type_f, pavement_type_f, &
701               vegetation_type_f, water_type_f
702
703    USE plant_canopy_model_mod,                                                &
704        ONLY:  lad_s, pc_heating_rate, pc_transpiration_rate, pc_latent_rate,  &
705               plant_canopy_transpiration, pcm_calc_transpiration_rate
706
707    USE pegrid
708
709#if defined ( __rrtmg )
710    USE parrrsw,                                                               &
711        ONLY:  naerec, nbndsw
712
713    USE parrrtm,                                                               &
714        ONLY:  nbndlw
715
716    USE rrtmg_lw_init,                                                         &
717        ONLY:  rrtmg_lw_ini
718
719    USE rrtmg_sw_init,                                                         &
720        ONLY:  rrtmg_sw_ini
721
722    USE rrtmg_lw_rad,                                                          &
723        ONLY:  rrtmg_lw
724
725    USE rrtmg_sw_rad,                                                          &
726        ONLY:  rrtmg_sw
727#endif
728    USE statistics,                                                            &
729        ONLY:  hom
730
731    USE surface_mod,                                                           &
732        ONLY:  get_topography_top_index, get_topography_top_index_ji,          &
733               ind_pav_green, ind_veg_wall, ind_wat_win,                       &
734               surf_lsm_h, surf_lsm_v, surf_type, surf_usm_h, surf_usm_v,      &
735               vertical_surfaces_exist
736
737    IMPLICIT NONE
738
739    CHARACTER(10) :: radiation_scheme = 'clear-sky' ! 'constant', 'clear-sky', or 'rrtmg'
740
741!
742!-- Predefined Land surface classes (albedo_type) after Briegleb (1992)
743    CHARACTER(37), DIMENSION(0:33), PARAMETER :: albedo_type_name = (/      &
744                                   'user defined                         ', & !  0
745                                   'ocean                                ', & !  1
746                                   'mixed farming, tall grassland        ', & !  2
747                                   'tall/medium grassland                ', & !  3
748                                   'evergreen shrubland                  ', & !  4
749                                   'short grassland/meadow/shrubland     ', & !  5
750                                   'evergreen needleleaf forest          ', & !  6
751                                   'mixed deciduous evergreen forest     ', & !  7
752                                   'deciduous forest                     ', & !  8
753                                   'tropical evergreen broadleaved forest', & !  9
754                                   'medium/tall grassland/woodland       ', & ! 10
755                                   'desert, sandy                        ', & ! 11
756                                   'desert, rocky                        ', & ! 12
757                                   'tundra                               ', & ! 13
758                                   'land ice                             ', & ! 14
759                                   'sea ice                              ', & ! 15
760                                   'snow                                 ', & ! 16
761                                   'bare soil                            ', & ! 17
762                                   'asphalt/concrete mix                 ', & ! 18
763                                   'asphalt (asphalt concrete)           ', & ! 19
764                                   'concrete (Portland concrete)         ', & ! 20
765                                   'sett                                 ', & ! 21
766                                   'paving stones                        ', & ! 22
767                                   'cobblestone                          ', & ! 23
768                                   'metal                                ', & ! 24
769                                   'wood                                 ', & ! 25
770                                   'gravel                               ', & ! 26
771                                   'fine gravel                          ', & ! 27
772                                   'pebblestone                          ', & ! 28
773                                   'woodchips                            ', & ! 29
774                                   'tartan (sports)                      ', & ! 30
775                                   'artifical turf (sports)              ', & ! 31
776                                   'clay (sports)                        ', & ! 32
777                                   'building (dummy)                     '  & ! 33
778                                                         /)
779
780    INTEGER(iwp) :: albedo_type  = 9999999_iwp, &     !< Albedo surface type
781                    dots_rad     = 0_iwp              !< starting index for timeseries output
782
783    LOGICAL ::  unscheduled_radiation_calls = .TRUE., & !< flag parameter indicating whether additional calls of the radiation code are allowed
784                constant_albedo = .FALSE.,            & !< flag parameter indicating whether the albedo may change depending on zenith
785                force_radiation_call = .FALSE.,       & !< flag parameter for unscheduled radiation calls
786                lw_radiation = .TRUE.,                & !< flag parameter indicating whether longwave radiation shall be calculated
787                radiation = .FALSE.,                  & !< flag parameter indicating whether the radiation model is used
788                sun_up    = .TRUE.,                   & !< flag parameter indicating whether the sun is up or down
789                sw_radiation = .TRUE.,                & !< flag parameter indicating whether shortwave radiation shall be calculated
790                sun_direction = .FALSE.,              & !< flag parameter indicating whether solar direction shall be calculated
791                average_radiation = .FALSE.,          & !< flag to set the calculation of radiation averaging for the domain
792                radiation_interactions = .FALSE.,     & !< flag to activiate RTM (TRUE only if vertical urban/land surface and trees exist)
793                surface_reflections = .TRUE.,         & !< flag to switch the calculation of radiation interaction between surfaces.
794                                                        !< When it switched off, only the effect of buildings and trees shadow
795                                                        !< will be considered. However fewer SVFs are expected.
796                radiation_interactions_on = .TRUE.      !< namelist flag to force RTM activiation regardless to vertical urban/land surface and trees
797
798    REAL(wp) :: albedo = 9999999.9_wp,           & !< NAMELIST alpha
799                albedo_lw_dif = 9999999.9_wp,    & !< NAMELIST aldif
800                albedo_lw_dir = 9999999.9_wp,    & !< NAMELIST aldir
801                albedo_sw_dif = 9999999.9_wp,    & !< NAMELIST asdif
802                albedo_sw_dir = 9999999.9_wp,    & !< NAMELIST asdir
803                decl_1,                          & !< declination coef. 1
804                decl_2,                          & !< declination coef. 2
805                decl_3,                          & !< declination coef. 3
806                dt_radiation = 0.0_wp,           & !< radiation model timestep
807                emissivity = 9999999.9_wp,       & !< NAMELIST surface emissivity
808                lon = 0.0_wp,                    & !< longitude in radians
809                lat = 0.0_wp,                    & !< latitude in radians
810                net_radiation = 0.0_wp,          & !< net radiation at surface
811                skip_time_do_radiation = 0.0_wp, & !< Radiation model is not called before this time
812                sky_trans,                       & !< sky transmissivity
813                time_radiation = 0.0_wp            !< time since last call of radiation code
814
815
816    REAL(wp) ::  cos_zenith        !< cosine of solar zenith angle, also z-coordinate of solar unit vector
817    REAL(wp) ::  sun_dir_lat       !< y-coordinate of solar unit vector
818    REAL(wp) ::  sun_dir_lon       !< x-coordinate of solar unit vector
819
820    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_net_av       !< average of net radiation (rad_net) at surface
821    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_lw_in_xy_av  !< average of incoming longwave radiation at surface
822    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_lw_out_xy_av !< average of outgoing longwave radiation at surface
823    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_sw_in_xy_av  !< average of incoming shortwave radiation at surface
824    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_sw_out_xy_av !< average of outgoing shortwave radiation at surface
825
826    REAL(wp), PARAMETER :: emissivity_atm_clsky = 0.8_wp       !< emissivity of the clear-sky atmosphere
827!
828!-- Land surface albedos for solar zenith angle of 60degree after Briegleb (1992)     
829!-- (broadband, longwave, shortwave ):   bb,      lw,      sw,
830    REAL(wp), DIMENSION(0:2,1:33), PARAMETER :: albedo_pars = RESHAPE( (/& 
831                                   0.06_wp, 0.06_wp, 0.06_wp,            & !  1
832                                   0.19_wp, 0.28_wp, 0.09_wp,            & !  2
833                                   0.23_wp, 0.33_wp, 0.11_wp,            & !  3
834                                   0.23_wp, 0.33_wp, 0.11_wp,            & !  4
835                                   0.25_wp, 0.34_wp, 0.14_wp,            & !  5
836                                   0.14_wp, 0.22_wp, 0.06_wp,            & !  6
837                                   0.17_wp, 0.27_wp, 0.06_wp,            & !  7
838                                   0.19_wp, 0.31_wp, 0.06_wp,            & !  8
839                                   0.14_wp, 0.22_wp, 0.06_wp,            & !  9
840                                   0.18_wp, 0.28_wp, 0.06_wp,            & ! 10
841                                   0.43_wp, 0.51_wp, 0.35_wp,            & ! 11
842                                   0.32_wp, 0.40_wp, 0.24_wp,            & ! 12
843                                   0.19_wp, 0.27_wp, 0.10_wp,            & ! 13
844                                   0.77_wp, 0.65_wp, 0.90_wp,            & ! 14
845                                   0.77_wp, 0.65_wp, 0.90_wp,            & ! 15
846                                   0.82_wp, 0.70_wp, 0.95_wp,            & ! 16
847                                   0.08_wp, 0.08_wp, 0.08_wp,            & ! 17
848                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 18
849                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 19
850                                   0.30_wp, 0.30_wp, 0.30_wp,            & ! 20
851                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 21
852                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 22
853                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 23
854                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 24
855                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 25
856                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 26
857                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 27
858                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 28
859                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 29
860                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 30
861                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 31
862                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 32
863                                   0.17_wp, 0.17_wp, 0.17_wp             & ! 33
864                                 /), (/ 3, 33 /) )
865
866    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE, TARGET :: &
867                        rad_lw_cs_hr,                  & !< longwave clear sky radiation heating rate (K/s)
868                        rad_lw_cs_hr_av,               & !< average of rad_lw_cs_hr
869                        rad_lw_hr,                     & !< longwave radiation heating rate (K/s)
870                        rad_lw_hr_av,                  & !< average of rad_sw_hr
871                        rad_lw_in,                     & !< incoming longwave radiation (W/m2)
872                        rad_lw_in_av,                  & !< average of rad_lw_in
873                        rad_lw_out,                    & !< outgoing longwave radiation (W/m2)
874                        rad_lw_out_av,                 & !< average of rad_lw_out
875                        rad_sw_cs_hr,                  & !< shortwave clear sky radiation heating rate (K/s)
876                        rad_sw_cs_hr_av,               & !< average of rad_sw_cs_hr
877                        rad_sw_hr,                     & !< shortwave radiation heating rate (K/s)
878                        rad_sw_hr_av,                  & !< average of rad_sw_hr
879                        rad_sw_in,                     & !< incoming shortwave radiation (W/m2)
880                        rad_sw_in_av,                  & !< average of rad_sw_in
881                        rad_sw_out,                    & !< outgoing shortwave radiation (W/m2)
882                        rad_sw_out_av                    !< average of rad_sw_out
883
884
885!
886!-- Variables and parameters used in RRTMG only
887#if defined ( __rrtmg )
888    CHARACTER(LEN=12) :: rrtm_input_file = "RAD_SND_DATA" !< name of the NetCDF input file (sounding data)
889
890
891!
892!-- Flag parameters to be passed to RRTMG (should not be changed until ice phase in clouds is allowed)
893    INTEGER(iwp), PARAMETER :: rrtm_idrv     = 1, & !< flag for longwave upward flux calculation option (0,1)
894                               rrtm_inflglw  = 2, & !< flag for lw cloud optical properties (0,1,2)
895                               rrtm_iceflglw = 0, & !< flag for lw ice particle specifications (0,1,2,3)
896                               rrtm_liqflglw = 1, & !< flag for lw liquid droplet specifications
897                               rrtm_inflgsw  = 2, & !< flag for sw cloud optical properties (0,1,2)
898                               rrtm_iceflgsw = 0, & !< flag for sw ice particle specifications (0,1,2,3)
899                               rrtm_liqflgsw = 1    !< flag for sw liquid droplet specifications
900
901!
902!-- The following variables should be only changed with care, as this will
903!-- require further setting of some variables, which is currently not
904!-- implemented (aerosols, ice phase).
905    INTEGER(iwp) :: nzt_rad,           & !< upper vertical limit for radiation calculations
906                    rrtm_icld = 0,     & !< cloud flag (0: clear sky column, 1: cloudy column)
907                    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)
908
909    INTEGER(iwp) :: nc_stat !< local variable for storin the result of netCDF calls for error message handling
910
911    LOGICAL :: snd_exists = .FALSE.      !< flag parameter to check whether a user-defined input files exists
912    LOGICAL :: sw_exists = .FALSE.       !< flag parameter to check whether that required rrtmg sw file exists
913    LOGICAL :: lw_exists = .FALSE.       !< flag parameter to check whether that required rrtmg lw file exists
914
915
916    REAL(wp), PARAMETER :: mol_mass_air_d_wv = 1.607793_wp !< molecular weight dry air / water vapor
917
918    REAL(wp), DIMENSION(:), ALLOCATABLE :: hyp_snd,     & !< hypostatic pressure from sounding data (hPa)
919                                           rrtm_tsfc,   & !< dummy array for storing surface temperature
920                                           t_snd          !< actual temperature from sounding data (hPa)
921
922    REAL(wp), DIMENSION(:,:), ALLOCATABLE :: rrtm_ccl4vmr,   & !< CCL4 volume mixing ratio (g/mol)
923                                             rrtm_cfc11vmr,  & !< CFC11 volume mixing ratio (g/mol)
924                                             rrtm_cfc12vmr,  & !< CFC12 volume mixing ratio (g/mol)
925                                             rrtm_cfc22vmr,  & !< CFC22 volume mixing ratio (g/mol)
926                                             rrtm_ch4vmr,    & !< CH4 volume mixing ratio
927                                             rrtm_cicewp,    & !< in-cloud ice water path (g/m2)
928                                             rrtm_cldfr,     & !< cloud fraction (0,1)
929                                             rrtm_cliqwp,    & !< in-cloud liquid water path (g/m2)
930                                             rrtm_co2vmr,    & !< CO2 volume mixing ratio (g/mol)
931                                             rrtm_emis,      & !< surface emissivity (0-1) 
932                                             rrtm_h2ovmr,    & !< H2O volume mixing ratio
933                                             rrtm_n2ovmr,    & !< N2O volume mixing ratio
934                                             rrtm_o2vmr,     & !< O2 volume mixing ratio
935                                             rrtm_o3vmr,     & !< O3 volume mixing ratio
936                                             rrtm_play,      & !< pressure layers (hPa, zu-grid)
937                                             rrtm_plev,      & !< pressure layers (hPa, zw-grid)
938                                             rrtm_reice,     & !< cloud ice effective radius (microns)
939                                             rrtm_reliq,     & !< cloud water drop effective radius (microns)
940                                             rrtm_tlay,      & !< actual temperature (K, zu-grid)
941                                             rrtm_tlev,      & !< actual temperature (K, zw-grid)
942                                             rrtm_lwdflx,    & !< RRTM output of incoming longwave radiation flux (W/m2)
943                                             rrtm_lwdflxc,   & !< RRTM output of outgoing clear sky longwave radiation flux (W/m2)
944                                             rrtm_lwuflx,    & !< RRTM output of outgoing longwave radiation flux (W/m2)
945                                             rrtm_lwuflxc,   & !< RRTM output of incoming clear sky longwave radiation flux (W/m2)
946                                             rrtm_lwuflx_dt, & !< RRTM output of incoming clear sky longwave radiation flux (W/m2)
947                                             rrtm_lwuflxc_dt,& !< RRTM output of outgoing clear sky longwave radiation flux (W/m2)
948                                             rrtm_lwhr,      & !< RRTM output of longwave radiation heating rate (K/d)
949                                             rrtm_lwhrc,     & !< RRTM output of incoming longwave clear sky radiation heating rate (K/d)
950                                             rrtm_swdflx,    & !< RRTM output of incoming shortwave radiation flux (W/m2)
951                                             rrtm_swdflxc,   & !< RRTM output of outgoing clear sky shortwave radiation flux (W/m2)
952                                             rrtm_swuflx,    & !< RRTM output of outgoing shortwave radiation flux (W/m2)
953                                             rrtm_swuflxc,   & !< RRTM output of incoming clear sky shortwave radiation flux (W/m2)
954                                             rrtm_swhr,      & !< RRTM output of shortwave radiation heating rate (K/d)
955                                             rrtm_swhrc,     & !< RRTM output of incoming shortwave clear sky radiation heating rate (K/d)
956                                             rrtm_dirdflux,  & !< RRTM output of incoming direct shortwave (W/m2)
957                                             rrtm_difdflux     !< RRTM output of incoming diffuse shortwave (W/m2)
958
959    REAL(wp), DIMENSION(1) ::                rrtm_aldif,     & !< surface albedo for longwave diffuse radiation
960                                             rrtm_aldir,     & !< surface albedo for longwave direct radiation
961                                             rrtm_asdif,     & !< surface albedo for shortwave diffuse radiation
962                                             rrtm_asdir        !< surface albedo for shortwave direct radiation
963
964!
965!-- Definition of arrays that are currently not used for calling RRTMG (due to setting of flag parameters)
966    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::  rad_lw_cs_in,   & !< incoming clear sky longwave radiation (W/m2) (not used)
967                                                rad_lw_cs_out,  & !< outgoing clear sky longwave radiation (W/m2) (not used)
968                                                rad_sw_cs_in,   & !< incoming clear sky shortwave radiation (W/m2) (not used)
969                                                rad_sw_cs_out,  & !< outgoing clear sky shortwave radiation (W/m2) (not used)
970                                                rrtm_lw_tauaer, & !< lw aerosol optical depth
971                                                rrtm_lw_taucld, & !< lw in-cloud optical depth
972                                                rrtm_sw_taucld, & !< sw in-cloud optical depth
973                                                rrtm_sw_ssacld, & !< sw in-cloud single scattering albedo
974                                                rrtm_sw_asmcld, & !< sw in-cloud asymmetry parameter
975                                                rrtm_sw_fsfcld, & !< sw in-cloud forward scattering fraction
976                                                rrtm_sw_tauaer, & !< sw aerosol optical depth
977                                                rrtm_sw_ssaaer, & !< sw aerosol single scattering albedo
978                                                rrtm_sw_asmaer, & !< sw aerosol asymmetry parameter
979                                                rrtm_sw_ecaer     !< sw aerosol optical detph at 0.55 microns (rrtm_iaer = 6 only)
980
981#endif
982!
983!-- Parameters of urban and land surface models
984    INTEGER(iwp)                                   ::  nz_urban                           !< number of layers of urban surface (will be calculated)
985    INTEGER(iwp)                                   ::  nz_plant                           !< number of layers of plant canopy (will be calculated)
986    INTEGER(iwp)                                   ::  nz_urban_b                         !< bottom layer of urban surface (will be calculated)
987    INTEGER(iwp)                                   ::  nz_urban_t                         !< top layer of urban surface (will be calculated)
988    INTEGER(iwp)                                   ::  nz_plant_t                         !< top layer of plant canopy (will be calculated)
989!-- parameters of urban and land surface models
990    INTEGER(iwp), PARAMETER                        ::  nzut_free = 3                      !< number of free layers above top of of topography
991    INTEGER(iwp), PARAMETER                        ::  ndsvf = 2                          !< number of dimensions of real values in SVF
992    INTEGER(iwp), PARAMETER                        ::  idsvf = 2                          !< number of dimensions of integer values in SVF
993    INTEGER(iwp), PARAMETER                        ::  ndcsf = 1                          !< number of dimensions of real values in CSF
994    INTEGER(iwp), PARAMETER                        ::  idcsf = 2                          !< number of dimensions of integer values in CSF
995    INTEGER(iwp), PARAMETER                        ::  kdcsf = 4                          !< number of dimensions of integer values in CSF calculation array
996    INTEGER(iwp), PARAMETER                        ::  id = 1                             !< position of d-index in surfl and surf
997    INTEGER(iwp), PARAMETER                        ::  iz = 2                             !< position of k-index in surfl and surf
998    INTEGER(iwp), PARAMETER                        ::  iy = 3                             !< position of j-index in surfl and surf
999    INTEGER(iwp), PARAMETER                        ::  ix = 4                             !< position of i-index in surfl and surf
1000    INTEGER(iwp), PARAMETER                        ::  im = 5                             !< position of surface m-index in surfl and surf
1001    INTEGER(iwp), PARAMETER                        ::  nidx_surf = 5                      !< number of indices in surfl and surf
1002
1003    INTEGER(iwp), PARAMETER                        ::  nsurf_type = 10                    !< number of surf types incl. phys.(land+urban) & (atm.,sky,boundary) surfaces - 1
1004
1005    INTEGER(iwp), PARAMETER                        ::  iup_u    = 0                       !< 0 - index of urban upward surface (ground or roof)
1006    INTEGER(iwp), PARAMETER                        ::  idown_u  = 1                       !< 1 - index of urban downward surface (overhanging)
1007    INTEGER(iwp), PARAMETER                        ::  inorth_u = 2                       !< 2 - index of urban northward facing wall
1008    INTEGER(iwp), PARAMETER                        ::  isouth_u = 3                       !< 3 - index of urban southward facing wall
1009    INTEGER(iwp), PARAMETER                        ::  ieast_u  = 4                       !< 4 - index of urban eastward facing wall
1010    INTEGER(iwp), PARAMETER                        ::  iwest_u  = 5                       !< 5 - index of urban westward facing wall
1011
1012    INTEGER(iwp), PARAMETER                        ::  iup_l    = 6                       !< 6 - index of land upward surface (ground or roof)
1013    INTEGER(iwp), PARAMETER                        ::  inorth_l = 7                       !< 7 - index of land northward facing wall
1014    INTEGER(iwp), PARAMETER                        ::  isouth_l = 8                       !< 8 - index of land southward facing wall
1015    INTEGER(iwp), PARAMETER                        ::  ieast_l  = 9                       !< 9 - index of land eastward facing wall
1016    INTEGER(iwp), PARAMETER                        ::  iwest_l  = 10                      !< 10- index of land westward facing wall
1017
1018    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  idir = (/0, 0,0, 0,1,-1,0,0, 0,1,-1/)   !< surface normal direction x indices
1019    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  jdir = (/0, 0,1,-1,0, 0,0,1,-1,0, 0/)   !< surface normal direction y indices
1020    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  kdir = (/1,-1,0, 0,0, 0,1,0, 0,0, 0/)   !< surface normal direction z indices
1021    REAL(wp),     DIMENSION(0:nsurf_type)          :: facearea                            !< area of single face in respective
1022                                                                                          !< direction (will be calc'd)
1023
1024
1025!-- indices and sizes of urban and land surface models
1026    INTEGER(iwp)                                   ::  startland        !< start index of block of land and roof surfaces
1027    INTEGER(iwp)                                   ::  endland          !< end index of block of land and roof surfaces
1028    INTEGER(iwp)                                   ::  nlands           !< number of land and roof surfaces in local processor
1029    INTEGER(iwp)                                   ::  startwall        !< start index of block of wall surfaces
1030    INTEGER(iwp)                                   ::  endwall          !< end index of block of wall surfaces
1031    INTEGER(iwp)                                   ::  nwalls           !< number of wall surfaces in local processor
1032
1033!-- indices needed for RTM netcdf output subroutines
1034    INTEGER(iwp), PARAMETER                        :: nd = 5
1035    CHARACTER(LEN=6), DIMENSION(0:nd-1), PARAMETER :: dirname = (/ '_roof ', '_south', '_north', '_west ', '_east ' /)
1036    INTEGER(iwp), DIMENSION(0:nd-1), PARAMETER     :: dirint_u = (/ iup_u, isouth_u, inorth_u, iwest_u, ieast_u /)
1037    INTEGER(iwp), DIMENSION(0:nd-1), PARAMETER     :: dirint_l = (/ iup_l, isouth_l, inorth_l, iwest_l, ieast_l /)
1038    INTEGER(iwp), DIMENSION(0:nd-1)                :: dirstart
1039    INTEGER(iwp), DIMENSION(0:nd-1)                :: dirend
1040
1041!-- indices and sizes of urban and land surface models
1042    INTEGER(iwp), DIMENSION(:,:), POINTER          ::  surfl            !< coordinates of i-th local surface in local grid - surfl[:,k] = [d, z, y, x, m]
1043    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surfl_linear     !< dtto (linearly allocated array)
1044    INTEGER(iwp), DIMENSION(:,:), POINTER          ::  surf             !< coordinates of i-th surface in grid - surf[:,k] = [d, z, y, x, m]
1045    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surf_linear      !< dtto (linearly allocated array)
1046    INTEGER(iwp)                                   ::  nsurfl           !< number of all surfaces in local processor
1047    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  nsurfs           !< array of number of all surfaces in individual processors
1048    INTEGER(iwp)                                   ::  nsurf            !< global number of surfaces in index array of surfaces (nsurf = proc nsurfs)
1049    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surfstart        !< starts of blocks of surfaces for individual processors in array surf (indexed from 1)
1050                                                                        !< respective block for particular processor is surfstart[iproc+1]+1 : surfstart[iproc+1]+nsurfs[iproc+1]
1051
1052!-- block variables needed for calculation of the plant canopy model inside the urban surface model
1053    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pct              !< top layer of the plant canopy
1054    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pch              !< heights of the plant canopy
1055    INTEGER(iwp)                                   ::  npcbl = 0        !< number of the plant canopy gridboxes in local processor
1056    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pcbl             !< k,j,i coordinates of l-th local plant canopy box pcbl[:,l] = [k, j, i]
1057    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinsw          !< array of absorbed sw radiation for local plant canopy box
1058    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdir       !< array of absorbed direct sw radiation for local plant canopy box
1059    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdif       !< array of absorbed diffusion sw radiation for local plant canopy box
1060    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinlw          !< array of absorbed lw radiation for local plant canopy box
1061
1062!-- configuration parameters (they can be setup in PALM config)
1063    LOGICAL                                        ::  raytrace_mpi_rma = .TRUE.          !< use MPI RMA to access LAD and gridsurf from remote processes during raytracing
1064    LOGICAL                                        ::  rad_angular_discretization = .TRUE.!< whether to use fixed resolution discretization of view factors for
1065                                                                                          !< reflected radiation (as opposed to all mutually visible pairs)
1066    LOGICAL                                        ::  plant_lw_interact = .TRUE.         !< whether plant canopy interacts with LW radiation (in addition to SW)
1067    INTEGER(iwp)                                   ::  mrt_nlevels = 0                    !< number of vertical boxes above surface for which to calculate MRT
1068    LOGICAL                                        ::  mrt_skip_roof = .TRUE.             !< do not calculate MRT above roof surfaces
1069    LOGICAL                                        ::  mrt_include_sw = .TRUE.            !< should MRT calculation include SW radiation as well?
1070    LOGICAL                                        ::  mrt_geom_human = .TRUE.            !< MRT direction weights simulate human body instead of a sphere
1071    INTEGER(iwp)                                   ::  nrefsteps = 3                      !< number of reflection steps to perform
1072    REAL(wp), PARAMETER                            ::  ext_coef = 0.6_wp                  !< extinction coefficient (a.k.a. alpha)
1073    INTEGER(iwp), PARAMETER                        ::  rad_version_len = 10               !< length of identification string of rad version
1074    CHARACTER(rad_version_len), PARAMETER          ::  rad_version = 'RAD v. 3.0'         !< identification of version of binary svf and restart files
1075    INTEGER(iwp)                                   ::  raytrace_discrete_elevs = 40       !< number of discretization steps for elevation (nadir to zenith)
1076    INTEGER(iwp)                                   ::  raytrace_discrete_azims = 80       !< number of discretization steps for azimuth (out of 360 degrees)
1077    REAL(wp)                                       ::  max_raytracing_dist = -999.0_wp    !< maximum distance for raytracing (in metres)
1078    REAL(wp)                                       ::  min_irrf_value = 1e-6_wp           !< minimum potential irradiance factor value for raytracing
1079    REAL(wp), DIMENSION(1:30)                      ::  svfnorm_report_thresh = 1e21_wp    !< thresholds of SVF normalization values to report
1080    INTEGER(iwp)                                   ::  svfnorm_report_num                 !< number of SVF normalization thresholds to report
1081
1082!-- radiation related arrays to be used in radiation_interaction routine
1083    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_sw_in_dir    !< direct sw radiation
1084    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_sw_in_diff   !< diffusion sw radiation
1085    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_lw_in_diff   !< diffusion lw radiation
1086
1087!-- parameters required for RRTMG lower boundary condition
1088    REAL(wp)                   :: albedo_urb      !< albedo value retuned to RRTMG boundary cond.
1089    REAL(wp)                   :: emissivity_urb  !< emissivity value retuned to RRTMG boundary cond.
1090    REAL(wp)                   :: t_rad_urb       !< temperature value retuned to RRTMG boundary cond.
1091
1092!-- type for calculation of svf
1093    TYPE t_svf
1094        INTEGER(iwp)                               :: isurflt           !<
1095        INTEGER(iwp)                               :: isurfs            !<
1096        REAL(wp)                                   :: rsvf              !<
1097        REAL(wp)                                   :: rtransp           !<
1098    END TYPE
1099
1100!-- type for calculation of csf
1101    TYPE t_csf
1102        INTEGER(iwp)                               :: ip                !<
1103        INTEGER(iwp)                               :: itx               !<
1104        INTEGER(iwp)                               :: ity               !<
1105        INTEGER(iwp)                               :: itz               !<
1106        INTEGER(iwp)                               :: isurfs            !< Idx of source face / -1 for sky
1107        REAL(wp)                                   :: rcvf              !< Canopy view factor for faces /
1108                                                                        !< canopy sink factor for sky (-1)
1109    END TYPE
1110
1111!-- arrays storing the values of USM
1112    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  svfsurf          !< svfsurf[:,isvf] = index of target and source surface for svf[isvf]
1113    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  svf              !< array of shape view factors+direct irradiation factors for local surfaces
1114    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfins          !< array of sw radiation falling to local surface after i-th reflection
1115    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinl          !< array of lw radiation for local surface after i-th reflection
1116
1117    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  skyvf            !< array of sky view factor for each local surface
1118    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  skyvft           !< array of sky view factor including transparency for each local surface
1119    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsitrans         !< dsidir[isvfl,i] = path transmittance of i-th
1120                                                                        !< direction of direct solar irradiance per target surface
1121    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsitransc        !< dtto per plant canopy box
1122    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsidir           !< dsidir[:,i] = unit vector of i-th
1123                                                                        !< direction of direct solar irradiance
1124    INTEGER(iwp)                                   ::  ndsidir          !< number of apparent solar directions used
1125    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  dsidir_rev       !< dsidir_rev[ielev,iazim] = i for dsidir or -1 if not present
1126
1127    INTEGER(iwp)                                   ::  nmrtbl           !< No. of local grid boxes for which MRT is calculated
1128    INTEGER(iwp)                                   ::  nmrtf            !< number of MRT factors for local processor
1129    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  mrtbl            !< coordinates of i-th local MRT box - surfl[:,i] = [z, y, x]
1130    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  mrtfsurf         !< mrtfsurf[:,imrtf] = index of target MRT box and source surface for mrtf[imrtf]
1131    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtf             !< array of MRT factors for each local MRT box
1132    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtft            !< array of MRT factors including transparency for each local MRT box
1133    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtsky           !< array of sky view factor for each local MRT box
1134    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtskyt          !< array of sky view factor including transparency for each local MRT box
1135    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  mrtdsit          !< array of direct solar transparencies for each local MRT box
1136    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinsw          !< mean SW radiant flux for each MRT box
1137    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinlw          !< mean LW radiant flux for each MRT box
1138    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrt              !< mean radiant temperature for each MRT box
1139    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinsw_av       !< time average mean SW radiant flux for each MRT box
1140    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinlw_av       !< time average mean LW radiant flux for each MRT box
1141    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrt_av           !< time average mean radiant temperature for each MRT box
1142
1143    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinsw         !< array of sw radiation falling to local surface including radiation from reflections
1144    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlw         !< array of lw radiation falling to local surface including radiation from reflections
1145    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdir      !< array of direct sw radiation falling to local surface
1146    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdif      !< array of diffuse sw radiation from sky and model boundary falling to local surface
1147    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwdif      !< array of diffuse lw radiation from sky and model boundary falling to local surface
1148   
1149                                                                        !< Outward radiation is only valid for nonvirtual surfaces
1150    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsl        !< array of reflected sw radiation for local surface in i-th reflection
1151    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutll        !< array of reflected + emitted lw radiation for local surface in i-th reflection
1152    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfouts         !< array of reflected sw radiation for all surfaces in i-th reflection
1153    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutl         !< array of reflected + emitted lw radiation for all surfaces in i-th reflection
1154    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlg         !< global array of incoming lw radiation from plant canopy
1155    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsw        !< array of total sw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1156    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutlw        !< array of total lw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1157    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfemitlwl      !< array of emitted lw radiation for local surface used to calculate effective surface temperature for radiation model
1158
1159!-- block variables needed for calculation of the plant canopy model inside the urban surface model
1160    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  csfsurf          !< csfsurf[:,icsf] = index of target surface and csf grid index for csf[icsf]
1161    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  csf              !< array of plant canopy sink fators + direct irradiation factors (transparency)
1162    REAL(wp), DIMENSION(:,:,:), POINTER            ::  sub_lad          !< subset of lad_s within urban surface, transformed to plain Z coordinate
1163    REAL(wp), DIMENSION(:), POINTER                ::  sub_lad_g        !< sub_lad globalized (used to avoid MPI RMA calls in raytracing)
1164    REAL(wp)                                       ::  prototype_lad    !< prototype leaf area density for computing effective optical depth
1165    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  nzterr, plantt   !< temporary global arrays for raytracing
1166    INTEGER(iwp)                                   ::  plantt_max
1167
1168!-- arrays and variables for calculation of svf and csf
1169    TYPE(t_svf), DIMENSION(:), POINTER             ::  asvf             !< pointer to growing svc array
1170    TYPE(t_csf), DIMENSION(:), POINTER             ::  acsf             !< pointer to growing csf array
1171    TYPE(t_svf), DIMENSION(:), POINTER             ::  amrtf            !< pointer to growing mrtf array
1172    TYPE(t_svf), DIMENSION(:), ALLOCATABLE, TARGET ::  asvf1, asvf2     !< realizations of svf array
1173    TYPE(t_csf), DIMENSION(:), ALLOCATABLE, TARGET ::  acsf1, acsf2     !< realizations of csf array
1174    TYPE(t_svf), DIMENSION(:), ALLOCATABLE, TARGET ::  amrtf1, amrtf2   !< realizations of mftf array
1175    INTEGER(iwp)                                   ::  nsvfla           !< dimmension of array allocated for storage of svf in local processor
1176    INTEGER(iwp)                                   ::  ncsfla           !< dimmension of array allocated for storage of csf in local processor
1177    INTEGER(iwp)                                   ::  nmrtfa           !< dimmension of array allocated for storage of mrt
1178    INTEGER(iwp)                                   ::  msvf, mcsf, mmrtf!< mod for swapping the growing array
1179    INTEGER(iwp), PARAMETER                        ::  gasize = 100000_iwp  !< initial size of growing arrays
1180    REAL(wp), PARAMETER                            ::  grow_factor = 1.4_wp !< growth factor of growing arrays
1181    INTEGER(iwp)                                   ::  nsvfl            !< number of svf for local processor
1182    INTEGER(iwp)                                   ::  ncsfl            !< no. of csf in local processor
1183                                                                        !< needed only during calc_svf but must be here because it is
1184                                                                        !< shared between subroutines calc_svf and raytrace
1185    INTEGER(iwp), DIMENSION(:,:,:,:), POINTER      ::  gridsurf         !< reverse index of local surfl[d,k,j,i] (for case rad_angular_discretization)
1186    INTEGER(iwp), DIMENSION(:,:,:), ALLOCATABLE    ::  gridpcbl         !< reverse index of local pcbl[k,j,i]
1187    INTEGER(iwp), PARAMETER                        ::  nsurf_type_u = 6 !< number of urban surf types (used in gridsurf)
1188
1189!-- temporary arrays for calculation of csf in raytracing
1190    INTEGER(iwp)                                   ::  maxboxesg        !< max number of boxes ray can cross in the domain
1191    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  boxes            !< coordinates of gridboxes being crossed by ray
1192    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  crlens           !< array of crossing lengths of ray for particular grid boxes
1193    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  lad_ip           !< array of numbers of process where lad is stored
1194#if defined( __parallel )
1195    INTEGER(kind=MPI_ADDRESS_KIND), &
1196                  DIMENSION(:), ALLOCATABLE        ::  lad_disp         !< array of displaycements of lad in local array of proc lad_ip
1197    INTEGER(iwp)                                   ::  win_lad          !< MPI RMA window for leaf area density
1198    INTEGER(iwp)                                   ::  win_gridsurf     !< MPI RMA window for reverse grid surface index
1199#endif
1200    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  lad_s_ray        !< array of received lad_s for appropriate gridboxes crossed by ray
1201    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  target_surfl
1202    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  rt2_track
1203    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rt2_track_lad
1204    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  rt2_track_dist
1205    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  rt2_dist
1206
1207!-- arrays for time averages
1208    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfradnet_av    !< average of net radiation to local surface including radiation from reflections
1209    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinsw_av      !< average of sw radiation falling to local surface including radiation from reflections
1210    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlw_av      !< average of lw radiation falling to local surface including radiation from reflections
1211    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdir_av   !< average of direct sw radiation falling to local surface
1212    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdif_av   !< average of diffuse sw radiation from sky and model boundary falling to local surface
1213    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwdif_av   !< average of diffuse lw radiation from sky and model boundary falling to local surface
1214    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswref_av   !< average of sw radiation falling to surface from reflections
1215    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwref_av   !< average of lw radiation falling to surface from reflections
1216    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsw_av     !< average of total sw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1217    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutlw_av     !< average of total lw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1218    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfins_av       !< average of array of residua of sw radiation absorbed in surface after last reflection
1219    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinl_av       !< average of array of residua of lw radiation absorbed in surface after last reflection
1220    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinlw_av       !< Average of pcbinlw
1221    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinsw_av       !< Average of pcbinsw
1222    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdir_av    !< Average of pcbinswdir
1223    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdif_av    !< Average of pcbinswdif
1224    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswref_av    !< Average of pcbinswref
1225
1226
1227!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1228!-- Energy balance variables
1229!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1230!-- parameters of the land, roof and wall surfaces
1231    REAL(wp), DIMENSION(:), ALLOCATABLE            :: albedo_surf        !< albedo of the surface
1232    REAL(wp), DIMENSION(:), ALLOCATABLE            :: emiss_surf         !< emissivity of the wall surface
1233
1234
1235    INTERFACE radiation_check_data_output
1236       MODULE PROCEDURE radiation_check_data_output
1237    END INTERFACE radiation_check_data_output
1238
1239    INTERFACE radiation_check_data_output_ts
1240       MODULE PROCEDURE radiation_check_data_output_ts
1241    END INTERFACE radiation_check_data_output_ts
1242
1243    INTERFACE radiation_check_data_output_pr
1244       MODULE PROCEDURE radiation_check_data_output_pr
1245    END INTERFACE radiation_check_data_output_pr
1246 
1247    INTERFACE radiation_check_parameters
1248       MODULE PROCEDURE radiation_check_parameters
1249    END INTERFACE radiation_check_parameters
1250 
1251    INTERFACE radiation_clearsky
1252       MODULE PROCEDURE radiation_clearsky
1253    END INTERFACE radiation_clearsky
1254 
1255    INTERFACE radiation_constant
1256       MODULE PROCEDURE radiation_constant
1257    END INTERFACE radiation_constant
1258 
1259    INTERFACE radiation_control
1260       MODULE PROCEDURE radiation_control
1261    END INTERFACE radiation_control
1262
1263    INTERFACE radiation_3d_data_averaging
1264       MODULE PROCEDURE radiation_3d_data_averaging
1265    END INTERFACE radiation_3d_data_averaging
1266
1267    INTERFACE radiation_data_output_2d
1268       MODULE PROCEDURE radiation_data_output_2d
1269    END INTERFACE radiation_data_output_2d
1270
1271    INTERFACE radiation_data_output_3d
1272       MODULE PROCEDURE radiation_data_output_3d
1273    END INTERFACE radiation_data_output_3d
1274
1275    INTERFACE radiation_data_output_mask
1276       MODULE PROCEDURE radiation_data_output_mask
1277    END INTERFACE radiation_data_output_mask
1278
1279    INTERFACE radiation_define_netcdf_grid
1280       MODULE PROCEDURE radiation_define_netcdf_grid
1281    END INTERFACE radiation_define_netcdf_grid
1282
1283    INTERFACE radiation_header
1284       MODULE PROCEDURE radiation_header
1285    END INTERFACE radiation_header 
1286 
1287    INTERFACE radiation_init
1288       MODULE PROCEDURE radiation_init
1289    END INTERFACE radiation_init
1290
1291    INTERFACE radiation_parin
1292       MODULE PROCEDURE radiation_parin
1293    END INTERFACE radiation_parin
1294   
1295    INTERFACE radiation_rrtmg
1296       MODULE PROCEDURE radiation_rrtmg
1297    END INTERFACE radiation_rrtmg
1298
1299#if defined( __rrtmg )
1300    INTERFACE radiation_tendency
1301       MODULE PROCEDURE radiation_tendency
1302       MODULE PROCEDURE radiation_tendency_ij
1303    END INTERFACE radiation_tendency
1304#endif
1305
1306    INTERFACE radiation_rrd_local
1307       MODULE PROCEDURE radiation_rrd_local
1308    END INTERFACE radiation_rrd_local
1309
1310    INTERFACE radiation_wrd_local
1311       MODULE PROCEDURE radiation_wrd_local
1312    END INTERFACE radiation_wrd_local
1313
1314    INTERFACE radiation_interaction
1315       MODULE PROCEDURE radiation_interaction
1316    END INTERFACE radiation_interaction
1317
1318    INTERFACE radiation_interaction_init
1319       MODULE PROCEDURE radiation_interaction_init
1320    END INTERFACE radiation_interaction_init
1321 
1322    INTERFACE radiation_presimulate_solar_pos
1323       MODULE PROCEDURE radiation_presimulate_solar_pos
1324    END INTERFACE radiation_presimulate_solar_pos
1325
1326    INTERFACE radiation_calc_svf
1327       MODULE PROCEDURE radiation_calc_svf
1328    END INTERFACE radiation_calc_svf
1329
1330    INTERFACE radiation_write_svf
1331       MODULE PROCEDURE radiation_write_svf
1332    END INTERFACE radiation_write_svf
1333
1334    INTERFACE radiation_read_svf
1335       MODULE PROCEDURE radiation_read_svf
1336    END INTERFACE radiation_read_svf
1337
1338
1339    SAVE
1340
1341    PRIVATE
1342
1343!
1344!-- Public functions / NEEDS SORTING
1345    PUBLIC radiation_check_data_output, radiation_check_data_output_pr,        &
1346           radiation_check_data_output_ts,                                     &
1347           radiation_check_parameters, radiation_control,                      &
1348           radiation_header, radiation_init, radiation_parin,                  &
1349           radiation_3d_data_averaging,                                        &
1350           radiation_data_output_2d, radiation_data_output_3d,                 &
1351           radiation_define_netcdf_grid, radiation_wrd_local,                  &
1352           radiation_rrd_local, radiation_data_output_mask,                    &
1353           radiation_calc_svf, radiation_write_svf,                            &
1354           radiation_interaction, radiation_interaction_init,                  &
1355           radiation_read_svf, radiation_presimulate_solar_pos
1356
1357   
1358!
1359!-- Public variables and constants / NEEDS SORTING
1360    PUBLIC albedo, albedo_type, decl_1, decl_2, decl_3, dots_rad, dt_radiation,&
1361           emissivity, force_radiation_call, lat, lon, mrt_geom_human,         &
1362           mrt_include_sw, mrt_nlevels, mrtbl, mrtinsw, mrtinlw, nmrtbl,       &
1363           rad_net_av, radiation, radiation_scheme, rad_lw_in,                 &
1364           rad_lw_in_av, rad_lw_out, rad_lw_out_av,                            &
1365           rad_lw_cs_hr, rad_lw_cs_hr_av, rad_lw_hr, rad_lw_hr_av, rad_sw_in,  &
1366           rad_sw_in_av, rad_sw_out, rad_sw_out_av, rad_sw_cs_hr,              &
1367           rad_sw_cs_hr_av, rad_sw_hr, rad_sw_hr_av, solar_constant,           &
1368           skip_time_do_radiation, time_radiation, unscheduled_radiation_calls,&
1369           cos_zenith, calc_zenith, sun_direction, sun_dir_lat, sun_dir_lon,   &
1370           idir, jdir, kdir, id, iz, iy, ix,                                   &
1371           iup_u, inorth_u, isouth_u, ieast_u, iwest_u,                        &
1372           iup_l, inorth_l, isouth_l, ieast_l, iwest_l,                        &
1373           nsurf_type, nz_urban_b, nz_urban_t, nz_urban, pch, nsurf,                 &
1374           idsvf, ndsvf, idcsf, ndcsf, kdcsf, pct,                             &
1375           radiation_interactions, startwall, startland, endland, endwall,     &
1376           skyvf, skyvft, radiation_interactions_on, average_radiation,        &
1377           rad_sw_in_diff, rad_sw_in_dir
1378
1379
1380#if defined ( __rrtmg )
1381    PUBLIC radiation_tendency, rrtm_aldif, rrtm_aldir, rrtm_asdif, rrtm_asdir
1382#endif
1383
1384 CONTAINS
1385
1386
1387!------------------------------------------------------------------------------!
1388! Description:
1389! ------------
1390!> This subroutine controls the calls of the radiation schemes
1391!------------------------------------------------------------------------------!
1392    SUBROUTINE radiation_control
1393 
1394 
1395       IMPLICIT NONE
1396
1397
1398       IF ( debug_output_timestep )  CALL debug_message( 'radiation_control', 'start' )
1399
1400
1401       SELECT CASE ( TRIM( radiation_scheme ) )
1402
1403          CASE ( 'constant' )
1404             CALL radiation_constant
1405         
1406          CASE ( 'clear-sky' ) 
1407             CALL radiation_clearsky
1408       
1409          CASE ( 'rrtmg' )
1410             CALL radiation_rrtmg
1411
1412          CASE DEFAULT
1413
1414       END SELECT
1415
1416       IF ( debug_output_timestep )  CALL debug_message( 'radiation_control', 'end' )
1417
1418    END SUBROUTINE radiation_control
1419
1420!------------------------------------------------------------------------------!
1421! Description:
1422! ------------
1423!> Check data output for radiation model
1424!------------------------------------------------------------------------------!
1425    SUBROUTINE radiation_check_data_output( variable, unit, i, ilen, k )
1426 
1427 
1428       USE control_parameters,                                                 &
1429           ONLY: data_output, message_string
1430
1431       IMPLICIT NONE
1432
1433       CHARACTER (LEN=*) ::  unit          !<
1434       CHARACTER (LEN=*) ::  variable      !<
1435
1436       INTEGER(iwp) :: i, k
1437       INTEGER(iwp) :: ilen
1438       CHARACTER(LEN=varnamelength) :: var  !< TRIM(variable)
1439
1440       var = TRIM(variable)
1441
1442       IF ( len(var) < 3_iwp  )  THEN
1443          unit = 'illegal'
1444          RETURN
1445       ENDIF
1446
1447       IF ( var(1:3) /= 'rad'  .AND.  var(1:3) /= 'rtm' )  THEN
1448          unit = 'illegal'
1449          RETURN
1450       ENDIF
1451
1452!--    first process diractional variables
1453       IF ( var(1:12) == 'rtm_rad_net_'  .OR.  var(1:13) == 'rtm_rad_insw_'  .OR.        &
1454            var(1:13) == 'rtm_rad_inlw_'  .OR.  var(1:16) == 'rtm_rad_inswdir_'  .OR.    &
1455            var(1:16) == 'rtm_rad_inswdif_'  .OR.  var(1:16) == 'rtm_rad_inswref_'  .OR. &
1456            var(1:16) == 'rtm_rad_inlwdif_'  .OR.  var(1:16) == 'rtm_rad_inlwref_'  .OR. &
1457            var(1:14) == 'rtm_rad_outsw_'  .OR.  var(1:14) == 'rtm_rad_outlw_'  .OR.     &
1458            var(1:14) == 'rtm_rad_ressw_'  .OR.  var(1:14) == 'rtm_rad_reslw_'  ) THEN
1459          IF ( .NOT.  radiation ) THEN
1460                message_string = 'output of "' // TRIM( var ) // '" require'&
1461                                 // 's radiation = .TRUE.'
1462                CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1463          ENDIF
1464          unit = 'W/m2'
1465       ELSE IF ( var(1:7) == 'rtm_svf'  .OR.  var(1:7) == 'rtm_dif'  .OR.                &
1466                 var(1:9) == 'rtm_skyvf' .OR. var(1:9) == 'rtm_skyvft'  .OR.             &
1467                 var(1:12) == 'rtm_surfalb_'  .OR.  var(1:13) == 'rtm_surfemis_'  ) THEN
1468          IF ( .NOT.  radiation ) THEN
1469                message_string = 'output of "' // TRIM( var ) // '" require'&
1470                                 // 's radiation = .TRUE.'
1471                CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1472          ENDIF
1473          unit = '1'
1474       ELSE
1475!--       non-directional variables
1476          SELECT CASE ( TRIM( var ) )
1477             CASE ( 'rad_lw_cs_hr', 'rad_lw_hr', 'rad_lw_in', 'rad_lw_out', &
1478                    'rad_sw_cs_hr', 'rad_sw_hr', 'rad_sw_in', 'rad_sw_out'  )
1479                IF (  .NOT.  radiation  .OR.  radiation_scheme /= 'rrtmg' )  THEN
1480                   message_string = '"output of "' // TRIM( var ) // '" requi' // &
1481                                    'res radiation = .TRUE. and ' //              &
1482                                    'radiation_scheme = "rrtmg"'
1483                   CALL message( 'check_parameters', 'PA0406', 1, 2, 0, 6, 0 )
1484                ENDIF
1485                unit = 'K/h'
1486
1487             CASE ( 'rad_net*', 'rrtm_aldif*', 'rrtm_aldir*', 'rrtm_asdif*',      &
1488                    'rrtm_asdir*', 'rad_lw_in*', 'rad_lw_out*', 'rad_sw_in*',     &
1489                    'rad_sw_out*')
1490                IF ( i == 0 .AND. ilen == 0 .AND. k == 0)  THEN
1491                   ! Workaround for masked output (calls with i=ilen=k=0)
1492                   unit = 'illegal'
1493                   RETURN
1494                ENDIF
1495                IF ( k == 0  .OR.  data_output(i)(ilen-2:ilen) /= '_xy' )  THEN
1496                   message_string = 'illegal value for data_output: "' //         &
1497                                    TRIM( var ) // '" & only 2d-horizontal ' //   &
1498                                    'cross sections are allowed for this value'
1499                   CALL message( 'check_parameters', 'PA0111', 1, 2, 0, 6, 0 )
1500                ENDIF
1501                IF (  .NOT.  radiation  .OR.  radiation_scheme /= "rrtmg" )  THEN
1502                   IF ( TRIM( var ) == 'rrtm_aldif*'  .OR.                        &
1503                        TRIM( var ) == 'rrtm_aldir*'  .OR.                        &
1504                        TRIM( var ) == 'rrtm_asdif*'  .OR.                        &
1505                        TRIM( var ) == 'rrtm_asdir*'      )                       &
1506                   THEN
1507                      message_string = 'output of "' // TRIM( var ) // '" require'&
1508                                       // 's radiation = .TRUE. and radiation_sch'&
1509                                       // 'eme = "rrtmg"'
1510                      CALL message( 'check_parameters', 'PA0409', 1, 2, 0, 6, 0 )
1511                   ENDIF
1512                ENDIF
1513
1514                IF ( TRIM( var ) == 'rad_net*'      ) unit = 'W/m2'
1515                IF ( TRIM( var ) == 'rad_lw_in*'    ) unit = 'W/m2'
1516                IF ( TRIM( var ) == 'rad_lw_out*'   ) unit = 'W/m2'
1517                IF ( TRIM( var ) == 'rad_sw_in*'    ) unit = 'W/m2'
1518                IF ( TRIM( var ) == 'rad_sw_out*'   ) unit = 'W/m2'
1519                IF ( TRIM( var ) == 'rad_sw_in'     ) unit = 'W/m2'
1520                IF ( TRIM( var ) == 'rrtm_aldif*'   ) unit = ''
1521                IF ( TRIM( var ) == 'rrtm_aldir*'   ) unit = ''
1522                IF ( TRIM( var ) == 'rrtm_asdif*'   ) unit = ''
1523                IF ( TRIM( var ) == 'rrtm_asdir*'   ) unit = ''
1524
1525             CASE ( 'rtm_rad_pc_inlw', 'rtm_rad_pc_insw', 'rtm_rad_pc_inswdir', &
1526                    'rtm_rad_pc_inswdif', 'rtm_rad_pc_inswref')
1527                IF ( .NOT.  radiation ) THEN
1528                   message_string = 'output of "' // TRIM( var ) // '" require'&
1529                                    // 's radiation = .TRUE.'
1530                   CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1531                ENDIF
1532                unit = 'W'
1533
1534             CASE ( 'rtm_mrt', 'rtm_mrt_sw', 'rtm_mrt_lw'  )
1535                IF ( i == 0 .AND. ilen == 0 .AND. k == 0)  THEN
1536                   ! Workaround for masked output (calls with i=ilen=k=0)
1537                   unit = 'illegal'
1538                   RETURN
1539                ENDIF
1540
1541                IF ( .NOT.  radiation ) THEN
1542                   message_string = 'output of "' // TRIM( var ) // '" require'&
1543                                    // 's radiation = .TRUE.'
1544                   CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1545                ENDIF
1546                IF ( mrt_nlevels == 0 ) THEN
1547                   message_string = 'output of "' // TRIM( var ) // '" require'&
1548                                    // 's mrt_nlevels > 0'
1549                   CALL message( 'check_parameters', 'PA0510', 1, 2, 0, 6, 0 )
1550                ENDIF
1551                IF ( TRIM( var ) == 'rtm_mrt_sw'  .AND.  .NOT. mrt_include_sw ) THEN
1552                   message_string = 'output of "' // TRIM( var ) // '" require'&
1553                                    // 's rtm_mrt_sw = .TRUE.'
1554                   CALL message( 'check_parameters', 'PA0511', 1, 2, 0, 6, 0 )
1555                ENDIF
1556                IF ( TRIM( var ) == 'rtm_mrt' ) THEN
1557                   unit = 'K'
1558                ELSE
1559                   unit = 'W m-2'
1560                ENDIF
1561
1562             CASE DEFAULT
1563                unit = 'illegal'
1564
1565          END SELECT
1566       ENDIF
1567
1568    END SUBROUTINE radiation_check_data_output
1569
1570
1571!------------------------------------------------------------------------------!
1572! Description:
1573! ------------
1574!> Set module-specific timeseries units and labels
1575!------------------------------------------------------------------------------!
1576 SUBROUTINE radiation_check_data_output_ts( dots_max, dots_num )
1577
1578
1579    INTEGER(iwp),      INTENT(IN)     ::  dots_max
1580    INTEGER(iwp),      INTENT(INOUT)  ::  dots_num
1581
1582!
1583!-- Next line is just to avoid compiler warning about unused variable.
1584    IF ( dots_max == 0 )  CONTINUE
1585
1586!
1587!-- Temporary solution to add LSM and radiation time series to the default
1588!-- output
1589    IF ( land_surface  .OR.  radiation )  THEN
1590       IF ( TRIM( radiation_scheme ) == 'rrtmg' )  THEN
1591          dots_num = dots_num + 15
1592       ELSE
1593          dots_num = dots_num + 11
1594       ENDIF
1595    ENDIF
1596
1597
1598 END SUBROUTINE radiation_check_data_output_ts
1599
1600!------------------------------------------------------------------------------!
1601! Description:
1602! ------------
1603!> Check data output of profiles for radiation model
1604!------------------------------------------------------------------------------! 
1605    SUBROUTINE radiation_check_data_output_pr( variable, var_count, unit,      &
1606               dopr_unit )
1607 
1608       USE arrays_3d,                                                          &
1609           ONLY: zu
1610
1611       USE control_parameters,                                                 &
1612           ONLY: data_output_pr, message_string
1613
1614       USE indices
1615
1616       USE profil_parameter
1617
1618       USE statistics
1619
1620       IMPLICIT NONE
1621   
1622       CHARACTER (LEN=*) ::  unit      !<
1623       CHARACTER (LEN=*) ::  variable  !<
1624       CHARACTER (LEN=*) ::  dopr_unit !< local value of dopr_unit
1625 
1626       INTEGER(iwp) ::  var_count     !<
1627
1628       SELECT CASE ( TRIM( variable ) )
1629       
1630         CASE ( 'rad_net' )
1631             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme == 'constant' )&
1632             THEN
1633                message_string = 'data_output_pr = ' //                        &
1634                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1635                                 'not available for radiation = .FALSE. or ' //&
1636                                 'radiation_scheme = "constant"'
1637                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1638             ELSE
1639                dopr_index(var_count) = 99
1640                dopr_unit  = 'W/m2'
1641                hom(:,2,99,:)  = SPREAD( zw, 2, statistic_regions+1 )
1642                unit = dopr_unit
1643             ENDIF
1644
1645          CASE ( 'rad_lw_in' )
1646             IF ( (  .NOT.  radiation)  .OR.  radiation_scheme == 'constant' ) &
1647             THEN
1648                message_string = 'data_output_pr = ' //                        &
1649                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1650                                 'not available for radiation = .FALSE. or ' //&
1651                                 'radiation_scheme = "constant"'
1652                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1653             ELSE
1654                dopr_index(var_count) = 100
1655                dopr_unit  = 'W/m2'
1656                hom(:,2,100,:)  = SPREAD( zw, 2, statistic_regions+1 )
1657                unit = dopr_unit 
1658             ENDIF
1659
1660          CASE ( 'rad_lw_out' )
1661             IF ( (  .NOT. radiation )  .OR.  radiation_scheme == 'constant' ) &
1662             THEN
1663                message_string = 'data_output_pr = ' //                        &
1664                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1665                                 'not available for radiation = .FALSE. or ' //&
1666                                 'radiation_scheme = "constant"'
1667                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1668             ELSE
1669                dopr_index(var_count) = 101
1670                dopr_unit  = 'W/m2'
1671                hom(:,2,101,:)  = SPREAD( zw, 2, statistic_regions+1 )
1672                unit = dopr_unit   
1673             ENDIF
1674
1675          CASE ( 'rad_sw_in' )
1676             IF ( (  .NOT. radiation )  .OR.  radiation_scheme == 'constant' ) &
1677             THEN
1678                message_string = 'data_output_pr = ' //                        &
1679                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1680                                 'not available for radiation = .FALSE. or ' //&
1681                                 'radiation_scheme = "constant"'
1682                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1683             ELSE
1684                dopr_index(var_count) = 102
1685                dopr_unit  = 'W/m2'
1686                hom(:,2,102,:)  = SPREAD( zw, 2, statistic_regions+1 )
1687                unit = dopr_unit
1688             ENDIF
1689
1690          CASE ( 'rad_sw_out')
1691             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme == 'constant' )&
1692             THEN
1693                message_string = 'data_output_pr = ' //                        &
1694                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1695                                 'not available for radiation = .FALSE. or ' //&
1696                                 'radiation_scheme = "constant"'
1697                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1698             ELSE
1699                dopr_index(var_count) = 103
1700                dopr_unit  = 'W/m2'
1701                hom(:,2,103,:)  = SPREAD( zw, 2, statistic_regions+1 )
1702                unit = dopr_unit
1703             ENDIF
1704
1705          CASE ( 'rad_lw_cs_hr' )
1706             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1707             THEN
1708                message_string = 'data_output_pr = ' //                        &
1709                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1710                                 'not available for radiation = .FALSE. or ' //&
1711                                 'radiation_scheme /= "rrtmg"'
1712                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1713             ELSE
1714                dopr_index(var_count) = 104
1715                dopr_unit  = 'K/h'
1716                hom(:,2,104,:)  = SPREAD( zu, 2, statistic_regions+1 )
1717                unit = dopr_unit
1718             ENDIF
1719
1720          CASE ( 'rad_lw_hr' )
1721             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1722             THEN
1723                message_string = 'data_output_pr = ' //                        &
1724                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1725                                 'not available for radiation = .FALSE. or ' //&
1726                                 'radiation_scheme /= "rrtmg"'
1727                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1728             ELSE
1729                dopr_index(var_count) = 105
1730                dopr_unit  = 'K/h'
1731                hom(:,2,105,:)  = SPREAD( zu, 2, statistic_regions+1 )
1732                unit = dopr_unit
1733             ENDIF
1734
1735          CASE ( 'rad_sw_cs_hr' )
1736             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1737             THEN
1738                message_string = 'data_output_pr = ' //                        &
1739                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1740                                 'not available for radiation = .FALSE. or ' //&
1741                                 'radiation_scheme /= "rrtmg"'
1742                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1743             ELSE
1744                dopr_index(var_count) = 106
1745                dopr_unit  = 'K/h'
1746                hom(:,2,106,:)  = SPREAD( zu, 2, statistic_regions+1 )
1747                unit = dopr_unit
1748             ENDIF
1749
1750          CASE ( 'rad_sw_hr' )
1751             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1752             THEN
1753                message_string = 'data_output_pr = ' //                        &
1754                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1755                                 'not available for radiation = .FALSE. or ' //&
1756                                 'radiation_scheme /= "rrtmg"'
1757                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1758             ELSE
1759                dopr_index(var_count) = 107
1760                dopr_unit  = 'K/h'
1761                hom(:,2,107,:)  = SPREAD( zu, 2, statistic_regions+1 )
1762                unit = dopr_unit
1763             ENDIF
1764
1765
1766          CASE DEFAULT
1767             unit = 'illegal'
1768
1769       END SELECT
1770
1771
1772    END SUBROUTINE radiation_check_data_output_pr
1773 
1774 
1775!------------------------------------------------------------------------------!
1776! Description:
1777! ------------
1778!> Check parameters routine for radiation model
1779!------------------------------------------------------------------------------!
1780    SUBROUTINE radiation_check_parameters
1781
1782       USE control_parameters,                                                 &
1783           ONLY: land_surface, message_string, urban_surface
1784
1785       USE netcdf_data_input_mod,                                              &
1786           ONLY:  input_pids_static                 
1787   
1788       IMPLICIT NONE
1789       
1790!
1791!--    In case no urban-surface or land-surface model is applied, usage of
1792!--    a radiation model make no sense.         
1793       IF ( .NOT. land_surface  .AND.  .NOT. urban_surface )  THEN
1794          message_string = 'Usage of radiation module is only allowed if ' //  &
1795                           'land-surface and/or urban-surface model is applied.'
1796          CALL message( 'check_parameters', 'PA0486', 1, 2, 0, 6, 0 )
1797       ENDIF
1798
1799       IF ( radiation_scheme /= 'constant'   .AND.                             &
1800            radiation_scheme /= 'clear-sky'  .AND.                             &
1801            radiation_scheme /= 'rrtmg' )  THEN
1802          message_string = 'unknown radiation_scheme = '//                     &
1803                           TRIM( radiation_scheme )
1804          CALL message( 'check_parameters', 'PA0405', 1, 2, 0, 6, 0 )
1805       ELSEIF ( radiation_scheme == 'rrtmg' )  THEN
1806#if ! defined ( __rrtmg )
1807          message_string = 'radiation_scheme = "rrtmg" requires ' //           & 
1808                           'compilation of PALM with pre-processor ' //        &
1809                           'directive -D__rrtmg'
1810          CALL message( 'check_parameters', 'PA0407', 1, 2, 0, 6, 0 )
1811#endif
1812#if defined ( __rrtmg ) && ! defined( __netcdf )
1813          message_string = 'radiation_scheme = "rrtmg" requires ' //           & 
1814                           'the use of NetCDF (preprocessor directive ' //     &
1815                           '-D__netcdf'
1816          CALL message( 'check_parameters', 'PA0412', 1, 2, 0, 6, 0 )
1817#endif
1818
1819       ENDIF
1820!
1821!--    Checks performed only if data is given via namelist only.
1822       IF ( .NOT. input_pids_static )  THEN
1823          IF ( albedo_type == 0  .AND.  albedo == 9999999.9_wp  .AND.          &
1824               radiation_scheme == 'clear-sky')  THEN
1825             message_string = 'radiation_scheme = "clear-sky" in combination'//& 
1826                              'with albedo_type = 0 requires setting of'//     &
1827                              'albedo /= 9999999.9'
1828             CALL message( 'check_parameters', 'PA0410', 1, 2, 0, 6, 0 )
1829          ENDIF
1830
1831          IF ( albedo_type == 0  .AND.  radiation_scheme == 'rrtmg'  .AND.     &
1832             ( albedo_lw_dif == 9999999.9_wp .OR. albedo_lw_dir == 9999999.9_wp&
1833          .OR. albedo_sw_dif == 9999999.9_wp .OR. albedo_sw_dir == 9999999.9_wp& 
1834             ) ) THEN
1835             message_string = 'radiation_scheme = "rrtmg" in combination' //   & 
1836                              'with albedo_type = 0 requires setting of ' //   &
1837                              'albedo_lw_dif /= 9999999.9' //                  &
1838                              'albedo_lw_dir /= 9999999.9' //                  &
1839                              'albedo_sw_dif /= 9999999.9 and' //              &
1840                              'albedo_sw_dir /= 9999999.9'
1841             CALL message( 'check_parameters', 'PA0411', 1, 2, 0, 6, 0 )
1842          ENDIF
1843       ENDIF
1844!
1845!--    Parallel rad_angular_discretization without raytrace_mpi_rma is not implemented
1846#if defined( __parallel )     
1847       IF ( rad_angular_discretization  .AND.  .NOT. raytrace_mpi_rma )  THEN
1848          message_string = 'rad_angular_discretization can only be used ' //  &
1849                           'together with raytrace_mpi_rma or when ' //  &
1850                           'no parallelization is applied.'
1851          CALL message( 'check_parameters', 'PA0486', 1, 2, 0, 6, 0 )
1852       ENDIF
1853#endif
1854
1855       IF ( cloud_droplets  .AND.   radiation_scheme == 'rrtmg'  .AND.         &
1856            average_radiation ) THEN
1857          message_string = 'average_radiation = .T. with radiation_scheme'//   & 
1858                           '= "rrtmg" in combination cloud_droplets = .T.'//   &
1859                           'is not implementd'
1860          CALL message( 'check_parameters', 'PA0560', 1, 2, 0, 6, 0 )
1861       ENDIF
1862
1863!
1864!--    Incialize svf normalization reporting histogram
1865       svfnorm_report_num = 1
1866       DO WHILE ( svfnorm_report_thresh(svfnorm_report_num) < 1e20_wp          &
1867                   .AND. svfnorm_report_num <= 30 )
1868          svfnorm_report_num = svfnorm_report_num + 1
1869       ENDDO
1870       svfnorm_report_num = svfnorm_report_num - 1
1871!
1872!--    Check for dt_radiation
1873       IF ( dt_radiation <= 0.0 )  THEN
1874          message_string = 'dt_radiation must be > 0.0' 
1875          CALL message( 'check_parameters', 'PA0591', 1, 2, 0, 6, 0 ) 
1876       ENDIF
1877 
1878    END SUBROUTINE radiation_check_parameters 
1879 
1880 
1881!------------------------------------------------------------------------------!
1882! Description:
1883! ------------
1884!> Initialization of the radiation model
1885!------------------------------------------------------------------------------!
1886    SUBROUTINE radiation_init
1887   
1888       IMPLICIT NONE
1889
1890       INTEGER(iwp) ::  i         !< running index x-direction
1891       INTEGER(iwp) ::  ioff      !< offset in x between surface element reference grid point in atmosphere and actual surface
1892       INTEGER(iwp) ::  j         !< running index y-direction
1893       INTEGER(iwp) ::  joff      !< offset in y between surface element reference grid point in atmosphere and actual surface
1894       INTEGER(iwp) ::  l         !< running index for orientation of vertical surfaces
1895       INTEGER(iwp) ::  m         !< running index for surface elements
1896#if defined( __rrtmg )
1897       INTEGER(iwp) ::  ind_type  !< running index for subgrid-surface tiles
1898#endif
1899
1900
1901       IF ( debug_output )  CALL debug_message( 'radiation_init', 'start' )
1902!
1903!--    Activate radiation_interactions according to the existence of vertical surfaces and/or trees.
1904!--    The namelist parameter radiation_interactions_on can override this behavior.
1905!--    (This check cannot be performed in check_parameters, because vertical_surfaces_exist is first set in
1906!--    init_surface_arrays.)
1907       IF ( radiation_interactions_on )  THEN
1908          IF ( vertical_surfaces_exist  .OR.  plant_canopy )  THEN
1909             radiation_interactions    = .TRUE.
1910             average_radiation         = .TRUE.
1911          ELSE
1912             radiation_interactions_on = .FALSE.   !< reset namelist parameter: no interactions
1913                                                   !< calculations necessary in case of flat surface
1914          ENDIF
1915       ELSEIF ( vertical_surfaces_exist  .OR.  plant_canopy )  THEN
1916          message_string = 'radiation_interactions_on is set to .FALSE. although '     // &
1917                           'vertical surfaces and/or trees exist. The model will run ' // &
1918                           'without RTM (no shadows, no radiation reflections)'
1919          CALL message( 'init_3d_model', 'PA0348', 0, 1, 0, 6, 0 )
1920       ENDIF
1921!
1922!--    If required, initialize radiation interactions between surfaces
1923!--    via sky-view factors. This must be done before radiation is initialized.
1924       IF ( radiation_interactions )  CALL radiation_interaction_init
1925!
1926!--    Allocate array for storing the surface net radiation
1927       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_net )  .AND.                      &
1928                  surf_lsm_h%ns > 0  )   THEN
1929          ALLOCATE( surf_lsm_h%rad_net(1:surf_lsm_h%ns) )
1930          surf_lsm_h%rad_net = 0.0_wp 
1931       ENDIF
1932       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_net )  .AND.                      &
1933                  surf_usm_h%ns > 0  )  THEN
1934          ALLOCATE( surf_usm_h%rad_net(1:surf_usm_h%ns) )
1935          surf_usm_h%rad_net = 0.0_wp 
1936       ENDIF
1937       DO  l = 0, 3
1938          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_net )  .AND.                &
1939                     surf_lsm_v(l)%ns > 0  )  THEN
1940             ALLOCATE( surf_lsm_v(l)%rad_net(1:surf_lsm_v(l)%ns) )
1941             surf_lsm_v(l)%rad_net = 0.0_wp 
1942          ENDIF
1943          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_net )  .AND.                &
1944                     surf_usm_v(l)%ns > 0  )  THEN
1945             ALLOCATE( surf_usm_v(l)%rad_net(1:surf_usm_v(l)%ns) )
1946             surf_usm_v(l)%rad_net = 0.0_wp 
1947          ENDIF
1948       ENDDO
1949
1950
1951!
1952!--    Allocate array for storing the surface longwave (out) radiation change
1953       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_lw_out_change_0 )  .AND.          &
1954                  surf_lsm_h%ns > 0  )   THEN
1955          ALLOCATE( surf_lsm_h%rad_lw_out_change_0(1:surf_lsm_h%ns) )
1956          surf_lsm_h%rad_lw_out_change_0 = 0.0_wp 
1957       ENDIF
1958       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_lw_out_change_0 )  .AND.          &
1959                  surf_usm_h%ns > 0  )  THEN
1960          ALLOCATE( surf_usm_h%rad_lw_out_change_0(1:surf_usm_h%ns) )
1961          surf_usm_h%rad_lw_out_change_0 = 0.0_wp 
1962       ENDIF
1963       DO  l = 0, 3
1964          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_lw_out_change_0 )  .AND.    &
1965                     surf_lsm_v(l)%ns > 0  )  THEN
1966             ALLOCATE( surf_lsm_v(l)%rad_lw_out_change_0(1:surf_lsm_v(l)%ns) )
1967             surf_lsm_v(l)%rad_lw_out_change_0 = 0.0_wp 
1968          ENDIF
1969          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_lw_out_change_0 )  .AND.    &
1970                     surf_usm_v(l)%ns > 0  )  THEN
1971             ALLOCATE( surf_usm_v(l)%rad_lw_out_change_0(1:surf_usm_v(l)%ns) )
1972             surf_usm_v(l)%rad_lw_out_change_0 = 0.0_wp 
1973          ENDIF
1974       ENDDO
1975
1976!
1977!--    Allocate surface arrays for incoming/outgoing short/longwave radiation
1978       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_sw_in )  .AND.                    &
1979                  surf_lsm_h%ns > 0  )   THEN
1980          ALLOCATE( surf_lsm_h%rad_sw_in(1:surf_lsm_h%ns)  )
1981          ALLOCATE( surf_lsm_h%rad_sw_out(1:surf_lsm_h%ns) )
1982          ALLOCATE( surf_lsm_h%rad_sw_dir(1:surf_lsm_h%ns) )
1983          ALLOCATE( surf_lsm_h%rad_sw_dif(1:surf_lsm_h%ns) )
1984          ALLOCATE( surf_lsm_h%rad_sw_ref(1:surf_lsm_h%ns) )
1985          ALLOCATE( surf_lsm_h%rad_sw_res(1:surf_lsm_h%ns) )
1986          ALLOCATE( surf_lsm_h%rad_lw_in(1:surf_lsm_h%ns)  )
1987          ALLOCATE( surf_lsm_h%rad_lw_out(1:surf_lsm_h%ns) )
1988          ALLOCATE( surf_lsm_h%rad_lw_dif(1:surf_lsm_h%ns) )
1989          ALLOCATE( surf_lsm_h%rad_lw_ref(1:surf_lsm_h%ns) )
1990          ALLOCATE( surf_lsm_h%rad_lw_res(1:surf_lsm_h%ns) )
1991          surf_lsm_h%rad_sw_in  = 0.0_wp 
1992          surf_lsm_h%rad_sw_out = 0.0_wp 
1993          surf_lsm_h%rad_sw_dir = 0.0_wp 
1994          surf_lsm_h%rad_sw_dif = 0.0_wp 
1995          surf_lsm_h%rad_sw_ref = 0.0_wp 
1996          surf_lsm_h%rad_sw_res = 0.0_wp 
1997          surf_lsm_h%rad_lw_in  = 0.0_wp 
1998          surf_lsm_h%rad_lw_out = 0.0_wp 
1999          surf_lsm_h%rad_lw_dif = 0.0_wp 
2000          surf_lsm_h%rad_lw_ref = 0.0_wp 
2001          surf_lsm_h%rad_lw_res = 0.0_wp 
2002       ENDIF
2003       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_sw_in )  .AND.                    &
2004                  surf_usm_h%ns > 0  )  THEN
2005          ALLOCATE( surf_usm_h%rad_sw_in(1:surf_usm_h%ns)  )
2006          ALLOCATE( surf_usm_h%rad_sw_out(1:surf_usm_h%ns) )
2007          ALLOCATE( surf_usm_h%rad_sw_dir(1:surf_usm_h%ns) )
2008          ALLOCATE( surf_usm_h%rad_sw_dif(1:surf_usm_h%ns) )
2009          ALLOCATE( surf_usm_h%rad_sw_ref(1:surf_usm_h%ns) )
2010          ALLOCATE( surf_usm_h%rad_sw_res(1:surf_usm_h%ns) )
2011          ALLOCATE( surf_usm_h%rad_lw_in(1:surf_usm_h%ns)  )
2012          ALLOCATE( surf_usm_h%rad_lw_out(1:surf_usm_h%ns) )
2013          ALLOCATE( surf_usm_h%rad_lw_dif(1:surf_usm_h%ns) )
2014          ALLOCATE( surf_usm_h%rad_lw_ref(1:surf_usm_h%ns) )
2015          ALLOCATE( surf_usm_h%rad_lw_res(1:surf_usm_h%ns) )
2016          surf_usm_h%rad_sw_in  = 0.0_wp 
2017          surf_usm_h%rad_sw_out = 0.0_wp 
2018          surf_usm_h%rad_sw_dir = 0.0_wp 
2019          surf_usm_h%rad_sw_dif = 0.0_wp 
2020          surf_usm_h%rad_sw_ref = 0.0_wp 
2021          surf_usm_h%rad_sw_res = 0.0_wp 
2022          surf_usm_h%rad_lw_in  = 0.0_wp 
2023          surf_usm_h%rad_lw_out = 0.0_wp 
2024          surf_usm_h%rad_lw_dif = 0.0_wp 
2025          surf_usm_h%rad_lw_ref = 0.0_wp 
2026          surf_usm_h%rad_lw_res = 0.0_wp 
2027       ENDIF
2028       DO  l = 0, 3
2029          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_sw_in )  .AND.              &
2030                     surf_lsm_v(l)%ns > 0  )  THEN
2031             ALLOCATE( surf_lsm_v(l)%rad_sw_in(1:surf_lsm_v(l)%ns)  )
2032             ALLOCATE( surf_lsm_v(l)%rad_sw_out(1:surf_lsm_v(l)%ns) )
2033             ALLOCATE( surf_lsm_v(l)%rad_sw_dir(1:surf_lsm_v(l)%ns) )
2034             ALLOCATE( surf_lsm_v(l)%rad_sw_dif(1:surf_lsm_v(l)%ns) )
2035             ALLOCATE( surf_lsm_v(l)%rad_sw_ref(1:surf_lsm_v(l)%ns) )
2036             ALLOCATE( surf_lsm_v(l)%rad_sw_res(1:surf_lsm_v(l)%ns) )
2037
2038             ALLOCATE( surf_lsm_v(l)%rad_lw_in(1:surf_lsm_v(l)%ns)  )
2039             ALLOCATE( surf_lsm_v(l)%rad_lw_out(1:surf_lsm_v(l)%ns) )
2040             ALLOCATE( surf_lsm_v(l)%rad_lw_dif(1:surf_lsm_v(l)%ns) )
2041             ALLOCATE( surf_lsm_v(l)%rad_lw_ref(1:surf_lsm_v(l)%ns) )
2042             ALLOCATE( surf_lsm_v(l)%rad_lw_res(1:surf_lsm_v(l)%ns) )
2043
2044             surf_lsm_v(l)%rad_sw_in  = 0.0_wp 
2045             surf_lsm_v(l)%rad_sw_out = 0.0_wp
2046             surf_lsm_v(l)%rad_sw_dir = 0.0_wp
2047             surf_lsm_v(l)%rad_sw_dif = 0.0_wp
2048             surf_lsm_v(l)%rad_sw_ref = 0.0_wp
2049             surf_lsm_v(l)%rad_sw_res = 0.0_wp
2050
2051             surf_lsm_v(l)%rad_lw_in  = 0.0_wp 
2052             surf_lsm_v(l)%rad_lw_out = 0.0_wp 
2053             surf_lsm_v(l)%rad_lw_dif = 0.0_wp 
2054             surf_lsm_v(l)%rad_lw_ref = 0.0_wp 
2055             surf_lsm_v(l)%rad_lw_res = 0.0_wp 
2056          ENDIF
2057          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_sw_in )  .AND.              &
2058                     surf_usm_v(l)%ns > 0  )  THEN
2059             ALLOCATE( surf_usm_v(l)%rad_sw_in(1:surf_usm_v(l)%ns)  )
2060             ALLOCATE( surf_usm_v(l)%rad_sw_out(1:surf_usm_v(l)%ns) )
2061             ALLOCATE( surf_usm_v(l)%rad_sw_dir(1:surf_usm_v(l)%ns) )
2062             ALLOCATE( surf_usm_v(l)%rad_sw_dif(1:surf_usm_v(l)%ns) )
2063             ALLOCATE( surf_usm_v(l)%rad_sw_ref(1:surf_usm_v(l)%ns) )
2064             ALLOCATE( surf_usm_v(l)%rad_sw_res(1:surf_usm_v(l)%ns) )
2065             ALLOCATE( surf_usm_v(l)%rad_lw_in(1:surf_usm_v(l)%ns)  )
2066             ALLOCATE( surf_usm_v(l)%rad_lw_out(1:surf_usm_v(l)%ns) )
2067             ALLOCATE( surf_usm_v(l)%rad_lw_dif(1:surf_usm_v(l)%ns) )
2068             ALLOCATE( surf_usm_v(l)%rad_lw_ref(1:surf_usm_v(l)%ns) )
2069             ALLOCATE( surf_usm_v(l)%rad_lw_res(1:surf_usm_v(l)%ns) )
2070             surf_usm_v(l)%rad_sw_in  = 0.0_wp 
2071             surf_usm_v(l)%rad_sw_out = 0.0_wp
2072             surf_usm_v(l)%rad_sw_dir = 0.0_wp
2073             surf_usm_v(l)%rad_sw_dif = 0.0_wp
2074             surf_usm_v(l)%rad_sw_ref = 0.0_wp
2075             surf_usm_v(l)%rad_sw_res = 0.0_wp
2076             surf_usm_v(l)%rad_lw_in  = 0.0_wp 
2077             surf_usm_v(l)%rad_lw_out = 0.0_wp 
2078             surf_usm_v(l)%rad_lw_dif = 0.0_wp 
2079             surf_usm_v(l)%rad_lw_ref = 0.0_wp 
2080             surf_usm_v(l)%rad_lw_res = 0.0_wp 
2081          ENDIF
2082       ENDDO
2083!
2084!--    Fix net radiation in case of radiation_scheme = 'constant'
2085       IF ( radiation_scheme == 'constant' )  THEN
2086          IF ( ALLOCATED( surf_lsm_h%rad_net ) )                               &
2087             surf_lsm_h%rad_net    = net_radiation
2088          IF ( ALLOCATED( surf_usm_h%rad_net ) )                               &
2089             surf_usm_h%rad_net    = net_radiation
2090!
2091!--       Todo: weight with inclination angle
2092          DO  l = 0, 3
2093             IF ( ALLOCATED( surf_lsm_v(l)%rad_net ) )                         &
2094                surf_lsm_v(l)%rad_net = net_radiation
2095             IF ( ALLOCATED( surf_usm_v(l)%rad_net ) )                         &
2096                surf_usm_v(l)%rad_net = net_radiation
2097          ENDDO
2098!          radiation = .FALSE.
2099!
2100!--    Calculate orbital constants
2101       ELSE
2102          decl_1 = SIN(23.45_wp * pi / 180.0_wp)
2103          decl_2 = 2.0_wp * pi / 365.0_wp
2104          decl_3 = decl_2 * 81.0_wp
2105          lat    = latitude * pi / 180.0_wp
2106          lon    = longitude * pi / 180.0_wp
2107       ENDIF
2108
2109       IF ( radiation_scheme == 'clear-sky'  .OR.                              &
2110            radiation_scheme == 'constant')  THEN
2111
2112
2113!
2114!--       Allocate arrays for incoming/outgoing short/longwave radiation
2115          IF ( .NOT. ALLOCATED ( rad_sw_in ) )  THEN
2116             ALLOCATE ( rad_sw_in(0:0,nysg:nyng,nxlg:nxrg) )
2117          ENDIF
2118          IF ( .NOT. ALLOCATED ( rad_sw_out ) )  THEN
2119             ALLOCATE ( rad_sw_out(0:0,nysg:nyng,nxlg:nxrg) )
2120          ENDIF
2121
2122          IF ( .NOT. ALLOCATED ( rad_lw_in ) )  THEN
2123             ALLOCATE ( rad_lw_in(0:0,nysg:nyng,nxlg:nxrg) )
2124          ENDIF
2125          IF ( .NOT. ALLOCATED ( rad_lw_out ) )  THEN
2126             ALLOCATE ( rad_lw_out(0:0,nysg:nyng,nxlg:nxrg) )
2127          ENDIF
2128
2129!
2130!--       Allocate average arrays for incoming/outgoing short/longwave radiation
2131          IF ( .NOT. ALLOCATED ( rad_sw_in_av ) )  THEN
2132             ALLOCATE ( rad_sw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
2133          ENDIF
2134          IF ( .NOT. ALLOCATED ( rad_sw_out_av ) )  THEN
2135             ALLOCATE ( rad_sw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
2136          ENDIF
2137
2138          IF ( .NOT. ALLOCATED ( rad_lw_in_av ) )  THEN
2139             ALLOCATE ( rad_lw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
2140          ENDIF
2141          IF ( .NOT. ALLOCATED ( rad_lw_out_av ) )  THEN
2142             ALLOCATE ( rad_lw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
2143          ENDIF
2144!
2145!--       Allocate arrays for broadband albedo, and level 1 initialization
2146!--       via namelist paramter, unless not already allocated.
2147          IF ( .NOT. ALLOCATED(surf_lsm_h%albedo) )  THEN
2148             ALLOCATE( surf_lsm_h%albedo(0:2,1:surf_lsm_h%ns)     )
2149             surf_lsm_h%albedo    = albedo
2150          ENDIF
2151          IF ( .NOT. ALLOCATED(surf_usm_h%albedo) )  THEN
2152             ALLOCATE( surf_usm_h%albedo(0:2,1:surf_usm_h%ns)     )
2153             surf_usm_h%albedo    = albedo
2154          ENDIF
2155
2156          DO  l = 0, 3
2157             IF ( .NOT. ALLOCATED( surf_lsm_v(l)%albedo ) )  THEN
2158                ALLOCATE( surf_lsm_v(l)%albedo(0:2,1:surf_lsm_v(l)%ns) )
2159                surf_lsm_v(l)%albedo = albedo
2160             ENDIF
2161             IF ( .NOT. ALLOCATED( surf_usm_v(l)%albedo ) )  THEN
2162                ALLOCATE( surf_usm_v(l)%albedo(0:2,1:surf_usm_v(l)%ns) )
2163                surf_usm_v(l)%albedo = albedo
2164             ENDIF
2165          ENDDO
2166!
2167!--       Level 2 initialization of broadband albedo via given albedo_type.
2168!--       Only if albedo_type is non-zero. In case of urban surface and
2169!--       input data is read from ASCII file, albedo_type will be zero, so that
2170!--       albedo won't be overwritten.
2171          DO  m = 1, surf_lsm_h%ns
2172             IF ( surf_lsm_h%albedo_type(ind_veg_wall,m) /= 0 )                &
2173                surf_lsm_h%albedo(ind_veg_wall,m) =                            &
2174                           albedo_pars(0,surf_lsm_h%albedo_type(ind_veg_wall,m))
2175             IF ( surf_lsm_h%albedo_type(ind_pav_green,m) /= 0 )               &
2176                surf_lsm_h%albedo(ind_pav_green,m) =                           &
2177                           albedo_pars(0,surf_lsm_h%albedo_type(ind_pav_green,m))
2178             IF ( surf_lsm_h%albedo_type(ind_wat_win,m) /= 0 )                 &
2179                surf_lsm_h%albedo(ind_wat_win,m) =                             &
2180                           albedo_pars(0,surf_lsm_h%albedo_type(ind_wat_win,m))
2181          ENDDO
2182          DO  m = 1, surf_usm_h%ns
2183             IF ( surf_usm_h%albedo_type(ind_veg_wall,m) /= 0 )                &
2184                surf_usm_h%albedo(ind_veg_wall,m) =                            &
2185                           albedo_pars(0,surf_usm_h%albedo_type(ind_veg_wall,m))
2186             IF ( surf_usm_h%albedo_type(ind_pav_green,m) /= 0 )               &
2187                surf_usm_h%albedo(ind_pav_green,m) =                           &
2188                           albedo_pars(0,surf_usm_h%albedo_type(ind_pav_green,m))
2189             IF ( surf_usm_h%albedo_type(ind_wat_win,m) /= 0 )                 &
2190                surf_usm_h%albedo(ind_wat_win,m) =                             &
2191                           albedo_pars(0,surf_usm_h%albedo_type(ind_wat_win,m))
2192          ENDDO
2193
2194          DO  l = 0, 3
2195             DO  m = 1, surf_lsm_v(l)%ns
2196                IF ( surf_lsm_v(l)%albedo_type(ind_veg_wall,m) /= 0 )          &
2197                   surf_lsm_v(l)%albedo(ind_veg_wall,m) =                      &
2198                        albedo_pars(0,surf_lsm_v(l)%albedo_type(ind_veg_wall,m))
2199                IF ( surf_lsm_v(l)%albedo_type(ind_pav_green,m) /= 0 )         &
2200                   surf_lsm_v(l)%albedo(ind_pav_green,m) =                     &
2201                        albedo_pars(0,surf_lsm_v(l)%albedo_type(ind_pav_green,m))
2202                IF ( surf_lsm_v(l)%albedo_type(ind_wat_win,m) /= 0 )           &
2203                   surf_lsm_v(l)%albedo(ind_wat_win,m) =                       &
2204                        albedo_pars(0,surf_lsm_v(l)%albedo_type(ind_wat_win,m))
2205             ENDDO
2206             DO  m = 1, surf_usm_v(l)%ns
2207                IF ( surf_usm_v(l)%albedo_type(ind_veg_wall,m) /= 0 )          &
2208                   surf_usm_v(l)%albedo(ind_veg_wall,m) =                      &
2209                        albedo_pars(0,surf_usm_v(l)%albedo_type(ind_veg_wall,m))
2210                IF ( surf_usm_v(l)%albedo_type(ind_pav_green,m) /= 0 )         &
2211                   surf_usm_v(l)%albedo(ind_pav_green,m) =                     &
2212                        albedo_pars(0,surf_usm_v(l)%albedo_type(ind_pav_green,m))
2213                IF ( surf_usm_v(l)%albedo_type(ind_wat_win,m) /= 0 )           &
2214                   surf_usm_v(l)%albedo(ind_wat_win,m) =                       &
2215                        albedo_pars(0,surf_usm_v(l)%albedo_type(ind_wat_win,m))
2216             ENDDO
2217          ENDDO
2218
2219!
2220!--       Level 3 initialization at grid points where albedo type is zero.
2221!--       This case, albedo is taken from file. In case of constant radiation
2222!--       or clear sky, only broadband albedo is given.
2223          IF ( albedo_pars_f%from_file )  THEN
2224!
2225!--          Horizontal surfaces
2226             DO  m = 1, surf_lsm_h%ns
2227                i = surf_lsm_h%i(m)
2228                j = surf_lsm_h%j(m)
2229                IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2230                   IF ( surf_lsm_h%albedo_type(ind_veg_wall,m) == 0 )          &
2231                      surf_lsm_h%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2232                   IF ( surf_lsm_h%albedo_type(ind_pav_green,m) == 0 )         &
2233                      surf_lsm_h%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2234                   IF ( surf_lsm_h%albedo_type(ind_wat_win,m) == 0 )           &
2235                      surf_lsm_h%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2236                ENDIF
2237             ENDDO
2238             DO  m = 1, surf_usm_h%ns
2239                i = surf_usm_h%i(m)
2240                j = surf_usm_h%j(m)
2241                IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2242                   IF ( surf_usm_h%albedo_type(ind_veg_wall,m) == 0 )          &
2243                      surf_usm_h%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2244                   IF ( surf_usm_h%albedo_type(ind_pav_green,m) == 0 )         &
2245                      surf_usm_h%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2246                   IF ( surf_usm_h%albedo_type(ind_wat_win,m) == 0 )           &
2247                      surf_usm_h%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2248                ENDIF
2249             ENDDO 
2250!
2251!--          Vertical surfaces           
2252             DO  l = 0, 3
2253
2254                ioff = surf_lsm_v(l)%ioff
2255                joff = surf_lsm_v(l)%joff
2256                DO  m = 1, surf_lsm_v(l)%ns
2257                   i = surf_lsm_v(l)%i(m) + ioff
2258                   j = surf_lsm_v(l)%j(m) + joff
2259                   IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2260                      IF ( surf_lsm_v(l)%albedo_type(ind_veg_wall,m) == 0 )    &
2261                         surf_lsm_v(l)%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2262                      IF ( surf_lsm_v(l)%albedo_type(ind_pav_green,m) == 0 )   &
2263                         surf_lsm_v(l)%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2264                      IF ( surf_lsm_v(l)%albedo_type(ind_wat_win,m) == 0 )     &
2265                         surf_lsm_v(l)%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2266                   ENDIF
2267                ENDDO
2268
2269                ioff = surf_usm_v(l)%ioff
2270                joff = surf_usm_v(l)%joff
2271                DO  m = 1, surf_usm_v(l)%ns
2272                   i = surf_usm_v(l)%i(m) + joff
2273                   j = surf_usm_v(l)%j(m) + joff
2274                   IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2275                      IF ( surf_usm_v(l)%albedo_type(ind_veg_wall,m) == 0 )    &
2276                         surf_usm_v(l)%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2277                      IF ( surf_usm_v(l)%albedo_type(ind_pav_green,m) == 0 )   &
2278                         surf_usm_v(l)%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2279                      IF ( surf_usm_v(l)%albedo_type(ind_wat_win,m) == 0 )     &
2280                         surf_usm_v(l)%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2281                   ENDIF
2282                ENDDO
2283             ENDDO
2284
2285          ENDIF 
2286!
2287!--    Initialization actions for RRTMG
2288       ELSEIF ( radiation_scheme == 'rrtmg' )  THEN
2289#if defined ( __rrtmg )
2290!
2291!--       Allocate albedos for short/longwave radiation, horizontal surfaces
2292!--       for wall/green/window (USM) or vegetation/pavement/water surfaces
2293!--       (LSM).
2294          ALLOCATE ( surf_lsm_h%aldif(0:2,1:surf_lsm_h%ns)       )
2295          ALLOCATE ( surf_lsm_h%aldir(0:2,1:surf_lsm_h%ns)       )
2296          ALLOCATE ( surf_lsm_h%asdif(0:2,1:surf_lsm_h%ns)       )
2297          ALLOCATE ( surf_lsm_h%asdir(0:2,1:surf_lsm_h%ns)       )
2298          ALLOCATE ( surf_lsm_h%rrtm_aldif(0:2,1:surf_lsm_h%ns)  )
2299          ALLOCATE ( surf_lsm_h%rrtm_aldir(0:2,1:surf_lsm_h%ns)  )
2300          ALLOCATE ( surf_lsm_h%rrtm_asdif(0:2,1:surf_lsm_h%ns)  )
2301          ALLOCATE ( surf_lsm_h%rrtm_asdir(0:2,1:surf_lsm_h%ns)  )
2302
2303          ALLOCATE ( surf_usm_h%aldif(0:2,1:surf_usm_h%ns)       )
2304          ALLOCATE ( surf_usm_h%aldir(0:2,1:surf_usm_h%ns)       )
2305          ALLOCATE ( surf_usm_h%asdif(0:2,1:surf_usm_h%ns)       )
2306          ALLOCATE ( surf_usm_h%asdir(0:2,1:surf_usm_h%ns)       )
2307          ALLOCATE ( surf_usm_h%rrtm_aldif(0:2,1:surf_usm_h%ns)  )
2308          ALLOCATE ( surf_usm_h%rrtm_aldir(0:2,1:surf_usm_h%ns)  )
2309          ALLOCATE ( surf_usm_h%rrtm_asdif(0:2,1:surf_usm_h%ns)  )
2310          ALLOCATE ( surf_usm_h%rrtm_asdir(0:2,1:surf_usm_h%ns)  )
2311
2312!
2313!--       Allocate broadband albedo (temporary for the current radiation
2314!--       implementations)
2315          IF ( .NOT. ALLOCATED(surf_lsm_h%albedo) )                            &
2316             ALLOCATE( surf_lsm_h%albedo(0:2,1:surf_lsm_h%ns)     )
2317          IF ( .NOT. ALLOCATED(surf_usm_h%albedo) )                            &
2318             ALLOCATE( surf_usm_h%albedo(0:2,1:surf_usm_h%ns)     )
2319
2320!
2321!--       Allocate albedos for short/longwave radiation, vertical surfaces
2322          DO  l = 0, 3
2323
2324             ALLOCATE ( surf_lsm_v(l)%aldif(0:2,1:surf_lsm_v(l)%ns)      )
2325             ALLOCATE ( surf_lsm_v(l)%aldir(0:2,1:surf_lsm_v(l)%ns)      )
2326             ALLOCATE ( surf_lsm_v(l)%asdif(0:2,1:surf_lsm_v(l)%ns)      )
2327             ALLOCATE ( surf_lsm_v(l)%asdir(0:2,1:surf_lsm_v(l)%ns)      )
2328
2329             ALLOCATE ( surf_lsm_v(l)%rrtm_aldif(0:2,1:surf_lsm_v(l)%ns) )
2330             ALLOCATE ( surf_lsm_v(l)%rrtm_aldir(0:2,1:surf_lsm_v(l)%ns) )
2331             ALLOCATE ( surf_lsm_v(l)%rrtm_asdif(0:2,1:surf_lsm_v(l)%ns) )
2332             ALLOCATE ( surf_lsm_v(l)%rrtm_asdir(0:2,1:surf_lsm_v(l)%ns) )
2333
2334             ALLOCATE ( surf_usm_v(l)%aldif(0:2,1:surf_usm_v(l)%ns)      )
2335             ALLOCATE ( surf_usm_v(l)%aldir(0:2,1:surf_usm_v(l)%ns)      )
2336             ALLOCATE ( surf_usm_v(l)%asdif(0:2,1:surf_usm_v(l)%ns)      )
2337             ALLOCATE ( surf_usm_v(l)%asdir(0:2,1:surf_usm_v(l)%ns)      )
2338
2339             ALLOCATE ( surf_usm_v(l)%rrtm_aldif(0:2,1:surf_usm_v(l)%ns) )
2340             ALLOCATE ( surf_usm_v(l)%rrtm_aldir(0:2,1:surf_usm_v(l)%ns) )
2341             ALLOCATE ( surf_usm_v(l)%rrtm_asdif(0:2,1:surf_usm_v(l)%ns) )
2342             ALLOCATE ( surf_usm_v(l)%rrtm_asdir(0:2,1:surf_usm_v(l)%ns) )
2343!
2344!--          Allocate broadband albedo (temporary for the current radiation
2345!--          implementations)
2346             IF ( .NOT. ALLOCATED( surf_lsm_v(l)%albedo ) )                    &
2347                ALLOCATE( surf_lsm_v(l)%albedo(0:2,1:surf_lsm_v(l)%ns) )
2348             IF ( .NOT. ALLOCATED( surf_usm_v(l)%albedo ) )                    &
2349                ALLOCATE( surf_usm_v(l)%albedo(0:2,1:surf_usm_v(l)%ns) )
2350
2351          ENDDO
2352!
2353!--       Level 1 initialization of spectral albedos via namelist
2354!--       paramters. Please note, this case all surface tiles are initialized
2355!--       the same.
2356          IF ( surf_lsm_h%ns > 0 )  THEN
2357             surf_lsm_h%aldif  = albedo_lw_dif
2358             surf_lsm_h%aldir  = albedo_lw_dir
2359             surf_lsm_h%asdif  = albedo_sw_dif
2360             surf_lsm_h%asdir  = albedo_sw_dir
2361             surf_lsm_h%albedo = albedo_sw_dif
2362          ENDIF
2363          IF ( surf_usm_h%ns > 0 )  THEN
2364             IF ( surf_usm_h%albedo_from_ascii )  THEN
2365                surf_usm_h%aldif  = surf_usm_h%albedo
2366                surf_usm_h%aldir  = surf_usm_h%albedo
2367                surf_usm_h%asdif  = surf_usm_h%albedo
2368                surf_usm_h%asdir  = surf_usm_h%albedo
2369             ELSE
2370                surf_usm_h%aldif  = albedo_lw_dif
2371                surf_usm_h%aldir  = albedo_lw_dir
2372                surf_usm_h%asdif  = albedo_sw_dif
2373                surf_usm_h%asdir  = albedo_sw_dir
2374                surf_usm_h%albedo = albedo_sw_dif
2375             ENDIF
2376          ENDIF
2377
2378          DO  l = 0, 3
2379
2380             IF ( surf_lsm_v(l)%ns > 0 )  THEN
2381                surf_lsm_v(l)%aldif  = albedo_lw_dif
2382                surf_lsm_v(l)%aldir  = albedo_lw_dir
2383                surf_lsm_v(l)%asdif  = albedo_sw_dif
2384                surf_lsm_v(l)%asdir  = albedo_sw_dir
2385                surf_lsm_v(l)%albedo = albedo_sw_dif
2386             ENDIF
2387
2388             IF ( surf_usm_v(l)%ns > 0 )  THEN
2389                IF ( surf_usm_v(l)%albedo_from_ascii )  THEN
2390                   surf_usm_v(l)%aldif  = surf_usm_v(l)%albedo
2391                   surf_usm_v(l)%aldir  = surf_usm_v(l)%albedo
2392                   surf_usm_v(l)%asdif  = surf_usm_v(l)%albedo
2393                   surf_usm_v(l)%asdir  = surf_usm_v(l)%albedo
2394                ELSE
2395                   surf_usm_v(l)%aldif  = albedo_lw_dif
2396                   surf_usm_v(l)%aldir  = albedo_lw_dir
2397                   surf_usm_v(l)%asdif  = albedo_sw_dif
2398                   surf_usm_v(l)%asdir  = albedo_sw_dir
2399                ENDIF
2400             ENDIF
2401          ENDDO
2402
2403!
2404!--       Level 2 initialization of spectral albedos via albedo_type.
2405!--       Please note, for natural- and urban-type surfaces, a tile approach
2406!--       is applied so that the resulting albedo is calculated via the weighted
2407!--       average of respective surface fractions.
2408          DO  m = 1, surf_lsm_h%ns
2409!
2410!--          Spectral albedos for vegetation/pavement/water surfaces
2411             DO  ind_type = 0, 2
2412                IF ( surf_lsm_h%albedo_type(ind_type,m) /= 0 )  THEN
2413                   surf_lsm_h%aldif(ind_type,m) =                              &
2414                               albedo_pars(1,surf_lsm_h%albedo_type(ind_type,m))
2415                   surf_lsm_h%asdif(ind_type,m) =                              &
2416                               albedo_pars(2,surf_lsm_h%albedo_type(ind_type,m))
2417                   surf_lsm_h%aldir(ind_type,m) =                              &
2418                               albedo_pars(1,surf_lsm_h%albedo_type(ind_type,m))
2419                   surf_lsm_h%asdir(ind_type,m) =                              &
2420                               albedo_pars(2,surf_lsm_h%albedo_type(ind_type,m))
2421                   surf_lsm_h%albedo(ind_type,m) =                             &
2422                               albedo_pars(0,surf_lsm_h%albedo_type(ind_type,m))
2423                ENDIF
2424             ENDDO
2425
2426          ENDDO
2427!
2428!--       For urban surface only if albedo has not been already initialized
2429!--       in the urban-surface model via the ASCII file.
2430          IF ( .NOT. surf_usm_h%albedo_from_ascii )  THEN
2431             DO  m = 1, surf_usm_h%ns
2432!
2433!--             Spectral albedos for wall/green/window surfaces
2434                DO  ind_type = 0, 2
2435                   IF ( surf_usm_h%albedo_type(ind_type,m) /= 0 )  THEN
2436                      surf_usm_h%aldif(ind_type,m) =                           &
2437                               albedo_pars(1,surf_usm_h%albedo_type(ind_type,m))
2438                      surf_usm_h%asdif(ind_type,m) =                           &
2439                               albedo_pars(2,surf_usm_h%albedo_type(ind_type,m))
2440                      surf_usm_h%aldir(ind_type,m) =                           &
2441                               albedo_pars(1,surf_usm_h%albedo_type(ind_type,m))
2442                      surf_usm_h%asdir(ind_type,m) =                           &
2443                               albedo_pars(2,surf_usm_h%albedo_type(ind_type,m))
2444                      surf_usm_h%albedo(ind_type,m) =                          &
2445                               albedo_pars(0,surf_usm_h%albedo_type(ind_type,m))
2446                   ENDIF
2447                ENDDO
2448
2449             ENDDO
2450          ENDIF
2451
2452          DO l = 0, 3
2453
2454             DO  m = 1, surf_lsm_v(l)%ns
2455!
2456!--             Spectral albedos for vegetation/pavement/water surfaces
2457                DO  ind_type = 0, 2
2458                   IF ( surf_lsm_v(l)%albedo_type(ind_type,m) /= 0 )  THEN
2459                      surf_lsm_v(l)%aldif(ind_type,m) =                        &
2460                            albedo_pars(1,surf_lsm_v(l)%albedo_type(ind_type,m))
2461                      surf_lsm_v(l)%asdif(ind_type,m) =                        &
2462                            albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_type,m))
2463                      surf_lsm_v(l)%aldir(ind_type,m) =                        &
2464                            albedo_pars(1,surf_lsm_v(l)%albedo_type(ind_type,m))
2465                      surf_lsm_v(l)%asdir(ind_type,m) =                        &
2466                            albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_type,m))
2467                      surf_lsm_v(l)%albedo(ind_type,m) =                       &
2468                            albedo_pars(0,surf_lsm_v(l)%albedo_type(ind_type,m))
2469                   ENDIF
2470                ENDDO
2471             ENDDO
2472!
2473!--          For urban surface only if albedo has not been already initialized
2474!--          in the urban-surface model via the ASCII file.
2475             IF ( .NOT. surf_usm_v(l)%albedo_from_ascii )  THEN
2476                DO  m = 1, surf_usm_v(l)%ns
2477!
2478!--                Spectral albedos for wall/green/window surfaces
2479                   DO  ind_type = 0, 2
2480                      IF ( surf_usm_v(l)%albedo_type(ind_type,m) /= 0 )  THEN
2481                         surf_usm_v(l)%aldif(ind_type,m) =                     &
2482                            albedo_pars(1,surf_usm_v(l)%albedo_type(ind_type,m))
2483                         surf_usm_v(l)%asdif(ind_type,m) =                     &
2484                            albedo_pars(2,surf_usm_v(l)%albedo_type(ind_type,m))
2485                         surf_usm_v(l)%aldir(ind_type,m) =                     &
2486                            albedo_pars(1,surf_usm_v(l)%albedo_type(ind_type,m))
2487                         surf_usm_v(l)%asdir(ind_type,m) =                     &
2488                            albedo_pars(2,surf_usm_v(l)%albedo_type(ind_type,m))
2489                         surf_usm_v(l)%albedo(ind_type,m) =                    &
2490                            albedo_pars(0,surf_usm_v(l)%albedo_type(ind_type,m))
2491                      ENDIF
2492                   ENDDO
2493
2494                ENDDO
2495             ENDIF
2496          ENDDO
2497!
2498!--       Level 3 initialization at grid points where albedo type is zero.
2499!--       This case, spectral albedos are taken from file if available
2500          IF ( albedo_pars_f%from_file )  THEN
2501!
2502!--          Horizontal
2503             DO  m = 1, surf_lsm_h%ns
2504                i = surf_lsm_h%i(m)
2505                j = surf_lsm_h%j(m)
2506!
2507!--             Spectral albedos for vegetation/pavement/water surfaces
2508                DO  ind_type = 0, 2
2509                   IF ( surf_lsm_h%albedo_type(ind_type,m) == 0 )  THEN
2510                      IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )&
2511                         surf_lsm_h%albedo(ind_type,m) =                       &
2512                                                albedo_pars_f%pars_xy(0,j,i)
2513                      IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2514                         surf_lsm_h%aldir(ind_type,m) =                        &
2515                                                albedo_pars_f%pars_xy(1,j,i)
2516                      IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2517                         surf_lsm_h%aldif(ind_type,m) =                        &
2518                                                albedo_pars_f%pars_xy(1,j,i)
2519                      IF ( albedo_pars_f%pars_xy(2,j,i) /= albedo_pars_f%fill )&
2520                         surf_lsm_h%asdir(ind_type,m) =                        &
2521                                                albedo_pars_f%pars_xy(2,j,i)
2522                      IF ( albedo_pars_f%pars_xy(2,j,i) /= albedo_pars_f%fill )&
2523                         surf_lsm_h%asdif(ind_type,m) =                        &
2524                                                albedo_pars_f%pars_xy(2,j,i)
2525                   ENDIF
2526                ENDDO
2527             ENDDO
2528!
2529!--          For urban surface only if albedo has not been already initialized
2530!--          in the urban-surface model via the ASCII file.
2531             IF ( .NOT. surf_usm_h%albedo_from_ascii )  THEN
2532                DO  m = 1, surf_usm_h%ns
2533                   i = surf_usm_h%i(m)
2534                   j = surf_usm_h%j(m)
2535!
2536!--                Broadband albedos for wall/green/window surfaces
2537                   DO  ind_type = 0, 2
2538                      IF ( surf_usm_h%albedo_type(ind_type,m) == 0 )  THEN
2539                         IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )&
2540                            surf_usm_h%albedo(ind_type,m) =                       &
2541                                                albedo_pars_f%pars_xy(0,j,i)
2542                      ENDIF
2543                   ENDDO
2544!
2545!--                Spectral albedos especially for building wall surfaces
2546                   IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )  THEN
2547                      surf_usm_h%aldir(ind_veg_wall,m) =                       &
2548                                                albedo_pars_f%pars_xy(1,j,i)
2549                      surf_usm_h%aldif(ind_veg_wall,m) =                       &
2550                                                albedo_pars_f%pars_xy(1,j,i)
2551                   ENDIF
2552                   IF ( albedo_pars_f%pars_xy(2,j,i) /= albedo_pars_f%fill )  THEN
2553                      surf_usm_h%asdir(ind_veg_wall,m) =                       &
2554                                                albedo_pars_f%pars_xy(2,j,i)
2555                      surf_usm_h%asdif(ind_veg_wall,m) =                       &
2556                                                albedo_pars_f%pars_xy(2,j,i)
2557                   ENDIF
2558!
2559!--                Spectral albedos especially for building green surfaces
2560                   IF ( albedo_pars_f%pars_xy(3,j,i) /= albedo_pars_f%fill )  THEN
2561                      surf_usm_h%aldir(ind_pav_green,m) =                      &
2562                                                albedo_pars_f%pars_xy(3,j,i)
2563                      surf_usm_h%aldif(ind_pav_green,m) =                      &
2564                                                albedo_pars_f%pars_xy(3,j,i)
2565                   ENDIF
2566                   IF ( albedo_pars_f%pars_xy(4,j,i) /= albedo_pars_f%fill )  THEN
2567                      surf_usm_h%asdir(ind_pav_green,m) =                      &
2568                                                albedo_pars_f%pars_xy(4,j,i)
2569                      surf_usm_h%asdif(ind_pav_green,m) =                      &
2570                                                albedo_pars_f%pars_xy(4,j,i)
2571                   ENDIF
2572!
2573!--                Spectral albedos especially for building window surfaces
2574                   IF ( albedo_pars_f%pars_xy(5,j,i) /= albedo_pars_f%fill )  THEN
2575                      surf_usm_h%aldir(ind_wat_win,m) =                        &
2576                                                albedo_pars_f%pars_xy(5,j,i)
2577                      surf_usm_h%aldif(ind_wat_win,m) =                        &
2578                                                albedo_pars_f%pars_xy(5,j,i)
2579                   ENDIF
2580                   IF ( albedo_pars_f%pars_xy(6,j,i) /= albedo_pars_f%fill )  THEN
2581                      surf_usm_h%asdir(ind_wat_win,m) =                        &
2582                                                albedo_pars_f%pars_xy(6,j,i)
2583                      surf_usm_h%asdif(ind_wat_win,m) =                        &
2584                                                albedo_pars_f%pars_xy(6,j,i)
2585                   ENDIF
2586
2587                ENDDO
2588             ENDIF
2589!
2590!--          Vertical
2591             DO  l = 0, 3
2592                ioff = surf_lsm_v(l)%ioff
2593                joff = surf_lsm_v(l)%joff
2594
2595                DO  m = 1, surf_lsm_v(l)%ns
2596                   i = surf_lsm_v(l)%i(m)
2597                   j = surf_lsm_v(l)%j(m)
2598!
2599!--                Spectral albedos for vegetation/pavement/water surfaces
2600                   DO  ind_type = 0, 2
2601                      IF ( surf_lsm_v(l)%albedo_type(ind_type,m) == 0 )  THEN
2602                         IF ( albedo_pars_f%pars_xy(0,j+joff,i+ioff) /=        &
2603                              albedo_pars_f%fill )                             &
2604                            surf_lsm_v(l)%albedo(ind_type,m) =                 &
2605                                          albedo_pars_f%pars_xy(0,j+joff,i+ioff)
2606                         IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2607                              albedo_pars_f%fill )                             &
2608                            surf_lsm_v(l)%aldir(ind_type,m) =                  &
2609                                          albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2610                         IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2611                              albedo_pars_f%fill )                             &
2612                            surf_lsm_v(l)%aldif(ind_type,m) =                  &
2613                                          albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2614                         IF ( albedo_pars_f%pars_xy(2,j+joff,i+ioff) /=        &
2615                              albedo_pars_f%fill )                             &
2616                            surf_lsm_v(l)%asdir(ind_type,m) =                  &
2617                                          albedo_pars_f%pars_xy(2,j+joff,i+ioff)
2618                         IF ( albedo_pars_f%pars_xy(2,j+joff,i+ioff) /=        &
2619                              albedo_pars_f%fill )                             &
2620                            surf_lsm_v(l)%asdif(ind_type,m) =                  &
2621                                          albedo_pars_f%pars_xy(2,j+joff,i+ioff)
2622                      ENDIF
2623                   ENDDO
2624                ENDDO
2625!
2626!--             For urban surface only if albedo has not been already initialized
2627!--             in the urban-surface model via the ASCII file.
2628                IF ( .NOT. surf_usm_v(l)%albedo_from_ascii )  THEN
2629                   ioff = surf_usm_v(l)%ioff
2630                   joff = surf_usm_v(l)%joff
2631
2632                   DO  m = 1, surf_usm_v(l)%ns
2633                      i = surf_usm_v(l)%i(m)
2634                      j = surf_usm_v(l)%j(m)
2635!
2636!--                   Broadband albedos for wall/green/window surfaces
2637                      DO  ind_type = 0, 2
2638                         IF ( surf_usm_v(l)%albedo_type(ind_type,m) == 0 )  THEN
2639                            IF ( albedo_pars_f%pars_xy(0,j+joff,i+ioff) /=     &
2640                                 albedo_pars_f%fill )                          &
2641                               surf_usm_v(l)%albedo(ind_type,m) =              &
2642                                             albedo_pars_f%pars_xy(0,j+joff,i+ioff)
2643                         ENDIF
2644                      ENDDO
2645!
2646!--                   Spectral albedos especially for building wall surfaces
2647                      IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=           &
2648                           albedo_pars_f%fill )  THEN
2649                         surf_usm_v(l)%aldir(ind_veg_wall,m) =                 &
2650                                         albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2651                         surf_usm_v(l)%aldif(ind_veg_wall,m) =                 &
2652                                         albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2653                      ENDIF
2654                      IF ( albedo_pars_f%pars_xy(2,j+joff,i+ioff) /=           &
2655                           albedo_pars_f%fill )  THEN
2656                         surf_usm_v(l)%asdir(ind_veg_wall,m) =                 &
2657                                         albedo_pars_f%pars_xy(2,j+joff,i+ioff)
2658                         surf_usm_v(l)%asdif(ind_veg_wall,m) =                 &
2659                                         albedo_pars_f%pars_xy(2,j+joff,i+ioff)
2660                      ENDIF
2661!                     
2662!--                   Spectral albedos especially for building green surfaces
2663                      IF ( albedo_pars_f%pars_xy(3,j+joff,i+ioff) /=           &
2664                           albedo_pars_f%fill )  THEN
2665                         surf_usm_v(l)%aldir(ind_pav_green,m) =                &
2666                                         albedo_pars_f%pars_xy(3,j+joff,i+ioff)
2667                         surf_usm_v(l)%aldif(ind_pav_green,m) =                &
2668                                         albedo_pars_f%pars_xy(3,j+joff,i+ioff)
2669                      ENDIF
2670                      IF ( albedo_pars_f%pars_xy(4,j+joff,i+ioff) /=           &
2671                           albedo_pars_f%fill )  THEN
2672                         surf_usm_v(l)%asdir(ind_pav_green,m) =                &
2673                                         albedo_pars_f%pars_xy(4,j+joff,i+ioff)
2674                         surf_usm_v(l)%asdif(ind_pav_green,m) =                &
2675                                         albedo_pars_f%pars_xy(4,j+joff,i+ioff)
2676                      ENDIF
2677!                     
2678!--                   Spectral albedos especially for building window surfaces
2679                      IF ( albedo_pars_f%pars_xy(5,j+joff,i+ioff) /=           &
2680                           albedo_pars_f%fill )  THEN
2681                         surf_usm_v(l)%aldir(ind_wat_win,m) =                  &
2682                                         albedo_pars_f%pars_xy(5,j+joff,i+ioff)
2683                         surf_usm_v(l)%aldif(ind_wat_win,m) =                  &
2684                                         albedo_pars_f%pars_xy(5,j+joff,i+ioff)
2685                      ENDIF
2686                      IF ( albedo_pars_f%pars_xy(6,j+joff,i+ioff) /=           &
2687                           albedo_pars_f%fill )  THEN
2688                         surf_usm_v(l)%asdir(ind_wat_win,m) =                  &
2689                                         albedo_pars_f%pars_xy(6,j+joff,i+ioff)
2690                         surf_usm_v(l)%asdif(ind_wat_win,m) =                  &
2691                                         albedo_pars_f%pars_xy(6,j+joff,i+ioff)
2692                      ENDIF
2693                   ENDDO
2694                ENDIF
2695             ENDDO
2696
2697          ENDIF
2698
2699!
2700!--       Calculate initial values of current (cosine of) the zenith angle and
2701!--       whether the sun is up
2702          CALL calc_zenith
2703!
2704!--       readjust date and time to its initial value
2705          CALL init_date_and_time
2706!
2707!--       Calculate initial surface albedo for different surfaces
2708          IF ( .NOT. constant_albedo )  THEN
2709#if defined( __netcdf )
2710!
2711!--          Horizontally aligned natural and urban surfaces
2712             CALL calc_albedo( surf_lsm_h )
2713             CALL calc_albedo( surf_usm_h )
2714!
2715!--          Vertically aligned natural and urban surfaces
2716             DO  l = 0, 3
2717                CALL calc_albedo( surf_lsm_v(l) )
2718                CALL calc_albedo( surf_usm_v(l) )
2719             ENDDO
2720#endif
2721          ELSE
2722!
2723!--          Initialize sun-inclination independent spectral albedos
2724!--          Horizontal surfaces
2725             IF ( surf_lsm_h%ns > 0 )  THEN
2726                surf_lsm_h%rrtm_aldir = surf_lsm_h%aldir
2727                surf_lsm_h%rrtm_asdir = surf_lsm_h%asdir
2728                surf_lsm_h%rrtm_aldif = surf_lsm_h%aldif
2729                surf_lsm_h%rrtm_asdif = surf_lsm_h%asdif
2730             ENDIF
2731             IF ( surf_usm_h%ns > 0 )  THEN
2732                surf_usm_h%rrtm_aldir = surf_usm_h%aldir
2733                surf_usm_h%rrtm_asdir = surf_usm_h%asdir
2734                surf_usm_h%rrtm_aldif = surf_usm_h%aldif
2735                surf_usm_h%rrtm_asdif = surf_usm_h%asdif
2736             ENDIF
2737!
2738!--          Vertical surfaces
2739             DO  l = 0, 3
2740                IF ( surf_lsm_v(l)%ns > 0 )  THEN
2741                   surf_lsm_v(l)%rrtm_aldir = surf_lsm_v(l)%aldir
2742                   surf_lsm_v(l)%rrtm_asdir = surf_lsm_v(l)%asdir
2743                   surf_lsm_v(l)%rrtm_aldif = surf_lsm_v(l)%aldif
2744                   surf_lsm_v(l)%rrtm_asdif = surf_lsm_v(l)%asdif
2745                ENDIF
2746                IF ( surf_usm_v(l)%ns > 0 )  THEN
2747                   surf_usm_v(l)%rrtm_aldir = surf_usm_v(l)%aldir
2748                   surf_usm_v(l)%rrtm_asdir = surf_usm_v(l)%asdir
2749                   surf_usm_v(l)%rrtm_aldif = surf_usm_v(l)%aldif
2750                   surf_usm_v(l)%rrtm_asdif = surf_usm_v(l)%asdif
2751                ENDIF
2752             ENDDO
2753
2754          ENDIF
2755
2756!
2757!--       Allocate 3d arrays of radiative fluxes and heating rates
2758          IF ( .NOT. ALLOCATED ( rad_sw_in ) )  THEN
2759             ALLOCATE ( rad_sw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2760             rad_sw_in = 0.0_wp
2761          ENDIF
2762
2763          IF ( .NOT. ALLOCATED ( rad_sw_in_av ) )  THEN
2764             ALLOCATE ( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2765          ENDIF
2766
2767          IF ( .NOT. ALLOCATED ( rad_sw_out ) )  THEN
2768             ALLOCATE ( rad_sw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2769             rad_sw_out = 0.0_wp
2770          ENDIF
2771
2772          IF ( .NOT. ALLOCATED ( rad_sw_out_av ) )  THEN
2773             ALLOCATE ( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2774          ENDIF
2775
2776          IF ( .NOT. ALLOCATED ( rad_sw_hr ) )  THEN
2777             ALLOCATE ( rad_sw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2778             rad_sw_hr = 0.0_wp
2779          ENDIF
2780
2781          IF ( .NOT. ALLOCATED ( rad_sw_hr_av ) )  THEN
2782             ALLOCATE ( rad_sw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2783             rad_sw_hr_av = 0.0_wp
2784          ENDIF
2785
2786          IF ( .NOT. ALLOCATED ( rad_sw_cs_hr ) )  THEN
2787             ALLOCATE ( rad_sw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2788             rad_sw_cs_hr = 0.0_wp
2789          ENDIF
2790
2791          IF ( .NOT. ALLOCATED ( rad_sw_cs_hr_av ) )  THEN
2792             ALLOCATE ( rad_sw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2793             rad_sw_cs_hr_av = 0.0_wp
2794          ENDIF
2795
2796          IF ( .NOT. ALLOCATED ( rad_lw_in ) )  THEN
2797             ALLOCATE ( rad_lw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2798             rad_lw_in = 0.0_wp
2799          ENDIF
2800
2801          IF ( .NOT. ALLOCATED ( rad_lw_in_av ) )  THEN
2802             ALLOCATE ( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2803          ENDIF
2804
2805          IF ( .NOT. ALLOCATED ( rad_lw_out ) )  THEN
2806             ALLOCATE ( rad_lw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2807            rad_lw_out = 0.0_wp
2808          ENDIF
2809
2810          IF ( .NOT. ALLOCATED ( rad_lw_out_av ) )  THEN
2811             ALLOCATE ( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2812          ENDIF
2813
2814          IF ( .NOT. ALLOCATED ( rad_lw_hr ) )  THEN
2815             ALLOCATE ( rad_lw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2816             rad_lw_hr = 0.0_wp
2817          ENDIF
2818
2819          IF ( .NOT. ALLOCATED ( rad_lw_hr_av ) )  THEN
2820             ALLOCATE ( rad_lw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2821             rad_lw_hr_av = 0.0_wp
2822          ENDIF
2823
2824          IF ( .NOT. ALLOCATED ( rad_lw_cs_hr ) )  THEN
2825             ALLOCATE ( rad_lw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2826             rad_lw_cs_hr = 0.0_wp
2827          ENDIF
2828
2829          IF ( .NOT. ALLOCATED ( rad_lw_cs_hr_av ) )  THEN
2830             ALLOCATE ( rad_lw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2831             rad_lw_cs_hr_av = 0.0_wp
2832          ENDIF
2833
2834          ALLOCATE ( rad_sw_cs_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2835          ALLOCATE ( rad_sw_cs_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2836          rad_sw_cs_in  = 0.0_wp
2837          rad_sw_cs_out = 0.0_wp
2838
2839          ALLOCATE ( rad_lw_cs_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2840          ALLOCATE ( rad_lw_cs_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2841          rad_lw_cs_in  = 0.0_wp
2842          rad_lw_cs_out = 0.0_wp
2843
2844!
2845!--       Allocate 1-element array for surface temperature
2846!--       (RRTMG anticipates an array as passed argument).
2847          ALLOCATE ( rrtm_tsfc(1) )
2848!
2849!--       Allocate surface emissivity.
2850!--       Values will be given directly before calling rrtm_lw.
2851          ALLOCATE ( rrtm_emis(0:0,1:nbndlw+1) )
2852
2853!
2854!--       Initialize RRTMG, before check if files are existent
2855          INQUIRE( FILE='rrtmg_lw.nc', EXIST=lw_exists )
2856          IF ( .NOT. lw_exists )  THEN
2857             message_string = 'Input file rrtmg_lw.nc' //                &
2858                            '&for rrtmg missing. ' // &
2859                            '&Please provide <jobname>_lsw file in the INPUT directory.'
2860             CALL message( 'radiation_init', 'PA0583', 1, 2, 0, 6, 0 )
2861          ENDIF         
2862          INQUIRE( FILE='rrtmg_sw.nc', EXIST=sw_exists )
2863          IF ( .NOT. sw_exists )  THEN
2864             message_string = 'Input file rrtmg_sw.nc' //                &
2865                            '&for rrtmg missing. ' // &
2866                            '&Please provide <jobname>_rsw file in the INPUT directory.'
2867             CALL message( 'radiation_init', 'PA0584', 1, 2, 0, 6, 0 )
2868          ENDIF         
2869         
2870          IF ( lw_radiation )  CALL rrtmg_lw_ini ( c_p )
2871          IF ( sw_radiation )  CALL rrtmg_sw_ini ( c_p )
2872         
2873!
2874!--       Set input files for RRTMG
2875          INQUIRE(FILE="RAD_SND_DATA", EXIST=snd_exists) 
2876          IF ( .NOT. snd_exists )  THEN
2877             rrtm_input_file = "rrtmg_lw.nc"
2878          ENDIF
2879
2880!
2881!--       Read vertical layers for RRTMG from sounding data
2882!--       The routine provides nzt_rad, hyp_snd(1:nzt_rad),
2883!--       t_snd(nzt+2:nzt_rad), rrtm_play(1:nzt_rad), rrtm_plev(1_nzt_rad+1),
2884!--       rrtm_tlay(nzt+2:nzt_rad), rrtm_tlev(nzt+2:nzt_rad+1)
2885          CALL read_sounding_data
2886
2887!
2888!--       Read trace gas profiles from file. This routine provides
2889!--       the rrtm_ arrays (1:nzt_rad+1)
2890          CALL read_trace_gas_data
2891#endif
2892       ENDIF
2893
2894!
2895!--    Perform user actions if required
2896       CALL user_init_radiation
2897
2898!
2899!--    Calculate radiative fluxes at model start
2900       SELECT CASE ( TRIM( radiation_scheme ) )
2901
2902          CASE ( 'rrtmg' )
2903             CALL radiation_rrtmg
2904
2905          CASE ( 'clear-sky' )
2906             CALL radiation_clearsky
2907
2908          CASE ( 'constant' )
2909             CALL radiation_constant
2910
2911          CASE DEFAULT
2912
2913       END SELECT
2914
2915! readjust date and time to its initial value
2916       CALL init_date_and_time
2917
2918!
2919!--    Find all discretized apparent solar positions for radiation interaction.
2920       IF ( radiation_interactions )  CALL radiation_presimulate_solar_pos
2921
2922!
2923!--    If required, read or calculate and write out the SVF
2924       IF ( radiation_interactions .AND. read_svf)  THEN
2925!
2926!--       Read sky-view factors and further required data from file
2927          CALL radiation_read_svf()
2928
2929       ELSEIF ( radiation_interactions .AND. .NOT. read_svf)  THEN
2930!
2931!--       calculate SFV and CSF
2932          CALL radiation_calc_svf()
2933       ENDIF
2934
2935       IF ( radiation_interactions .AND. write_svf)  THEN
2936!
2937!--       Write svf, csf svfsurf and csfsurf data to file
2938          CALL radiation_write_svf()
2939       ENDIF
2940
2941!
2942!--    Adjust radiative fluxes. In case of urban and land surfaces, also
2943!--    call an initial interaction.
2944       IF ( radiation_interactions )  THEN
2945          CALL radiation_interaction
2946       ENDIF
2947
2948       IF ( debug_output )  CALL debug_message( 'radiation_init', 'end' )
2949
2950       RETURN !todo: remove, I don't see what we need this for here
2951
2952    END SUBROUTINE radiation_init
2953
2954
2955!------------------------------------------------------------------------------!
2956! Description:
2957! ------------
2958!> A simple clear sky radiation model
2959!------------------------------------------------------------------------------!
2960    SUBROUTINE radiation_clearsky
2961
2962
2963       IMPLICIT NONE
2964
2965       INTEGER(iwp) ::  l         !< running index for surface orientation
2966       REAL(wp)     ::  pt1       !< potential temperature at first grid level or mean value at urban layer top
2967       REAL(wp)     ::  pt1_l     !< potential temperature at first grid level or mean value at urban layer top at local subdomain
2968       REAL(wp)     ::  ql1       !< liquid water mixing ratio at first grid level or mean value at urban layer top
2969       REAL(wp)     ::  ql1_l     !< liquid water mixing ratio at first grid level or mean value at urban layer top at local subdomain
2970
2971       TYPE(surf_type), POINTER ::  surf !< pointer on respective surface type, used to generalize routine   
2972
2973!
2974!--    Calculate current zenith angle
2975       CALL calc_zenith
2976
2977!
2978!--    Calculate sky transmissivity
2979       sky_trans = 0.6_wp + 0.2_wp * cos_zenith
2980
2981!
2982!--    Calculate value of the Exner function at model surface
2983!
2984!--    In case averaged radiation is used, calculate mean temperature and
2985!--    liquid water mixing ratio at the urban-layer top.
2986       IF ( average_radiation ) THEN
2987          pt1   = 0.0_wp
2988          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1   = 0.0_wp
2989
2990          pt1_l = SUM( pt(nz_urban_t,nys:nyn,nxl:nxr) )
2991          IF ( bulk_cloud_model  .OR.  cloud_droplets  )  ql1_l = SUM( ql(nz_urban_t,nys:nyn,nxl:nxr) )
2992
2993#if defined( __parallel )     
2994          IF ( collective_wait )  CALL MPI_BARRIER( comm2d, ierr )
2995          CALL MPI_ALLREDUCE( pt1_l, pt1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
2996          IF ( ierr /= 0 ) THEN
2997              WRITE(9,*) 'Error MPI_AllReduce1:', ierr, pt1_l, pt1
2998              FLUSH(9)
2999          ENDIF
3000
3001          IF ( bulk_cloud_model  .OR.  cloud_droplets ) THEN
3002              CALL MPI_ALLREDUCE( ql1_l, ql1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
3003              IF ( ierr /= 0 ) THEN
3004                  WRITE(9,*) 'Error MPI_AllReduce2:', ierr, ql1_l, ql1
3005                  FLUSH(9)
3006              ENDIF
3007          ENDIF
3008#else
3009          pt1 = pt1_l 
3010          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1 = ql1_l
3011#endif
3012
3013          IF ( bulk_cloud_model  .OR.  cloud_droplets  )  pt1 = pt1 + lv_d_cp / exner(nz_urban_t) * ql1
3014!
3015!--       Finally, divide by number of grid points
3016          pt1 = pt1 / REAL( ( nx + 1 ) * ( ny + 1 ), KIND=wp )
3017       ENDIF
3018!
3019!--    Call clear-sky calculation for each surface orientation.
3020!--    First, horizontal surfaces
3021       surf => surf_lsm_h
3022       CALL radiation_clearsky_surf
3023       surf => surf_usm_h
3024       CALL radiation_clearsky_surf
3025!
3026!--    Vertical surfaces
3027       DO  l = 0, 3
3028          surf => surf_lsm_v(l)
3029          CALL radiation_clearsky_surf
3030          surf => surf_usm_v(l)
3031          CALL radiation_clearsky_surf
3032       ENDDO
3033
3034       CONTAINS
3035
3036          SUBROUTINE radiation_clearsky_surf
3037
3038             IMPLICIT NONE
3039
3040             INTEGER(iwp) ::  i         !< index x-direction
3041             INTEGER(iwp) ::  j         !< index y-direction
3042             INTEGER(iwp) ::  k         !< index z-direction
3043             INTEGER(iwp) ::  m         !< running index for surface elements
3044
3045             IF ( surf%ns < 1 )  RETURN
3046
3047!
3048!--          Calculate radiation fluxes and net radiation (rad_net) assuming
3049!--          homogeneous urban radiation conditions.
3050             IF ( average_radiation ) THEN       
3051
3052                k = nz_urban_t
3053
3054                surf%rad_sw_in  = solar_constant * sky_trans * cos_zenith
3055                surf%rad_sw_out = albedo_urb * surf%rad_sw_in
3056               
3057                surf%rad_lw_in  = emissivity_atm_clsky * sigma_sb * (pt1 * exner(k+1))**4
3058
3059                surf%rad_lw_out = emissivity_urb * sigma_sb * (t_rad_urb)**4   &
3060                                    + (1.0_wp - emissivity_urb) * surf%rad_lw_in
3061
3062                surf%rad_net = surf%rad_sw_in - surf%rad_sw_out                &
3063                             + surf%rad_lw_in - surf%rad_lw_out
3064
3065                surf%rad_lw_out_change_0 = 4.0_wp * emissivity_urb * sigma_sb  &
3066                                           * (t_rad_urb)**3
3067
3068!
3069!--          Calculate radiation fluxes and net radiation (rad_net) for each surface
3070!--          element.
3071             ELSE
3072
3073                DO  m = 1, surf%ns
3074                   i = surf%i(m)
3075                   j = surf%j(m)
3076                   k = surf%k(m)
3077
3078                   surf%rad_sw_in(m) = solar_constant * sky_trans * cos_zenith
3079
3080!
3081!--                Weighted average according to surface fraction.
3082!--                ATTENTION: when radiation interactions are switched on the
3083!--                calculated fluxes below are not actually used as they are
3084!--                overwritten in radiation_interaction.
3085                   surf%rad_sw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
3086                                          surf%albedo(ind_veg_wall,m)          &
3087                                        + surf%frac(ind_pav_green,m) *         &
3088                                          surf%albedo(ind_pav_green,m)         &
3089                                        + surf%frac(ind_wat_win,m)   *         &
3090                                          surf%albedo(ind_wat_win,m) )         &
3091                                        * surf%rad_sw_in(m)
3092
3093                   surf%rad_lw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
3094                                          surf%emissivity(ind_veg_wall,m)      &
3095                                        + surf%frac(ind_pav_green,m) *         &
3096                                          surf%emissivity(ind_pav_green,m)     &
3097                                        + surf%frac(ind_wat_win,m)   *         &
3098                                          surf%emissivity(ind_wat_win,m)       &
3099                                        )                                      &
3100                                        * sigma_sb                             &
3101                                        * ( surf%pt_surface(m) * exner(nzb) )**4
3102
3103                   surf%rad_lw_out_change_0(m) =                               &
3104                                      ( surf%frac(ind_veg_wall,m)  *           &
3105                                        surf%emissivity(ind_veg_wall,m)        &
3106                                      + surf%frac(ind_pav_green,m) *           &
3107                                        surf%emissivity(ind_pav_green,m)       &
3108                                      + surf%frac(ind_wat_win,m)   *           &
3109                                        surf%emissivity(ind_wat_win,m)         &
3110                                      ) * 4.0_wp * sigma_sb                    &
3111                                      * ( surf%pt_surface(m) * exner(nzb) )** 3
3112
3113
3114                   IF ( bulk_cloud_model  .OR.  cloud_droplets  )  THEN
3115                      pt1 = pt(k,j,i) + lv_d_cp / exner(k) * ql(k,j,i)
3116                      surf%rad_lw_in(m)  = emissivity_atm_clsky * sigma_sb * (pt1 * exner(k))**4
3117                   ELSE
3118                      surf%rad_lw_in(m)  = emissivity_atm_clsky * sigma_sb * (pt(k,j,i) * exner(k))**4
3119                   ENDIF
3120
3121                   surf%rad_net(m) = surf%rad_sw_in(m) - surf%rad_sw_out(m)    &
3122                                   + surf%rad_lw_in(m) - surf%rad_lw_out(m)
3123
3124                ENDDO
3125
3126             ENDIF
3127
3128!
3129!--          Fill out values in radiation arrays
3130             DO  m = 1, surf%ns
3131                i = surf%i(m)
3132                j = surf%j(m)
3133                rad_sw_in(0,j,i) = surf%rad_sw_in(m)
3134                rad_sw_out(0,j,i) = surf%rad_sw_out(m)
3135                rad_lw_in(0,j,i) = surf%rad_lw_in(m)
3136                rad_lw_out(0,j,i) = surf%rad_lw_out(m)
3137             ENDDO
3138 
3139          END SUBROUTINE radiation_clearsky_surf
3140
3141    END SUBROUTINE radiation_clearsky
3142
3143
3144!------------------------------------------------------------------------------!
3145! Description:
3146! ------------
3147!> This scheme keeps the prescribed net radiation constant during the run
3148!------------------------------------------------------------------------------!
3149    SUBROUTINE radiation_constant
3150
3151
3152       IMPLICIT NONE
3153
3154       INTEGER(iwp) ::  l         !< running index for surface orientation
3155
3156       REAL(wp)     ::  pt1       !< potential temperature at first grid level or mean value at urban layer top
3157       REAL(wp)     ::  pt1_l     !< potential temperature at first grid level or mean value at urban layer top at local subdomain
3158       REAL(wp)     ::  ql1       !< liquid water mixing ratio at first grid level or mean value at urban layer top
3159       REAL(wp)     ::  ql1_l     !< liquid water mixing ratio at first grid level or mean value at urban layer top at local subdomain
3160
3161       TYPE(surf_type), POINTER ::  surf !< pointer on respective surface type, used to generalize routine
3162
3163!
3164!--    In case averaged radiation is used, calculate mean temperature and
3165!--    liquid water mixing ratio at the urban-layer top.
3166       IF ( average_radiation ) THEN   
3167          pt1   = 0.0_wp
3168          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1   = 0.0_wp
3169
3170          pt1_l = SUM( pt(nz_urban_t,nys:nyn,nxl:nxr) )
3171          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1_l = SUM( ql(nz_urban_t,nys:nyn,nxl:nxr) )
3172
3173#if defined( __parallel )     
3174          IF ( collective_wait )  CALL MPI_BARRIER( comm2d, ierr )
3175          CALL MPI_ALLREDUCE( pt1_l, pt1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
3176          IF ( ierr /= 0 ) THEN
3177              WRITE(9,*) 'Error MPI_AllReduce3:', ierr, pt1_l, pt1
3178              FLUSH(9)
3179          ENDIF
3180          IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
3181             CALL MPI_ALLREDUCE( ql1_l, ql1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
3182             IF ( ierr /= 0 ) THEN
3183                 WRITE(9,*) 'Error MPI_AllReduce4:', ierr, ql1_l, ql1
3184                 FLUSH(9)
3185             ENDIF
3186          ENDIF
3187#else
3188          pt1 = pt1_l
3189          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1 = ql1_l
3190#endif
3191          IF ( bulk_cloud_model  .OR.  cloud_droplets )  pt1 = pt1 + lv_d_cp / exner(nz_urban_t+1) * ql1
3192!
3193!--       Finally, divide by number of grid points
3194          pt1 = pt1 / REAL( ( nx + 1 ) * ( ny + 1 ), KIND=wp )
3195       ENDIF
3196
3197!
3198!--    First, horizontal surfaces
3199       surf => surf_lsm_h
3200       CALL radiation_constant_surf
3201       surf => surf_usm_h
3202       CALL radiation_constant_surf
3203!
3204!--    Vertical surfaces
3205       DO  l = 0, 3
3206          surf => surf_lsm_v(l)
3207          CALL radiation_constant_surf
3208          surf => surf_usm_v(l)
3209          CALL radiation_constant_surf
3210       ENDDO
3211
3212       CONTAINS
3213
3214          SUBROUTINE radiation_constant_surf
3215
3216             IMPLICIT NONE
3217
3218             INTEGER(iwp) ::  i         !< index x-direction
3219             INTEGER(iwp) ::  ioff      !< offset between surface element and adjacent grid point along x
3220             INTEGER(iwp) ::  j         !< index y-direction
3221             INTEGER(iwp) ::  joff      !< offset between surface element and adjacent grid point along y
3222             INTEGER(iwp) ::  k         !< index z-direction
3223             INTEGER(iwp) ::  koff      !< offset between surface element and adjacent grid point along z
3224             INTEGER(iwp) ::  m         !< running index for surface elements
3225
3226             IF ( surf%ns < 1 )  RETURN
3227
3228!--          Calculate homogenoeus urban radiation fluxes
3229             IF ( average_radiation ) THEN
3230
3231                surf%rad_net = net_radiation
3232
3233                surf%rad_lw_in  = emissivity_atm_clsky * sigma_sb * (pt1 * exner(nz_urban_t+1))**4
3234
3235                surf%rad_lw_out = emissivity_urb * sigma_sb * (t_rad_urb)**4   &
3236                                    + ( 1.0_wp - emissivity_urb )             & ! shouldn't be this a bulk value -- emissivity_urb?
3237                                    * surf%rad_lw_in
3238
3239                surf%rad_lw_out_change_0 = 4.0_wp * emissivity_urb * sigma_sb  &
3240                                           * t_rad_urb**3
3241
3242                surf%rad_sw_in = ( surf%rad_net - surf%rad_lw_in               &
3243                                     + surf%rad_lw_out )                       &
3244                                     / ( 1.0_wp - albedo_urb )
3245
3246                surf%rad_sw_out =  albedo_urb * surf%rad_sw_in
3247
3248!
3249!--          Calculate radiation fluxes for each surface element
3250             ELSE
3251!
3252!--             Determine index offset between surface element and adjacent
3253!--             atmospheric grid point
3254                ioff = surf%ioff
3255                joff = surf%joff
3256                koff = surf%koff
3257
3258!
3259!--             Prescribe net radiation and estimate the remaining radiative fluxes
3260                DO  m = 1, surf%ns
3261                   i = surf%i(m)
3262                   j = surf%j(m)
3263                   k = surf%k(m)
3264
3265                   surf%rad_net(m) = net_radiation
3266
3267                   IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
3268                      pt1 = pt(k,j,i) + lv_d_cp / exner(k) * ql(k,j,i)
3269                      surf%rad_lw_in(m)  = emissivity_atm_clsky * sigma_sb * (pt1 * exner(k))**4
3270                   ELSE
3271                      surf%rad_lw_in(m)  = emissivity_atm_clsky * sigma_sb *                 &
3272                                             ( pt(k,j,i) * exner(k) )**4
3273                   ENDIF
3274
3275!
3276!--                Weighted average according to surface fraction.
3277                   surf%rad_lw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
3278                                          surf%emissivity(ind_veg_wall,m)      &
3279                                        + surf%frac(ind_pav_green,m) *         &
3280                                          surf%emissivity(ind_pav_green,m)     &
3281                                        + surf%frac(ind_wat_win,m)   *         &
3282                                          surf%emissivity(ind_wat_win,m)       &
3283                                        )                                      &
3284                                      * sigma_sb                               &
3285                                      * ( surf%pt_surface(m) * exner(nzb) )**4
3286
3287                   surf%rad_sw_in(m) = ( surf%rad_net(m) - surf%rad_lw_in(m)   &
3288                                       + surf%rad_lw_out(m) )                  &
3289                                       / ( 1.0_wp -                            &
3290                                          ( surf%frac(ind_veg_wall,m)  *       &
3291                                            surf%albedo(ind_veg_wall,m)        &
3292                                         +  surf%frac(ind_pav_green,m) *       &
3293                                            surf%albedo(ind_pav_green,m)       &
3294                                         +  surf%frac(ind_wat_win,m)   *       &
3295                                            surf%albedo(ind_wat_win,m) )       &
3296                                         )
3297
3298                   surf%rad_sw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
3299                                          surf%albedo(ind_veg_wall,m)          &
3300                                        + surf%frac(ind_pav_green,m) *         &
3301                                          surf%albedo(ind_pav_green,m)         &
3302                                        + surf%frac(ind_wat_win,m)   *         &
3303                                          surf%albedo(ind_wat_win,m) )         &
3304                                      * surf%rad_sw_in(m)
3305
3306                ENDDO
3307
3308             ENDIF
3309
3310!
3311!--          Fill out values in radiation arrays
3312             DO  m = 1, surf%ns
3313                i = surf%i(m)
3314                j = surf%j(m)
3315                rad_sw_in(0,j,i) = surf%rad_sw_in(m)
3316                rad_sw_out(0,j,i) = surf%rad_sw_out(m)
3317                rad_lw_in(0,j,i) = surf%rad_lw_in(m)
3318                rad_lw_out(0,j,i) = surf%rad_lw_out(m)
3319             ENDDO
3320
3321          END SUBROUTINE radiation_constant_surf
3322         
3323
3324    END SUBROUTINE radiation_constant
3325
3326!------------------------------------------------------------------------------!
3327! Description:
3328! ------------
3329!> Header output for radiation model
3330!------------------------------------------------------------------------------!
3331    SUBROUTINE radiation_header ( io )
3332
3333
3334       IMPLICIT NONE
3335 
3336       INTEGER(iwp), INTENT(IN) ::  io            !< Unit of the output file
3337   
3338
3339       
3340!
3341!--    Write radiation model header
3342       WRITE( io, 3 )
3343
3344       IF ( radiation_scheme == "constant" )  THEN
3345          WRITE( io, 4 ) net_radiation
3346       ELSEIF ( radiation_scheme == "clear-sky" )  THEN
3347          WRITE( io, 5 )
3348       ELSEIF ( radiation_scheme == "rrtmg" )  THEN
3349          WRITE( io, 6 )
3350          IF ( .NOT. lw_radiation )  WRITE( io, 10 )
3351          IF ( .NOT. sw_radiation )  WRITE( io, 11 )
3352       ENDIF
3353
3354       IF ( albedo_type_f%from_file  .OR.  vegetation_type_f%from_file  .OR.   &
3355            pavement_type_f%from_file  .OR.  water_type_f%from_file  .OR.      &
3356            building_type_f%from_file )  THEN
3357             WRITE( io, 13 )
3358       ELSE 
3359          IF ( albedo_type == 0 )  THEN
3360             WRITE( io, 7 ) albedo
3361          ELSE
3362             WRITE( io, 8 ) TRIM( albedo_type_name(albedo_type) )
3363          ENDIF
3364       ENDIF
3365       IF ( constant_albedo )  THEN
3366          WRITE( io, 9 )
3367       ENDIF
3368       
3369       WRITE( io, 12 ) dt_radiation
3370 
3371
3372 3 FORMAT (//' Radiation model information:'/                                  &
3373              ' ----------------------------'/)
3374 4 FORMAT ('    --> Using constant net radiation: net_radiation = ', F6.2,     &
3375           // 'W/m**2')
3376 5 FORMAT ('    --> Simple radiation scheme for clear sky is used (no clouds,',&
3377                   ' default)')
3378 6 FORMAT ('    --> RRTMG scheme is used')
3379 7 FORMAT (/'    User-specific surface albedo: albedo =', F6.3)
3380 8 FORMAT (/'    Albedo is set for land surface type: ', A)
3381 9 FORMAT (/'    --> Albedo is fixed during the run')
338210 FORMAT (/'    --> Longwave radiation is disabled')
338311 FORMAT (/'    --> Shortwave radiation is disabled.')
338412 FORMAT  ('    Timestep: dt_radiation = ', F6.2, '  s')
338513 FORMAT (/'    Albedo is set individually for each xy-location, according ', &
3386                 'to given surface type.')
3387
3388
3389    END SUBROUTINE radiation_header
3390   
3391
3392!------------------------------------------------------------------------------!
3393! Description:
3394! ------------
3395!> Parin for &radiation_parameters for radiation model
3396!------------------------------------------------------------------------------!
3397    SUBROUTINE radiation_parin
3398
3399
3400       IMPLICIT NONE
3401
3402       CHARACTER (LEN=80) ::  line  !< dummy string that contains the current line of the parameter file
3403       
3404       NAMELIST /radiation_par/   albedo, albedo_lw_dif, albedo_lw_dir,         &
3405                                  albedo_sw_dif, albedo_sw_dir, albedo_type,    &
3406                                  constant_albedo, dt_radiation, emissivity,    &
3407                                  lw_radiation, max_raytracing_dist,            &
3408                                  min_irrf_value, mrt_geom_human,               &
3409                                  mrt_include_sw, mrt_nlevels,                  &
3410                                  mrt_skip_roof, net_radiation, nrefsteps,      &
3411                                  plant_lw_interact, rad_angular_discretization,&
3412                                  radiation_interactions_on, radiation_scheme,  &
3413                                  raytrace_discrete_azims,                      &
3414                                  raytrace_discrete_elevs, raytrace_mpi_rma,    &
3415                                  skip_time_do_radiation, surface_reflections,  &
3416                                  svfnorm_report_thresh, sw_radiation,          &
3417                                  unscheduled_radiation_calls
3418
3419   
3420       NAMELIST /radiation_parameters/ albedo, albedo_lw_dif, albedo_lw_dir,    &
3421                                  albedo_sw_dif, albedo_sw_dir, albedo_type,    &
3422                                  constant_albedo, dt_radiation, emissivity,    &
3423                                  lw_radiation, max_raytracing_dist,            &
3424                                  min_irrf_value, mrt_geom_human,               &
3425                                  mrt_include_sw, mrt_nlevels,                  &
3426                                  mrt_skip_roof, net_radiation, nrefsteps,      &
3427                                  plant_lw_interact, rad_angular_discretization,&
3428                                  radiation_interactions_on, radiation_scheme,  &
3429                                  raytrace_discrete_azims,                      &
3430                                  raytrace_discrete_elevs, raytrace_mpi_rma,    &
3431                                  skip_time_do_radiation, surface_reflections,  &
3432                                  svfnorm_report_thresh, sw_radiation,          &
3433                                  unscheduled_radiation_calls
3434   
3435       line = ' '
3436       
3437!
3438!--    Try to find radiation model namelist
3439       REWIND ( 11 )
3440       line = ' '
3441       DO WHILE ( INDEX( line, '&radiation_parameters' ) == 0 )
3442          READ ( 11, '(A)', END=12 )  line
3443       ENDDO
3444       BACKSPACE ( 11 )
3445
3446!
3447!--    Read user-defined namelist
3448       READ ( 11, radiation_parameters, ERR = 10 )
3449
3450!
3451!--    Set flag that indicates that the radiation model is switched on
3452       radiation = .TRUE.
3453
3454       GOTO 14
3455
3456 10    BACKSPACE( 11 )
3457       READ( 11 , '(A)') line
3458       CALL parin_fail_message( 'radiation_parameters', line )
3459!
3460!--    Try to find old namelist
3461 12    REWIND ( 11 )
3462       line = ' '
3463       DO WHILE ( INDEX( line, '&radiation_par' ) == 0 )
3464          READ ( 11, '(A)', END=14 )  line
3465       ENDDO
3466       BACKSPACE ( 11 )
3467
3468!
3469!--    Read user-defined namelist
3470       READ ( 11, radiation_par, ERR = 13, END = 14 )
3471
3472       message_string = 'namelist radiation_par is deprecated and will be ' // &
3473                     'removed in near future. Please use namelist ' //         &
3474                     'radiation_parameters instead'
3475       CALL message( 'radiation_parin', 'PA0487', 0, 1, 0, 6, 0 )
3476
3477!
3478!--    Set flag that indicates that the radiation model is switched on
3479       radiation = .TRUE.
3480
3481       IF ( .NOT.  radiation_interactions_on  .AND.  surface_reflections )  THEN
3482          message_string = 'surface_reflections is allowed only when '      // &
3483               'radiation_interactions_on is set to TRUE'
3484          CALL message( 'radiation_parin', 'PA0293',1, 2, 0, 6, 0 )
3485       ENDIF
3486
3487       GOTO 14
3488
3489 13    BACKSPACE( 11 )
3490       READ( 11 , '(A)') line
3491       CALL parin_fail_message( 'radiation_par', line )
3492
3493 14    CONTINUE
3494       
3495    END SUBROUTINE radiation_parin
3496
3497
3498!------------------------------------------------------------------------------!
3499! Description:
3500! ------------
3501!> Implementation of the RRTMG radiation_scheme
3502!------------------------------------------------------------------------------!
3503    SUBROUTINE radiation_rrtmg
3504
3505#if defined ( __rrtmg )
3506       USE indices,                                                            &
3507           ONLY:  nbgp
3508
3509       USE particle_attributes,                                                &
3510           ONLY:  grid_particles, number_of_particles, particles, prt_count
3511
3512       IMPLICIT NONE
3513
3514
3515       INTEGER(iwp) ::  i, j, k, l, m, n !< loop indices
3516       INTEGER(iwp) ::  k_topo_l   !< topography top index
3517       INTEGER(iwp) ::  k_topo     !< topography top index
3518
3519       REAL(wp)     ::  nc_rad, &    !< number concentration of cloud droplets
3520                        s_r2,   &    !< weighted sum over all droplets with r^2
3521                        s_r3         !< weighted sum over all droplets with r^3
3522
3523       REAL(wp), DIMENSION(0:nzt+1) :: pt_av, q_av, ql_av
3524       REAL(wp), DIMENSION(0:0)     :: zenith   !< to provide indexed array
3525!
3526!--    Just dummy arguments
3527       REAL(wp), DIMENSION(:,:,:), ALLOCATABLE :: rrtm_lw_taucld_dum,          &
3528                                                  rrtm_lw_tauaer_dum,          &
3529                                                  rrtm_sw_taucld_dum,          &
3530                                                  rrtm_sw_ssacld_dum,          &
3531                                                  rrtm_sw_asmcld_dum,          &
3532                                                  rrtm_sw_fsfcld_dum,          &
3533                                                  rrtm_sw_tauaer_dum,          &
3534                                                  rrtm_sw_ssaaer_dum,          &
3535                                                  rrtm_sw_asmaer_dum,          &
3536                                                  rrtm_sw_ecaer_dum
3537
3538!
3539!--    Calculate current (cosine of) zenith angle and whether the sun is up
3540       CALL calc_zenith     
3541       zenith(0) = cos_zenith
3542!
3543!--    Calculate surface albedo. In case average radiation is applied,
3544!--    this is not required.
3545#if defined( __netcdf )
3546       IF ( .NOT. constant_albedo )  THEN
3547!
3548!--       Horizontally aligned default, natural and urban surfaces
3549          CALL calc_albedo( surf_lsm_h    )
3550          CALL calc_albedo( surf_usm_h    )
3551!
3552!--       Vertically aligned default, natural and urban surfaces
3553          DO  l = 0, 3
3554             CALL calc_albedo( surf_lsm_v(l) )
3555             CALL calc_albedo( surf_usm_v(l) )
3556          ENDDO
3557       ENDIF
3558#endif
3559
3560!
3561!--    Prepare input data for RRTMG
3562
3563!
3564!--    In case of large scale forcing with surface data, calculate new pressure
3565!--    profile. nzt_rad might be modified by these calls and all required arrays
3566!--    will then be re-allocated
3567       IF ( large_scale_forcing  .AND.  lsf_surf )  THEN
3568          CALL read_sounding_data
3569          CALL read_trace_gas_data
3570       ENDIF
3571
3572
3573       IF ( average_radiation ) THEN
3574!
3575!--       Determine minimum topography top index.
3576          k_topo_l = MINVAL( get_topography_top_index( 's' ) )
3577#if defined( __parallel )
3578          CALL MPI_ALLREDUCE( k_topo_l, k_topo, 1, MPI_INTEGER, MPI_MIN, &
3579                              comm2d, ierr)
3580#else
3581          k_topo = k_topo_l
3582#endif
3583       
3584          rrtm_asdir(1)  = albedo_urb
3585          rrtm_asdif(1)  = albedo_urb
3586          rrtm_aldir(1)  = albedo_urb
3587          rrtm_aldif(1)  = albedo_urb
3588
3589          rrtm_emis = emissivity_urb
3590!
3591!--       Calculate mean pt profile.
3592          CALL calc_mean_profile( pt, 4 )
3593          pt_av = hom(:, 1, 4, 0)
3594         
3595          IF ( humidity )  THEN
3596             CALL calc_mean_profile( q, 41 )
3597             q_av  = hom(:, 1, 41, 0)
3598          ENDIF
3599!
3600!--       Prepare profiles of temperature and H2O volume mixing ratio
3601          rrtm_tlev(0,k_topo+1) = t_rad_urb
3602
3603          IF ( bulk_cloud_model )  THEN
3604
3605             CALL calc_mean_profile( ql, 54 )
3606             ! average ql is now in hom(:, 1, 54, 0)
3607             ql_av = hom(:, 1, 54, 0)
3608             
3609             DO k = nzb+1, nzt+1
3610                rrtm_tlay(0,k) = pt_av(k) * ( (hyp(k) ) / 100000._wp       &
3611                                 )**.286_wp + lv_d_cp * ql_av(k)
3612                rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * (q_av(k) - ql_av(k))
3613             ENDDO
3614          ELSE
3615             DO k = nzb+1, nzt+1
3616                rrtm_tlay(0,k) = pt_av(k) * ( (hyp(k) ) / 100000._wp       &
3617                                 )**.286_wp
3618             ENDDO
3619
3620             IF ( humidity )  THEN
3621                DO k = nzb+1, nzt+1
3622                   rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * q_av(k)
3623                ENDDO
3624             ELSE
3625                rrtm_h2ovmr(0,nzb+1:nzt+1) = 0.0_wp
3626             ENDIF
3627          ENDIF
3628
3629!
3630!--       Avoid temperature/humidity jumps at the top of the PALM domain by
3631!--       linear interpolation from nzt+2 to nzt+7. Jumps are induced by
3632!--       discrepancies between the values in the  domain and those above that
3633!--       are prescribed in RRTMG
3634          DO k = nzt+2, nzt+7
3635             rrtm_tlay(0,k) = rrtm_tlay(0,nzt+1)                            &
3636                           + ( rrtm_tlay(0,nzt+8) - rrtm_tlay(0,nzt+1) )    &
3637                           / ( rrtm_play(0,nzt+8) - rrtm_play(0,nzt+1) )    &
3638                           * ( rrtm_play(0,k) - rrtm_play(0,nzt+1) )
3639
3640             rrtm_h2ovmr(0,k) = rrtm_h2ovmr(0,nzt+1)                        &
3641                           + ( rrtm_h2ovmr(0,nzt+8) - rrtm_h2ovmr(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          ENDDO
3646
3647!--       Linear interpolate to zw grid. Loop reaches one level further up
3648!--       due to the staggered grid in RRTMG
3649          DO k = k_topo+2, nzt+8
3650             rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k) -        &
3651                                rrtm_tlay(0,k-1))                           &
3652                                / ( rrtm_play(0,k) - rrtm_play(0,k-1) )     &
3653                                * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
3654          ENDDO
3655!
3656!--       Calculate liquid water path and cloud fraction for each column.
3657!--       Note that LWP is required in g/m2 instead of kg/kg m.
3658          rrtm_cldfr  = 0.0_wp
3659          rrtm_reliq  = 0.0_wp
3660          rrtm_cliqwp = 0.0_wp
3661          rrtm_icld   = 0
3662
3663          IF ( bulk_cloud_model )  THEN
3664             DO k = nzb+1, nzt+1
3665                rrtm_cliqwp(0,k) =  ql_av(k) * 1000._wp *                   &
3666                                    (rrtm_plev(0,k) - rrtm_plev(0,k+1))     &
3667                                    * 100._wp / g 
3668
3669                IF ( rrtm_cliqwp(0,k) > 0._wp )  THEN
3670                   rrtm_cldfr(0,k) = 1._wp
3671                   IF ( rrtm_icld == 0 )  rrtm_icld = 1
3672
3673!
3674!--                Calculate cloud droplet effective radius
3675                   rrtm_reliq(0,k) = 1.0E6_wp * ( 3.0_wp * ql_av(k)         &
3676                                     * rho_surface                          &
3677                                     / ( 4.0_wp * pi * nc_const * rho_l )   &
3678                                     )**0.33333333333333_wp                 &
3679                                     * EXP( LOG( sigma_gc )**2 )
3680!
3681!--                Limit effective radius
3682                   IF ( rrtm_reliq(0,k) > 0.0_wp )  THEN
3683                      rrtm_reliq(0,k) = MAX(rrtm_reliq(0,k),2.5_wp)
3684                      rrtm_reliq(0,k) = MIN(rrtm_reliq(0,k),60.0_wp)
3685                   ENDIF
3686                ENDIF
3687             ENDDO
3688          ENDIF
3689
3690!
3691!--       Set surface temperature
3692          rrtm_tsfc = t_rad_urb
3693         
3694          IF ( lw_radiation )  THEN 
3695!
3696!--          Due to technical reasons, copy optical depth to dummy arguments
3697!--          which are allocated on the exact size as the rrtmg_lw is called.
3698!--          As one dimesion is allocated with zero size, compiler complains
3699!--          that rank of the array does not match that of the
3700!--          assumed-shaped arguments in the RRTMG library. In order to
3701!--          avoid this, write to dummy arguments and give pass the entire
3702!--          dummy array. Seems to be the only existing work-around. 
3703             ALLOCATE( rrtm_lw_taucld_dum(1:nbndlw+1,0:0,k_topo+1:nzt_rad+1) )
3704             ALLOCATE( rrtm_lw_tauaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndlw+1) )
3705
3706             rrtm_lw_taucld_dum =                                              &
3707                             rrtm_lw_taucld(1:nbndlw+1,0:0,k_topo+1:nzt_rad+1)
3708             rrtm_lw_tauaer_dum =                                              &
3709                             rrtm_lw_tauaer(0:0,k_topo+1:nzt_rad+1,1:nbndlw+1)
3710         
3711             CALL rrtmg_lw( 1,                                                 &                                       
3712                            nzt_rad-k_topo,                                    &
3713                            rrtm_icld,                                         &
3714                            rrtm_idrv,                                         &
3715                            rrtm_play(:,k_topo+1:),                   &
3716                            rrtm_plev(:,k_topo+1:),                   &
3717                            rrtm_tlay(:,k_topo+1:),                   &
3718                            rrtm_tlev(:,k_topo+1:),                   &
3719                            rrtm_tsfc,                                         &
3720                            rrtm_h2ovmr(:,k_topo+1:),                 &
3721                            rrtm_o3vmr(:,k_topo+1:),                  &
3722                            rrtm_co2vmr(:,k_topo+1:),                 &
3723                            rrtm_ch4vmr(:,k_topo+1:),                 &
3724                            rrtm_n2ovmr(:,k_topo+1:),                 &
3725                            rrtm_o2vmr(:,k_topo+1:),                  &
3726                            rrtm_cfc11vmr(:,k_topo+1:),               &
3727                            rrtm_cfc12vmr(:,k_topo+1:),               &
3728                            rrtm_cfc22vmr(:,k_topo+1:),               &
3729                            rrtm_ccl4vmr(:,k_topo+1:),                &
3730                            rrtm_emis,                                         &
3731                            rrtm_inflglw,                                      &
3732                            rrtm_iceflglw,                                     &
3733                            rrtm_liqflglw,                                     &
3734                            rrtm_cldfr(:,k_topo+1:),                  &
3735                            rrtm_lw_taucld_dum,                                &
3736                            rrtm_cicewp(:,k_topo+1:),                 &
3737                            rrtm_cliqwp(:,k_topo+1:),                 &
3738                            rrtm_reice(:,k_topo+1:),                  & 
3739                            rrtm_reliq(:,k_topo+1:),                  &
3740                            rrtm_lw_tauaer_dum,                                &
3741                            rrtm_lwuflx(:,k_topo:),                   &
3742                            rrtm_lwdflx(:,k_topo:),                   &
3743                            rrtm_lwhr(:,k_topo+1:),                   &
3744                            rrtm_lwuflxc(:,k_topo:),                  &
3745                            rrtm_lwdflxc(:,k_topo:),                  &
3746                            rrtm_lwhrc(:,k_topo+1:),                  &
3747                            rrtm_lwuflx_dt(:,k_topo:),                &
3748                            rrtm_lwuflxc_dt(:,k_topo:) )
3749                           
3750             DEALLOCATE ( rrtm_lw_taucld_dum )
3751             DEALLOCATE ( rrtm_lw_tauaer_dum )
3752!
3753!--          Save fluxes
3754             DO k = nzb, nzt+1
3755                rad_lw_in(k,:,:)  = rrtm_lwdflx(0,k)
3756                rad_lw_out(k,:,:) = rrtm_lwuflx(0,k)
3757             ENDDO
3758             rad_lw_in_diff(:,:) = rad_lw_in(k_topo,:,:)
3759!
3760!--          Save heating rates (convert from K/d to K/h).
3761!--          Further, even though an aggregated radiation is computed, map
3762!--          signle-column profiles on top of any topography, in order to
3763!--          obtain correct near surface radiation heating/cooling rates.
3764             DO  i = nxl, nxr
3765                DO  j = nys, nyn
3766                   k_topo_l = get_topography_top_index_ji( j, i, 's' )
3767                   DO k = k_topo_l+1, nzt+1
3768                      rad_lw_hr(k,j,i)     = rrtm_lwhr(0,k-k_topo_l)  * d_hours_day
3769                      rad_lw_cs_hr(k,j,i)  = rrtm_lwhrc(0,k-k_topo_l) * d_hours_day
3770                   ENDDO
3771                ENDDO
3772             ENDDO
3773
3774          ENDIF
3775
3776          IF ( sw_radiation .AND. sun_up )  THEN
3777!
3778!--          Due to technical reasons, copy optical depths and other
3779!--          to dummy arguments which are allocated on the exact size as the
3780!--          rrtmg_sw is called.
3781!--          As one dimesion is allocated with zero size, compiler complains
3782!--          that rank of the array does not match that of the
3783!--          assumed-shaped arguments in the RRTMG library. In order to
3784!--          avoid this, write to dummy arguments and give pass the entire
3785!--          dummy array. Seems to be the only existing work-around. 
3786             ALLOCATE( rrtm_sw_taucld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3787             ALLOCATE( rrtm_sw_ssacld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3788             ALLOCATE( rrtm_sw_asmcld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3789             ALLOCATE( rrtm_sw_fsfcld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3790             ALLOCATE( rrtm_sw_tauaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3791             ALLOCATE( rrtm_sw_ssaaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3792             ALLOCATE( rrtm_sw_asmaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3793             ALLOCATE( rrtm_sw_ecaer_dum(0:0,k_topo+1:nzt_rad+1,1:naerec+1)  )
3794     
3795             rrtm_sw_taucld_dum = rrtm_sw_taucld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3796             rrtm_sw_ssacld_dum = rrtm_sw_ssacld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3797             rrtm_sw_asmcld_dum = rrtm_sw_asmcld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3798             rrtm_sw_fsfcld_dum = rrtm_sw_fsfcld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3799             rrtm_sw_tauaer_dum = rrtm_sw_tauaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3800             rrtm_sw_ssaaer_dum = rrtm_sw_ssaaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3801             rrtm_sw_asmaer_dum = rrtm_sw_asmaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3802             rrtm_sw_ecaer_dum  = rrtm_sw_ecaer(0:0,k_topo+1:nzt_rad+1,1:naerec+1)
3803
3804             CALL rrtmg_sw( 1,                                                 &
3805                            nzt_rad-k_topo,                                    &
3806                            rrtm_icld,                                         &
3807                            rrtm_iaer,                                         &
3808                            rrtm_play(:,k_topo+1:nzt_rad+1),                   &
3809                            rrtm_plev(:,k_topo+1:nzt_rad+2),                   &
3810                            rrtm_tlay(:,k_topo+1:nzt_rad+1),                   &
3811                            rrtm_tlev(:,k_topo+1:nzt_rad+2),                   &
3812                            rrtm_tsfc,                                         &
3813                            rrtm_h2ovmr(:,k_topo+1:nzt_rad+1),                 &                               
3814                            rrtm_o3vmr(:,k_topo+1:nzt_rad+1),                  &       
3815                            rrtm_co2vmr(:,k_topo+1:nzt_rad+1),                 &
3816                            rrtm_ch4vmr(:,k_topo+1:nzt_rad+1),                 &
3817                            rrtm_n2ovmr(:,k_topo+1:nzt_rad+1),                 &
3818                            rrtm_o2vmr(:,k_topo+1:nzt_rad+1),                  &
3819                            rrtm_asdir,                                        & 
3820                            rrtm_asdif,                                        &
3821                            rrtm_aldir,                                        &
3822                            rrtm_aldif,                                        &
3823                            zenith,                                            &
3824                            0.0_wp,                                            &
3825                            day_of_year,                                       &
3826                            solar_constant,                                    &
3827                            rrtm_inflgsw,                                      &
3828                            rrtm_iceflgsw,                                     &
3829                            rrtm_liqflgsw,                                     &
3830                            rrtm_cldfr(:,k_topo+1:nzt_rad+1),                  &
3831                            rrtm_sw_taucld_dum,                                &
3832                            rrtm_sw_ssacld_dum,                                &
3833                            rrtm_sw_asmcld_dum,                                &
3834                            rrtm_sw_fsfcld_dum,                                &
3835                            rrtm_cicewp(:,k_topo+1:nzt_rad+1),                 &
3836                            rrtm_cliqwp(:,k_topo+1:nzt_rad+1),                 &
3837                            rrtm_reice(:,k_topo+1:nzt_rad+1),                  &
3838                            rrtm_reliq(:,k_topo+1:nzt_rad+1),                  &
3839                            rrtm_sw_tauaer_dum,                                &
3840                            rrtm_sw_ssaaer_dum,                                &
3841                            rrtm_sw_asmaer_dum,                                &
3842                            rrtm_sw_ecaer_dum,                                 &
3843                            rrtm_swuflx(:,k_topo:nzt_rad+1),                   & 
3844                            rrtm_swdflx(:,k_topo:nzt_rad+1),                   & 
3845                            rrtm_swhr(:,k_topo+1:nzt_rad+1),                   & 
3846                            rrtm_swuflxc(:,k_topo:nzt_rad+1),                  & 
3847                            rrtm_swdflxc(:,k_topo:nzt_rad+1),                  &
3848                            rrtm_swhrc(:,k_topo+1:nzt_rad+1),                  &
3849                            rrtm_dirdflux(:,k_topo:nzt_rad+1),                 &
3850                            rrtm_difdflux(:,k_topo:nzt_rad+1) )
3851                           
3852             DEALLOCATE( rrtm_sw_taucld_dum )
3853             DEALLOCATE( rrtm_sw_ssacld_dum )
3854             DEALLOCATE( rrtm_sw_asmcld_dum )
3855             DEALLOCATE( rrtm_sw_fsfcld_dum )
3856             DEALLOCATE( rrtm_sw_tauaer_dum )
3857             DEALLOCATE( rrtm_sw_ssaaer_dum )
3858             DEALLOCATE( rrtm_sw_asmaer_dum )
3859             DEALLOCATE( rrtm_sw_ecaer_dum )
3860 
3861!
3862!--          Save radiation fluxes for the entire depth of the model domain
3863             DO k = nzb, nzt+1
3864                rad_sw_in(k,:,:)  = rrtm_swdflx(0,k)
3865                rad_sw_out(k,:,:) = rrtm_swuflx(0,k)
3866             ENDDO
3867!--          Save direct and diffuse SW radiation at the surface (required by RTM)
3868             rad_sw_in_dir(:,:) = rrtm_dirdflux(0,k_topo)
3869             rad_sw_in_diff(:,:) = rrtm_difdflux(0,k_topo)
3870
3871!
3872!--          Save heating rates (convert from K/d to K/s)
3873             DO k = nzb+1, nzt+1
3874                rad_sw_hr(k,:,:)     = rrtm_swhr(0,k)  * d_hours_day
3875                rad_sw_cs_hr(k,:,:)  = rrtm_swhrc(0,k) * d_hours_day
3876             ENDDO
3877!
3878!--       Solar radiation is zero during night
3879          ELSE
3880             rad_sw_in  = 0.0_wp
3881             rad_sw_out = 0.0_wp
3882             rad_sw_in_dir(:,:) = 0.0_wp
3883             rad_sw_in_diff(:,:) = 0.0_wp
3884          ENDIF
3885!
3886!--    RRTMG is called for each (j,i) grid point separately, starting at the
3887!--    highest topography level. Here no RTM is used since average_radiation is false
3888       ELSE
3889!
3890!--       Loop over all grid points
3891          DO i = nxl, nxr
3892             DO j = nys, nyn
3893
3894!
3895!--             Prepare profiles of temperature and H2O volume mixing ratio
3896                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
3897                   rrtm_tlev(0,nzb+1) = surf_lsm_h%pt_surface(m) * exner(nzb)
3898                ENDDO
3899                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
3900                   rrtm_tlev(0,nzb+1) = surf_usm_h%pt_surface(m) * exner(nzb)
3901                ENDDO
3902
3903
3904                IF ( bulk_cloud_model )  THEN
3905                   DO k = nzb+1, nzt+1
3906                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)                    &
3907                                        + lv_d_cp * ql(k,j,i)
3908                      rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * (q(k,j,i) - ql(k,j,i))
3909                   ENDDO
3910                ELSEIF ( cloud_droplets )  THEN
3911                   DO k = nzb+1, nzt+1
3912                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)                     &
3913                                        + lv_d_cp * ql(k,j,i)
3914                      rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * q(k,j,i) 
3915                   ENDDO
3916                ELSE
3917                   DO k = nzb+1, nzt+1
3918                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)
3919                   ENDDO
3920
3921                   IF ( humidity )  THEN
3922                      DO k = nzb+1, nzt+1
3923                         rrtm_h2ovmr(0,k) =  mol_mass_air_d_wv * q(k,j,i)
3924                      ENDDO   
3925                   ELSE
3926                      rrtm_h2ovmr(0,nzb+1:nzt+1) = 0.0_wp
3927                   ENDIF
3928                ENDIF
3929
3930!
3931!--             Avoid temperature/humidity jumps at the top of the LES domain by
3932!--             linear interpolation from nzt+2 to nzt+7
3933                DO k = nzt+2, nzt+7
3934                   rrtm_tlay(0,k) = rrtm_tlay(0,nzt+1)                         &
3935                                 + ( rrtm_tlay(0,nzt+8) - rrtm_tlay(0,nzt+1) ) &
3936                                 / ( rrtm_play(0,nzt+8) - rrtm_play(0,nzt+1) ) &
3937                                 * ( rrtm_play(0,k)     - rrtm_play(0,nzt+1) )
3938
3939                   rrtm_h2ovmr(0,k) = rrtm_h2ovmr(0,nzt+1)                     &
3940                              + ( rrtm_h2ovmr(0,nzt+8) - rrtm_h2ovmr(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                ENDDO
3945
3946!--             Linear interpolate to zw grid
3947                DO k = nzb+2, nzt+8
3948                   rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k) -     &
3949                                      rrtm_tlay(0,k-1))                        &
3950                                      / ( rrtm_play(0,k) - rrtm_play(0,k-1) )  &
3951                                      * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
3952                ENDDO
3953
3954
3955!
3956!--             Calculate liquid water path and cloud fraction for each column.
3957!--             Note that LWP is required in g/m2 instead of kg/kg m.
3958                rrtm_cldfr  = 0.0_wp
3959                rrtm_reliq  = 0.0_wp
3960                rrtm_cliqwp = 0.0_wp
3961                rrtm_icld   = 0
3962
3963                IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
3964                   DO k = nzb+1, nzt+1
3965                      rrtm_cliqwp(0,k) =  ql(k,j,i) * 1000.0_wp *              &
3966                                          (rrtm_plev(0,k) - rrtm_plev(0,k+1))  &
3967                                          * 100.0_wp / g 
3968
3969                      IF ( rrtm_cliqwp(0,k) > 0.0_wp )  THEN
3970                         rrtm_cldfr(0,k) = 1.0_wp
3971                         IF ( rrtm_icld == 0 )  rrtm_icld = 1
3972
3973!
3974!--                      Calculate cloud droplet effective radius
3975                         IF ( bulk_cloud_model )  THEN
3976!
3977!--                         Calculete effective droplet radius. In case of using
3978!--                         cloud_scheme = 'morrison' and a non reasonable number
3979!--                         of cloud droplets the inital aerosol number 
3980!--                         concentration is considered.
3981                            IF ( microphysics_morrison )  THEN
3982                               IF ( nc(k,j,i) > 1.0E-20_wp )  THEN
3983                                  nc_rad = nc(k,j,i)
3984                               ELSE
3985                                  nc_rad = na_init
3986                               ENDIF
3987                            ELSE
3988                               nc_rad = nc_const
3989                            ENDIF 
3990
3991                            rrtm_reliq(0,k) = 1.0E6_wp * ( 3.0_wp * ql(k,j,i)     &
3992                                              * rho_surface                       &
3993                                              / ( 4.0_wp * pi * nc_rad * rho_l )  &
3994                                              )**0.33333333333333_wp              &
3995                                              * EXP( LOG( sigma_gc )**2 )
3996
3997                         ELSEIF ( cloud_droplets )  THEN
3998                            number_of_particles = prt_count(k,j,i)
3999
4000                            IF (number_of_particles <= 0)  CYCLE
4001                            particles => grid_particles(k,j,i)%particles(1:number_of_particles)
4002                            s_r2 = 0.0_wp
4003                            s_r3 = 0.0_wp
4004
4005                            DO  n = 1, number_of_particles
4006                               IF ( particles(n)%particle_mask )  THEN
4007                                  s_r2 = s_r2 + particles(n)%radius**2 *       &
4008                                         particles(n)%weight_factor
4009                                  s_r3 = s_r3 + particles(n)%radius**3 *       &
4010                                         particles(n)%weight_factor
4011                               ENDIF
4012                            ENDDO
4013
4014                            IF ( s_r2 > 0.0_wp )  rrtm_reliq(0,k) = s_r3 / s_r2
4015
4016                         ENDIF
4017
4018!
4019!--                      Limit effective radius
4020                         IF ( rrtm_reliq(0,k) > 0.0_wp )  THEN
4021                            rrtm_reliq(0,k) = MAX(rrtm_reliq(0,k),2.5_wp)
4022                            rrtm_reliq(0,k) = MIN(rrtm_reliq(0,k),60.0_wp)
4023                        ENDIF
4024                      ENDIF
4025                   ENDDO
4026                ENDIF
4027
4028!
4029!--             Write surface emissivity and surface temperature at current
4030!--             surface element on RRTMG-shaped array.
4031!--             Please note, as RRTMG is a single column model, surface attributes
4032!--             are only obtained from horizontally aligned surfaces (for
4033!--             simplicity). Taking surface attributes from horizontal and
4034!--             vertical walls would lead to multiple solutions. 
4035!--             Moreover, for natural- and urban-type surfaces, several surface
4036!--             classes can exist at a surface element next to each other.
4037!--             To obtain bulk parameters, apply a weighted average for these
4038!--             surfaces.
4039                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
4040                   rrtm_emis = surf_lsm_h%frac(ind_veg_wall,m)  *              &
4041                               surf_lsm_h%emissivity(ind_veg_wall,m)  +        &
4042                               surf_lsm_h%frac(ind_pav_green,m) *              &
4043                               surf_lsm_h%emissivity(ind_pav_green,m) +        & 
4044                               surf_lsm_h%frac(ind_wat_win,m)   *              &
4045                               surf_lsm_h%emissivity(ind_wat_win,m)
4046                   rrtm_tsfc = surf_lsm_h%pt_surface(m) * exner(nzb)
4047                ENDDO             
4048                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
4049                   rrtm_emis = surf_usm_h%frac(ind_veg_wall,m)  *              &
4050                               surf_usm_h%emissivity(ind_veg_wall,m)  +        &
4051                               surf_usm_h%frac(ind_pav_green,m) *              &
4052                               surf_usm_h%emissivity(ind_pav_green,m) +        & 
4053                               surf_usm_h%frac(ind_wat_win,m)   *              &
4054                               surf_usm_h%emissivity(ind_wat_win,m)
4055                   rrtm_tsfc = surf_usm_h%pt_surface(m) * exner(nzb)
4056                ENDDO
4057!
4058!--             Obtain topography top index (lower bound of RRTMG)
4059                k_topo = get_topography_top_index_ji( j, i, 's' )
4060
4061                IF ( lw_radiation )  THEN
4062!
4063!--                Due to technical reasons, copy optical depth to dummy arguments
4064!--                which are allocated on the exact size as the rrtmg_lw is called.
4065!--                As one dimesion is allocated with zero size, compiler complains
4066!--                that rank of the array does not match that of the
4067!--                assumed-shaped arguments in the RRTMG library. In order to
4068!--                avoid this, write to dummy arguments and give pass the entire
4069!--                dummy array. Seems to be the only existing work-around. 
4070                   ALLOCATE( rrtm_lw_taucld_dum(1:nbndlw+1,0:0,k_topo+1:nzt_rad+1) )
4071                   ALLOCATE( rrtm_lw_tauaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndlw+1) )
4072
4073                   rrtm_lw_taucld_dum =                                        &
4074                               rrtm_lw_taucld(1:nbndlw+1,0:0,k_topo+1:nzt_rad+1)
4075                   rrtm_lw_tauaer_dum =                                        &
4076                               rrtm_lw_tauaer(0:0,k_topo+1:nzt_rad+1,1:nbndlw+1)
4077
4078                   CALL rrtmg_lw( 1,                                           &                                       
4079                                  nzt_rad-k_topo,                              &
4080                                  rrtm_icld,                                   &
4081                                  rrtm_idrv,                                   &
4082                                  rrtm_play(:,k_topo+1:nzt_rad+1),             &
4083                                  rrtm_plev(:,k_topo+1:nzt_rad+2),             &
4084                                  rrtm_tlay(:,k_topo+1:nzt_rad+1),             &
4085                                  rrtm_tlev(:,k_topo+1:nzt_rad+2),             &
4086                                  rrtm_tsfc,                                   &
4087                                  rrtm_h2ovmr(:,k_topo+1:nzt_rad+1),           &
4088                                  rrtm_o3vmr(:,k_topo+1:nzt_rad+1),            &
4089                                  rrtm_co2vmr(:,k_topo+1:nzt_rad+1),           &
4090                                  rrtm_ch4vmr(:,k_topo+1:nzt_rad+1),           &
4091                                  rrtm_n2ovmr(:,k_topo+1:nzt_rad+1),           &
4092                                  rrtm_o2vmr(:,k_topo+1:nzt_rad+1),            &
4093                                  rrtm_cfc11vmr(:,k_topo+1:nzt_rad+1),         &
4094                                  rrtm_cfc12vmr(:,k_topo+1:nzt_rad+1),         &
4095                                  rrtm_cfc22vmr(:,k_topo+1:nzt_rad+1),         &
4096                                  rrtm_ccl4vmr(:,k_topo+1:nzt_rad+1),          &
4097                                  rrtm_emis,                                   &
4098                                  rrtm_inflglw,                                &
4099                                  rrtm_iceflglw,                               &
4100                                  rrtm_liqflglw,                               &
4101                                  rrtm_cldfr(:,k_topo+1:nzt_rad+1),            &
4102                                  rrtm_lw_taucld_dum,                          &
4103                                  rrtm_cicewp(:,k_topo+1:nzt_rad+1),           &
4104                                  rrtm_cliqwp(:,k_topo+1:nzt_rad+1),           &
4105                                  rrtm_reice(:,k_topo+1:nzt_rad+1),            & 
4106                                  rrtm_reliq(:,k_topo+1:nzt_rad+1),            &
4107                                  rrtm_lw_tauaer_dum,                          &
4108                                  rrtm_lwuflx(:,k_topo:nzt_rad+1),             &
4109                                  rrtm_lwdflx(:,k_topo:nzt_rad+1),             &
4110                                  rrtm_lwhr(:,k_topo+1:nzt_rad+1),             &
4111                                  rrtm_lwuflxc(:,k_topo:nzt_rad+1),            &
4112                                  rrtm_lwdflxc(:,k_topo:nzt_rad+1),            &
4113                                  rrtm_lwhrc(:,k_topo+1:nzt_rad+1),            &
4114                                  rrtm_lwuflx_dt(:,k_topo:nzt_rad+1),          &
4115                                  rrtm_lwuflxc_dt(:,k_topo:nzt_rad+1) )
4116
4117                   DEALLOCATE ( rrtm_lw_taucld_dum )
4118                   DEALLOCATE ( rrtm_lw_tauaer_dum )
4119!
4120!--                Save fluxes
4121                   DO k = k_topo, nzt+1
4122                      rad_lw_in(k,j,i)  = rrtm_lwdflx(0,k)
4123                      rad_lw_out(k,j,i) = rrtm_lwuflx(0,k)
4124                   ENDDO
4125
4126!
4127!--                Save heating rates (convert from K/d to K/h)
4128                   DO k = k_topo+1, nzt+1
4129                      rad_lw_hr(k,j,i)     = rrtm_lwhr(0,k-k_topo)  * d_hours_day
4130                      rad_lw_cs_hr(k,j,i)  = rrtm_lwhrc(0,k-k_topo) * d_hours_day
4131                   ENDDO
4132
4133!
4134!--                Save surface radiative fluxes and change in LW heating rate
4135!--                onto respective surface elements
4136!--                Horizontal surfaces
4137                   DO  m = surf_lsm_h%start_index(j,i),                        &
4138                           surf_lsm_h%end_index(j,i)
4139                      surf_lsm_h%rad_lw_in(m)           = rrtm_lwdflx(0,k_topo)
4140                      surf_lsm_h%rad_lw_out(m)          = rrtm_lwuflx(0,k_topo)
4141                      surf_lsm_h%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k_topo)
4142                   ENDDO             
4143                   DO  m = surf_usm_h%start_index(j,i),                        &
4144                           surf_usm_h%end_index(j,i)
4145                      surf_usm_h%rad_lw_in(m)           = rrtm_lwdflx(0,k_topo)
4146                      surf_usm_h%rad_lw_out(m)          = rrtm_lwuflx(0,k_topo)
4147                      surf_usm_h%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k_topo)
4148                   ENDDO 
4149!
4150!--                Vertical surfaces. Fluxes are obtain at vertical level of the
4151!--                respective surface element
4152                   DO  l = 0, 3
4153                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
4154                              surf_lsm_v(l)%end_index(j,i)
4155                         k                                    = surf_lsm_v(l)%k(m)
4156                         surf_lsm_v(l)%rad_lw_in(m)           = rrtm_lwdflx(0,k)
4157                         surf_lsm_v(l)%rad_lw_out(m)          = rrtm_lwuflx(0,k)
4158                         surf_lsm_v(l)%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k)
4159                      ENDDO             
4160                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
4161                              surf_usm_v(l)%end_index(j,i)
4162                         k                                    = surf_usm_v(l)%k(m)
4163                         surf_usm_v(l)%rad_lw_in(m)           = rrtm_lwdflx(0,k)
4164                         surf_usm_v(l)%rad_lw_out(m)          = rrtm_lwuflx(0,k)
4165                         surf_usm_v(l)%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k)
4166                      ENDDO 
4167                   ENDDO
4168
4169                ENDIF
4170
4171                IF ( sw_radiation .AND. sun_up )  THEN
4172!
4173!--                Get albedo for direct/diffusive long/shortwave radiation at
4174!--                current (y,x)-location from surface variables.
4175!--                Only obtain it from horizontal surfaces, as RRTMG is a single
4176!--                column model
4177!--                (Please note, only one loop will entered, controlled by
4178!--                start-end index.)
4179                   DO  m = surf_lsm_h%start_index(j,i),                        &
4180                           surf_lsm_h%end_index(j,i)
4181                      rrtm_asdir(1)  = SUM( surf_lsm_h%frac(:,m) *             &
4182                                            surf_lsm_h%rrtm_asdir(:,m) )
4183                      rrtm_asdif(1)  = SUM( surf_lsm_h%frac(:,m) *             &
4184                                            surf_lsm_h%rrtm_asdif(:,m) )
4185                      rrtm_aldir(1)  = SUM( surf_lsm_h%frac(:,m) *             &
4186                                            surf_lsm_h%rrtm_aldir(:,m) )
4187                      rrtm_aldif(1)  = SUM( surf_lsm_h%frac(:,m) *             &
4188                                            surf_lsm_h%rrtm_aldif(:,m) )
4189                   ENDDO             
4190                   DO  m = surf_usm_h%start_index(j,i),                        &
4191                           surf_usm_h%end_index(j,i)
4192                      rrtm_asdir(1)  = SUM( surf_usm_h%frac(:,m) *             &
4193                                            surf_usm_h%rrtm_asdir(:,m) )
4194                      rrtm_asdif(1)  = SUM( surf_usm_h%frac(:,m) *             &
4195                                            surf_usm_h%rrtm_asdif(:,m) )
4196                      rrtm_aldir(1)  = SUM( surf_usm_h%frac(:,m) *             &
4197                                            surf_usm_h%rrtm_aldir(:,m) )
4198                      rrtm_aldif(1)  = SUM( surf_usm_h%frac(:,m) *             &
4199                                            surf_usm_h%rrtm_aldif(:,m) )
4200                   ENDDO
4201!
4202!--                Due to technical reasons, copy optical depths and other
4203!--                to dummy arguments which are allocated on the exact size as the
4204!--                rrtmg_sw is called.
4205!--                As one dimesion is allocated with zero size, compiler complains
4206!--                that rank of the array does not match that of the
4207!--                assumed-shaped arguments in the RRTMG library. In order to
4208!--                avoid this, write to dummy arguments and give pass the entire
4209!--                dummy array. Seems to be the only existing work-around. 
4210                   ALLOCATE( rrtm_sw_taucld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
4211                   ALLOCATE( rrtm_sw_ssacld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
4212                   ALLOCATE( rrtm_sw_asmcld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
4213                   ALLOCATE( rrtm_sw_fsfcld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
4214                   ALLOCATE( rrtm_sw_tauaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
4215                   ALLOCATE( rrtm_sw_ssaaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
4216                   ALLOCATE( rrtm_sw_asmaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
4217                   ALLOCATE( rrtm_sw_ecaer_dum(0:0,k_topo+1:nzt_rad+1,1:naerec+1)  )
4218     
4219                   rrtm_sw_taucld_dum = rrtm_sw_taucld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
4220                   rrtm_sw_ssacld_dum = rrtm_sw_ssacld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
4221                   rrtm_sw_asmcld_dum = rrtm_sw_asmcld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
4222                   rrtm_sw_fsfcld_dum = rrtm_sw_fsfcld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
4223                   rrtm_sw_tauaer_dum = rrtm_sw_tauaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
4224                   rrtm_sw_ssaaer_dum = rrtm_sw_ssaaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
4225                   rrtm_sw_asmaer_dum = rrtm_sw_asmaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
4226                   rrtm_sw_ecaer_dum  = rrtm_sw_ecaer(0:0,k_topo+1:nzt_rad+1,1:naerec+1)
4227
4228                   CALL rrtmg_sw( 1,                                           &
4229                                  nzt_rad-k_topo,                              &
4230                                  rrtm_icld,                                   &
4231                                  rrtm_iaer,                                   &
4232                                  rrtm_play(:,k_topo+1:nzt_rad+1),             &
4233                                  rrtm_plev(:,k_topo+1:nzt_rad+2),             &
4234                                  rrtm_tlay(:,k_topo+1:nzt_rad+1),             &
4235                                  rrtm_tlev(:,k_topo+1:nzt_rad+2),             &
4236                                  rrtm_tsfc,                                   &
4237                                  rrtm_h2ovmr(:,k_topo+1:nzt_rad+1),           &                               
4238                                  rrtm_o3vmr(:,k_topo+1:nzt_rad+1),            &       
4239                                  rrtm_co2vmr(:,k_topo+1:nzt_rad+1),           &
4240                                  rrtm_ch4vmr(:,k_topo+1:nzt_rad+1),           &
4241                                  rrtm_n2ovmr(:,k_topo+1:nzt_rad+1),           &
4242                                  rrtm_o2vmr(:,k_topo+1:nzt_rad+1),            &
4243                                  rrtm_asdir,                                  & 
4244                                  rrtm_asdif,                                  &
4245                                  rrtm_aldir,                                  &
4246                                  rrtm_aldif,                                  &
4247                                  zenith,                                      &
4248                                  0.0_wp,                                      &
4249                                  day_of_year,                                 &
4250                                  solar_constant,                              &
4251                                  rrtm_inflgsw,                                &
4252                                  rrtm_iceflgsw,                               &
4253                                  rrtm_liqflgsw,                               &
4254                                  rrtm_cldfr(:,k_topo+1:nzt_rad+1),            &
4255                                  rrtm_sw_taucld_dum,                          &
4256                                  rrtm_sw_ssacld_dum,                          &
4257                                  rrtm_sw_asmcld_dum,                          &
4258                                  rrtm_sw_fsfcld_dum,                          &
4259                                  rrtm_cicewp(:,k_topo+1:nzt_rad+1),           &
4260                                  rrtm_cliqwp(:,k_topo+1:nzt_rad+1),           &
4261                                  rrtm_reice(:,k_topo+1:nzt_rad+1),            &
4262                                  rrtm_reliq(:,k_topo+1:nzt_rad+1),            &
4263                                  rrtm_sw_tauaer_dum,                          &
4264                                  rrtm_sw_ssaaer_dum,                          &
4265                                  rrtm_sw_asmaer_dum,                          &
4266                                  rrtm_sw_ecaer_dum,                           &
4267                                  rrtm_swuflx(:,k_topo:nzt_rad+1),             & 
4268                                  rrtm_swdflx(:,k_topo:nzt_rad+1),             & 
4269                                  rrtm_swhr(:,k_topo+1:nzt_rad+1),             & 
4270                                  rrtm_swuflxc(:,k_topo:nzt_rad+1),            & 
4271                                  rrtm_swdflxc(:,k_topo:nzt_rad+1),            &
4272                                  rrtm_swhrc(:,k_topo+1:nzt_rad+1),            &
4273                                  rrtm_dirdflux(:,k_topo:nzt_rad+1),           &
4274                                  rrtm_difdflux(:,k_topo:nzt_rad+1) )
4275
4276                   DEALLOCATE( rrtm_sw_taucld_dum )
4277                   DEALLOCATE( rrtm_sw_ssacld_dum )
4278                   DEALLOCATE( rrtm_sw_asmcld_dum )
4279                   DEALLOCATE( rrtm_sw_fsfcld_dum )
4280                   DEALLOCATE( rrtm_sw_tauaer_dum )
4281                   DEALLOCATE( rrtm_sw_ssaaer_dum )
4282                   DEALLOCATE( rrtm_sw_asmaer_dum )
4283                   DEALLOCATE( rrtm_sw_ecaer_dum )
4284!
4285!--                Save fluxes
4286                   DO k = nzb, nzt+1
4287                      rad_sw_in(k,j,i)  = rrtm_swdflx(0,k)
4288                      rad_sw_out(k,j,i) = rrtm_swuflx(0,k)
4289                   ENDDO
4290!
4291!--                Save heating rates (convert from K/d to K/s)
4292                   DO k = nzb+1, nzt+1
4293                      rad_sw_hr(k,j,i)     = rrtm_swhr(0,k)  * d_hours_day
4294                      rad_sw_cs_hr(k,j,i)  = rrtm_swhrc(0,k) * d_hours_day
4295                   ENDDO
4296
4297!
4298!--                Save surface radiative fluxes onto respective surface elements
4299!--                Horizontal surfaces
4300                   DO  m = surf_lsm_h%start_index(j,i),                        &
4301                           surf_lsm_h%end_index(j,i)
4302                      surf_lsm_h%rad_sw_in(m)     = rrtm_swdflx(0,k_topo)
4303                      surf_lsm_h%rad_sw_out(m)    = rrtm_swuflx(0,k_topo)
4304                   ENDDO             
4305                   DO  m = surf_usm_h%start_index(j,i),                        &
4306                           surf_usm_h%end_index(j,i)
4307                      surf_usm_h%rad_sw_in(m)     = rrtm_swdflx(0,k_topo)
4308                      surf_usm_h%rad_sw_out(m)    = rrtm_swuflx(0,k_topo)
4309                   ENDDO 
4310!
4311!--                Vertical surfaces. Fluxes are obtain at respective vertical
4312!--                level of the surface element
4313                   DO  l = 0, 3
4314                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
4315                              surf_lsm_v(l)%end_index(j,i)
4316                         k                           = surf_lsm_v(l)%k(m)
4317                         surf_lsm_v(l)%rad_sw_in(m)  = rrtm_swdflx(0,k)
4318                         surf_lsm_v(l)%rad_sw_out(m) = rrtm_swuflx(0,k)
4319                      ENDDO             
4320                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
4321                              surf_usm_v(l)%end_index(j,i)
4322                         k                           = surf_usm_v(l)%k(m)
4323                         surf_usm_v(l)%rad_sw_in(m)  = rrtm_swdflx(0,k)
4324                         surf_usm_v(l)%rad_sw_out(m) = rrtm_swuflx(0,k)
4325                      ENDDO 
4326                   ENDDO
4327!
4328!--             Solar radiation is zero during night
4329                ELSE
4330                   rad_sw_in  = 0.0_wp
4331                   rad_sw_out = 0.0_wp
4332!--             !!!!!!!! ATTENSION !!!!!!!!!!!!!!!
4333!--             Surface radiative fluxes should be also set to zero here                 
4334!--                Save surface radiative fluxes onto respective surface elements
4335!--                Horizontal surfaces
4336                   DO  m = surf_lsm_h%start_index(j,i),                        &
4337                           surf_lsm_h%end_index(j,i)
4338                      surf_lsm_h%rad_sw_in(m)     = 0.0_wp
4339                      surf_lsm_h%rad_sw_out(m)    = 0.0_wp
4340                   ENDDO             
4341                   DO  m = surf_usm_h%start_index(j,i),                        &
4342                           surf_usm_h%end_index(j,i)
4343                      surf_usm_h%rad_sw_in(m)     = 0.0_wp
4344                      surf_usm_h%rad_sw_out(m)    = 0.0_wp
4345                   ENDDO 
4346!
4347!--                Vertical surfaces. Fluxes are obtain at respective vertical
4348!--                level of the surface element
4349                   DO  l = 0, 3
4350                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
4351                              surf_lsm_v(l)%end_index(j,i)
4352                         k                           = surf_lsm_v(l)%k(m)
4353                         surf_lsm_v(l)%rad_sw_in(m)  = 0.0_wp
4354                         surf_lsm_v(l)%rad_sw_out(m) = 0.0_wp
4355                      ENDDO             
4356                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
4357                              surf_usm_v(l)%end_index(j,i)
4358                         k                           = surf_usm_v(l)%k(m)
4359                         surf_usm_v(l)%rad_sw_in(m)  = 0.0_wp
4360                         surf_usm_v(l)%rad_sw_out(m) = 0.0_wp
4361                      ENDDO 
4362                   ENDDO
4363                ENDIF
4364
4365             ENDDO
4366          ENDDO
4367
4368       ENDIF
4369!
4370!--    Finally, calculate surface net radiation for surface elements.
4371       IF (  .NOT.  radiation_interactions  ) THEN
4372!--       First, for horizontal surfaces   
4373          DO  m = 1, surf_lsm_h%ns
4374             surf_lsm_h%rad_net(m) = surf_lsm_h%rad_sw_in(m)                   &
4375                                   - surf_lsm_h%rad_sw_out(m)                  &
4376                                   + surf_lsm_h%rad_lw_in(m)                   &
4377                                   - surf_lsm_h%rad_lw_out(m)
4378          ENDDO
4379          DO  m = 1, surf_usm_h%ns
4380             surf_usm_h%rad_net(m) = surf_usm_h%rad_sw_in(m)                   &
4381                                   - surf_usm_h%rad_sw_out(m)                  &
4382                                   + surf_usm_h%rad_lw_in(m)                   &
4383                                   - surf_usm_h%rad_lw_out(m)
4384          ENDDO
4385!
4386!--       Vertical surfaces.
4387!--       Todo: weight with azimuth and zenith angle according to their orientation!
4388          DO  l = 0, 3     
4389             DO  m = 1, surf_lsm_v(l)%ns
4390                surf_lsm_v(l)%rad_net(m) = surf_lsm_v(l)%rad_sw_in(m)          &
4391                                         - surf_lsm_v(l)%rad_sw_out(m)         &
4392                                         + surf_lsm_v(l)%rad_lw_in(m)          &
4393                                         - surf_lsm_v(l)%rad_lw_out(m)
4394             ENDDO
4395             DO  m = 1, surf_usm_v(l)%ns
4396                surf_usm_v(l)%rad_net(m) = surf_usm_v(l)%rad_sw_in(m)          &
4397                                         - surf_usm_v(l)%rad_sw_out(m)         &
4398                                         + surf_usm_v(l)%rad_lw_in(m)          &
4399                                         - surf_usm_v(l)%rad_lw_out(m)
4400             ENDDO
4401          ENDDO
4402       ENDIF
4403
4404
4405       CALL exchange_horiz( rad_lw_in,  nbgp )
4406       CALL exchange_horiz( rad_lw_out, nbgp )
4407       CALL exchange_horiz( rad_lw_hr,    nbgp )
4408       CALL exchange_horiz( rad_lw_cs_hr, nbgp )
4409
4410       CALL exchange_horiz( rad_sw_in,  nbgp )
4411       CALL exchange_horiz( rad_sw_out, nbgp ) 
4412       CALL exchange_horiz( rad_sw_hr,    nbgp )
4413       CALL exchange_horiz( rad_sw_cs_hr, nbgp )
4414
4415#endif
4416
4417    END SUBROUTINE radiation_rrtmg
4418
4419
4420!------------------------------------------------------------------------------!
4421! Description:
4422! ------------
4423!> Calculate the cosine of the zenith angle (variable is called zenith)
4424!------------------------------------------------------------------------------!
4425    SUBROUTINE calc_zenith
4426
4427       IMPLICIT NONE
4428
4429       REAL(wp) ::  declination,  & !< solar declination angle
4430                    hour_angle      !< solar hour angle
4431!
4432!--    Calculate current day and time based on the initial values and simulation
4433!--    time
4434       CALL calc_date_and_time
4435
4436!
4437!--    Calculate solar declination and hour angle   
4438       declination = ASIN( decl_1 * SIN(decl_2 * REAL(day_of_year, KIND=wp) - decl_3) )
4439       hour_angle  = 2.0_wp * pi * (time_utc / 86400.0_wp) + lon - pi
4440
4441!
4442!--    Calculate cosine of solar zenith angle
4443       cos_zenith = SIN(lat) * SIN(declination) + COS(lat) * COS(declination)   &
4444                                            * COS(hour_angle)
4445       cos_zenith = MAX(0.0_wp,cos_zenith)
4446
4447!
4448!--    Calculate solar directional vector
4449       IF ( sun_direction )  THEN
4450
4451!
4452!--       Direction in longitudes equals to sin(solar_azimuth) * sin(zenith)
4453          sun_dir_lon = -SIN(hour_angle) * COS(declination)
4454
4455!
4456!--       Direction in latitues equals to cos(solar_azimuth) * sin(zenith)
4457          sun_dir_lat = SIN(declination) * COS(lat) - COS(hour_angle) &
4458                              * COS(declination) * SIN(lat)
4459       ENDIF
4460
4461!
4462!--    Check if the sun is up (otheriwse shortwave calculations can be skipped)
4463       IF ( cos_zenith > 0.0_wp )  THEN
4464          sun_up = .TRUE.
4465       ELSE
4466          sun_up = .FALSE.
4467       END IF
4468
4469    END SUBROUTINE calc_zenith
4470
4471#if defined ( __rrtmg ) && defined ( __netcdf )
4472!------------------------------------------------------------------------------!
4473! Description:
4474! ------------
4475!> Calculates surface albedo components based on Briegleb (1992) and
4476!> Briegleb et al. (1986)
4477!------------------------------------------------------------------------------!
4478    SUBROUTINE calc_albedo( surf )
4479
4480        IMPLICIT NONE
4481
4482        INTEGER(iwp)    ::  ind_type !< running index surface tiles
4483        INTEGER(iwp)    ::  m        !< running index surface elements
4484
4485        TYPE(surf_type) ::  surf !< treated surfaces
4486
4487        IF ( sun_up  .AND.  .NOT. average_radiation )  THEN
4488
4489           DO  m = 1, surf%ns
4490!
4491!--           Loop over surface elements
4492              DO  ind_type = 0, SIZE( surf%albedo_type, 1 ) - 1
4493           
4494!
4495!--              Ocean
4496                 IF ( surf%albedo_type(ind_type,m) == 1 )  THEN
4497                    surf%rrtm_aldir(ind_type,m) = 0.026_wp /                    &
4498                                                ( cos_zenith**1.7_wp + 0.065_wp )&
4499                                     + 0.15_wp * ( cos_zenith - 0.1_wp )         &
4500                                               * ( cos_zenith - 0.5_wp )         &
4501                                               * ( cos_zenith - 1.0_wp )
4502                    surf%rrtm_asdir(ind_type,m) = surf%rrtm_aldir(ind_type,m)
4503!
4504!--              Snow
4505                 ELSEIF ( surf%albedo_type(ind_type,m) == 16 )  THEN
4506                    IF ( cos_zenith < 0.5_wp )  THEN
4507                       surf%rrtm_aldir(ind_type,m) =                           &
4508                                 0.5_wp * ( 1.0_wp - surf%aldif(ind_type,m) )  &
4509                                        * ( 3.0_wp / ( 1.0_wp + 4.0_wp         &
4510                                        * cos_zenith ) ) - 1.0_wp
4511                       surf%rrtm_asdir(ind_type,m) =                           &
4512                                 0.5_wp * ( 1.0_wp - surf%asdif(ind_type,m) )  &
4513                                        * ( 3.0_wp / ( 1.0_wp + 4.0_wp         &
4514                                        * cos_zenith ) ) - 1.0_wp
4515
4516                       surf%rrtm_aldir(ind_type,m) =                           &
4517                                       MIN(0.98_wp, surf%rrtm_aldir(ind_type,m))
4518                       surf%rrtm_asdir(ind_type,m) =                           &
4519                                       MIN(0.98_wp, surf%rrtm_asdir(ind_type,m))
4520                    ELSE
4521                       surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4522                       surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4523                    ENDIF
4524!
4525!--              Sea ice
4526                 ELSEIF ( surf%albedo_type(ind_type,m) == 15 )  THEN
4527                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4528                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4529
4530!
4531!--              Asphalt
4532                 ELSEIF ( surf%albedo_type(ind_type,m) == 17 )  THEN
4533                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4534                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4535
4536
4537!
4538!--              Bare soil
4539                 ELSEIF ( surf%albedo_type(ind_type,m) == 18 )  THEN
4540                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4541                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4542
4543!
4544!--              Land surfaces
4545                 ELSE
4546                    SELECT CASE ( surf%albedo_type(ind_type,m) )
4547
4548!
4549!--                    Surface types with strong zenith dependence
4550                       CASE ( 1, 2, 3, 4, 11, 12, 13 )
4551                          surf%rrtm_aldir(ind_type,m) =                        &
4552                                surf%aldif(ind_type,m) * 1.4_wp /              &
4553                                           ( 1.0_wp + 0.8_wp * cos_zenith )
4554                          surf%rrtm_asdir(ind_type,m) =                        &
4555                                surf%asdif(ind_type,m) * 1.4_wp /              &
4556                                           ( 1.0_wp + 0.8_wp * cos_zenith )
4557!
4558!--                    Surface types with weak zenith dependence
4559                       CASE ( 5, 6, 7, 8, 9, 10, 14 )
4560                          surf%rrtm_aldir(ind_type,m) =                        &
4561                                surf%aldif(ind_type,m) * 1.1_wp /              &
4562                                           ( 1.0_wp + 0.2_wp * cos_zenith )
4563                          surf%rrtm_asdir(ind_type,m) =                        &
4564                                surf%asdif(ind_type,m) * 1.1_wp /              &
4565                                           ( 1.0_wp + 0.2_wp * cos_zenith )
4566
4567                       CASE DEFAULT
4568
4569                    END SELECT
4570                 ENDIF
4571!
4572!--              Diffusive albedo is taken from Table 2
4573                 surf%rrtm_aldif(ind_type,m) = surf%aldif(ind_type,m)
4574                 surf%rrtm_asdif(ind_type,m) = surf%asdif(ind_type,m)
4575              ENDDO
4576           ENDDO
4577!
4578!--     Set albedo in case of average radiation
4579        ELSEIF ( sun_up  .AND.  average_radiation )  THEN
4580           surf%rrtm_asdir = albedo_urb
4581           surf%rrtm_asdif = albedo_urb
4582           surf%rrtm_aldir = albedo_urb
4583           surf%rrtm_aldif = albedo_urb 
4584!
4585!--     Darkness
4586        ELSE
4587           surf%rrtm_aldir = 0.0_wp
4588           surf%rrtm_asdir = 0.0_wp
4589           surf%rrtm_aldif = 0.0_wp
4590           surf%rrtm_asdif = 0.0_wp
4591        ENDIF
4592
4593    END SUBROUTINE calc_albedo
4594
4595!------------------------------------------------------------------------------!
4596! Description:
4597! ------------
4598!> Read sounding data (pressure and temperature) from RADIATION_DATA.
4599!------------------------------------------------------------------------------!
4600    SUBROUTINE read_sounding_data
4601
4602       IMPLICIT NONE
4603
4604       INTEGER(iwp) :: id,           & !< NetCDF id of input file
4605                       id_dim_zrad,  & !< pressure level id in the NetCDF file
4606                       id_var,       & !< NetCDF variable id
4607                       k,            & !< loop index
4608                       nz_snd,       & !< number of vertical levels in the sounding data
4609                       nz_snd_start, & !< start vertical index for sounding data to be used
4610                       nz_snd_end      !< end vertical index for souding data to be used
4611
4612       REAL(wp) :: t_surface           !< actual surface temperature
4613
4614       REAL(wp), DIMENSION(:), ALLOCATABLE ::  hyp_snd_tmp, & !< temporary hydrostatic pressure profile (sounding)
4615                                               t_snd_tmp      !< temporary temperature profile (sounding)
4616
4617!
4618!--    In case of updates, deallocate arrays first (sufficient to check one
4619!--    array as the others are automatically allocated). This is required
4620!--    because nzt_rad might change during the update
4621       IF ( ALLOCATED ( hyp_snd ) )  THEN
4622          DEALLOCATE( hyp_snd )
4623          DEALLOCATE( t_snd )
4624          DEALLOCATE ( rrtm_play )
4625          DEALLOCATE ( rrtm_plev )
4626          DEALLOCATE ( rrtm_tlay )
4627          DEALLOCATE ( rrtm_tlev )
4628
4629          DEALLOCATE ( rrtm_cicewp )
4630          DEALLOCATE ( rrtm_cldfr )
4631          DEALLOCATE ( rrtm_cliqwp )
4632          DEALLOCATE ( rrtm_reice )
4633          DEALLOCATE ( rrtm_reliq )
4634          DEALLOCATE ( rrtm_lw_taucld )
4635          DEALLOCATE ( rrtm_lw_tauaer )
4636
4637          DEALLOCATE ( rrtm_lwdflx  )
4638          DEALLOCATE ( rrtm_lwdflxc )
4639          DEALLOCATE ( rrtm_lwuflx  )
4640          DEALLOCATE ( rrtm_lwuflxc )
4641          DEALLOCATE ( rrtm_lwuflx_dt )
4642          DEALLOCATE ( rrtm_lwuflxc_dt )
4643          DEALLOCATE ( rrtm_lwhr  )
4644          DEALLOCATE ( rrtm_lwhrc )
4645
4646          DEALLOCATE ( rrtm_sw_taucld )
4647          DEALLOCATE ( rrtm_sw_ssacld )
4648          DEALLOCATE ( rrtm_sw_asmcld )
4649          DEALLOCATE ( rrtm_sw_fsfcld )
4650          DEALLOCATE ( rrtm_sw_tauaer )
4651          DEALLOCATE ( rrtm_sw_ssaaer )
4652          DEALLOCATE ( rrtm_sw_asmaer ) 
4653          DEALLOCATE ( rrtm_sw_ecaer )   
4654 
4655          DEALLOCATE ( rrtm_swdflx  )
4656          DEALLOCATE ( rrtm_swdflxc )
4657          DEALLOCATE ( rrtm_swuflx  )
4658          DEALLOCATE ( rrtm_swuflxc )
4659          DEALLOCATE ( rrtm_swhr  )
4660          DEALLOCATE ( rrtm_swhrc )
4661          DEALLOCATE ( rrtm_dirdflux )
4662          DEALLOCATE ( rrtm_difdflux )
4663
4664       ENDIF
4665
4666!
4667!--    Open file for reading
4668       nc_stat = NF90_OPEN( rrtm_input_file, NF90_NOWRITE, id )
4669       CALL netcdf_handle_error_rad( 'read_sounding_data', 549 )
4670
4671!
4672!--    Inquire dimension of z axis and save in nz_snd
4673       nc_stat = NF90_INQ_DIMID( id, "Pressure", id_dim_zrad )
4674       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim_zrad, len = nz_snd )
4675       CALL netcdf_handle_error_rad( 'read_sounding_data', 551 )
4676
4677!
4678! !--    Allocate temporary array for storing pressure data
4679       ALLOCATE( hyp_snd_tmp(1:nz_snd) )
4680       hyp_snd_tmp = 0.0_wp
4681
4682
4683!--    Read pressure from file
4684       nc_stat = NF90_INQ_VARID( id, "Pressure", id_var )
4685       nc_stat = NF90_GET_VAR( id, id_var, hyp_snd_tmp(:), start = (/1/),      &
4686                               count = (/nz_snd/) )
4687       CALL netcdf_handle_error_rad( 'read_sounding_data', 552 )
4688
4689!
4690!--    Allocate temporary array for storing temperature data
4691       ALLOCATE( t_snd_tmp(1:nz_snd) )
4692       t_snd_tmp = 0.0_wp
4693
4694!
4695!--    Read temperature from file
4696       nc_stat = NF90_INQ_VARID( id, "ReferenceTemperature", id_var )
4697       nc_stat = NF90_GET_VAR( id, id_var, t_snd_tmp(:), start = (/1/),        &
4698                               count = (/nz_snd/) )
4699       CALL netcdf_handle_error_rad( 'read_sounding_data', 553 )
4700
4701!
4702!--    Calculate start of sounding data
4703       nz_snd_start = nz_snd + 1
4704       nz_snd_end   = nz_snd + 1
4705
4706!
4707!--    Start filling vertical dimension at 10hPa above the model domain (hyp is
4708!--    in Pa, hyp_snd in hPa).
4709       DO  k = 1, nz_snd
4710          IF ( hyp_snd_tmp(k) < ( hyp(nzt+1) - 1000.0_wp) * 0.01_wp )  THEN
4711             nz_snd_start = k
4712             EXIT
4713          END IF
4714       END DO
4715
4716       IF ( nz_snd_start <= nz_snd )  THEN
4717          nz_snd_end = nz_snd
4718       END IF
4719
4720
4721!
4722!--    Calculate of total grid points for RRTMG calculations
4723       nzt_rad = nzt + nz_snd_end - nz_snd_start + 1
4724
4725!
4726!--    Save data above LES domain in hyp_snd, t_snd
4727       ALLOCATE( hyp_snd(nzb+1:nzt_rad) )
4728       ALLOCATE( t_snd(nzb+1:nzt_rad)   )
4729       hyp_snd = 0.0_wp
4730       t_snd = 0.0_wp
4731
4732       hyp_snd(nzt+2:nzt_rad) = hyp_snd_tmp(nz_snd_start+1:nz_snd_end)
4733       t_snd(nzt+2:nzt_rad)   = t_snd_tmp(nz_snd_start+1:nz_snd_end)
4734
4735       nc_stat = NF90_CLOSE( id )
4736
4737!
4738!--    Calculate pressure levels on zu and zw grid. Sounding data is added at
4739!--    top of the LES domain. This routine does not consider horizontal or
4740!--    vertical variability of pressure and temperature
4741       ALLOCATE ( rrtm_play(0:0,nzb+1:nzt_rad+1)   )
4742       ALLOCATE ( rrtm_plev(0:0,nzb+1:nzt_rad+2)   )
4743
4744       t_surface = pt_surface * exner(nzb)
4745       DO k = nzb+1, nzt+1
4746          rrtm_play(0,k) = hyp(k) * 0.01_wp
4747          rrtm_plev(0,k) = barometric_formula(zw(k-1),                         &
4748                              pt_surface * exner(nzb), &
4749                              surface_pressure )
4750       ENDDO
4751
4752       DO k = nzt+2, nzt_rad
4753          rrtm_play(0,k) = hyp_snd(k)
4754          rrtm_plev(0,k) = 0.5_wp * ( rrtm_play(0,k) + rrtm_play(0,k-1) )
4755       ENDDO
4756       rrtm_plev(0,nzt_rad+1) = MAX( 0.5 * hyp_snd(nzt_rad),                   &
4757                                   1.5 * hyp_snd(nzt_rad)                      &
4758                                 - 0.5 * hyp_snd(nzt_rad-1) )
4759       rrtm_plev(0,nzt_rad+2)  = MIN( 1.0E-4_wp,                               &
4760                                      0.25_wp * rrtm_plev(0,nzt_rad+1) )
4761
4762       rrtm_play(0,nzt_rad+1) = 0.5 * rrtm_plev(0,nzt_rad+1)
4763
4764!
4765!--    Calculate temperature/humidity levels at top of the LES domain.
4766!--    Currently, the temperature is taken from sounding data (might lead to a
4767!--    temperature jump at interface. To do: Humidity is currently not
4768!--    calculated above the LES domain.
4769       ALLOCATE ( rrtm_tlay(0:0,nzb+1:nzt_rad+1)   )
4770       ALLOCATE ( rrtm_tlev(0:0,nzb+1:nzt_rad+2)   )
4771
4772       DO k = nzt+8, nzt_rad
4773          rrtm_tlay(0,k)   = t_snd(k)
4774       ENDDO
4775       rrtm_tlay(0,nzt_rad+1) = 2.0_wp * rrtm_tlay(0,nzt_rad)                  &
4776                                - rrtm_tlay(0,nzt_rad-1)
4777       DO k = nzt+9, nzt_rad+1
4778          rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k)                &
4779                             - rrtm_tlay(0,k-1))                               &
4780                             / ( rrtm_play(0,k) - rrtm_play(0,k-1) )           &
4781                             * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
4782       ENDDO
4783
4784       rrtm_tlev(0,nzt_rad+2)   = 2.0_wp * rrtm_tlay(0,nzt_rad+1)              &
4785                                  - rrtm_tlev(0,nzt_rad)
4786!
4787!--    Allocate remaining RRTMG arrays
4788       ALLOCATE ( rrtm_cicewp(0:0,nzb+1:nzt_rad+1) )
4789       ALLOCATE ( rrtm_cldfr(0:0,nzb+1:nzt_rad+1) )
4790       ALLOCATE ( rrtm_cliqwp(0:0,nzb+1:nzt_rad+1) )
4791       ALLOCATE ( rrtm_reice(0:0,nzb+1:nzt_rad+1) )
4792       ALLOCATE ( rrtm_reliq(0:0,nzb+1:nzt_rad+1) )
4793       ALLOCATE ( rrtm_lw_taucld(1:nbndlw+1,0:0,nzb+1:nzt_rad+1) )
4794       ALLOCATE ( rrtm_lw_tauaer(0:0,nzb+1:nzt_rad+1,1:nbndlw+1) )
4795       ALLOCATE ( rrtm_sw_taucld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4796       ALLOCATE ( rrtm_sw_ssacld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4797       ALLOCATE ( rrtm_sw_asmcld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4798       ALLOCATE ( rrtm_sw_fsfcld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4799       ALLOCATE ( rrtm_sw_tauaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) )
4800       ALLOCATE ( rrtm_sw_ssaaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) )
4801       ALLOCATE ( rrtm_sw_asmaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) ) 
4802       ALLOCATE ( rrtm_sw_ecaer(0:0,nzb+1:nzt_rad+1,1:naerec+1) )   
4803
4804!
4805!--    The ice phase is currently not considered in PALM
4806       rrtm_cicewp = 0.0_wp
4807       rrtm_reice  = 0.0_wp
4808
4809!
4810!--    Set other parameters (move to NAMELIST parameters in the future)
4811       rrtm_lw_tauaer = 0.0_wp
4812       rrtm_lw_taucld = 0.0_wp
4813       rrtm_sw_taucld = 0.0_wp
4814       rrtm_sw_ssacld = 0.0_wp
4815       rrtm_sw_asmcld = 0.0_wp
4816       rrtm_sw_fsfcld = 0.0_wp
4817       rrtm_sw_tauaer = 0.0_wp
4818       rrtm_sw_ssaaer = 0.0_wp
4819       rrtm_sw_asmaer = 0.0_wp
4820       rrtm_sw_ecaer  = 0.0_wp
4821
4822
4823       ALLOCATE ( rrtm_swdflx(0:0,nzb:nzt_rad+1)  )
4824       ALLOCATE ( rrtm_swuflx(0:0,nzb:nzt_rad+1)  )
4825       ALLOCATE ( rrtm_swhr(0:0,nzb+1:nzt_rad+1)  )
4826       ALLOCATE ( rrtm_swuflxc(0:0,nzb:nzt_rad+1) )
4827       ALLOCATE ( rrtm_swdflxc(0:0,nzb:nzt_rad+1) )
4828       ALLOCATE ( rrtm_swhrc(0:0,nzb+1:nzt_rad+1) )
4829       ALLOCATE ( rrtm_dirdflux(0:0,nzb:nzt_rad+1) )
4830       ALLOCATE ( rrtm_difdflux(0:0,nzb:nzt_rad+1) )
4831
4832       rrtm_swdflx  = 0.0_wp
4833       rrtm_swuflx  = 0.0_wp
4834       rrtm_swhr    = 0.0_wp 
4835       rrtm_swuflxc = 0.0_wp
4836       rrtm_swdflxc = 0.0_wp
4837       rrtm_swhrc   = 0.0_wp
4838       rrtm_dirdflux = 0.0_wp
4839       rrtm_difdflux = 0.0_wp
4840
4841       ALLOCATE ( rrtm_lwdflx(0:0,nzb:nzt_rad+1)  )
4842       ALLOCATE ( rrtm_lwuflx(0:0,nzb:nzt_rad+1)  )
4843       ALLOCATE ( rrtm_lwhr(0:0,nzb+1:nzt_rad+1)  )
4844       ALLOCATE ( rrtm_lwuflxc(0:0,nzb:nzt_rad+1) )
4845       ALLOCATE ( rrtm_lwdflxc(0:0,nzb:nzt_rad+1) )
4846       ALLOCATE ( rrtm_lwhrc(0:0,nzb+1:nzt_rad+1) )
4847
4848       rrtm_lwdflx  = 0.0_wp
4849       rrtm_lwuflx  = 0.0_wp
4850       rrtm_lwhr    = 0.0_wp 
4851       rrtm_lwuflxc = 0.0_wp
4852       rrtm_lwdflxc = 0.0_wp
4853       rrtm_lwhrc   = 0.0_wp
4854
4855       ALLOCATE ( rrtm_lwuflx_dt(0:0,nzb:nzt_rad+1) )
4856       ALLOCATE ( rrtm_lwuflxc_dt(0:0,nzb:nzt_rad+1) )
4857
4858       rrtm_lwuflx_dt = 0.0_wp
4859       rrtm_lwuflxc_dt = 0.0_wp
4860
4861    END SUBROUTINE read_sounding_data
4862
4863
4864!------------------------------------------------------------------------------!
4865! Description:
4866! ------------
4867!> Read trace gas data from file and convert into trace gas paths / volume
4868!> mixing ratios. If a user-defined input file is provided it needs to follow
4869!> the convections used in RRTMG (see respective netCDF files shipped with
4870!> RRTMG)
4871!------------------------------------------------------------------------------!
4872    SUBROUTINE read_trace_gas_data
4873
4874       USE rrsw_ncpar
4875
4876       IMPLICIT NONE
4877
4878       INTEGER(iwp), PARAMETER :: num_trace_gases = 10 !< number of trace gases (absorbers)
4879
4880       CHARACTER(LEN=5), DIMENSION(num_trace_gases), PARAMETER ::              & !< trace gas names
4881           trace_names = (/'O3   ', 'CO2  ', 'CH4  ', 'N2O  ', 'O2   ',        &
4882                           'CFC11', 'CFC12', 'CFC22', 'CCL4 ', 'H2O  '/)
4883
4884       INTEGER(iwp) :: id,     & !< NetCDF id
4885                       k,      & !< loop index
4886                       m,      & !< loop index
4887                       n,      & !< loop index
4888                       nabs,   & !< number of absorbers
4889                       np,     & !< number of pressure levels
4890                       id_abs, & !< NetCDF id of the respective absorber
4891                       id_dim, & !< NetCDF id of asborber's dimension
4892                       id_var    !< NetCDf id ot the absorber
4893
4894       REAL(wp) :: p_mls_l, &    !< pressure lower limit for interpolation
4895                   p_mls_u, &    !< pressure upper limit for interpolation
4896                   p_wgt_l, &    !< pressure weight lower limit for interpolation
4897                   p_wgt_u, &    !< pressure weight upper limit for interpolation
4898                   p_mls_m       !< mean pressure between upper and lower limits
4899
4900
4901       REAL(wp), DIMENSION(:), ALLOCATABLE   ::  p_mls,          & !< pressure levels for the absorbers
4902                                                 rrtm_play_tmp,  & !< temporary array for pressure zu-levels
4903                                                 rrtm_plev_tmp,  & !< temporary array for pressure zw-levels
4904                                                 trace_path_tmp    !< temporary array for storing trace gas path data
4905
4906       REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  trace_mls,      & !< array for storing the absorber amounts
4907                                                 trace_mls_path, & !< array for storing trace gas path data
4908                                                 trace_mls_tmp     !< temporary array for storing trace gas data
4909
4910
4911!
4912!--    In case of updates, deallocate arrays first (sufficient to check one
4913!--    array as the others are automatically allocated)
4914       IF ( ALLOCATED ( rrtm_o3vmr ) )  THEN
4915          DEALLOCATE ( rrtm_o3vmr  )
4916          DEALLOCATE ( rrtm_co2vmr )
4917          DEALLOCATE ( rrtm_ch4vmr )
4918          DEALLOCATE ( rrtm_n2ovmr )
4919          DEALLOCATE ( rrtm_o2vmr  )
4920          DEALLOCATE ( rrtm_cfc11vmr )
4921          DEALLOCATE ( rrtm_cfc12vmr )
4922          DEALLOCATE ( rrtm_cfc22vmr )
4923          DEALLOCATE ( rrtm_ccl4vmr  )
4924          DEALLOCATE ( rrtm_h2ovmr  )     
4925       ENDIF
4926
4927!
4928!--    Allocate trace gas profiles
4929       ALLOCATE ( rrtm_o3vmr(0:0,1:nzt_rad+1)  )
4930       ALLOCATE ( rrtm_co2vmr(0:0,1:nzt_rad+1) )
4931       ALLOCATE ( rrtm_ch4vmr(0:0,1:nzt_rad+1) )
4932       ALLOCATE ( rrtm_n2ovmr(0:0,1:nzt_rad+1) )
4933       ALLOCATE ( rrtm_o2vmr(0:0,1:nzt_rad+1)  )
4934       ALLOCATE ( rrtm_cfc11vmr(0:0,1:nzt_rad+1) )
4935       ALLOCATE ( rrtm_cfc12vmr(0:0,1:nzt_rad+1) )
4936       ALLOCATE ( rrtm_cfc22vmr(0:0,1:nzt_rad+1) )
4937       ALLOCATE ( rrtm_ccl4vmr(0:0,1:nzt_rad+1)  )
4938       ALLOCATE ( rrtm_h2ovmr(0:0,1:nzt_rad+1)  )
4939
4940!
4941!--    Open file for reading
4942       nc_stat = NF90_OPEN( rrtm_input_file, NF90_NOWRITE, id )
4943       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 549 )
4944!
4945!--    Inquire dimension ids and dimensions
4946       nc_stat = NF90_INQ_DIMID( id, "Pressure", id_dim )
4947       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4948       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim, len = np) 
4949       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4950
4951       nc_stat = NF90_INQ_DIMID( id, "Absorber", id_dim )
4952       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4953       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim, len = nabs ) 
4954       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4955   
4956
4957!
4958!--    Allocate pressure, and trace gas arrays     
4959       ALLOCATE( p_mls(1:np) )
4960       ALLOCATE( trace_mls(1:num_trace_gases,1:np) ) 
4961       ALLOCATE( trace_mls_tmp(1:nabs,1:np) ) 
4962
4963
4964       nc_stat = NF90_INQ_VARID( id, "Pressure", id_var )
4965       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4966       nc_stat = NF90_GET_VAR( id, id_var, p_mls )
4967       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4968
4969       nc_stat = NF90_INQ_VARID( id, "AbsorberAmountMLS", id_var )
4970       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4971       nc_stat = NF90_GET_VAR( id, id_var, trace_mls_tmp )
4972       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4973
4974
4975!
4976!--    Write absorber amounts (mls) to trace_mls
4977       DO n = 1, num_trace_gases
4978          CALL getAbsorberIndex( TRIM( trace_names(n) ), id_abs )
4979
4980          trace_mls(n,1:np) = trace_mls_tmp(id_abs,1:np)
4981
4982!
4983!--       Replace missing values by zero
4984          WHERE ( trace_mls(n,:) > 2.0_wp ) 
4985             trace_mls(n,:) = 0.0_wp
4986          END WHERE
4987       END DO
4988
4989       DEALLOCATE ( trace_mls_tmp )
4990
4991       nc_stat = NF90_CLOSE( id )
4992       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 551 )
4993
4994!
4995!--    Add extra pressure level for calculations of the trace gas paths
4996       ALLOCATE ( rrtm_play_tmp(1:nzt_rad+1) )
4997       ALLOCATE ( rrtm_plev_tmp(1:nzt_rad+2) )
4998
4999       rrtm_play_tmp(1:nzt_rad)   = rrtm_play(0,1:nzt_rad) 
5000       rrtm_plev_tmp(1:nzt_rad+1) = rrtm_plev(0,1:nzt_rad+1)
5001       rrtm_play_tmp(nzt_rad+1)   = rrtm_plev(0,nzt_rad+1) * 0.5_wp
5002       rrtm_plev_tmp(nzt_rad+2)   = MIN( 1.0E-4_wp, 0.25_wp                    &
5003                                         * rrtm_plev(0,nzt_rad+1) )
5004 
5005!
5006!--    Calculate trace gas path (zero at surface) with interpolation to the
5007!--    sounding levels
5008       ALLOCATE ( trace_mls_path(1:nzt_rad+2,1:num_trace_gases) )
5009
5010       trace_mls_path(nzb+1,:) = 0.0_wp
5011       
5012       DO k = nzb+2, nzt_rad+2
5013          DO m = 1, num_trace_gases
5014             trace_mls_path(k,m) = trace_mls_path(k-1,m)
5015
5016!
5017!--          When the pressure level is higher than the trace gas pressure
5018!--          level, assume that
5019             IF ( rrtm_plev_tmp(k-1) > p_mls(1) )  THEN             
5020               
5021                trace_mls_path(k,m) = trace_mls_path(k,m) + trace_mls(m,1)     &
5022                                      * ( rrtm_plev_tmp(k-1)                   &
5023                                          - MAX( p_mls(1), rrtm_plev_tmp(k) )  &
5024                                        ) / g
5025             ENDIF
5026
5027!
5028!--          Integrate for each sounding level from the contributing p_mls
5029!--          levels
5030             DO n = 2, np
5031!
5032!--             Limit p_mls so that it is within the model level
5033                p_mls_u = MIN( rrtm_plev_tmp(k-1),                             &
5034                          MAX( rrtm_plev_tmp(k), p_mls(n) ) )
5035                p_mls_l = MIN( rrtm_plev_tmp(k-1),                             &
5036                          MAX( rrtm_plev_tmp(k), p_mls(n-1) ) )
5037
5038                IF ( p_mls_l > p_mls_u )  THEN
5039
5040!
5041!--                Calculate weights for interpolation
5042                   p_mls_m = 0.5_wp * (p_mls_l + p_mls_u)
5043                   p_wgt_u = (p_mls(n-1) - p_mls_m) / (p_mls(n-1) - p_mls(n))
5044                   p_wgt_l = (p_mls_m - p_mls(n))   / (p_mls(n-1) - p_mls(n))
5045
5046!
5047!--                Add level to trace gas path
5048                   trace_mls_path(k,m) = trace_mls_path(k,m)                   &
5049                                         +  ( p_wgt_u * trace_mls(m,n)         &
5050                                            + p_wgt_l * trace_mls(m,n-1) )     &
5051                                         * (p_mls_l - p_mls_u) / g
5052                ENDIF
5053             ENDDO
5054
5055             IF ( rrtm_plev_tmp(k) < p_mls(np) )  THEN
5056                trace_mls_path(k,m) = trace_mls_path(k,m) + trace_mls(m,np)    &
5057                                      * ( MIN( rrtm_plev_tmp(k-1), p_mls(np) ) &
5058                                          - rrtm_plev_tmp(k)                   &
5059                                        ) / g 
5060             ENDIF 
5061          ENDDO
5062       ENDDO
5063
5064
5065!
5066!--    Prepare trace gas path profiles
5067       ALLOCATE ( trace_path_tmp(1:nzt_rad+1) )
5068
5069       DO m = 1, num_trace_gases
5070
5071          trace_path_tmp(1:nzt_rad+1) = ( trace_mls_path(2:nzt_rad+2,m)        &
5072                                       - trace_mls_path(1:nzt_rad+1,m) ) * g   &
5073                                       / ( rrtm_plev_tmp(1:nzt_rad+1)          &
5074                                       - rrtm_plev_tmp(2:nzt_rad+2) )
5075
5076!
5077!--       Save trace gas paths to the respective arrays
5078          SELECT CASE ( TRIM( trace_names(m) ) )
5079
5080             CASE ( 'O3' )
5081
5082                rrtm_o3vmr(0,:) = trace_path_tmp(:)
5083
5084             CASE ( 'CO2' )
5085
5086                rrtm_co2vmr(0,:) = trace_path_tmp(:)
5087
5088             CASE ( 'CH4' )
5089
5090                rrtm_ch4vmr(0,:) = trace_path_tmp(:)
5091
5092             CASE ( 'N2O' )
5093
5094                rrtm_n2ovmr(0,:) = trace_path_tmp(:)
5095
5096             CASE ( 'O2' )
5097
5098                rrtm_o2vmr(0,:) = trace_path_tmp(:)
5099
5100             CASE ( 'CFC11' )
5101
5102                rrtm_cfc11vmr(0,:) = trace_path_tmp(:)
5103
5104             CASE ( 'CFC12' )
5105
5106                rrtm_cfc12vmr(0,:) = trace_path_tmp(:)
5107
5108             CASE ( 'CFC22' )
5109
5110                rrtm_cfc22vmr(0,:) = trace_path_tmp(:)
5111
5112             CASE ( 'CCL4' )
5113
5114                rrtm_ccl4vmr(0,:) = trace_path_tmp(:)
5115
5116             CASE ( 'H2O' )
5117
5118                rrtm_h2ovmr(0,:) = trace_path_tmp(:)
5119               
5120             CASE DEFAULT
5121
5122          END SELECT
5123
5124       ENDDO
5125
5126       DEALLOCATE ( trace_path_tmp )
5127       DEALLOCATE ( trace_mls_path )
5128       DEALLOCATE ( rrtm_play_tmp )
5129       DEALLOCATE ( rrtm_plev_tmp )
5130       DEALLOCATE ( trace_mls )
5131       DEALLOCATE ( p_mls )
5132
5133    END SUBROUTINE read_trace_gas_data
5134
5135
5136    SUBROUTINE netcdf_handle_error_rad( routine_name, errno )
5137
5138       USE control_parameters,                                                 &
5139           ONLY:  message_string
5140
5141       USE NETCDF
5142
5143       USE pegrid
5144
5145       IMPLICIT NONE
5146
5147       CHARACTER(LEN=6) ::  message_identifier
5148       CHARACTER(LEN=*) ::  routine_name
5149
5150       INTEGER(iwp) ::  errno
5151
5152       IF ( nc_stat /= NF90_NOERR )  THEN
5153
5154          WRITE( message_identifier, '(''NC'',I4.4)' )  errno
5155          message_string = TRIM( NF90_STRERROR( nc_stat ) )
5156
5157          CALL message( routine_name, message_identifier, 2, 2, 0, 6, 1 )
5158
5159       ENDIF
5160
5161    END SUBROUTINE netcdf_handle_error_rad
5162#endif
5163
5164
5165!------------------------------------------------------------------------------!
5166! Description:
5167! ------------
5168!> Calculate temperature tendency due to radiative cooling/heating.
5169!> Cache-optimized version.
5170!------------------------------------------------------------------------------!
5171#if defined( __rrtmg )
5172 SUBROUTINE radiation_tendency_ij ( i, j, tend )
5173
5174    IMPLICIT NONE
5175
5176    INTEGER(iwp) :: i, j, k !< loop indices
5177
5178    REAL(wp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg) :: tend !< pt tendency term
5179
5180    IF ( radiation_scheme == 'rrtmg' )  THEN
5181!
5182!--    Calculate tendency based on heating rate
5183       DO k = nzb+1, nzt+1
5184          tend(k,j,i) = tend(k,j,i) + (rad_lw_hr(k,j,i) + rad_sw_hr(k,j,i))    &
5185                                         * d_exner(k) * d_seconds_hour
5186       ENDDO
5187
5188    ENDIF
5189
5190 END SUBROUTINE radiation_tendency_ij
5191#endif
5192
5193
5194!------------------------------------------------------------------------------!
5195! Description:
5196! ------------
5197!> Calculate temperature tendency due to radiative cooling/heating.
5198!> Vector-optimized version
5199!------------------------------------------------------------------------------!
5200#if defined( __rrtmg )
5201 SUBROUTINE radiation_tendency ( tend )
5202
5203    USE indices,                                                               &
5204        ONLY:  nxl, nxr, nyn, nys
5205
5206    IMPLICIT NONE
5207
5208    INTEGER(iwp) :: i, j, k !< loop indices
5209
5210    REAL(wp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg) :: tend !< pt tendency term
5211
5212    IF ( radiation_scheme == 'rrtmg' )  THEN
5213!
5214!--    Calculate tendency based on heating rate
5215       DO  i = nxl, nxr
5216          DO  j = nys, nyn
5217             DO k = nzb+1, nzt+1
5218                tend(k,j,i) = tend(k,j,i) + ( rad_lw_hr(k,j,i)                 &
5219                                          +  rad_sw_hr(k,j,i) ) * d_exner(k)   &
5220                                          * d_seconds_hour
5221             ENDDO
5222          ENDDO
5223       ENDDO
5224    ENDIF
5225
5226 END SUBROUTINE radiation_tendency
5227#endif
5228
5229!------------------------------------------------------------------------------!
5230! Description:
5231! ------------
5232!> This subroutine calculates interaction of the solar radiation
5233!> with urban and land surfaces and updates all surface heatfluxes.
5234!> It calculates also the required parameters for RRTMG lower BC.
5235!>
5236!> For more info. see Resler et al. 2017
5237!>
5238!> The new version 2.0 was radically rewriten, the discretization scheme
5239!> has been changed. This new version significantly improves effectivity
5240!> of the paralelization and the scalability of the model.
5241!------------------------------------------------------------------------------!
5242
5243 SUBROUTINE radiation_interaction
5244
5245     IMPLICIT NONE
5246
5247     INTEGER(iwp)                      :: i, j, k, kk, d, refstep, m, mm, l, ll
5248     INTEGER(iwp)                      :: isurf, isurfsrc, isvf, icsf, ipcgb
5249     INTEGER(iwp)                      :: imrt, imrtf
5250     INTEGER(iwp)                      :: isd                !< solar direction number
5251     INTEGER(iwp)                      :: pc_box_dimshift    !< transform for best accuracy
5252     INTEGER(iwp), DIMENSION(0:3)      :: reorder = (/ 1, 0, 3, 2 /)
5253     
5254     REAL(wp), DIMENSION(3,3)          :: mrot               !< grid rotation matrix (zyx)
5255     REAL(wp), DIMENSION(3,0:nsurf_type):: vnorm             !< face direction normal vectors (zyx)
5256     REAL(wp), DIMENSION(3)            :: sunorig            !< grid rotated solar direction unit vector (zyx)
5257     REAL(wp), DIMENSION(3)            :: sunorig_grid       !< grid squashed solar direction unit vector (zyx)
5258     REAL(wp), DIMENSION(0:nsurf_type) :: costheta           !< direct irradiance factor of solar angle
5259     REAL(wp), DIMENSION(nz_urban_b:nz_urban_t)    :: pchf_prep          !< precalculated factor for canopy temperature tendency
5260     REAL(wp), PARAMETER               :: alpha = 0._wp      !< grid rotation (TODO: synchronize with rotation_angle
5261                                                             !< from netcdf_data_input_mod)
5262     REAL(wp)                          :: pc_box_area, pc_abs_frac, pc_abs_eff
5263     REAL(wp)                          :: asrc               !< area of source face
5264     REAL(wp)                          :: pcrad              !< irradiance from plant canopy
5265     REAL(wp)                          :: pabsswl  = 0.0_wp  !< total absorbed SW radiation energy in local processor (W)
5266     REAL(wp)                          :: pabssw   = 0.0_wp  !< total absorbed SW radiation energy in all processors (W)
5267     REAL(wp)                          :: pabslwl  = 0.0_wp  !< total absorbed LW radiation energy in local processor (W)
5268     REAL(wp)                          :: pabslw   = 0.0_wp  !< total absorbed LW radiation energy in all processors (W)
5269     REAL(wp)                          :: pemitlwl = 0.0_wp  !< total emitted LW radiation energy in all processors (W)
5270     REAL(wp)                          :: pemitlw  = 0.0_wp  !< total emitted LW radiation energy in all processors (W)
5271     REAL(wp)                          :: pinswl   = 0.0_wp  !< total received SW radiation energy in local processor (W)
5272     REAL(wp)                          :: pinsw    = 0.0_wp  !< total received SW radiation energy in all processor (W)
5273     REAL(wp)                          :: pinlwl   = 0.0_wp  !< total received LW radiation energy in local processor (W)
5274     REAL(wp)                          :: pinlw    = 0.0_wp  !< total received LW radiation energy in all processor (W)
5275     REAL(wp)                          :: emiss_sum_surfl    !< sum of emissisivity of surfaces in local processor
5276     REAL(wp)                          :: emiss_sum_surf     !< sum of emissisivity of surfaces in all processor
5277     REAL(wp)                          :: area_surfl         !< total area of surfaces in local processor
5278     REAL(wp)                          :: area_surf          !< total area of surfaces in all processor
5279     REAL(wp)                          :: area_hor           !< total horizontal area of domain in all processor
5280
5281
5282     IF ( debug_output_timestep )  CALL debug_message( 'radiation_interaction', 'start' )
5283
5284     IF ( plant_canopy )  THEN
5285         pchf_prep(:) = r_d * exner(nz_urban_b:nz_urban_t)                                 &
5286                     / (c_p * hyp(nz_urban_b:nz_urban_t) * dx*dy*dz(1)) !< equals to 1 / (rho * c_p * Vbox * T)
5287     ENDIF
5288
5289     sun_direction = .TRUE.
5290     CALL calc_zenith  !< required also for diffusion radiation
5291
5292!--     prepare rotated normal vectors and irradiance factor
5293     vnorm(1,:) = kdir(:)
5294     vnorm(2,:) = jdir(:)
5295     vnorm(3,:) = idir(:)
5296     mrot(1, :) = (/ 1._wp,  0._wp,      0._wp      /)
5297     mrot(2, :) = (/ 0._wp,  COS(alpha), SIN(alpha) /)
5298     mrot(3, :) = (/ 0._wp, -SIN(alpha), COS(alpha) /)
5299     sunorig = (/ cos_zenith, sun_dir_lat, sun_dir_lon /)
5300     sunorig = MATMUL(mrot, sunorig)
5301     DO d = 0, nsurf_type
5302         costheta(d) = DOT_PRODUCT(sunorig, vnorm(:,d))
5303     ENDDO
5304
5305     IF ( cos_zenith > 0 )  THEN
5306!--      now we will "squash" the sunorig vector by grid box size in
5307!--      each dimension, so that this new direction vector will allow us
5308!--      to traverse the ray path within grid coordinates directly
5309         sunorig_grid = (/ sunorig(1)/dz(1), sunorig(2)/dy, sunorig(3)/dx /)
5310!--      sunorig_grid = sunorig_grid / norm2(sunorig_grid)
5311         sunorig_grid = sunorig_grid / SQRT(SUM(sunorig_grid**2))
5312
5313         IF ( npcbl > 0 )  THEN
5314!--         precompute effective box depth with prototype Leaf Area Density
5315            pc_box_dimshift = MAXLOC(ABS(sunorig), 1) - 1
5316            CALL box_absorb(CSHIFT((/dz(1),dy,dx/), pc_box_dimshift),       &
5317                                60, prototype_lad,                          &
5318                                CSHIFT(ABS(sunorig), pc_box_dimshift),      &
5319                                pc_box_area, pc_abs_frac)
5320            pc_box_area = pc_box_area * ABS(sunorig(pc_box_dimshift+1)      &
5321                          / sunorig(1))
5322            pc_abs_eff = LOG(1._wp - pc_abs_frac) / prototype_lad
5323         ENDIF
5324     ENDIF
5325
5326!--  if radiation scheme is not RRTMG, split diffusion and direct part of the solar downward radiation
5327!--  comming from radiation model and store it in 2D arrays
5328     IF (  radiation_scheme /= 'rrtmg'  )  CALL calc_diffusion_radiation
5329
5330!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5331!--     First pass: direct + diffuse irradiance + thermal
5332!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5333     surfinswdir   = 0._wp !nsurfl
5334     surfins       = 0._wp !nsurfl
5335     surfinl       = 0._wp !nsurfl
5336     surfoutsl(:)  = 0.0_wp !start-end
5337     surfoutll(:)  = 0.0_wp !start-end
5338     IF ( nmrtbl > 0 )  THEN
5339        mrtinsw(:) = 0._wp
5340        mrtinlw(:) = 0._wp
5341     ENDIF
5342     surfinlg(:)  = 0._wp !global
5343
5344
5345!--  Set up thermal radiation from surfaces
5346!--  emiss_surf is defined only for surfaces for which energy balance is calculated
5347!--  Workaround: reorder surface data type back on 1D array including all surfaces,
5348!--  which implies to reorder horizontal and vertical surfaces
5349!
5350!--  Horizontal walls
5351     mm = 1
5352     DO  i = nxl, nxr
5353        DO  j = nys, nyn
5354!--           urban
5355           DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
5356              surfoutll(mm) = SUM ( surf_usm_h%frac(:,m) *                  &
5357                                    surf_usm_h%emissivity(:,m) )            &
5358                                  * sigma_sb                                &
5359                                  * surf_usm_h%pt_surface(m)**4
5360              albedo_surf(mm) = SUM ( surf_usm_h%frac(:,m) *                &
5361                                      surf_usm_h%albedo(:,m) )
5362              emiss_surf(mm)  = SUM ( surf_usm_h%frac(:,m) *                &
5363                                      surf_usm_h%emissivity(:,m) )
5364              mm = mm + 1
5365           ENDDO
5366!--           land
5367           DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
5368              surfoutll(mm) = SUM ( surf_lsm_h%frac(:,m) *                  &
5369                                    surf_lsm_h%emissivity(:,m) )            &
5370                                  * sigma_sb                                &
5371                                  * surf_lsm_h%pt_surface(m)**4
5372              albedo_surf(mm) = SUM ( surf_lsm_h%frac(:,m) *                &
5373                                      surf_lsm_h%albedo(:,m) )
5374              emiss_surf(mm)  = SUM ( surf_lsm_h%frac(:,m) *                &
5375                                      surf_lsm_h%emissivity(:,m) )
5376              mm = mm + 1
5377           ENDDO
5378        ENDDO
5379     ENDDO
5380!
5381!--     Vertical walls
5382     DO  i = nxl, nxr
5383        DO  j = nys, nyn
5384           DO  ll = 0, 3
5385              l = reorder(ll)
5386!--              urban
5387              DO  m = surf_usm_v(l)%start_index(j,i),                       &
5388                      surf_usm_v(l)%end_index(j,i)
5389                 surfoutll(mm) = SUM ( surf_usm_v(l)%frac(:,m) *            &
5390                                       surf_usm_v(l)%emissivity(:,m) )      &
5391                                  * sigma_sb                                &
5392                                  * surf_usm_v(l)%pt_surface(m)**4
5393                 albedo_surf(mm) = SUM ( surf_usm_v(l)%frac(:,m) *          &
5394                                         surf_usm_v(l)%albedo(:,m) )
5395                 emiss_surf(mm)  = SUM ( surf_usm_v(l)%frac(:,m) *          &
5396                                         surf_usm_v(l)%emissivity(:,m) )
5397                 mm = mm + 1
5398              ENDDO
5399!--              land
5400              DO  m = surf_lsm_v(l)%start_index(j,i),                       &
5401                      surf_lsm_v(l)%end_index(j,i)
5402                 surfoutll(mm) = SUM ( surf_lsm_v(l)%frac(:,m) *            &
5403                                       surf_lsm_v(l)%emissivity(:,m) )      &
5404                                  * sigma_sb                                &
5405                                  * surf_lsm_v(l)%pt_surface(m)**4
5406                 albedo_surf(mm) = SUM ( surf_lsm_v(l)%frac(:,m) *          &
5407                                         surf_lsm_v(l)%albedo(:,m) )
5408                 emiss_surf(mm)  = SUM ( surf_lsm_v(l)%frac(:,m) *          &
5409                                         surf_lsm_v(l)%emissivity(:,m) )
5410                 mm = mm + 1
5411              ENDDO
5412           ENDDO
5413        ENDDO
5414     ENDDO
5415
5416#if defined( __parallel )
5417!--     might be optimized and gather only values relevant for current processor
5418     CALL MPI_AllGatherv(surfoutll, nsurfl, MPI_REAL, &
5419                         surfoutl, nsurfs, surfstart, MPI_REAL, comm2d, ierr) !nsurf global
5420     IF ( ierr /= 0 ) THEN
5421         WRITE(9,*) 'Error MPI_AllGatherv1:', ierr, SIZE(surfoutll), nsurfl, &
5422                     SIZE(surfoutl), nsurfs, surfstart
5423         FLUSH(9)
5424     ENDIF
5425#else
5426     surfoutl(:) = surfoutll(:) !nsurf global
5427#endif
5428
5429     IF ( surface_reflections)  THEN
5430        DO  isvf = 1, nsvfl
5431           isurf = svfsurf(1, isvf)
5432           k     = surfl(iz, isurf)
5433           j     = surfl(iy, isurf)
5434           i     = surfl(ix, isurf)
5435           isurfsrc = svfsurf(2, isvf)
5436!
5437!--        For surface-to-surface factors we calculate thermal radiation in 1st pass
5438           IF ( plant_lw_interact )  THEN
5439              surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * svf(2,isvf) * surfoutl(isurfsrc)
5440           ELSE
5441              surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * surfoutl(isurfsrc)
5442           ENDIF
5443        ENDDO
5444     ENDIF
5445!
5446!--  diffuse radiation using sky view factor
5447     DO isurf = 1, nsurfl
5448        j = surfl(iy, isurf)
5449        i = surfl(ix, isurf)
5450        surfinswdif(isurf) = rad_sw_in_diff(j,i) * skyvft(isurf)
5451        IF ( plant_lw_interact )  THEN
5452           surfinlwdif(isurf) = rad_lw_in_diff(j,i) * skyvft(isurf)
5453        ELSE
5454           surfinlwdif(isurf) = rad_lw_in_diff(j,i) * skyvf(isurf)
5455        ENDIF
5456     ENDDO
5457!
5458!--  MRT diffuse irradiance
5459     DO  imrt = 1, nmrtbl
5460        j = mrtbl(iy, imrt)
5461        i = mrtbl(ix, imrt)
5462        mrtinsw(imrt) = mrtskyt(imrt) * rad_sw_in_diff(j,i)
5463        mrtinlw(imrt) = mrtsky(imrt) * rad_lw_in_diff(j,i)
5464     ENDDO
5465
5466     !-- direct radiation
5467     IF ( cos_zenith > 0 )  THEN
5468        !--Identify solar direction vector (discretized number) 1)
5469        !--
5470        j = FLOOR(ACOS(cos_zenith) / pi * raytrace_discrete_elevs)
5471        i = MODULO(NINT(ATAN2(sun_dir_lon, sun_dir_lat)               &
5472                        / (2._wp*pi) * raytrace_discrete_azims-.5_wp, iwp), &
5473                   raytrace_discrete_azims)
5474        isd = dsidir_rev(j, i)
5475!-- TODO: check if isd = -1 to report that this solar position is not precalculated
5476        DO isurf = 1, nsurfl
5477           j = surfl(iy, isurf)
5478           i = surfl(ix, isurf)
5479           surfinswdir(isurf) = rad_sw_in_dir(j,i) *                        &
5480                costheta(surfl(id, isurf)) * dsitrans(isurf, isd) / cos_zenith
5481        ENDDO
5482!
5483!--     MRT direct irradiance
5484        DO  imrt = 1, nmrtbl
5485           j = mrtbl(iy, imrt)
5486           i = mrtbl(ix, imrt)
5487           mrtinsw(imrt) = mrtinsw(imrt) + mrtdsit(imrt, isd) * rad_sw_in_dir(j,i) &
5488                                     / cos_zenith / 4._wp ! normal to sphere
5489        ENDDO
5490     ENDIF
5491!
5492!--  MRT first pass thermal
5493     DO  imrtf = 1, nmrtf
5494        imrt = mrtfsurf(1, imrtf)
5495        isurfsrc = mrtfsurf(2, imrtf)
5496        mrtinlw(imrt) = mrtinlw(imrt) + mrtf(imrtf) * surfoutl(isurfsrc)
5497     ENDDO
5498!
5499!--  Absorption in each local plant canopy grid box from the first atmospheric
5500!--  pass of radiation
5501     IF ( npcbl > 0 )  THEN
5502
5503         pcbinswdir(:) = 0._wp
5504         pcbinswdif(:) = 0._wp
5505         pcbinlw(:) = 0._wp
5506
5507         DO icsf = 1, ncsfl
5508             ipcgb = csfsurf(1, icsf)
5509             i = pcbl(ix,ipcgb)
5510             j = pcbl(iy,ipcgb)
5511             k = pcbl(iz,ipcgb)
5512             isurfsrc = csfsurf(2, icsf)
5513
5514             IF ( isurfsrc == -1 )  THEN
5515!
5516!--             Diffuse radiation from sky
5517                pcbinswdif(ipcgb) = csf(1,icsf) * rad_sw_in_diff(j,i)
5518!
5519!--             Absorbed diffuse LW radiation from sky minus emitted to sky
5520                IF ( plant_lw_interact )  THEN
5521                   pcbinlw(ipcgb) = csf(1,icsf)                                  &
5522                                       * (rad_lw_in_diff(j, i)                   &
5523                                          - sigma_sb * (pt(k,j,i)*exner(k))**4)
5524                ENDIF
5525!
5526!--             Direct solar radiation
5527                IF ( cos_zenith > 0 )  THEN
5528!--                Estimate directed box absorption
5529                   pc_abs_frac = 1._wp - exp(pc_abs_eff * lad_s(k,j,i))
5530!
5531!--                isd has already been established, see 1)
5532                   pcbinswdir(ipcgb) = rad_sw_in_dir(j, i) * pc_box_area &
5533                                       * pc_abs_frac * dsitransc(ipcgb, isd)
5534                ENDIF
5535             ELSE
5536                IF ( plant_lw_interact )  THEN
5537!
5538!--                Thermal emission from plan canopy towards respective face
5539                   pcrad = sigma_sb * (pt(k,j,i) * exner(k))**4 * csf(1,icsf)
5540                   surfinlg(isurfsrc) = surfinlg(isurfsrc) + pcrad
5541!
5542!--                Remove the flux above + absorb LW from first pass from surfaces
5543                   asrc = facearea(surf(id, isurfsrc))
5544                   pcbinlw(ipcgb) = pcbinlw(ipcgb)                      &
5545                                    + (csf(1,icsf) * surfoutl(isurfsrc) & ! Absorb from first pass surf emit
5546                                       - pcrad)                         & ! Remove emitted heatflux
5547                                    * asrc
5548                ENDIF
5549             ENDIF
5550         ENDDO
5551
5552         pcbinsw(:) = pcbinswdir(:) + pcbinswdif(:)
5553     ENDIF
5554
5555     IF ( plant_lw_interact )  THEN
5556!
5557!--     Exchange incoming lw radiation from plant canopy
5558#if defined( __parallel )
5559        CALL MPI_Allreduce(MPI_IN_PLACE, surfinlg, nsurf, MPI_REAL, MPI_SUM, comm2d, ierr)
5560        IF ( ierr /= 0 )  THEN
5561           WRITE (9,*) 'Error MPI_Allreduce:', ierr
5562           FLUSH(9)
5563        ENDIF
5564        surfinl(:) = surfinl(:) + surfinlg(surfstart(myid)+1:surfstart(myid+1))
5565#else
5566        surfinl(:) = surfinl(:) + surfinlg(:)
5567#endif
5568     ENDIF
5569
5570     surfins = surfinswdir + surfinswdif
5571     surfinl = surfinl + surfinlwdif
5572     surfinsw = surfins
5573     surfinlw = surfinl
5574     surfoutsw = 0.0_wp
5575     surfoutlw = surfoutll
5576     surfemitlwl = surfoutll
5577
5578     IF ( .NOT.  surface_reflections )  THEN
5579!
5580!--     Set nrefsteps to 0 to disable reflections       
5581        nrefsteps = 0
5582        surfoutsl = albedo_surf * surfins
5583        surfoutll = (1._wp - emiss_surf) * surfinl
5584        surfoutsw = surfoutsw + surfoutsl
5585        surfoutlw = surfoutlw + surfoutll
5586     ENDIF
5587
5588!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5589!--     Next passes - reflections
5590!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5591     DO refstep = 1, nrefsteps
5592
5593         surfoutsl = albedo_surf * surfins
5594!
5595!--      for non-transparent surfaces, longwave albedo is 1 - emissivity
5596         surfoutll = (1._wp - emiss_surf) * surfinl
5597
5598#if defined( __parallel )
5599         CALL MPI_AllGatherv(surfoutsl, nsurfl, MPI_REAL, &
5600             surfouts, nsurfs, surfstart, MPI_REAL, comm2d, ierr)
5601         IF ( ierr /= 0 )  THEN
5602             WRITE(9,*) 'Error MPI_AllGatherv2:', ierr, SIZE(surfoutsl), nsurfl, &
5603                        SIZE(surfouts), nsurfs, surfstart
5604             FLUSH(9)
5605         ENDIF
5606
5607         CALL MPI_AllGatherv(surfoutll, nsurfl, MPI_REAL, &
5608             surfoutl, nsurfs, surfstart, MPI_REAL, comm2d, ierr)
5609         IF ( ierr /= 0 )  THEN
5610             WRITE(9,*) 'Error MPI_AllGatherv3:', ierr, SIZE(surfoutll), nsurfl, &
5611                        SIZE(surfoutl), nsurfs, surfstart
5612             FLUSH(9)
5613         ENDIF
5614
5615#else
5616         surfouts = surfoutsl
5617         surfoutl = surfoutll
5618#endif
5619!
5620!--      Reset for the input from next reflective pass
5621         surfins = 0._wp
5622         surfinl = 0._wp
5623!
5624!--      Reflected radiation
5625         DO isvf = 1, nsvfl
5626             isurf = svfsurf(1, isvf)
5627             isurfsrc = svfsurf(2, isvf)
5628             surfins(isurf) = surfins(isurf) + svf(1,isvf) * svf(2,isvf) * surfouts(isurfsrc)
5629             IF ( plant_lw_interact )  THEN
5630                surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * svf(2,isvf) * surfoutl(isurfsrc)
5631             ELSE
5632                surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * surfoutl(isurfsrc)
5633             ENDIF
5634         ENDDO
5635!
5636!--      NOTE: PC absorbtion and MRT from reflected can both be done at once
5637!--      after all reflections if we do one more MPI_ALLGATHERV on surfout.
5638!--      Advantage: less local computation. Disadvantage: one more collective
5639!--      MPI call.
5640!
5641!--      Radiation absorbed by plant canopy
5642         DO  icsf = 1, ncsfl
5643             ipcgb = csfsurf(1, icsf)
5644             isurfsrc = csfsurf(2, icsf)
5645             IF ( isurfsrc == -1 )  CYCLE ! sky->face only in 1st pass, not here
5646!
5647!--          Calculate source surface area. If the `surf' array is removed
5648!--          before timestepping starts (future version), then asrc must be
5649!--          stored within `csf'
5650             asrc = facearea(surf(id, isurfsrc))
5651             pcbinsw(ipcgb) = pcbinsw(ipcgb) + csf(1,icsf) * surfouts(isurfsrc) * asrc
5652             IF ( plant_lw_interact )  THEN
5653                pcbinlw(ipcgb) = pcbinlw(ipcgb) + csf(1,icsf) * surfoutl(isurfsrc) * asrc
5654             ENDIF
5655         ENDDO
5656!
5657!--      MRT reflected
5658         DO  imrtf = 1, nmrtf
5659            imrt = mrtfsurf(1, imrtf)
5660            isurfsrc = mrtfsurf(2, imrtf)
5661            mrtinsw(imrt) = mrtinsw(imrt) + mrtft(imrtf) * surfouts(isurfsrc)
5662            mrtinlw(imrt) = mrtinlw(imrt) + mrtf(imrtf) * surfoutl(isurfsrc)
5663         ENDDO
5664
5665         surfinsw = surfinsw  + surfins
5666         surfinlw = surfinlw  + surfinl
5667         surfoutsw = surfoutsw + surfoutsl
5668         surfoutlw = surfoutlw + surfoutll
5669
5670     ENDDO ! refstep
5671
5672!--  push heat flux absorbed by plant canopy to respective 3D arrays
5673     IF ( npcbl > 0 )  THEN
5674         pc_heating_rate(:,:,:) = 0.0_wp
5675         DO ipcgb = 1, npcbl
5676             j = pcbl(iy, ipcgb)
5677             i = pcbl(ix, ipcgb)
5678             k = pcbl(iz, ipcgb)
5679!
5680!--          Following expression equals former kk = k - nzb_s_inner(j,i)
5681             kk = k - get_topography_top_index_ji( j, i, 's' )  !- lad arrays are defined flat
5682             pc_heating_rate(kk, j, i) = (pcbinsw(ipcgb) + pcbinlw(ipcgb)) &
5683                 * pchf_prep(k) * pt(k, j, i) !-- = dT/dt
5684         ENDDO
5685
5686         IF ( humidity .AND. plant_canopy_transpiration ) THEN
5687!--          Calculation of plant canopy transpiration rate and correspondidng latent heat rate
5688             pc_transpiration_rate(:,:,:) = 0.0_wp
5689             pc_latent_rate(:,:,:) = 0.0_wp
5690             DO ipcgb = 1, npcbl
5691                 i = pcbl(ix, ipcgb)
5692                 j = pcbl(iy, ipcgb)
5693                 k = pcbl(iz, ipcgb)
5694                 kk = k - get_topography_top_index_ji( j, i, 's' )  !- lad arrays are defined flat
5695                 CALL pcm_calc_transpiration_rate( i, j, k, kk, pcbinsw(ipcgb), pcbinlw(ipcgb), &
5696                                                   pc_transpiration_rate(kk,j,i), pc_latent_rate(kk,j,i) )
5697              ENDDO
5698         ENDIF
5699     ENDIF
5700!
5701!--  Calculate black body MRT (after all reflections)
5702     IF ( nmrtbl > 0 )  THEN
5703        IF ( mrt_include_sw )  THEN
5704           mrt(:) = ((mrtinsw(:) + mrtinlw(:)) / sigma_sb) ** .25_wp
5705        ELSE
5706           mrt(:) = (mrtinlw(:) / sigma_sb) ** .25_wp
5707        ENDIF
5708     ENDIF
5709!
5710!--     Transfer radiation arrays required for energy balance to the respective data types
5711     DO  i = 1, nsurfl
5712        m  = surfl(im,i)
5713!
5714!--     (1) Urban surfaces
5715!--     upward-facing
5716        IF ( surfl(1,i) == iup_u )  THEN
5717           surf_usm_h%rad_sw_in(m)  = surfinsw(i)
5718           surf_usm_h%rad_sw_out(m) = surfoutsw(i)
5719           surf_usm_h%rad_sw_dir(m) = surfinswdir(i)
5720           surf_usm_h%rad_sw_dif(m) = surfinswdif(i)
5721           surf_usm_h%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -        &
5722                                      surfinswdif(i)
5723           surf_usm_h%rad_sw_res(m) = surfins(i)
5724           surf_usm_h%rad_lw_in(m)  = surfinlw(i)
5725           surf_usm_h%rad_lw_out(m) = surfoutlw(i)
5726           surf_usm_h%rad_net(m)    = surfinsw(i) - surfoutsw(i) +          &
5727                                      surfinlw(i) - surfoutlw(i)
5728           surf_usm_h%rad_net_l(m)  = surf_usm_h%rad_net(m)
5729           surf_usm_h%rad_lw_dif(m) = surfinlwdif(i)
5730           surf_usm_h%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5731           surf_usm_h%rad_lw_res(m) = surfinl(i)
5732!
5733!--     northward-facding
5734        ELSEIF ( surfl(1,i) == inorth_u )  THEN
5735           surf_usm_v(0)%rad_sw_in(m)  = surfinsw(i)
5736           surf_usm_v(0)%rad_sw_out(m) = surfoutsw(i)
5737           surf_usm_v(0)%rad_sw_dir(m) = surfinswdir(i)
5738           surf_usm_v(0)%rad_sw_dif(m) = surfinswdif(i)
5739           surf_usm_v(0)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5740                                         surfinswdif(i)
5741           surf_usm_v(0)%rad_sw_res(m) = surfins(i)
5742           surf_usm_v(0)%rad_lw_in(m)  = surfinlw(i)
5743           surf_usm_v(0)%rad_lw_out(m) = surfoutlw(i)
5744           surf_usm_v(0)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5745                                         surfinlw(i) - surfoutlw(i)
5746           surf_usm_v(0)%rad_net_l(m)  = surf_usm_v(0)%rad_net(m)
5747           surf_usm_v(0)%rad_lw_dif(m) = surfinlwdif(i)
5748           surf_usm_v(0)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5749           surf_usm_v(0)%rad_lw_res(m) = surfinl(i)
5750!
5751!--     southward-facding
5752        ELSEIF ( surfl(1,i) == isouth_u )  THEN
5753           surf_usm_v(1)%rad_sw_in(m)  = surfinsw(i)
5754           surf_usm_v(1)%rad_sw_out(m) = surfoutsw(i)
5755           surf_usm_v(1)%rad_sw_dir(m) = surfinswdir(i)
5756           surf_usm_v(1)%rad_sw_dif(m) = surfinswdif(i)
5757           surf_usm_v(1)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5758                                         surfinswdif(i)
5759           surf_usm_v(1)%rad_sw_res(m) = surfins(i)
5760           surf_usm_v(1)%rad_lw_in(m)  = surfinlw(i)
5761           surf_usm_v(1)%rad_lw_out(m) = surfoutlw(i)
5762           surf_usm_v(1)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5763                                         surfinlw(i) - surfoutlw(i)
5764           surf_usm_v(1)%rad_net_l(m)  = surf_usm_v(1)%rad_net(m)
5765           surf_usm_v(1)%rad_lw_dif(m) = surfinlwdif(i)
5766           surf_usm_v(1)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5767           surf_usm_v(1)%rad_lw_res(m) = surfinl(i)
5768!
5769!--     eastward-facing
5770        ELSEIF ( surfl(1,i) == ieast_u )  THEN
5771           surf_usm_v(2)%rad_sw_in(m)  = surfinsw(i)
5772           surf_usm_v(2)%rad_sw_out(m) = surfoutsw(i)
5773           surf_usm_v(2)%rad_sw_dir(m) = surfinswdir(i)
5774           surf_usm_v(2)%rad_sw_dif(m) = surfinswdif(i)
5775           surf_usm_v(2)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5776                                         surfinswdif(i)
5777           surf_usm_v(2)%rad_sw_res(m) = surfins(i)
5778           surf_usm_v(2)%rad_lw_in(m)  = surfinlw(i)
5779           surf_usm_v(2)%rad_lw_out(m) = surfoutlw(i)
5780           surf_usm_v(2)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5781                                         surfinlw(i) - surfoutlw(i)
5782           surf_usm_v(2)%rad_net_l(m)  = surf_usm_v(2)%rad_net(m)
5783           surf_usm_v(2)%rad_lw_dif(m) = surfinlwdif(i)
5784           surf_usm_v(2)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5785           surf_usm_v(2)%rad_lw_res(m) = surfinl(i)
5786!
5787!--     westward-facding
5788        ELSEIF ( surfl(1,i) == iwest_u )  THEN
5789           surf_usm_v(3)%rad_sw_in(m)  = surfinsw(i)
5790           surf_usm_v(3)%rad_sw_out(m) = surfoutsw(i)
5791           surf_usm_v(3)%rad_sw_dir(m) = surfinswdir(i)
5792           surf_usm_v(3)%rad_sw_dif(m) = surfinswdif(i)
5793           surf_usm_v(3)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5794                                         surfinswdif(i)
5795           surf_usm_v(3)%rad_sw_res(m) = surfins(i)
5796           surf_usm_v(3)%rad_lw_in(m)  = surfinlw(i)
5797           surf_usm_v(3)%rad_lw_out(m) = surfoutlw(i)
5798           surf_usm_v(3)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5799                                         surfinlw(i) - surfoutlw(i)
5800           surf_usm_v(3)%rad_net_l(m)  = surf_usm_v(3)%rad_net(m)
5801           surf_usm_v(3)%rad_lw_dif(m) = surfinlwdif(i)
5802           surf_usm_v(3)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5803           surf_usm_v(3)%rad_lw_res(m) = surfinl(i)
5804!
5805!--     (2) land surfaces
5806!--     upward-facing
5807        ELSEIF ( surfl(1,i) == iup_l )  THEN
5808           surf_lsm_h%rad_sw_in(m)  = surfinsw(i)
5809           surf_lsm_h%rad_sw_out(m) = surfoutsw(i)
5810           surf_lsm_h%rad_sw_dir(m) = surfinswdir(i)
5811           surf_lsm_h%rad_sw_dif(m) = surfinswdif(i)
5812           surf_lsm_h%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -        &
5813                                         surfinswdif(i)
5814           surf_lsm_h%rad_sw_res(m) = surfins(i)
5815           surf_lsm_h%rad_lw_in(m)  = surfinlw(i)
5816           surf_lsm_h%rad_lw_out(m) = surfoutlw(i)
5817           surf_lsm_h%rad_net(m)    = surfinsw(i) - surfoutsw(i) +          &
5818                                      surfinlw(i) - surfoutlw(i)
5819           surf_lsm_h%rad_lw_dif(m) = surfinlwdif(i)
5820           surf_lsm_h%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5821           surf_lsm_h%rad_lw_res(m) = surfinl(i)
5822!
5823!--     northward-facding
5824        ELSEIF ( surfl(1,i) == inorth_l )  THEN
5825           surf_lsm_v(0)%rad_sw_in(m)  = surfinsw(i)
5826           surf_lsm_v(0)%rad_sw_out(m) = surfoutsw(i)
5827           surf_lsm_v(0)%rad_sw_dir(m) = surfinswdir(i)
5828           surf_lsm_v(0)%rad_sw_dif(m) = surfinswdif(i)
5829           surf_lsm_v(0)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5830                                         surfinswdif(i)
5831           surf_lsm_v(0)%rad_sw_res(m) = surfins(i)
5832           surf_lsm_v(0)%rad_lw_in(m)  = surfinlw(i)
5833           surf_lsm_v(0)%rad_lw_out(m) = surfoutlw(i)
5834           surf_lsm_v(0)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5835                                         surfinlw(i) - surfoutlw(i)
5836           surf_lsm_v(0)%rad_lw_dif(m) = surfinlwdif(i)
5837           surf_lsm_v(0)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5838           surf_lsm_v(0)%rad_lw_res(m) = surfinl(i)
5839!
5840!--     southward-facding
5841        ELSEIF ( surfl(1,i) == isouth_l )  THEN
5842           surf_lsm_v(1)%rad_sw_in(m)  = surfinsw(i)
5843           surf_lsm_v(1)%rad_sw_out(m) = surfoutsw(i)
5844           surf_lsm_v(1)%rad_sw_dir(m) = surfinswdir(i)
5845           surf_lsm_v(1)%rad_sw_dif(m) = surfinswdif(i)
5846           surf_lsm_v(1)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5847                                         surfinswdif(i)
5848           surf_lsm_v(1)%rad_sw_res(m) = surfins(i)
5849           surf_lsm_v(1)%rad_lw_in(m)  = surfinlw(i)
5850           surf_lsm_v(1)%rad_lw_out(m) = surfoutlw(i)
5851           surf_lsm_v(1)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5852                                         surfinlw(i) - surfoutlw(i)
5853           surf_lsm_v(1)%rad_lw_dif(m) = surfinlwdif(i)
5854           surf_lsm_v(1)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5855           surf_lsm_v(1)%rad_lw_res(m) = surfinl(i)
5856!
5857!--     eastward-facing
5858        ELSEIF ( surfl(1,i) == ieast_l )  THEN
5859           surf_lsm_v(2)%rad_sw_in(m)  = surfinsw(i)
5860           surf_lsm_v(2)%rad_sw_out(m) = surfoutsw(i)
5861           surf_lsm_v(2)%rad_sw_dir(m) = surfinswdir(i)
5862           surf_lsm_v(2)%rad_sw_dif(m) = surfinswdif(i)
5863           surf_lsm_v(2)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5864                                         surfinswdif(i)
5865           surf_lsm_v(2)%rad_sw_res(m) = surfins(i)
5866           surf_lsm_v(2)%rad_lw_in(m)  = surfinlw(i)
5867           surf_lsm_v(2)%rad_lw_out(m) = surfoutlw(i)
5868           surf_lsm_v(2)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5869                                         surfinlw(i) - surfoutlw(i)
5870           surf_lsm_v(2)%rad_lw_dif(m) = surfinlwdif(i)
5871           surf_lsm_v(2)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5872           surf_lsm_v(2)%rad_lw_res(m) = surfinl(i)
5873!
5874!--     westward-facing
5875        ELSEIF ( surfl(1,i) == iwest_l )  THEN
5876           surf_lsm_v(3)%rad_sw_in(m)  = surfinsw(i)
5877           surf_lsm_v(3)%rad_sw_out(m) = surfoutsw(i)
5878           surf_lsm_v(3)%rad_sw_dir(m) = surfinswdir(i)
5879           surf_lsm_v(3)%rad_sw_dif(m) = surfinswdif(i)
5880           surf_lsm_v(3)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5881                                         surfinswdif(i)
5882           surf_lsm_v(3)%rad_sw_res(m) = surfins(i)
5883           surf_lsm_v(3)%rad_lw_in(m)  = surfinlw(i)
5884           surf_lsm_v(3)%rad_lw_out(m) = surfoutlw(i)
5885           surf_lsm_v(3)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5886                                         surfinlw(i) - surfoutlw(i)
5887           surf_lsm_v(3)%rad_lw_dif(m) = surfinlwdif(i)
5888           surf_lsm_v(3)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5889           surf_lsm_v(3)%rad_lw_res(m) = surfinl(i)
5890        ENDIF
5891
5892     ENDDO
5893
5894     DO  m = 1, surf_usm_h%ns
5895        surf_usm_h%surfhf(m) = surf_usm_h%rad_sw_in(m)  +                   &
5896                               surf_usm_h%rad_lw_in(m)  -                   &
5897                               surf_usm_h%rad_sw_out(m) -                   &
5898                               surf_usm_h%rad_lw_out(m)
5899     ENDDO
5900     DO  m = 1, surf_lsm_h%ns
5901        surf_lsm_h%surfhf(m) = surf_lsm_h%rad_sw_in(m)  +                   &
5902                               surf_lsm_h%rad_lw_in(m)  -                   &
5903                               surf_lsm_h%rad_sw_out(m) -                   &
5904                               surf_lsm_h%rad_lw_out(m)
5905     ENDDO
5906
5907     DO  l = 0, 3
5908!--     urban
5909        DO  m = 1, surf_usm_v(l)%ns
5910           surf_usm_v(l)%surfhf(m) = surf_usm_v(l)%rad_sw_in(m)  +          &
5911                                     surf_usm_v(l)%rad_lw_in(m)  -          &
5912                                     surf_usm_v(l)%rad_sw_out(m) -          &
5913                                     surf_usm_v(l)%rad_lw_out(m)
5914        ENDDO
5915!--     land
5916        DO  m = 1, surf_lsm_v(l)%ns
5917           surf_lsm_v(l)%surfhf(m) = surf_lsm_v(l)%rad_sw_in(m)  +          &
5918                                     surf_lsm_v(l)%rad_lw_in(m)  -          &
5919                                     surf_lsm_v(l)%rad_sw_out(m) -          &
5920                                     surf_lsm_v(l)%rad_lw_out(m)
5921
5922        ENDDO
5923     ENDDO
5924!
5925!--  Calculate the average temperature, albedo, and emissivity for urban/land
5926!--  domain when using average_radiation in the respective radiation model
5927
5928!--  calculate horizontal area
5929! !!! ATTENTION!!! uniform grid is assumed here
5930     area_hor = (nx+1) * (ny+1) * dx * dy
5931!
5932!--  absorbed/received SW & LW and emitted LW energy of all physical
5933!--  surfaces (land and urban) in local processor
5934     pinswl = 0._wp
5935     pinlwl = 0._wp
5936     pabsswl = 0._wp
5937     pabslwl = 0._wp
5938     pemitlwl = 0._wp
5939     emiss_sum_surfl = 0._wp
5940     area_surfl = 0._wp
5941     DO  i = 1, nsurfl
5942        d = surfl(id, i)
5943!--  received SW & LW
5944        pinswl = pinswl + (surfinswdir(i) + surfinswdif(i)) * facearea(d)
5945        pinlwl = pinlwl + surfinlwdif(i) * facearea(d)
5946!--   absorbed SW & LW
5947        pabsswl = pabsswl + (1._wp - albedo_surf(i)) *                   &
5948                                                surfinsw(i) * facearea(d)
5949        pabslwl = pabslwl + emiss_surf(i) * surfinlw(i) * facearea(d)
5950!--   emitted LW
5951        pemitlwl = pemitlwl + surfemitlwl(i) * facearea(d)
5952!--   emissivity and area sum
5953        emiss_sum_surfl = emiss_sum_surfl + emiss_surf(i) * facearea(d)
5954        area_surfl = area_surfl + facearea(d)
5955     END DO
5956!
5957!--  add the absorbed SW energy by plant canopy
5958     IF ( npcbl > 0 )  THEN
5959        pabsswl = pabsswl + SUM(pcbinsw)
5960        pabslwl = pabslwl + SUM(pcbinlw)
5961        pinswl = pinswl + SUM(pcbinswdir) + SUM(pcbinswdif)
5962     ENDIF
5963!
5964!--  gather all rad flux energy in all processors
5965#if defined( __parallel )
5966     CALL MPI_ALLREDUCE( pinswl, pinsw, 1, MPI_REAL, MPI_SUM, comm2d, ierr)
5967     IF ( ierr /= 0 ) THEN
5968         WRITE(9,*) 'Error MPI_AllReduce5:', ierr, pinswl, pinsw
5969         FLUSH(9)
5970     ENDIF
5971     CALL MPI_ALLREDUCE( pinlwl, pinlw, 1, MPI_REAL, MPI_SUM, comm2d, ierr)
5972     IF ( ierr /= 0 ) THEN
5973         WRITE(9,*) 'Error MPI_AllReduce6:', ierr, pinlwl, pinlw
5974         FLUSH(9)
5975     ENDIF
5976     CALL MPI_ALLREDUCE( pabsswl, pabssw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5977     IF ( ierr /= 0 ) THEN
5978         WRITE(9,*) 'Error MPI_AllReduce7:', ierr, pabsswl, pabssw
5979         FLUSH(9)
5980     ENDIF
5981     CALL MPI_ALLREDUCE( pabslwl, pabslw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5982     IF ( ierr /= 0 ) THEN
5983         WRITE(9,*) 'Error MPI_AllReduce8:', ierr, pabslwl, pabslw
5984         FLUSH(9)
5985     ENDIF
5986     CALL MPI_ALLREDUCE( pemitlwl, pemitlw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5987     IF ( ierr /= 0 ) THEN
5988         WRITE(9,*) 'Error MPI_AllReduce8:', ierr, pemitlwl, pemitlw
5989         FLUSH(9)
5990     ENDIF
5991     CALL MPI_ALLREDUCE( emiss_sum_surfl, emiss_sum_surf, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5992     IF ( ierr /= 0 ) THEN
5993         WRITE(9,*) 'Error MPI_AllReduce9:', ierr, emiss_sum_surfl, emiss_sum_surf
5994         FLUSH(9)
5995     ENDIF
5996     CALL MPI_ALLREDUCE( area_surfl, area_surf, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5997     IF ( ierr /= 0 ) THEN
5998         WRITE(9,*) 'Error MPI_AllReduce10:', ierr, area_surfl, area_surf
5999         FLUSH(9)
6000     ENDIF
6001#else
6002     pinsw = pinswl
6003     pinlw = pinlwl
6004     pabssw = pabsswl
6005     pabslw = pabslwl
6006     pemitlw = pemitlwl
6007     emiss_sum_surf = emiss_sum_surfl
6008     area_surf = area_surfl
6009#endif
6010
6011!--  (1) albedo
6012     IF ( pinsw /= 0.0_wp )  &
6013          albedo_urb = (pinsw - pabssw) / pinsw
6014!--  (2) average emmsivity
6015     IF ( area_surf /= 0.0_wp ) &
6016          emissivity_urb = emiss_sum_surf / area_surf
6017!
6018!--  Temporally comment out calculation of effective radiative temperature.
6019!--  See below for more explanation.
6020!--  (3) temperature
6021!--   first we calculate an effective horizontal area to account for
6022!--   the effect of vertical surfaces (which contributes to LW emission)
6023!--   We simply use the ratio of the total LW to the incoming LW flux
6024      area_hor = pinlw/rad_lw_in_diff(nyn,nxl)
6025      t_rad_urb = ( (pemitlw - pabslw + emissivity_urb*pinlw) / &
6026           (emissivity_urb*sigma_sb * area_hor) )**0.25_wp
6027
6028     IF ( debug_output_timestep )  CALL debug_message( 'radiation_interaction', 'end' )
6029
6030
6031    CONTAINS
6032
6033!------------------------------------------------------------------------------!
6034!> Calculates radiation absorbed by box with given size and LAD.
6035!>
6036!> Simulates resol**2 rays (by equally spacing a bounding horizontal square
6037!> conatining all possible rays that would cross the box) and calculates
6038!> average transparency per ray. Returns fraction of absorbed radiation flux
6039!> and area for which this fraction is effective.
6040!------------------------------------------------------------------------------!
6041    PURE SUBROUTINE box_absorb(boxsize, resol, dens, uvec, area, absorb)
6042       IMPLICIT NONE
6043
6044       REAL(wp), DIMENSION(3), INTENT(in) :: &
6045            boxsize, &      !< z, y, x size of box in m
6046            uvec            !< z, y, x unit vector of incoming flux
6047       INTEGER(iwp), INTENT(in) :: &
6048            resol           !< No. of rays in x and y dimensions
6049       REAL(wp), INTENT(in) :: &
6050            dens            !< box density (e.g. Leaf Area Density)
6051       REAL(wp), INTENT(out) :: &
6052            area, &         !< horizontal area for flux absorbtion
6053            absorb          !< fraction of absorbed flux
6054       REAL(wp) :: &
6055            xshift, yshift, &
6056            xmin, xmax, ymin, ymax, &
6057            xorig, yorig, &
6058            dx1, dy1, dz1, dx2, dy2, dz2, &
6059            crdist, &
6060            transp
6061       INTEGER(iwp) :: &
6062            i, j
6063
6064       xshift = uvec(3) / uvec(1) * boxsize(1)
6065       xmin = min(0._wp, -xshift)
6066       xmax = boxsize(3) + max(0._wp, -xshift)
6067       yshift = uvec(2) / uvec(1) * boxsize(1)
6068       ymin = min(0._wp, -yshift)
6069       ymax = boxsize(2) + max(0._wp, -yshift)
6070
6071       transp = 0._wp
6072       DO i = 1, resol
6073          xorig = xmin + (xmax-xmin) * (i-.5_wp) / resol
6074          DO j = 1, resol
6075             yorig = ymin + (ymax-ymin) * (j-.5_wp) / resol
6076
6077             dz1 = 0._wp
6078             dz2 = boxsize(1)/uvec(1)
6079
6080             IF ( uvec(2) > 0._wp )  THEN
6081                dy1 = -yorig             / uvec(2) !< crossing with y=0
6082                dy2 = (boxsize(2)-yorig) / uvec(2) !< crossing with y=boxsize(2)
6083             ELSE !uvec(2)==0
6084                dy1 = -huge(1._wp)
6085                dy2 = huge(1._wp)
6086             ENDIF
6087
6088             IF ( uvec(3) > 0._wp )  THEN
6089                dx1 = -xorig             / uvec(3) !< crossing with x=0
6090                dx2 = (boxsize(3)-xorig) / uvec(3) !< crossing with x=boxsize(3)
6091             ELSE !uvec(3)==0
6092                dx1 = -huge(1._wp)
6093                dx2 = huge(1._wp)
6094             ENDIF
6095
6096             crdist = max(0._wp, (min(dz2, dy2, dx2) - max(dz1, dy1, dx1)))
6097             transp = transp + exp(-ext_coef * dens * crdist)
6098          ENDDO
6099       ENDDO
6100       transp = transp / resol**2
6101       area = (boxsize(3)+xshift)*(boxsize(2)+yshift)
6102       absorb = 1._wp - transp
6103
6104    END SUBROUTINE box_absorb
6105
6106!------------------------------------------------------------------------------!
6107! Description:
6108! ------------
6109!> This subroutine splits direct and diffusion dw radiation
6110!> It sould not be called in case the radiation model already does it
6111!> It follows Boland, Ridley & Brown (2008)
6112!------------------------------------------------------------------------------!
6113    SUBROUTINE calc_diffusion_radiation 
6114   
6115        REAL(wp), PARAMETER                          :: lowest_solarUp = 0.1_wp  !< limit the sun elevation to protect stability of the calculation
6116        INTEGER(iwp)                                 :: i, j
6117        REAL(wp)                                     ::  year_angle              !< angle
6118        REAL(wp)                                     ::  etr                     !< extraterestrial radiation
6119        REAL(wp)                                     ::  corrected_solarUp       !< corrected solar up radiation
6120        REAL(wp)                                     ::  horizontalETR           !< horizontal extraterestrial radiation
6121        REAL(wp)                                     ::  clearnessIndex          !< clearness index
6122        REAL(wp)                                     ::  diff_frac               !< diffusion fraction of the radiation
6123
6124       
6125!--     Calculate current day and time based on the initial values and simulation time
6126        year_angle = ( (day_of_year_init * 86400) + time_utc_init              &
6127                        + time_since_reference_point )  * d_seconds_year       &
6128                        * 2.0_wp * pi
6129       
6130        etr = solar_constant * (1.00011_wp +                                   &
6131                          0.034221_wp * cos(year_angle) +                      &
6132                          0.001280_wp * sin(year_angle) +                      &
6133                          0.000719_wp * cos(2.0_wp * year_angle) +             &
6134                          0.000077_wp * sin(2.0_wp * year_angle))
6135       
6136!--   
6137!--     Under a very low angle, we keep extraterestrial radiation at
6138!--     the last small value, therefore the clearness index will be pushed
6139!--     towards 0 while keeping full continuity.
6140!--   
6141        IF ( cos_zenith <= lowest_solarUp )  THEN
6142            corrected_solarUp = lowest_solarUp
6143        ELSE
6144            corrected_solarUp = cos_zenith
6145        ENDIF
6146       
6147        horizontalETR = etr * corrected_solarUp
6148       
6149        DO i = nxl, nxr
6150            DO j = nys, nyn
6151                clearnessIndex = rad_sw_in(0,j,i) / horizontalETR
6152                diff_frac = 1.0_wp / (1.0_wp + exp(-5.0033_wp + 8.6025_wp * clearnessIndex))
6153                rad_sw_in_diff(j,i) = rad_sw_in(0,j,i) * diff_frac
6154                rad_sw_in_dir(j,i)  = rad_sw_in(0,j,i) * (1.0_wp - diff_frac)
6155                rad_lw_in_diff(j,i) = rad_lw_in(0,j,i)
6156            ENDDO
6157        ENDDO
6158       
6159    END SUBROUTINE calc_diffusion_radiation
6160
6161 END SUBROUTINE radiation_interaction
6162   
6163!------------------------------------------------------------------------------!
6164! Description:
6165! ------------
6166!> This subroutine initializes structures needed for radiative transfer
6167!> model. This model calculates transformation processes of the
6168!> radiation inside urban and land canopy layer. The module includes also
6169!> the interaction of the radiation with the resolved plant canopy.
6170!>
6171!> For more info. see Resler et al. 2017
6172!>
6173!> The new version 2.0 was radically rewriten, the discretization scheme
6174!> has been changed. This new version significantly improves effectivity
6175!> of the paralelization and the scalability of the model.
6176!>
6177!------------------------------------------------------------------------------!
6178    SUBROUTINE radiation_interaction_init
6179
6180       USE control_parameters,                                                 &
6181           ONLY:  dz_stretch_level_start
6182
6183       USE plant_canopy_model_mod,                                             &
6184           ONLY:  lad_s
6185
6186       IMPLICIT NONE
6187
6188       INTEGER(iwp) :: i, j, k, l, m, d
6189       INTEGER(iwp) :: k_topo     !< vertical index indicating topography top for given (j,i)
6190       INTEGER(iwp) :: nzptl, nzubl, nzutl, isurf, ipcgb, imrt
6191       REAL(wp)     :: mrl
6192#if defined( __parallel )
6193       INTEGER(iwp), DIMENSION(:), POINTER, SAVE ::  gridsurf_rma   !< fortran pointer, but lower bounds are 1
6194       TYPE(c_ptr)                               ::  gridsurf_rma_p !< allocated c pointer
6195       INTEGER(iwp)                              ::  minfo          !< MPI RMA window info handle
6196#endif
6197
6198!
6199!--     precalculate face areas for different face directions using normal vector
6200        DO d = 0, nsurf_type
6201            facearea(d) = 1._wp
6202            IF ( idir(d) == 0 ) facearea(d) = facearea(d) * dx
6203            IF ( jdir(d) == 0 ) facearea(d) = facearea(d) * dy
6204            IF ( kdir(d) == 0 ) facearea(d) = facearea(d) * dz(1)
6205        ENDDO
6206!
6207!--    Find nz_urban_b, nz_urban_t, nz_urban via wall_flag_0 array (nzb_s_inner will be
6208!--    removed later). The following contruct finds the lowest / largest index
6209!--    for any upward-facing wall (see bit 12).
6210       nzubl = MINVAL( get_topography_top_index( 's' ) )
6211       nzutl = MAXVAL( get_topography_top_index( 's' ) )
6212
6213       nzubl = MAX( nzubl, nzb )
6214
6215       IF ( plant_canopy )  THEN
6216!--        allocate needed arrays
6217           ALLOCATE( pct(nys:nyn,nxl:nxr) )
6218           ALLOCATE( pch(nys:nyn,nxl:nxr) )
6219
6220!--        calculate plant canopy height
6221           npcbl = 0
6222           pct   = 0
6223           pch   = 0
6224           DO i = nxl, nxr
6225               DO j = nys, nyn
6226!
6227!--                Find topography top index
6228                   k_topo = get_topography_top_index_ji( j, i, 's' )
6229
6230                   DO k = nzt+1, 0, -1
6231                       IF ( lad_s(k,j,i) /= 0.0_wp )  THEN
6232!--                        we are at the top of the pcs
6233                           pct(j,i) = k + k_topo
6234                           pch(j,i) = k
6235                           npcbl = npcbl + pch(j,i)
6236                           EXIT
6237                       ENDIF
6238                   ENDDO
6239               ENDDO
6240           ENDDO
6241
6242           nzutl = MAX( nzutl, MAXVAL( pct ) )
6243           nzptl = MAXVAL( pct )
6244
6245           prototype_lad = MAXVAL( lad_s ) * .9_wp  !< better be *1.0 if lad is either 0 or maxval(lad) everywhere
6246           IF ( prototype_lad <= 0._wp ) prototype_lad = .3_wp
6247           !WRITE(message_string, '(a,f6.3)') 'Precomputing effective box optical ' &
6248           !    // 'depth using prototype leaf area density = ', prototype_lad
6249           !CALL message('radiation_interaction_init', 'PA0520', 0, 0, -1, 6, 0)
6250       ENDIF
6251
6252       nzutl = MIN( nzutl + nzut_free, nzt )
6253
6254#if defined( __parallel )
6255       CALL MPI_AllReduce(nzubl, nz_urban_b, 1, MPI_INTEGER, MPI_MIN, comm2d, ierr )
6256       IF ( ierr /= 0 ) THEN
6257           WRITE(9,*) 'Error MPI_AllReduce11:', ierr, nzubl, nz_urban_b
6258           FLUSH(9)
6259       ENDIF
6260       CALL MPI_AllReduce(nzutl, nz_urban_t, 1, MPI_INTEGER, MPI_MAX, comm2d, ierr )
6261       IF ( ierr /= 0 ) THEN
6262           WRITE(9,*) 'Error MPI_AllReduce12:', ierr, nzutl, nz_urban_t
6263           FLUSH(9)
6264       ENDIF
6265       CALL MPI_AllReduce(nzptl, nz_plant_t, 1, MPI_INTEGER, MPI_MAX, comm2d, ierr )
6266       IF ( ierr /= 0 ) THEN
6267           WRITE(9,*) 'Error MPI_AllReduce13:', ierr, nzptl, nz_plant_t
6268           FLUSH(9)
6269       ENDIF
6270#else
6271       nz_urban_b = nzubl
6272       nz_urban_t = nzutl
6273       nz_plant_t = nzptl
6274#endif
6275!
6276!--    Stretching (non-uniform grid spacing) is not considered in the radiation
6277!--    model. Therefore, vertical stretching has to be applied above the area
6278!--    where the parts of the radiation model which assume constant grid spacing
6279!--    are active. ABS (...) is required because the default value of
6280!--    dz_stretch_level_start is -9999999.9_wp (negative).
6281       IF ( ABS( dz_stretch_level_start(1) ) <= zw(nz_urban_t) ) THEN
6282          WRITE( message_string, * ) 'The lowest level where vertical ',       &
6283                                     'stretching is applied have to be ',      &
6284                                     'greater than ', zw(nz_urban_t)
6285          CALL message( 'radiation_interaction_init', 'PA0496', 1, 2, 0, 6, 0 )
6286       ENDIF 
6287!
6288!--    global number of urban and plant layers
6289       nz_urban = nz_urban_t - nz_urban_b + 1
6290       nz_plant = nz_plant_t - nz_urban_b + 1
6291!
6292!--    check max_raytracing_dist relative to urban surface layer height
6293       mrl = 2.0_wp * nz_urban * dz(1)
6294!--    set max_raytracing_dist to double the urban surface layer height, if not set
6295       IF ( max_raytracing_dist == -999.0_wp ) THEN
6296          max_raytracing_dist = mrl
6297       ENDIF
6298!--    check if max_raytracing_dist set too low (here we only warn the user. Other
6299!      option is to correct the value again to double the urban surface layer height)
6300       IF ( max_raytracing_dist  <  mrl ) THEN
6301          WRITE(message_string, '(a,f6.1)') 'Max_raytracing_dist is set less than ' // &
6302               'double the urban surface layer height, i.e. ', mrl
6303          CALL message('radiation_interaction_init', 'PA0521', 0, 0, -1, 6, 0)
6304       ENDIF
6305!        IF ( max_raytracing_dist <= mrl ) THEN
6306!           IF ( max_raytracing_dist /= -999.0_wp ) THEN
6307! !--          max_raytracing_dist too low
6308!              WRITE(message_string, '(a,f6.1)') 'Max_raytracing_dist too low, ' &
6309!                    // 'override to value ', mrl
6310!              CALL message('radiation_interaction_init', 'PA0521', 0, 0, -1, 6, 0)
6311!           ENDIF
6312!           max_raytracing_dist = mrl
6313!        ENDIF
6314!
6315!--    allocate urban surfaces grid
6316!--    calc number of surfaces in local proc
6317       IF ( debug_output )  CALL debug_message( 'calculation of indices for surfaces', 'info' )
6318
6319       nsurfl = 0
6320!
6321!--    Number of horizontal surfaces including land- and roof surfaces in both USM and LSM. Note that
6322!--    All horizontal surface elements are already counted in surface_mod.
6323       startland = 1
6324       nsurfl    = surf_usm_h%ns + surf_lsm_h%ns
6325       endland   = nsurfl
6326       nlands    = endland - startland + 1
6327
6328!
6329!--    Number of vertical surfaces in both USM and LSM. Note that all vertical surface elements are
6330!--    already counted in surface_mod.
6331       startwall = nsurfl+1
6332       DO  i = 0,3
6333          nsurfl = nsurfl + surf_usm_v(i)%ns + surf_lsm_v(i)%ns
6334       ENDDO
6335       endwall = nsurfl
6336       nwalls  = endwall - startwall + 1
6337       dirstart = (/ startland, startwall, startwall, startwall, startwall /)
6338       dirend = (/ endland, endwall, endwall, endwall, endwall /)
6339
6340!--    fill gridpcbl and pcbl
6341       IF ( npcbl > 0 )  THEN
6342           ALLOCATE( pcbl(iz:ix, 1:npcbl) )
6343           ALLOCATE( gridpcbl(nz_urban_b:nz_plant_t,nys:nyn,nxl:nxr) )
6344           pcbl = -1
6345           gridpcbl(:,:,:) = 0
6346           ipcgb = 0
6347           DO i = nxl, nxr
6348               DO j = nys, nyn
6349!
6350!--                Find topography top index
6351                   k_topo = get_topography_top_index_ji( j, i, 's' )
6352
6353                   DO k = k_topo + 1, pct(j,i)
6354                       ipcgb = ipcgb + 1
6355                       gridpcbl(k,j,i) = ipcgb
6356                       pcbl(:,ipcgb) = (/ k, j, i /)
6357                   ENDDO
6358               ENDDO
6359           ENDDO
6360           ALLOCATE( pcbinsw( 1:npcbl ) )
6361           ALLOCATE( pcbinswdir( 1:npcbl ) )
6362           ALLOCATE( pcbinswdif( 1:npcbl ) )
6363           ALLOCATE( pcbinlw( 1:npcbl ) )
6364       ENDIF
6365
6366!
6367!--    Fill surfl (the ordering of local surfaces given by the following
6368!--    cycles must not be altered, certain file input routines may depend
6369!--    on it).
6370!
6371!--    We allocate the array as linear and then use a two-dimensional pointer
6372!--    into it, because some MPI implementations crash with 2D-allocated arrays.
6373       ALLOCATE(surfl_linear(nidx_surf*nsurfl))
6374       surfl(1:nidx_surf,1:nsurfl) => surfl_linear(1:nidx_surf*nsurfl)
6375       isurf = 0
6376       IF ( rad_angular_discretization )  THEN
6377!
6378!--       Allocate and fill the reverse indexing array gridsurf
6379#if defined( __parallel )
6380!
6381!--       raytrace_mpi_rma is asserted
6382
6383          CALL MPI_Info_create(minfo, ierr)
6384          IF ( ierr /= 0 ) THEN
6385              WRITE(9,*) 'Error MPI_Info_create1:', ierr
6386              FLUSH(9)
6387          ENDIF
6388          CALL MPI_Info_set(minfo, 'accumulate_ordering', 'none', ierr)
6389          IF ( ierr /= 0 ) THEN
6390              WRITE(9,*) 'Error MPI_Info_set1:', ierr
6391              FLUSH(9)
6392          ENDIF
6393          CALL MPI_Info_set(minfo, 'accumulate_ops', 'same_op', ierr)
6394          IF ( ierr /= 0 ) THEN
6395              WRITE(9,*) 'Error MPI_Info_set2:', ierr
6396              FLUSH(9)
6397          ENDIF
6398          CALL MPI_Info_set(minfo, 'same_size', 'true', ierr)
6399          IF ( ierr /= 0 ) THEN
6400              WRITE(9,*) 'Error MPI_Info_set3:', ierr
6401              FLUSH(9)
6402          ENDIF
6403          CALL MPI_Info_set(minfo, 'same_disp_unit', 'true', ierr)
6404          IF ( ierr /= 0 ) THEN
6405              WRITE(9,*) 'Error MPI_Info_set4:', ierr
6406              FLUSH(9)
6407          ENDIF
6408
6409          CALL MPI_Win_allocate(INT(STORAGE_SIZE(1_iwp)/8*nsurf_type_u*nz_urban*nny*nnx, &
6410                                    kind=MPI_ADDRESS_KIND), STORAGE_SIZE(1_iwp)/8,  &
6411                                minfo, comm2d, gridsurf_rma_p, win_gridsurf, ierr)
6412          IF ( ierr /= 0 ) THEN
6413              WRITE(9,*) 'Error MPI_Win_allocate1:', ierr, &
6414                 INT(STORAGE_SIZE(1_iwp)/8*nsurf_type_u*nz_urban*nny*nnx,kind=MPI_ADDRESS_KIND), &
6415                 STORAGE_SIZE(1_iwp)/8, win_gridsurf
6416              FLUSH(9)
6417          ENDIF
6418
6419          CALL MPI_Info_free(minfo, ierr)
6420          IF ( ierr /= 0 ) THEN
6421              WRITE(9,*) 'Error MPI_Info_free1:', ierr
6422              FLUSH(9)
6423          ENDIF
6424
6425!
6426!--       On Intel compilers, calling c_f_pointer to transform a C pointer
6427!--       directly to a multi-dimensional Fotran pointer leads to strange
6428!--       errors on dimension boundaries. However, transforming to a 1D
6429!--       pointer and then redirecting a multidimensional pointer to it works
6430!--       fine.
6431          CALL c_f_pointer(gridsurf_rma_p, gridsurf_rma, (/ nsurf_type_u*nz_urban*nny*nnx /))
6432          gridsurf(0:nsurf_type_u-1, nz_urban_b:nz_urban_t, nys:nyn, nxl:nxr) =>                &
6433                     gridsurf_rma(1:nsurf_type_u*nz_urban*nny*nnx)
6434#else
6435          ALLOCATE(gridsurf(0:nsurf_type_u-1,nz_urban_b:nz_urban_t,nys:nyn,nxl:nxr) )
6436#endif
6437          gridsurf(:,:,:,:) = -999
6438       ENDIF
6439
6440!--    add horizontal surface elements (land and urban surfaces)
6441!--    TODO: add urban overhanging surfaces (idown_u)
6442       DO i = nxl, nxr
6443           DO j = nys, nyn
6444              DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
6445                 k = surf_usm_h%k(m)
6446                 isurf = isurf + 1
6447                 surfl(:,isurf) = (/iup_u,k,j,i,m/)
6448                 IF ( rad_angular_discretization ) THEN
6449                    gridsurf(iup_u,k,j,i) = isurf
6450                 ENDIF
6451              ENDDO
6452
6453              DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6454                 k = surf_lsm_h%k(m)
6455                 isurf = isurf + 1
6456                 surfl(:,isurf) = (/iup_l,k,j,i,m/)
6457                 IF ( rad_angular_discretization ) THEN
6458                    gridsurf(iup_u,k,j,i) = isurf
6459                 ENDIF
6460              ENDDO
6461
6462           ENDDO
6463       ENDDO
6464
6465!--    add vertical surface elements (land and urban surfaces)
6466!--    TODO: remove the hard coding of l = 0 to l = idirection
6467       DO i = nxl, nxr
6468           DO j = nys, nyn
6469              l = 0
6470              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6471                 k = surf_usm_v(l)%k(m)
6472                 isurf = isurf + 1
6473                 surfl(:,isurf) = (/inorth_u,k,j,i,m/)
6474                 IF ( rad_angular_discretization ) THEN
6475                    gridsurf(inorth_u,k,j,i) = isurf
6476                 ENDIF
6477              ENDDO
6478              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6479                 k = surf_lsm_v(l)%k(m)
6480                 isurf = isurf + 1
6481                 surfl(:,isurf) = (/inorth_l,k,j,i,m/)
6482                 IF ( rad_angular_discretization ) THEN
6483                    gridsurf(inorth_u,k,j,i) = isurf
6484                 ENDIF
6485              ENDDO
6486
6487              l = 1
6488              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6489                 k = surf_usm_v(l)%k(m)
6490                 isurf = isurf + 1
6491                 surfl(:,isurf) = (/isouth_u,k,j,i,m/)
6492                 IF ( rad_angular_discretization ) THEN
6493                    gridsurf(isouth_u,k,j,i) = isurf
6494                 ENDIF
6495              ENDDO
6496              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6497                 k = surf_lsm_v(l)%k(m)
6498                 isurf = isurf + 1
6499                 surfl(:,isurf) = (/isouth_l,k,j,i,m/)
6500                 IF ( rad_angular_discretization ) THEN
6501                    gridsurf(isouth_u,k,j,i) = isurf
6502                 ENDIF
6503              ENDDO
6504
6505              l = 2
6506              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6507                 k = surf_usm_v(l)%k(m)
6508                 isurf = isurf + 1
6509                 surfl(:,isurf) = (/ieast_u,k,j,i,m/)
6510                 IF ( rad_angular_discretization ) THEN
6511                    gridsurf(ieast_u,k,j,i) = isurf
6512                 ENDIF
6513              ENDDO
6514              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6515                 k = surf_lsm_v(l)%k(m)
6516                 isurf = isurf + 1
6517                 surfl(:,isurf) = (/ieast_l,k,j,i,m/)
6518                 IF ( rad_angular_discretization ) THEN
6519                    gridsurf(ieast_u,k,j,i) = isurf
6520                 ENDIF
6521              ENDDO
6522
6523              l = 3
6524              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6525                 k = surf_usm_v(l)%k(m)
6526                 isurf = isurf + 1
6527                 surfl(:,isurf) = (/iwest_u,k,j,i,m/)
6528                 IF ( rad_angular_discretization ) THEN
6529                    gridsurf(iwest_u,k,j,i) = isurf
6530                 ENDIF
6531              ENDDO
6532              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6533                 k = surf_lsm_v(l)%k(m)
6534                 isurf = isurf + 1
6535                 surfl(:,isurf) = (/iwest_l,k,j,i,m/)
6536                 IF ( rad_angular_discretization ) THEN
6537                    gridsurf(iwest_u,k,j,i) = isurf
6538                 ENDIF
6539              ENDDO
6540           ENDDO
6541       ENDDO
6542!
6543!--    Add local MRT boxes for specified number of levels
6544       nmrtbl = 0
6545       IF ( mrt_nlevels > 0 )  THEN
6546          DO  i = nxl, nxr
6547             DO  j = nys, nyn
6548                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
6549!
6550!--                Skip roof if requested
6551                   IF ( mrt_skip_roof  .AND.  surf_usm_h%isroof_surf(m) )  CYCLE
6552!
6553!--                Cycle over specified no of levels
6554                   nmrtbl = nmrtbl + mrt_nlevels
6555                ENDDO
6556!
6557!--             Dtto for LSM
6558                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6559                   nmrtbl = nmrtbl + mrt_nlevels
6560                ENDDO
6561             ENDDO
6562          ENDDO
6563
6564          ALLOCATE( mrtbl(iz:ix,nmrtbl), mrtsky(nmrtbl), mrtskyt(nmrtbl), &
6565                    mrtinsw(nmrtbl), mrtinlw(nmrtbl), mrt(nmrtbl) )
6566
6567          imrt = 0
6568          DO  i = nxl, nxr
6569             DO  j = nys, nyn
6570                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
6571!
6572!--                Skip roof if requested
6573                   IF ( mrt_skip_roof  .AND.  surf_usm_h%isroof_surf(m) )  CYCLE
6574!
6575!--                Cycle over specified no of levels
6576                   l = surf_usm_h%k(m)
6577                   DO  k = l, l + mrt_nlevels - 1
6578                      imrt = imrt + 1
6579                      mrtbl(:,imrt) = (/k,j,i/)
6580                   ENDDO
6581                ENDDO
6582!
6583!--             Dtto for LSM
6584                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6585                   l = surf_lsm_h%k(m)
6586                   DO  k = l, l + mrt_nlevels - 1
6587                      imrt = imrt + 1
6588                      mrtbl(:,imrt) = (/k,j,i/)
6589                   ENDDO
6590                ENDDO
6591             ENDDO
6592          ENDDO
6593       ENDIF
6594
6595!
6596!--    broadband albedo of the land, roof and wall surface
6597!--    for domain border and sky set artifically to 1.0
6598!--    what allows us to calculate heat flux leaving over
6599!--    side and top borders of the domain
6600       ALLOCATE ( albedo_surf(nsurfl) )
6601       albedo_surf = 1.0_wp
6602!
6603!--    Also allocate further array for emissivity with identical order of
6604!--    surface elements as radiation arrays.
6605       ALLOCATE ( emiss_surf(nsurfl)  )
6606
6607
6608!
6609!--    global array surf of indices of surfaces and displacement index array surfstart
6610       ALLOCATE(nsurfs(0:numprocs-1))
6611
6612#if defined( __parallel )
6613       CALL MPI_Allgather(nsurfl,1,MPI_INTEGER,nsurfs,1,MPI_INTEGER,comm2d,ierr)
6614       IF ( ierr /= 0 ) THEN
6615         WRITE(9,*) 'Error MPI_AllGather1:', ierr, nsurfl, nsurfs
6616         FLUSH(9)
6617     ENDIF
6618
6619#else
6620       nsurfs(0) = nsurfl
6621#endif
6622       ALLOCATE(surfstart(0:numprocs))
6623       k = 0
6624       DO i=0,numprocs-1
6625           surfstart(i) = k
6626           k = k+nsurfs(i)
6627       ENDDO
6628       surfstart(numprocs) = k
6629       nsurf = k
6630!
6631!--    We allocate the array as linear and then use a two-dimensional pointer
6632!--    into it, because some MPI implementations crash with 2D-allocated arrays.
6633       ALLOCATE(surf_linear(nidx_surf*nsurf))
6634       surf(1:nidx_surf,1:nsurf) => surf_linear(1:nidx_surf*nsurf)
6635
6636#if defined( __parallel )
6637       CALL MPI_AllGatherv(surfl_linear, nsurfl*nidx_surf, MPI_INTEGER,    &
6638                           surf_linear, nsurfs*nidx_surf,                  &
6639                           surfstart(0:numprocs-1)*nidx_surf, MPI_INTEGER, &
6640                           comm2d, ierr)
6641       IF ( ierr /= 0 ) THEN
6642           WRITE(9,*) 'Error MPI_AllGatherv4:', ierr, SIZE(surfl_linear),    &
6643                      nsurfl*nidx_surf, SIZE(surf_linear), nsurfs*nidx_surf, &
6644                      surfstart(0:numprocs-1)*nidx_surf
6645           FLUSH(9)
6646       ENDIF
6647#else
6648       surf = surfl
6649#endif
6650
6651!--
6652!--    allocation of the arrays for direct and diffusion radiation
6653       IF ( debug_output )  CALL debug_message( 'allocation of radiation arrays', 'info' )
6654!--    rad_sw_in, rad_lw_in are computed in radiation model,
6655!--    splitting of direct and diffusion part is done
6656!--    in calc_diffusion_radiation for now
6657
6658       ALLOCATE( rad_sw_in_dir(nysg:nyng,nxlg:nxrg) )
6659       ALLOCATE( rad_sw_in_diff(nysg:nyng,nxlg:nxrg) )
6660       ALLOCATE( rad_lw_in_diff(nysg:nyng,nxlg:nxrg) )
6661       rad_sw_in_dir  = 0.0_wp
6662       rad_sw_in_diff = 0.0_wp
6663       rad_lw_in_diff = 0.0_wp
6664
6665!--    allocate radiation arrays
6666       ALLOCATE( surfins(nsurfl) )
6667       ALLOCATE( surfinl(nsurfl) )
6668       ALLOCATE( surfinsw(nsurfl) )
6669       ALLOCATE( surfinlw(nsurfl) )
6670       ALLOCATE( surfinswdir(nsurfl) )
6671       ALLOCATE( surfinswdif(nsurfl) )
6672       ALLOCATE( surfinlwdif(nsurfl) )
6673       ALLOCATE( surfoutsl(nsurfl) )
6674       ALLOCATE( surfoutll(nsurfl) )
6675       ALLOCATE( surfoutsw(nsurfl) )
6676       ALLOCATE( surfoutlw(nsurfl) )
6677       ALLOCATE( surfouts(nsurf) )
6678       ALLOCATE( surfoutl(nsurf) )
6679       ALLOCATE( surfinlg(nsurf) )
6680       ALLOCATE( skyvf(nsurfl) )
6681       ALLOCATE( skyvft(nsurfl) )
6682       ALLOCATE( surfemitlwl(nsurfl) )
6683
6684!
6685!--    In case of average_radiation, aggregated surface albedo and emissivity,
6686!--    also set initial value for t_rad_urb.
6687!--    For now set an arbitrary initial value.
6688       IF ( average_radiation )  THEN
6689          albedo_urb = 0.1_wp
6690          emissivity_urb = 0.9_wp
6691          t_rad_urb = pt_surface
6692       ENDIF
6693
6694    END SUBROUTINE radiation_interaction_init
6695
6696!------------------------------------------------------------------------------!
6697! Description:
6698! ------------
6699!> Calculates shape view factors (SVF), plant sink canopy factors (PCSF),
6700!> sky-view factors, discretized path for direct solar radiation, MRT factors
6701!> and other preprocessed data needed for radiation_interaction.
6702!------------------------------------------------------------------------------!
6703    SUBROUTINE radiation_calc_svf
6704   
6705        IMPLICIT NONE
6706       
6707        INTEGER(iwp)                                  :: i, j, k, d, ip, jp
6708        INTEGER(iwp)                                  :: isvf, ksvf, icsf, kcsf, npcsfl, isvf_surflt, imrt, imrtf, ipcgb
6709        INTEGER(iwp)                                  :: sd, td
6710        INTEGER(iwp)                                  :: iaz, izn      !< azimuth, zenith counters
6711        INTEGER(iwp)                                  :: naz, nzn      !< azimuth, zenith num of steps
6712        REAL(wp)                                      :: az0, zn0      !< starting azimuth/zenith
6713        REAL(wp)                                      :: azs, zns      !< azimuth/zenith cycle step
6714        REAL(wp)                                      :: az1, az2      !< relative azimuth of section borders
6715        REAL(wp)                                      :: azmid         !< ray (center) azimuth
6716        REAL(wp)                                      :: yxlen         !< |yxdir|
6717        REAL(wp), DIMENSION(2)                        :: yxdir         !< y,x *unit* vector of ray direction (in grid units)
6718        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zdirs         !< directions in z (tangent of elevation)
6719        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zcent         !< zenith angle centers
6720        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zbdry         !< zenith angle boundaries
6721        REAL(wp), DIMENSION(:), ALLOCATABLE           :: vffrac        !< view factor fractions for individual rays
6722        REAL(wp), DIMENSION(:), ALLOCATABLE           :: vffrac0       !< dtto (original values)
6723        REAL(wp), DIMENSION(:), ALLOCATABLE           :: ztransp       !< array of transparency in z steps
6724        INTEGER(iwp)                                  :: lowest_free_ray !< index into zdirs
6725        INTEGER(iwp), DIMENSION(:), ALLOCATABLE       :: itarget       !< face indices of detected obstacles
6726        INTEGER(iwp)                                  :: itarg0, itarg1
6727
6728        INTEGER(iwp)                                  :: udim
6729        INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET:: nzterrl_l
6730        INTEGER(iwp), DIMENSION(:,:), POINTER         :: nzterrl
6731        REAL(wp),     DIMENSION(:), ALLOCATABLE,TARGET:: csflt_l, pcsflt_l
6732        REAL(wp),     DIMENSION(:,:), POINTER         :: csflt, pcsflt
6733        INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET:: kcsflt_l,kpcsflt_l
6734        INTEGER(iwp), DIMENSION(:,:), POINTER         :: kcsflt,kpcsflt
6735        INTEGER(iwp), DIMENSION(:), ALLOCATABLE       :: icsflt,dcsflt,ipcsflt,dpcsflt
6736        REAL(wp), DIMENSION(3)                        :: uv
6737        LOGICAL                                       :: visible
6738        REAL(wp), DIMENSION(3)                        :: sa, ta          !< real coordinates z,y,x of source and target
6739        REAL(wp)                                      :: difvf           !< differential view factor
6740        REAL(wp)                                      :: transparency, rirrf, sqdist, svfsum
6741        INTEGER(iwp)                                  :: isurflt, isurfs, isurflt_prev
6742        INTEGER(idp)                                  :: ray_skip_maxdist, ray_skip_minval !< skipped raytracing counts
6743        INTEGER(iwp)                                  :: max_track_len !< maximum 2d track length
6744        INTEGER(iwp)                                  :: minfo
6745        REAL(wp), DIMENSION(:), POINTER, SAVE         :: lad_s_rma       !< fortran 1D pointer
6746        TYPE(c_ptr)                                   :: lad_s_rma_p     !< allocated c pointer
6747#if defined( __parallel )
6748        INTEGER(kind=MPI_ADDRESS_KIND)                :: size_lad_rma
6749#endif
6750!   
6751        INTEGER(iwp), DIMENSION(0:svfnorm_report_num) :: svfnorm_counts
6752
6753
6754!--     calculation of the SVF
6755        CALL location_message( 'calculating view factors for radiation interaction', 'start' )
6756
6757!--     initialize variables and temporary arrays for calculation of svf and csf
6758        nsvfl  = 0
6759        ncsfl  = 0
6760        nsvfla = gasize
6761        msvf   = 1
6762        ALLOCATE( asvf1(nsvfla) )
6763        asvf => asvf1
6764        IF ( plant_canopy )  THEN
6765            ncsfla = gasize
6766            mcsf   = 1
6767            ALLOCATE( acsf1(ncsfla) )
6768            acsf => acsf1
6769        ENDIF
6770        nmrtf = 0
6771        IF ( mrt_nlevels > 0 )  THEN
6772           nmrtfa = gasize
6773           mmrtf = 1
6774           ALLOCATE ( amrtf1(nmrtfa) )
6775           amrtf => amrtf1
6776        ENDIF
6777        ray_skip_maxdist = 0
6778        ray_skip_minval = 0
6779       
6780!--     initialize temporary terrain and plant canopy height arrays (global 2D array!)
6781        ALLOCATE( nzterr(0:(nx+1)*(ny+1)-1) )
6782#if defined( __parallel )
6783        !ALLOCATE( nzterrl(nys:nyn,nxl:nxr) )
6784        ALLOCATE( nzterrl_l((nyn-nys+1)*(nxr-nxl+1)) )
6785        nzterrl(nys:nyn,nxl:nxr) => nzterrl_l(1:(nyn-nys+1)*(nxr-nxl+1))
6786        nzterrl = get_topography_top_index( 's' )
6787        CALL MPI_AllGather( nzterrl_l, nnx*nny, MPI_INTEGER, &
6788                            nzterr, nnx*nny, MPI_INTEGER, comm2d, ierr )
6789        IF ( ierr /= 0 ) THEN
6790            WRITE(9,*) 'Error MPI_AllGather1:', ierr, SIZE(nzterrl_l), nnx*nny, &
6791                       SIZE(nzterr), nnx*nny
6792            FLUSH(9)
6793        ENDIF
6794        DEALLOCATE(nzterrl_l)
6795#else
6796        nzterr = RESHAPE( get_topography_top_index( 's' ), (/(nx+1)*(ny+1)/) )
6797#endif
6798        IF ( plant_canopy )  THEN
6799            ALLOCATE( plantt(0:(nx+1)*(ny+1)-1) )
6800            maxboxesg = nx + ny + nz_plant + 1
6801            max_track_len = nx + ny + 1
6802!--         temporary arrays storing values for csf calculation during raytracing
6803            ALLOCATE( boxes(3, maxboxesg) )
6804            ALLOCATE( crlens(maxboxesg) )
6805
6806#if defined( __parallel )
6807            CALL MPI_AllGather( pct, nnx*nny, MPI_INTEGER, &
6808                                plantt, nnx*nny, MPI_INTEGER, comm2d, ierr )
6809            IF ( ierr /= 0 ) THEN
6810                WRITE(9,*) 'Error MPI_AllGather2:', ierr, SIZE(pct), nnx*nny, &
6811                           SIZE(plantt), nnx*nny
6812                FLUSH(9)
6813            ENDIF
6814
6815!--         temporary arrays storing values for csf calculation during raytracing
6816            ALLOCATE( lad_ip(maxboxesg) )
6817            ALLOCATE( lad_disp(maxboxesg) )
6818
6819            IF ( raytrace_mpi_rma )  THEN
6820                ALLOCATE( lad_s_ray(maxboxesg) )
6821               
6822                ! set conditions for RMA communication
6823                CALL MPI_Info_create(minfo, ierr)
6824                IF ( ierr /= 0 ) THEN
6825                    WRITE(9,*) 'Error MPI_Info_create2:', ierr
6826                    FLUSH(9)
6827                ENDIF
6828                CALL MPI_Info_set(minfo, 'accumulate_ordering', 'none', ierr)
6829                IF ( ierr /= 0 ) THEN
6830                    WRITE(9,*) 'Error MPI_Info_set5:', ierr
6831                    FLUSH(9)
6832                ENDIF
6833                CALL MPI_Info_set(minfo, 'accumulate_ops', 'same_op', ierr)
6834                IF ( ierr /= 0 ) THEN
6835                    WRITE(9,*) 'Error MPI_Info_set6:', ierr
6836                    FLUSH(9)
6837                ENDIF
6838                CALL MPI_Info_set(minfo, 'same_size', 'true', ierr)
6839                IF ( ierr /= 0 ) THEN
6840                    WRITE(9,*) 'Error MPI_Info_set7:', ierr
6841                    FLUSH(9)
6842                ENDIF
6843                CALL MPI_Info_set(minfo, 'same_disp_unit', 'true', ierr)
6844                IF ( ierr /= 0 ) THEN
6845                    WRITE(9,*) 'Error MPI_Info_set8:', ierr
6846                    FLUSH(9)
6847                ENDIF
6848
6849!--             Allocate and initialize the MPI RMA window
6850!--             must be in accordance with allocation of lad_s in plant_canopy_model
6851!--             optimization of memory should be done
6852!--             Argument X of function STORAGE_SIZE(X) needs arbitrary REAL(wp) value, set to 1.0_wp for now
6853                size_lad_rma = STORAGE_SIZE(1.0_wp)/8*nnx*nny*nz_plant
6854                CALL MPI_Win_allocate(size_lad_rma, STORAGE_SIZE(1.0_wp)/8, minfo, comm2d, &
6855                                        lad_s_rma_p, win_lad, ierr)
6856                IF ( ierr /= 0 ) THEN
6857                    WRITE(9,*) 'Error MPI_Win_allocate2:', ierr, size_lad_rma, &
6858                                STORAGE_SIZE(1.0_wp)/8, win_lad
6859                    FLUSH(9)
6860                ENDIF
6861                CALL c_f_pointer(lad_s_rma_p, lad_s_rma, (/ nz_plant*nny*nnx /))
6862                sub_lad(nz_urban_b:nz_plant_t, nys:nyn, nxl:nxr) => lad_s_rma(1:nz_plant*nny*nnx)
6863            ELSE
6864                ALLOCATE(sub_lad(nz_urban_b:nz_plant_t, nys:nyn, nxl:nxr))
6865            ENDIF
6866#else
6867            plantt = RESHAPE( pct(nys:nyn,nxl:nxr), (/(nx+1)*(ny+1)/) )
6868            ALLOCATE(sub_lad(nz_urban_b:nz_plant_t, nys:nyn, nxl:nxr))
6869#endif
6870            plantt_max = MAXVAL(plantt)
6871            ALLOCATE( rt2_track(2, max_track_len), rt2_track_lad(nz_urban_b:plantt_max, max_track_len), &
6872                      rt2_track_dist(0:max_track_len), rt2_dist(plantt_max-nz_urban_b+2) )
6873
6874            sub_lad(:,:,:) = 0._wp
6875            DO i = nxl, nxr
6876                DO j = nys, nyn
6877                    k = get_topography_top_index_ji( j, i, 's' )
6878
6879                    sub_lad(k:nz_plant_t, j, i) = lad_s(0:nz_plant_t-k, j, i)
6880                ENDDO
6881            ENDDO
6882
6883#if defined( __parallel )
6884            IF ( raytrace_mpi_rma )  THEN
6885                CALL MPI_Info_free(minfo, ierr)
6886                IF ( ierr /= 0 ) THEN
6887                    WRITE(9,*) 'Error MPI_Info_free2:', ierr
6888                    FLUSH(9)
6889                ENDIF
6890                CALL MPI_Win_lock_all(0, win_lad, ierr)
6891                IF ( ierr /= 0 ) THEN
6892                    WRITE(9,*) 'Error MPI_Win_lock_all1:', ierr, win_lad
6893                    FLUSH(9)
6894                ENDIF
6895               
6896            ELSE
6897                ALLOCATE( sub_lad_g(0:(nx+1)*(ny+1)*nz_plant-1) )
6898                CALL MPI_AllGather( sub_lad, nnx*nny*nz_plant, MPI_REAL, &
6899                                    sub_lad_g, nnx*nny*nz_plant, MPI_REAL, comm2d, ierr )
6900                IF ( ierr /= 0 ) THEN
6901                    WRITE(9,*) 'Error MPI_AllGather3:', ierr, SIZE(sub_lad), &
6902                                nnx*nny*nz_plant, SIZE(sub_lad_g), nnx*nny*nz_plant
6903                    FLUSH(9)
6904                ENDIF
6905            ENDIF
6906#endif
6907        ENDIF
6908
6909!--     prepare the MPI_Win for collecting the surface indices
6910!--     from the reverse index arrays gridsurf from processors of target surfaces
6911#if defined( __parallel )
6912        IF ( rad_angular_discretization )  THEN
6913!
6914!--         raytrace_mpi_rma is asserted
6915            CALL MPI_Win_lock_all(0, win_gridsurf, ierr)
6916            IF ( ierr /= 0 ) THEN
6917                WRITE(9,*) 'Error MPI_Win_lock_all2:', ierr, win_gridsurf
6918                FLUSH(9)
6919            ENDIF
6920        ENDIF
6921#endif
6922
6923
6924        !--Directions opposite to face normals are not even calculated,
6925        !--they must be preset to 0
6926        !--
6927        dsitrans(:,:) = 0._wp
6928       
6929        DO isurflt = 1, nsurfl
6930!--         determine face centers
6931            td = surfl(id, isurflt)
6932            ta = (/ REAL(surfl(iz, isurflt), wp) - 0.5_wp * kdir(td),  &
6933                      REAL(surfl(iy, isurflt), wp) - 0.5_wp * jdir(td),  &
6934                      REAL(surfl(ix, isurflt), wp) - 0.5_wp * idir(td)  /)
6935
6936            !--Calculate sky view factor and raytrace DSI paths
6937            skyvf(isurflt) = 0._wp
6938            skyvft(isurflt) = 0._wp
6939
6940            !--Select a proper half-sphere for 2D raytracing
6941            SELECT CASE ( td )
6942               CASE ( iup_u, iup_l )
6943                  az0 = 0._wp
6944                  naz = raytrace_discrete_azims
6945                  azs = 2._wp * pi / REAL(naz, wp)
6946                  zn0 = 0._wp
6947                  nzn = raytrace_discrete_elevs / 2
6948                  zns = pi / 2._wp / REAL(nzn, wp)
6949               CASE ( isouth_u, isouth_l )
6950                  az0 = pi / 2._wp
6951                  naz = raytrace_discrete_azims / 2
6952                  azs = pi / REAL(naz, wp)
6953                  zn0 = 0._wp
6954                  nzn = raytrace_discrete_elevs
6955                  zns = pi / REAL(nzn, wp)
6956               CASE ( inorth_u, inorth_l )
6957                  az0 = - pi / 2._wp
6958                  naz = raytrace_discrete_azims / 2
6959                  azs = pi / REAL(naz, wp)
6960                  zn0 = 0._wp
6961                  nzn = raytrace_discrete_elevs
6962                  zns = pi / REAL(nzn, wp)
6963               CASE ( iwest_u, iwest_l )
6964                  az0 = pi
6965                  naz = raytrace_discrete_azims / 2
6966                  azs = pi / REAL(naz, wp)
6967                  zn0 = 0._wp
6968                  nzn = raytrace_discrete_elevs
6969                  zns = pi / REAL(nzn, wp)
6970               CASE ( ieast_u, ieast_l )
6971                  az0 = 0._wp
6972                  naz = raytrace_discrete_azims / 2
6973                  azs = pi / REAL(naz, wp)
6974                  zn0 = 0._wp
6975                  nzn = raytrace_discrete_elevs
6976                  zns = pi / REAL(nzn, wp)
6977               CASE DEFAULT
6978                  WRITE(message_string, *) 'ERROR: the surface type ', td,     &
6979                                           ' is not supported for calculating',&
6980                                           ' SVF'
6981                  CALL message( 'radiation_calc_svf', 'PA0488', 1, 2, 0, 6, 0 )
6982            END SELECT
6983
6984            ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), zbdry(0:nzn), vffrac(1:nzn*naz), &
6985                       ztransp(1:nzn*naz), itarget(1:nzn*naz) )   !FIXME allocate itarget only
6986                                                                  !in case of rad_angular_discretization
6987
6988            itarg0 = 1
6989            itarg1 = nzn
6990            zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
6991            zbdry(:) = (/( zn0+REAL(izn,wp)*zns, izn=0, nzn )/)
6992            IF ( td == iup_u  .OR.  td == iup_l )  THEN
6993               vffrac(1:nzn) = (COS(2 * zbdry(0:nzn-1)) - COS(2 * zbdry(1:nzn))) / 2._wp / REAL(naz, wp)
6994!
6995!--            For horizontal target, vf fractions are constant per azimuth
6996               DO iaz = 1, naz-1
6997                  vffrac(iaz*nzn+1:(iaz+1)*nzn) = vffrac(1:nzn)
6998               ENDDO
6999!--            sum of whole vffrac equals 1, verified
7000            ENDIF
7001!
7002!--         Calculate sky-view factor and direct solar visibility using 2D raytracing
7003            DO iaz = 1, naz
7004               azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
7005               IF ( td /= iup_u  .AND.  td /= iup_l )  THEN
7006                  az2 = REAL(iaz, wp) * azs - pi/2._wp
7007                  az1 = az2 - azs
7008                  !TODO precalculate after 1st line
7009                  vffrac(itarg0:itarg1) = (SIN(az2) - SIN(az1))               &
7010                              * (zbdry(1:nzn) - zbdry(0:nzn-1)                &
7011                                 + SIN(zbdry(0:nzn-1))*COS(zbdry(0:nzn-1))    &
7012                                 - SIN(zbdry(1:nzn))*COS(zbdry(1:nzn)))       &
7013                              / (2._wp * pi)
7014!--               sum of whole vffrac equals 1, verified
7015               ENDIF
7016               yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
7017               yxlen = SQRT(SUM(yxdir(:)**2))
7018               zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
7019               yxdir(:) = yxdir(:) / yxlen
7020
7021               CALL raytrace_2d(ta, yxdir, nzn, zdirs,                        &
7022                                    surfstart(myid) + isurflt, facearea(td),  &
7023                                    vffrac(itarg0:itarg1), .TRUE., .TRUE.,    &
7024                                    .FALSE., lowest_free_ray,                 &
7025                                    ztransp(itarg0:itarg1),                   &
7026                                    itarget(itarg0:itarg1))
7027
7028               skyvf(isurflt) = skyvf(isurflt) + &
7029                                SUM(vffrac(itarg0:itarg0+lowest_free_ray-1))
7030               skyvft(isurflt) = skyvft(isurflt) + &
7031                                 SUM(ztransp(itarg0:itarg0+lowest_free_ray-1) &
7032                                             * vffrac(itarg0:itarg0+lowest_free_ray-1))
7033 
7034!--            Save direct solar transparency
7035               j = MODULO(NINT(azmid/                                          &
7036                               (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
7037                          raytrace_discrete_azims)
7038
7039               DO k = 1, raytrace_discrete_elevs/2
7040                  i = dsidir_rev(k-1, j)
7041                  IF ( i /= -1  .AND.  k <= lowest_free_ray )  &
7042                     dsitrans(isurflt, i) = ztransp(itarg0+k-1)
7043               ENDDO
7044
7045!
7046!--            Advance itarget indices
7047               itarg0 = itarg1 + 1
7048               itarg1 = itarg1 + nzn
7049            ENDDO
7050
7051            IF ( rad_angular_discretization )  THEN
7052!--            sort itarget by face id
7053               CALL quicksort_itarget(itarget,vffrac,ztransp,1,nzn*naz)
7054!
7055!--            For aggregation, we need fractions multiplied by transmissivities
7056               ztransp(:) = vffrac(:) * ztransp(:)
7057!
7058!--            find the first valid position
7059               itarg0 = 1
7060               DO WHILE ( itarg0 <= nzn*naz )
7061                  IF ( itarget(itarg0) /= -1 )  EXIT
7062                  itarg0 = itarg0 + 1
7063               ENDDO
7064
7065               DO  i = itarg0, nzn*naz
7066!
7067!--               For duplicate values, only sum up vf fraction value
7068                  IF ( i < nzn*naz )  THEN
7069                     IF ( itarget(i+1) == itarget(i) )  THEN
7070                        vffrac(i+1) = vffrac(i+1) + vffrac(i)
7071                        ztransp(i+1) = ztransp(i+1) + ztransp(i)
7072                        CYCLE
7073                     ENDIF
7074                  ENDIF
7075!
7076!--               write to the svf array
7077                  nsvfl = nsvfl + 1
7078!--               check dimmension of asvf array and enlarge it if needed
7079                  IF ( nsvfla < nsvfl )  THEN
7080                     k = CEILING(REAL(nsvfla, kind=wp) * grow_factor)
7081                     IF ( msvf == 0 )  THEN
7082                        msvf = 1
7083                        ALLOCATE( asvf1(k) )
7084                        asvf => asvf1
7085                        asvf1(1:nsvfla) = asvf2
7086                        DEALLOCATE( asvf2 )
7087                     ELSE
7088                        msvf = 0
7089                        ALLOCATE( asvf2(k) )
7090                        asvf => asvf2
7091                        asvf2(1:nsvfla) = asvf1
7092                        DEALLOCATE( asvf1 )
7093                     ENDIF
7094
7095                     IF ( debug_output )  THEN
7096                        WRITE( debug_string, '(A,3I12)' ) 'Grow asvf:', nsvfl, nsvfla, k
7097                        CALL debug_message( debug_string, 'info' )
7098                     ENDIF
7099                     
7100                     nsvfla = k
7101                  ENDIF
7102!--               write svf values into the array
7103                  asvf(nsvfl)%isurflt = isurflt
7104                  asvf(nsvfl)%isurfs = itarget(i)
7105                  asvf(nsvfl)%rsvf = vffrac(i)
7106                  asvf(nsvfl)%rtransp = ztransp(i) / vffrac(i)
7107               END DO
7108
7109            ENDIF ! rad_angular_discretization
7110
7111            DEALLOCATE ( zdirs, zcent, zbdry, vffrac, ztransp, itarget ) !FIXME itarget shall be allocated only
7112                                                                  !in case of rad_angular_discretization
7113!
7114!--         Following calculations only required for surface_reflections
7115            IF ( surface_reflections  .AND.  .NOT. rad_angular_discretization )  THEN
7116
7117               DO  isurfs = 1, nsurf
7118                  IF ( .NOT.  surface_facing(surfl(ix, isurflt), surfl(iy, isurflt), &
7119                     surfl(iz, isurflt), surfl(id, isurflt), &
7120                     surf(ix, isurfs), surf(iy, isurfs), &
7121                     surf(iz, isurfs), surf(id, isurfs)) )  THEN
7122                     CYCLE
7123                  ENDIF
7124                 
7125                  sd = surf(id, isurfs)
7126                  sa = (/ REAL(surf(iz, isurfs), wp) - 0.5_wp * kdir(sd),  &
7127                          REAL(surf(iy, isurfs), wp) - 0.5_wp * jdir(sd),  &
7128                          REAL(surf(ix, isurfs), wp) - 0.5_wp * idir(sd)  /)
7129
7130!--               unit vector source -> target
7131                  uv = (/ (ta(1)-sa(1))*dz(1), (ta(2)-sa(2))*dy, (ta(3)-sa(3))*dx /)
7132                  sqdist = SUM(uv(:)**2)
7133                  uv = uv / SQRT(sqdist)
7134
7135!--               reject raytracing above max distance
7136                  IF ( SQRT(sqdist) > max_raytracing_dist ) THEN
7137                     ray_skip_maxdist = ray_skip_maxdist + 1
7138                     CYCLE
7139                  ENDIF
7140                 
7141                  difvf = dot_product((/ kdir(sd), jdir(sd), idir(sd) /), uv) & ! cosine of source normal and direction
7142                      * dot_product((/ kdir(td), jdir(td), idir(td) /), -uv) &  ! cosine of target normal and reverse direction
7143                      / (pi * sqdist) ! square of distance between centers
7144!
7145!--               irradiance factor (our unshaded shape view factor) = view factor per differential target area * source area
7146                  rirrf = difvf * facearea(sd)
7147
7148!--               reject raytracing for potentially too small view factor values
7149                  IF ( rirrf < min_irrf_value ) THEN
7150                      ray_skip_minval = ray_skip_minval + 1
7151                      CYCLE
7152                  ENDIF
7153
7154!--               raytrace + process plant canopy sinks within
7155                  CALL raytrace(sa, ta, isurfs, difvf, facearea(td), .TRUE., &
7156                                visible, transparency)
7157
7158                  IF ( .NOT.  visible ) CYCLE
7159                 ! rsvf = rirrf * transparency
7160
7161!--               write to the svf array
7162                  nsvfl = nsvfl + 1
7163!--               check dimmension of asvf array and enlarge it if needed
7164                  IF ( nsvfla < nsvfl )  THEN
7165                     k = CEILING(REAL(nsvfla, kind=wp) * grow_factor)
7166                     IF ( msvf == 0 )  THEN
7167                        msvf = 1
7168                        ALLOCATE( asvf1(k) )
7169                        asvf => asvf1
7170                        asvf1(1:nsvfla) = asvf2
7171                        DEALLOCATE( asvf2 )
7172                     ELSE
7173                        msvf = 0
7174                        ALLOCATE( asvf2(k) )
7175                        asvf => asvf2
7176                        asvf2(1:nsvfla) = asvf1
7177                        DEALLOCATE( asvf1 )
7178                     ENDIF
7179
7180                     IF ( debug_output )  THEN
7181                        WRITE( debug_string, '(A,3I12)' ) 'Grow asvf:', nsvfl, nsvfla, k
7182                        CALL debug_message( debug_string, 'info' )
7183                     ENDIF
7184                     
7185                     nsvfla = k
7186                  ENDIF
7187!--               write svf values into the array
7188                  asvf(nsvfl)%isurflt = isurflt
7189                  asvf(nsvfl)%isurfs = isurfs
7190                  asvf(nsvfl)%rsvf = rirrf !we postopne multiplication by transparency
7191                  asvf(nsvfl)%rtransp = transparency !a.k.a. Direct Irradiance Factor
7192               ENDDO
7193            ENDIF
7194        ENDDO
7195
7196!--
7197!--     Raytrace to canopy boxes to fill dsitransc TODO optimize
7198        dsitransc(:,:) = 0._wp
7199        az0 = 0._wp
7200        naz = raytrace_discrete_azims
7201        azs = 2._wp * pi / REAL(naz, wp)
7202        zn0 = 0._wp
7203        nzn = raytrace_discrete_elevs / 2
7204        zns = pi / 2._wp / REAL(nzn, wp)
7205        ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), vffrac(1:nzn), ztransp(1:nzn), &
7206               itarget(1:nzn) )
7207        zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
7208        vffrac(:) = 0._wp
7209
7210        DO  ipcgb = 1, npcbl
7211           ta = (/ REAL(pcbl(iz, ipcgb), wp),  &
7212                   REAL(pcbl(iy, ipcgb), wp),  &
7213                   REAL(pcbl(ix, ipcgb), wp) /)
7214!--        Calculate direct solar visibility using 2D raytracing
7215           DO  iaz = 1, naz
7216              azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
7217              yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
7218              yxlen = SQRT(SUM(yxdir(:)**2))
7219              zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
7220              yxdir(:) = yxdir(:) / yxlen
7221              CALL raytrace_2d(ta, yxdir, nzn, zdirs,                                &
7222                                   -999, -999._wp, vffrac, .FALSE., .FALSE., .TRUE., &
7223                                   lowest_free_ray, ztransp, itarget)
7224
7225!--           Save direct solar transparency
7226              j = MODULO(NINT(azmid/                                         &
7227                             (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
7228                         raytrace_discrete_azims)
7229              DO  k = 1, raytrace_discrete_elevs/2
7230                 i = dsidir_rev(k-1, j)
7231                 IF ( i /= -1  .AND.  k <= lowest_free_ray ) &
7232                    dsitransc(ipcgb, i) = ztransp(k)
7233              ENDDO
7234           ENDDO
7235        ENDDO
7236        DEALLOCATE ( zdirs, zcent, vffrac, ztransp, itarget )
7237!--
7238!--     Raytrace to MRT boxes
7239        IF ( nmrtbl > 0 )  THEN
7240           mrtdsit(:,:) = 0._wp
7241           mrtsky(:) = 0._wp
7242           mrtskyt(:) = 0._wp
7243           az0 = 0._wp
7244           naz = raytrace_discrete_azims
7245           azs = 2._wp * pi / REAL(naz, wp)
7246           zn0 = 0._wp
7247           nzn = raytrace_discrete_elevs
7248           zns = pi / REAL(nzn, wp)
7249           ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), zbdry(0:nzn), vffrac(1:nzn*naz), vffrac0(1:nzn), &
7250                      ztransp(1:nzn*naz), itarget(1:nzn*naz) )   !FIXME allocate itarget only
7251                                                                 !in case of rad_angular_discretization
7252
7253           zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
7254           zbdry(:) = (/( zn0+REAL(izn,wp)*zns, izn=0, nzn )/)
7255           vffrac0(:) = (COS(zbdry(0:nzn-1)) - COS(zbdry(1:nzn))) / 2._wp / REAL(naz, wp)
7256           !
7257           !--Modify direction weights to simulate human body (lower weight for top-down)
7258           IF ( mrt_geom_human )  THEN
7259              vffrac0(:) = vffrac0(:) * MAX(0._wp, SIN(zcent(:))*0.88_wp + COS(zcent(:))*0.12_wp)
7260              vffrac0(:) = vffrac0(:) / (SUM(vffrac0) * REAL(naz, wp))
7261           ENDIF
7262
7263           DO  imrt = 1, nmrtbl
7264              ta = (/ REAL(mrtbl(iz, imrt), wp),  &
7265                      REAL(mrtbl(iy, imrt), wp),  &
7266                      REAL(mrtbl(ix, imrt), wp) /)
7267!
7268!--           vf fractions are constant per azimuth
7269              DO iaz = 0, naz-1
7270                 vffrac(iaz*nzn+1:(iaz+1)*nzn) = vffrac0(:)
7271              ENDDO
7272!--           sum of whole vffrac equals 1, verified
7273              itarg0 = 1
7274              itarg1 = nzn
7275!
7276!--           Calculate sky-view factor and direct solar visibility using 2D raytracing
7277              DO  iaz = 1, naz
7278                 azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
7279                 yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
7280                 yxlen = SQRT(SUM(yxdir(:)**2))
7281                 zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
7282                 yxdir(:) = yxdir(:) / yxlen
7283
7284                 CALL raytrace_2d(ta, yxdir, nzn, zdirs,                         &
7285                                  -999, -999._wp, vffrac(itarg0:itarg1), .TRUE., &
7286                                  .FALSE., .TRUE., lowest_free_ray,              &
7287                                  ztransp(itarg0:itarg1),                        &
7288                                  itarget(itarg0:itarg1))
7289
7290!--              Sky view factors for MRT
7291                 mrtsky(imrt) = mrtsky(imrt) + &
7292                                  SUM(vffrac(itarg0:itarg0+lowest_free_ray-1))
7293                 mrtskyt(imrt) = mrtskyt(imrt) + &
7294                                   SUM(ztransp(itarg0:itarg0+lowest_free_ray-1) &
7295                                               * vffrac(itarg0:itarg0+lowest_free_ray-1))
7296!--              Direct solar transparency for MRT
7297                 j = MODULO(NINT(azmid/                                         &
7298                                (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
7299                            raytrace_discrete_azims)
7300                 DO  k = 1, raytrace_discrete_elevs/2
7301                    i = dsidir_rev(k-1, j)
7302                    IF ( i /= -1  .AND.  k <= lowest_free_ray ) &
7303                       mrtdsit(imrt, i) = ztransp(itarg0+k-1)
7304                 ENDDO
7305!
7306!--              Advance itarget indices
7307                 itarg0 = itarg1 + 1
7308                 itarg1 = itarg1 + nzn
7309              ENDDO
7310
7311!--           sort itarget by face id
7312              CALL quicksort_itarget(itarget,vffrac,ztransp,1,nzn*naz)
7313!
7314!--           find the first valid position
7315              itarg0 = 1
7316              DO WHILE ( itarg0 <= nzn*naz )
7317                 IF ( itarget(itarg0) /= -1 )  EXIT
7318                 itarg0 = itarg0 + 1
7319              ENDDO
7320
7321              DO  i = itarg0, nzn*naz
7322!
7323!--              For duplicate values, only sum up vf fraction value
7324                 IF ( i < nzn*naz )  THEN
7325                    IF ( itarget(i+1) == itarget(i) )  THEN
7326                       vffrac(i+1) = vffrac(i+1) + vffrac(i)
7327                       CYCLE
7328                    ENDIF
7329                 ENDIF
7330!
7331!--              write to the mrtf array
7332                 nmrtf = nmrtf + 1
7333!--              check dimmension of mrtf array and enlarge it if needed
7334                 IF ( nmrtfa < nmrtf )  THEN
7335                    k = CEILING(REAL(nmrtfa, kind=wp) * grow_factor)
7336                    IF ( mmrtf == 0 )  THEN
7337                       mmrtf = 1
7338                       ALLOCATE( amrtf1(k) )
7339                       amrtf => amrtf1
7340                       amrtf1(1:nmrtfa) = amrtf2
7341                       DEALLOCATE( amrtf2 )
7342                    ELSE
7343                       mmrtf = 0
7344                       ALLOCATE( amrtf2(k) )
7345                       amrtf => amrtf2
7346                       amrtf2(1:nmrtfa) = amrtf1
7347                       DEALLOCATE( amrtf1 )
7348                    ENDIF
7349
7350                    IF ( debug_output )  THEN
7351                       WRITE( debug_string, '(A,3I12)' ) 'Grow amrtf:', nmrtf, nmrtfa, k
7352                       CALL debug_message( debug_string, 'info' )
7353                    ENDIF
7354
7355                    nmrtfa = k
7356                 ENDIF
7357!--              write mrtf values into the array
7358                 amrtf(nmrtf)%isurflt = imrt
7359                 amrtf(nmrtf)%isurfs = itarget(i)
7360                 amrtf(nmrtf)%rsvf = vffrac(i)
7361                 amrtf(nmrtf)%rtransp = ztransp(i)
7362              ENDDO ! itarg
7363
7364           ENDDO ! imrt
7365           DEALLOCATE ( zdirs, zcent, zbdry, vffrac, vffrac0, ztransp, itarget )
7366!
7367!--        Move MRT factors to final arrays
7368           ALLOCATE ( mrtf(nmrtf), mrtft(nmrtf), mrtfsurf(2,nmrtf) )
7369           DO  imrtf = 1, nmrtf
7370              mrtf(imrtf) = amrtf(imrtf)%rsvf
7371              mrtft(imrtf) = amrtf(imrtf)%rsvf * amrtf(imrtf)%rtransp
7372              mrtfsurf(:,imrtf) = (/amrtf(imrtf)%isurflt, amrtf(imrtf)%isurfs /)
7373           ENDDO
7374           IF ( ALLOCATED(amrtf1) )  DEALLOCATE( amrtf1 )
7375           IF ( ALLOCATED(amrtf2) )  DEALLOCATE( amrtf2 )
7376        ENDIF ! nmrtbl > 0
7377
7378        IF ( rad_angular_discretization )  THEN
7379#if defined( __parallel )
7380!--        finalize MPI_RMA communication established to get global index of the surface from grid indices
7381!--        flush all MPI window pending requests
7382           CALL MPI_Win_flush_all(win_gridsurf, ierr)
7383           IF ( ierr /= 0 ) THEN
7384               WRITE(9,*) 'Error MPI_Win_flush_all1:', ierr, win_gridsurf
7385               FLUSH(9)
7386           ENDIF
7387!--        unlock MPI window
7388           CALL MPI_Win_unlock_all(win_gridsurf, ierr)
7389           IF ( ierr /= 0 ) THEN
7390               WRITE(9,*) 'Error MPI_Win_unlock_all1:', ierr, win_gridsurf
7391               FLUSH(9)
7392           ENDIF
7393!--        free MPI window
7394           CALL MPI_Win_free(win_gridsurf, ierr)
7395           IF ( ierr /= 0 ) THEN
7396               WRITE(9,*) 'Error MPI_Win_free1:', ierr, win_gridsurf
7397               FLUSH(9)
7398           ENDIF
7399#else
7400           DEALLOCATE ( gridsurf )
7401#endif
7402        ENDIF
7403
7404        IF ( debug_output )  CALL debug_message( 'waiting for completion of SVF and CSF calculation in all processes', 'info' )
7405
7406!--     deallocate temporary global arrays
7407        DEALLOCATE(nzterr)
7408       
7409        IF ( plant_canopy )  THEN
7410!--         finalize mpi_rma communication and deallocate temporary arrays
7411#if defined( __parallel )
7412            IF ( raytrace_mpi_rma )  THEN
7413                CALL MPI_Win_flush_all(win_lad, ierr)
7414                IF ( ierr /= 0 ) THEN
7415                    WRITE(9,*) 'Error MPI_Win_flush_all2:', ierr, win_lad
7416                    FLUSH(9)
7417                ENDIF
7418!--             unlock MPI window
7419                CALL MPI_Win_unlock_all(win_lad, ierr)
7420                IF ( ierr /= 0 ) THEN
7421                    WRITE(9,*) 'Error MPI_Win_unlock_all2:', ierr, win_lad
7422                    FLUSH(9)
7423                ENDIF
7424!--             free MPI window
7425                CALL MPI_Win_free(win_lad, ierr)
7426                IF ( ierr /= 0 ) THEN
7427                    WRITE(9,*) 'Error MPI_Win_free2:', ierr, win_lad
7428                    FLUSH(9)
7429                ENDIF
7430!--             deallocate temporary arrays storing values for csf calculation during raytracing
7431                DEALLOCATE( lad_s_ray )
7432!--             sub_lad is the pointer to lad_s_rma in case of raytrace_mpi_rma
7433!--             and must not be deallocated here
7434            ELSE
7435                DEALLOCATE(sub_lad)
7436                DEALLOCATE(sub_lad_g)
7437            ENDIF
7438#else
7439            DEALLOCATE(sub_lad)
7440#endif
7441            DEALLOCATE( boxes )
7442            DEALLOCATE( crlens )
7443            DEALLOCATE( plantt )
7444            DEALLOCATE( rt2_track, rt2_track_lad, rt2_track_dist, rt2_dist )
7445        ENDIF
7446
7447        IF ( debug_output )  CALL debug_message( 'calculation of the complete SVF array', 'info' )
7448
7449        IF ( rad_angular_discretization )  THEN
7450           IF ( debug_output )  CALL debug_message( 'Load svf from the structure array to plain arrays', 'info' )
7451           ALLOCATE( svf(ndsvf,nsvfl) )
7452           ALLOCATE( svfsurf(idsvf,nsvfl) )
7453
7454           DO isvf = 1, nsvfl
7455               svf(:, isvf) = (/ asvf(isvf)%rsvf, asvf(isvf)%rtransp /)
7456               svfsurf(:, isvf) = (/ asvf(isvf)%isurflt, asvf(isvf)%isurfs /)
7457           ENDDO
7458        ELSE
7459           IF ( debug_output )  CALL debug_message( 'Start SVF sort', 'info' )
7460!--        sort svf ( a version of quicksort )
7461           CALL quicksort_svf(asvf,1,nsvfl)
7462
7463           !< load svf from the structure array to plain arrays
7464           IF ( debug_output )  CALL debug_message( 'Load svf from the structure array to plain arrays', 'info' )
7465           ALLOCATE( svf(ndsvf,nsvfl) )
7466           ALLOCATE( svfsurf(idsvf,nsvfl) )
7467           svfnorm_counts(:) = 0._wp
7468           isurflt_prev = -1
7469           ksvf = 1
7470           svfsum = 0._wp
7471           DO isvf = 1, nsvfl
7472!--            normalize svf per target face
7473               IF ( asvf(ksvf)%isurflt /= isurflt_prev )  THEN
7474                   IF ( isurflt_prev /= -1  .AND.  svfsum /= 0._wp )  THEN
7475                       !< update histogram of logged svf normalization values
7476                       i = searchsorted(svfnorm_report_thresh, svfsum / (1._wp-skyvf(isurflt_prev)))
7477                       svfnorm_counts(i) = svfnorm_counts(i) + 1
7478
7479                       svf(1, isvf_surflt:isvf-1) = svf(1, isvf_surflt:isvf-1) / svfsum * (1._wp-skyvf(isurflt_prev))
7480                   ENDIF
7481                   isurflt_prev = asvf(ksvf)%isurflt
7482                   isvf_surflt = isvf
7483                   svfsum = asvf(ksvf)%rsvf !?? / asvf(ksvf)%rtransp
7484               ELSE
7485                   svfsum = svfsum + asvf(ksvf)%rsvf !?? / asvf(ksvf)%rtransp
7486               ENDIF
7487
7488               svf(:, isvf) = (/ asvf(ksvf)%rsvf, asvf(ksvf)%rtransp /)
7489               svfsurf(:, isvf) = (/ asvf(ksvf)%isurflt, asvf(ksvf)%isurfs /)
7490
7491!--            next element
7492               ksvf = ksvf + 1
7493           ENDDO
7494
7495           IF ( isurflt_prev /= -1  .AND.  svfsum /= 0._wp )  THEN
7496               i = searchsorted(svfnorm_report_thresh, svfsum / (1._wp-skyvf(isurflt_prev)))
7497               svfnorm_counts(i) = svfnorm_counts(i) + 1
7498
7499               svf(1, isvf_surflt:nsvfl) = svf(1, isvf_surflt:nsvfl) / svfsum * (1._wp-skyvf(isurflt_prev))
7500           ENDIF
7501           WRITE(9, *) 'SVF normalization histogram:', svfnorm_counts,  &
7502                       'on thresholds:', svfnorm_report_thresh(1:svfnorm_report_num), '(val < thresh <= val)'
7503           !TODO we should be able to deallocate skyvf, from now on we only need skyvft
7504        ENDIF ! rad_angular_discretization
7505
7506!--     deallocate temporary asvf array
7507!--     DEALLOCATE(asvf) - ifort has a problem with deallocation of allocatable target
7508!--     via pointing pointer - we need to test original targets
7509        IF ( ALLOCATED(asvf1) )  THEN
7510            DEALLOCATE(asvf1)
7511        ENDIF
7512        IF ( ALLOCATED(asvf2) )  THEN
7513            DEALLOCATE(asvf2)
7514        ENDIF
7515
7516        npcsfl = 0
7517        IF ( plant_canopy )  THEN
7518
7519            IF ( debug_output )  CALL debug_message( 'Calculation of the complete CSF array', 'info' )
7520!--         sort and merge csf for the last time, keeping the array size to minimum
7521            CALL merge_and_grow_csf(-1)
7522           
7523!--         aggregate csb among processors
7524!--         allocate necessary arrays
7525            udim = max(ncsfl,1)
7526            ALLOCATE( csflt_l(ndcsf*udim) )
7527            csflt(1:ndcsf,1:udim) => csflt_l(1:ndcsf*udim)
7528            ALLOCATE( kcsflt_l(kdcsf*udim) )
7529            kcsflt(1:kdcsf,1:udim) => kcsflt_l(1:kdcsf*udim)
7530            ALLOCATE( icsflt(0:numprocs-1) )
7531            ALLOCATE( dcsflt(0:numprocs-1) )
7532            ALLOCATE( ipcsflt(0:numprocs-1) )
7533            ALLOCATE( dpcsflt(0:numprocs-1) )
7534           
7535!--         fill out arrays of csf values and
7536!--         arrays of number of elements and displacements
7537!--         for particular precessors
7538            icsflt = 0
7539            dcsflt = 0
7540            ip = -1
7541            j = -1
7542            d = 0
7543            DO kcsf = 1, ncsfl
7544                j = j+1
7545                IF ( acsf(kcsf)%ip /= ip )  THEN
7546!--                 new block of the processor
7547!--                 number of elements of previous block
7548                    IF ( ip>=0) icsflt(ip) = j
7549                    d = d+j
7550!--                 blank blocks
7551                    DO jp = ip+1, acsf(kcsf)%ip-1
7552!--                     number of elements is zero, displacement is equal to previous
7553                        icsflt(jp) = 0
7554                        dcsflt(jp) = d
7555                    ENDDO
7556!--                 the actual block
7557                    ip = acsf(kcsf)%ip
7558                    dcsflt(ip) = d
7559                    j = 0
7560                ENDIF
7561                csflt(1,kcsf) = acsf(kcsf)%rcvf
7562!--             fill out integer values of itz,ity,itx,isurfs
7563                kcsflt(1,kcsf) = acsf(kcsf)%itz
7564                kcsflt(2,kcsf) = acsf(kcsf)%ity
7565                kcsflt(3,kcsf) = acsf(kcsf)%itx
7566                kcsflt(4,kcsf) = acsf(kcsf)%isurfs
7567            ENDDO
7568!--         last blank blocks at the end of array
7569            j = j+1
7570            IF ( ip>=0 ) icsflt(ip) = j
7571            d = d+j
7572            DO jp = ip+1, numprocs-1
7573!--             number of elements is zero, displacement is equal to previous
7574                icsflt(jp) = 0
7575                dcsflt(jp) = d
7576            ENDDO
7577           
7578!--         deallocate temporary acsf array
7579!--         DEALLOCATE(acsf) - ifort has a problem with deallocation of allocatable target
7580!--         via pointing pointer - we need to test original targets
7581            IF ( ALLOCATED(acsf1) )  THEN
7582                DEALLOCATE(acsf1)
7583            ENDIF
7584            IF ( ALLOCATED(acsf2) )  THEN
7585                DEALLOCATE(acsf2)
7586            ENDIF
7587                   
7588#if defined( __parallel )
7589!--         scatter and gather the number of elements to and from all processor
7590!--         and calculate displacements
7591            IF ( debug_output )  CALL debug_message( 'Scatter and gather the number of elements to and from all processor', 'info' )
7592
7593            CALL MPI_AlltoAll(icsflt,1,MPI_INTEGER,ipcsflt,1,MPI_INTEGER,comm2d, ierr)
7594
7595            IF ( ierr /= 0 ) THEN
7596                WRITE(9,*) 'Error MPI_AlltoAll1:', ierr, SIZE(icsflt), SIZE(ipcsflt)
7597                FLUSH(9)
7598            ENDIF
7599
7600            npcsfl = SUM(ipcsflt)
7601            d = 0
7602            DO i = 0, numprocs-1
7603                dpcsflt(i) = d
7604                d = d + ipcsflt(i)
7605            ENDDO
7606
7607!--         exchange csf fields between processors
7608            IF ( debug_output )  CALL debug_message( 'Exchange csf fields between processors', 'info' )
7609            udim = max(npcsfl,1)
7610            ALLOCATE( pcsflt_l(ndcsf*udim) )
7611            pcsflt(1:ndcsf,1:udim) => pcsflt_l(1:ndcsf*udim)
7612            ALLOCATE( kpcsflt_l(kdcsf*udim) )
7613            kpcsflt(1:kdcsf,1:udim) => kpcsflt_l(1:kdcsf*udim)
7614            CALL MPI_AlltoAllv(csflt_l, ndcsf*icsflt, ndcsf*dcsflt, MPI_REAL, &
7615                pcsflt_l, ndcsf*ipcsflt, ndcsf*dpcsflt, MPI_REAL, comm2d, ierr)
7616            IF ( ierr /= 0 ) THEN
7617                WRITE(9,*) 'Error MPI_AlltoAllv1:', ierr, SIZE(ipcsflt), ndcsf*icsflt, &
7618                            ndcsf*dcsflt, SIZE(pcsflt_l),ndcsf*ipcsflt, ndcsf*dpcsflt
7619                FLUSH(9)
7620            ENDIF
7621
7622            CALL MPI_AlltoAllv(kcsflt_l, kdcsf*icsflt, kdcsf*dcsflt, MPI_INTEGER, &
7623                kpcsflt_l, kdcsf*ipcsflt, kdcsf*dpcsflt, MPI_INTEGER, comm2d, ierr)
7624            IF ( ierr /= 0 ) THEN
7625                WRITE(9,*) 'Error MPI_AlltoAllv2:', ierr, SIZE(kcsflt_l),kdcsf*icsflt, &
7626                           kdcsf*dcsflt, SIZE(kpcsflt_l), kdcsf*ipcsflt, kdcsf*dpcsflt
7627                FLUSH(9)
7628            ENDIF
7629           
7630#else
7631            npcsfl = ncsfl
7632            ALLOCATE( pcsflt(ndcsf,max(npcsfl,ndcsf)) )
7633            ALLOCATE( kpcsflt(kdcsf,max(npcsfl,kdcsf)) )
7634            pcsflt = csflt
7635            kpcsflt = kcsflt
7636#endif
7637
7638!--         deallocate temporary arrays
7639            DEALLOCATE( csflt_l )
7640            DEALLOCATE( kcsflt_l )
7641            DEALLOCATE( icsflt )
7642            DEALLOCATE( dcsflt )
7643            DEALLOCATE( ipcsflt )
7644            DEALLOCATE( dpcsflt )
7645
7646!--         sort csf ( a version of quicksort )
7647            IF ( debug_output )  CALL debug_message( 'Sort csf', 'info' )
7648            CALL quicksort_csf2(kpcsflt, pcsflt, 1, npcsfl)
7649
7650!--         aggregate canopy sink factor records with identical box & source
7651!--         againg across all values from all processors
7652            IF ( debug_output )  CALL debug_message( 'Aggregate canopy sink factor records with identical box', 'info' )
7653
7654            IF ( npcsfl > 0 )  THEN
7655                icsf = 1 !< reading index
7656                kcsf = 1 !< writing index
7657                DO WHILE (icsf < npcsfl)
7658!--                 here kpcsf(kcsf) already has values from kpcsf(icsf)
7659                    IF ( kpcsflt(3,icsf) == kpcsflt(3,icsf+1)  .AND.  &
7660                         kpcsflt(2,icsf) == kpcsflt(2,icsf+1)  .AND.  &
7661                         kpcsflt(1,icsf) == kpcsflt(1,icsf+1)  .AND.  &
7662                         kpcsflt(4,icsf) == kpcsflt(4,icsf+1) )  THEN
7663
7664                        pcsflt(1,kcsf) = pcsflt(1,kcsf) + pcsflt(1,icsf+1)
7665
7666!--                     advance reading index, keep writing index
7667                        icsf = icsf + 1
7668                    ELSE
7669!--                     not identical, just advance and copy
7670                        icsf = icsf + 1
7671                        kcsf = kcsf + 1
7672                        kpcsflt(:,kcsf) = kpcsflt(:,icsf)
7673                        pcsflt(:,kcsf) = pcsflt(:,icsf)
7674                    ENDIF
7675                ENDDO
7676!--             last written item is now also the last item in valid part of array
7677                npcsfl = kcsf
7678            ENDIF
7679
7680            ncsfl = npcsfl
7681            IF ( ncsfl > 0 )  THEN
7682                ALLOCATE( csf(ndcsf,ncsfl) )
7683                ALLOCATE( csfsurf(idcsf,ncsfl) )
7684                DO icsf = 1, ncsfl
7685                    csf(:,icsf) = pcsflt(:,icsf)
7686                    csfsurf(1,icsf) =  gridpcbl(kpcsflt(1,icsf),kpcsflt(2,icsf),kpcsflt(3,icsf))
7687                    csfsurf(2,icsf) =  kpcsflt(4,icsf)
7688                ENDDO
7689            ENDIF
7690           
7691!--         deallocation of temporary arrays
7692            IF ( npcbl > 0 )  DEALLOCATE( gridpcbl )
7693            DEALLOCATE( pcsflt_l )
7694            DEALLOCATE( kpcsflt_l )
7695            IF ( debug_output )  CALL debug_message( 'End of aggregate csf', 'info' )
7696           
7697        ENDIF
7698
7699#if defined( __parallel )
7700        CALL MPI_BARRIER( comm2d, ierr )
7701#endif
7702        CALL location_message( 'calculating view factors for radiation interaction', 'finished' )
7703
7704        RETURN  !todo: remove
7705       
7706!        WRITE( message_string, * )  &
7707!            'I/O error when processing shape view factors / ',  &
7708!            'plant canopy sink factors / direct irradiance factors.'
7709!        CALL message( 'init_urban_surface', 'PA0502', 2, 2, 0, 6, 0 )
7710       
7711    END SUBROUTINE radiation_calc_svf
7712
7713   
7714!------------------------------------------------------------------------------!
7715! Description:
7716! ------------
7717!> Raytracing for detecting obstacles and calculating compound canopy sink
7718!> factors. (A simple obstacle detection would only need to process faces in
7719!> 3 dimensions without any ordering.)
7720!> Assumtions:
7721!> -----------
7722!> 1. The ray always originates from a face midpoint (only one coordinate equals
7723!>    *.5, i.e. wall) and doesn't travel parallel to the surface (that would mean
7724!>    shape factor=0). Therefore, the ray may never travel exactly along a face
7725!>    or an edge.
7726!> 2. From grid bottom to urban surface top the grid has to be *equidistant*
7727!>    within each of the dimensions, including vertical (but the resolution
7728!>    doesn't need to be the same in all three dimensions).
7729!------------------------------------------------------------------------------!
7730    SUBROUTINE raytrace(src, targ, isrc, difvf, atarg, create_csf, visible, transparency)
7731        IMPLICIT NONE
7732
7733        REAL(wp), DIMENSION(3), INTENT(in)     :: src, targ    !< real coordinates z,y,x
7734        INTEGER(iwp), INTENT(in)               :: isrc         !< index of source face for csf
7735        REAL(wp), INTENT(in)                   :: difvf        !< differential view factor for csf
7736        REAL(wp), INTENT(in)                   :: atarg        !< target surface area for csf
7737        LOGICAL, INTENT(in)                    :: create_csf   !< whether to generate new CSFs during raytracing
7738        LOGICAL, INTENT(out)                   :: visible
7739        REAL(wp), INTENT(out)                  :: transparency !< along whole path
7740        INTEGER(iwp)                           :: i, k, d
7741        INTEGER(iwp)                           :: seldim       !< dimension to be incremented
7742        INTEGER(iwp)                           :: ncsb         !< no of written plant canopy sinkboxes
7743        INTEGER(iwp)                           :: maxboxes     !< max no of gridboxes visited
7744        REAL(wp)                               :: distance     !< euclidean along path
7745        REAL(wp)                               :: crlen        !< length of gridbox crossing
7746        REAL(wp)                               :: lastdist     !< beginning of current crossing
7747        REAL(wp)                               :: nextdist     !< end of current crossing
7748        REAL(wp)                               :: realdist     !< distance in meters per unit distance
7749        REAL(wp)                               :: crmid        !< midpoint of crossing
7750        REAL(wp)                               :: cursink      !< sink factor for current canopy box
7751        REAL(wp), DIMENSION(3)                 :: delta        !< path vector
7752        REAL(wp), DIMENSION(3)                 :: uvect        !< unit vector
7753        REAL(wp), DIMENSION(3)                 :: dimnextdist  !< distance for each dimension increments
7754        INTEGER(iwp), DIMENSION(3)             :: box          !< gridbox being crossed
7755        INTEGER(iwp), DIMENSION(3)             :: dimnext      !< next dimension increments along path
7756        INTEGER(iwp), DIMENSION(3)             :: dimdelta     !< dimension direction = +- 1
7757        INTEGER(iwp)                           :: px, py       !< number of processors in x and y dir before
7758                                                               !< the processor in the question
7759        INTEGER(iwp)                           :: ip           !< number of processor where gridbox reside
7760        INTEGER(iwp)                           :: ig           !< 1D index of gridbox in global 2D array
7761       
7762        REAL(wp)                               :: eps = 1E-10_wp !< epsilon for value comparison
7763        REAL(wp)                               :: lad_s_target   !< recieved lad_s of particular grid box
7764
7765!
7766!--     Maximum number of gridboxes visited equals to maximum number of boundaries crossed in each dimension plus one. That's also
7767!--     the maximum number of plant canopy boxes written. We grow the acsf array accordingly using exponential factor.
7768        maxboxes = SUM(ABS(NINT(targ, iwp) - NINT(src, iwp))) + 1
7769        IF ( plant_canopy  .AND.  ncsfl + maxboxes > ncsfla )  THEN
7770!--         use this code for growing by fixed exponential increments (equivalent to case where ncsfl always increases by 1)
7771!--         k = CEILING(grow_factor ** real(CEILING(log(real(ncsfl + maxboxes, kind=wp)) &
7772!--                                                / log(grow_factor)), kind=wp))
7773!--         or use this code to simply always keep some extra space after growing
7774            k = CEILING(REAL(ncsfl + maxboxes, kind=wp) * grow_factor)
7775
7776            CALL merge_and_grow_csf(k)
7777        ENDIF
7778       
7779        transparency = 1._wp
7780        ncsb = 0
7781
7782        delta(:) = targ(:) - src(:)
7783        distance = SQRT(SUM(delta(:)**2))
7784        IF ( distance == 0._wp )  THEN
7785            visible = .TRUE.
7786            RETURN
7787        ENDIF
7788        uvect(:) = delta(:) / distance
7789        realdist = SQRT(SUM( (uvect(:)*(/dz(1),dy,dx/))**2 ))
7790
7791        lastdist = 0._wp
7792
7793!--     Since all face coordinates have values *.5 and we'd like to use
7794!--     integers, all these have .5 added
7795        DO d = 1, 3
7796            IF ( uvect(d) == 0._wp )  THEN
7797                dimnext(d) = 999999999
7798                dimdelta(d) = 999999999
7799                dimnextdist(d) = 1.0E20_wp
7800            ELSE IF ( uvect(d) > 0._wp )  THEN
7801                dimnext(d) = CEILING(src(d) + .5_wp)
7802                dimdelta(d) = 1
7803                dimnextdist(d) = (dimnext(d) - .5_wp - src(d)) / uvect(d)
7804            ELSE
7805                dimnext(d) = FLOOR(src(d) + .5_wp)
7806                dimdelta(d) = -1
7807                dimnextdist(d) = (dimnext(d) - .5_wp - src(d)) / uvect(d)
7808            ENDIF
7809        ENDDO
7810
7811        DO
7812!--         along what dimension will the next wall crossing be?
7813            seldim = minloc(dimnextdist, 1)
7814            nextdist = dimnextdist(seldim)
7815            IF ( nextdist > distance ) nextdist = distance
7816
7817            crlen = nextdist - lastdist
7818            IF ( crlen > .001_wp )  THEN
7819                crmid = (lastdist + nextdist) * .5_wp
7820                box = NINT(src(:) + uvect(:) * crmid, iwp)
7821
7822!--             calculate index of the grid with global indices (box(2),box(3))
7823!--             in the array nzterr and plantt and id of the coresponding processor
7824                px = box(3)/nnx
7825                py = box(2)/nny
7826                ip = px*pdims(2)+py
7827                ig = ip*nnx*nny + (box(3)-px*nnx)*nny + box(2)-py*nny
7828                IF ( box(1) <= nzterr(ig) )  THEN
7829                    visible = .FALSE.
7830                    RETURN
7831                ENDIF
7832
7833                IF ( plant_canopy )  THEN
7834                    IF ( box(1) <= plantt(ig) )  THEN
7835                        ncsb = ncsb + 1
7836                        boxes(:,ncsb) = box
7837                        crlens(ncsb) = crlen
7838#if defined( __parallel )
7839                        lad_ip(ncsb) = ip
7840                        lad_disp(ncsb) = (box(3)-px*nnx)*(nny*nz_plant) + (box(2)-py*nny)*nz_plant + box(1)-nz_urban_b
7841#endif
7842                    ENDIF
7843                ENDIF
7844            ENDIF
7845
7846            IF ( ABS(distance - nextdist) < eps )  EXIT
7847            lastdist = nextdist
7848            dimnext(seldim) = dimnext(seldim) + dimdelta(seldim)
7849            dimnextdist(seldim) = (dimnext(seldim) - .5_wp - src(seldim)) / uvect(seldim)
7850        ENDDO
7851       
7852        IF ( plant_canopy )  THEN
7853#if defined( __parallel )
7854            IF ( raytrace_mpi_rma )  THEN
7855!--             send requests for lad_s to appropriate processor
7856                CALL cpu_log( log_point_s(77), 'rad_rma_lad', 'start' )
7857                DO i = 1, ncsb
7858                    CALL MPI_Get(lad_s_ray(i), 1, MPI_REAL, lad_ip(i), lad_disp(i), &
7859                                 1, MPI_REAL, win_lad, ierr)
7860                    IF ( ierr /= 0 )  THEN
7861                        WRITE(9,*) 'Error MPI_Get1:', ierr, lad_s_ray(i), &
7862                                   lad_ip(i), lad_disp(i), win_lad
7863                        FLUSH(9)
7864                    ENDIF
7865                ENDDO
7866               
7867!--             wait for all pending local requests complete
7868                CALL MPI_Win_flush_local_all(win_lad, ierr)
7869                IF ( ierr /= 0 )  THEN
7870                    WRITE(9,*) 'Error MPI_Win_flush_local_all1:', ierr, win_lad
7871                    FLUSH(9)
7872                ENDIF
7873                CALL cpu_log( log_point_s(77), 'rad_rma_lad', 'stop' )
7874               
7875            ENDIF
7876#endif
7877
7878!--         calculate csf and transparency
7879            DO i = 1, ncsb
7880#if defined( __parallel )
7881                IF ( raytrace_mpi_rma )  THEN
7882                    lad_s_target = lad_s_ray(i)
7883                ELSE
7884                    lad_s_target = sub_lad_g(lad_ip(i)*nnx*nny*nz_plant + lad_disp(i))
7885                ENDIF
7886#else
7887                lad_s_target = sub_lad(boxes(1,i),boxes(2,i),boxes(3,i))
7888#endif
7889                cursink = 1._wp - exp(-ext_coef * lad_s_target * crlens(i)*realdist)
7890
7891                IF ( create_csf )  THEN
7892!--                 write svf values into the array
7893                    ncsfl = ncsfl + 1
7894                    acsf(ncsfl)%ip = lad_ip(i)
7895                    acsf(ncsfl)%itx = boxes(3,i)
7896                    acsf(ncsfl)%ity = boxes(2,i)
7897                    acsf(ncsfl)%itz = boxes(1,i)
7898                    acsf(ncsfl)%isurfs = isrc
7899                    acsf(ncsfl)%rcvf = cursink*transparency*difvf*atarg
7900                ENDIF  !< create_csf
7901
7902                transparency = transparency * (1._wp - cursink)
7903               
7904            ENDDO
7905        ENDIF
7906       
7907        visible = .TRUE.
7908
7909    END SUBROUTINE raytrace
7910   
7911 
7912!------------------------------------------------------------------------------!
7913! Description:
7914! ------------
7915!> A new, more efficient version of ray tracing algorithm that processes a whole
7916!> arc instead of a single ray.
7917!>
7918!> In all comments, horizon means tangent of horizon angle, i.e.
7919!> vertical_delta / horizontal_distance
7920!------------------------------------------------------------------------------!
7921   SUBROUTINE raytrace_2d(origin, yxdir, nrays, zdirs, iorig, aorig, vffrac,  &
7922                              calc_svf, create_csf, skip_1st_pcb,             &
7923                              lowest_free_ray, transparency, itarget)
7924      IMPLICIT NONE
7925
7926      REAL(wp), DIMENSION(3), INTENT(IN)     ::  origin        !< z,y,x coordinates of ray origin
7927      REAL(wp), DIMENSION(2), INTENT(IN)     ::  yxdir         !< y,x *unit* vector of ray direction (in grid units)
7928      INTEGER(iwp)                           ::  nrays         !< number of rays (z directions) to raytrace
7929      REAL(wp), DIMENSION(nrays), INTENT(IN) ::  zdirs         !< list of z directions to raytrace (z/hdist, grid, zenith->nadir)
7930      INTEGER(iwp), INTENT(in)               ::  iorig         !< index of origin face for csf
7931      REAL(wp), INTENT(in)                   ::  aorig         !< origin face area for csf
7932      REAL(wp), DIMENSION(nrays), INTENT(in) ::  vffrac        !< view factor fractions of each ray for csf
7933      LOGICAL, INTENT(in)                    ::  calc_svf      !< whether to calculate SFV (identify obstacle surfaces)
7934      LOGICAL, INTENT(in)                    ::  create_csf    !< whether to create canopy sink factors
7935      LOGICAL, INTENT(in)                    ::  skip_1st_pcb  !< whether to skip first plant canopy box during raytracing
7936      INTEGER(iwp), INTENT(out)              ::  lowest_free_ray !< index into zdirs
7937      REAL(wp), DIMENSION(nrays), INTENT(OUT) ::  transparency !< transparencies of zdirs paths
7938      INTEGER(iwp), DIMENSION(nrays), INTENT(OUT) ::  itarget  !< global indices of target faces for zdirs
7939
7940      INTEGER(iwp), DIMENSION(nrays)         ::  target_procs
7941      REAL(wp)                               ::  horizon       !< highest horizon found after raytracing (z/hdist)
7942      INTEGER(iwp)                           ::  i, k, l, d
7943      INTEGER(iwp)                           ::  seldim       !< dimension to be incremented
7944      REAL(wp), DIMENSION(2)                 ::  yxorigin     !< horizontal copy of origin (y,x)
7945      REAL(wp)                               ::  distance     !< euclidean along path
7946      REAL(wp)                               ::  lastdist     !< beginning of current crossing
7947      REAL(wp)                               ::  nextdist     !< end of current crossing
7948      REAL(wp)                               ::  crmid        !< midpoint of crossing
7949      REAL(wp)                               ::  horz_entry   !< horizon at entry to column
7950      REAL(wp)                               ::  horz_exit    !< horizon at exit from column
7951      REAL(wp)                               ::  bdydim       !< boundary for current dimension
7952      REAL(wp), DIMENSION(2)                 ::  crossdist    !< distances to boundary for dimensions
7953      REAL(wp), DIMENSION(2)                 ::  dimnextdist  !< distance for each dimension increments
7954      INTEGER(iwp), DIMENSION(2)             ::  column       !< grid column being crossed
7955      INTEGER(iwp), DIMENSION(2)             ::  dimnext      !< next dimension increments along path
7956      INTEGER(iwp), DIMENSION(2)             ::  dimdelta     !< dimension direction = +- 1
7957      INTEGER(iwp)                           ::  px, py       !< number of processors in x and y dir before
7958                                                              !< the processor in the question
7959      INTEGER(iwp)                           ::  ip           !< number of processor where gridbox reside
7960      INTEGER(iwp)                           ::  ig           !< 1D index of gridbox in global 2D array
7961      INTEGER(iwp)                           ::  wcount       !< RMA window item count
7962      INTEGER(iwp)                           ::  maxboxes     !< max no of CSF created
7963      INTEGER(iwp)                           ::  nly          !< maximum  plant canopy height
7964      INTEGER(iwp)                           ::  ntrack
7965     
7966      INTEGER(iwp)                           ::  zb0
7967      INTEGER(iwp)                           ::  zb1
7968      INTEGER(iwp)                           ::  nz
7969      INTEGER(iwp)                           ::  iz
7970      INTEGER(iwp)                           ::  zsgn
7971      INTEGER(iwp)                           ::  lowest_lad   !< lowest column cell for which we need LAD
7972      INTEGER(iwp)                           ::  lastdir      !< wall direction before hitting this column
7973      INTEGER(iwp), DIMENSION(2)             ::  lastcolumn
7974
7975#if defined( __parallel )
7976      INTEGER(MPI_ADDRESS_KIND)              ::  wdisp        !< RMA window displacement
7977#endif
7978     
7979      REAL(wp)                               ::  eps = 1E-10_wp !< epsilon for value comparison
7980      REAL(wp)                               ::  zbottom, ztop !< urban surface boundary in real numbers
7981      REAL(wp)                               ::  zorig         !< z coordinate of ray column entry
7982      REAL(wp)                               ::  zexit         !< z coordinate of ray column exit
7983      REAL(wp)                               ::  qdist         !< ratio of real distance to z coord difference
7984      REAL(wp)                               ::  dxxyy         !< square of real horizontal distance
7985      REAL(wp)                               ::  curtrans      !< transparency of current PC box crossing
7986     
7987
7988     
7989      yxorigin(:) = origin(2:3)
7990      transparency(:) = 1._wp !-- Pre-set the all rays to transparent before reducing
7991      horizon = -HUGE(1._wp)
7992      lowest_free_ray = nrays
7993      IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7994         ALLOCATE(target_surfl(nrays))
7995         target_surfl(:) = -1
7996         lastdir = -999
7997         lastcolumn(:) = -999
7998      ENDIF
7999
8000!--   Determine distance to boundary (in 2D xy)
8001      IF ( yxdir(1) > 0._wp )  THEN
8002         bdydim = ny + .5_wp !< north global boundary
8003         crossdist(1) = (bdydim - yxorigin(1)) / yxdir(1)
8004      ELSEIF ( yxdir(1) == 0._wp )  THEN
8005         crossdist(1) = HUGE(1._wp)
8006      ELSE
8007          bdydim = -.5_wp !< south global boundary
8008          crossdist(1) = (bdydim - yxorigin(1)) / yxdir(1)
8009      ENDIF
8010
8011      IF ( yxdir(2) > 0._wp )  THEN
8012          bdydim = nx + .5_wp !< east global boundary
8013          crossdist(2) = (bdydim - yxorigin(2)) / yxdir(2)
8014      ELSEIF ( yxdir(2) == 0._wp )  THEN
8015         crossdist(2) = HUGE(1._wp)
8016      ELSE
8017          bdydim = -.5_wp !< west global boundary
8018          crossdist(2) = (bdydim - yxorigin(2)) / yxdir(2)
8019      ENDIF
8020      distance = minval(crossdist, 1)
8021
8022      IF ( plant_canopy )  THEN
8023         rt2_track_dist(0) = 0._wp
8024         rt2_track_lad(:,:) = 0._wp
8025         nly = plantt_max - nz_urban_b + 1
8026      ENDIF
8027
8028      lastdist = 0._wp
8029
8030!--   Since all face coordinates have values *.5 and we'd like to use
8031!--   integers, all these have .5 added
8032      DO  d = 1, 2
8033          IF ( yxdir(d) == 0._wp )  THEN
8034              dimnext(d) = HUGE(1_iwp)
8035              dimdelta(d) = HUGE(1_iwp)
8036              dimnextdist(d) = HUGE(1._wp)
8037          ELSE IF ( yxdir(d) > 0._wp )  THEN
8038              dimnext(d) = FLOOR(yxorigin(d) + .5_wp) + 1
8039              dimdelta(d) = 1
8040              dimnextdist(d) = (dimnext(d) - .5_wp - yxorigin(d)) / yxdir(d)
8041          ELSE
8042              dimnext(d) = CEILING(yxorigin(d) + .5_wp) - 1
8043              dimdelta(d) = -1
8044              dimnextdist(d) = (dimnext(d) - .5_wp - yxorigin(d)) / yxdir(d)
8045          ENDIF
8046      ENDDO
8047
8048      ntrack = 0
8049      DO
8050!--      along what dimension will the next wall crossing be?
8051         seldim = minloc(dimnextdist, 1)
8052         nextdist = dimnextdist(seldim)
8053         IF ( nextdist > distance )  nextdist = distance
8054
8055         IF ( nextdist > lastdist )  THEN
8056            ntrack = ntrack + 1
8057            crmid = (lastdist + nextdist) * .5_wp
8058            column = NINT(yxorigin(:) + yxdir(:) * crmid, iwp)
8059
8060!--         calculate index of the grid with global indices (column(1),column(2))
8061!--         in the array nzterr and plantt and id of the coresponding processor
8062            px = column(2)/nnx
8063            py = column(1)/nny
8064            ip = px*pdims(2)+py
8065            ig = ip*nnx*nny + (column(2)-px*nnx)*nny + column(1)-py*nny
8066
8067            IF ( lastdist == 0._wp )  THEN
8068               horz_entry = -HUGE(1._wp)
8069            ELSE
8070               horz_entry = (REAL(nzterr(ig), wp) + .5_wp - origin(1)) / lastdist
8071            ENDIF
8072            horz_exit = (REAL(nzterr(ig), wp) + .5_wp - origin(1)) / nextdist
8073
8074            IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
8075!
8076!--            Identify vertical obstacles hit by rays in current column
8077               DO WHILE ( lowest_free_ray > 0 )
8078                  IF ( zdirs(lowest_free_ray) > horz_entry )  EXIT
8079!
8080!--               This may only happen after 1st column, so lastdir and lastcolumn are valid
8081                  CALL request_itarget(lastdir,                                         &
8082                        CEILING(-0.5_wp + origin(1) + zdirs(lowest_free_ray)*lastdist), &
8083                        lastcolumn(1), lastcolumn(2),                                   &
8084                        target_surfl(lowest_free_ray), target_procs(lowest_free_ray))
8085                  lowest_free_ray = lowest_free_ray - 1
8086               ENDDO
8087!
8088!--            Identify horizontal obstacles hit by rays in current column
8089               DO WHILE ( lowest_free_ray > 0 )
8090                  IF ( zdirs(lowest_free_ray) > horz_exit )  EXIT
8091                  CALL request_itarget(iup_u, nzterr(ig)+1, column(1), column(2), &
8092                                       target_surfl(lowest_free_ray),           &
8093                                       target_procs(lowest_free_ray))
8094                  lowest_free_ray = lowest_free_ray - 1
8095               ENDDO
8096            ENDIF
8097
8098            horizon = MAX(horizon, horz_entry, horz_exit)
8099
8100            IF ( plant_canopy )  THEN
8101               rt2_track(:, ntrack) = column(:)
8102               rt2_track_dist(ntrack) = nextdist
8103            ENDIF
8104         ENDIF
8105
8106         IF ( nextdist + eps >= distance )  EXIT
8107
8108         IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
8109!
8110!--         Save wall direction of coming building column (= this air column)
8111            IF ( seldim == 1 )  THEN
8112               IF ( dimdelta(seldim) == 1 )  THEN
8113                  lastdir = isouth_u
8114               ELSE
8115                  lastdir = inorth_u
8116               ENDIF
8117            ELSE
8118               IF ( dimdelta(seldim) == 1 )  THEN
8119                  lastdir = iwest_u
8120               ELSE
8121                  lastdir = ieast_u
8122               ENDIF
8123            ENDIF
8124            lastcolumn = column
8125         ENDIF
8126         lastdist = nextdist
8127         dimnext(seldim) = dimnext(seldim) + dimdelta(seldim)
8128         dimnextdist(seldim) = (dimnext(seldim) - .5_wp - yxorigin(seldim)) / yxdir(seldim)
8129      ENDDO
8130
8131      IF ( plant_canopy )  THEN
8132!--      Request LAD WHERE applicable
8133!--     
8134#if defined( __parallel )
8135         IF ( raytrace_mpi_rma )  THEN
8136!--         send requests for lad_s to appropriate processor
8137            !CALL cpu_log( log_point_s(77), 'usm_init_rma', 'start' )
8138            DO  i = 1, ntrack
8139               px = rt2_track(2,i)/nnx
8140               py = rt2_track(1,i)/nny
8141               ip = px*pdims(2)+py
8142               ig = ip*nnx*nny + (rt2_track(2,i)-px*nnx)*nny + rt2_track(1,i)-py*nny
8143
8144               IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
8145!
8146!--               For fixed view resolution, we need plant canopy even for rays
8147!--               to opposing surfaces
8148                  lowest_lad = nzterr(ig) + 1
8149               ELSE
8150!
8151!--               We only need LAD for rays directed above horizon (to sky)
8152                  lowest_lad = CEILING( -0.5_wp + origin(1) +            &
8153                                    MIN( horizon * rt2_track_dist(i-1),  & ! entry
8154                                         horizon * rt2_track_dist(i)   ) ) ! exit
8155               ENDIF
8156!
8157!--            Skip asking for LAD where all plant canopy is under requested level
8158               IF ( plantt(ig) < lowest_lad )  CYCLE
8159
8160               wdisp = (rt2_track(2,i)-px*nnx)*(nny*nz_plant) + (rt2_track(1,i)-py*nny)*nz_plant + lowest_lad-nz_urban_b
8161               wcount = plantt(ig)-lowest_lad+1
8162               ! TODO send request ASAP - even during raytracing
8163               CALL MPI_Get(rt2_track_lad(lowest_lad:plantt(ig), i), wcount, MPI_REAL, ip,    &
8164                            wdisp, wcount, MPI_REAL, win_lad, ierr)
8165               IF ( ierr /= 0 )  THEN
8166                  WRITE(9,*) 'Error MPI_Get2:', ierr, rt2_track_lad(lowest_lad:plantt(ig), i), &
8167                             wcount, ip, wdisp, win_lad
8168                  FLUSH(9)
8169               ENDIF
8170            ENDDO
8171
8172!--         wait for all pending local requests complete
8173            ! TODO WAIT selectively for each column later when needed
8174            CALL MPI_Win_flush_local_all(win_lad, ierr)
8175            IF ( ierr /= 0 )  THEN
8176               WRITE(9,*) 'Error MPI_Win_flush_local_all2:', ierr, win_lad
8177               FLUSH(9)
8178            ENDIF
8179            !CALL cpu_log( log_point_s(77), 'usm_init_rma', 'stop' )
8180
8181         ELSE ! raytrace_mpi_rma = .F.
8182            DO  i = 1, ntrack
8183               px = rt2_track(2,i)/nnx
8184               py = rt2_track(1,i)/nny
8185               ip = px*pdims(2)+py
8186               ig = ip*nnx*nny*nz_plant + (rt2_track(2,i)-px*nnx)*(nny*nz_plant) + (rt2_track(1,i)-py*nny)*nz_plant
8187               rt2_track_lad(nz_urban_b:plantt_max, i) = sub_lad_g(ig:ig+nly-1)
8188            ENDDO
8189         ENDIF
8190#else
8191         DO  i = 1, ntrack
8192            rt2_track_lad(nz_urban_b:plantt_max, i) = sub_lad(rt2_track(1,i), rt2_track(2,i), nz_urban_b:plantt_max)
8193         ENDDO
8194#endif
8195      ENDIF ! plant_canopy
8196
8197      IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
8198#if defined( __parallel )
8199!--      wait for all gridsurf requests to complete
8200         CALL MPI_Win_flush_local_all(win_gridsurf, ierr)
8201         IF ( ierr /= 0 )  THEN
8202            WRITE(9,*) 'Error MPI_Win_flush_local_all3:', ierr, win_gridsurf
8203            FLUSH(9)
8204         ENDIF
8205#endif
8206!
8207!--      recalculate local surf indices into global ones
8208         DO i = 1, nrays
8209            IF ( target_surfl(i) == -1 )  THEN
8210               itarget(i) = -1
8211            ELSE
8212               itarget(i) = target_surfl(i) + surfstart(target_procs(i))
8213            ENDIF
8214         ENDDO
8215         
8216         DEALLOCATE( target_surfl )
8217         
8218      ELSE
8219         itarget(:) = -1
8220      ENDIF ! rad_angular_discretization
8221
8222      IF ( plant_canopy )  THEN
8223!--      Skip the PCB around origin if requested (for MRT, the PCB might not be there)
8224!--     
8225         IF ( skip_1st_pcb  .AND.  NINT(origin(1)) <= plantt_max )  THEN
8226            rt2_track_lad(NINT(origin(1), iwp), 1) = 0._wp
8227         ENDIF
8228
8229!--      Assert that we have space allocated for CSFs
8230!--     
8231         maxboxes = (ntrack + MAX(CEILING(origin(1)-.5_wp) - nz_urban_b,          &
8232                                  nz_urban_t - CEILING(origin(1)-.5_wp))) * nrays
8233         IF ( ncsfl + maxboxes > ncsfla )  THEN
8234!--         use this code for growing by fixed exponential increments (equivalent to case where ncsfl always increases by 1)
8235!--         k = CEILING(grow_factor ** real(CEILING(log(real(ncsfl + maxboxes, kind=wp)) &
8236!--                                                / log(grow_factor)), kind=wp))
8237!--         or use this code to simply always keep some extra space after growing
8238            k = CEILING(REAL(ncsfl + maxboxes, kind=wp) * grow_factor)
8239            CALL merge_and_grow_csf(k)
8240         ENDIF
8241
8242!--      Calculate transparencies and store new CSFs
8243!--     
8244         zbottom = REAL(nz_urban_b, wp) - .5_wp
8245         ztop = REAL(plantt_max, wp) + .5_wp
8246
8247!--      Reverse direction of radiation (face->sky), only when calc_svf
8248!--     
8249         IF ( calc_svf )  THEN
8250            DO  i = 1, ntrack ! for each column
8251               dxxyy = ((dy*yxdir(1))**2 + (dx*yxdir(2))**2) * (rt2_track_dist(i)-rt2_track_dist(i-1))**2
8252               px = rt2_track(2,i)/nnx
8253               py = rt2_track(1,i)/nny
8254               ip = px*pdims(2)+py
8255
8256               DO  k = 1, nrays ! for each ray
8257!
8258!--               NOTE 6778:
8259!--               With traditional svf discretization, CSFs under the horizon
8260!--               (i.e. for surface to surface radiation)  are created in
8261!--               raytrace(). With rad_angular_discretization, we must create
8262!--               CSFs under horizon only for one direction, otherwise we would
8263!--               have duplicate amount of energy. Although we could choose
8264!--               either of the two directions (they differ only by
8265!--               discretization error with no bias), we choose the the backward
8266!--               direction, because it tends to cumulate high canopy sink
8267!--               factors closer to raytrace origin, i.e. it should potentially
8268!--               cause less moiree.
8269                  IF ( .NOT. rad_angular_discretization )  THEN
8270                     IF ( zdirs(k) <= horizon )  CYCLE
8271                  ENDIF
8272
8273                  zorig = origin(1) + zdirs(k) * rt2_track_dist(i-1)
8274                  IF ( zorig <= zbottom  .OR.  zorig >= ztop )  CYCLE
8275
8276                  zsgn = INT(SIGN(1._wp, zdirs(k)), iwp)
8277                  rt2_dist(1) = 0._wp
8278                  IF ( zdirs(k) == 0._wp )  THEN ! ray is exactly horizontal
8279                     nz = 2
8280                     rt2_dist(nz) = SQRT(dxxyy)
8281                     iz = CEILING(-.5_wp + zorig, iwp)
8282                  ELSE
8283                     zexit = MIN(MAX(origin(1) + zdirs(k) * rt2_track_dist(i), zbottom), ztop)
8284
8285                     zb0 = FLOOR(  zorig * zsgn - .5_wp) + 1  ! because it must be greater than orig
8286                     zb1 = CEILING(zexit * zsgn - .5_wp) - 1  ! because it must be smaller than exit
8287                     nz = MAX(zb1 - zb0 + 3, 2)
8288                     rt2_dist(nz) = SQRT(((zexit-zorig)*dz(1))**2 + dxxyy)
8289                     qdist = rt2_dist(nz) / (zexit-zorig)
8290                     rt2_dist(2:nz-1) = (/( ((REAL(l, wp) + .5_wp) * zsgn - zorig) * qdist , l = zb0, zb1 )/)
8291                     iz = zb0 * zsgn
8292                  ENDIF
8293
8294                  DO  l = 2, nz
8295                     IF ( rt2_track_lad(iz, i) > 0._wp )  THEN
8296                        curtrans = exp(-ext_coef * rt2_track_lad(iz, i) * (rt2_dist(l)-rt2_dist(l-1)))
8297
8298                        IF ( create_csf )  THEN
8299                           ncsfl = ncsfl + 1
8300                           acsf(ncsfl)%ip = ip
8301                           acsf(ncsfl)%itx = rt2_track(2,i)
8302                           acsf(ncsfl)%ity = rt2_track(1,i)
8303                           acsf(ncsfl)%itz = iz
8304                           acsf(ncsfl)%isurfs = iorig
8305                           acsf(ncsfl)%rcvf = (1._wp - curtrans)*transparency(k)*vffrac(k)
8306                        ENDIF
8307
8308                        transparency(k) = transparency(k) * curtrans
8309                     ENDIF
8310                     iz = iz + zsgn
8311                  ENDDO ! l = 1, nz - 1
8312               ENDDO ! k = 1, nrays
8313            ENDDO ! i = 1, ntrack
8314
8315            transparency(1:lowest_free_ray) = 1._wp !-- Reset rays above horizon to transparent (see NOTE 6778)
8316         ENDIF
8317
8318!--      Forward direction of radiation (sky->face), always
8319!--     
8320         DO  i = ntrack, 1, -1 ! for each column backwards
8321            dxxyy = ((dy*yxdir(1))**2 + (dx*yxdir(2))**2) * (rt2_track_dist(i)-rt2_track_dist(i-1))**2
8322            px = rt2_track(2,i)/nnx
8323            py = rt2_track(1,i)/nny
8324            ip = px*pdims(2)+py
8325
8326            DO  k = 1, nrays ! for each ray
8327!
8328!--            See NOTE 6778 above
8329               IF ( zdirs(k) <= horizon )  CYCLE
8330
8331               zexit = origin(1) + zdirs(k) * rt2_track_dist(i-1)
8332               IF ( zexit <= zbottom  .OR.  zexit >= ztop )  CYCLE
8333
8334               zsgn = -INT(SIGN(1._wp, zdirs(k)), iwp)
8335               rt2_dist(1) = 0._wp
8336               IF ( zdirs(k) == 0._wp )  THEN ! ray is exactly horizontal
8337                  nz = 2
8338                  rt2_dist(nz) = SQRT(dxxyy)
8339                  iz = NINT(zexit, iwp)
8340               ELSE
8341                  zorig = MIN(MAX(origin(1) + zdirs(k) * rt2_track_dist(i), zbottom), ztop)
8342
8343                  zb0 = FLOOR(  zorig * zsgn - .5_wp) + 1  ! because it must be greater than orig
8344                  zb1 = CEILING(zexit * zsgn - .5_wp) - 1  ! because it must be smaller than exit
8345                  nz = MAX(zb1 - zb0 + 3, 2)
8346                  rt2_dist(nz) = SQRT(((zexit-zorig)*dz(1))**2 + dxxyy)
8347                  qdist = rt2_dist(nz) / (zexit-zorig)
8348                  rt2_dist(2:nz-1) = (/( ((REAL(l, wp) + .5_wp) * zsgn - zorig) * qdist , l = zb0, zb1 )/)
8349                  iz = zb0 * zsgn
8350               ENDIF
8351
8352               DO  l = 2, nz
8353                  IF ( rt2_track_lad(iz, i) > 0._wp )  THEN
8354                     curtrans = exp(-ext_coef * rt2_track_lad(iz, i) * (rt2_dist(l)-rt2_dist(l-1)))
8355
8356                     IF ( create_csf )  THEN
8357                        ncsfl = ncsfl + 1
8358                        acsf(ncsfl)%ip = ip
8359                        acsf(ncsfl)%itx = rt2_track(2,i)
8360                        acsf(ncsfl)%ity = rt2_track(1,i)
8361                        acsf(ncsfl)%itz = iz
8362                        IF ( itarget(k) /= -1 ) STOP 1 !FIXME remove after test
8363                        acsf(ncsfl)%isurfs = -1
8364                        acsf(ncsfl)%rcvf = (1._wp - curtrans)*transparency(k)*aorig*vffrac(k)
8365                     ENDIF  ! create_csf
8366
8367                     transparency(k) = transparency(k) * curtrans
8368                  ENDIF
8369                  iz = iz + zsgn
8370               ENDDO ! l = 1, nz - 1
8371            ENDDO ! k = 1, nrays
8372         ENDDO ! i = 1, ntrack
8373      ENDIF ! plant_canopy
8374
8375      IF ( .NOT. (rad_angular_discretization  .AND.  calc_svf) )  THEN
8376!
8377!--      Just update lowest_free_ray according to horizon
8378         DO WHILE ( lowest_free_ray > 0 )
8379            IF ( zdirs(lowest_free_ray) > horizon )  EXIT
8380            lowest_free_ray = lowest_free_ray - 1
8381         ENDDO
8382      ENDIF
8383
8384   CONTAINS
8385
8386      SUBROUTINE request_itarget( d, z, y, x, isurfl, iproc )
8387
8388         INTEGER(iwp), INTENT(in)            ::  d, z, y, x
8389         INTEGER(iwp), TARGET, INTENT(out)   ::  isurfl
8390         INTEGER(iwp), INTENT(out)           ::  iproc
8391#if defined( __parallel )
8392#else
8393         INTEGER(iwp)                        ::  target_displ  !< index of the grid in the local gridsurf array
8394#endif
8395         INTEGER(iwp)                        ::  px, py        !< number of processors in x and y direction
8396                                                               !< before the processor in the question
8397#if defined( __parallel )
8398         INTEGER(KIND=MPI_ADDRESS_KIND)      ::  target_displ  !< index of the grid in the local gridsurf array
8399
8400!
8401!--      Calculate target processor and index in the remote local target gridsurf array
8402         px = x / nnx
8403         py = y / nny
8404         iproc = px * pdims(2) + py
8405         target_displ = ((x-px*nnx) * nny + y - py*nny ) * nz_urban * nsurf_type_u +&
8406                        ( z-nz_urban_b ) * nsurf_type_u + d
8407!
8408!--      Send MPI_Get request to obtain index target_surfl(i)
8409         CALL MPI_GET( isurfl, 1, MPI_INTEGER, iproc, target_displ,            &
8410                       1, MPI_INTEGER, win_gridsurf, ierr)
8411         IF ( ierr /= 0 )  THEN
8412            WRITE( 9,* ) 'Error MPI_Get3:', ierr, isurfl, iproc, target_displ, &
8413                         win_gridsurf
8414            FLUSH( 9 )
8415         ENDIF
8416#else
8417!--      set index target_surfl(i)
8418         isurfl = gridsurf(d,z,y,x)
8419#endif
8420
8421      END SUBROUTINE request_itarget
8422
8423   END SUBROUTINE raytrace_2d
8424 
8425
8426!------------------------------------------------------------------------------!
8427!
8428! Description:
8429! ------------
8430!> Calculates apparent solar positions for all timesteps and stores discretized
8431!> positions.
8432!------------------------------------------------------------------------------!
8433   SUBROUTINE radiation_presimulate_solar_pos
8434
8435      IMPLICIT NONE
8436
8437      INTEGER(iwp)                              ::  it, i, j
8438      INTEGER(iwp)                              ::  day_of_month_prev,month_of_year_prev
8439      REAL(wp)                                  ::  tsrp_prev
8440      REAL(wp)                                  ::  simulated_time_prev
8441      REAL(wp), DIMENSION(:,:), ALLOCATABLE     ::  dsidir_tmp       !< dsidir_tmp[:,i] = unit vector of i-th
8442                                                                     !< appreant solar direction
8443
8444      ALLOCATE ( dsidir_rev(0:raytrace_discrete_elevs/2-1,                 &
8445                            0:raytrace_discrete_azims-1) )
8446      dsidir_rev(:,:) = -1
8447      ALLOCATE ( dsidir_tmp(3,                                             &
8448                     raytrace_discrete_elevs/2*raytrace_discrete_azims) )
8449      ndsidir = 0
8450
8451!
8452!--   We will artificialy update time_since_reference_point and return to
8453!--   true value later
8454      tsrp_prev = time_since_reference_point
8455      simulated_time_prev = simulated_time
8456      day_of_month_prev = day_of_month
8457      month_of_year_prev = month_of_year
8458      sun_direction = .TRUE.
8459
8460!
8461!--   initialize the simulated_time
8462      simulated_time = 0._wp
8463!
8464!--   Process spinup time if configured
8465      IF ( spinup_time > 0._wp )  THEN
8466         DO  it = 0, CEILING(spinup_time / dt_spinup)
8467            time_since_reference_point = -spinup_time + REAL(it, wp) * dt_spinup
8468            simulated_time = simulated_time + dt_spinup
8469            CALL simulate_pos
8470         ENDDO
8471      ENDIF
8472!
8473!--   Process simulation time
8474      DO  it = 0, CEILING(( end_time - spinup_time ) / dt_radiation)
8475         time_since_reference_point = REAL(it, wp) * dt_radiation
8476         simulated_time = simulated_time + dt_radiation
8477         CALL simulate_pos
8478      ENDDO
8479!
8480!--   Return date and time to its original values
8481      time_since_reference_point = tsrp_prev
8482      simulated_time = simulated_time_prev
8483      day_of_month = day_of_month_prev
8484      month_of_year = month_of_year_prev
8485      CALL init_date_and_time
8486
8487!--   Allocate global vars which depend on ndsidir
8488      ALLOCATE ( dsidir ( 3, ndsidir ) )
8489      dsidir(:,:) = dsidir_tmp(:, 1:ndsidir)
8490      DEALLOCATE ( dsidir_tmp )
8491
8492      ALLOCATE ( dsitrans(nsurfl, ndsidir) )
8493      ALLOCATE ( dsitransc(npcbl, ndsidir) )
8494      IF ( nmrtbl > 0 )  ALLOCATE ( mrtdsit(nmrtbl, ndsidir) )
8495
8496      WRITE ( message_string, * ) 'Precalculated', ndsidir, ' solar positions', &
8497                                  ' from', it, ' timesteps.'
8498      CALL message( 'radiation_presimulate_solar_pos', 'UI0013', 0, 0, 0, 6, 0 )
8499
8500      CONTAINS
8501
8502      !------------------------------------------------------------------------!
8503      ! Description:
8504      ! ------------
8505      !> Simuates a single position
8506      !------------------------------------------------------------------------!
8507      SUBROUTINE simulate_pos
8508         IMPLICIT NONE
8509!
8510!--      Update apparent solar position based on modified t_s_r_p
8511         CALL calc_zenith
8512         IF ( cos_zenith > 0 )  THEN
8513!--         
8514!--         Identify solar direction vector (discretized number) 1)
8515            i = MODULO(NINT(ATAN2(sun_dir_lon, sun_dir_lat)               &
8516                            / (2._wp*pi) * raytrace_discrete_azims-.5_wp, iwp), &
8517                       raytrace_discrete_azims)
8518            j = FLOOR(ACOS(cos_zenith) / pi * raytrace_discrete_elevs)
8519            IF ( dsidir_rev(j, i) == -1 )  THEN
8520               ndsidir = ndsidir + 1
8521               dsidir_tmp(:, ndsidir) =                                              &
8522                     (/ COS((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs), &
8523                        SIN((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs)  &
8524                      * COS((REAL(i,wp)+.5_wp) * 2_wp*pi / raytrace_discrete_azims), &
8525                        SIN((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs)  &
8526                      * SIN((REAL(i,wp)+.5_wp) * 2_wp*pi / raytrace_discrete_azims) /)
8527               dsidir_rev(j, i) = ndsidir
8528            ENDIF
8529         ENDIF
8530      END SUBROUTINE simulate_pos
8531
8532   END SUBROUTINE radiation_presimulate_solar_pos
8533
8534
8535
8536!------------------------------------------------------------------------------!
8537! Description:
8538! ------------
8539!> Determines whether two faces are oriented towards each other. Since the
8540!> surfaces follow the gird box surfaces, it checks first whether the two surfaces
8541!> are directed in the same direction, then it checks if the two surfaces are
8542!> located in confronted direction but facing away from each other, e.g. <--| |-->
8543!------------------------------------------------------------------------------!
8544    PURE LOGICAL FUNCTION surface_facing(x, y, z, d, x2, y2, z2, d2)
8545        IMPLICIT NONE
8546        INTEGER(iwp),   INTENT(in)  :: x, y, z, d, x2, y2, z2, d2
8547     
8548        surface_facing = .FALSE.
8549
8550!-- first check: are the two surfaces directed in the same direction
8551        IF ( (d==iup_u  .OR.  d==iup_l )                             &
8552             .AND. (d2==iup_u  .OR. d2==iup_l) ) RETURN
8553        IF ( (d==isouth_u  .OR.  d==isouth_l ) &
8554             .AND.  (d2==isouth_u  .OR.  d2==isouth_l) ) RETURN
8555        IF ( (d==inorth_u  .OR.  d==inorth_l ) &
8556             .AND.  (d2==inorth_u  .OR.  d2==inorth_l) ) RETURN
8557        IF ( (d==iwest_u  .OR.  d==iwest_l )     &
8558             .AND.  (d2==iwest_u  .OR.  d2==iwest_l ) ) RETURN
8559        IF ( (d==ieast_u  .OR.  d==ieast_l )     &
8560             .AND.  (d2==ieast_u  .OR.  d2==ieast_l ) ) RETURN
8561
8562!-- second check: are surfaces facing away from each other
8563        SELECT CASE (d)
8564            CASE (iup_u, iup_l)                     !< upward facing surfaces
8565                IF ( z2 < z ) RETURN
8566            CASE (isouth_u, isouth_l)               !< southward facing surfaces
8567                IF ( y2 > y ) RETURN
8568            CASE (inorth_u, inorth_l)               !< northward facing surfaces
8569                IF ( y2 < y ) RETURN
8570            CASE (iwest_u, iwest_l)                 !< westward facing surfaces
8571                IF ( x2 > x ) RETURN
8572            CASE (ieast_u, ieast_l)                 !< eastward facing surfaces
8573                IF ( x2 < x ) RETURN
8574        END SELECT
8575
8576        SELECT CASE (d2)
8577            CASE (iup_u)                            !< ground, roof
8578                IF ( z < z2 ) RETURN
8579            CASE (isouth_u, isouth_l)               !< south facing
8580                IF ( y > y2 ) RETURN
8581            CASE (inorth_u, inorth_l)               !< north facing
8582                IF ( y < y2 ) RETURN
8583            CASE (iwest_u, iwest_l)                 !< west facing
8584                IF ( x > x2 ) RETURN
8585            CASE (ieast_u, ieast_l)                 !< east facing
8586                IF ( x < x2 ) RETURN
8587            CASE (-1)
8588                CONTINUE
8589        END SELECT
8590
8591        surface_facing = .TRUE.
8592       
8593    END FUNCTION surface_facing
8594
8595
8596!------------------------------------------------------------------------------!
8597!
8598! Description:
8599! ------------
8600!> Reads svf, svfsurf, csf, csfsurf and mrt factors data from saved file
8601!> SVF means sky view factors and CSF means canopy sink factors
8602!------------------------------------------------------------------------------!
8603    SUBROUTINE radiation_read_svf
8604
8605       IMPLICIT NONE
8606       
8607       CHARACTER(rad_version_len)   :: rad_version_field
8608       
8609       INTEGER(iwp)                 :: i
8610       INTEGER(iwp)                 :: ndsidir_from_file = 0
8611       INTEGER(iwp)                 :: npcbl_from_file = 0
8612       INTEGER(iwp)                 :: nsurfl_from_file = 0
8613       INTEGER(iwp)                 :: nmrtbl_from_file = 0
8614
8615
8616       CALL location_message( 'reading view factors for radiation interaction', 'start' )
8617
8618       DO  i = 0, io_blocks-1
8619          IF ( i == io_group )  THEN
8620
8621!
8622!--          numprocs_previous_run is only known in case of reading restart
8623!--          data. If a new initial run which reads svf data is started the
8624!--          following query will be skipped
8625             IF ( initializing_actions == 'read_restart_data' ) THEN
8626
8627                IF ( numprocs_previous_run /= numprocs ) THEN
8628                   WRITE( message_string, * ) 'A different number of ',        &
8629                                              'processors between the run ',   &
8630                                              'that has written the svf data ',&
8631                                              'and the one that will read it ',&
8632                                              'is not allowed' 
8633                   CALL message( 'check_open', 'PA0491', 1, 2, 0, 6, 0 )
8634                ENDIF
8635
8636             ENDIF
8637             
8638!
8639!--          Open binary file
8640             CALL check_open( 88 )
8641
8642!
8643!--          read and check version
8644             READ ( 88 ) rad_version_field
8645             IF ( TRIM(rad_version_field) /= TRIM(rad_version) )  THEN
8646                 WRITE( message_string, * ) 'Version of binary SVF file "',    &
8647                             TRIM(rad_version_field), '" does not match ',     &
8648                             'the version of model "', TRIM(rad_version), '"'
8649                 CALL message( 'radiation_read_svf', 'PA0482', 1, 2, 0, 6, 0 )
8650             ENDIF
8651             
8652!
8653!--          read nsvfl, ncsfl, nsurfl, nmrtf
8654             READ ( 88 ) nsvfl, ncsfl, nsurfl_from_file, npcbl_from_file,      &
8655                         ndsidir_from_file, nmrtbl_from_file, nmrtf
8656             
8657             IF ( nsvfl < 0  .OR.  ncsfl < 0 )  THEN
8658                 WRITE( message_string, * ) 'Wrong number of SVF or CSF'
8659                 CALL message( 'radiation_read_svf', 'PA0483', 1, 2, 0, 6, 0 )
8660             ELSE
8661                 WRITE(debug_string,*)   'Number of SVF, CSF, and nsurfl ',    &
8662                                         'to read', nsvfl, ncsfl,              &
8663                                         nsurfl_from_file
8664                 IF ( debug_output )  CALL debug_message( debug_string, 'info' )
8665             ENDIF
8666             
8667             IF ( nsurfl_from_file /= nsurfl )  THEN
8668                 WRITE( message_string, * ) 'nsurfl from SVF file does not ',  &
8669                                            'match calculated nsurfl from ',   &
8670                                            'radiation_interaction_init'
8671                 CALL message( 'radiation_read_svf', 'PA0490', 1, 2, 0, 6, 0 )
8672             ENDIF
8673             
8674             IF ( npcbl_from_file /= npcbl )  THEN
8675                 WRITE( message_string, * ) 'npcbl from SVF file does not ',   &
8676                                            'match calculated npcbl from ',    &
8677                                            'radiation_interaction_init'
8678                 CALL message( 'radiation_read_svf', 'PA0493', 1, 2, 0, 6, 0 )
8679             ENDIF
8680             
8681             IF ( ndsidir_from_file /= ndsidir )  THEN
8682                 WRITE( message_string, * ) 'ndsidir from SVF file does not ', &
8683                                            'match calculated ndsidir from ',  &
8684                                            'radiation_presimulate_solar_pos'
8685                 CALL message( 'radiation_read_svf', 'PA0494', 1, 2, 0, 6, 0 )
8686             ENDIF
8687             IF ( nmrtbl_from_file /= nmrtbl )  THEN
8688                 WRITE( message_string, * ) 'nmrtbl from SVF file does not ',  &
8689                                            'match calculated nmrtbl from ',   &
8690                                            'radiation_interaction_init'
8691                 CALL message( 'radiation_read_svf', 'PA0494', 1, 2, 0, 6, 0 )
8692             ELSE
8693                 WRITE(debug_string,*) 'Number of nmrtf to read ', nmrtf
8694                 IF ( debug_output )  CALL debug_message( debug_string, 'info' )
8695             ENDIF
8696             
8697!
8698!--          Arrays skyvf, skyvft, dsitrans and dsitransc are allready
8699!--          allocated in radiation_interaction_init and
8700!--          radiation_presimulate_solar_pos
8701             IF ( nsurfl > 0 )  THEN
8702                READ(88) skyvf
8703                READ(88) skyvft
8704                READ(88) dsitrans 
8705             ENDIF
8706             
8707             IF ( plant_canopy  .AND.  npcbl > 0 ) THEN
8708                READ ( 88 )  dsitransc
8709             ENDIF
8710             
8711!
8712!--          The allocation of svf, svfsurf, csf, csfsurf, mrtf, mrtft, and
8713!--          mrtfsurf happens in routine radiation_calc_svf which is not
8714!--          called if the program enters radiation_read_svf. Therefore
8715!--          these arrays has to allocate in the following
8716             IF ( nsvfl > 0 )  THEN
8717                ALLOCATE( svf(ndsvf,nsvfl) )
8718                ALLOCATE( svfsurf(idsvf,nsvfl) )
8719                READ(88) svf
8720                READ(88) svfsurf
8721             ENDIF
8722
8723             IF ( plant_canopy  .AND.  ncsfl > 0 )  THEN
8724                ALLOCATE( csf(ndcsf,ncsfl) )
8725                ALLOCATE( csfsurf(idcsf,ncsfl) )
8726                READ(88) csf
8727                READ(88) csfsurf
8728             ENDIF
8729
8730             IF ( nmrtbl > 0 )  THEN
8731                READ(88) mrtsky
8732                READ(88) mrtskyt
8733                READ(88) mrtdsit
8734             ENDIF
8735
8736             IF ( nmrtf > 0 )  THEN
8737                ALLOCATE ( mrtf(nmrtf) )
8738                ALLOCATE ( mrtft(nmrtf) )
8739                ALLOCATE ( mrtfsurf(2,nmrtf) )
8740                READ(88) mrtf
8741                READ(88) mrtft
8742                READ(88) mrtfsurf
8743             ENDIF
8744             
8745!
8746!--          Close binary file                 
8747             CALL close_file( 88 )
8748               
8749          ENDIF
8750#if defined( __parallel )
8751          CALL MPI_BARRIER( comm2d, ierr )
8752#endif
8753       ENDDO
8754
8755       CALL location_message( 'reading view factors for radiation interaction', 'finished' )
8756
8757
8758    END SUBROUTINE radiation_read_svf
8759
8760
8761!------------------------------------------------------------------------------!
8762!
8763! Description:
8764! ------------
8765!> Subroutine stores svf, svfsurf, csf, csfsurf and mrt data to a file.
8766!------------------------------------------------------------------------------!
8767    SUBROUTINE radiation_write_svf
8768
8769       IMPLICIT NONE
8770       
8771       INTEGER(iwp)        :: i
8772
8773
8774       CALL location_message( 'writing view factors for radiation interaction', 'start' )
8775
8776       DO  i = 0, io_blocks-1
8777          IF ( i == io_group )  THEN
8778!
8779!--          Open binary file
8780             CALL check_open( 89 )
8781
8782             WRITE ( 89 )  rad_version
8783             WRITE ( 89 )  nsvfl, ncsfl, nsurfl, npcbl, ndsidir, nmrtbl, nmrtf
8784             IF ( nsurfl > 0 ) THEN
8785                WRITE ( 89 )  skyvf
8786                WRITE ( 89 )  skyvft
8787                WRITE ( 89 )  dsitrans
8788             ENDIF
8789             IF ( npcbl > 0 ) THEN
8790                WRITE ( 89 )  dsitransc
8791             ENDIF
8792             IF ( nsvfl > 0 ) THEN
8793                WRITE ( 89 )  svf
8794                WRITE ( 89 )  svfsurf
8795             ENDIF
8796             IF ( plant_canopy  .AND.  ncsfl > 0 )  THEN
8797                 WRITE ( 89 )  csf
8798                 WRITE ( 89 )  csfsurf
8799             ENDIF
8800             IF ( nmrtbl > 0 )  THEN
8801                WRITE ( 89 ) mrtsky
8802                WRITE ( 89 ) mrtskyt
8803                WRITE ( 89 ) mrtdsit
8804             ENDIF
8805             IF ( nmrtf > 0 )  THEN
8806                 WRITE ( 89 )  mrtf
8807                 WRITE ( 89 )  mrtft               
8808                 WRITE ( 89 )  mrtfsurf
8809             ENDIF
8810!
8811!--          Close binary file                 
8812             CALL close_file( 89 )
8813
8814          ENDIF
8815#if defined( __parallel )
8816          CALL MPI_BARRIER( comm2d, ierr )
8817#endif
8818       ENDDO
8819
8820       CALL location_message( 'writing view factors for radiation interaction', 'finished' )
8821
8822
8823    END SUBROUTINE radiation_write_svf
8824
8825
8826!------------------------------------------------------------------------------!
8827!
8828! Description:
8829! ------------
8830!> Block of auxiliary subroutines:
8831!> 1. quicksort and corresponding comparison
8832!> 2. merge_and_grow_csf for implementation of "dynamical growing"
8833!>    array for csf
8834!------------------------------------------------------------------------------!
8835!-- quicksort.f -*-f90-*-
8836!-- Author: t-nissie, adaptation J.Resler
8837!-- License: GPLv3
8838!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8839    RECURSIVE SUBROUTINE quicksort_itarget(itarget, vffrac, ztransp, first, last)
8840        IMPLICIT NONE
8841        INTEGER(iwp), DIMENSION(:), INTENT(INOUT)   :: itarget
8842        REAL(wp), DIMENSION(:), INTENT(INOUT)       :: vffrac, ztransp
8843        INTEGER(iwp), INTENT(IN)                    :: first, last
8844        INTEGER(iwp)                                :: x, t
8845        INTEGER(iwp)                                :: i, j
8846        REAL(wp)                                    :: tr
8847
8848        IF ( first>=last ) RETURN
8849        x = itarget((first+last)/2)
8850        i = first
8851        j = last
8852        DO
8853            DO WHILE ( itarget(i) < x )
8854               i=i+1
8855            ENDDO
8856            DO WHILE ( x < itarget(j) )
8857                j=j-1
8858            ENDDO
8859            IF ( i >= j ) EXIT
8860            t = itarget(i);  itarget(i) = itarget(j);  itarget(j) = t
8861            tr = vffrac(i);  vffrac(i) = vffrac(j);  vffrac(j) = tr
8862            tr = ztransp(i);  ztransp(i) = ztransp(j);  ztransp(j) = tr
8863            i=i+1
8864            j=j-1
8865        ENDDO
8866        IF ( first < i-1 ) CALL quicksort_itarget(itarget, vffrac, ztransp, first, i-1)
8867        IF ( j+1 < last )  CALL quicksort_itarget(itarget, vffrac, ztransp, j+1, last)
8868    END SUBROUTINE quicksort_itarget
8869
8870    PURE FUNCTION svf_lt(svf1,svf2) result (res)
8871      TYPE (t_svf), INTENT(in) :: svf1,svf2
8872      LOGICAL                  :: res
8873      IF ( svf1%isurflt < svf2%isurflt  .OR.    &
8874          (svf1%isurflt == svf2%isurflt  .AND.  svf1%isurfs < svf2%isurfs) )  THEN
8875          res = .TRUE.
8876      ELSE
8877          res = .FALSE.
8878      ENDIF
8879    END FUNCTION svf_lt
8880
8881
8882!-- quicksort.f -*-f90-*-
8883!-- Author: t-nissie, adaptation J.Resler
8884!-- License: GPLv3
8885!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8886    RECURSIVE SUBROUTINE quicksort_svf(svfl, first, last)
8887        IMPLICIT NONE
8888        TYPE(t_svf), DIMENSION(:), INTENT(INOUT)  :: svfl
8889        INTEGER(iwp), INTENT(IN)                  :: first, last
8890        TYPE(t_svf)                               :: x, t
8891        INTEGER(iwp)                              :: i, j
8892
8893        IF ( first>=last ) RETURN
8894        x = svfl( (first+last) / 2 )
8895        i = first
8896        j = last
8897        DO
8898            DO while ( svf_lt(svfl(i),x) )
8899               i=i+1
8900            ENDDO
8901            DO while ( svf_lt(x,svfl(j)) )
8902                j=j-1
8903            ENDDO
8904            IF ( i >= j ) EXIT
8905            t = svfl(i);  svfl(i) = svfl(j);  svfl(j) = t
8906            i=i+1
8907            j=j-1
8908        ENDDO
8909        IF ( first < i-1 ) CALL quicksort_svf(svfl, first, i-1)
8910        IF ( j+1 < last )  CALL quicksort_svf(svfl, j+1, last)
8911    END SUBROUTINE quicksort_svf
8912
8913    PURE FUNCTION csf_lt(csf1,csf2) result (res)
8914      TYPE (t_csf), INTENT(in) :: csf1,csf2
8915      LOGICAL                  :: res
8916      IF ( csf1%ip < csf2%ip  .OR.    &
8917           (csf1%ip == csf2%ip  .AND.  csf1%itx < csf2%itx)  .OR.  &
8918           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity < csf2%ity)  .OR.  &
8919           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity == csf2%ity  .AND.   &
8920            csf1%itz < csf2%itz)  .OR.  &
8921           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity == csf2%ity  .AND.   &
8922            csf1%itz == csf2%itz  .AND.  csf1%isurfs < csf2%isurfs) )  THEN
8923          res = .TRUE.
8924      ELSE
8925          res = .FALSE.
8926      ENDIF
8927    END FUNCTION csf_lt
8928
8929
8930!-- quicksort.f -*-f90-*-
8931!-- Author: t-nissie, adaptation J.Resler
8932!-- License: GPLv3
8933!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8934    RECURSIVE SUBROUTINE quicksort_csf(csfl, first, last)
8935        IMPLICIT NONE
8936        TYPE(t_csf), DIMENSION(:), INTENT(INOUT)  :: csfl
8937        INTEGER(iwp), INTENT(IN)                  :: first, last
8938        TYPE(t_csf)                               :: x, t
8939        INTEGER(iwp)                              :: i, j
8940
8941        IF ( first>=last ) RETURN
8942        x = csfl( (first+last)/2 )
8943        i = first
8944        j = last
8945        DO
8946            DO while ( csf_lt(csfl(i),x) )
8947                i=i+1
8948            ENDDO
8949            DO while ( csf_lt(x,csfl(j)) )
8950                j=j-1
8951            ENDDO
8952            IF ( i >= j ) EXIT
8953            t = csfl(i);  csfl(i) = csfl(j);  csfl(j) = t
8954            i=i+1
8955            j=j-1
8956        ENDDO
8957        IF ( first < i-1 ) CALL quicksort_csf(csfl, first, i-1)
8958        IF ( j+1 < last )  CALL quicksort_csf(csfl, j+1, last)
8959    END SUBROUTINE quicksort_csf
8960
8961   
8962!------------------------------------------------------------------------------!
8963!
8964! Description:
8965! ------------
8966!> Grows the CSF array exponentially after it is full. During that, the ray
8967!> canopy sink factors with common source face and target plant canopy grid
8968!> cell are merged together so that the size doesn't grow out of control.
8969!------------------------------------------------------------------------------!
8970    SUBROUTINE merge_and_grow_csf(newsize)
8971        INTEGER(iwp), INTENT(in)                :: newsize  !< new array size after grow, must be >= ncsfl
8972                                                            !< or -1 to shrink to minimum
8973        INTEGER(iwp)                            :: iread, iwrite
8974        TYPE(t_csf), DIMENSION(:), POINTER      :: acsfnew
8975
8976
8977        IF ( newsize == -1 )  THEN
8978!--         merge in-place
8979            acsfnew => acsf
8980        ELSE
8981!--         allocate new array
8982            IF ( mcsf == 0 )  THEN
8983                ALLOCATE( acsf1(newsize) )
8984                acsfnew => acsf1
8985            ELSE
8986                ALLOCATE( acsf2(newsize) )
8987                acsfnew => acsf2
8988            ENDIF
8989        ENDIF
8990
8991        IF ( ncsfl >= 1 )  THEN
8992!--         sort csf in place (quicksort)
8993            CALL quicksort_csf(acsf,1,ncsfl)
8994
8995!--         while moving to a new array, aggregate canopy sink factor records with identical box & source
8996            acsfnew(1) = acsf(1)
8997            iwrite = 1
8998            DO iread = 2, ncsfl
8999!--             here acsf(kcsf) already has values from acsf(icsf)
9000                IF ( acsfnew(iwrite)%itx == acsf(iread)%itx &
9001                         .AND.  acsfnew(iwrite)%ity == acsf(iread)%ity &
9002                         .AND.  acsfnew(iwrite)%itz == acsf(iread)%itz &
9003                         .AND.  acsfnew(iwrite)%isurfs == acsf(iread)%isurfs )  THEN
9004
9005                    acsfnew(iwrite)%rcvf = acsfnew(iwrite)%rcvf + acsf(iread)%rcvf
9006!--                 advance reading index, keep writing index
9007                ELSE
9008!--                 not identical, just advance and copy
9009                    iwrite = iwrite + 1
9010                    acsfnew(iwrite) = acsf(iread)
9011                ENDIF
9012            ENDDO
9013            ncsfl = iwrite
9014        ENDIF
9015
9016        IF ( newsize == -1 )  THEN
9017!--         allocate new array and copy shrinked data
9018            IF ( mcsf == 0 )  THEN
9019                ALLOCATE( acsf1(ncsfl) )
9020                acsf1(1:ncsfl) = acsf2(1:ncsfl)
9021            ELSE
9022                ALLOCATE( acsf2(ncsfl) )
9023                acsf2(1:ncsfl) = acsf1(1:ncsfl)
9024            ENDIF
9025        ENDIF
9026
9027!--     deallocate old array
9028        IF ( mcsf == 0 )  THEN
9029            mcsf = 1
9030            acsf => acsf1
9031            DEALLOCATE( acsf2 )
9032        ELSE
9033            mcsf = 0
9034            acsf => acsf2
9035            DEALLOCATE( acsf1 )
9036        ENDIF
9037        ncsfla = newsize
9038
9039        IF ( debug_output )  THEN
9040           WRITE( debug_string, '(A,2I12)' ) 'Grow acsf2:', ncsfl, ncsfla
9041           CALL debug_message( debug_string, 'info' )
9042        ENDIF
9043
9044    END SUBROUTINE merge_and_grow_csf
9045
9046   
9047!-- quicksort.f -*-f90-*-
9048!-- Author: t-nissie, adaptation J.Resler
9049!-- License: GPLv3
9050!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
9051    RECURSIVE SUBROUTINE quicksort_csf2(kpcsflt, pcsflt, first, last)
9052        IMPLICIT NONE
9053        INTEGER(iwp), DIMENSION(:,:), INTENT(INOUT)  :: kpcsflt
9054        REAL(wp), DIMENSION(:,:), INTENT(INOUT)      :: pcsflt
9055        INTEGER(iwp), INTENT(IN)                     :: first, last
9056        REAL(wp), DIMENSION(ndcsf)                   :: t2
9057        INTEGER(iwp), DIMENSION(kdcsf)               :: x, t1
9058        INTEGER(iwp)                                 :: i, j
9059
9060        IF ( first>=last ) RETURN
9061        x = kpcsflt(:, (first+last)/2 )
9062        i = first
9063        j = last
9064        DO
9065            DO while ( csf_lt2(kpcsflt(:,i),x) )
9066                i=i+1
9067            ENDDO
9068            DO while ( csf_lt2(x,kpcsflt(:,j)) )
9069                j=j-1
9070            ENDDO
9071            IF ( i >= j ) EXIT
9072            t1 = kpcsflt(:,i);  kpcsflt(:,i) = kpcsflt(:,j);  kpcsflt(:,j) = t1
9073            t2 = pcsflt(:,i);  pcsflt(:,i) = pcsflt(:,j);  pcsflt(:,j) = t2
9074            i=i+1
9075            j=j-1
9076        ENDDO
9077        IF ( first < i-1 ) CALL quicksort_csf2(kpcsflt, pcsflt, first, i-1)
9078        IF ( j+1 < last )  CALL quicksort_csf2(kpcsflt, pcsflt, j+1, last)
9079    END SUBROUTINE quicksort_csf2
9080   
9081
9082    PURE FUNCTION csf_lt2(item1, item2) result(res)
9083        INTEGER(iwp), DIMENSION(kdcsf), INTENT(in)  :: item1, item2
9084        LOGICAL                                     :: res
9085        res = ( (item1(3) < item2(3))                                                        &
9086             .OR.  (item1(3) == item2(3)  .AND.  item1(2) < item2(2))                            &
9087             .OR.  (item1(3) == item2(3)  .AND.  item1(2) == item2(2)  .AND.  item1(1) < item2(1)) &
9088             .OR.  (item1(3) == item2(3)  .AND.  item1(2) == item2(2)  .AND.  item1(1) == item2(1) &
9089                 .AND.  item1(4) < item2(4)) )
9090    END FUNCTION csf_lt2
9091
9092    PURE FUNCTION searchsorted(athresh, val) result(ind)
9093        REAL(wp), DIMENSION(:), INTENT(IN)  :: athresh
9094        REAL(wp), INTENT(IN)                :: val
9095        INTEGER(iwp)                        :: ind
9096        INTEGER(iwp)                        :: i
9097
9098        DO i = LBOUND(athresh, 1), UBOUND(athresh, 1)
9099            IF ( val < athresh(i) ) THEN
9100                ind = i - 1
9101                RETURN
9102            ENDIF
9103        ENDDO
9104        ind = UBOUND(athresh, 1)
9105    END FUNCTION searchsorted
9106
9107
9108!------------------------------------------------------------------------------!
9109!
9110! Description:
9111! ------------
9112!> Subroutine for averaging 3D data
9113!------------------------------------------------------------------------------!
9114SUBROUTINE radiation_3d_data_averaging( mode, variable )
9115 
9116
9117    USE control_parameters
9118
9119    USE indices
9120
9121    USE kinds
9122
9123    IMPLICIT NONE
9124
9125    CHARACTER (LEN=*) ::  mode    !<
9126    CHARACTER (LEN=*) :: variable !<
9127
9128    LOGICAL      ::  match_lsm !< flag indicating natural-type surface
9129    LOGICAL      ::  match_usm !< flag indicating urban-type surface
9130   
9131    INTEGER(iwp) ::  i !<
9132    INTEGER(iwp) ::  j !<
9133    INTEGER(iwp) ::  k !<
9134    INTEGER(iwp) ::  l, m !< index of current surface element
9135
9136    INTEGER(iwp)                                       :: ids, idsint_u, idsint_l, isurf
9137    CHARACTER(LEN=varnamelength)                       :: var
9138
9139!-- find the real name of the variable
9140    ids = -1
9141    l = -1
9142    var = TRIM(variable)
9143    DO i = 0, nd-1
9144        k = len(TRIM(var))
9145        j = len(TRIM(dirname(i)))
9146        IF ( k-j+1 >= 1_iwp ) THEN
9147           IF ( TRIM(var(k-j+1:k)) == TRIM(dirname(i)) )  THEN
9148               ids = i
9149               idsint_u = dirint_u(ids)
9150               idsint_l = dirint_l(ids)
9151               var = var(:k-j)
9152               EXIT
9153           ENDIF
9154        ENDIF
9155    ENDDO
9156    IF ( ids == -1 )  THEN
9157        var = TRIM(variable)
9158    ENDIF
9159
9160    IF ( mode == 'allocate' )  THEN
9161
9162       SELECT CASE ( TRIM( var ) )
9163!--          block of large scale (e.g. RRTMG) radiation output variables
9164             CASE ( 'rad_net*' )
9165                IF ( .NOT. ALLOCATED( rad_net_av ) )  THEN
9166                   ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
9167                ENDIF
9168                rad_net_av = 0.0_wp
9169             
9170             CASE ( 'rad_lw_in*' )
9171                IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) )  THEN
9172                   ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
9173                ENDIF
9174                rad_lw_in_xy_av = 0.0_wp
9175               
9176             CASE ( 'rad_lw_out*' )
9177                IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) )  THEN
9178                   ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
9179                ENDIF
9180                rad_lw_out_xy_av = 0.0_wp
9181               
9182             CASE ( 'rad_sw_in*' )
9183                IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) )  THEN
9184                   ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
9185                ENDIF
9186                rad_sw_in_xy_av = 0.0_wp
9187               
9188             CASE ( 'rad_sw_out*' )
9189                IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) )  THEN
9190                   ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
9191                ENDIF
9192                rad_sw_out_xy_av = 0.0_wp               
9193
9194             CASE ( 'rad_lw_in' )
9195                IF ( .NOT. ALLOCATED( rad_lw_in_av ) )  THEN
9196                   ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9197                ENDIF
9198                rad_lw_in_av = 0.0_wp
9199
9200             CASE ( 'rad_lw_out' )
9201                IF ( .NOT. ALLOCATED( rad_lw_out_av ) )  THEN
9202                   ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9203                ENDIF
9204                rad_lw_out_av = 0.0_wp
9205
9206             CASE ( 'rad_lw_cs_hr' )
9207                IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) )  THEN
9208                   ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9209                ENDIF
9210                rad_lw_cs_hr_av = 0.0_wp
9211
9212             CASE ( 'rad_lw_hr' )
9213                IF ( .NOT. ALLOCATED( rad_lw_hr_av ) )  THEN
9214                   ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9215                ENDIF
9216                rad_lw_hr_av = 0.0_wp
9217
9218             CASE ( 'rad_sw_in' )
9219                IF ( .NOT. ALLOCATED( rad_sw_in_av ) )  THEN
9220                   ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9221                ENDIF
9222                rad_sw_in_av = 0.0_wp
9223
9224             CASE ( 'rad_sw_out' )
9225                IF ( .NOT. ALLOCATED( rad_sw_out_av ) )  THEN
9226                   ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9227                ENDIF
9228                rad_sw_out_av = 0.0_wp
9229
9230             CASE ( 'rad_sw_cs_hr' )
9231                IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) )  THEN
9232                   ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9233                ENDIF
9234                rad_sw_cs_hr_av = 0.0_wp
9235
9236             CASE ( 'rad_sw_hr' )
9237                IF ( .NOT. ALLOCATED( rad_sw_hr_av ) )  THEN
9238                   ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9239                ENDIF
9240                rad_sw_hr_av = 0.0_wp
9241
9242!--          block of RTM output variables
9243             CASE ( 'rtm_rad_net' )
9244!--              array of complete radiation balance
9245                 IF ( .NOT.  ALLOCATED(surfradnet_av) )  THEN
9246                     ALLOCATE( surfradnet_av(nsurfl) )
9247                     surfradnet_av = 0.0_wp
9248                 ENDIF
9249
9250             CASE ( 'rtm_rad_insw' )
9251!--                 array of sw radiation falling to surface after i-th reflection
9252                 IF ( .NOT.  ALLOCATED(surfinsw_av) )  THEN
9253                     ALLOCATE( surfinsw_av(nsurfl) )
9254                     surfinsw_av = 0.0_wp
9255                 ENDIF
9256
9257             CASE ( 'rtm_rad_inlw' )
9258!--                 array of lw radiation falling to surface after i-th reflection
9259                 IF ( .NOT.  ALLOCATED(surfinlw_av) )  THEN
9260                     ALLOCATE( surfinlw_av(nsurfl) )
9261                     surfinlw_av = 0.0_wp
9262                 ENDIF
9263
9264             CASE ( 'rtm_rad_inswdir' )
9265!--                 array of direct sw radiation falling to surface from sun
9266                 IF ( .NOT.  ALLOCATED(surfinswdir_av) )  THEN
9267                     ALLOCATE( surfinswdir_av(nsurfl) )
9268                     surfinswdir_av = 0.0_wp
9269                 ENDIF
9270
9271             CASE ( 'rtm_rad_inswdif' )
9272!--                 array of difusion sw radiation falling to surface from sky and borders of the domain
9273                 IF ( .NOT.  ALLOCATED(surfinswdif_av) )  THEN
9274                     ALLOCATE( surfinswdif_av(nsurfl) )
9275                     surfinswdif_av = 0.0_wp
9276                 ENDIF
9277
9278             CASE ( 'rtm_rad_inswref' )
9279!--                 array of sw radiation falling to surface from reflections
9280                 IF ( .NOT.  ALLOCATED(surfinswref_av) )  THEN
9281                     ALLOCATE( surfinswref_av(nsurfl) )
9282                     surfinswref_av = 0.0_wp
9283                 ENDIF
9284
9285             CASE ( 'rtm_rad_inlwdif' )
9286!--                 array of sw radiation falling to surface after i-th reflection
9287                IF ( .NOT.  ALLOCATED(surfinlwdif_av) )  THEN
9288                     ALLOCATE( surfinlwdif_av(nsurfl) )
9289                     surfinlwdif_av = 0.0_wp
9290                 ENDIF
9291
9292             CASE ( 'rtm_rad_inlwref' )
9293!--                 array of lw radiation falling to surface from reflections
9294                 IF ( .NOT.  ALLOCATED(surfinlwref_av) )  THEN
9295                     ALLOCATE( surfinlwref_av(nsurfl) )
9296                     surfinlwref_av = 0.0_wp
9297                 ENDIF
9298
9299             CASE ( 'rtm_rad_outsw' )
9300!--                 array of sw radiation emitted from surface after i-th reflection
9301                 IF ( .NOT.  ALLOCATED(surfoutsw_av) )  THEN
9302                     ALLOCATE( surfoutsw_av(nsurfl) )
9303                     surfoutsw_av = 0.0_wp
9304                 ENDIF
9305
9306             CASE ( 'rtm_rad_outlw' )
9307!--                 array of lw radiation emitted from surface after i-th reflection
9308                 IF ( .NOT.  ALLOCATED(surfoutlw_av) )  THEN
9309                     ALLOCATE( surfoutlw_av(nsurfl) )
9310                     surfoutlw_av = 0.0_wp
9311                 ENDIF
9312             CASE ( 'rtm_rad_ressw' )
9313!--                 array of residua of sw radiation absorbed in surface after last reflection
9314                 IF ( .NOT.  ALLOCATED(surfins_av) )  THEN
9315                     ALLOCATE( surfins_av(nsurfl) )
9316                     surfins_av = 0.0_wp
9317                 ENDIF
9318
9319             CASE ( 'rtm_rad_reslw' )
9320!--                 array of residua of lw radiation absorbed in surface after last reflection
9321                 IF ( .NOT.  ALLOCATED(surfinl_av) )  THEN
9322                     ALLOCATE( surfinl_av(nsurfl) )
9323                     surfinl_av = 0.0_wp
9324                 ENDIF
9325
9326             CASE ( 'rtm_rad_pc_inlw' )
9327!--                 array of of lw radiation absorbed in plant canopy
9328                 IF ( .NOT.  ALLOCATED(pcbinlw_av) )  THEN
9329                     ALLOCATE( pcbinlw_av(1:npcbl) )
9330                     pcbinlw_av = 0.0_wp
9331                 ENDIF
9332
9333             CASE ( 'rtm_rad_pc_insw' )
9334!--                 array of of sw radiation absorbed in plant canopy
9335                 IF ( .NOT.  ALLOCATED(pcbinsw_av) )  THEN
9336                     ALLOCATE( pcbinsw_av(1:npcbl) )
9337                     pcbinsw_av = 0.0_wp
9338                 ENDIF
9339
9340             CASE ( 'rtm_rad_pc_inswdir' )
9341!--                 array of of direct sw radiation absorbed in plant canopy
9342                 IF ( .NOT.  ALLOCATED(pcbinswdir_av) )  THEN
9343                     ALLOCATE( pcbinswdir_av(1:npcbl) )
9344                     pcbinswdir_av = 0.0_wp
9345                 ENDIF
9346
9347             CASE ( 'rtm_rad_pc_inswdif' )
9348!--                 array of of diffuse sw radiation absorbed in plant canopy
9349                 IF ( .NOT.  ALLOCATED(pcbinswdif_av) )  THEN
9350                     ALLOCATE( pcbinswdif_av(1:npcbl) )
9351                     pcbinswdif_av = 0.0_wp
9352                 ENDIF
9353
9354             CASE ( 'rtm_rad_pc_inswref' )
9355!--                 array of of reflected sw radiation absorbed in plant canopy
9356                 IF ( .NOT.  ALLOCATED(pcbinswref_av) )  THEN
9357                     ALLOCATE( pcbinswref_av(1:npcbl) )
9358                     pcbinswref_av = 0.0_wp
9359                 ENDIF
9360
9361             CASE ( 'rtm_mrt_sw' )
9362                IF ( .NOT. ALLOCATED( mrtinsw_av ) )  THEN
9363                   ALLOCATE( mrtinsw_av(nmrtbl) )
9364                ENDIF
9365                mrtinsw_av = 0.0_wp
9366
9367             CASE ( 'rtm_mrt_lw' )
9368                IF ( .NOT. ALLOCATED( mrtinlw_av ) )  THEN
9369                   ALLOCATE( mrtinlw_av(nmrtbl) )
9370                ENDIF
9371                mrtinlw_av = 0.0_wp
9372
9373             CASE ( 'rtm_mrt' )
9374                IF ( .NOT. ALLOCATED( mrt_av ) )  THEN
9375                   ALLOCATE( mrt_av(nmrtbl) )
9376                ENDIF
9377                mrt_av = 0.0_wp
9378
9379          CASE DEFAULT
9380             CONTINUE
9381
9382       END SELECT
9383
9384    ELSEIF ( mode == 'sum' )  THEN
9385
9386       SELECT CASE ( TRIM( var ) )
9387!--       block of large scale (e.g. RRTMG) radiation output variables
9388          CASE ( 'rad_net*' )
9389             IF ( ALLOCATED( rad_net_av ) ) THEN
9390                DO  i = nxl, nxr
9391                   DO  j = nys, nyn
9392                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9393                                  surf_lsm_h%end_index(j,i)
9394                      match_usm = surf_usm_h%start_index(j,i) <=               &
9395                                  surf_usm_h%end_index(j,i)
9396
9397                     IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9398                         m = surf_lsm_h%end_index(j,i)
9399                         rad_net_av(j,i) = rad_net_av(j,i) +                   &
9400                                         surf_lsm_h%rad_net(m)
9401                      ELSEIF ( match_usm )  THEN
9402                         m = surf_usm_h%end_index(j,i)
9403                         rad_net_av(j,i) = rad_net_av(j,i) +                   &
9404                                         surf_usm_h%rad_net(m)
9405                      ENDIF
9406                   ENDDO
9407                ENDDO
9408             ENDIF
9409
9410          CASE ( 'rad_lw_in*' )
9411             IF ( ALLOCATED( rad_lw_in_xy_av ) ) THEN
9412                DO  i = nxl, nxr
9413                   DO  j = nys, nyn
9414                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9415                                  surf_lsm_h%end_index(j,i)
9416                      match_usm = surf_usm_h%start_index(j,i) <=               &
9417                                  surf_usm_h%end_index(j,i)
9418
9419                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9420                         m = surf_lsm_h%end_index(j,i)
9421                         rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i) +         &
9422                                         surf_lsm_h%rad_lw_in(m)
9423                      ELSEIF ( match_usm )  THEN
9424                         m = surf_usm_h%end_index(j,i)
9425                         rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i) +         &
9426                                         surf_usm_h%rad_lw_in(m)
9427                      ENDIF
9428                   ENDDO
9429                ENDDO
9430             ENDIF
9431             
9432          CASE ( 'rad_lw_out*' )
9433             IF ( ALLOCATED( rad_lw_out_xy_av ) ) THEN
9434                DO  i = nxl, nxr
9435                   DO  j = nys, nyn
9436                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9437                                  surf_lsm_h%end_index(j,i)
9438                      match_usm = surf_usm_h%start_index(j,i) <=               &
9439                                  surf_usm_h%end_index(j,i)
9440
9441                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9442                         m = surf_lsm_h%end_index(j,i)
9443                         rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i) +       &
9444                                                 surf_lsm_h%rad_lw_out(m)
9445                      ELSEIF ( match_usm )  THEN
9446                         m = surf_usm_h%end_index(j,i)
9447                         rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i) +       &
9448                                                 surf_usm_h%rad_lw_out(m)
9449                      ENDIF
9450                   ENDDO
9451                ENDDO
9452             ENDIF
9453             
9454          CASE ( 'rad_sw_in*' )
9455             IF ( ALLOCATED( rad_sw_in_xy_av ) ) THEN
9456                DO  i = nxl, nxr
9457                   DO  j = nys, nyn
9458                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9459                                  surf_lsm_h%end_index(j,i)
9460                      match_usm = surf_usm_h%start_index(j,i) <=               &
9461                                  surf_usm_h%end_index(j,i)
9462
9463                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9464                         m = surf_lsm_h%end_index(j,i)
9465                         rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i) +         &
9466                                                surf_lsm_h%rad_sw_in(m)
9467                      ELSEIF ( match_usm )  THEN
9468                         m = surf_usm_h%end_index(j,i)
9469                         rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i) +         &
9470                                                surf_usm_h%rad_sw_in(m)
9471                      ENDIF
9472                   ENDDO
9473                ENDDO
9474             ENDIF
9475             
9476          CASE ( 'rad_sw_out*' )
9477             IF ( ALLOCATED( rad_sw_out_xy_av ) ) THEN
9478                DO  i = nxl, nxr
9479                   DO  j = nys, nyn
9480                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9481                                  surf_lsm_h%end_index(j,i)
9482                      match_usm = surf_usm_h%start_index(j,i) <=               &
9483                                  surf_usm_h%end_index(j,i)
9484
9485                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9486                         m = surf_lsm_h%end_index(j,i)
9487                         rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i) +       &
9488                                                 surf_lsm_h%rad_sw_out(m)
9489                      ELSEIF ( match_usm )  THEN
9490                         m = surf_usm_h%end_index(j,i)
9491                         rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i) +       &
9492                                                 surf_usm_h%rad_sw_out(m)
9493                      ENDIF
9494                   ENDDO
9495                ENDDO
9496             ENDIF
9497             
9498          CASE ( 'rad_lw_in' )
9499             IF ( ALLOCATED( rad_lw_in_av ) ) THEN
9500                DO  i = nxlg, nxrg
9501                   DO  j = nysg, nyng
9502                      DO  k = nzb, nzt+1
9503                         rad_lw_in_av(k,j,i) = rad_lw_in_av(k,j,i)             &
9504                                               + rad_lw_in(k,j,i)
9505                      ENDDO
9506                   ENDDO
9507                ENDDO
9508             ENDIF
9509
9510          CASE ( 'rad_lw_out' )
9511             IF ( ALLOCATED( rad_lw_out_av ) ) THEN
9512                DO  i = nxlg, nxrg
9513                   DO  j = nysg, nyng
9514                      DO  k = nzb, nzt+1
9515                         rad_lw_out_av(k,j,i) = rad_lw_out_av(k,j,i)           &
9516                                                + rad_lw_out(k,j,i)
9517                      ENDDO
9518                   ENDDO
9519                ENDDO
9520             ENDIF
9521
9522          CASE ( 'rad_lw_cs_hr' )
9523             IF ( ALLOCATED( rad_lw_cs_hr_av ) ) THEN
9524                DO  i = nxlg, nxrg
9525                   DO  j = nysg, nyng
9526                      DO  k = nzb, nzt+1
9527                         rad_lw_cs_hr_av(k,j,i) = rad_lw_cs_hr_av(k,j,i)       &
9528                                                  + rad_lw_cs_hr(k,j,i)
9529                      ENDDO
9530                   ENDDO
9531                ENDDO
9532             ENDIF
9533
9534          CASE ( 'rad_lw_hr' )
9535             IF ( ALLOCATED( rad_lw_hr_av ) ) THEN
9536                DO  i = nxlg, nxrg
9537                   DO  j = nysg, nyng
9538                      DO  k = nzb, nzt+1
9539                         rad_lw_hr_av(k,j,i) = rad_lw_hr_av(k,j,i)             &
9540                                               + rad_lw_hr(k,j,i)
9541                      ENDDO
9542                   ENDDO
9543                ENDDO
9544             ENDIF
9545
9546          CASE ( 'rad_sw_in' )
9547             IF ( ALLOCATED( rad_sw_in_av ) ) THEN
9548                DO  i = nxlg, nxrg
9549                   DO  j = nysg, nyng
9550                      DO  k = nzb, nzt+1
9551                         rad_sw_in_av(k,j,i) = rad_sw_in_av(k,j,i)             &
9552                                               + rad_sw_in(k,j,i)
9553                      ENDDO
9554                   ENDDO
9555                ENDDO
9556             ENDIF
9557
9558          CASE ( 'rad_sw_out' )
9559             IF ( ALLOCATED( rad_sw_out_av ) ) THEN
9560                DO  i = nxlg, nxrg
9561                   DO  j = nysg, nyng
9562                      DO  k = nzb, nzt+1
9563                         rad_sw_out_av(k,j,i) = rad_sw_out_av(k,j,i)           &
9564                                                + rad_sw_out(k,j,i)
9565                      ENDDO
9566                   ENDDO
9567                ENDDO
9568             ENDIF
9569
9570          CASE ( 'rad_sw_cs_hr' )
9571             IF ( ALLOCATED( rad_sw_cs_hr_av ) ) THEN
9572                DO  i = nxlg, nxrg
9573                   DO  j = nysg, nyng
9574                      DO  k = nzb, nzt+1
9575                         rad_sw_cs_hr_av(k,j,i) = rad_sw_cs_hr_av(k,j,i)       &
9576                                                  + rad_sw_cs_hr(k,j,i)
9577                      ENDDO
9578                   ENDDO
9579                ENDDO
9580             ENDIF
9581
9582          CASE ( 'rad_sw_hr' )
9583             IF ( ALLOCATED( rad_sw_hr_av ) ) THEN
9584                DO  i = nxlg, nxrg
9585                   DO  j = nysg, nyng
9586                      DO  k = nzb, nzt+1
9587                         rad_sw_hr_av(k,j,i) = rad_sw_hr_av(k,j,i)             &
9588                                               + rad_sw_hr(k,j,i)
9589                      ENDDO
9590                   ENDDO
9591                ENDDO
9592             ENDIF
9593
9594!--       block of RTM output variables
9595          CASE ( 'rtm_rad_net' )
9596!--           array of complete radiation balance
9597              DO isurf = dirstart(ids), dirend(ids)
9598                 IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9599                    surfradnet_av(isurf) = surfinsw(isurf) - surfoutsw(isurf) +  surfinlw(isurf) - surfoutlw(isurf)
9600                 ENDIF
9601              ENDDO
9602
9603          CASE ( 'rtm_rad_insw' )
9604!--           array of sw radiation falling to surface after i-th reflection
9605              DO isurf = dirstart(ids), dirend(ids)
9606                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9607                      surfinsw_av(isurf) = surfinsw_av(isurf) + surfinsw(isurf)
9608                  ENDIF
9609              ENDDO
9610
9611          CASE ( 'rtm_rad_inlw' )
9612!--           array of lw radiation falling to surface after i-th reflection
9613              DO isurf = dirstart(ids), dirend(ids)
9614                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9615                      surfinlw_av(isurf) = surfinlw_av(isurf) + surfinlw(isurf)
9616                  ENDIF
9617              ENDDO
9618
9619          CASE ( 'rtm_rad_inswdir' )
9620!--           array of direct sw radiation falling to surface from sun
9621              DO isurf = dirstart(ids), dirend(ids)
9622                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9623                      surfinswdir_av(isurf) = surfinswdir_av(isurf) + surfinswdir(isurf)
9624                  ENDIF
9625              ENDDO
9626
9627          CASE ( 'rtm_rad_inswdif' )
9628!--           array of difusion sw radiation falling to surface from sky and borders of the domain
9629              DO isurf = dirstart(ids), dirend(ids)
9630                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9631                      surfinswdif_av(isurf) = surfinswdif_av(isurf) + surfinswdif(isurf)
9632                  ENDIF
9633              ENDDO
9634
9635          CASE ( 'rtm_rad_inswref' )
9636!--           array of sw radiation falling to surface from reflections
9637              DO isurf = dirstart(ids), dirend(ids)
9638                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9639                      surfinswref_av(isurf) = surfinswref_av(isurf) + surfinsw(isurf) - &
9640                                          surfinswdir(isurf) - surfinswdif(isurf)
9641                  ENDIF
9642              ENDDO
9643
9644
9645          CASE ( 'rtm_rad_inlwdif' )
9646!--           array of sw radiation falling to surface after i-th reflection
9647              DO isurf = dirstart(ids), dirend(ids)
9648                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9649                      surfinlwdif_av(isurf) = surfinlwdif_av(isurf) + surfinlwdif(isurf)
9650                  ENDIF
9651              ENDDO
9652!
9653          CASE ( 'rtm_rad_inlwref' )
9654!--           array of lw radiation falling to surface from reflections
9655              DO isurf = dirstart(ids), dirend(ids)
9656                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9657                      surfinlwref_av(isurf) = surfinlwref_av(isurf) + &
9658                                          surfinlw(isurf) - surfinlwdif(isurf)
9659                  ENDIF
9660              ENDDO
9661
9662          CASE ( 'rtm_rad_outsw' )
9663!--           array of sw radiation emitted from surface after i-th reflection
9664              DO isurf = dirstart(ids), dirend(ids)
9665                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9666                      surfoutsw_av(isurf) = surfoutsw_av(isurf) + surfoutsw(isurf)
9667                  ENDIF
9668              ENDDO
9669
9670          CASE ( 'rtm_rad_outlw' )
9671!--           array of lw radiation emitted from surface after i-th reflection
9672              DO isurf = dirstart(ids), dirend(ids)
9673                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9674                      surfoutlw_av(isurf) = surfoutlw_av(isurf) + surfoutlw(isurf)
9675                  ENDIF
9676              ENDDO
9677
9678          CASE ( 'rtm_rad_ressw' )
9679!--           array of residua of sw radiation absorbed in surface after last reflection
9680              DO isurf = dirstart(ids), dirend(ids)
9681                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9682                      surfins_av(isurf) = surfins_av(isurf) + surfins(isurf)
9683                  ENDIF
9684              ENDDO
9685
9686          CASE ( 'rtm_rad_reslw' )
9687!--           array of residua of lw radiation absorbed in surface after last reflection
9688              DO isurf = dirstart(ids), dirend(ids)
9689                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9690                      surfinl_av(isurf) = surfinl_av(isurf) + surfinl(isurf)
9691                  ENDIF
9692              ENDDO
9693
9694          CASE ( 'rtm_rad_pc_inlw' )
9695              DO l = 1, npcbl
9696                 pcbinlw_av(l) = pcbinlw_av(l) + pcbinlw(l)
9697              ENDDO
9698
9699          CASE ( 'rtm_rad_pc_insw' )
9700              DO l = 1, npcbl
9701                 pcbinsw_av(l) = pcbinsw_av(l) + pcbinsw(l)
9702              ENDDO
9703
9704          CASE ( 'rtm_rad_pc_inswdir' )
9705              DO l = 1, npcbl
9706                 pcbinswdir_av(l) = pcbinswdir_av(l) + pcbinswdir(l)
9707              ENDDO
9708
9709          CASE ( 'rtm_rad_pc_inswdif' )
9710              DO l = 1, npcbl
9711                 pcbinswdif_av(l) = pcbinswdif_av(l) + pcbinswdif(l)
9712              ENDDO
9713
9714          CASE ( 'rtm_rad_pc_inswref' )
9715              DO l = 1, npcbl
9716                 pcbinswref_av(l) = pcbinswref_av(l) + pcbinsw(l) - pcbinswdir(l) - pcbinswdif(l)
9717              ENDDO
9718
9719          CASE ( 'rad_mrt_sw' )
9720             IF ( ALLOCATED( mrtinsw_av ) )  THEN
9721                mrtinsw_av(:) = mrtinsw_av(:) + mrtinsw(:)
9722             ENDIF
9723
9724          CASE ( 'rad_mrt_lw' )
9725             IF ( ALLOCATED( mrtinlw_av ) )  THEN
9726                mrtinlw_av(:) = mrtinlw_av(:) + mrtinlw(:)
9727             ENDIF
9728
9729          CASE ( 'rad_mrt' )
9730             IF ( ALLOCATED( mrt_av ) )  THEN
9731                mrt_av(:) = mrt_av(:) + mrt(:)
9732             ENDIF
9733
9734          CASE DEFAULT
9735             CONTINUE
9736
9737       END SELECT
9738
9739    ELSEIF ( mode == 'average' )  THEN
9740
9741       SELECT CASE ( TRIM( var ) )
9742!--       block of large scale (e.g. RRTMG) radiation output variables
9743          CASE ( 'rad_net*' )
9744             IF ( ALLOCATED( rad_net_av ) ) THEN
9745                DO  i = nxlg, nxrg
9746                   DO  j = nysg, nyng
9747                      rad_net_av(j,i) = rad_net_av(j,i)                        &
9748                                        / REAL( average_count_3d, KIND=wp )
9749                   ENDDO
9750                ENDDO
9751             ENDIF
9752             
9753          CASE ( 'rad_lw_in*' )
9754             IF ( ALLOCATED( rad_lw_in_xy_av ) ) THEN
9755                DO  i = nxlg, nxrg
9756                   DO  j = nysg, nyng
9757                      rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i)              &
9758                                        / REAL( average_count_3d, KIND=wp )
9759                   ENDDO
9760                ENDDO
9761             ENDIF
9762             
9763          CASE ( 'rad_lw_out*' )
9764             IF ( ALLOCATED( rad_lw_out_xy_av ) ) THEN
9765                DO  i = nxlg, nxrg
9766                   DO  j = nysg, nyng
9767                      rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i)            &
9768                                        / REAL( average_count_3d, KIND=wp )
9769                   ENDDO
9770                ENDDO
9771             ENDIF
9772             
9773          CASE ( 'rad_sw_in*' )
9774             IF ( ALLOCATED( rad_sw_in_xy_av ) ) THEN
9775                DO  i = nxlg, nxrg
9776                   DO  j = nysg, nyng
9777                      rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i)              &
9778                                        / REAL( average_count_3d, KIND=wp )
9779                   ENDDO
9780                ENDDO
9781             ENDIF
9782             
9783          CASE ( 'rad_sw_out*' )
9784             IF ( ALLOCATED( rad_sw_out_xy_av ) ) THEN
9785                DO  i = nxlg, nxrg
9786                   DO  j = nysg, nyng
9787                      rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i)             &
9788                                        / REAL( average_count_3d, KIND=wp )
9789                   ENDDO
9790                ENDDO
9791             ENDIF
9792
9793          CASE ( 'rad_lw_in' )
9794             IF ( ALLOCATED( rad_lw_in_av ) ) THEN
9795                DO  i = nxlg, nxrg
9796                   DO  j = nysg, nyng
9797                      DO  k = nzb, nzt+1
9798                         rad_lw_in_av(k,j,i) = rad_lw_in_av(k,j,i)             &
9799                                               / REAL( average_count_3d, KIND=wp )
9800                      ENDDO
9801                   ENDDO
9802                ENDDO
9803             ENDIF
9804
9805          CASE ( 'rad_lw_out' )
9806             IF ( ALLOCATED( rad_lw_out_av ) ) THEN
9807                DO  i = nxlg, nxrg
9808                   DO  j = nysg, nyng
9809                      DO  k = nzb, nzt+1
9810                         rad_lw_out_av(k,j,i) = rad_lw_out_av(k,j,i)           &
9811                                                / REAL( average_count_3d, KIND=wp )
9812                      ENDDO
9813                   ENDDO
9814                ENDDO
9815             ENDIF
9816
9817          CASE ( 'rad_lw_cs_hr' )
9818             IF ( ALLOCATED( rad_lw_cs_hr_av ) ) THEN
9819                DO  i = nxlg, nxrg
9820                   DO  j = nysg, nyng
9821                      DO  k = nzb, nzt+1
9822                         rad_lw_cs_hr_av(k,j,i) = rad_lw_cs_hr_av(k,j,i)       &
9823                                                / REAL( average_count_3d, KIND=wp )
9824                      ENDDO
9825                   ENDDO
9826                ENDDO
9827             ENDIF
9828
9829          CASE ( 'rad_lw_hr' )
9830             IF ( ALLOCATED( rad_lw_hr_av ) ) THEN
9831                DO  i = nxlg, nxrg
9832                   DO  j = nysg, nyng
9833                      DO  k = nzb, nzt+1
9834                         rad_lw_hr_av(k,j,i) = rad_lw_hr_av(k,j,i)             &
9835                                               / REAL( average_count_3d, KIND=wp )
9836                      ENDDO
9837                   ENDDO
9838                ENDDO
9839             ENDIF
9840
9841          CASE ( 'rad_sw_in' )
9842             IF ( ALLOCATED( rad_sw_in_av ) ) THEN
9843                DO  i = nxlg, nxrg
9844                   DO  j = nysg, nyng
9845                      DO  k = nzb, nzt+1
9846                         rad_sw_in_av(k,j,i) = rad_sw_in_av(k,j,i)             &
9847                                               / REAL( average_count_3d, KIND=wp )
9848                      ENDDO
9849                   ENDDO
9850                ENDDO
9851             ENDIF
9852
9853          CASE ( 'rad_sw_out' )
9854             IF ( ALLOCATED( rad_sw_out_av ) ) THEN
9855                DO  i = nxlg, nxrg
9856                   DO  j = nysg, nyng
9857                      DO  k = nzb, nzt+1
9858                         rad_sw_out_av(k,j,i) = rad_sw_out_av(k,j,i)           &
9859                                                / REAL( average_count_3d, KIND=wp )
9860                      ENDDO
9861                   ENDDO
9862                ENDDO
9863             ENDIF
9864
9865          CASE ( 'rad_sw_cs_hr' )
9866             IF ( ALLOCATED( rad_sw_cs_hr_av ) ) THEN
9867                DO  i = nxlg, nxrg
9868                   DO  j = nysg, nyng
9869                      DO  k = nzb, nzt+1
9870                         rad_sw_cs_hr_av(k,j,i) = rad_sw_cs_hr_av(k,j,i)       &
9871                                                / REAL( average_count_3d, KIND=wp )
9872                      ENDDO
9873                   ENDDO
9874                ENDDO
9875             ENDIF
9876
9877          CASE ( 'rad_sw_hr' )
9878             IF ( ALLOCATED( rad_sw_hr_av ) ) THEN
9879                DO  i = nxlg, nxrg
9880                   DO  j = nysg, nyng
9881                      DO  k = nzb, nzt+1
9882                         rad_sw_hr_av(k,j,i) = rad_sw_hr_av(k,j,i)             &
9883                                               / REAL( average_count_3d, KIND=wp )
9884                      ENDDO
9885                   ENDDO
9886                ENDDO
9887             ENDIF
9888
9889!--       block of RTM output variables
9890          CASE ( 'rtm_rad_net' )
9891!--           array of complete radiation balance
9892              DO isurf = dirstart(ids), dirend(ids)
9893                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9894                      surfradnet_av(isurf) = surfinsw_av(isurf) / REAL( average_count_3d, kind=wp )
9895                  ENDIF
9896              ENDDO
9897
9898          CASE ( 'rtm_rad_insw' )
9899!--           array of sw radiation falling to surface after i-th reflection
9900              DO isurf = dirstart(ids), dirend(ids)
9901                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9902                      surfinsw_av(isurf) = surfinsw_av(isurf) / REAL( average_count_3d, kind=wp )
9903                  ENDIF
9904              ENDDO
9905
9906          CASE ( 'rtm_rad_inlw' )
9907!--           array of lw radiation falling to surface after i-th reflection
9908              DO isurf = dirstart(ids), dirend(ids)
9909                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9910                      surfinlw_av(isurf) = surfinlw_av(isurf) / REAL( average_count_3d, kind=wp )
9911                  ENDIF
9912              ENDDO
9913
9914          CASE ( 'rtm_rad_inswdir' )
9915!--           array of direct sw radiation falling to surface from sun
9916              DO isurf = dirstart(ids), dirend(ids)
9917                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9918                      surfinswdir_av(isurf) = surfinswdir_av(isurf) / REAL( average_count_3d, kind=wp )
9919                  ENDIF
9920              ENDDO
9921
9922          CASE ( 'rtm_rad_inswdif' )
9923!--           array of difusion sw radiation falling to surface from sky and borders of the domain
9924              DO isurf = dirstart(ids), dirend(ids)
9925                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9926                      surfinswdif_av(isurf) = surfinswdif_av(isurf) / REAL( average_count_3d, kind=wp )
9927                  ENDIF
9928              ENDDO
9929
9930          CASE ( 'rtm_rad_inswref' )
9931!--           array of sw radiation falling to surface from reflections
9932              DO isurf = dirstart(ids), dirend(ids)
9933                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9934                      surfinswref_av(isurf) = surfinswref_av(isurf) / REAL( average_count_3d, kind=wp )
9935                  ENDIF
9936              ENDDO
9937
9938          CASE ( 'rtm_rad_inlwdif' )
9939!--           array of sw radiation falling to surface after i-th reflection
9940              DO isurf = dirstart(ids), dirend(ids)
9941                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9942                      surfinlwdif_av(isurf) = surfinlwdif_av(isurf) / REAL( average_count_3d, kind=wp )
9943                  ENDIF
9944              ENDDO
9945
9946          CASE ( 'rtm_rad_inlwref' )
9947!--           array of lw radiation falling to surface from reflections
9948              DO isurf = dirstart(ids), dirend(ids)
9949                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9950                      surfinlwref_av(isurf) = surfinlwref_av(isurf) / REAL( average_count_3d, kind=wp )
9951                  ENDIF
9952              ENDDO
9953
9954          CASE ( 'rtm_rad_outsw' )
9955!--           array of sw radiation emitted from surface after i-th reflection
9956              DO isurf = dirstart(ids), dirend(ids)
9957                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9958                      surfoutsw_av(isurf) = surfoutsw_av(isurf) / REAL( average_count_3d, kind=wp )
9959                  ENDIF
9960              ENDDO
9961
9962          CASE ( 'rtm_rad_outlw' )
9963!--           array of lw radiation emitted from surface after i-th reflection
9964              DO isurf = dirstart(ids), dirend(ids)
9965                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9966                      surfoutlw_av(isurf) = surfoutlw_av(isurf) / REAL( average_count_3d, kind=wp )
9967                  ENDIF
9968              ENDDO
9969
9970          CASE ( 'rtm_rad_ressw' )
9971!--           array of residua of sw radiation absorbed in surface after last reflection
9972              DO isurf = dirstart(ids), dirend(ids)
9973                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9974                      surfins_av(isurf) = surfins_av(isurf) / REAL( average_count_3d, kind=wp )
9975                  ENDIF
9976              ENDDO
9977
9978          CASE ( 'rtm_rad_reslw' )
9979!--           array of residua of lw radiation absorbed in surface after last reflection
9980              DO isurf = dirstart(ids), dirend(ids)
9981                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9982                      surfinl_av(isurf) = surfinl_av(isurf) / REAL( average_count_3d, kind=wp )
9983                  ENDIF
9984              ENDDO
9985
9986          CASE ( 'rtm_rad_pc_inlw' )
9987              DO l = 1, npcbl
9988                 pcbinlw_av(:) = pcbinlw_av(:) / REAL( average_count_3d, kind=wp )
9989              ENDDO
9990
9991          CASE ( 'rtm_rad_pc_insw' )
9992              DO l = 1, npcbl
9993                 pcbinsw_av(:) = pcbinsw_av(:) / REAL( average_count_3d, kind=wp )
9994              ENDDO
9995
9996          CASE ( 'rtm_rad_pc_inswdir' )
9997              DO l = 1, npcbl
9998                 pcbinswdir_av(:) = pcbinswdir_av(:) / REAL( average_count_3d, kind=wp )
9999              ENDDO
10000
10001          CASE ( 'rtm_rad_pc_inswdif' )
10002              DO l = 1, npcbl
10003                 pcbinswdif_av(:) = pcbinswdif_av(:) / REAL( average_count_3d, kind=wp )
10004              ENDDO
10005
10006          CASE ( 'rtm_rad_pc_inswref' )
10007              DO l = 1, npcbl
10008                 pcbinswref_av(:) = pcbinswref_av(:) / REAL( average_count_3d, kind=wp )
10009              ENDDO
10010
10011          CASE ( 'rad_mrt_lw' )
10012             IF ( ALLOCATED( mrtinlw_av ) )  THEN
10013                mrtinlw_av(:) = mrtinlw_av(:) / REAL( average_count_3d, KIND=wp )
10014             ENDIF
10015
10016          CASE ( 'rad_mrt' )
10017             IF ( ALLOCATED( mrt_av ) )  THEN
10018                mrt_av(:) = mrt_av(:) / REAL( average_count_3d, KIND=wp )
10019             ENDIF
10020
10021       END SELECT
10022
10023    ENDIF
10024
10025END SUBROUTINE radiation_3d_data_averaging
10026
10027
10028!------------------------------------------------------------------------------!
10029!
10030! Description:
10031! ------------
10032!> Subroutine defining appropriate grid for netcdf variables.
10033!> It is called out from subroutine netcdf.
10034!------------------------------------------------------------------------------!
10035SUBROUTINE radiation_define_netcdf_grid( variable, found, grid_x, grid_y, grid_z )
10036   
10037    IMPLICIT NONE
10038
10039    CHARACTER (LEN=*), INTENT(IN)  ::  variable    !<
10040    LOGICAL, INTENT(OUT)           ::  found       !<
10041    CHARACTER (LEN=*), INTENT(OUT) ::  grid_x      !<
10042    CHARACTER (LEN=*), INTENT(OUT) ::  grid_y      !<
10043    CHARACTER (LEN=*), INTENT(OUT) ::  grid_z      !<
10044
10045    CHARACTER (len=varnamelength)  :: var
10046
10047    found  = .TRUE.
10048
10049!
10050!-- Check for the grid
10051    var = TRIM(variable)
10052!-- RTM directional variables
10053    IF ( var(1:12) == 'rtm_rad_net_'  .OR.  var(1:13) == 'rtm_rad_insw_'  .OR.          &
10054         var(1:13) == 'rtm_rad_inlw_'  .OR.  var(1:16) == 'rtm_rad_inswdir_'  .OR.      &
10055         var(1:16) == 'rtm_rad_inswdif_'  .OR.  var(1:16) == 'rtm_rad_inswref_'  .OR.   &
10056         var(1:16) == 'rtm_rad_inlwdif_'  .OR.  var(1:16) == 'rtm_rad_inlwref_'  .OR.   &
10057         var(1:14) == 'rtm_rad_outsw_'  .OR.  var(1:14) == 'rtm_rad_outlw_'  .OR.       &
10058         var(1:14) == 'rtm_rad_ressw_'  .OR.  var(1:14) == 'rtm_rad_reslw_'  .OR.       &
10059         var == 'rtm_rad_pc_inlw'  .OR.                                                 &
10060         var == 'rtm_rad_pc_insw'  .OR.  var == 'rtm_rad_pc_inswdir'  .OR.              &
10061         var == 'rtm_rad_pc_inswdif'  .OR.  var == 'rtm_rad_pc_inswref'  .OR.           &
10062         var(1:7) == 'rtm_svf'  .OR.  var(1:7) == 'rtm_dif'  .OR.                       &
10063         var(1:9) == 'rtm_skyvf' .OR. var(1:10) == 'rtm_skyvft'  .OR.                   &
10064         var(1:12) == 'rtm_surfalb_'  .OR.  var(1:13) == 'rtm_surfemis_'  .OR.          &
10065         var == 'rtm_mrt'  .OR.  var ==  'rtm_mrt_sw'  .OR.  var == 'rtm_mrt_lw' )  THEN
10066
10067         found = .TRUE.
10068         grid_x = 'x'
10069         grid_y = 'y'
10070         grid_z = 'zu'
10071    ELSE
10072
10073       SELECT CASE ( TRIM( var ) )
10074
10075          CASE ( 'rad_lw_cs_hr', 'rad_lw_hr', 'rad_sw_cs_hr', 'rad_sw_hr',        &
10076                 'rad_lw_cs_hr_xy', 'rad_lw_hr_xy', 'rad_sw_cs_hr_xy',            &
10077                 'rad_sw_hr_xy', 'rad_lw_cs_hr_xz', 'rad_lw_hr_xz',               &
10078                 'rad_sw_cs_hr_xz', 'rad_sw_hr_xz', 'rad_lw_cs_hr_yz',            &
10079                 'rad_lw_hr_yz', 'rad_sw_cs_hr_yz', 'rad_sw_hr_yz',               &
10080                 'rad_mrt', 'rad_mrt_sw', 'rad_mrt_lw' )
10081             grid_x = 'x'
10082             grid_y = 'y'
10083             grid_z = 'zu'
10084
10085          CASE ( 'rad_lw_in', 'rad_lw_out', 'rad_sw_in', 'rad_sw_out',            &
10086                 'rad_lw_in_xy', 'rad_lw_out_xy', 'rad_sw_in_xy','rad_sw_out_xy', &
10087                 'rad_lw_in_xz', 'rad_lw_out_xz', 'rad_sw_in_xz','rad_sw_out_xz', &
10088                 'rad_lw_in_yz', 'rad_lw_out_yz', 'rad_sw_in_yz','rad_sw_out_yz' )
10089             grid_x = 'x'
10090             grid_y = 'y'
10091             grid_z = 'zw'
10092
10093
10094          CASE DEFAULT
10095             found  = .FALSE.
10096             grid_x = 'none'
10097             grid_y = 'none'
10098             grid_z = 'none'
10099
10100           END SELECT
10101       ENDIF
10102
10103    END SUBROUTINE radiation_define_netcdf_grid
10104
10105!------------------------------------------------------------------------------!
10106!
10107! Description:
10108! ------------
10109!> Subroutine defining 2D output variables
10110!------------------------------------------------------------------------------!
10111 SUBROUTINE radiation_data_output_2d( av, variable, found, grid, mode,         &
10112                                      local_pf, two_d, nzb_do, nzt_do )
10113 
10114    USE indices
10115
10116    USE kinds
10117
10118
10119    IMPLICIT NONE
10120
10121    CHARACTER (LEN=*) ::  grid     !<
10122    CHARACTER (LEN=*) ::  mode     !<
10123    CHARACTER (LEN=*) ::  variable !<
10124
10125    INTEGER(iwp) ::  av !<
10126    INTEGER(iwp) ::  i  !<
10127    INTEGER(iwp) ::  j  !<
10128    INTEGER(iwp) ::  k  !<
10129    INTEGER(iwp) ::  m  !< index of surface element at grid point (j,i)
10130    INTEGER(iwp) ::  nzb_do   !<
10131    INTEGER(iwp) ::  nzt_do   !<
10132
10133    LOGICAL      ::  found !<
10134    LOGICAL      ::  two_d !< flag parameter that indicates 2D variables (horizontal cross sections)
10135
10136    REAL(wp) ::  fill_value = -999.0_wp    !< value for the _FillValue attribute
10137
10138    REAL(wp), DIMENSION(nxl:nxr,nys:nyn,nzb_do:nzt_do) ::  local_pf !<
10139
10140    found = .TRUE.
10141
10142    SELECT CASE ( TRIM( variable ) )
10143
10144       CASE ( 'rad_net*_xy' )        ! 2d-array
10145          IF ( av == 0 ) THEN
10146             DO  i = nxl, nxr
10147                DO  j = nys, nyn
10148!
10149!--                Obtain rad_net from its respective surface type
10150!--                Natural-type surfaces
10151                   DO  m = surf_lsm_h%start_index(j,i),                        &
10152                           surf_lsm_h%end_index(j,i) 
10153                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_net(m)
10154                   ENDDO
10155!
10156!--                Urban-type surfaces
10157                   DO  m = surf_usm_h%start_index(j,i),                        &
10158                           surf_usm_h%end_index(j,i) 
10159                      local_pf(i,j,nzb+1) = surf_usm_h%rad_net(m)
10160                   ENDDO
10161                ENDDO
10162             ENDDO
10163          ELSE
10164             IF ( .NOT. ALLOCATED( rad_net_av ) ) THEN
10165                ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
10166                rad_net_av = REAL( fill_value, KIND = wp )
10167             ENDIF
10168             DO  i = nxl, nxr
10169                DO  j = nys, nyn 
10170                   local_pf(i,j,nzb+1) = rad_net_av(j,i)
10171                ENDDO
10172             ENDDO
10173          ENDIF
10174          two_d = .TRUE.
10175          grid = 'zu1'
10176         
10177       CASE ( 'rad_lw_in*_xy' )        ! 2d-array
10178          IF ( av == 0 ) THEN
10179             DO  i = nxl, nxr
10180                DO  j = nys, nyn
10181!
10182!--                Obtain rad_net from its respective surface type
10183!--                Natural-type surfaces
10184                   DO  m = surf_lsm_h%start_index(j,i),                        &
10185                           surf_lsm_h%end_index(j,i) 
10186                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_lw_in(m)
10187                   ENDDO
10188!
10189!--                Urban-type surfaces
10190                   DO  m = surf_usm_h%start_index(j,i),                        &
10191                           surf_usm_h%end_index(j,i) 
10192                      local_pf(i,j,nzb+1) = surf_usm_h%rad_lw_in(m)
10193                   ENDDO
10194                ENDDO
10195             ENDDO
10196          ELSE
10197             IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) ) THEN
10198                ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
10199                rad_lw_in_xy_av = REAL( fill_value, KIND = wp )
10200             ENDIF
10201             DO  i = nxl, nxr
10202                DO  j = nys, nyn 
10203                   local_pf(i,j,nzb+1) = rad_lw_in_xy_av(j,i)
10204                ENDDO
10205             ENDDO
10206          ENDIF
10207          two_d = .TRUE.
10208          grid = 'zu1'
10209         
10210       CASE ( 'rad_lw_out*_xy' )        ! 2d-array
10211          IF ( av == 0 ) THEN
10212             DO  i = nxl, nxr
10213                DO  j = nys, nyn
10214!
10215!--                Obtain rad_net from its respective surface type
10216!--                Natural-type surfaces
10217                   DO  m = surf_lsm_h%start_index(j,i),                        &
10218                           surf_lsm_h%end_index(j,i) 
10219                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_lw_out(m)
10220                   ENDDO
10221!
10222!--                Urban-type surfaces
10223                   DO  m = surf_usm_h%start_index(j,i),                        &
10224                           surf_usm_h%end_index(j,i) 
10225                      local_pf(i,j,nzb+1) = surf_usm_h%rad_lw_out(m)
10226                   ENDDO
10227                ENDDO
10228             ENDDO
10229          ELSE
10230             IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) ) THEN
10231                ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
10232                rad_lw_out_xy_av = REAL( fill_value, KIND = wp )
10233             ENDIF
10234             DO  i = nxl, nxr
10235                DO  j = nys, nyn 
10236                   local_pf(i,j,nzb+1) = rad_lw_out_xy_av(j,i)
10237                ENDDO
10238             ENDDO
10239          ENDIF
10240          two_d = .TRUE.
10241          grid = 'zu1'
10242         
10243       CASE ( 'rad_sw_in*_xy' )        ! 2d-array
10244          IF ( av == 0 ) THEN
10245             DO  i = nxl, nxr
10246                DO  j = nys, nyn
10247!
10248!--                Obtain rad_net from its respective surface type
10249!--                Natural-type surfaces
10250                   DO  m = surf_lsm_h%start_index(j,i),                        &
10251                           surf_lsm_h%end_index(j,i) 
10252                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_sw_in(m)
10253                   ENDDO
10254!
10255!--                Urban-type surfaces
10256                   DO  m = surf_usm_h%start_index(j,i),                        &
10257                           surf_usm_h%end_index(j,i) 
10258                      local_pf(i,j,nzb+1) = surf_usm_h%rad_sw_in(m)
10259                   ENDDO
10260                ENDDO
10261             ENDDO
10262          ELSE
10263             IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) ) THEN
10264                ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
10265                rad_sw_in_xy_av = REAL( fill_value, KIND = wp )
10266             ENDIF
10267             DO  i = nxl, nxr
10268                DO  j = nys, nyn 
10269                   local_pf(i,j,nzb+1) = rad_sw_in_xy_av(j,i)
10270                ENDDO
10271             ENDDO
10272          ENDIF
10273          two_d = .TRUE.
10274          grid = 'zu1'
10275         
10276       CASE ( 'rad_sw_out*_xy' )        ! 2d-array
10277          IF ( av == 0 ) THEN
10278             DO  i = nxl, nxr
10279                DO  j = nys, nyn
10280!
10281!--                Obtain rad_net from its respective surface type
10282!--                Natural-type surfaces
10283                   DO  m = surf_lsm_h%start_index(j,i),                        &
10284                           surf_lsm_h%end_index(j,i) 
10285                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_sw_out(m)
10286                   ENDDO
10287!
10288!--                Urban-type surfaces
10289                   DO  m = surf_usm_h%start_index(j,i),                        &
10290                           surf_usm_h%end_index(j,i) 
10291                      local_pf(i,j,nzb+1) = surf_usm_h%rad_sw_out(m)
10292                   ENDDO
10293                ENDDO
10294             ENDDO
10295          ELSE
10296             IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) ) THEN
10297                ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
10298                rad_sw_out_xy_av = REAL( fill_value, KIND = wp )
10299             ENDIF
10300             DO  i = nxl, nxr
10301                DO  j = nys, nyn 
10302                   local_pf(i,j,nzb+1) = rad_sw_out_xy_av(j,i)
10303                ENDDO
10304             ENDDO
10305          ENDIF
10306          two_d = .TRUE.
10307          grid = 'zu1'         
10308         
10309       CASE ( 'rad_lw_in_xy', 'rad_lw_in_xz', 'rad_lw_in_yz' )
10310          IF ( av == 0 ) THEN
10311             DO  i = nxl, nxr
10312                DO  j = nys, nyn
10313                   DO  k = nzb_do, nzt_do
10314                      local_pf(i,j,k) = rad_lw_in(k,j,i)
10315                   ENDDO
10316                ENDDO
10317             ENDDO
10318          ELSE
10319            IF ( .NOT. ALLOCATED( rad_lw_in_av ) ) THEN
10320               ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10321               rad_lw_in_av = REAL( fill_value, KIND = wp )
10322            ENDIF
10323             DO  i = nxl, nxr
10324                DO  j = nys, nyn 
10325                   DO  k = nzb_do, nzt_do
10326                      local_pf(i,j,k) = rad_lw_in_av(k,j,i)
10327                   ENDDO
10328                ENDDO
10329             ENDDO
10330          ENDIF
10331          IF ( mode == 'xy' )  grid = 'zu'
10332
10333       CASE ( 'rad_lw_out_xy', 'rad_lw_out_xz', 'rad_lw_out_yz' )
10334          IF ( av == 0 ) THEN
10335             DO  i = nxl, nxr
10336                DO  j = nys, nyn
10337                   DO  k = nzb_do, nzt_do
10338                      local_pf(i,j,k) = rad_lw_out(k,j,i)
10339                   ENDDO
10340                ENDDO
10341             ENDDO
10342          ELSE
10343            IF ( .NOT. ALLOCATED( rad_lw_out_av ) ) THEN
10344               ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10345               rad_lw_out_av = REAL( fill_value, KIND = wp )
10346            ENDIF
10347             DO  i = nxl, nxr
10348                DO  j = nys, nyn 
10349                   DO  k = nzb_do, nzt_do
10350                      local_pf(i,j,k) = rad_lw_out_av(k,j,i)
10351                   ENDDO
10352                ENDDO
10353             ENDDO
10354          ENDIF   
10355          IF ( mode == 'xy' )  grid = 'zu'
10356
10357       CASE ( 'rad_lw_cs_hr_xy', 'rad_lw_cs_hr_xz', 'rad_lw_cs_hr_yz' )
10358          IF ( av == 0 ) THEN
10359             DO  i = nxl, nxr
10360                DO  j = nys, nyn
10361                   DO  k = nzb_do, nzt_do
10362                      local_pf(i,j,k) = rad_lw_cs_hr(k,j,i)
10363                   ENDDO
10364                ENDDO
10365             ENDDO
10366          ELSE
10367            IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) ) THEN
10368               ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10369               rad_lw_cs_hr_av = REAL( fill_value, KIND = wp )
10370            ENDIF
10371             DO  i = nxl, nxr
10372                DO  j = nys, nyn 
10373                   DO  k = nzb_do, nzt_do
10374                      local_pf(i,j,k) = rad_lw_cs_hr_av(k,j,i)
10375                   ENDDO
10376                ENDDO
10377             ENDDO
10378          ENDIF
10379          IF ( mode == 'xy' )  grid = 'zw'
10380
10381       CASE ( 'rad_lw_hr_xy', 'rad_lw_hr_xz', 'rad_lw_hr_yz' )
10382          IF ( av == 0 ) THEN
10383             DO  i = nxl, nxr
10384                DO  j = nys, nyn
10385                   DO  k = nzb_do, nzt_do
10386                      local_pf(i,j,k) = rad_lw_hr(k,j,i)
10387                   ENDDO
10388                ENDDO
10389             ENDDO
10390          ELSE
10391            IF ( .NOT. ALLOCATED( rad_lw_hr_av ) ) THEN
10392               ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10393               rad_lw_hr_av= REAL( fill_value, KIND = wp )
10394            ENDIF
10395             DO  i = nxl, nxr
10396                DO  j = nys, nyn 
10397                   DO  k = nzb_do, nzt_do
10398                      local_pf(i,j,k) = rad_lw_hr_av(k,j,i)
10399                   ENDDO
10400                ENDDO
10401             ENDDO
10402          ENDIF
10403          IF ( mode == 'xy' )  grid = 'zw'
10404
10405       CASE ( 'rad_sw_in_xy', 'rad_sw_in_xz', 'rad_sw_in_yz' )
10406          IF ( av == 0 ) THEN
10407             DO  i = nxl, nxr
10408                DO  j = nys, nyn
10409                   DO  k = nzb_do, nzt_do
10410                      local_pf(i,j,k) = rad_sw_in(k,j,i)
10411                   ENDDO
10412                ENDDO
10413             ENDDO
10414          ELSE
10415            IF ( .NOT. ALLOCATED( rad_sw_in_av ) ) THEN
10416               ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10417               rad_sw_in_av = REAL( fill_value, KIND = wp )
10418            ENDIF
10419             DO  i = nxl, nxr
10420                DO  j = nys, nyn 
10421                   DO  k = nzb_do, nzt_do
10422                      local_pf(i,j,k) = rad_sw_in_av(k,j,i)
10423                   ENDDO
10424                ENDDO
10425             ENDDO
10426          ENDIF
10427          IF ( mode == 'xy' )  grid = 'zu'
10428
10429       CASE ( 'rad_sw_out_xy', 'rad_sw_out_xz', 'rad_sw_out_yz' )
10430          IF ( av == 0 ) THEN
10431             DO  i = nxl, nxr
10432                DO  j = nys, nyn
10433                   DO  k = nzb_do, nzt_do
10434                      local_pf(i,j,k) = rad_sw_out(k,j,i)
10435                   ENDDO
10436                ENDDO
10437             ENDDO
10438          ELSE
10439            IF ( .NOT. ALLOCATED( rad_sw_out_av ) ) THEN
10440               ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10441               rad_sw_out_av = REAL( fill_value, KIND = wp )
10442            ENDIF
10443             DO  i = nxl, nxr
10444                DO  j = nys, nyn 
10445                   DO  k = nzb, nzt+1
10446                      local_pf(i,j,k) = rad_sw_out_av(k,j,i)
10447                   ENDDO
10448                ENDDO
10449             ENDDO
10450          ENDIF
10451          IF ( mode == 'xy' )  grid = 'zu'
10452
10453       CASE ( 'rad_sw_cs_hr_xy', 'rad_sw_cs_hr_xz', 'rad_sw_cs_hr_yz' )
10454          IF ( av == 0 ) THEN
10455             DO  i = nxl, nxr
10456                DO  j = nys, nyn
10457                   DO  k = nzb_do, nzt_do
10458                      local_pf(i,j,k) = rad_sw_cs_hr(k,j,i)
10459                   ENDDO
10460                ENDDO
10461             ENDDO
10462          ELSE
10463            IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) ) THEN
10464               ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10465               rad_sw_cs_hr_av = REAL( fill_value, KIND = wp )
10466            ENDIF
10467             DO  i = nxl, nxr
10468                DO  j = nys, nyn 
10469                   DO  k = nzb_do, nzt_do
10470                      local_pf(i,j,k) = rad_sw_cs_hr_av(k,j,i)
10471                   ENDDO
10472                ENDDO
10473             ENDDO
10474          ENDIF
10475          IF ( mode == 'xy' )  grid = 'zw'
10476
10477       CASE ( 'rad_sw_hr_xy', 'rad_sw_hr_xz', 'rad_sw_hr_yz' )
10478          IF ( av == 0 ) THEN
10479             DO  i = nxl, nxr
10480                DO  j = nys, nyn
10481                   DO  k = nzb_do, nzt_do
10482                      local_pf(i,j,k) = rad_sw_hr(k,j,i)
10483                   ENDDO
10484                ENDDO
10485             ENDDO
10486          ELSE
10487            IF ( .NOT. ALLOCATED( rad_sw_hr_av ) ) THEN
10488               ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10489               rad_sw_hr_av = REAL( fill_value, KIND = wp )
10490            ENDIF
10491             DO  i = nxl, nxr
10492                DO  j = nys, nyn 
10493                   DO  k = nzb_do, nzt_do
10494                      local_pf(i,j,k) = rad_sw_hr_av(k,j,i)
10495                   ENDDO
10496                ENDDO
10497             ENDDO
10498          ENDIF
10499          IF ( mode == 'xy' )  grid = 'zw'
10500
10501       CASE DEFAULT
10502          found = .FALSE.
10503          grid  = 'none'
10504
10505    END SELECT
10506 
10507 END SUBROUTINE radiation_data_output_2d
10508
10509
10510!------------------------------------------------------------------------------!
10511!
10512! Description:
10513! ------------
10514!> Subroutine defining 3D output variables
10515!------------------------------------------------------------------------------!
10516 SUBROUTINE radiation_data_output_3d( av, variable, found, local_pf, nzb_do, nzt_do )
10517 
10518
10519    USE indices
10520
10521    USE kinds
10522
10523
10524    IMPLICIT NONE
10525
10526    CHARACTER (LEN=*) ::  variable !<
10527
10528    INTEGER(iwp) ::  av          !<
10529    INTEGER(iwp) ::  i, j, k, l  !<
10530    INTEGER(iwp) ::  nzb_do      !<
10531    INTEGER(iwp) ::  nzt_do      !<
10532
10533    LOGICAL      ::  found       !<
10534
10535    REAL(wp)     ::  fill_value = -999.0_wp    !< value for the _FillValue attribute
10536
10537    REAL(sp), DIMENSION(nxl:nxr,nys:nyn,nzb_do:nzt_do) ::  local_pf !<
10538
10539    CHARACTER (len=varnamelength)                   :: var, surfid
10540    INTEGER(iwp)                                    :: ids,idsint_u,idsint_l,isurf,isvf,isurfs,isurflt,ipcgb
10541    INTEGER(iwp)                                    :: is, js, ks, istat
10542
10543    found = .TRUE.
10544    var = TRIM(variable)
10545
10546!-- check if variable belongs to radiation related variables (starts with rad or rtm)
10547    IF ( len(var) < 3_iwp  )  THEN
10548       found = .FALSE.
10549       RETURN
10550    ENDIF
10551   
10552    IF ( var(1:3) /= 'rad'  .AND.  var(1:3) /= 'rtm' )  THEN
10553       found = .FALSE.
10554       RETURN
10555    ENDIF
10556
10557    ids = -1
10558    DO i = 0, nd-1
10559        k = len(TRIM(var))
10560        j = len(TRIM(dirname(i)))
10561        IF ( k-j+1 >= 1_iwp ) THEN
10562           IF ( TRIM(var(k-j+1:k)) == TRIM(dirname(i)) )  THEN
10563              ids = i
10564              idsint_u = dirint_u(ids)
10565              idsint_l = dirint_l(ids)
10566              var = var(:k-j)
10567              EXIT
10568           ENDIF
10569        ENDIF
10570    ENDDO
10571    IF ( ids == -1 )  THEN
10572        var = TRIM(variable)
10573    ENDIF
10574
10575    IF ( (var(1:8) == 'rtm_svf_'  .OR.  var(1:8) == 'rtm_dif_')  .AND.  len(TRIM(var)) >= 13 )  THEN
10576!--     svf values to particular surface
10577        surfid = var(9:)
10578        i = index(surfid,'_')
10579        j = index(surfid(i+1:),'_')
10580        READ(surfid(1:i-1),*, iostat=istat ) is
10581        IF ( istat == 0 )  THEN
10582            READ(surfid(i+1:i+j-1),*, iostat=istat ) js
10583        ENDIF
10584        IF ( istat == 0 )  THEN
10585            READ(surfid(i+j+1:),*, iostat=istat ) ks
10586        ENDIF
10587        IF ( istat == 0 )  THEN
10588            var = var(1:7)
10589        ENDIF
10590    ENDIF
10591
10592    local_pf = fill_value
10593
10594    SELECT CASE ( TRIM( var ) )
10595!--   block of large scale radiation model (e.g. RRTMG) output variables
10596      CASE ( 'rad_sw_in' )
10597         IF ( av == 0 )  THEN
10598            DO  i = nxl, nxr
10599               DO  j = nys, nyn
10600                  DO  k = nzb_do, nzt_do
10601                     local_pf(i,j,k) = rad_sw_in(k,j,i)
10602                  ENDDO
10603               ENDDO
10604            ENDDO
10605         ELSE
10606            IF ( .NOT. ALLOCATED( rad_sw_in_av ) ) THEN
10607               ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10608               rad_sw_in_av = REAL( fill_value, KIND = wp )
10609            ENDIF
10610            DO  i = nxl, nxr
10611               DO  j = nys, nyn
10612                  DO  k = nzb_do, nzt_do
10613                     local_pf(i,j,k) = rad_sw_in_av(k,j,i)
10614                  ENDDO
10615               ENDDO
10616            ENDDO
10617         ENDIF
10618
10619      CASE ( 'rad_sw_out' )
10620         IF ( av == 0 )  THEN
10621            DO  i = nxl, nxr
10622               DO  j = nys, nyn
10623                  DO  k = nzb_do, nzt_do
10624                     local_pf(i,j,k) = rad_sw_out(k,j,i)
10625                  ENDDO
10626               ENDDO
10627            ENDDO
10628         ELSE
10629            IF ( .NOT. ALLOCATED( rad_sw_out_av ) ) THEN
10630               ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10631               rad_sw_out_av = REAL( fill_value, KIND = wp )
10632            ENDIF
10633            DO  i = nxl, nxr
10634               DO  j = nys, nyn
10635                  DO  k = nzb_do, nzt_do
10636                     local_pf(i,j,k) = rad_sw_out_av(k,j,i)
10637                  ENDDO
10638               ENDDO
10639            ENDDO
10640         ENDIF
10641
10642      CASE ( 'rad_sw_cs_hr' )
10643         IF ( av == 0 )  THEN
10644            DO  i = nxl, nxr
10645               DO  j = nys, nyn
10646                  DO  k = nzb_do, nzt_do
10647                     local_pf(i,j,k) = rad_sw_cs_hr(k,j,i)
10648                  ENDDO
10649               ENDDO
10650            ENDDO
10651         ELSE
10652            IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) ) THEN
10653               ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10654               rad_sw_cs_hr_av = REAL( fill_value, KIND = wp )
10655            ENDIF
10656            DO  i = nxl, nxr
10657               DO  j = nys, nyn
10658                  DO  k = nzb_do, nzt_do
10659                     local_pf(i,j,k) = rad_sw_cs_hr_av(k,j,i)
10660                  ENDDO
10661               ENDDO
10662            ENDDO
10663         ENDIF
10664
10665      CASE ( 'rad_sw_hr' )
10666         IF ( av == 0 )  THEN
10667            DO  i = nxl, nxr
10668               DO  j = nys, nyn
10669                  DO  k = nzb_do, nzt_do
10670                     local_pf(i,j,k) = rad_sw_hr(k,j,i)
10671                  ENDDO
10672               ENDDO
10673            ENDDO
10674         ELSE
10675            IF ( .NOT. ALLOCATED( rad_sw_hr_av ) ) THEN
10676               ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10677               rad_sw_hr_av = REAL( fill_value, KIND = wp )
10678            ENDIF
10679            DO  i = nxl, nxr
10680               DO  j = nys, nyn
10681                  DO  k = nzb_do, nzt_do
10682                     local_pf(i,j,k) = rad_sw_hr_av(k,j,i)
10683                  ENDDO
10684               ENDDO
10685            ENDDO
10686         ENDIF
10687
10688      CASE ( 'rad_lw_in' )
10689         IF ( av == 0 )  THEN
10690            DO  i = nxl, nxr
10691               DO  j = nys, nyn
10692                  DO  k = nzb_do, nzt_do
10693                     local_pf(i,j,k) = rad_lw_in(k,j,i)
10694                  ENDDO
10695               ENDDO
10696            ENDDO
10697         ELSE
10698            IF ( .NOT. ALLOCATED( rad_lw_in_av ) ) THEN
10699               ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10700               rad_lw_in_av = REAL( fill_value, KIND = wp )
10701            ENDIF
10702            DO  i = nxl, nxr
10703               DO  j = nys, nyn
10704                  DO  k = nzb_do, nzt_do
10705                     local_pf(i,j,k) = rad_lw_in_av(k,j,i)
10706                  ENDDO
10707               ENDDO
10708            ENDDO
10709         ENDIF
10710
10711      CASE ( 'rad_lw_out' )
10712         IF ( av == 0 )  THEN
10713            DO  i = nxl, nxr
10714               DO  j = nys, nyn
10715                  DO  k = nzb_do, nzt_do
10716                     local_pf(i,j,k) = rad_lw_out(k,j,i)
10717                  ENDDO
10718               ENDDO
10719            ENDDO
10720         ELSE
10721            IF ( .NOT. ALLOCATED( rad_lw_out_av ) ) THEN
10722               ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10723               rad_lw_out_av = REAL( fill_value, KIND = wp )
10724            ENDIF
10725            DO  i = nxl, nxr
10726               DO  j = nys, nyn
10727                  DO  k = nzb_do, nzt_do
10728                     local_pf(i,j,k) = rad_lw_out_av(k,j,i)
10729                  ENDDO
10730               ENDDO
10731            ENDDO
10732         ENDIF
10733
10734      CASE ( 'rad_lw_cs_hr' )
10735         IF ( av == 0 )  THEN
10736            DO  i = nxl, nxr
10737               DO  j = nys, nyn
10738                  DO  k = nzb_do, nzt_do
10739                     local_pf(i,j,k) = rad_lw_cs_hr(k,j,i)
10740                  ENDDO
10741               ENDDO
10742            ENDDO
10743         ELSE
10744            IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) ) THEN
10745               ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10746               rad_lw_cs_hr_av = REAL( fill_value, KIND = wp )
10747            ENDIF
10748            DO  i = nxl, nxr
10749               DO  j = nys, nyn
10750                  DO  k = nzb_do, nzt_do
10751                     local_pf(i,j,k) = rad_lw_cs_hr_av(k,j,i)
10752                  ENDDO
10753               ENDDO
10754            ENDDO
10755         ENDIF
10756
10757      CASE ( 'rad_lw_hr' )
10758         IF ( av == 0 )  THEN
10759            DO  i = nxl, nxr
10760               DO  j = nys, nyn
10761                  DO  k = nzb_do, nzt_do
10762                     local_pf(i,j,k) = rad_lw_hr(k,j,i)
10763                  ENDDO
10764               ENDDO
10765            ENDDO
10766         ELSE
10767            IF ( .NOT. ALLOCATED( rad_lw_hr_av ) ) THEN
10768               ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10769              rad_lw_hr_av = REAL( fill_value, KIND = wp )
10770            ENDIF
10771            DO  i = nxl, nxr
10772               DO  j = nys, nyn
10773                  DO  k = nzb_do, nzt_do
10774                     local_pf(i,j,k) = rad_lw_hr_av(k,j,i)
10775                  ENDDO
10776               ENDDO
10777            ENDDO
10778         ENDIF
10779
10780      CASE ( 'rtm_rad_net' )
10781!--     array of complete radiation balance
10782         DO isurf = dirstart(ids), dirend(ids)
10783            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10784               IF ( av == 0 )  THEN
10785                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = &
10786                         surfinsw(isurf) - surfoutsw(isurf) +  surfinlw(isurf) - surfoutlw(isurf)
10787               ELSE
10788                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfradnet_av(isurf)
10789               ENDIF
10790            ENDIF
10791         ENDDO
10792
10793      CASE ( 'rtm_rad_insw' )
10794!--      array of sw radiation falling to surface after i-th reflection
10795         DO isurf = dirstart(ids), dirend(ids)
10796            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10797               IF ( av == 0 )  THEN
10798                 local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinsw(isurf)
10799               ELSE
10800                 local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinsw_av(isurf)
10801               ENDIF
10802            ENDIF
10803         ENDDO
10804
10805      CASE ( 'rtm_rad_inlw' )
10806!--      array of lw radiation falling to surface after i-th reflection
10807         DO isurf = dirstart(ids), dirend(ids)
10808            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10809               IF ( av == 0 )  THEN
10810                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlw(isurf)
10811               ELSE
10812                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlw_av(isurf)
10813               ENDIF
10814             ENDIF
10815         ENDDO
10816
10817      CASE ( 'rtm_rad_inswdir' )
10818!--      array of direct sw radiation falling to surface from sun
10819         DO isurf = dirstart(ids), dirend(ids)
10820            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10821               IF ( av == 0 )  THEN
10822                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdir(isurf)
10823               ELSE
10824                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdir_av(isurf)
10825               ENDIF
10826            ENDIF
10827         ENDDO
10828
10829      CASE ( 'rtm_rad_inswdif' )
10830!--      array of difusion sw radiation falling to surface from sky and borders of the domain
10831         DO isurf = dirstart(ids), dirend(ids)
10832            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10833               IF ( av == 0 )  THEN
10834                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdif(isurf)
10835               ELSE
10836                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdif_av(isurf)
10837               ENDIF
10838            ENDIF
10839         ENDDO
10840
10841      CASE ( 'rtm_rad_inswref' )
10842!--      array of sw radiation falling to surface from reflections
10843         DO isurf = dirstart(ids), dirend(ids)
10844            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10845               IF ( av == 0 )  THEN
10846                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = &
10847                    surfinsw(isurf) - surfinswdir(isurf) - surfinswdif(isurf)
10848               ELSE
10849                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswref_av(isurf)
10850               ENDIF
10851            ENDIF
10852         ENDDO
10853
10854      CASE ( 'rtm_rad_inlwdif' )
10855!--      array of difusion lw radiation falling to surface from sky and borders of the domain
10856         DO isurf = dirstart(ids), dirend(ids)
10857            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10858               IF ( av == 0 )  THEN
10859                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlwdif(isurf)
10860               ELSE
10861                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlwdif_av(isurf)
10862               ENDIF
10863            ENDIF
10864         ENDDO
10865
10866      CASE ( 'rtm_rad_inlwref' )
10867!--      array of lw radiation falling to surface from reflections
10868         DO isurf = dirstart(ids), dirend(ids)
10869            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10870               IF ( av == 0 )  THEN
10871                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlw(isurf) - surfinlwdif(isurf)
10872               ELSE
10873                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlwref_av(isurf)
10874               ENDIF
10875            ENDIF
10876         ENDDO
10877
10878      CASE ( 'rtm_rad_outsw' )
10879!--      array of sw radiation emitted from surface after i-th reflection
10880         DO isurf = dirstart(ids), dirend(ids)
10881            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10882               IF ( av == 0 )  THEN
10883                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutsw(isurf)
10884               ELSE
10885                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutsw_av(isurf)
10886               ENDIF
10887            ENDIF
10888         ENDDO
10889
10890      CASE ( 'rtm_rad_outlw' )
10891!--      array of lw radiation emitted from surface after i-th reflection
10892         DO isurf = dirstart(ids), dirend(ids)
10893            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10894               IF ( av == 0 )  THEN
10895                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutlw(isurf)
10896               ELSE
10897                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutlw_av(isurf)
10898               ENDIF
10899            ENDIF
10900         ENDDO
10901
10902      CASE ( 'rtm_rad_ressw' )
10903!--      average of array of residua of sw radiation absorbed in surface after last reflection
10904         DO isurf = dirstart(ids), dirend(ids)
10905            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10906               IF ( av == 0 )  THEN
10907                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfins(isurf)
10908               ELSE
10909                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfins_av(isurf)
10910               ENDIF
10911            ENDIF
10912         ENDDO
10913
10914      CASE ( 'rtm_rad_reslw' )
10915!--      average of array of residua of lw radiation absorbed in surface after last reflection
10916         DO isurf = dirstart(ids), dirend(ids)
10917            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10918               IF ( av == 0 )  THEN
10919                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinl(isurf)
10920               ELSE
10921                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinl_av(isurf)
10922               ENDIF
10923            ENDIF
10924         ENDDO
10925
10926      CASE ( 'rtm_rad_pc_inlw' )
10927!--      array of lw radiation absorbed by plant canopy
10928         DO ipcgb = 1, npcbl
10929            IF ( av == 0 )  THEN
10930               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinlw(ipcgb)
10931            ELSE
10932               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinlw_av(ipcgb)
10933            ENDIF
10934         ENDDO
10935
10936      CASE ( 'rtm_rad_pc_insw' )
10937!--      array of sw radiation absorbed by plant canopy
10938         DO ipcgb = 1, npcbl
10939            IF ( av == 0 )  THEN
10940              local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinsw(ipcgb)
10941            ELSE
10942              local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinsw_av(ipcgb)
10943            ENDIF
10944         ENDDO
10945
10946      CASE ( 'rtm_rad_pc_inswdir' )
10947!--      array of direct sw radiation absorbed by plant canopy
10948         DO ipcgb = 1, npcbl
10949            IF ( av == 0 )  THEN
10950               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdir(ipcgb)
10951            ELSE
10952               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdir_av(ipcgb)
10953            ENDIF
10954         ENDDO
10955
10956      CASE ( 'rtm_rad_pc_inswdif' )
10957!--      array of diffuse sw radiation absorbed by plant canopy
10958         DO ipcgb = 1, npcbl
10959            IF ( av == 0 )  THEN
10960               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdif(ipcgb)
10961            ELSE
10962               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdif_av(ipcgb)
10963            ENDIF
10964         ENDDO
10965
10966      CASE ( 'rtm_rad_pc_inswref' )
10967!--      array of reflected sw radiation absorbed by plant canopy
10968         DO ipcgb = 1, npcbl
10969            IF ( av == 0 )  THEN
10970               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = &
10971                                    pcbinsw(ipcgb) - pcbinswdir(ipcgb) - pcbinswdif(ipcgb)
10972            ELSE
10973               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswref_av(ipcgb)
10974            ENDIF
10975         ENDDO
10976
10977      CASE ( 'rtm_mrt_sw' )
10978         local_pf = REAL( fill_value, KIND = wp )
10979         IF ( av == 0 )  THEN
10980            DO  l = 1, nmrtbl
10981               local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinsw(l)
10982            ENDDO
10983         ELSE
10984            IF ( ALLOCATED( mrtinsw_av ) ) THEN
10985               DO  l = 1, nmrtbl
10986                  local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinsw_av(l)
10987               ENDDO
10988            ENDIF
10989         ENDIF
10990
10991      CASE ( 'rtm_mrt_lw' )
10992         local_pf = REAL( fill_value, KIND = wp )
10993         IF ( av == 0 )  THEN
10994            DO  l = 1, nmrtbl
10995               local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinlw(l)
10996            ENDDO
10997         ELSE
10998            IF ( ALLOCATED( mrtinlw_av ) ) THEN
10999               DO  l = 1, nmrtbl
11000                  local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinlw_av(l)
11001               ENDDO
11002            ENDIF
11003         ENDIF
11004
11005      CASE ( 'rtm_mrt' )
11006         local_pf = REAL( fill_value, KIND = wp )
11007         IF ( av == 0 )  THEN
11008            DO  l = 1, nmrtbl
11009               local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrt(l)
11010            ENDDO
11011         ELSE
11012            IF ( ALLOCATED( mrt_av ) ) THEN
11013               DO  l = 1, nmrtbl
11014                  local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrt_av(l)
11015               ENDDO
11016            ENDIF
11017         ENDIF
11018!         
11019!--   block of RTM output variables
11020!--   variables are intended mainly for debugging and detailed analyse purposes
11021      CASE ( 'rtm_skyvf' )
11022!     
11023!--      sky view factor
11024         DO isurf = dirstart(ids), dirend(ids)
11025            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
11026               local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = skyvf(isurf)
11027            ENDIF
11028         ENDDO
11029
11030      CASE ( 'rtm_skyvft' )
11031!
11032!--      sky view factor
11033         DO isurf = dirstart(ids), dirend(ids)
11034            IF ( surfl(id,isurf) == ids )  THEN
11035               local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = skyvft(isurf)
11036            ENDIF
11037         ENDDO
11038
11039      CASE ( 'rtm_svf', 'rtm_dif' )
11040!
11041!--      shape view factors or iradiance factors to selected surface
11042         IF ( TRIM(var)=='rtm_svf' )  THEN
11043             k = 1
11044         ELSE
11045             k = 2
11046         ENDIF
11047         DO isvf = 1, nsvfl
11048            isurflt = svfsurf(1, isvf)
11049            isurfs = svfsurf(2, isvf)
11050
11051            IF ( surf(ix,isurfs) == is  .AND.  surf(iy,isurfs) == js  .AND. surf(iz,isurfs) == ks  .AND. &
11052                 (surf(id,isurfs) == idsint_u .OR. surfl(id,isurfs) == idsint_l ) ) THEN
11053!
11054!--            correct source surface
11055               local_pf(surfl(ix,isurflt),surfl(iy,isurflt),surfl(iz,isurflt)) = svf(k,isvf)
11056            ENDIF
11057         ENDDO
11058
11059      CASE ( 'rtm_surfalb' )
11060!
11061!--      surface albedo
11062         DO isurf = dirstart(ids), dirend(ids)
11063            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
11064               local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = albedo_surf(isurf)
11065            ENDIF
11066         ENDDO
11067
11068      CASE ( 'rtm_surfemis' )
11069!
11070!--      surface emissivity, weighted average
11071         DO isurf = dirstart(ids), dirend(ids)
11072            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
11073               local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = emiss_surf(isurf)
11074            ENDIF
11075         ENDDO
11076
11077      CASE DEFAULT
11078         found = .FALSE.
11079
11080    END SELECT
11081
11082
11083 END SUBROUTINE radiation_data_output_3d
11084
11085!------------------------------------------------------------------------------!
11086!
11087! Description:
11088! ------------
11089!> Subroutine defining masked data output
11090!------------------------------------------------------------------------------!
11091 SUBROUTINE radiation_data_output_mask( av, variable, found, local_pf, mid )
11092 
11093    USE control_parameters
11094       
11095    USE indices
11096   
11097    USE kinds
11098   
11099
11100    IMPLICIT NONE
11101
11102    CHARACTER (LEN=*) ::  variable   !<
11103
11104    CHARACTER(LEN=5) ::  grid        !< flag to distinquish between staggered grids
11105
11106    INTEGER(iwp) ::  av              !<
11107    INTEGER(iwp) ::  i               !<
11108    INTEGER(iwp) ::  j               !<
11109    INTEGER(iwp) ::  k               !<
11110    INTEGER(iwp) ::  mid             !< masked output running index
11111    INTEGER(iwp) ::  topo_top_ind    !< k index of highest horizontal surface
11112
11113    LOGICAL ::  found                !< true if output array was found
11114    LOGICAL ::  resorted             !< true if array is resorted
11115
11116
11117    REAL(wp),                                                                  &
11118       DIMENSION(mask_size_l(mid,1),mask_size_l(mid,2),mask_size_l(mid,3)) ::  &
11119          local_pf   !<
11120
11121    REAL(wp), DIMENSION(:,:,:), POINTER ::  to_be_resorted  !< points to array which needs to be resorted for output
11122
11123
11124    found    = .TRUE.
11125    grid     = 's'
11126    resorted = .FALSE.
11127
11128    SELECT CASE ( TRIM( variable ) )
11129
11130
11131       CASE ( 'rad_lw_in' )
11132          IF ( av == 0 )  THEN
11133             to_be_resorted => rad_lw_in
11134          ELSE
11135             to_be_resorted => rad_lw_in_av
11136          ENDIF
11137
11138       CASE ( 'rad_lw_out' )
11139          IF ( av == 0 )  THEN
11140             to_be_resorted => rad_lw_out
11141          ELSE
11142             to_be_resorted => rad_lw_out_av
11143          ENDIF
11144
11145       CASE ( 'rad_lw_cs_hr' )
11146          IF ( av == 0 )  THEN
11147             to_be_resorted => rad_lw_cs_hr
11148          ELSE
11149             to_be_resorted => rad_lw_cs_hr_av
11150          ENDIF
11151
11152       CASE ( 'rad_lw_hr' )
11153          IF ( av == 0 )  THEN
11154             to_be_resorted => rad_lw_hr
11155          ELSE
11156             to_be_resorted => rad_lw_hr_av
11157          ENDIF
11158
11159       CASE ( 'rad_sw_in' )
11160          IF ( av == 0 )  THEN
11161             to_be_resorted => rad_sw_in
11162          ELSE
11163             to_be_resorted => rad_sw_in_av
11164          ENDIF
11165
11166       CASE ( 'rad_sw_out' )
11167          IF ( av == 0 )  THEN
11168             to_be_resorted => rad_sw_out
11169          ELSE
11170             to_be_resorted => rad_sw_out_av
11171          ENDIF
11172
11173       CASE ( 'rad_sw_cs_hr' )
11174          IF ( av == 0 )  THEN
11175             to_be_resorted => rad_sw_cs_hr
11176          ELSE
11177             to_be_resorted => rad_sw_cs_hr_av
11178          ENDIF
11179
11180       CASE ( 'rad_sw_hr' )
11181          IF ( av == 0 )  THEN
11182             to_be_resorted => rad_sw_hr
11183          ELSE
11184             to_be_resorted => rad_sw_hr_av
11185          ENDIF
11186
11187       CASE DEFAULT
11188          found = .FALSE.
11189
11190    END SELECT
11191
11192!
11193!-- Resort the array to be output, if not done above
11194    IF ( found  .AND.  .NOT. resorted )  THEN
11195       IF ( .NOT. mask_surface(mid) )  THEN
11196!
11197!--       Default masked output
11198          DO  i = 1, mask_size_l(mid,1)
11199             DO  j = 1, mask_size_l(mid,2)
11200                DO  k = 1, mask_size_l(mid,3)
11201                   local_pf(i,j,k) =  to_be_resorted(mask_k(mid,k), &
11202                                      mask_j(mid,j),mask_i(mid,i))
11203                ENDDO
11204             ENDDO
11205          ENDDO
11206
11207       ELSE
11208!
11209!--       Terrain-following masked output
11210          DO  i = 1, mask_size_l(mid,1)
11211             DO  j = 1, mask_size_l(mid,2)
11212!
11213!--             Get k index of highest horizontal surface
11214                topo_top_ind = get_topography_top_index_ji( mask_j(mid,j), &
11215                                                            mask_i(mid,i), &
11216                                                            grid )
11217!
11218!--             Save output array
11219                DO  k = 1, mask_size_l(mid,3)
11220                   local_pf(i,j,k) = to_be_resorted(                       &
11221                                          MIN( topo_top_ind+mask_k(mid,k), &
11222                                               nzt+1 ),                    &
11223                                          mask_j(mid,j),                   &
11224                                          mask_i(mid,i)                     )
11225                ENDDO
11226             ENDDO
11227          ENDDO
11228
11229       ENDIF
11230    ENDIF
11231
11232
11233
11234 END SUBROUTINE radiation_data_output_mask
11235
11236
11237!------------------------------------------------------------------------------!
11238! Description:
11239! ------------
11240!> Subroutine writes local (subdomain) restart data
11241!------------------------------------------------------------------------------!
11242 SUBROUTINE radiation_wrd_local
11243
11244
11245    IMPLICIT NONE
11246
11247
11248    IF ( ALLOCATED( rad_net_av ) )  THEN
11249       CALL wrd_write_string( 'rad_net_av' )
11250       WRITE ( 14 )  rad_net_av
11251    ENDIF
11252   
11253    IF ( ALLOCATED( rad_lw_in_xy_av ) )  THEN
11254       CALL wrd_write_string( 'rad_lw_in_xy_av' )
11255       WRITE ( 14 )  rad_lw_in_xy_av
11256    ENDIF
11257   
11258    IF ( ALLOCATED( rad_lw_out_xy_av ) )  THEN
11259       CALL wrd_write_string( 'rad_lw_out_xy_av' )
11260       WRITE ( 14 )  rad_lw_out_xy_av
11261    ENDIF
11262   
11263    IF ( ALLOCATED( rad_sw_in_xy_av ) )  THEN
11264       CALL wrd_write_string( 'rad_sw_in_xy_av' )
11265       WRITE ( 14 )  rad_sw_in_xy_av
11266    ENDIF
11267   
11268    IF ( ALLOCATED( rad_sw_out_xy_av ) )  THEN
11269       CALL wrd_write_string( 'rad_sw_out_xy_av' )
11270       WRITE ( 14 )  rad_sw_out_xy_av
11271    ENDIF
11272
11273    IF ( ALLOCATED( rad_lw_in ) )  THEN
11274       CALL wrd_write_string( 'rad_lw_in' )
11275       WRITE ( 14 )  rad_lw_in
11276    ENDIF
11277
11278    IF ( ALLOCATED( rad_lw_in_av ) )  THEN
11279       CALL wrd_write_string( 'rad_lw_in_av' )
11280       WRITE ( 14 )  rad_lw_in_av
11281    ENDIF
11282
11283    IF ( ALLOCATED( rad_lw_out ) )  THEN
11284       CALL wrd_write_string( 'rad_lw_out' )
11285       WRITE ( 14 )  rad_lw_out
11286    ENDIF
11287
11288    IF ( ALLOCATED( rad_lw_out_av) )  THEN
11289       CALL wrd_write_string( 'rad_lw_out_av' )
11290       WRITE ( 14 )  rad_lw_out_av
11291    ENDIF
11292
11293    IF ( ALLOCATED( rad_lw_cs_hr) )  THEN
11294       CALL wrd_write_string( 'rad_lw_cs_hr' )
11295       WRITE ( 14 )  rad_lw_cs_hr
11296    ENDIF
11297
11298    IF ( ALLOCATED( rad_lw_cs_hr_av) )  THEN
11299       CALL wrd_write_string( 'rad_lw_cs_hr_av' )
11300       WRITE ( 14 )  rad_lw_cs_hr_av
11301    ENDIF
11302
11303    IF ( ALLOCATED( rad_lw_hr) )  THEN
11304       CALL wrd_write_string( 'rad_lw_hr' )
11305       WRITE ( 14 )  rad_lw_hr
11306    ENDIF
11307
11308    IF ( ALLOCATED( rad_lw_hr_av) )  THEN
11309       CALL wrd_write_string( 'rad_lw_hr_av' )
11310       WRITE ( 14 )  rad_lw_hr_av
11311    ENDIF
11312
11313    IF ( ALLOCATED( rad_sw_in) )  THEN
11314       CALL wrd_write_string( 'rad_sw_in' )
11315       WRITE ( 14 )  rad_sw_in
11316    ENDIF
11317
11318    IF ( ALLOCATED( rad_sw_in_av) )  THEN
11319       CALL wrd_write_string( 'rad_sw_in_av' )
11320       WRITE ( 14 )  rad_sw_in_av
11321    ENDIF
11322
11323    IF ( ALLOCATED( rad_sw_out) )  THEN
11324       CALL wrd_write_string( 'rad_sw_out' )
11325       WRITE ( 14 )  rad_sw_out
11326    ENDIF
11327
11328    IF ( ALLOCATED( rad_sw_out_av) )  THEN
11329       CALL wrd_write_string( 'rad_sw_out_av' )
11330       WRITE ( 14 )  rad_sw_out_av
11331    ENDIF
11332
11333    IF ( ALLOCATED( rad_sw_cs_hr) )  THEN
11334       CALL wrd_write_string( 'rad_sw_cs_hr' )
11335       WRITE ( 14 )  rad_sw_cs_hr
11336    ENDIF
11337
11338    IF ( ALLOCATED( rad_sw_cs_hr_av) )  THEN
11339       CALL wrd_write_string( 'rad_sw_cs_hr_av' )
11340       WRITE ( 14 )  rad_sw_cs_hr_av
11341    ENDIF
11342
11343    IF ( ALLOCATED( rad_sw_hr) )  THEN
11344       CALL wrd_write_string( 'rad_sw_hr' )
11345       WRITE ( 14 )  rad_sw_hr
11346    ENDIF
11347
11348    IF ( ALLOCATED( rad_sw_hr_av) )  THEN
11349       CALL wrd_write_string( 'rad_sw_hr_av' )
11350       WRITE ( 14 )  rad_sw_hr_av
11351    ENDIF
11352
11353
11354 END SUBROUTINE radiation_wrd_local
11355
11356!------------------------------------------------------------------------------!
11357! Description:
11358! ------------
11359!> Subroutine reads local (subdomain) restart data
11360!------------------------------------------------------------------------------!
11361 SUBROUTINE radiation_rrd_local( k, nxlf, nxlc, nxl_on_file, nxrf, nxrc,       &
11362                                nxr_on_file, nynf, nync, nyn_on_file, nysf,    &
11363                                nysc, nys_on_file, tmp_2d, tmp_3d, found )
11364 
11365
11366    USE control_parameters
11367       
11368    USE indices
11369   
11370    USE kinds
11371   
11372    USE pegrid
11373
11374
11375    IMPLICIT NONE
11376
11377    INTEGER(iwp) ::  k               !<
11378    INTEGER(iwp) ::  nxlc            !<
11379    INTEGER(iwp) ::  nxlf            !<
11380    INTEGER(iwp) ::  nxl_on_file     !<
11381    INTEGER(iwp) ::  nxrc            !<
11382    INTEGER(iwp) ::  nxrf            !<
11383    INTEGER(iwp) ::  nxr_on_file     !<
11384    INTEGER(iwp) ::  nync            !<
11385    INTEGER(iwp) ::  nynf            !<
11386    INTEGER(iwp) ::  nyn_on_file     !<
11387    INTEGER(iwp) ::  nysc            !<
11388    INTEGER(iwp) ::  nysf            !<
11389    INTEGER(iwp) ::  nys_on_file     !<
11390
11391    LOGICAL, INTENT(OUT)  :: found
11392
11393    REAL(wp), DIMENSION(nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_2d   !<
11394
11395    REAL(wp), DIMENSION(nzb:nzt+1,nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_3d   !<
11396
11397    REAL(wp), DIMENSION(0:0,nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_3d2   !<
11398
11399
11400    found = .TRUE.
11401
11402
11403    SELECT CASE ( restart_string(1:length) )
11404
11405       CASE ( 'rad_net_av' )
11406          IF ( .NOT. ALLOCATED( rad_net_av ) )  THEN
11407             ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
11408          ENDIF 
11409          IF ( k == 1 )  READ ( 13 )  tmp_2d
11410          rad_net_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =           &
11411                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11412                       
11413       CASE ( 'rad_lw_in_xy_av' )
11414          IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) )  THEN
11415             ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
11416          ENDIF 
11417          IF ( k == 1 )  READ ( 13 )  tmp_2d
11418          rad_lw_in_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =      &
11419                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11420                       
11421       CASE ( 'rad_lw_out_xy_av' )
11422          IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) )  THEN
11423             ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
11424          ENDIF 
11425          IF ( k == 1 )  READ ( 13 )  tmp_2d
11426          rad_lw_out_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =     &
11427                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11428                       
11429       CASE ( 'rad_sw_in_xy_av' )
11430          IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) )  THEN
11431             ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
11432          ENDIF 
11433          IF ( k == 1 )  READ ( 13 )  tmp_2d
11434          rad_sw_in_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =      &
11435                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11436                       
11437       CASE ( 'rad_sw_out_xy_av' )
11438          IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) )  THEN
11439             ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
11440          ENDIF 
11441          IF ( k == 1 )  READ ( 13 )  tmp_2d
11442          rad_sw_out_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =     &
11443                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11444                       
11445       CASE ( 'rad_lw_in' )
11446          IF ( .NOT. ALLOCATED( rad_lw_in ) )  THEN
11447             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11448                  radiation_scheme == 'constant')  THEN
11449                ALLOCATE( rad_lw_in(0:0,nysg:nyng,nxlg:nxrg) )
11450             ELSE
11451                ALLOCATE( rad_lw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11452             ENDIF
11453          ENDIF 
11454          IF ( k == 1 )  THEN
11455             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11456                  radiation_scheme == 'constant')  THEN
11457                READ ( 13 )  tmp_3d2
11458                rad_lw_in(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =   &
11459                   tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11460             ELSE
11461                READ ( 13 )  tmp_3d
11462                rad_lw_in(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11463                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11464             ENDIF
11465          ENDIF
11466
11467       CASE ( 'rad_lw_in_av' )
11468          IF ( .NOT. ALLOCATED( rad_lw_in_av ) )  THEN
11469             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11470                  radiation_scheme == 'constant')  THEN
11471                ALLOCATE( rad_lw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
11472             ELSE
11473                ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11474             ENDIF
11475          ENDIF 
11476          IF ( k == 1 )  THEN
11477             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11478                  radiation_scheme == 'constant')  THEN
11479                READ ( 13 )  tmp_3d2
11480                rad_lw_in_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =&
11481                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11482             ELSE
11483                READ ( 13 )  tmp_3d
11484                rad_lw_in_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11485                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11486             ENDIF
11487          ENDIF
11488
11489       CASE ( 'rad_lw_out' )
11490          IF ( .NOT. ALLOCATED( rad_lw_out ) )  THEN
11491             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11492                  radiation_scheme == 'constant')  THEN
11493                ALLOCATE( rad_lw_out(0:0,nysg:nyng,nxlg:nxrg) )
11494             ELSE
11495                ALLOCATE( rad_lw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11496             ENDIF
11497          ENDIF 
11498          IF ( k == 1 )  THEN
11499             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11500                  radiation_scheme == 'constant')  THEN
11501                READ ( 13 )  tmp_3d2
11502                rad_lw_out(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11503                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11504             ELSE
11505                READ ( 13 )  tmp_3d
11506                rad_lw_out(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =    &
11507                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11508             ENDIF
11509          ENDIF
11510
11511       CASE ( 'rad_lw_out_av' )
11512          IF ( .NOT. ALLOCATED( rad_lw_out_av ) )  THEN
11513             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11514                  radiation_scheme == 'constant')  THEN
11515                ALLOCATE( rad_lw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
11516             ELSE
11517                ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11518             ENDIF
11519          ENDIF 
11520          IF ( k == 1 )  THEN
11521             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11522                  radiation_scheme == 'constant')  THEN
11523                READ ( 13 )  tmp_3d2
11524                rad_lw_out_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) &
11525                   = tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11526             ELSE
11527                READ ( 13 )  tmp_3d
11528                rad_lw_out_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &
11529                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11530             ENDIF
11531          ENDIF
11532
11533       CASE ( 'rad_lw_cs_hr' )
11534          IF ( .NOT. ALLOCATED( rad_lw_cs_hr ) )  THEN
11535             ALLOCATE( rad_lw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11536          ENDIF
11537          IF ( k == 1 )  READ ( 13 )  tmp_3d
11538          rad_lw_cs_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11539                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11540
11541       CASE ( 'rad_lw_cs_hr_av' )
11542          IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) )  THEN
11543             ALLOCATE( rad_lw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11544          ENDIF
11545          IF ( k == 1 )  READ ( 13 )  tmp_3d
11546          rad_lw_cs_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11547                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11548
11549       CASE ( 'rad_lw_hr' )
11550          IF ( .NOT. ALLOCATED( rad_lw_hr ) )  THEN
11551             ALLOCATE( rad_lw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11552          ENDIF
11553          IF ( k == 1 )  READ ( 13 )  tmp_3d
11554          rad_lw_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =           &
11555                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11556
11557       CASE ( 'rad_lw_hr_av' )
11558          IF ( .NOT. ALLOCATED( rad_lw_hr_av ) )  THEN
11559             ALLOCATE( rad_lw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11560          ENDIF
11561          IF ( k == 1 )  READ ( 13 )  tmp_3d
11562          rad_lw_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11563                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11564
11565       CASE ( 'rad_sw_in' )
11566          IF ( .NOT. ALLOCATED( rad_sw_in ) )  THEN
11567             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11568                  radiation_scheme == 'constant')  THEN
11569                ALLOCATE( rad_sw_in(0:0,nysg:nyng,nxlg:nxrg) )
11570             ELSE
11571                ALLOCATE( rad_sw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11572             ENDIF
11573          ENDIF 
11574          IF ( k == 1 )  THEN
11575             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11576                  radiation_scheme == 'constant')  THEN
11577                READ ( 13 )  tmp_3d2
11578                rad_sw_in(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =   &
11579                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11580             ELSE
11581                READ ( 13 )  tmp_3d
11582                rad_sw_in(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11583                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11584             ENDIF
11585          ENDIF
11586
11587       CASE ( 'rad_sw_in_av' )
11588          IF ( .NOT. ALLOCATED( rad_sw_in_av ) )  THEN
11589             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11590                  radiation_scheme == 'constant')  THEN
11591                ALLOCATE( rad_sw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
11592             ELSE
11593                ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11594             ENDIF
11595          ENDIF 
11596          IF ( k == 1 )  THEN
11597             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11598                  radiation_scheme == 'constant')  THEN
11599                READ ( 13 )  tmp_3d2
11600                rad_sw_in_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =&
11601                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11602             ELSE
11603                READ ( 13 )  tmp_3d
11604                rad_sw_in_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11605                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11606             ENDIF
11607          ENDIF
11608
11609       CASE ( 'rad_sw_out' )
11610          IF ( .NOT. ALLOCATED( rad_sw_out ) )  THEN
11611             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11612                  radiation_scheme == 'constant')  THEN
11613                ALLOCATE( rad_sw_out(0:0,nysg:nyng,nxlg:nxrg) )
11614             ELSE
11615                ALLOCATE( rad_sw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11616             ENDIF
11617          ENDIF 
11618          IF ( k == 1 )  THEN
11619             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11620                  radiation_scheme == 'constant')  THEN
11621                READ ( 13 )  tmp_3d2
11622                rad_sw_out(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11623                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11624             ELSE
11625                READ ( 13 )  tmp_3d
11626                rad_sw_out(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =    &
11627                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11628             ENDIF
11629          ENDIF
11630
11631       CASE ( 'rad_sw_out_av' )
11632          IF ( .NOT. ALLOCATED( rad_sw_out_av ) )  THEN
11633             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11634                  radiation_scheme == 'constant')  THEN
11635                ALLOCATE( rad_sw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
11636             ELSE
11637                ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11638             ENDIF
11639          ENDIF 
11640          IF ( k == 1 )  THEN
11641             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11642                  radiation_scheme == 'constant')  THEN
11643                READ ( 13 )  tmp_3d2
11644                rad_sw_out_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) &
11645                   = tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11646             ELSE
11647                READ ( 13 )  tmp_3d
11648                rad_sw_out_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &
11649                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11650             ENDIF
11651          ENDIF
11652
11653       CASE ( 'rad_sw_cs_hr' )
11654          IF ( .NOT. ALLOCATED( rad_sw_cs_hr ) )  THEN
11655             ALLOCATE( rad_sw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11656          ENDIF
11657          IF ( k == 1 )  READ ( 13 )  tmp_3d
11658          rad_sw_cs_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11659                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11660
11661       CASE ( 'rad_sw_cs_hr_av' )
11662          IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) )  THEN
11663             ALLOCATE( rad_sw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11664          ENDIF
11665          IF ( k == 1 )  READ ( 13 )  tmp_3d
11666          rad_sw_cs_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11667                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11668
11669       CASE ( 'rad_sw_hr' )
11670          IF ( .NOT. ALLOCATED( rad_sw_hr ) )  THEN
11671             ALLOCATE( rad_sw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11672          ENDIF
11673          IF ( k == 1 )  READ ( 13 )  tmp_3d
11674          rad_sw_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =           &
11675                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11676
11677       CASE ( 'rad_sw_hr_av' )
11678          IF ( .NOT. ALLOCATED( rad_sw_hr_av ) )  THEN
11679             ALLOCATE( rad_sw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11680          ENDIF
11681          IF ( k == 1 )  READ ( 13 )  tmp_3d
11682          rad_lw_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11683                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11684
11685       CASE DEFAULT
11686
11687          found = .FALSE.
11688
11689    END SELECT
11690
11691 END SUBROUTINE radiation_rrd_local
11692
11693
11694 END MODULE radiation_model_mod
Note: See TracBrowser for help on using the repository browser.