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

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

Correct level 2 initialization of spectral albedos in rrtmg branch, long- and shortwave albedos were mixed-up; Change order of albedo_pars so that it is now consistent with the defined order of albedo_pars in PIDS

  • 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: 515.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 4089 2019-07-11 14:30:27Z suehring $
30! - Correct level 2 initialization of spectral albedos in rrtmg branch, long- and
31!   shortwave albedos were mixed-up.
32! - Change order of albedo_pars so that it is now consistent with the defined
33!   order of albedo_pars in PIDS
34!
35! 4069 2019-07-01 14:05:51Z Giersch
36! Masked output running index mid has been introduced as a local variable to
37! avoid runtime error (Loop variable has been modified) in time_integration
38!
39! 4067 2019-07-01 13:29:25Z suehring
40! Bugfix, pass dummy string to MPI_INFO_SET (J. Resler)
41!
42! 4039 2019-06-18 10:32:41Z suehring
43! Bugfix for masked data output
44!
45! 4008 2019-05-30 09:50:11Z moh.hefny
46! Bugfix in check variable when a variable's string is less than 3
47! characters is processed. All variables now are checked if they
48! belong to radiation
49!
50! 3992 2019-05-22 16:49:38Z suehring
51! Bugfix in rrtmg radiation branch in a nested run when the lowest prognistic
52! grid points in a child domain are all inside topography
53!
54! 3987 2019-05-22 09:52:13Z kanani
55! Introduce alternative switch for debug output during timestepping
56!
57! 3943 2019-05-02 09:50:41Z maronga
58! Missing blank characteer added.
59!
60! 3900 2019-04-16 15:17:43Z suehring
61! Fixed initialization problem
62!
63! 3885 2019-04-11 11:29:34Z kanani
64! Changes related to global restructuring of location messages and introduction
65! of additional debug messages
66!
67! 3881 2019-04-10 09:31:22Z suehring
68! Output of albedo and emissivity moved from USM, bugfixes in initialization
69! of albedo
70!
71! 3861 2019-04-04 06:27:41Z maronga
72! Bugfix: factor of 4.0 required instead of 3.0 in calculation of rad_lw_out_change_0
73!
74! 3859 2019-04-03 20:30:31Z maronga
75! Added some descriptions
76!
77! 3847 2019-04-01 14:51:44Z suehring
78! Implement check for dt_radiation (must be > 0)
79!
80! 3846 2019-04-01 13:55:30Z suehring
81! unused variable removed
82!
83! 3814 2019-03-26 08:40:31Z pavelkrc
84! Change zenith(0:0) and others to scalar.
85! Code review.
86! Rename exported nzu, nzp and related variables due to name conflict
87!
88! 3771 2019-02-28 12:19:33Z raasch
89! rrtmg preprocessor for directives moved/added, save attribute added to temporary
90! pointers to avoid compiler warnings about outlived pointer targets,
91! statement added to avoid compiler warning about unused variable
92!
93! 3769 2019-02-28 10:16:49Z moh.hefny
94! removed unused variables and subroutine radiation_radflux_gridbox
95!
96! 3767 2019-02-27 08:18:02Z raasch
97! unused variable for file index removed from rrd-subroutines parameter list
98!
99! 3760 2019-02-21 18:47:35Z moh.hefny
100! Bugfix: initialized simulated_time before calculating solar position
101! to enable restart option with reading in SVF from file(s).
102!
103! 3754 2019-02-19 17:02:26Z kanani
104! (resler, pavelkrc)
105! Bugfixes: add further required MRT factors to read/write_svf,
106! fix for aggregating view factors to eliminate local noise in reflected
107! irradiance at mutually close surfaces (corners, presence of trees) in the
108! angular discretization scheme.
109!
110! 3752 2019-02-19 09:37:22Z resler
111! added read/write number of MRT factors to the respective routines
112!
113! 3705 2019-01-29 19:56:39Z suehring
114! Make variables that are sampled in virtual measurement module public
115!
116! 3704 2019-01-29 19:51:41Z suehring
117! Some interface calls moved to module_interface + cleanup
118!
119! 3667 2019-01-10 14:26:24Z schwenkel
120! Modified check for rrtmg input files
121!
122! 3655 2019-01-07 16:51:22Z knoop
123! nopointer option removed
124!
125! 3633 2018-12-17 16:17:57Z schwenkel
126! Include check for rrtmg files
127!
128! 3630 2018-12-17 11:04:17Z knoop
129! - fix initialization of date and time after calling zenith
130! - fix a bug in radiation_solar_pos
131!
132! 3616 2018-12-10 09:44:36Z Salim
133! fix manipulation of time variables in radiation_presimulate_solar_pos
134!
135! 3608 2018-12-07 12:59:57Z suehring $
136! Bugfix radiation output
137!
138! 3607 2018-12-07 11:56:58Z suehring
139! Output of radiation-related quantities migrated to radiation_model_mod.
140!
141! 3589 2018-11-30 15:09:51Z suehring
142! Remove erroneous UTF encoding
143!
144! 3572 2018-11-28 11:40:28Z suehring
145! Add filling the short- and longwave radiation flux arrays (e.g. diffuse,
146! direct, reflected, resedual) for all surfaces. This is required to surface
147! outputs in suface_output_mod. (M. Salim)
148!
149! 3571 2018-11-28 09:24:03Z moh.hefny
150! Add an epsilon value to compare values in if statement to fix possible
151! precsion related errors in raytrace routines.
152!
153! 3524 2018-11-14 13:36:44Z raasch
154! missing cpp-directives added
155!
156! 3495 2018-11-06 15:22:17Z kanani
157! Resort control_parameters ONLY list,
158! From branch radiation@3491 moh.hefny:
159! bugfix in calculating the apparent solar positions by updating
160! the simulated time so that the actual time is correct.
161!
162! 3464 2018-10-30 18:08:55Z kanani
163! From branch resler@3462, pavelkrc:
164! add MRT shaping function for human
165!
166! 3449 2018-10-29 19:36:56Z suehring
167! New RTM version 3.0: (Pavel Krc, Jaroslav Resler, ICS, Prague)
168!   - Interaction of plant canopy with LW radiation
169!   - Transpiration from resolved plant canopy dependent on radiation
170!     called from RTM
171!
172!
173! 3435 2018-10-26 18:25:44Z gronemeier
174! - workaround: return unit=illegal in check_data_output for certain variables
175!   when check called from init_masks
176! - Use pointer in masked output to reduce code redundancies
177! - Add terrain-following masked output
178!
179! 3424 2018-10-25 07:29:10Z gronemeier
180! bugfix: add rad_lw_in, rad_lw_out, rad_sw_out to radiation_check_data_output
181!
182! 3378 2018-10-19 12:34:59Z kanani
183! merge from radiation branch (r3362) into trunk
184! (moh.hefny):
185! - removed read/write_svf_on_init and read_dist_max_svf (not used anymore)
186! - bugfix nzut > nzpt in calculating maxboxes
187!
188! 3372 2018-10-18 14:03:19Z raasch
189! bugfix: kind type of 2nd argument of mpi_win_allocate changed, misplaced
190!         __parallel directive
191!
192! 3351 2018-10-15 18:40:42Z suehring
193! Do not overwrite values of spectral and broadband albedo during initialization
194! if they are already initialized in the urban-surface model via ASCII input.
195!
196! 3337 2018-10-12 15:17:09Z kanani
197! - New RTM version 2.9: (Pavel Krc, Jaroslav Resler, ICS, Prague)
198!   added calculation of the MRT inside the RTM module
199!   MRT fluxes are consequently used in the new biometeorology module
200!   for calculation of biological indices (MRT, PET)
201!   Fixes of v. 2.5 and SVN trunk:
202!    - proper initialization of rad_net_l
203!    - make arrays nsurfs and surfstart TARGET to prevent some MPI problems
204!    - initialization of arrays used in MPI one-sided operation as 1-D arrays
205!      to prevent problems with some MPI/compiler combinations
206!    - fix indexing of target displacement in subroutine request_itarget to
207!      consider nzub
208!    - fix LAD dimmension range in PCB calculation
209!    - check ierr in all MPI calls
210!    - use proper per-gridbox sky and diffuse irradiance
211!    - fix shading for reflected irradiance
212!    - clear away the residuals of "atmospheric surfaces" implementation
213!    - fix rounding bug in raytrace_2d introduced in SVN trunk
214! - New RTM version 2.5: (Pavel Krc, Jaroslav Resler, ICS, Prague)
215!   can use angular discretization for all SVF
216!   (i.e. reflected and emitted radiation in addition to direct and diffuse),
217!   allowing for much better scaling wih high resoltion and/or complex terrain
218! - Unite array grow factors
219! - Fix slightly shifted terrain height in raytrace_2d
220! - Use more efficient MPI_Win_allocate for reverse gridsurf index
221! - Fix random MPI RMA bugs on Intel compilers
222! - Fix approx. double plant canopy sink values for reflected radiation
223! - Fix mostly missing plant canopy sinks for direct radiation
224! - Fix discretization errors for plant canopy sink in diffuse radiation
225! - Fix rounding errors in raytrace_2d
226!
227! 3274 2018-09-24 15:42:55Z knoop
228! Modularization of all bulk cloud physics code components
229!
230! 3272 2018-09-24 10:16:32Z suehring
231! - split direct and diffusion shortwave radiation using RRTMG rather than using
232!   calc_diffusion_radiation, in case of RRTMG
233! - removed the namelist variable split_diffusion_radiation. Now splitting depends
234!   on the choise of radiation radiation scheme
235! - removed calculating the rdiation flux for surfaces at the radiation scheme
236!   in case of using RTM since it will be calculated anyway in the radiation
237!   interaction routine.
238! - set SW radiation flux for surfaces to zero at night in case of no RTM is used
239! - precalculate the unit vector yxdir of ray direction to avoid the temporarly
240!   array allocation during the subroutine call
241! - fixed a bug in calculating the max number of boxes ray can cross in the domain
242!
243! 3264 2018-09-20 13:54:11Z moh.hefny
244! Bugfix in raytrace_2d calls
245!
246! 3248 2018-09-14 09:42:06Z sward
247! Minor formating changes
248!
249! 3246 2018-09-13 15:14:50Z sward
250! Added error handling for input namelist via parin_fail_message
251!
252! 3241 2018-09-12 15:02:00Z raasch
253! unused variables removed or commented
254!
255! 3233 2018-09-07 13:21:24Z schwenkel
256! Adapted for the use of cloud_droplets
257!
258! 3230 2018-09-05 09:29:05Z schwenkel
259! Bugfix in radiation_constant_surf: changed (10.0 - emissivity_urb) to
260! (1.0 - emissivity_urb)
261!
262! 3226 2018-08-31 12:27:09Z suehring
263! Bugfixes in calculation of sky-view factors and canopy-sink factors.
264!
265! 3186 2018-07-30 17:07:14Z suehring
266! Remove print statement
267!
268! 3180 2018-07-27 11:00:56Z suehring
269! Revise concept for calculation of effective radiative temperature and mapping
270! of radiative heating
271!
272! 3175 2018-07-26 14:07:38Z suehring
273! Bugfix for commit 3172
274!
275! 3173 2018-07-26 12:55:23Z suehring
276! Revise output of surface radiation quantities in case of overhanging
277! structures
278!
279! 3172 2018-07-26 12:06:06Z suehring
280! Bugfixes:
281!  - temporal work-around for calculation of effective radiative surface
282!    temperature
283!  - prevent positive solar radiation during nighttime
284!
285! 3170 2018-07-25 15:19:37Z suehring
286! Bugfix, map signle-column radiation forcing profiles on top of any topography
287!
288! 3156 2018-07-19 16:30:54Z knoop
289! Bugfix: replaced usage of the pt array with the surf%pt_surface array
290!
291! 3137 2018-07-17 06:44:21Z maronga
292! String length for trace_names fixed
293!
294! 3127 2018-07-15 08:01:25Z maronga
295! A few pavement parameters updated.
296!
297! 3123 2018-07-12 16:21:53Z suehring
298! Correct working precision for INTEGER number
299!
300! 3122 2018-07-11 21:46:41Z maronga
301! Bugfix: maximum distance for raytracing was set to  -999 m by default,
302! effectively switching off all surface reflections when max_raytracing_dist
303! was not explicitly set in namelist
304!
305! 3117 2018-07-11 09:59:11Z maronga
306! Bugfix: water vapor was not transfered to RRTMG when bulk_cloud_model = .F.
307! Bugfix: changed the calculation of RRTMG boundary conditions (Mohamed Salim)
308! Bugfix: dry residual atmosphere is replaced by standard RRTMG atmosphere
309!
310! 3116 2018-07-10 14:31:58Z suehring
311! Output of long/shortwave radiation at surface
312!
313! 3107 2018-07-06 15:55:51Z suehring
314! Bugfix, missing index for dz
315!
316! 3066 2018-06-12 08:55:55Z Giersch
317! Error message revised
318!
319! 3065 2018-06-12 07:03:02Z Giersch
320! dz was replaced by dz(1), error message concerning vertical stretching was
321! added 
322!
323! 3049 2018-05-29 13:52:36Z Giersch
324! Error messages revised
325!
326! 3045 2018-05-28 07:55:41Z Giersch
327! Error message revised
328!
329! 3026 2018-05-22 10:30:53Z schwenkel
330! Changed the name specific humidity to mixing ratio, since we are computing
331! mixing ratios.
332!
333! 3016 2018-05-09 10:53:37Z Giersch
334! Revised structure of reading svf data according to PALM coding standard:
335! svf_code_field/len and fsvf removed, error messages PA0493 and PA0494 added,
336! allocation status of output arrays checked.
337!
338! 3014 2018-05-09 08:42:38Z maronga
339! Introduced plant canopy height similar to urban canopy height to limit
340! the memory requirement to allocate lad.
341! Deactivated automatic setting of minimum raytracing distance.
342!
343! 3004 2018-04-27 12:33:25Z Giersch
344! Further allocation checks implemented (averaged data will be assigned to fill
345! values if no allocation happened so far)
346!
347! 2995 2018-04-19 12:13:16Z Giersch
348! IF-statement in radiation_init removed so that the calculation of radiative
349! fluxes at model start is done in any case, bugfix in
350! radiation_presimulate_solar_pos (end_time is the sum of end_time and the
351! spinup_time specified in the p3d_file ), list of variables/fields that have
352! to be written out or read in case of restarts has been extended
353!
354! 2977 2018-04-17 10:27:57Z kanani
355! Implement changes from branch radiation (r2948-2971) with minor modifications,
356! plus some formatting.
357! (moh.hefny):
358! - replaced plant_canopy by npcbl to check tree existence to avoid weird
359!   allocation of related arrays (after domain decomposition some domains
360!   contains no trees although plant_canopy (global parameter) is still TRUE).
361! - added a namelist parameter to force RTM settings
362! - enabled the option to switch radiation reflections off
363! - renamed surf_reflections to surface_reflections
364! - removed average_radiation flag from the namelist (now it is implicitly set
365!   in init_3d_model according to RTM)
366! - edited read and write sky view factors and CSF routines to account for
367!   the sub-domains which may not contain any of them
368!
369! 2967 2018-04-13 11:22:08Z raasch
370! bugfix: missing parallel cpp-directives added
371!
372! 2964 2018-04-12 16:04:03Z Giersch
373! Error message PA0491 has been introduced which could be previously found in
374! check_open. The variable numprocs_previous_run is only known in case of
375! initializing_actions == read_restart_data
376!
377! 2963 2018-04-12 14:47:44Z suehring
378! - Introduce index for vegetation/wall, pavement/green-wall and water/window
379!   surfaces, for clearer access of surface fraction, albedo, emissivity, etc. .
380! - Minor bugfix in initialization of albedo for window surfaces
381!
382! 2944 2018-04-03 16:20:18Z suehring
383! Fixed bad commit
384!
385! 2943 2018-04-03 16:17:10Z suehring
386! No read of nsurfl from SVF file since it is calculated in
387! radiation_interaction_init,
388! allocation of arrays in radiation_read_svf only if not yet allocated,
389! update of 2920 revision comment.
390!
391! 2932 2018-03-26 09:39:22Z maronga
392! renamed radiation_par to radiation_parameters
393!
394! 2930 2018-03-23 16:30:46Z suehring
395! Remove default surfaces from radiation model, does not make much sense to
396! apply radiation model without energy-balance solvers; Further, add check for
397! this.
398!
399! 2920 2018-03-22 11:22:01Z kanani
400! - Bugfix: Initialize pcbl array (=-1)
401! RTM version 2.0 (Jaroslav Resler, Pavel Krc, Mohamed Salim):
402! - new major version of radiation interactions
403! - substantially enhanced performance and scalability
404! - processing of direct and diffuse solar radiation separated from reflected
405!   radiation, removed virtual surfaces
406! - new type of sky discretization by azimuth and elevation angles
407! - diffuse radiation processed cumulatively using sky view factor
408! - used precalculated apparent solar positions for direct irradiance
409! - added new 2D raytracing process for processing whole vertical column at once
410!   to increase memory efficiency and decrease number of MPI RMA operations
411! - enabled limiting the number of view factors between surfaces by the distance
412!   and value
413! - fixing issues induced by transferring radiation interactions from
414!   urban_surface_mod to radiation_mod
415! - bugfixes and other minor enhancements
416!
417! 2906 2018-03-19 08:56:40Z Giersch
418! NAMELIST paramter read/write_svf_on_init have been removed, functions
419! check_open and close_file are used now for opening/closing files related to
420! svf data, adjusted unit number and error numbers
421!
422! 2894 2018-03-15 09:17:58Z Giersch
423! Calculations of the index range of the subdomain on file which overlaps with
424! the current subdomain are already done in read_restart_data_mod
425! radiation_read_restart_data was renamed to radiation_rrd_local and
426! radiation_last_actions was renamed to radiation_wrd_local, variable named
427! found has been introduced for checking if restart data was found, reading
428! of restart strings has been moved completely to read_restart_data_mod,
429! radiation_rrd_local is already inside the overlap loop programmed in
430! read_restart_data_mod, the marker *** end rad *** is not necessary anymore,
431! strings and their respective lengths are written out and read now in case of
432! restart runs to get rid of prescribed character lengths (Giersch)
433!
434! 2809 2018-02-15 09:55:58Z suehring
435! Bugfix for gfortran: Replace the function C_SIZEOF with STORAGE_SIZE
436!
437! 2753 2018-01-16 14:16:49Z suehring
438! Tile approach for spectral albedo implemented.
439!
440! 2746 2018-01-15 12:06:04Z suehring
441! Move flag plant canopy to modules
442!
443! 2724 2018-01-05 12:12:38Z maronga
444! Set default of average_radiation to .FALSE.
445!
446! 2723 2018-01-05 09:27:03Z maronga
447! Bugfix in calculation of rad_lw_out (clear-sky). First grid level was used
448! instead of the surface value
449!
450! 2718 2018-01-02 08:49:38Z maronga
451! Corrected "Former revisions" section
452!
453! 2707 2017-12-18 18:34:46Z suehring
454! Changes from last commit documented
455!
456! 2706 2017-12-18 18:33:49Z suehring
457! Bugfix, in average radiation case calculate exner function before using it.
458!
459! 2701 2017-12-15 15:40:50Z suehring
460! Changes from last commit documented
461!
462! 2698 2017-12-14 18:46:24Z suehring
463! Bugfix in get_topography_top_index
464!
465! 2696 2017-12-14 17:12:51Z kanani
466! - Change in file header (GPL part)
467! - Improved reading/writing of SVF from/to file (BM)
468! - Bugfixes concerning RRTMG as well as average_radiation options (M. Salim)
469! - Revised initialization of surface albedo and some minor bugfixes (MS)
470! - Update net radiation after running radiation interaction routine (MS)
471! - Revisions from M Salim included
472! - Adjustment to topography and surface structure (MS)
473! - Initialization of albedo and surface emissivity via input file (MS)
474! - albedo_pars extended (MS)
475!
476! 2604 2017-11-06 13:29:00Z schwenkel
477! bugfix for calculation of effective radius using morrison microphysics
478!
479! 2601 2017-11-02 16:22:46Z scharf
480! added emissivity to namelist
481!
482! 2575 2017-10-24 09:57:58Z maronga
483! Bugfix: calculation of shortwave and longwave albedos for RRTMG swapped
484!
485! 2547 2017-10-16 12:41:56Z schwenkel
486! extended by cloud_droplets option, minor bugfix and correct calculation of
487! cloud droplet number concentration
488!
489! 2544 2017-10-13 18:09:32Z maronga
490! Moved date and time quantitis to separate module date_and_time_mod
491!
492! 2512 2017-10-04 08:26:59Z raasch
493! upper bounds of cross section and 3d output changed from nx+1,ny+1 to nx,ny
494! no output of ghost layer data
495!
496! 2504 2017-09-27 10:36:13Z maronga
497! Updates pavement types and albedo parameters
498!
499! 2328 2017-08-03 12:34:22Z maronga
500! Emissivity can now be set individually for each pixel.
501! Albedo type can be inferred from land surface model.
502! Added default albedo type for bare soil
503!
504! 2318 2017-07-20 17:27:44Z suehring
505! Get topography top index via Function call
506!
507! 2317 2017-07-20 17:27:19Z suehring
508! Improved syntax layout
509!
510! 2298 2017-06-29 09:28:18Z raasch
511! type of write_binary changed from CHARACTER to LOGICAL
512!
513! 2296 2017-06-28 07:53:56Z maronga
514! Added output of rad_sw_out for radiation_scheme = 'constant'
515!
516! 2270 2017-06-09 12:18:47Z maronga
517! Numbering changed (2 timeseries removed)
518!
519! 2249 2017-06-06 13:58:01Z sward
520! Allow for RRTMG runs without humidity/cloud physics
521!
522! 2248 2017-06-06 13:52:54Z sward
523! Error no changed
524!
525! 2233 2017-05-30 18:08:54Z suehring
526!
527! 2232 2017-05-30 17:47:52Z suehring
528! Adjustments to new topography concept
529! Bugfix in read restart
530!
531! 2200 2017-04-11 11:37:51Z suehring
532! Bugfix in call of exchange_horiz_2d and read restart data
533!
534! 2163 2017-03-01 13:23:15Z schwenkel
535! Bugfix in radiation_check_data_output
536!
537! 2157 2017-02-22 15:10:35Z suehring
538! Bugfix in read_restart data
539!
540! 2011 2016-09-19 17:29:57Z kanani
541! Removed CALL of auxiliary SUBROUTINE get_usm_info,
542! flag urban_surface is now defined in module control_parameters.
543!
544! 2007 2016-08-24 15:47:17Z kanani
545! Added calculation of solar directional vector for new urban surface
546! model,
547! accounted for urban_surface model in radiation_check_parameters,
548! correction of comments for zenith angle.
549!
550! 2000 2016-08-20 18:09:15Z knoop
551! Forced header and separation lines into 80 columns
552!
553! 1976 2016-07-27 13:28:04Z maronga
554! Output of 2D/3D/masked data is now directly done within this module. The
555! radiation schemes have been simplified for better usability so that
556! rad_lw_in, rad_lw_out, rad_sw_in, and rad_sw_out are available independent of
557! the radiation code used.
558!
559! 1856 2016-04-13 12:56:17Z maronga
560! Bugfix: allocation of rad_lw_out for radiation_scheme = 'clear-sky'
561!
562! 1853 2016-04-11 09:00:35Z maronga
563! Added routine for radiation_scheme = constant.
564
565! 1849 2016-04-08 11:33:18Z hoffmann
566! Adapted for modularization of microphysics
567!
568! 1826 2016-04-07 12:01:39Z maronga
569! Further modularization.
570!
571! 1788 2016-03-10 11:01:04Z maronga
572! Added new albedo class for pavements / roads.
573!
574! 1783 2016-03-06 18:36:17Z raasch
575! palm-netcdf-module removed in order to avoid a circular module dependency,
576! netcdf-variables moved to netcdf-module, new routine netcdf_handle_error_rad
577! added
578!
579! 1757 2016-02-22 15:49:32Z maronga
580! Added parameter unscheduled_radiation_calls. Bugfix: interpolation of sounding
581! profiles for pressure and temperature above the LES domain.
582!
583! 1709 2015-11-04 14:47:01Z maronga
584! Bugfix: set initial value for rrtm_lwuflx_dt to zero, small formatting
585! corrections
586!
587! 1701 2015-11-02 07:43:04Z maronga
588! Bugfixes: wrong index for output of timeseries, setting of nz_snd_end
589!
590! 1691 2015-10-26 16:17:44Z maronga
591! Added option for spin-up runs without radiation (skip_time_do_radiation). Bugfix
592! in calculation of pressure profiles. Bugfix in calculation of trace gas profiles.
593! Added output of radiative heating rates.
594!
595! 1682 2015-10-07 23:56:08Z knoop
596! Code annotations made doxygen readable
597!
598! 1606 2015-06-29 10:43:37Z maronga
599! Added preprocessor directive __netcdf to allow for compiling without netCDF.
600! Note, however, that RRTMG cannot be used without netCDF.
601!
602! 1590 2015-05-08 13:56:27Z maronga
603! Bugfix: definition of character strings requires same length for all elements
604!
605! 1587 2015-05-04 14:19:01Z maronga
606! Added albedo class for snow
607!
608! 1585 2015-04-30 07:05:52Z maronga
609! Added support for RRTMG
610!
611! 1571 2015-03-12 16:12:49Z maronga
612! Added missing KIND attribute. Removed upper-case variable names
613!
614! 1551 2015-03-03 14:18:16Z maronga
615! Added support for data output. Various variables have been renamed. Added
616! interface for different radiation schemes (currently: clear-sky, constant, and
617! RRTM (not yet implemented).
618!
619! 1496 2014-12-02 17:25:50Z maronga
620! Initial revision
621!
622!
623! Description:
624! ------------
625!> Radiation models and interfaces
626!> @todo Replace dz(1) appropriatly to account for grid stretching
627!> @todo move variable definitions used in radiation_init only to the subroutine
628!>       as they are no longer required after initialization.
629!> @todo Output of full column vertical profiles used in RRTMG
630!> @todo Output of other rrtm arrays (such as volume mixing ratios)
631!> @todo Check for mis-used NINT() calls in raytrace_2d
632!>       RESULT: Original was correct (carefully verified formula), the change
633!>               to INT broke raytracing      -- P. Krc
634!> @todo Optimize radiation_tendency routines
635!>
636!> @note Many variables have a leading dummy dimension (0:0) in order to
637!>       match the assume-size shape expected by the RRTMG model.
638!------------------------------------------------------------------------------!
639 MODULE radiation_model_mod
640 
641    USE arrays_3d,                                                             &
642        ONLY:  dzw, hyp, nc, pt, p, q, ql, u, v, w, zu, zw, exner, d_exner
643
644    USE basic_constants_and_equations_mod,                                     &
645        ONLY:  c_p, g, lv_d_cp, l_v, pi, r_d, rho_l, solar_constant, sigma_sb, &
646               barometric_formula
647
648    USE calc_mean_profile_mod,                                                 &
649        ONLY:  calc_mean_profile
650
651    USE control_parameters,                                                    &
652        ONLY:  cloud_droplets, coupling_char,                                  &
653               debug_output, debug_output_timestep, debug_string,              &
654               dz, dt_spinup, end_time,                                        &
655               humidity,                                                       &
656               initializing_actions, io_blocks, io_group,                      &
657               land_surface, large_scale_forcing,                              &
658               latitude, longitude, lsf_surf,                                  &
659               message_string, plant_canopy, pt_surface,                       &
660               rho_surface, simulated_time, spinup_time, surface_pressure,     &
661               read_svf, write_svf,                                            &
662               time_since_reference_point, urban_surface, varnamelength
663
664    USE cpulog,                                                                &
665        ONLY:  cpu_log, log_point, log_point_s
666
667    USE grid_variables,                                                        &
668         ONLY:  ddx, ddy, dx, dy 
669
670    USE date_and_time_mod,                                                     &
671        ONLY:  calc_date_and_time, d_hours_day, d_seconds_hour, d_seconds_year,&
672               day_of_year, d_seconds_year, day_of_month, day_of_year_init,    &
673               init_date_and_time, month_of_year, time_utc_init, time_utc
674
675    USE indices,                                                               &
676        ONLY:  nnx, nny, nx, nxl, nxlg, nxr, nxrg, ny, nyn, nyng, nys, nysg,   &
677               nzb, nzt
678
679    USE, INTRINSIC :: iso_c_binding
680
681    USE kinds
682
683    USE bulk_cloud_model_mod,                                                  &
684        ONLY:  bulk_cloud_model, microphysics_morrison, na_init, nc_const, sigma_gc
685
686#if defined ( __netcdf )
687    USE NETCDF
688#endif
689
690    USE netcdf_data_input_mod,                                                 &
691        ONLY:  albedo_type_f, albedo_pars_f, building_type_f, pavement_type_f, &
692               vegetation_type_f, water_type_f
693
694    USE plant_canopy_model_mod,                                                &
695        ONLY:  lad_s, pc_heating_rate, pc_transpiration_rate, pc_latent_rate,  &
696               plant_canopy_transpiration, pcm_calc_transpiration_rate
697
698    USE pegrid
699
700#if defined ( __rrtmg )
701    USE parrrsw,                                                               &
702        ONLY:  naerec, nbndsw
703
704    USE parrrtm,                                                               &
705        ONLY:  nbndlw
706
707    USE rrtmg_lw_init,                                                         &
708        ONLY:  rrtmg_lw_ini
709
710    USE rrtmg_sw_init,                                                         &
711        ONLY:  rrtmg_sw_ini
712
713    USE rrtmg_lw_rad,                                                          &
714        ONLY:  rrtmg_lw
715
716    USE rrtmg_sw_rad,                                                          &
717        ONLY:  rrtmg_sw
718#endif
719    USE statistics,                                                            &
720        ONLY:  hom
721
722    USE surface_mod,                                                           &
723        ONLY:  get_topography_top_index, get_topography_top_index_ji,          &
724               ind_pav_green, ind_veg_wall, ind_wat_win,                       &
725               surf_lsm_h, surf_lsm_v, surf_type, surf_usm_h, surf_usm_v,      &
726               vertical_surfaces_exist
727
728    IMPLICIT NONE
729
730    CHARACTER(10) :: radiation_scheme = 'clear-sky' ! 'constant', 'clear-sky', or 'rrtmg'
731
732!
733!-- Predefined Land surface classes (albedo_type) after Briegleb (1992)
734    CHARACTER(37), DIMENSION(0:33), PARAMETER :: albedo_type_name = (/      &
735                                   'user defined                         ', & !  0
736                                   'ocean                                ', & !  1
737                                   'mixed farming, tall grassland        ', & !  2
738                                   'tall/medium grassland                ', & !  3
739                                   'evergreen shrubland                  ', & !  4
740                                   'short grassland/meadow/shrubland     ', & !  5
741                                   'evergreen needleleaf forest          ', & !  6
742                                   'mixed deciduous evergreen forest     ', & !  7
743                                   'deciduous forest                     ', & !  8
744                                   'tropical evergreen broadleaved forest', & !  9
745                                   'medium/tall grassland/woodland       ', & ! 10
746                                   'desert, sandy                        ', & ! 11
747                                   'desert, rocky                        ', & ! 12
748                                   'tundra                               ', & ! 13
749                                   'land ice                             ', & ! 14
750                                   'sea ice                              ', & ! 15
751                                   'snow                                 ', & ! 16
752                                   'bare soil                            ', & ! 17
753                                   'asphalt/concrete mix                 ', & ! 18
754                                   'asphalt (asphalt concrete)           ', & ! 19
755                                   'concrete (Portland concrete)         ', & ! 20
756                                   'sett                                 ', & ! 21
757                                   'paving stones                        ', & ! 22
758                                   'cobblestone                          ', & ! 23
759                                   'metal                                ', & ! 24
760                                   'wood                                 ', & ! 25
761                                   'gravel                               ', & ! 26
762                                   'fine gravel                          ', & ! 27
763                                   'pebblestone                          ', & ! 28
764                                   'woodchips                            ', & ! 29
765                                   'tartan (sports)                      ', & ! 30
766                                   'artifical turf (sports)              ', & ! 31
767                                   'clay (sports)                        ', & ! 32
768                                   'building (dummy)                     '  & ! 33
769                                                         /)
770
771    INTEGER(iwp) :: albedo_type  = 9999999_iwp, &     !< Albedo surface type
772                    dots_rad     = 0_iwp              !< starting index for timeseries output
773
774    LOGICAL ::  unscheduled_radiation_calls = .TRUE., & !< flag parameter indicating whether additional calls of the radiation code are allowed
775                constant_albedo = .FALSE.,            & !< flag parameter indicating whether the albedo may change depending on zenith
776                force_radiation_call = .FALSE.,       & !< flag parameter for unscheduled radiation calls
777                lw_radiation = .TRUE.,                & !< flag parameter indicating whether longwave radiation shall be calculated
778                radiation = .FALSE.,                  & !< flag parameter indicating whether the radiation model is used
779                sun_up    = .TRUE.,                   & !< flag parameter indicating whether the sun is up or down
780                sw_radiation = .TRUE.,                & !< flag parameter indicating whether shortwave radiation shall be calculated
781                sun_direction = .FALSE.,              & !< flag parameter indicating whether solar direction shall be calculated
782                average_radiation = .FALSE.,          & !< flag to set the calculation of radiation averaging for the domain
783                radiation_interactions = .FALSE.,     & !< flag to activiate RTM (TRUE only if vertical urban/land surface and trees exist)
784                surface_reflections = .TRUE.,         & !< flag to switch the calculation of radiation interaction between surfaces.
785                                                        !< When it switched off, only the effect of buildings and trees shadow
786                                                        !< will be considered. However fewer SVFs are expected.
787                radiation_interactions_on = .TRUE.      !< namelist flag to force RTM activiation regardless to vertical urban/land surface and trees
788
789    REAL(wp) :: albedo = 9999999.9_wp,           & !< NAMELIST alpha
790                albedo_lw_dif = 9999999.9_wp,    & !< NAMELIST aldif
791                albedo_lw_dir = 9999999.9_wp,    & !< NAMELIST aldir
792                albedo_sw_dif = 9999999.9_wp,    & !< NAMELIST asdif
793                albedo_sw_dir = 9999999.9_wp,    & !< NAMELIST asdir
794                decl_1,                          & !< declination coef. 1
795                decl_2,                          & !< declination coef. 2
796                decl_3,                          & !< declination coef. 3
797                dt_radiation = 0.0_wp,           & !< radiation model timestep
798                emissivity = 9999999.9_wp,       & !< NAMELIST surface emissivity
799                lon = 0.0_wp,                    & !< longitude in radians
800                lat = 0.0_wp,                    & !< latitude in radians
801                net_radiation = 0.0_wp,          & !< net radiation at surface
802                skip_time_do_radiation = 0.0_wp, & !< Radiation model is not called before this time
803                sky_trans,                       & !< sky transmissivity
804                time_radiation = 0.0_wp            !< time since last call of radiation code
805
806
807    REAL(wp) ::  cos_zenith        !< cosine of solar zenith angle, also z-coordinate of solar unit vector
808    REAL(wp) ::  sun_dir_lat       !< y-coordinate of solar unit vector
809    REAL(wp) ::  sun_dir_lon       !< x-coordinate of solar unit vector
810
811    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_net_av       !< average of net radiation (rad_net) at surface
812    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_lw_in_xy_av  !< average of incoming longwave radiation at surface
813    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_lw_out_xy_av !< average of outgoing longwave radiation at surface
814    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_sw_in_xy_av  !< average of incoming shortwave radiation at surface
815    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_sw_out_xy_av !< average of outgoing shortwave radiation at surface
816
817    REAL(wp), PARAMETER :: emissivity_atm_clsky = 0.8_wp       !< emissivity of the clear-sky atmosphere
818!
819!-- Land surface albedos for solar zenith angle of 60degree after Briegleb (1992)     
820!-- (broadband, longwave, shortwave ):   bb,      lw,      sw,
821    REAL(wp), DIMENSION(0:2,1:33), PARAMETER :: albedo_pars = RESHAPE( (/& 
822                                   0.06_wp, 0.06_wp, 0.06_wp,            & !  1
823                                   0.19_wp, 0.28_wp, 0.09_wp,            & !  2
824                                   0.23_wp, 0.33_wp, 0.11_wp,            & !  3
825                                   0.23_wp, 0.33_wp, 0.11_wp,            & !  4
826                                   0.25_wp, 0.34_wp, 0.14_wp,            & !  5
827                                   0.14_wp, 0.22_wp, 0.06_wp,            & !  6
828                                   0.17_wp, 0.27_wp, 0.06_wp,            & !  7
829                                   0.19_wp, 0.31_wp, 0.06_wp,            & !  8
830                                   0.14_wp, 0.22_wp, 0.06_wp,            & !  9
831                                   0.18_wp, 0.28_wp, 0.06_wp,            & ! 10
832                                   0.43_wp, 0.51_wp, 0.35_wp,            & ! 11
833                                   0.32_wp, 0.40_wp, 0.24_wp,            & ! 12
834                                   0.19_wp, 0.27_wp, 0.10_wp,            & ! 13
835                                   0.77_wp, 0.65_wp, 0.90_wp,            & ! 14
836                                   0.77_wp, 0.65_wp, 0.90_wp,            & ! 15
837                                   0.82_wp, 0.70_wp, 0.95_wp,            & ! 16
838                                   0.08_wp, 0.08_wp, 0.08_wp,            & ! 17
839                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 18
840                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 19
841                                   0.30_wp, 0.30_wp, 0.30_wp,            & ! 20
842                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 21
843                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 22
844                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 23
845                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 24
846                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 25
847                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 26
848                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 27
849                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 28
850                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 29
851                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 30
852                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 31
853                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 32
854                                   0.17_wp, 0.17_wp, 0.17_wp             & ! 33
855                                 /), (/ 3, 33 /) )
856
857    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE, TARGET :: &
858                        rad_lw_cs_hr,                  & !< longwave clear sky radiation heating rate (K/s)
859                        rad_lw_cs_hr_av,               & !< average of rad_lw_cs_hr
860                        rad_lw_hr,                     & !< longwave radiation heating rate (K/s)
861                        rad_lw_hr_av,                  & !< average of rad_sw_hr
862                        rad_lw_in,                     & !< incoming longwave radiation (W/m2)
863                        rad_lw_in_av,                  & !< average of rad_lw_in
864                        rad_lw_out,                    & !< outgoing longwave radiation (W/m2)
865                        rad_lw_out_av,                 & !< average of rad_lw_out
866                        rad_sw_cs_hr,                  & !< shortwave clear sky radiation heating rate (K/s)
867                        rad_sw_cs_hr_av,               & !< average of rad_sw_cs_hr
868                        rad_sw_hr,                     & !< shortwave radiation heating rate (K/s)
869                        rad_sw_hr_av,                  & !< average of rad_sw_hr
870                        rad_sw_in,                     & !< incoming shortwave radiation (W/m2)
871                        rad_sw_in_av,                  & !< average of rad_sw_in
872                        rad_sw_out,                    & !< outgoing shortwave radiation (W/m2)
873                        rad_sw_out_av                    !< average of rad_sw_out
874
875
876!
877!-- Variables and parameters used in RRTMG only
878#if defined ( __rrtmg )
879    CHARACTER(LEN=12) :: rrtm_input_file = "RAD_SND_DATA" !< name of the NetCDF input file (sounding data)
880
881
882!
883!-- Flag parameters to be passed to RRTMG (should not be changed until ice phase in clouds is allowed)
884    INTEGER(iwp), PARAMETER :: rrtm_idrv     = 1, & !< flag for longwave upward flux calculation option (0,1)
885                               rrtm_inflglw  = 2, & !< flag for lw cloud optical properties (0,1,2)
886                               rrtm_iceflglw = 0, & !< flag for lw ice particle specifications (0,1,2,3)
887                               rrtm_liqflglw = 1, & !< flag for lw liquid droplet specifications
888                               rrtm_inflgsw  = 2, & !< flag for sw cloud optical properties (0,1,2)
889                               rrtm_iceflgsw = 0, & !< flag for sw ice particle specifications (0,1,2,3)
890                               rrtm_liqflgsw = 1    !< flag for sw liquid droplet specifications
891
892!
893!-- The following variables should be only changed with care, as this will
894!-- require further setting of some variables, which is currently not
895!-- implemented (aerosols, ice phase).
896    INTEGER(iwp) :: nzt_rad,           & !< upper vertical limit for radiation calculations
897                    rrtm_icld = 0,     & !< cloud flag (0: clear sky column, 1: cloudy column)
898                    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)
899
900    INTEGER(iwp) :: nc_stat !< local variable for storin the result of netCDF calls for error message handling
901
902    LOGICAL :: snd_exists = .FALSE.      !< flag parameter to check whether a user-defined input files exists
903    LOGICAL :: sw_exists = .FALSE.       !< flag parameter to check whether that required rrtmg sw file exists
904    LOGICAL :: lw_exists = .FALSE.       !< flag parameter to check whether that required rrtmg lw file exists
905
906
907    REAL(wp), PARAMETER :: mol_mass_air_d_wv = 1.607793_wp !< molecular weight dry air / water vapor
908
909    REAL(wp), DIMENSION(:), ALLOCATABLE :: hyp_snd,     & !< hypostatic pressure from sounding data (hPa)
910                                           rrtm_tsfc,   & !< dummy array for storing surface temperature
911                                           t_snd          !< actual temperature from sounding data (hPa)
912
913    REAL(wp), DIMENSION(:,:), ALLOCATABLE :: rrtm_ccl4vmr,   & !< CCL4 volume mixing ratio (g/mol)
914                                             rrtm_cfc11vmr,  & !< CFC11 volume mixing ratio (g/mol)
915                                             rrtm_cfc12vmr,  & !< CFC12 volume mixing ratio (g/mol)
916                                             rrtm_cfc22vmr,  & !< CFC22 volume mixing ratio (g/mol)
917                                             rrtm_ch4vmr,    & !< CH4 volume mixing ratio
918                                             rrtm_cicewp,    & !< in-cloud ice water path (g/m2)
919                                             rrtm_cldfr,     & !< cloud fraction (0,1)
920                                             rrtm_cliqwp,    & !< in-cloud liquid water path (g/m2)
921                                             rrtm_co2vmr,    & !< CO2 volume mixing ratio (g/mol)
922                                             rrtm_emis,      & !< surface emissivity (0-1) 
923                                             rrtm_h2ovmr,    & !< H2O volume mixing ratio
924                                             rrtm_n2ovmr,    & !< N2O volume mixing ratio
925                                             rrtm_o2vmr,     & !< O2 volume mixing ratio
926                                             rrtm_o3vmr,     & !< O3 volume mixing ratio
927                                             rrtm_play,      & !< pressure layers (hPa, zu-grid)
928                                             rrtm_plev,      & !< pressure layers (hPa, zw-grid)
929                                             rrtm_reice,     & !< cloud ice effective radius (microns)
930                                             rrtm_reliq,     & !< cloud water drop effective radius (microns)
931                                             rrtm_tlay,      & !< actual temperature (K, zu-grid)
932                                             rrtm_tlev,      & !< actual temperature (K, zw-grid)
933                                             rrtm_lwdflx,    & !< RRTM output of incoming longwave radiation flux (W/m2)
934                                             rrtm_lwdflxc,   & !< RRTM output of outgoing clear sky longwave radiation flux (W/m2)
935                                             rrtm_lwuflx,    & !< RRTM output of outgoing longwave radiation flux (W/m2)
936                                             rrtm_lwuflxc,   & !< RRTM output of incoming clear sky longwave radiation flux (W/m2)
937                                             rrtm_lwuflx_dt, & !< RRTM output of incoming clear sky longwave radiation flux (W/m2)
938                                             rrtm_lwuflxc_dt,& !< RRTM output of outgoing clear sky longwave radiation flux (W/m2)
939                                             rrtm_lwhr,      & !< RRTM output of longwave radiation heating rate (K/d)
940                                             rrtm_lwhrc,     & !< RRTM output of incoming longwave clear sky radiation heating rate (K/d)
941                                             rrtm_swdflx,    & !< RRTM output of incoming shortwave radiation flux (W/m2)
942                                             rrtm_swdflxc,   & !< RRTM output of outgoing clear sky shortwave radiation flux (W/m2)
943                                             rrtm_swuflx,    & !< RRTM output of outgoing shortwave radiation flux (W/m2)
944                                             rrtm_swuflxc,   & !< RRTM output of incoming clear sky shortwave radiation flux (W/m2)
945                                             rrtm_swhr,      & !< RRTM output of shortwave radiation heating rate (K/d)
946                                             rrtm_swhrc,     & !< RRTM output of incoming shortwave clear sky radiation heating rate (K/d)
947                                             rrtm_dirdflux,  & !< RRTM output of incoming direct shortwave (W/m2)
948                                             rrtm_difdflux     !< RRTM output of incoming diffuse shortwave (W/m2)
949
950    REAL(wp), DIMENSION(1) ::                rrtm_aldif,     & !< surface albedo for longwave diffuse radiation
951                                             rrtm_aldir,     & !< surface albedo for longwave direct radiation
952                                             rrtm_asdif,     & !< surface albedo for shortwave diffuse radiation
953                                             rrtm_asdir        !< surface albedo for shortwave direct radiation
954
955!
956!-- Definition of arrays that are currently not used for calling RRTMG (due to setting of flag parameters)
957    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::  rad_lw_cs_in,   & !< incoming clear sky longwave radiation (W/m2) (not used)
958                                                rad_lw_cs_out,  & !< outgoing clear sky longwave radiation (W/m2) (not used)
959                                                rad_sw_cs_in,   & !< incoming clear sky shortwave radiation (W/m2) (not used)
960                                                rad_sw_cs_out,  & !< outgoing clear sky shortwave radiation (W/m2) (not used)
961                                                rrtm_lw_tauaer, & !< lw aerosol optical depth
962                                                rrtm_lw_taucld, & !< lw in-cloud optical depth
963                                                rrtm_sw_taucld, & !< sw in-cloud optical depth
964                                                rrtm_sw_ssacld, & !< sw in-cloud single scattering albedo
965                                                rrtm_sw_asmcld, & !< sw in-cloud asymmetry parameter
966                                                rrtm_sw_fsfcld, & !< sw in-cloud forward scattering fraction
967                                                rrtm_sw_tauaer, & !< sw aerosol optical depth
968                                                rrtm_sw_ssaaer, & !< sw aerosol single scattering albedo
969                                                rrtm_sw_asmaer, & !< sw aerosol asymmetry parameter
970                                                rrtm_sw_ecaer     !< sw aerosol optical detph at 0.55 microns (rrtm_iaer = 6 only)
971
972#endif
973!
974!-- Parameters of urban and land surface models
975    INTEGER(iwp)                                   ::  nz_urban                           !< number of layers of urban surface (will be calculated)
976    INTEGER(iwp)                                   ::  nz_plant                           !< number of layers of plant canopy (will be calculated)
977    INTEGER(iwp)                                   ::  nz_urban_b                         !< bottom layer of urban surface (will be calculated)
978    INTEGER(iwp)                                   ::  nz_urban_t                         !< top layer of urban surface (will be calculated)
979    INTEGER(iwp)                                   ::  nz_plant_t                         !< top layer of plant canopy (will be calculated)
980!-- parameters of urban and land surface models
981    INTEGER(iwp), PARAMETER                        ::  nzut_free = 3                      !< number of free layers above top of of topography
982    INTEGER(iwp), PARAMETER                        ::  ndsvf = 2                          !< number of dimensions of real values in SVF
983    INTEGER(iwp), PARAMETER                        ::  idsvf = 2                          !< number of dimensions of integer values in SVF
984    INTEGER(iwp), PARAMETER                        ::  ndcsf = 1                          !< number of dimensions of real values in CSF
985    INTEGER(iwp), PARAMETER                        ::  idcsf = 2                          !< number of dimensions of integer values in CSF
986    INTEGER(iwp), PARAMETER                        ::  kdcsf = 4                          !< number of dimensions of integer values in CSF calculation array
987    INTEGER(iwp), PARAMETER                        ::  id = 1                             !< position of d-index in surfl and surf
988    INTEGER(iwp), PARAMETER                        ::  iz = 2                             !< position of k-index in surfl and surf
989    INTEGER(iwp), PARAMETER                        ::  iy = 3                             !< position of j-index in surfl and surf
990    INTEGER(iwp), PARAMETER                        ::  ix = 4                             !< position of i-index in surfl and surf
991    INTEGER(iwp), PARAMETER                        ::  im = 5                             !< position of surface m-index in surfl and surf
992    INTEGER(iwp), PARAMETER                        ::  nidx_surf = 5                      !< number of indices in surfl and surf
993
994    INTEGER(iwp), PARAMETER                        ::  nsurf_type = 10                    !< number of surf types incl. phys.(land+urban) & (atm.,sky,boundary) surfaces - 1
995
996    INTEGER(iwp), PARAMETER                        ::  iup_u    = 0                       !< 0 - index of urban upward surface (ground or roof)
997    INTEGER(iwp), PARAMETER                        ::  idown_u  = 1                       !< 1 - index of urban downward surface (overhanging)
998    INTEGER(iwp), PARAMETER                        ::  inorth_u = 2                       !< 2 - index of urban northward facing wall
999    INTEGER(iwp), PARAMETER                        ::  isouth_u = 3                       !< 3 - index of urban southward facing wall
1000    INTEGER(iwp), PARAMETER                        ::  ieast_u  = 4                       !< 4 - index of urban eastward facing wall
1001    INTEGER(iwp), PARAMETER                        ::  iwest_u  = 5                       !< 5 - index of urban westward facing wall
1002
1003    INTEGER(iwp), PARAMETER                        ::  iup_l    = 6                       !< 6 - index of land upward surface (ground or roof)
1004    INTEGER(iwp), PARAMETER                        ::  inorth_l = 7                       !< 7 - index of land northward facing wall
1005    INTEGER(iwp), PARAMETER                        ::  isouth_l = 8                       !< 8 - index of land southward facing wall
1006    INTEGER(iwp), PARAMETER                        ::  ieast_l  = 9                       !< 9 - index of land eastward facing wall
1007    INTEGER(iwp), PARAMETER                        ::  iwest_l  = 10                      !< 10- index of land westward facing wall
1008
1009    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  idir = (/0, 0,0, 0,1,-1,0,0, 0,1,-1/)   !< surface normal direction x indices
1010    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  jdir = (/0, 0,1,-1,0, 0,0,1,-1,0, 0/)   !< surface normal direction y indices
1011    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  kdir = (/1,-1,0, 0,0, 0,1,0, 0,0, 0/)   !< surface normal direction z indices
1012    REAL(wp),     DIMENSION(0:nsurf_type)          :: facearea                            !< area of single face in respective
1013                                                                                          !< direction (will be calc'd)
1014
1015
1016!-- indices and sizes of urban and land surface models
1017    INTEGER(iwp)                                   ::  startland        !< start index of block of land and roof surfaces
1018    INTEGER(iwp)                                   ::  endland          !< end index of block of land and roof surfaces
1019    INTEGER(iwp)                                   ::  nlands           !< number of land and roof surfaces in local processor
1020    INTEGER(iwp)                                   ::  startwall        !< start index of block of wall surfaces
1021    INTEGER(iwp)                                   ::  endwall          !< end index of block of wall surfaces
1022    INTEGER(iwp)                                   ::  nwalls           !< number of wall surfaces in local processor
1023
1024!-- indices needed for RTM netcdf output subroutines
1025    INTEGER(iwp), PARAMETER                        :: nd = 5
1026    CHARACTER(LEN=6), DIMENSION(0:nd-1), PARAMETER :: dirname = (/ '_roof ', '_south', '_north', '_west ', '_east ' /)
1027    INTEGER(iwp), DIMENSION(0:nd-1), PARAMETER     :: dirint_u = (/ iup_u, isouth_u, inorth_u, iwest_u, ieast_u /)
1028    INTEGER(iwp), DIMENSION(0:nd-1), PARAMETER     :: dirint_l = (/ iup_l, isouth_l, inorth_l, iwest_l, ieast_l /)
1029    INTEGER(iwp), DIMENSION(0:nd-1)                :: dirstart
1030    INTEGER(iwp), DIMENSION(0:nd-1)                :: dirend
1031
1032!-- indices and sizes of urban and land surface models
1033    INTEGER(iwp), DIMENSION(:,:), POINTER          ::  surfl            !< coordinates of i-th local surface in local grid - surfl[:,k] = [d, z, y, x, m]
1034    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surfl_linear     !< dtto (linearly allocated array)
1035    INTEGER(iwp), DIMENSION(:,:), POINTER          ::  surf             !< coordinates of i-th surface in grid - surf[:,k] = [d, z, y, x, m]
1036    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surf_linear      !< dtto (linearly allocated array)
1037    INTEGER(iwp)                                   ::  nsurfl           !< number of all surfaces in local processor
1038    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  nsurfs           !< array of number of all surfaces in individual processors
1039    INTEGER(iwp)                                   ::  nsurf            !< global number of surfaces in index array of surfaces (nsurf = proc nsurfs)
1040    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surfstart        !< starts of blocks of surfaces for individual processors in array surf (indexed from 1)
1041                                                                        !< respective block for particular processor is surfstart[iproc+1]+1 : surfstart[iproc+1]+nsurfs[iproc+1]
1042
1043!-- block variables needed for calculation of the plant canopy model inside the urban surface model
1044    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pct              !< top layer of the plant canopy
1045    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pch              !< heights of the plant canopy
1046    INTEGER(iwp)                                   ::  npcbl = 0        !< number of the plant canopy gridboxes in local processor
1047    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pcbl             !< k,j,i coordinates of l-th local plant canopy box pcbl[:,l] = [k, j, i]
1048    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinsw          !< array of absorbed sw radiation for local plant canopy box
1049    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdir       !< array of absorbed direct sw radiation for local plant canopy box
1050    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdif       !< array of absorbed diffusion sw radiation for local plant canopy box
1051    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinlw          !< array of absorbed lw radiation for local plant canopy box
1052
1053!-- configuration parameters (they can be setup in PALM config)
1054    LOGICAL                                        ::  raytrace_mpi_rma = .TRUE.          !< use MPI RMA to access LAD and gridsurf from remote processes during raytracing
1055    LOGICAL                                        ::  rad_angular_discretization = .TRUE.!< whether to use fixed resolution discretization of view factors for
1056                                                                                          !< reflected radiation (as opposed to all mutually visible pairs)
1057    LOGICAL                                        ::  plant_lw_interact = .TRUE.         !< whether plant canopy interacts with LW radiation (in addition to SW)
1058    INTEGER(iwp)                                   ::  mrt_nlevels = 0                    !< number of vertical boxes above surface for which to calculate MRT
1059    LOGICAL                                        ::  mrt_skip_roof = .TRUE.             !< do not calculate MRT above roof surfaces
1060    LOGICAL                                        ::  mrt_include_sw = .TRUE.            !< should MRT calculation include SW radiation as well?
1061    LOGICAL                                        ::  mrt_geom_human = .TRUE.            !< MRT direction weights simulate human body instead of a sphere
1062    INTEGER(iwp)                                   ::  nrefsteps = 3                      !< number of reflection steps to perform
1063    REAL(wp), PARAMETER                            ::  ext_coef = 0.6_wp                  !< extinction coefficient (a.k.a. alpha)
1064    INTEGER(iwp), PARAMETER                        ::  rad_version_len = 10               !< length of identification string of rad version
1065    CHARACTER(rad_version_len), PARAMETER          ::  rad_version = 'RAD v. 3.0'         !< identification of version of binary svf and restart files
1066    INTEGER(iwp)                                   ::  raytrace_discrete_elevs = 40       !< number of discretization steps for elevation (nadir to zenith)
1067    INTEGER(iwp)                                   ::  raytrace_discrete_azims = 80       !< number of discretization steps for azimuth (out of 360 degrees)
1068    REAL(wp)                                       ::  max_raytracing_dist = -999.0_wp    !< maximum distance for raytracing (in metres)
1069    REAL(wp)                                       ::  min_irrf_value = 1e-6_wp           !< minimum potential irradiance factor value for raytracing
1070    REAL(wp), DIMENSION(1:30)                      ::  svfnorm_report_thresh = 1e21_wp    !< thresholds of SVF normalization values to report
1071    INTEGER(iwp)                                   ::  svfnorm_report_num                 !< number of SVF normalization thresholds to report
1072
1073!-- radiation related arrays to be used in radiation_interaction routine
1074    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_sw_in_dir    !< direct sw radiation
1075    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_sw_in_diff   !< diffusion sw radiation
1076    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_lw_in_diff   !< diffusion lw radiation
1077
1078!-- parameters required for RRTMG lower boundary condition
1079    REAL(wp)                   :: albedo_urb      !< albedo value retuned to RRTMG boundary cond.
1080    REAL(wp)                   :: emissivity_urb  !< emissivity value retuned to RRTMG boundary cond.
1081    REAL(wp)                   :: t_rad_urb       !< temperature value retuned to RRTMG boundary cond.
1082
1083!-- type for calculation of svf
1084    TYPE t_svf
1085        INTEGER(iwp)                               :: isurflt           !<
1086        INTEGER(iwp)                               :: isurfs            !<
1087        REAL(wp)                                   :: rsvf              !<
1088        REAL(wp)                                   :: rtransp           !<
1089    END TYPE
1090
1091!-- type for calculation of csf
1092    TYPE t_csf
1093        INTEGER(iwp)                               :: ip                !<
1094        INTEGER(iwp)                               :: itx               !<
1095        INTEGER(iwp)                               :: ity               !<
1096        INTEGER(iwp)                               :: itz               !<
1097        INTEGER(iwp)                               :: isurfs            !< Idx of source face / -1 for sky
1098        REAL(wp)                                   :: rcvf              !< Canopy view factor for faces /
1099                                                                        !< canopy sink factor for sky (-1)
1100    END TYPE
1101
1102!-- arrays storing the values of USM
1103    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  svfsurf          !< svfsurf[:,isvf] = index of target and source surface for svf[isvf]
1104    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  svf              !< array of shape view factors+direct irradiation factors for local surfaces
1105    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfins          !< array of sw radiation falling to local surface after i-th reflection
1106    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinl          !< array of lw radiation for local surface after i-th reflection
1107
1108    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  skyvf            !< array of sky view factor for each local surface
1109    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  skyvft           !< array of sky view factor including transparency for each local surface
1110    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsitrans         !< dsidir[isvfl,i] = path transmittance of i-th
1111                                                                        !< direction of direct solar irradiance per target surface
1112    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsitransc        !< dtto per plant canopy box
1113    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsidir           !< dsidir[:,i] = unit vector of i-th
1114                                                                        !< direction of direct solar irradiance
1115    INTEGER(iwp)                                   ::  ndsidir          !< number of apparent solar directions used
1116    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  dsidir_rev       !< dsidir_rev[ielev,iazim] = i for dsidir or -1 if not present
1117
1118    INTEGER(iwp)                                   ::  nmrtbl           !< No. of local grid boxes for which MRT is calculated
1119    INTEGER(iwp)                                   ::  nmrtf            !< number of MRT factors for local processor
1120    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  mrtbl            !< coordinates of i-th local MRT box - surfl[:,i] = [z, y, x]
1121    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  mrtfsurf         !< mrtfsurf[:,imrtf] = index of target MRT box and source surface for mrtf[imrtf]
1122    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtf             !< array of MRT factors for each local MRT box
1123    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtft            !< array of MRT factors including transparency for each local MRT box
1124    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtsky           !< array of sky view factor for each local MRT box
1125    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtskyt          !< array of sky view factor including transparency for each local MRT box
1126    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  mrtdsit          !< array of direct solar transparencies for each local MRT box
1127    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinsw          !< mean SW radiant flux for each MRT box
1128    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinlw          !< mean LW radiant flux for each MRT box
1129    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrt              !< mean radiant temperature for each MRT box
1130    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinsw_av       !< time average mean SW radiant flux for each MRT box
1131    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinlw_av       !< time average mean LW radiant flux for each MRT box
1132    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrt_av           !< time average mean radiant temperature for each MRT box
1133
1134    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinsw         !< array of sw radiation falling to local surface including radiation from reflections
1135    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlw         !< array of lw radiation falling to local surface including radiation from reflections
1136    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdir      !< array of direct sw radiation falling to local surface
1137    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdif      !< array of diffuse sw radiation from sky and model boundary falling to local surface
1138    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwdif      !< array of diffuse lw radiation from sky and model boundary falling to local surface
1139   
1140                                                                        !< Outward radiation is only valid for nonvirtual surfaces
1141    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsl        !< array of reflected sw radiation for local surface in i-th reflection
1142    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutll        !< array of reflected + emitted lw radiation for local surface in i-th reflection
1143    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfouts         !< array of reflected sw radiation for all surfaces in i-th reflection
1144    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutl         !< array of reflected + emitted lw radiation for all surfaces in i-th reflection
1145    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlg         !< global array of incoming lw radiation from plant canopy
1146    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsw        !< array of total sw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1147    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutlw        !< array of total lw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1148    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfemitlwl      !< array of emitted lw radiation for local surface used to calculate effective surface temperature for radiation model
1149
1150!-- block variables needed for calculation of the plant canopy model inside the urban surface model
1151    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  csfsurf          !< csfsurf[:,icsf] = index of target surface and csf grid index for csf[icsf]
1152    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  csf              !< array of plant canopy sink fators + direct irradiation factors (transparency)
1153    REAL(wp), DIMENSION(:,:,:), POINTER            ::  sub_lad          !< subset of lad_s within urban surface, transformed to plain Z coordinate
1154    REAL(wp), DIMENSION(:), POINTER                ::  sub_lad_g        !< sub_lad globalized (used to avoid MPI RMA calls in raytracing)
1155    REAL(wp)                                       ::  prototype_lad    !< prototype leaf area density for computing effective optical depth
1156    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  nzterr, plantt   !< temporary global arrays for raytracing
1157    INTEGER(iwp)                                   ::  plantt_max
1158
1159!-- arrays and variables for calculation of svf and csf
1160    TYPE(t_svf), DIMENSION(:), POINTER             ::  asvf             !< pointer to growing svc array
1161    TYPE(t_csf), DIMENSION(:), POINTER             ::  acsf             !< pointer to growing csf array
1162    TYPE(t_svf), DIMENSION(:), POINTER             ::  amrtf            !< pointer to growing mrtf array
1163    TYPE(t_svf), DIMENSION(:), ALLOCATABLE, TARGET ::  asvf1, asvf2     !< realizations of svf array
1164    TYPE(t_csf), DIMENSION(:), ALLOCATABLE, TARGET ::  acsf1, acsf2     !< realizations of csf array
1165    TYPE(t_svf), DIMENSION(:), ALLOCATABLE, TARGET ::  amrtf1, amrtf2   !< realizations of mftf array
1166    INTEGER(iwp)                                   ::  nsvfla           !< dimmension of array allocated for storage of svf in local processor
1167    INTEGER(iwp)                                   ::  ncsfla           !< dimmension of array allocated for storage of csf in local processor
1168    INTEGER(iwp)                                   ::  nmrtfa           !< dimmension of array allocated for storage of mrt
1169    INTEGER(iwp)                                   ::  msvf, mcsf, mmrtf!< mod for swapping the growing array
1170    INTEGER(iwp), PARAMETER                        ::  gasize = 100000_iwp  !< initial size of growing arrays
1171    REAL(wp), PARAMETER                            ::  grow_factor = 1.4_wp !< growth factor of growing arrays
1172    INTEGER(iwp)                                   ::  nsvfl            !< number of svf for local processor
1173    INTEGER(iwp)                                   ::  ncsfl            !< no. of csf in local processor
1174                                                                        !< needed only during calc_svf but must be here because it is
1175                                                                        !< shared between subroutines calc_svf and raytrace
1176    INTEGER(iwp), DIMENSION(:,:,:,:), POINTER      ::  gridsurf         !< reverse index of local surfl[d,k,j,i] (for case rad_angular_discretization)
1177    INTEGER(iwp), DIMENSION(:,:,:), ALLOCATABLE    ::  gridpcbl         !< reverse index of local pcbl[k,j,i]
1178    INTEGER(iwp), PARAMETER                        ::  nsurf_type_u = 6 !< number of urban surf types (used in gridsurf)
1179
1180!-- temporary arrays for calculation of csf in raytracing
1181    INTEGER(iwp)                                   ::  maxboxesg        !< max number of boxes ray can cross in the domain
1182    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  boxes            !< coordinates of gridboxes being crossed by ray
1183    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  crlens           !< array of crossing lengths of ray for particular grid boxes
1184    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  lad_ip           !< array of numbers of process where lad is stored
1185#if defined( __parallel )
1186    INTEGER(kind=MPI_ADDRESS_KIND), &
1187                  DIMENSION(:), ALLOCATABLE        ::  lad_disp         !< array of displaycements of lad in local array of proc lad_ip
1188    INTEGER(iwp)                                   ::  win_lad          !< MPI RMA window for leaf area density
1189    INTEGER(iwp)                                   ::  win_gridsurf     !< MPI RMA window for reverse grid surface index
1190#endif
1191    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  lad_s_ray        !< array of received lad_s for appropriate gridboxes crossed by ray
1192    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  target_surfl
1193    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  rt2_track
1194    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rt2_track_lad
1195    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  rt2_track_dist
1196    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  rt2_dist
1197
1198!-- arrays for time averages
1199    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfradnet_av    !< average of net radiation to local surface including radiation from reflections
1200    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinsw_av      !< average of sw radiation falling to local surface including radiation from reflections
1201    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlw_av      !< average of lw radiation falling to local surface including radiation from reflections
1202    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdir_av   !< average of direct sw radiation falling to local surface
1203    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdif_av   !< average of diffuse sw radiation from sky and model boundary falling to local surface
1204    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwdif_av   !< average of diffuse lw radiation from sky and model boundary falling to local surface
1205    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswref_av   !< average of sw radiation falling to surface from reflections
1206    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwref_av   !< average of lw radiation falling to surface from reflections
1207    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsw_av     !< average of total sw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1208    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutlw_av     !< average of total lw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1209    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfins_av       !< average of array of residua of sw radiation absorbed in surface after last reflection
1210    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinl_av       !< average of array of residua of lw radiation absorbed in surface after last reflection
1211    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinlw_av       !< Average of pcbinlw
1212    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinsw_av       !< Average of pcbinsw
1213    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdir_av    !< Average of pcbinswdir
1214    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdif_av    !< Average of pcbinswdif
1215    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswref_av    !< Average of pcbinswref
1216
1217
1218!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1219!-- Energy balance variables
1220!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1221!-- parameters of the land, roof and wall surfaces
1222    REAL(wp), DIMENSION(:), ALLOCATABLE            :: albedo_surf        !< albedo of the surface
1223    REAL(wp), DIMENSION(:), ALLOCATABLE            :: emiss_surf         !< emissivity of the wall surface
1224
1225
1226    INTERFACE radiation_check_data_output
1227       MODULE PROCEDURE radiation_check_data_output
1228    END INTERFACE radiation_check_data_output
1229
1230    INTERFACE radiation_check_data_output_ts
1231       MODULE PROCEDURE radiation_check_data_output_ts
1232    END INTERFACE radiation_check_data_output_ts
1233
1234    INTERFACE radiation_check_data_output_pr
1235       MODULE PROCEDURE radiation_check_data_output_pr
1236    END INTERFACE radiation_check_data_output_pr
1237 
1238    INTERFACE radiation_check_parameters
1239       MODULE PROCEDURE radiation_check_parameters
1240    END INTERFACE radiation_check_parameters
1241 
1242    INTERFACE radiation_clearsky
1243       MODULE PROCEDURE radiation_clearsky
1244    END INTERFACE radiation_clearsky
1245 
1246    INTERFACE radiation_constant
1247       MODULE PROCEDURE radiation_constant
1248    END INTERFACE radiation_constant
1249 
1250    INTERFACE radiation_control
1251       MODULE PROCEDURE radiation_control
1252    END INTERFACE radiation_control
1253
1254    INTERFACE radiation_3d_data_averaging
1255       MODULE PROCEDURE radiation_3d_data_averaging
1256    END INTERFACE radiation_3d_data_averaging
1257
1258    INTERFACE radiation_data_output_2d
1259       MODULE PROCEDURE radiation_data_output_2d
1260    END INTERFACE radiation_data_output_2d
1261
1262    INTERFACE radiation_data_output_3d
1263       MODULE PROCEDURE radiation_data_output_3d
1264    END INTERFACE radiation_data_output_3d
1265
1266    INTERFACE radiation_data_output_mask
1267       MODULE PROCEDURE radiation_data_output_mask
1268    END INTERFACE radiation_data_output_mask
1269
1270    INTERFACE radiation_define_netcdf_grid
1271       MODULE PROCEDURE radiation_define_netcdf_grid
1272    END INTERFACE radiation_define_netcdf_grid
1273
1274    INTERFACE radiation_header
1275       MODULE PROCEDURE radiation_header
1276    END INTERFACE radiation_header 
1277 
1278    INTERFACE radiation_init
1279       MODULE PROCEDURE radiation_init
1280    END INTERFACE radiation_init
1281
1282    INTERFACE radiation_parin
1283       MODULE PROCEDURE radiation_parin
1284    END INTERFACE radiation_parin
1285   
1286    INTERFACE radiation_rrtmg
1287       MODULE PROCEDURE radiation_rrtmg
1288    END INTERFACE radiation_rrtmg
1289
1290#if defined( __rrtmg )
1291    INTERFACE radiation_tendency
1292       MODULE PROCEDURE radiation_tendency
1293       MODULE PROCEDURE radiation_tendency_ij
1294    END INTERFACE radiation_tendency
1295#endif
1296
1297    INTERFACE radiation_rrd_local
1298       MODULE PROCEDURE radiation_rrd_local
1299    END INTERFACE radiation_rrd_local
1300
1301    INTERFACE radiation_wrd_local
1302       MODULE PROCEDURE radiation_wrd_local
1303    END INTERFACE radiation_wrd_local
1304
1305    INTERFACE radiation_interaction
1306       MODULE PROCEDURE radiation_interaction
1307    END INTERFACE radiation_interaction
1308
1309    INTERFACE radiation_interaction_init
1310       MODULE PROCEDURE radiation_interaction_init
1311    END INTERFACE radiation_interaction_init
1312 
1313    INTERFACE radiation_presimulate_solar_pos
1314       MODULE PROCEDURE radiation_presimulate_solar_pos
1315    END INTERFACE radiation_presimulate_solar_pos
1316
1317    INTERFACE radiation_calc_svf
1318       MODULE PROCEDURE radiation_calc_svf
1319    END INTERFACE radiation_calc_svf
1320
1321    INTERFACE radiation_write_svf
1322       MODULE PROCEDURE radiation_write_svf
1323    END INTERFACE radiation_write_svf
1324
1325    INTERFACE radiation_read_svf
1326       MODULE PROCEDURE radiation_read_svf
1327    END INTERFACE radiation_read_svf
1328
1329
1330    SAVE
1331
1332    PRIVATE
1333
1334!
1335!-- Public functions / NEEDS SORTING
1336    PUBLIC radiation_check_data_output, radiation_check_data_output_pr,        &
1337           radiation_check_data_output_ts,                                     &
1338           radiation_check_parameters, radiation_control,                      &
1339           radiation_header, radiation_init, radiation_parin,                  &
1340           radiation_3d_data_averaging,                                        &
1341           radiation_data_output_2d, radiation_data_output_3d,                 &
1342           radiation_define_netcdf_grid, radiation_wrd_local,                  &
1343           radiation_rrd_local, radiation_data_output_mask,                    &
1344           radiation_calc_svf, radiation_write_svf,                            &
1345           radiation_interaction, radiation_interaction_init,                  &
1346           radiation_read_svf, radiation_presimulate_solar_pos
1347
1348   
1349!
1350!-- Public variables and constants / NEEDS SORTING
1351    PUBLIC albedo, albedo_type, decl_1, decl_2, decl_3, dots_rad, dt_radiation,&
1352           emissivity, force_radiation_call, lat, lon, mrt_geom_human,         &
1353           mrt_include_sw, mrt_nlevels, mrtbl, mrtinsw, mrtinlw, nmrtbl,       &
1354           rad_net_av, radiation, radiation_scheme, rad_lw_in,                 &
1355           rad_lw_in_av, rad_lw_out, rad_lw_out_av,                            &
1356           rad_lw_cs_hr, rad_lw_cs_hr_av, rad_lw_hr, rad_lw_hr_av, rad_sw_in,  &
1357           rad_sw_in_av, rad_sw_out, rad_sw_out_av, rad_sw_cs_hr,              &
1358           rad_sw_cs_hr_av, rad_sw_hr, rad_sw_hr_av, solar_constant,           &
1359           skip_time_do_radiation, time_radiation, unscheduled_radiation_calls,&
1360           cos_zenith, calc_zenith, sun_direction, sun_dir_lat, sun_dir_lon,   &
1361           idir, jdir, kdir, id, iz, iy, ix,                                   &
1362           iup_u, inorth_u, isouth_u, ieast_u, iwest_u,                        &
1363           iup_l, inorth_l, isouth_l, ieast_l, iwest_l,                        &
1364           nsurf_type, nz_urban_b, nz_urban_t, nz_urban, pch, nsurf,                 &
1365           idsvf, ndsvf, idcsf, ndcsf, kdcsf, pct,                             &
1366           radiation_interactions, startwall, startland, endland, endwall,     &
1367           skyvf, skyvft, radiation_interactions_on, average_radiation,        &
1368           rad_sw_in_diff, rad_sw_in_dir
1369
1370
1371#if defined ( __rrtmg )
1372    PUBLIC radiation_tendency, rrtm_aldif, rrtm_aldir, rrtm_asdif, rrtm_asdir
1373#endif
1374
1375 CONTAINS
1376
1377
1378!------------------------------------------------------------------------------!
1379! Description:
1380! ------------
1381!> This subroutine controls the calls of the radiation schemes
1382!------------------------------------------------------------------------------!
1383    SUBROUTINE radiation_control
1384 
1385 
1386       IMPLICIT NONE
1387
1388
1389       IF ( debug_output_timestep )  CALL debug_message( 'radiation_control', 'start' )
1390
1391
1392       SELECT CASE ( TRIM( radiation_scheme ) )
1393
1394          CASE ( 'constant' )
1395             CALL radiation_constant
1396         
1397          CASE ( 'clear-sky' ) 
1398             CALL radiation_clearsky
1399       
1400          CASE ( 'rrtmg' )
1401             CALL radiation_rrtmg
1402
1403          CASE DEFAULT
1404
1405       END SELECT
1406
1407       IF ( debug_output_timestep )  CALL debug_message( 'radiation_control', 'end' )
1408
1409    END SUBROUTINE radiation_control
1410
1411!------------------------------------------------------------------------------!
1412! Description:
1413! ------------
1414!> Check data output for radiation model
1415!------------------------------------------------------------------------------!
1416    SUBROUTINE radiation_check_data_output( variable, unit, i, ilen, k )
1417 
1418 
1419       USE control_parameters,                                                 &
1420           ONLY: data_output, message_string
1421
1422       IMPLICIT NONE
1423
1424       CHARACTER (LEN=*) ::  unit          !<
1425       CHARACTER (LEN=*) ::  variable      !<
1426
1427       INTEGER(iwp) :: i, k
1428       INTEGER(iwp) :: ilen
1429       CHARACTER(LEN=varnamelength) :: var  !< TRIM(variable)
1430
1431       var = TRIM(variable)
1432
1433       IF ( len(var) < 3_iwp  )  THEN
1434          unit = 'illegal'
1435          RETURN
1436       ENDIF
1437
1438       IF ( var(1:3) /= 'rad'  .AND.  var(1:3) /= 'rtm' )  THEN
1439          unit = 'illegal'
1440          RETURN
1441       ENDIF
1442
1443!--    first process diractional variables
1444       IF ( var(1:12) == 'rtm_rad_net_'  .OR.  var(1:13) == 'rtm_rad_insw_'  .OR.        &
1445            var(1:13) == 'rtm_rad_inlw_'  .OR.  var(1:16) == 'rtm_rad_inswdir_'  .OR.    &
1446            var(1:16) == 'rtm_rad_inswdif_'  .OR.  var(1:16) == 'rtm_rad_inswref_'  .OR. &
1447            var(1:16) == 'rtm_rad_inlwdif_'  .OR.  var(1:16) == 'rtm_rad_inlwref_'  .OR. &
1448            var(1:14) == 'rtm_rad_outsw_'  .OR.  var(1:14) == 'rtm_rad_outlw_'  .OR.     &
1449            var(1:14) == 'rtm_rad_ressw_'  .OR.  var(1:14) == 'rtm_rad_reslw_'  ) THEN
1450          IF ( .NOT.  radiation ) THEN
1451                message_string = 'output of "' // TRIM( var ) // '" require'&
1452                                 // 's radiation = .TRUE.'
1453                CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1454          ENDIF
1455          unit = 'W/m2'
1456       ELSE IF ( var(1:7) == 'rtm_svf'  .OR.  var(1:7) == 'rtm_dif'  .OR.                &
1457                 var(1:9) == 'rtm_skyvf' .OR. var(1:9) == 'rtm_skyvft'  .OR.             &
1458                 var(1:12) == 'rtm_surfalb_'  .OR.  var(1:13) == 'rtm_surfemis_'  ) 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 = '1'
1465       ELSE
1466!--       non-directional variables
1467          SELECT CASE ( TRIM( var ) )
1468             CASE ( 'rad_lw_cs_hr', 'rad_lw_hr', 'rad_lw_in', 'rad_lw_out', &
1469                    'rad_sw_cs_hr', 'rad_sw_hr', 'rad_sw_in', 'rad_sw_out'  )
1470                IF (  .NOT.  radiation  .OR.  radiation_scheme /= 'rrtmg' )  THEN
1471                   message_string = '"output of "' // TRIM( var ) // '" requi' // &
1472                                    'res radiation = .TRUE. and ' //              &
1473                                    'radiation_scheme = "rrtmg"'
1474                   CALL message( 'check_parameters', 'PA0406', 1, 2, 0, 6, 0 )
1475                ENDIF
1476                unit = 'K/h'
1477
1478             CASE ( 'rad_net*', 'rrtm_aldif*', 'rrtm_aldir*', 'rrtm_asdif*',      &
1479                    'rrtm_asdir*', 'rad_lw_in*', 'rad_lw_out*', 'rad_sw_in*',     &
1480                    'rad_sw_out*')
1481                IF ( i == 0 .AND. ilen == 0 .AND. k == 0)  THEN
1482                   ! Workaround for masked output (calls with i=ilen=k=0)
1483                   unit = 'illegal'
1484                   RETURN
1485                ENDIF
1486                IF ( k == 0  .OR.  data_output(i)(ilen-2:ilen) /= '_xy' )  THEN
1487                   message_string = 'illegal value for data_output: "' //         &
1488                                    TRIM( var ) // '" & only 2d-horizontal ' //   &
1489                                    'cross sections are allowed for this value'
1490                   CALL message( 'check_parameters', 'PA0111', 1, 2, 0, 6, 0 )
1491                ENDIF
1492                IF (  .NOT.  radiation  .OR.  radiation_scheme /= "rrtmg" )  THEN
1493                   IF ( TRIM( var ) == 'rrtm_aldif*'  .OR.                        &
1494                        TRIM( var ) == 'rrtm_aldir*'  .OR.                        &
1495                        TRIM( var ) == 'rrtm_asdif*'  .OR.                        &
1496                        TRIM( var ) == 'rrtm_asdir*'      )                       &
1497                   THEN
1498                      message_string = 'output of "' // TRIM( var ) // '" require'&
1499                                       // 's radiation = .TRUE. and radiation_sch'&
1500                                       // 'eme = "rrtmg"'
1501                      CALL message( 'check_parameters', 'PA0409', 1, 2, 0, 6, 0 )
1502                   ENDIF
1503                ENDIF
1504
1505                IF ( TRIM( var ) == 'rad_net*'      ) unit = 'W/m2'
1506                IF ( TRIM( var ) == 'rad_lw_in*'    ) unit = 'W/m2'
1507                IF ( TRIM( var ) == 'rad_lw_out*'   ) unit = 'W/m2'
1508                IF ( TRIM( var ) == 'rad_sw_in*'    ) unit = 'W/m2'
1509                IF ( TRIM( var ) == 'rad_sw_out*'   ) unit = 'W/m2'
1510                IF ( TRIM( var ) == 'rad_sw_in'     ) unit = 'W/m2'
1511                IF ( TRIM( var ) == 'rrtm_aldif*'   ) unit = ''
1512                IF ( TRIM( var ) == 'rrtm_aldir*'   ) unit = ''
1513                IF ( TRIM( var ) == 'rrtm_asdif*'   ) unit = ''
1514                IF ( TRIM( var ) == 'rrtm_asdir*'   ) unit = ''
1515
1516             CASE ( 'rtm_rad_pc_inlw', 'rtm_rad_pc_insw', 'rtm_rad_pc_inswdir', &
1517                    'rtm_rad_pc_inswdif', 'rtm_rad_pc_inswref')
1518                IF ( .NOT.  radiation ) THEN
1519                   message_string = 'output of "' // TRIM( var ) // '" require'&
1520                                    // 's radiation = .TRUE.'
1521                   CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1522                ENDIF
1523                unit = 'W'
1524
1525             CASE ( 'rtm_mrt', 'rtm_mrt_sw', 'rtm_mrt_lw'  )
1526                IF ( i == 0 .AND. ilen == 0 .AND. k == 0)  THEN
1527                   ! Workaround for masked output (calls with i=ilen=k=0)
1528                   unit = 'illegal'
1529                   RETURN
1530                ENDIF
1531
1532                IF ( .NOT.  radiation ) THEN
1533                   message_string = 'output of "' // TRIM( var ) // '" require'&
1534                                    // 's radiation = .TRUE.'
1535                   CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1536                ENDIF
1537                IF ( mrt_nlevels == 0 ) THEN
1538                   message_string = 'output of "' // TRIM( var ) // '" require'&
1539                                    // 's mrt_nlevels > 0'
1540                   CALL message( 'check_parameters', 'PA0510', 1, 2, 0, 6, 0 )
1541                ENDIF
1542                IF ( TRIM( var ) == 'rtm_mrt_sw'  .AND.  .NOT. mrt_include_sw ) THEN
1543                   message_string = 'output of "' // TRIM( var ) // '" require'&
1544                                    // 's rtm_mrt_sw = .TRUE.'
1545                   CALL message( 'check_parameters', 'PA0511', 1, 2, 0, 6, 0 )
1546                ENDIF
1547                IF ( TRIM( var ) == 'rtm_mrt' ) THEN
1548                   unit = 'K'
1549                ELSE
1550                   unit = 'W m-2'
1551                ENDIF
1552
1553             CASE DEFAULT
1554                unit = 'illegal'
1555
1556          END SELECT
1557       ENDIF
1558
1559    END SUBROUTINE radiation_check_data_output
1560
1561
1562!------------------------------------------------------------------------------!
1563! Description:
1564! ------------
1565!> Set module-specific timeseries units and labels
1566!------------------------------------------------------------------------------!
1567 SUBROUTINE radiation_check_data_output_ts( dots_max, dots_num )
1568
1569
1570    INTEGER(iwp),      INTENT(IN)     ::  dots_max
1571    INTEGER(iwp),      INTENT(INOUT)  ::  dots_num
1572
1573!
1574!-- Next line is just to avoid compiler warning about unused variable.
1575    IF ( dots_max == 0 )  CONTINUE
1576
1577!
1578!-- Temporary solution to add LSM and radiation time series to the default
1579!-- output
1580    IF ( land_surface  .OR.  radiation )  THEN
1581       IF ( TRIM( radiation_scheme ) == 'rrtmg' )  THEN
1582          dots_num = dots_num + 15
1583       ELSE
1584          dots_num = dots_num + 11
1585       ENDIF
1586    ENDIF
1587
1588
1589 END SUBROUTINE radiation_check_data_output_ts
1590
1591!------------------------------------------------------------------------------!
1592! Description:
1593! ------------
1594!> Check data output of profiles for radiation model
1595!------------------------------------------------------------------------------! 
1596    SUBROUTINE radiation_check_data_output_pr( variable, var_count, unit,      &
1597               dopr_unit )
1598 
1599       USE arrays_3d,                                                          &
1600           ONLY: zu
1601
1602       USE control_parameters,                                                 &
1603           ONLY: data_output_pr, message_string
1604
1605       USE indices
1606
1607       USE profil_parameter
1608
1609       USE statistics
1610
1611       IMPLICIT NONE
1612   
1613       CHARACTER (LEN=*) ::  unit      !<
1614       CHARACTER (LEN=*) ::  variable  !<
1615       CHARACTER (LEN=*) ::  dopr_unit !< local value of dopr_unit
1616 
1617       INTEGER(iwp) ::  var_count     !<
1618
1619       SELECT CASE ( TRIM( variable ) )
1620       
1621         CASE ( 'rad_net' )
1622             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme == 'constant' )&
1623             THEN
1624                message_string = 'data_output_pr = ' //                        &
1625                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1626                                 'not available for radiation = .FALSE. or ' //&
1627                                 'radiation_scheme = "constant"'
1628                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1629             ELSE
1630                dopr_index(var_count) = 99
1631                dopr_unit  = 'W/m2'
1632                hom(:,2,99,:)  = SPREAD( zw, 2, statistic_regions+1 )
1633                unit = dopr_unit
1634             ENDIF
1635
1636          CASE ( 'rad_lw_in' )
1637             IF ( (  .NOT.  radiation)  .OR.  radiation_scheme == 'constant' ) &
1638             THEN
1639                message_string = 'data_output_pr = ' //                        &
1640                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1641                                 'not available for radiation = .FALSE. or ' //&
1642                                 'radiation_scheme = "constant"'
1643                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1644             ELSE
1645                dopr_index(var_count) = 100
1646                dopr_unit  = 'W/m2'
1647                hom(:,2,100,:)  = SPREAD( zw, 2, statistic_regions+1 )
1648                unit = dopr_unit 
1649             ENDIF
1650
1651          CASE ( 'rad_lw_out' )
1652             IF ( (  .NOT. radiation )  .OR.  radiation_scheme == 'constant' ) &
1653             THEN
1654                message_string = 'data_output_pr = ' //                        &
1655                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1656                                 'not available for radiation = .FALSE. or ' //&
1657                                 'radiation_scheme = "constant"'
1658                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1659             ELSE
1660                dopr_index(var_count) = 101
1661                dopr_unit  = 'W/m2'
1662                hom(:,2,101,:)  = SPREAD( zw, 2, statistic_regions+1 )
1663                unit = dopr_unit   
1664             ENDIF
1665
1666          CASE ( 'rad_sw_in' )
1667             IF ( (  .NOT. radiation )  .OR.  radiation_scheme == 'constant' ) &
1668             THEN
1669                message_string = 'data_output_pr = ' //                        &
1670                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1671                                 'not available for radiation = .FALSE. or ' //&
1672                                 'radiation_scheme = "constant"'
1673                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1674             ELSE
1675                dopr_index(var_count) = 102
1676                dopr_unit  = 'W/m2'
1677                hom(:,2,102,:)  = SPREAD( zw, 2, statistic_regions+1 )
1678                unit = dopr_unit
1679             ENDIF
1680
1681          CASE ( 'rad_sw_out')
1682             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme == 'constant' )&
1683             THEN
1684                message_string = 'data_output_pr = ' //                        &
1685                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1686                                 'not available for radiation = .FALSE. or ' //&
1687                                 'radiation_scheme = "constant"'
1688                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1689             ELSE
1690                dopr_index(var_count) = 103
1691                dopr_unit  = 'W/m2'
1692                hom(:,2,103,:)  = SPREAD( zw, 2, statistic_regions+1 )
1693                unit = dopr_unit
1694             ENDIF
1695
1696          CASE ( 'rad_lw_cs_hr' )
1697             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1698             THEN
1699                message_string = 'data_output_pr = ' //                        &
1700                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1701                                 'not available for radiation = .FALSE. or ' //&
1702                                 'radiation_scheme /= "rrtmg"'
1703                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1704             ELSE
1705                dopr_index(var_count) = 104
1706                dopr_unit  = 'K/h'
1707                hom(:,2,104,:)  = SPREAD( zu, 2, statistic_regions+1 )
1708                unit = dopr_unit
1709             ENDIF
1710
1711          CASE ( 'rad_lw_hr' )
1712             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1713             THEN
1714                message_string = 'data_output_pr = ' //                        &
1715                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1716                                 'not available for radiation = .FALSE. or ' //&
1717                                 'radiation_scheme /= "rrtmg"'
1718                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1719             ELSE
1720                dopr_index(var_count) = 105
1721                dopr_unit  = 'K/h'
1722                hom(:,2,105,:)  = SPREAD( zu, 2, statistic_regions+1 )
1723                unit = dopr_unit
1724             ENDIF
1725
1726          CASE ( 'rad_sw_cs_hr' )
1727             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1728             THEN
1729                message_string = 'data_output_pr = ' //                        &
1730                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1731                                 'not available for radiation = .FALSE. or ' //&
1732                                 'radiation_scheme /= "rrtmg"'
1733                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1734             ELSE
1735                dopr_index(var_count) = 106
1736                dopr_unit  = 'K/h'
1737                hom(:,2,106,:)  = SPREAD( zu, 2, statistic_regions+1 )
1738                unit = dopr_unit
1739             ENDIF
1740
1741          CASE ( 'rad_sw_hr' )
1742             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1743             THEN
1744                message_string = 'data_output_pr = ' //                        &
1745                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1746                                 'not available for radiation = .FALSE. or ' //&
1747                                 'radiation_scheme /= "rrtmg"'
1748                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1749             ELSE
1750                dopr_index(var_count) = 107
1751                dopr_unit  = 'K/h'
1752                hom(:,2,107,:)  = SPREAD( zu, 2, statistic_regions+1 )
1753                unit = dopr_unit
1754             ENDIF
1755
1756
1757          CASE DEFAULT
1758             unit = 'illegal'
1759
1760       END SELECT
1761
1762
1763    END SUBROUTINE radiation_check_data_output_pr
1764 
1765 
1766!------------------------------------------------------------------------------!
1767! Description:
1768! ------------
1769!> Check parameters routine for radiation model
1770!------------------------------------------------------------------------------!
1771    SUBROUTINE radiation_check_parameters
1772
1773       USE control_parameters,                                                 &
1774           ONLY: land_surface, message_string, urban_surface
1775
1776       USE netcdf_data_input_mod,                                              &
1777           ONLY:  input_pids_static                 
1778   
1779       IMPLICIT NONE
1780       
1781!
1782!--    In case no urban-surface or land-surface model is applied, usage of
1783!--    a radiation model make no sense.         
1784       IF ( .NOT. land_surface  .AND.  .NOT. urban_surface )  THEN
1785          message_string = 'Usage of radiation module is only allowed if ' //  &
1786                           'land-surface and/or urban-surface model is applied.'
1787          CALL message( 'check_parameters', 'PA0486', 1, 2, 0, 6, 0 )
1788       ENDIF
1789
1790       IF ( radiation_scheme /= 'constant'   .AND.                             &
1791            radiation_scheme /= 'clear-sky'  .AND.                             &
1792            radiation_scheme /= 'rrtmg' )  THEN
1793          message_string = 'unknown radiation_scheme = '//                     &
1794                           TRIM( radiation_scheme )
1795          CALL message( 'check_parameters', 'PA0405', 1, 2, 0, 6, 0 )
1796       ELSEIF ( radiation_scheme == 'rrtmg' )  THEN
1797#if ! defined ( __rrtmg )
1798          message_string = 'radiation_scheme = "rrtmg" requires ' //           & 
1799                           'compilation of PALM with pre-processor ' //        &
1800                           'directive -D__rrtmg'
1801          CALL message( 'check_parameters', 'PA0407', 1, 2, 0, 6, 0 )
1802#endif
1803#if defined ( __rrtmg ) && ! defined( __netcdf )
1804          message_string = 'radiation_scheme = "rrtmg" requires ' //           & 
1805                           'the use of NetCDF (preprocessor directive ' //     &
1806                           '-D__netcdf'
1807          CALL message( 'check_parameters', 'PA0412', 1, 2, 0, 6, 0 )
1808#endif
1809
1810       ENDIF
1811!
1812!--    Checks performed only if data is given via namelist only.
1813       IF ( .NOT. input_pids_static )  THEN
1814          IF ( albedo_type == 0  .AND.  albedo == 9999999.9_wp  .AND.          &
1815               radiation_scheme == 'clear-sky')  THEN
1816             message_string = 'radiation_scheme = "clear-sky" in combination'//& 
1817                              'with albedo_type = 0 requires setting of'//     &
1818                              'albedo /= 9999999.9'
1819             CALL message( 'check_parameters', 'PA0410', 1, 2, 0, 6, 0 )
1820          ENDIF
1821
1822          IF ( albedo_type == 0  .AND.  radiation_scheme == 'rrtmg'  .AND.     &
1823             ( albedo_lw_dif == 9999999.9_wp .OR. albedo_lw_dir == 9999999.9_wp&
1824          .OR. albedo_sw_dif == 9999999.9_wp .OR. albedo_sw_dir == 9999999.9_wp& 
1825             ) ) THEN
1826             message_string = 'radiation_scheme = "rrtmg" in combination' //   & 
1827                              'with albedo_type = 0 requires setting of ' //   &
1828                              'albedo_lw_dif /= 9999999.9' //                  &
1829                              'albedo_lw_dir /= 9999999.9' //                  &
1830                              'albedo_sw_dif /= 9999999.9 and' //              &
1831                              'albedo_sw_dir /= 9999999.9'
1832             CALL message( 'check_parameters', 'PA0411', 1, 2, 0, 6, 0 )
1833          ENDIF
1834       ENDIF
1835!
1836!--    Parallel rad_angular_discretization without raytrace_mpi_rma is not implemented
1837#if defined( __parallel )     
1838       IF ( rad_angular_discretization  .AND.  .NOT. raytrace_mpi_rma )  THEN
1839          message_string = 'rad_angular_discretization can only be used ' //  &
1840                           'together with raytrace_mpi_rma or when ' //  &
1841                           'no parallelization is applied.'
1842          CALL message( 'check_parameters', 'PA0486', 1, 2, 0, 6, 0 )
1843       ENDIF
1844#endif
1845
1846       IF ( cloud_droplets  .AND.   radiation_scheme == 'rrtmg'  .AND.         &
1847            average_radiation ) THEN
1848          message_string = 'average_radiation = .T. with radiation_scheme'//   & 
1849                           '= "rrtmg" in combination cloud_droplets = .T.'//   &
1850                           'is not implementd'
1851          CALL message( 'check_parameters', 'PA0560', 1, 2, 0, 6, 0 )
1852       ENDIF
1853
1854!
1855!--    Incialize svf normalization reporting histogram
1856       svfnorm_report_num = 1
1857       DO WHILE ( svfnorm_report_thresh(svfnorm_report_num) < 1e20_wp          &
1858                   .AND. svfnorm_report_num <= 30 )
1859          svfnorm_report_num = svfnorm_report_num + 1
1860       ENDDO
1861       svfnorm_report_num = svfnorm_report_num - 1
1862!
1863!--    Check for dt_radiation
1864       IF ( dt_radiation <= 0.0 )  THEN
1865          message_string = 'dt_radiation must be > 0.0' 
1866          CALL message( 'check_parameters', 'PA0591', 1, 2, 0, 6, 0 ) 
1867       ENDIF
1868 
1869    END SUBROUTINE radiation_check_parameters 
1870 
1871 
1872!------------------------------------------------------------------------------!
1873! Description:
1874! ------------
1875!> Initialization of the radiation model
1876!------------------------------------------------------------------------------!
1877    SUBROUTINE radiation_init
1878   
1879       IMPLICIT NONE
1880
1881       INTEGER(iwp) ::  i         !< running index x-direction
1882       INTEGER(iwp) ::  ioff      !< offset in x between surface element reference grid point in atmosphere and actual surface
1883       INTEGER(iwp) ::  j         !< running index y-direction
1884       INTEGER(iwp) ::  joff      !< offset in y between surface element reference grid point in atmosphere and actual surface
1885       INTEGER(iwp) ::  l         !< running index for orientation of vertical surfaces
1886       INTEGER(iwp) ::  m         !< running index for surface elements
1887#if defined( __rrtmg )
1888       INTEGER(iwp) ::  ind_type  !< running index for subgrid-surface tiles
1889#endif
1890
1891
1892       IF ( debug_output )  CALL debug_message( 'radiation_init', 'start' )
1893!
1894!--    Activate radiation_interactions according to the existence of vertical surfaces and/or trees.
1895!--    The namelist parameter radiation_interactions_on can override this behavior.
1896!--    (This check cannot be performed in check_parameters, because vertical_surfaces_exist is first set in
1897!--    init_surface_arrays.)
1898       IF ( radiation_interactions_on )  THEN
1899          IF ( vertical_surfaces_exist  .OR.  plant_canopy )  THEN
1900             radiation_interactions    = .TRUE.
1901             average_radiation         = .TRUE.
1902          ELSE
1903             radiation_interactions_on = .FALSE.   !< reset namelist parameter: no interactions
1904                                                   !< calculations necessary in case of flat surface
1905          ENDIF
1906       ELSEIF ( vertical_surfaces_exist  .OR.  plant_canopy )  THEN
1907          message_string = 'radiation_interactions_on is set to .FALSE. although '     // &
1908                           'vertical surfaces and/or trees exist. The model will run ' // &
1909                           'without RTM (no shadows, no radiation reflections)'
1910          CALL message( 'init_3d_model', 'PA0348', 0, 1, 0, 6, 0 )
1911       ENDIF
1912!
1913!--    If required, initialize radiation interactions between surfaces
1914!--    via sky-view factors. This must be done before radiation is initialized.
1915       IF ( radiation_interactions )  CALL radiation_interaction_init
1916!
1917!--    Allocate array for storing the surface net radiation
1918       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_net )  .AND.                      &
1919                  surf_lsm_h%ns > 0  )   THEN
1920          ALLOCATE( surf_lsm_h%rad_net(1:surf_lsm_h%ns) )
1921          surf_lsm_h%rad_net = 0.0_wp 
1922       ENDIF
1923       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_net )  .AND.                      &
1924                  surf_usm_h%ns > 0  )  THEN
1925          ALLOCATE( surf_usm_h%rad_net(1:surf_usm_h%ns) )
1926          surf_usm_h%rad_net = 0.0_wp 
1927       ENDIF
1928       DO  l = 0, 3
1929          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_net )  .AND.                &
1930                     surf_lsm_v(l)%ns > 0  )  THEN
1931             ALLOCATE( surf_lsm_v(l)%rad_net(1:surf_lsm_v(l)%ns) )
1932             surf_lsm_v(l)%rad_net = 0.0_wp 
1933          ENDIF
1934          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_net )  .AND.                &
1935                     surf_usm_v(l)%ns > 0  )  THEN
1936             ALLOCATE( surf_usm_v(l)%rad_net(1:surf_usm_v(l)%ns) )
1937             surf_usm_v(l)%rad_net = 0.0_wp 
1938          ENDIF
1939       ENDDO
1940
1941
1942!
1943!--    Allocate array for storing the surface longwave (out) radiation change
1944       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_lw_out_change_0 )  .AND.          &
1945                  surf_lsm_h%ns > 0  )   THEN
1946          ALLOCATE( surf_lsm_h%rad_lw_out_change_0(1:surf_lsm_h%ns) )
1947          surf_lsm_h%rad_lw_out_change_0 = 0.0_wp 
1948       ENDIF
1949       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_lw_out_change_0 )  .AND.          &
1950                  surf_usm_h%ns > 0  )  THEN
1951          ALLOCATE( surf_usm_h%rad_lw_out_change_0(1:surf_usm_h%ns) )
1952          surf_usm_h%rad_lw_out_change_0 = 0.0_wp 
1953       ENDIF
1954       DO  l = 0, 3
1955          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_lw_out_change_0 )  .AND.    &
1956                     surf_lsm_v(l)%ns > 0  )  THEN
1957             ALLOCATE( surf_lsm_v(l)%rad_lw_out_change_0(1:surf_lsm_v(l)%ns) )
1958             surf_lsm_v(l)%rad_lw_out_change_0 = 0.0_wp 
1959          ENDIF
1960          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_lw_out_change_0 )  .AND.    &
1961                     surf_usm_v(l)%ns > 0  )  THEN
1962             ALLOCATE( surf_usm_v(l)%rad_lw_out_change_0(1:surf_usm_v(l)%ns) )
1963             surf_usm_v(l)%rad_lw_out_change_0 = 0.0_wp 
1964          ENDIF
1965       ENDDO
1966
1967!
1968!--    Allocate surface arrays for incoming/outgoing short/longwave radiation
1969       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_sw_in )  .AND.                    &
1970                  surf_lsm_h%ns > 0  )   THEN
1971          ALLOCATE( surf_lsm_h%rad_sw_in(1:surf_lsm_h%ns)  )
1972          ALLOCATE( surf_lsm_h%rad_sw_out(1:surf_lsm_h%ns) )
1973          ALLOCATE( surf_lsm_h%rad_sw_dir(1:surf_lsm_h%ns) )
1974          ALLOCATE( surf_lsm_h%rad_sw_dif(1:surf_lsm_h%ns) )
1975          ALLOCATE( surf_lsm_h%rad_sw_ref(1:surf_lsm_h%ns) )
1976          ALLOCATE( surf_lsm_h%rad_sw_res(1:surf_lsm_h%ns) )
1977          ALLOCATE( surf_lsm_h%rad_lw_in(1:surf_lsm_h%ns)  )
1978          ALLOCATE( surf_lsm_h%rad_lw_out(1:surf_lsm_h%ns) )
1979          ALLOCATE( surf_lsm_h%rad_lw_dif(1:surf_lsm_h%ns) )
1980          ALLOCATE( surf_lsm_h%rad_lw_ref(1:surf_lsm_h%ns) )
1981          ALLOCATE( surf_lsm_h%rad_lw_res(1:surf_lsm_h%ns) )
1982          surf_lsm_h%rad_sw_in  = 0.0_wp 
1983          surf_lsm_h%rad_sw_out = 0.0_wp 
1984          surf_lsm_h%rad_sw_dir = 0.0_wp 
1985          surf_lsm_h%rad_sw_dif = 0.0_wp 
1986          surf_lsm_h%rad_sw_ref = 0.0_wp 
1987          surf_lsm_h%rad_sw_res = 0.0_wp 
1988          surf_lsm_h%rad_lw_in  = 0.0_wp 
1989          surf_lsm_h%rad_lw_out = 0.0_wp 
1990          surf_lsm_h%rad_lw_dif = 0.0_wp 
1991          surf_lsm_h%rad_lw_ref = 0.0_wp 
1992          surf_lsm_h%rad_lw_res = 0.0_wp 
1993       ENDIF
1994       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_sw_in )  .AND.                    &
1995                  surf_usm_h%ns > 0  )  THEN
1996          ALLOCATE( surf_usm_h%rad_sw_in(1:surf_usm_h%ns)  )
1997          ALLOCATE( surf_usm_h%rad_sw_out(1:surf_usm_h%ns) )
1998          ALLOCATE( surf_usm_h%rad_sw_dir(1:surf_usm_h%ns) )
1999          ALLOCATE( surf_usm_h%rad_sw_dif(1:surf_usm_h%ns) )
2000          ALLOCATE( surf_usm_h%rad_sw_ref(1:surf_usm_h%ns) )
2001          ALLOCATE( surf_usm_h%rad_sw_res(1:surf_usm_h%ns) )
2002          ALLOCATE( surf_usm_h%rad_lw_in(1:surf_usm_h%ns)  )
2003          ALLOCATE( surf_usm_h%rad_lw_out(1:surf_usm_h%ns) )
2004          ALLOCATE( surf_usm_h%rad_lw_dif(1:surf_usm_h%ns) )
2005          ALLOCATE( surf_usm_h%rad_lw_ref(1:surf_usm_h%ns) )
2006          ALLOCATE( surf_usm_h%rad_lw_res(1:surf_usm_h%ns) )
2007          surf_usm_h%rad_sw_in  = 0.0_wp 
2008          surf_usm_h%rad_sw_out = 0.0_wp 
2009          surf_usm_h%rad_sw_dir = 0.0_wp 
2010          surf_usm_h%rad_sw_dif = 0.0_wp 
2011          surf_usm_h%rad_sw_ref = 0.0_wp 
2012          surf_usm_h%rad_sw_res = 0.0_wp 
2013          surf_usm_h%rad_lw_in  = 0.0_wp 
2014          surf_usm_h%rad_lw_out = 0.0_wp 
2015          surf_usm_h%rad_lw_dif = 0.0_wp 
2016          surf_usm_h%rad_lw_ref = 0.0_wp 
2017          surf_usm_h%rad_lw_res = 0.0_wp 
2018       ENDIF
2019       DO  l = 0, 3
2020          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_sw_in )  .AND.              &
2021                     surf_lsm_v(l)%ns > 0  )  THEN
2022             ALLOCATE( surf_lsm_v(l)%rad_sw_in(1:surf_lsm_v(l)%ns)  )
2023             ALLOCATE( surf_lsm_v(l)%rad_sw_out(1:surf_lsm_v(l)%ns) )
2024             ALLOCATE( surf_lsm_v(l)%rad_sw_dir(1:surf_lsm_v(l)%ns) )
2025             ALLOCATE( surf_lsm_v(l)%rad_sw_dif(1:surf_lsm_v(l)%ns) )
2026             ALLOCATE( surf_lsm_v(l)%rad_sw_ref(1:surf_lsm_v(l)%ns) )
2027             ALLOCATE( surf_lsm_v(l)%rad_sw_res(1:surf_lsm_v(l)%ns) )
2028
2029             ALLOCATE( surf_lsm_v(l)%rad_lw_in(1:surf_lsm_v(l)%ns)  )
2030             ALLOCATE( surf_lsm_v(l)%rad_lw_out(1:surf_lsm_v(l)%ns) )
2031             ALLOCATE( surf_lsm_v(l)%rad_lw_dif(1:surf_lsm_v(l)%ns) )
2032             ALLOCATE( surf_lsm_v(l)%rad_lw_ref(1:surf_lsm_v(l)%ns) )
2033             ALLOCATE( surf_lsm_v(l)%rad_lw_res(1:surf_lsm_v(l)%ns) )
2034
2035             surf_lsm_v(l)%rad_sw_in  = 0.0_wp 
2036             surf_lsm_v(l)%rad_sw_out = 0.0_wp
2037             surf_lsm_v(l)%rad_sw_dir = 0.0_wp
2038             surf_lsm_v(l)%rad_sw_dif = 0.0_wp
2039             surf_lsm_v(l)%rad_sw_ref = 0.0_wp
2040             surf_lsm_v(l)%rad_sw_res = 0.0_wp
2041
2042             surf_lsm_v(l)%rad_lw_in  = 0.0_wp 
2043             surf_lsm_v(l)%rad_lw_out = 0.0_wp 
2044             surf_lsm_v(l)%rad_lw_dif = 0.0_wp 
2045             surf_lsm_v(l)%rad_lw_ref = 0.0_wp 
2046             surf_lsm_v(l)%rad_lw_res = 0.0_wp 
2047          ENDIF
2048          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_sw_in )  .AND.              &
2049                     surf_usm_v(l)%ns > 0  )  THEN
2050             ALLOCATE( surf_usm_v(l)%rad_sw_in(1:surf_usm_v(l)%ns)  )
2051             ALLOCATE( surf_usm_v(l)%rad_sw_out(1:surf_usm_v(l)%ns) )
2052             ALLOCATE( surf_usm_v(l)%rad_sw_dir(1:surf_usm_v(l)%ns) )
2053             ALLOCATE( surf_usm_v(l)%rad_sw_dif(1:surf_usm_v(l)%ns) )
2054             ALLOCATE( surf_usm_v(l)%rad_sw_ref(1:surf_usm_v(l)%ns) )
2055             ALLOCATE( surf_usm_v(l)%rad_sw_res(1:surf_usm_v(l)%ns) )
2056             ALLOCATE( surf_usm_v(l)%rad_lw_in(1:surf_usm_v(l)%ns)  )
2057             ALLOCATE( surf_usm_v(l)%rad_lw_out(1:surf_usm_v(l)%ns) )
2058             ALLOCATE( surf_usm_v(l)%rad_lw_dif(1:surf_usm_v(l)%ns) )
2059             ALLOCATE( surf_usm_v(l)%rad_lw_ref(1:surf_usm_v(l)%ns) )
2060             ALLOCATE( surf_usm_v(l)%rad_lw_res(1:surf_usm_v(l)%ns) )
2061             surf_usm_v(l)%rad_sw_in  = 0.0_wp 
2062             surf_usm_v(l)%rad_sw_out = 0.0_wp
2063             surf_usm_v(l)%rad_sw_dir = 0.0_wp
2064             surf_usm_v(l)%rad_sw_dif = 0.0_wp
2065             surf_usm_v(l)%rad_sw_ref = 0.0_wp
2066             surf_usm_v(l)%rad_sw_res = 0.0_wp
2067             surf_usm_v(l)%rad_lw_in  = 0.0_wp 
2068             surf_usm_v(l)%rad_lw_out = 0.0_wp 
2069             surf_usm_v(l)%rad_lw_dif = 0.0_wp 
2070             surf_usm_v(l)%rad_lw_ref = 0.0_wp 
2071             surf_usm_v(l)%rad_lw_res = 0.0_wp 
2072          ENDIF
2073       ENDDO
2074!
2075!--    Fix net radiation in case of radiation_scheme = 'constant'
2076       IF ( radiation_scheme == 'constant' )  THEN
2077          IF ( ALLOCATED( surf_lsm_h%rad_net ) )                               &
2078             surf_lsm_h%rad_net    = net_radiation
2079          IF ( ALLOCATED( surf_usm_h%rad_net ) )                               &
2080             surf_usm_h%rad_net    = net_radiation
2081!
2082!--       Todo: weight with inclination angle
2083          DO  l = 0, 3
2084             IF ( ALLOCATED( surf_lsm_v(l)%rad_net ) )                         &
2085                surf_lsm_v(l)%rad_net = net_radiation
2086             IF ( ALLOCATED( surf_usm_v(l)%rad_net ) )                         &
2087                surf_usm_v(l)%rad_net = net_radiation
2088          ENDDO
2089!          radiation = .FALSE.
2090!
2091!--    Calculate orbital constants
2092       ELSE
2093          decl_1 = SIN(23.45_wp * pi / 180.0_wp)
2094          decl_2 = 2.0_wp * pi / 365.0_wp
2095          decl_3 = decl_2 * 81.0_wp
2096          lat    = latitude * pi / 180.0_wp
2097          lon    = longitude * pi / 180.0_wp
2098       ENDIF
2099
2100       IF ( radiation_scheme == 'clear-sky'  .OR.                              &
2101            radiation_scheme == 'constant')  THEN
2102
2103
2104!
2105!--       Allocate arrays for incoming/outgoing short/longwave radiation
2106          IF ( .NOT. ALLOCATED ( rad_sw_in ) )  THEN
2107             ALLOCATE ( rad_sw_in(0:0,nysg:nyng,nxlg:nxrg) )
2108          ENDIF
2109          IF ( .NOT. ALLOCATED ( rad_sw_out ) )  THEN
2110             ALLOCATE ( rad_sw_out(0:0,nysg:nyng,nxlg:nxrg) )
2111          ENDIF
2112
2113          IF ( .NOT. ALLOCATED ( rad_lw_in ) )  THEN
2114             ALLOCATE ( rad_lw_in(0:0,nysg:nyng,nxlg:nxrg) )
2115          ENDIF
2116          IF ( .NOT. ALLOCATED ( rad_lw_out ) )  THEN
2117             ALLOCATE ( rad_lw_out(0:0,nysg:nyng,nxlg:nxrg) )
2118          ENDIF
2119
2120!
2121!--       Allocate average arrays for incoming/outgoing short/longwave radiation
2122          IF ( .NOT. ALLOCATED ( rad_sw_in_av ) )  THEN
2123             ALLOCATE ( rad_sw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
2124          ENDIF
2125          IF ( .NOT. ALLOCATED ( rad_sw_out_av ) )  THEN
2126             ALLOCATE ( rad_sw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
2127          ENDIF
2128
2129          IF ( .NOT. ALLOCATED ( rad_lw_in_av ) )  THEN
2130             ALLOCATE ( rad_lw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
2131          ENDIF
2132          IF ( .NOT. ALLOCATED ( rad_lw_out_av ) )  THEN
2133             ALLOCATE ( rad_lw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
2134          ENDIF
2135!
2136!--       Allocate arrays for broadband albedo, and level 1 initialization
2137!--       via namelist paramter, unless not already allocated.
2138          IF ( .NOT. ALLOCATED(surf_lsm_h%albedo) )  THEN
2139             ALLOCATE( surf_lsm_h%albedo(0:2,1:surf_lsm_h%ns)     )
2140             surf_lsm_h%albedo    = albedo
2141          ENDIF
2142          IF ( .NOT. ALLOCATED(surf_usm_h%albedo) )  THEN
2143             ALLOCATE( surf_usm_h%albedo(0:2,1:surf_usm_h%ns)     )
2144             surf_usm_h%albedo    = albedo
2145          ENDIF
2146
2147          DO  l = 0, 3
2148             IF ( .NOT. ALLOCATED( surf_lsm_v(l)%albedo ) )  THEN
2149                ALLOCATE( surf_lsm_v(l)%albedo(0:2,1:surf_lsm_v(l)%ns) )
2150                surf_lsm_v(l)%albedo = albedo
2151             ENDIF
2152             IF ( .NOT. ALLOCATED( surf_usm_v(l)%albedo ) )  THEN
2153                ALLOCATE( surf_usm_v(l)%albedo(0:2,1:surf_usm_v(l)%ns) )
2154                surf_usm_v(l)%albedo = albedo
2155             ENDIF
2156          ENDDO
2157!
2158!--       Level 2 initialization of broadband albedo via given albedo_type.
2159!--       Only if albedo_type is non-zero. In case of urban surface and
2160!--       input data is read from ASCII file, albedo_type will be zero, so that
2161!--       albedo won't be overwritten.
2162          DO  m = 1, surf_lsm_h%ns
2163             IF ( surf_lsm_h%albedo_type(ind_veg_wall,m) /= 0 )                &
2164                surf_lsm_h%albedo(ind_veg_wall,m) =                            &
2165                           albedo_pars(0,surf_lsm_h%albedo_type(ind_veg_wall,m))
2166             IF ( surf_lsm_h%albedo_type(ind_pav_green,m) /= 0 )               &
2167                surf_lsm_h%albedo(ind_pav_green,m) =                           &
2168                           albedo_pars(0,surf_lsm_h%albedo_type(ind_pav_green,m))
2169             IF ( surf_lsm_h%albedo_type(ind_wat_win,m) /= 0 )                 &
2170                surf_lsm_h%albedo(ind_wat_win,m) =                             &
2171                           albedo_pars(0,surf_lsm_h%albedo_type(ind_wat_win,m))
2172          ENDDO
2173          DO  m = 1, surf_usm_h%ns
2174             IF ( surf_usm_h%albedo_type(ind_veg_wall,m) /= 0 )                &
2175                surf_usm_h%albedo(ind_veg_wall,m) =                            &
2176                           albedo_pars(0,surf_usm_h%albedo_type(ind_veg_wall,m))
2177             IF ( surf_usm_h%albedo_type(ind_pav_green,m) /= 0 )               &
2178                surf_usm_h%albedo(ind_pav_green,m) =                           &
2179                           albedo_pars(0,surf_usm_h%albedo_type(ind_pav_green,m))
2180             IF ( surf_usm_h%albedo_type(ind_wat_win,m) /= 0 )                 &
2181                surf_usm_h%albedo(ind_wat_win,m) =                             &
2182                           albedo_pars(0,surf_usm_h%albedo_type(ind_wat_win,m))
2183          ENDDO
2184
2185          DO  l = 0, 3
2186             DO  m = 1, surf_lsm_v(l)%ns
2187                IF ( surf_lsm_v(l)%albedo_type(ind_veg_wall,m) /= 0 )          &
2188                   surf_lsm_v(l)%albedo(ind_veg_wall,m) =                      &
2189                        albedo_pars(0,surf_lsm_v(l)%albedo_type(ind_veg_wall,m))
2190                IF ( surf_lsm_v(l)%albedo_type(ind_pav_green,m) /= 0 )         &
2191                   surf_lsm_v(l)%albedo(ind_pav_green,m) =                     &
2192                        albedo_pars(0,surf_lsm_v(l)%albedo_type(ind_pav_green,m))
2193                IF ( surf_lsm_v(l)%albedo_type(ind_wat_win,m) /= 0 )           &
2194                   surf_lsm_v(l)%albedo(ind_wat_win,m) =                       &
2195                        albedo_pars(0,surf_lsm_v(l)%albedo_type(ind_wat_win,m))
2196             ENDDO
2197             DO  m = 1, surf_usm_v(l)%ns
2198                IF ( surf_usm_v(l)%albedo_type(ind_veg_wall,m) /= 0 )          &
2199                   surf_usm_v(l)%albedo(ind_veg_wall,m) =                      &
2200                        albedo_pars(0,surf_usm_v(l)%albedo_type(ind_veg_wall,m))
2201                IF ( surf_usm_v(l)%albedo_type(ind_pav_green,m) /= 0 )         &
2202                   surf_usm_v(l)%albedo(ind_pav_green,m) =                     &
2203                        albedo_pars(0,surf_usm_v(l)%albedo_type(ind_pav_green,m))
2204                IF ( surf_usm_v(l)%albedo_type(ind_wat_win,m) /= 0 )           &
2205                   surf_usm_v(l)%albedo(ind_wat_win,m) =                       &
2206                        albedo_pars(0,surf_usm_v(l)%albedo_type(ind_wat_win,m))
2207             ENDDO
2208          ENDDO
2209
2210!
2211!--       Level 3 initialization at grid points where albedo type is zero.
2212!--       This case, albedo is taken from file. In case of constant radiation
2213!--       or clear sky, only broadband albedo is given.
2214          IF ( albedo_pars_f%from_file )  THEN
2215!
2216!--          Horizontal surfaces
2217             DO  m = 1, surf_lsm_h%ns
2218                i = surf_lsm_h%i(m)
2219                j = surf_lsm_h%j(m)
2220                IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2221                   IF ( surf_lsm_h%albedo_type(ind_veg_wall,m) == 0 )          &
2222                      surf_lsm_h%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2223                   IF ( surf_lsm_h%albedo_type(ind_pav_green,m) == 0 )         &
2224                      surf_lsm_h%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2225                   IF ( surf_lsm_h%albedo_type(ind_wat_win,m) == 0 )           &
2226                      surf_lsm_h%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2227                ENDIF
2228             ENDDO
2229             DO  m = 1, surf_usm_h%ns
2230                i = surf_usm_h%i(m)
2231                j = surf_usm_h%j(m)
2232                IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2233                   IF ( surf_usm_h%albedo_type(ind_veg_wall,m) == 0 )          &
2234                      surf_usm_h%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2235                   IF ( surf_usm_h%albedo_type(ind_pav_green,m) == 0 )         &
2236                      surf_usm_h%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2237                   IF ( surf_usm_h%albedo_type(ind_wat_win,m) == 0 )           &
2238                      surf_usm_h%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2239                ENDIF
2240             ENDDO 
2241!
2242!--          Vertical surfaces           
2243             DO  l = 0, 3
2244
2245                ioff = surf_lsm_v(l)%ioff
2246                joff = surf_lsm_v(l)%joff
2247                DO  m = 1, surf_lsm_v(l)%ns
2248                   i = surf_lsm_v(l)%i(m) + ioff
2249                   j = surf_lsm_v(l)%j(m) + joff
2250                   IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2251                      IF ( surf_lsm_v(l)%albedo_type(ind_veg_wall,m) == 0 )    &
2252                         surf_lsm_v(l)%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2253                      IF ( surf_lsm_v(l)%albedo_type(ind_pav_green,m) == 0 )   &
2254                         surf_lsm_v(l)%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2255                      IF ( surf_lsm_v(l)%albedo_type(ind_wat_win,m) == 0 )     &
2256                         surf_lsm_v(l)%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2257                   ENDIF
2258                ENDDO
2259
2260                ioff = surf_usm_v(l)%ioff
2261                joff = surf_usm_v(l)%joff
2262                DO  m = 1, surf_usm_v(l)%ns
2263                   i = surf_usm_v(l)%i(m) + joff
2264                   j = surf_usm_v(l)%j(m) + joff
2265                   IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2266                      IF ( surf_usm_v(l)%albedo_type(ind_veg_wall,m) == 0 )    &
2267                         surf_usm_v(l)%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2268                      IF ( surf_usm_v(l)%albedo_type(ind_pav_green,m) == 0 )   &
2269                         surf_usm_v(l)%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2270                      IF ( surf_usm_v(l)%albedo_type(ind_wat_win,m) == 0 )     &
2271                         surf_usm_v(l)%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2272                   ENDIF
2273                ENDDO
2274             ENDDO
2275
2276          ENDIF 
2277!
2278!--    Initialization actions for RRTMG
2279       ELSEIF ( radiation_scheme == 'rrtmg' )  THEN
2280#if defined ( __rrtmg )
2281!
2282!--       Allocate albedos for short/longwave radiation, horizontal surfaces
2283!--       for wall/green/window (USM) or vegetation/pavement/water surfaces
2284!--       (LSM).
2285          ALLOCATE ( surf_lsm_h%aldif(0:2,1:surf_lsm_h%ns)       )
2286          ALLOCATE ( surf_lsm_h%aldir(0:2,1:surf_lsm_h%ns)       )
2287          ALLOCATE ( surf_lsm_h%asdif(0:2,1:surf_lsm_h%ns)       )
2288          ALLOCATE ( surf_lsm_h%asdir(0:2,1:surf_lsm_h%ns)       )
2289          ALLOCATE ( surf_lsm_h%rrtm_aldif(0:2,1:surf_lsm_h%ns)  )
2290          ALLOCATE ( surf_lsm_h%rrtm_aldir(0:2,1:surf_lsm_h%ns)  )
2291          ALLOCATE ( surf_lsm_h%rrtm_asdif(0:2,1:surf_lsm_h%ns)  )
2292          ALLOCATE ( surf_lsm_h%rrtm_asdir(0:2,1:surf_lsm_h%ns)  )
2293
2294          ALLOCATE ( surf_usm_h%aldif(0:2,1:surf_usm_h%ns)       )
2295          ALLOCATE ( surf_usm_h%aldir(0:2,1:surf_usm_h%ns)       )
2296          ALLOCATE ( surf_usm_h%asdif(0:2,1:surf_usm_h%ns)       )
2297          ALLOCATE ( surf_usm_h%asdir(0:2,1:surf_usm_h%ns)       )
2298          ALLOCATE ( surf_usm_h%rrtm_aldif(0:2,1:surf_usm_h%ns)  )
2299          ALLOCATE ( surf_usm_h%rrtm_aldir(0:2,1:surf_usm_h%ns)  )
2300          ALLOCATE ( surf_usm_h%rrtm_asdif(0:2,1:surf_usm_h%ns)  )
2301          ALLOCATE ( surf_usm_h%rrtm_asdir(0:2,1:surf_usm_h%ns)  )
2302
2303!
2304!--       Allocate broadband albedo (temporary for the current radiation
2305!--       implementations)
2306          IF ( .NOT. ALLOCATED(surf_lsm_h%albedo) )                            &
2307             ALLOCATE( surf_lsm_h%albedo(0:2,1:surf_lsm_h%ns)     )
2308          IF ( .NOT. ALLOCATED(surf_usm_h%albedo) )                            &
2309             ALLOCATE( surf_usm_h%albedo(0:2,1:surf_usm_h%ns)     )
2310
2311!
2312!--       Allocate albedos for short/longwave radiation, vertical surfaces
2313          DO  l = 0, 3
2314
2315             ALLOCATE ( surf_lsm_v(l)%aldif(0:2,1:surf_lsm_v(l)%ns)      )
2316             ALLOCATE ( surf_lsm_v(l)%aldir(0:2,1:surf_lsm_v(l)%ns)      )
2317             ALLOCATE ( surf_lsm_v(l)%asdif(0:2,1:surf_lsm_v(l)%ns)      )
2318             ALLOCATE ( surf_lsm_v(l)%asdir(0:2,1:surf_lsm_v(l)%ns)      )
2319
2320             ALLOCATE ( surf_lsm_v(l)%rrtm_aldif(0:2,1:surf_lsm_v(l)%ns) )
2321             ALLOCATE ( surf_lsm_v(l)%rrtm_aldir(0:2,1:surf_lsm_v(l)%ns) )
2322             ALLOCATE ( surf_lsm_v(l)%rrtm_asdif(0:2,1:surf_lsm_v(l)%ns) )
2323             ALLOCATE ( surf_lsm_v(l)%rrtm_asdir(0:2,1:surf_lsm_v(l)%ns) )
2324
2325             ALLOCATE ( surf_usm_v(l)%aldif(0:2,1:surf_usm_v(l)%ns)      )
2326             ALLOCATE ( surf_usm_v(l)%aldir(0:2,1:surf_usm_v(l)%ns)      )
2327             ALLOCATE ( surf_usm_v(l)%asdif(0:2,1:surf_usm_v(l)%ns)      )
2328             ALLOCATE ( surf_usm_v(l)%asdir(0:2,1:surf_usm_v(l)%ns)      )
2329
2330             ALLOCATE ( surf_usm_v(l)%rrtm_aldif(0:2,1:surf_usm_v(l)%ns) )
2331             ALLOCATE ( surf_usm_v(l)%rrtm_aldir(0:2,1:surf_usm_v(l)%ns) )
2332             ALLOCATE ( surf_usm_v(l)%rrtm_asdif(0:2,1:surf_usm_v(l)%ns) )
2333             ALLOCATE ( surf_usm_v(l)%rrtm_asdir(0:2,1:surf_usm_v(l)%ns) )
2334!
2335!--          Allocate broadband albedo (temporary for the current radiation
2336!--          implementations)
2337             IF ( .NOT. ALLOCATED( surf_lsm_v(l)%albedo ) )                    &
2338                ALLOCATE( surf_lsm_v(l)%albedo(0:2,1:surf_lsm_v(l)%ns) )
2339             IF ( .NOT. ALLOCATED( surf_usm_v(l)%albedo ) )                    &
2340                ALLOCATE( surf_usm_v(l)%albedo(0:2,1:surf_usm_v(l)%ns) )
2341
2342          ENDDO
2343!
2344!--       Level 1 initialization of spectral albedos via namelist
2345!--       paramters. Please note, this case all surface tiles are initialized
2346!--       the same.
2347          IF ( surf_lsm_h%ns > 0 )  THEN
2348             surf_lsm_h%aldif  = albedo_lw_dif
2349             surf_lsm_h%aldir  = albedo_lw_dir
2350             surf_lsm_h%asdif  = albedo_sw_dif
2351             surf_lsm_h%asdir  = albedo_sw_dir
2352             surf_lsm_h%albedo = albedo_sw_dif
2353          ENDIF
2354          IF ( surf_usm_h%ns > 0 )  THEN
2355             IF ( surf_usm_h%albedo_from_ascii )  THEN
2356                surf_usm_h%aldif  = surf_usm_h%albedo
2357                surf_usm_h%aldir  = surf_usm_h%albedo
2358                surf_usm_h%asdif  = surf_usm_h%albedo
2359                surf_usm_h%asdir  = surf_usm_h%albedo
2360             ELSE
2361                surf_usm_h%aldif  = albedo_lw_dif
2362                surf_usm_h%aldir  = albedo_lw_dir
2363                surf_usm_h%asdif  = albedo_sw_dif
2364                surf_usm_h%asdir  = albedo_sw_dir
2365                surf_usm_h%albedo = albedo_sw_dif
2366             ENDIF
2367          ENDIF
2368
2369          DO  l = 0, 3
2370
2371             IF ( surf_lsm_v(l)%ns > 0 )  THEN
2372                surf_lsm_v(l)%aldif  = albedo_lw_dif
2373                surf_lsm_v(l)%aldir  = albedo_lw_dir
2374                surf_lsm_v(l)%asdif  = albedo_sw_dif
2375                surf_lsm_v(l)%asdir  = albedo_sw_dir
2376                surf_lsm_v(l)%albedo = albedo_sw_dif
2377             ENDIF
2378
2379             IF ( surf_usm_v(l)%ns > 0 )  THEN
2380                IF ( surf_usm_v(l)%albedo_from_ascii )  THEN
2381                   surf_usm_v(l)%aldif  = surf_usm_v(l)%albedo
2382                   surf_usm_v(l)%aldir  = surf_usm_v(l)%albedo
2383                   surf_usm_v(l)%asdif  = surf_usm_v(l)%albedo
2384                   surf_usm_v(l)%asdir  = surf_usm_v(l)%albedo
2385                ELSE
2386                   surf_usm_v(l)%aldif  = albedo_lw_dif
2387                   surf_usm_v(l)%aldir  = albedo_lw_dir
2388                   surf_usm_v(l)%asdif  = albedo_sw_dif
2389                   surf_usm_v(l)%asdir  = albedo_sw_dir
2390                ENDIF
2391             ENDIF
2392          ENDDO
2393
2394!
2395!--       Level 2 initialization of spectral albedos via albedo_type.
2396!--       Please note, for natural- and urban-type surfaces, a tile approach
2397!--       is applied so that the resulting albedo is calculated via the weighted
2398!--       average of respective surface fractions.
2399          DO  m = 1, surf_lsm_h%ns
2400!
2401!--          Spectral albedos for vegetation/pavement/water surfaces
2402             DO  ind_type = 0, 2
2403                IF ( surf_lsm_h%albedo_type(ind_type,m) /= 0 )  THEN
2404                   surf_lsm_h%aldif(ind_type,m) =                              &
2405                               albedo_pars(1,surf_lsm_h%albedo_type(ind_type,m))
2406                   surf_lsm_h%asdif(ind_type,m) =                              &
2407                               albedo_pars(2,surf_lsm_h%albedo_type(ind_type,m))
2408                   surf_lsm_h%aldir(ind_type,m) =                              &
2409                               albedo_pars(1,surf_lsm_h%albedo_type(ind_type,m))
2410                   surf_lsm_h%asdir(ind_type,m) =                              &
2411                               albedo_pars(2,surf_lsm_h%albedo_type(ind_type,m))
2412                   surf_lsm_h%albedo(ind_type,m) =                             &
2413                               albedo_pars(0,surf_lsm_h%albedo_type(ind_type,m))
2414                ENDIF
2415             ENDDO
2416
2417          ENDDO
2418!
2419!--       For urban surface only if albedo has not been already initialized
2420!--       in the urban-surface model via the ASCII file.
2421          IF ( .NOT. surf_usm_h%albedo_from_ascii )  THEN
2422             DO  m = 1, surf_usm_h%ns
2423!
2424!--             Spectral albedos for wall/green/window surfaces
2425                DO  ind_type = 0, 2
2426                   IF ( surf_usm_h%albedo_type(ind_type,m) /= 0 )  THEN
2427                      surf_usm_h%aldif(ind_type,m) =                           &
2428                               albedo_pars(1,surf_usm_h%albedo_type(ind_type,m))
2429                      surf_usm_h%asdif(ind_type,m) =                           &
2430                               albedo_pars(2,surf_usm_h%albedo_type(ind_type,m))
2431                      surf_usm_h%aldir(ind_type,m) =                           &
2432                               albedo_pars(1,surf_usm_h%albedo_type(ind_type,m))
2433                      surf_usm_h%asdir(ind_type,m) =                           &
2434                               albedo_pars(2,surf_usm_h%albedo_type(ind_type,m))
2435                      surf_usm_h%albedo(ind_type,m) =                          &
2436                               albedo_pars(0,surf_usm_h%albedo_type(ind_type,m))
2437                   ENDIF
2438                ENDDO
2439
2440             ENDDO
2441          ENDIF
2442
2443          DO l = 0, 3
2444
2445             DO  m = 1, surf_lsm_v(l)%ns
2446!
2447!--             Spectral albedos for vegetation/pavement/water surfaces
2448                DO  ind_type = 0, 2
2449                   IF ( surf_lsm_v(l)%albedo_type(ind_type,m) /= 0 )  THEN
2450                      surf_lsm_v(l)%aldif(ind_type,m) =                        &
2451                            albedo_pars(1,surf_lsm_v(l)%albedo_type(ind_type,m))
2452                      surf_lsm_v(l)%asdif(ind_type,m) =                        &
2453                            albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_type,m))
2454                      surf_lsm_v(l)%aldir(ind_type,m) =                        &
2455                            albedo_pars(1,surf_lsm_v(l)%albedo_type(ind_type,m))
2456                      surf_lsm_v(l)%asdir(ind_type,m) =                        &
2457                            albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_type,m))
2458                      surf_lsm_v(l)%albedo(ind_type,m) =                       &
2459                            albedo_pars(0,surf_lsm_v(l)%albedo_type(ind_type,m))
2460                   ENDIF
2461                ENDDO
2462             ENDDO
2463!
2464!--          For urban surface only if albedo has not been already initialized
2465!--          in the urban-surface model via the ASCII file.
2466             IF ( .NOT. surf_usm_v(l)%albedo_from_ascii )  THEN
2467                DO  m = 1, surf_usm_v(l)%ns
2468!
2469!--                Spectral albedos for wall/green/window surfaces
2470                   DO  ind_type = 0, 2
2471                      IF ( surf_usm_v(l)%albedo_type(ind_type,m) /= 0 )  THEN
2472                         surf_usm_v(l)%aldif(ind_type,m) =                     &
2473                            albedo_pars(1,surf_usm_v(l)%albedo_type(ind_type,m))
2474                         surf_usm_v(l)%asdif(ind_type,m) =                     &
2475                            albedo_pars(2,surf_usm_v(l)%albedo_type(ind_type,m))
2476                         surf_usm_v(l)%aldir(ind_type,m) =                     &
2477                            albedo_pars(1,surf_usm_v(l)%albedo_type(ind_type,m))
2478                         surf_usm_v(l)%asdir(ind_type,m) =                     &
2479                            albedo_pars(2,surf_usm_v(l)%albedo_type(ind_type,m))
2480                         surf_usm_v(l)%albedo(ind_type,m) =                    &
2481                            albedo_pars(0,surf_usm_v(l)%albedo_type(ind_type,m))
2482                      ENDIF
2483                   ENDDO
2484
2485                ENDDO
2486             ENDIF
2487          ENDDO
2488!
2489!--       Level 3 initialization at grid points where albedo type is zero.
2490!--       This case, spectral albedos are taken from file if available
2491          IF ( albedo_pars_f%from_file )  THEN
2492!
2493!--          Horizontal
2494             DO  m = 1, surf_lsm_h%ns
2495                i = surf_lsm_h%i(m)
2496                j = surf_lsm_h%j(m)
2497!
2498!--             Spectral albedos for vegetation/pavement/water surfaces
2499                DO  ind_type = 0, 2
2500                   IF ( surf_lsm_h%albedo_type(ind_type,m) == 0 )  THEN
2501                      IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )&
2502                         surf_lsm_h%albedo(ind_type,m) =                       &
2503                                                albedo_pars_f%pars_xy(0,j,i)
2504                      IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2505                         surf_lsm_h%aldir(ind_type,m) =                        &
2506                                                albedo_pars_f%pars_xy(1,j,i)
2507                      IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2508                         surf_lsm_h%aldif(ind_type,m) =                        &
2509                                                albedo_pars_f%pars_xy(1,j,i)
2510                      IF ( albedo_pars_f%pars_xy(2,j,i) /= albedo_pars_f%fill )&
2511                         surf_lsm_h%asdir(ind_type,m) =                        &
2512                                                albedo_pars_f%pars_xy(2,j,i)
2513                      IF ( albedo_pars_f%pars_xy(2,j,i) /= albedo_pars_f%fill )&
2514                         surf_lsm_h%asdif(ind_type,m) =                        &
2515                                                albedo_pars_f%pars_xy(2,j,i)
2516                   ENDIF
2517                ENDDO
2518             ENDDO
2519!
2520!--          For urban surface only if albedo has not been already initialized
2521!--          in the urban-surface model via the ASCII file.
2522             IF ( .NOT. surf_usm_h%albedo_from_ascii )  THEN
2523                DO  m = 1, surf_usm_h%ns
2524                   i = surf_usm_h%i(m)
2525                   j = surf_usm_h%j(m)
2526!
2527!--                Broadband albedos for wall/green/window surfaces
2528                   DO  ind_type = 0, 2
2529                      IF ( surf_usm_h%albedo_type(ind_type,m) == 0 )  THEN
2530                         IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )&
2531                            surf_usm_h%albedo(ind_type,m) =                       &
2532                                                albedo_pars_f%pars_xy(0,j,i)
2533                      ENDIF
2534                   ENDDO
2535!
2536!--                Spectral albedos especially for building wall surfaces
2537                   IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )  THEN
2538                      surf_usm_h%aldir(ind_veg_wall,m) =                       &
2539                                                albedo_pars_f%pars_xy(1,j,i)
2540                      surf_usm_h%aldif(ind_veg_wall,m) =                       &
2541                                                albedo_pars_f%pars_xy(1,j,i)
2542                   ENDIF
2543                   IF ( albedo_pars_f%pars_xy(2,j,i) /= albedo_pars_f%fill )  THEN
2544                      surf_usm_h%asdir(ind_veg_wall,m) =                       &
2545                                                albedo_pars_f%pars_xy(2,j,i)
2546                      surf_usm_h%asdif(ind_veg_wall,m) =                       &
2547                                                albedo_pars_f%pars_xy(2,j,i)
2548                   ENDIF
2549!
2550!--                Spectral albedos especially for building green surfaces
2551                   IF ( albedo_pars_f%pars_xy(3,j,i) /= albedo_pars_f%fill )  THEN
2552                      surf_usm_h%aldir(ind_pav_green,m) =                      &
2553                                                albedo_pars_f%pars_xy(3,j,i)
2554                      surf_usm_h%aldif(ind_pav_green,m) =                      &
2555                                                albedo_pars_f%pars_xy(3,j,i)
2556                   ENDIF
2557                   IF ( albedo_pars_f%pars_xy(4,j,i) /= albedo_pars_f%fill )  THEN
2558                      surf_usm_h%asdir(ind_pav_green,m) =                      &
2559                                                albedo_pars_f%pars_xy(4,j,i)
2560                      surf_usm_h%asdif(ind_pav_green,m) =                      &
2561                                                albedo_pars_f%pars_xy(4,j,i)
2562                   ENDIF
2563!
2564!--                Spectral albedos especially for building window surfaces
2565                   IF ( albedo_pars_f%pars_xy(5,j,i) /= albedo_pars_f%fill )  THEN
2566                      surf_usm_h%aldir(ind_wat_win,m) =                        &
2567                                                albedo_pars_f%pars_xy(5,j,i)
2568                      surf_usm_h%aldif(ind_wat_win,m) =                        &
2569                                                albedo_pars_f%pars_xy(5,j,i)
2570                   ENDIF
2571                   IF ( albedo_pars_f%pars_xy(6,j,i) /= albedo_pars_f%fill )  THEN
2572                      surf_usm_h%asdir(ind_wat_win,m) =                        &
2573                                                albedo_pars_f%pars_xy(6,j,i)
2574                      surf_usm_h%asdif(ind_wat_win,m) =                        &
2575                                                albedo_pars_f%pars_xy(6,j,i)
2576                   ENDIF
2577
2578                ENDDO
2579             ENDIF
2580!
2581!--          Vertical
2582             DO  l = 0, 3
2583                ioff = surf_lsm_v(l)%ioff
2584                joff = surf_lsm_v(l)%joff
2585
2586                DO  m = 1, surf_lsm_v(l)%ns
2587                   i = surf_lsm_v(l)%i(m)
2588                   j = surf_lsm_v(l)%j(m)
2589!
2590!--                Spectral albedos for vegetation/pavement/water surfaces
2591                   DO  ind_type = 0, 2
2592                      IF ( surf_lsm_v(l)%albedo_type(ind_type,m) == 0 )  THEN
2593                         IF ( albedo_pars_f%pars_xy(0,j+joff,i+ioff) /=        &
2594                              albedo_pars_f%fill )                             &
2595                            surf_lsm_v(l)%albedo(ind_type,m) =                 &
2596                                          albedo_pars_f%pars_xy(0,j+joff,i+ioff)
2597                         IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2598                              albedo_pars_f%fill )                             &
2599                            surf_lsm_v(l)%aldir(ind_type,m) =                  &
2600                                          albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2601                         IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2602                              albedo_pars_f%fill )                             &
2603                            surf_lsm_v(l)%aldif(ind_type,m) =                  &
2604                                          albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2605                         IF ( albedo_pars_f%pars_xy(2,j+joff,i+ioff) /=        &
2606                              albedo_pars_f%fill )                             &
2607                            surf_lsm_v(l)%asdir(ind_type,m) =                  &
2608                                          albedo_pars_f%pars_xy(2,j+joff,i+ioff)
2609                         IF ( albedo_pars_f%pars_xy(2,j+joff,i+ioff) /=        &
2610                              albedo_pars_f%fill )                             &
2611                            surf_lsm_v(l)%asdif(ind_type,m) =                  &
2612                                          albedo_pars_f%pars_xy(2,j+joff,i+ioff)
2613                      ENDIF
2614                   ENDDO
2615                ENDDO
2616!
2617!--             For urban surface only if albedo has not been already initialized
2618!--             in the urban-surface model via the ASCII file.
2619                IF ( .NOT. surf_usm_v(l)%albedo_from_ascii )  THEN
2620                   ioff = surf_usm_v(l)%ioff
2621                   joff = surf_usm_v(l)%joff
2622
2623                   DO  m = 1, surf_usm_v(l)%ns
2624                      i = surf_usm_v(l)%i(m)
2625                      j = surf_usm_v(l)%j(m)
2626!
2627!--                   Broadband albedos for wall/green/window surfaces
2628                      DO  ind_type = 0, 2
2629                         IF ( surf_usm_v(l)%albedo_type(ind_type,m) == 0 )  THEN
2630                            IF ( albedo_pars_f%pars_xy(0,j+joff,i+ioff) /=     &
2631                                 albedo_pars_f%fill )                          &
2632                               surf_usm_v(l)%albedo(ind_type,m) =              &
2633                                             albedo_pars_f%pars_xy(0,j+joff,i+ioff)
2634                         ENDIF
2635                      ENDDO
2636!
2637!--                   Spectral albedos especially for building wall surfaces
2638                      IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=           &
2639                           albedo_pars_f%fill )  THEN
2640                         surf_usm_v(l)%aldir(ind_veg_wall,m) =                 &
2641                                         albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2642                         surf_usm_v(l)%aldif(ind_veg_wall,m) =                 &
2643                                         albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2644                      ENDIF
2645                      IF ( albedo_pars_f%pars_xy(2,j+joff,i+ioff) /=           &
2646                           albedo_pars_f%fill )  THEN
2647                         surf_usm_v(l)%asdir(ind_veg_wall,m) =                 &
2648                                         albedo_pars_f%pars_xy(2,j+joff,i+ioff)
2649                         surf_usm_v(l)%asdif(ind_veg_wall,m) =                 &
2650                                         albedo_pars_f%pars_xy(2,j+joff,i+ioff)
2651                      ENDIF
2652!                     
2653!--                   Spectral albedos especially for building green surfaces
2654                      IF ( albedo_pars_f%pars_xy(3,j+joff,i+ioff) /=           &
2655                           albedo_pars_f%fill )  THEN
2656                         surf_usm_v(l)%aldir(ind_pav_green,m) =                &
2657                                         albedo_pars_f%pars_xy(3,j+joff,i+ioff)
2658                         surf_usm_v(l)%aldif(ind_pav_green,m) =                &
2659                                         albedo_pars_f%pars_xy(3,j+joff,i+ioff)
2660                      ENDIF
2661                      IF ( albedo_pars_f%pars_xy(4,j+joff,i+ioff) /=           &
2662                           albedo_pars_f%fill )  THEN
2663                         surf_usm_v(l)%asdir(ind_pav_green,m) =                &
2664                                         albedo_pars_f%pars_xy(4,j+joff,i+ioff)
2665                         surf_usm_v(l)%asdif(ind_pav_green,m) =                &
2666                                         albedo_pars_f%pars_xy(4,j+joff,i+ioff)
2667                      ENDIF
2668!                     
2669!--                   Spectral albedos especially for building window surfaces
2670                      IF ( albedo_pars_f%pars_xy(5,j+joff,i+ioff) /=           &
2671                           albedo_pars_f%fill )  THEN
2672                         surf_usm_v(l)%aldir(ind_wat_win,m) =                  &
2673                                         albedo_pars_f%pars_xy(5,j+joff,i+ioff)
2674                         surf_usm_v(l)%aldif(ind_wat_win,m) =                  &
2675                                         albedo_pars_f%pars_xy(5,j+joff,i+ioff)
2676                      ENDIF
2677                      IF ( albedo_pars_f%pars_xy(6,j+joff,i+ioff) /=           &
2678                           albedo_pars_f%fill )  THEN
2679                         surf_usm_v(l)%asdir(ind_wat_win,m) =                  &
2680                                         albedo_pars_f%pars_xy(6,j+joff,i+ioff)
2681                         surf_usm_v(l)%asdif(ind_wat_win,m) =                  &
2682                                         albedo_pars_f%pars_xy(6,j+joff,i+ioff)
2683                      ENDIF
2684                   ENDDO
2685                ENDIF
2686             ENDDO
2687
2688          ENDIF
2689
2690!
2691!--       Calculate initial values of current (cosine of) the zenith angle and
2692!--       whether the sun is up
2693          CALL calc_zenith
2694!
2695!--       readjust date and time to its initial value
2696          CALL init_date_and_time
2697!
2698!--       Calculate initial surface albedo for different surfaces
2699          IF ( .NOT. constant_albedo )  THEN
2700#if defined( __netcdf )
2701!
2702!--          Horizontally aligned natural and urban surfaces
2703             CALL calc_albedo( surf_lsm_h )
2704             CALL calc_albedo( surf_usm_h )
2705!
2706!--          Vertically aligned natural and urban surfaces
2707             DO  l = 0, 3
2708                CALL calc_albedo( surf_lsm_v(l) )
2709                CALL calc_albedo( surf_usm_v(l) )
2710             ENDDO
2711#endif
2712          ELSE
2713!
2714!--          Initialize sun-inclination independent spectral albedos
2715!--          Horizontal surfaces
2716             IF ( surf_lsm_h%ns > 0 )  THEN
2717                surf_lsm_h%rrtm_aldir = surf_lsm_h%aldir
2718                surf_lsm_h%rrtm_asdir = surf_lsm_h%asdir
2719                surf_lsm_h%rrtm_aldif = surf_lsm_h%aldif
2720                surf_lsm_h%rrtm_asdif = surf_lsm_h%asdif
2721             ENDIF
2722             IF ( surf_usm_h%ns > 0 )  THEN
2723                surf_usm_h%rrtm_aldir = surf_usm_h%aldir
2724                surf_usm_h%rrtm_asdir = surf_usm_h%asdir
2725                surf_usm_h%rrtm_aldif = surf_usm_h%aldif
2726                surf_usm_h%rrtm_asdif = surf_usm_h%asdif
2727             ENDIF
2728!
2729!--          Vertical surfaces
2730             DO  l = 0, 3
2731                IF ( surf_lsm_v(l)%ns > 0 )  THEN
2732                   surf_lsm_v(l)%rrtm_aldir = surf_lsm_v(l)%aldir
2733                   surf_lsm_v(l)%rrtm_asdir = surf_lsm_v(l)%asdir
2734                   surf_lsm_v(l)%rrtm_aldif = surf_lsm_v(l)%aldif
2735                   surf_lsm_v(l)%rrtm_asdif = surf_lsm_v(l)%asdif
2736                ENDIF
2737                IF ( surf_usm_v(l)%ns > 0 )  THEN
2738                   surf_usm_v(l)%rrtm_aldir = surf_usm_v(l)%aldir
2739                   surf_usm_v(l)%rrtm_asdir = surf_usm_v(l)%asdir
2740                   surf_usm_v(l)%rrtm_aldif = surf_usm_v(l)%aldif
2741                   surf_usm_v(l)%rrtm_asdif = surf_usm_v(l)%asdif
2742                ENDIF
2743             ENDDO
2744
2745          ENDIF
2746
2747!
2748!--       Allocate 3d arrays of radiative fluxes and heating rates
2749          IF ( .NOT. ALLOCATED ( rad_sw_in ) )  THEN
2750             ALLOCATE ( rad_sw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2751             rad_sw_in = 0.0_wp
2752          ENDIF
2753
2754          IF ( .NOT. ALLOCATED ( rad_sw_in_av ) )  THEN
2755             ALLOCATE ( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2756          ENDIF
2757
2758          IF ( .NOT. ALLOCATED ( rad_sw_out ) )  THEN
2759             ALLOCATE ( rad_sw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2760             rad_sw_out = 0.0_wp
2761          ENDIF
2762
2763          IF ( .NOT. ALLOCATED ( rad_sw_out_av ) )  THEN
2764             ALLOCATE ( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2765          ENDIF
2766
2767          IF ( .NOT. ALLOCATED ( rad_sw_hr ) )  THEN
2768             ALLOCATE ( rad_sw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2769             rad_sw_hr = 0.0_wp
2770          ENDIF
2771
2772          IF ( .NOT. ALLOCATED ( rad_sw_hr_av ) )  THEN
2773             ALLOCATE ( rad_sw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2774             rad_sw_hr_av = 0.0_wp
2775          ENDIF
2776
2777          IF ( .NOT. ALLOCATED ( rad_sw_cs_hr ) )  THEN
2778             ALLOCATE ( rad_sw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2779             rad_sw_cs_hr = 0.0_wp
2780          ENDIF
2781
2782          IF ( .NOT. ALLOCATED ( rad_sw_cs_hr_av ) )  THEN
2783             ALLOCATE ( rad_sw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2784             rad_sw_cs_hr_av = 0.0_wp
2785          ENDIF
2786
2787          IF ( .NOT. ALLOCATED ( rad_lw_in ) )  THEN
2788             ALLOCATE ( rad_lw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2789             rad_lw_in = 0.0_wp
2790          ENDIF
2791
2792          IF ( .NOT. ALLOCATED ( rad_lw_in_av ) )  THEN
2793             ALLOCATE ( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2794          ENDIF
2795
2796          IF ( .NOT. ALLOCATED ( rad_lw_out ) )  THEN
2797             ALLOCATE ( rad_lw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2798            rad_lw_out = 0.0_wp
2799          ENDIF
2800
2801          IF ( .NOT. ALLOCATED ( rad_lw_out_av ) )  THEN
2802             ALLOCATE ( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2803          ENDIF
2804
2805          IF ( .NOT. ALLOCATED ( rad_lw_hr ) )  THEN
2806             ALLOCATE ( rad_lw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2807             rad_lw_hr = 0.0_wp
2808          ENDIF
2809
2810          IF ( .NOT. ALLOCATED ( rad_lw_hr_av ) )  THEN
2811             ALLOCATE ( rad_lw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2812             rad_lw_hr_av = 0.0_wp
2813          ENDIF
2814
2815          IF ( .NOT. ALLOCATED ( rad_lw_cs_hr ) )  THEN
2816             ALLOCATE ( rad_lw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2817             rad_lw_cs_hr = 0.0_wp
2818          ENDIF
2819
2820          IF ( .NOT. ALLOCATED ( rad_lw_cs_hr_av ) )  THEN
2821             ALLOCATE ( rad_lw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2822             rad_lw_cs_hr_av = 0.0_wp
2823          ENDIF
2824
2825          ALLOCATE ( rad_sw_cs_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2826          ALLOCATE ( rad_sw_cs_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2827          rad_sw_cs_in  = 0.0_wp
2828          rad_sw_cs_out = 0.0_wp
2829
2830          ALLOCATE ( rad_lw_cs_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2831          ALLOCATE ( rad_lw_cs_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2832          rad_lw_cs_in  = 0.0_wp
2833          rad_lw_cs_out = 0.0_wp
2834
2835!
2836!--       Allocate 1-element array for surface temperature
2837!--       (RRTMG anticipates an array as passed argument).
2838          ALLOCATE ( rrtm_tsfc(1) )
2839!
2840!--       Allocate surface emissivity.
2841!--       Values will be given directly before calling rrtm_lw.
2842          ALLOCATE ( rrtm_emis(0:0,1:nbndlw+1) )
2843
2844!
2845!--       Initialize RRTMG, before check if files are existent
2846          INQUIRE( FILE='rrtmg_lw.nc', EXIST=lw_exists )
2847          IF ( .NOT. lw_exists )  THEN
2848             message_string = 'Input file rrtmg_lw.nc' //                &
2849                            '&for rrtmg missing. ' // &
2850                            '&Please provide <jobname>_lsw file in the INPUT directory.'
2851             CALL message( 'radiation_init', 'PA0583', 1, 2, 0, 6, 0 )
2852          ENDIF         
2853          INQUIRE( FILE='rrtmg_sw.nc', EXIST=sw_exists )
2854          IF ( .NOT. sw_exists )  THEN
2855             message_string = 'Input file rrtmg_sw.nc' //                &
2856                            '&for rrtmg missing. ' // &
2857                            '&Please provide <jobname>_rsw file in the INPUT directory.'
2858             CALL message( 'radiation_init', 'PA0584', 1, 2, 0, 6, 0 )
2859          ENDIF         
2860         
2861          IF ( lw_radiation )  CALL rrtmg_lw_ini ( c_p )
2862          IF ( sw_radiation )  CALL rrtmg_sw_ini ( c_p )
2863         
2864!
2865!--       Set input files for RRTMG
2866          INQUIRE(FILE="RAD_SND_DATA", EXIST=snd_exists) 
2867          IF ( .NOT. snd_exists )  THEN
2868             rrtm_input_file = "rrtmg_lw.nc"
2869          ENDIF
2870
2871!
2872!--       Read vertical layers for RRTMG from sounding data
2873!--       The routine provides nzt_rad, hyp_snd(1:nzt_rad),
2874!--       t_snd(nzt+2:nzt_rad), rrtm_play(1:nzt_rad), rrtm_plev(1_nzt_rad+1),
2875!--       rrtm_tlay(nzt+2:nzt_rad), rrtm_tlev(nzt+2:nzt_rad+1)
2876          CALL read_sounding_data
2877
2878!
2879!--       Read trace gas profiles from file. This routine provides
2880!--       the rrtm_ arrays (1:nzt_rad+1)
2881          CALL read_trace_gas_data
2882#endif
2883       ENDIF
2884
2885!
2886!--    Perform user actions if required
2887       CALL user_init_radiation
2888
2889!
2890!--    Calculate radiative fluxes at model start
2891       SELECT CASE ( TRIM( radiation_scheme ) )
2892
2893          CASE ( 'rrtmg' )
2894             CALL radiation_rrtmg
2895
2896          CASE ( 'clear-sky' )
2897             CALL radiation_clearsky
2898
2899          CASE ( 'constant' )
2900             CALL radiation_constant
2901
2902          CASE DEFAULT
2903
2904       END SELECT
2905
2906! readjust date and time to its initial value
2907       CALL init_date_and_time
2908
2909!
2910!--    Find all discretized apparent solar positions for radiation interaction.
2911       IF ( radiation_interactions )  CALL radiation_presimulate_solar_pos
2912
2913!
2914!--    If required, read or calculate and write out the SVF
2915       IF ( radiation_interactions .AND. read_svf)  THEN
2916!
2917!--       Read sky-view factors and further required data from file
2918          CALL radiation_read_svf()
2919
2920       ELSEIF ( radiation_interactions .AND. .NOT. read_svf)  THEN
2921!
2922!--       calculate SFV and CSF
2923          CALL radiation_calc_svf()
2924       ENDIF
2925
2926       IF ( radiation_interactions .AND. write_svf)  THEN
2927!
2928!--       Write svf, csf svfsurf and csfsurf data to file
2929          CALL radiation_write_svf()
2930       ENDIF
2931
2932!
2933!--    Adjust radiative fluxes. In case of urban and land surfaces, also
2934!--    call an initial interaction.
2935       IF ( radiation_interactions )  THEN
2936          CALL radiation_interaction
2937       ENDIF
2938
2939       IF ( debug_output )  CALL debug_message( 'radiation_init', 'end' )
2940
2941       RETURN !todo: remove, I don't see what we need this for here
2942
2943    END SUBROUTINE radiation_init
2944
2945
2946!------------------------------------------------------------------------------!
2947! Description:
2948! ------------
2949!> A simple clear sky radiation model
2950!------------------------------------------------------------------------------!
2951    SUBROUTINE radiation_clearsky
2952
2953
2954       IMPLICIT NONE
2955
2956       INTEGER(iwp) ::  l         !< running index for surface orientation
2957       REAL(wp)     ::  pt1       !< potential temperature at first grid level or mean value at urban layer top
2958       REAL(wp)     ::  pt1_l     !< potential temperature at first grid level or mean value at urban layer top at local subdomain
2959       REAL(wp)     ::  ql1       !< liquid water mixing ratio at first grid level or mean value at urban layer top
2960       REAL(wp)     ::  ql1_l     !< liquid water mixing ratio at first grid level or mean value at urban layer top at local subdomain
2961
2962       TYPE(surf_type), POINTER ::  surf !< pointer on respective surface type, used to generalize routine   
2963
2964!
2965!--    Calculate current zenith angle
2966       CALL calc_zenith
2967
2968!
2969!--    Calculate sky transmissivity
2970       sky_trans = 0.6_wp + 0.2_wp * cos_zenith
2971
2972!
2973!--    Calculate value of the Exner function at model surface
2974!
2975!--    In case averaged radiation is used, calculate mean temperature and
2976!--    liquid water mixing ratio at the urban-layer top.
2977       IF ( average_radiation ) THEN
2978          pt1   = 0.0_wp
2979          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1   = 0.0_wp
2980
2981          pt1_l = SUM( pt(nz_urban_t,nys:nyn,nxl:nxr) )
2982          IF ( bulk_cloud_model  .OR.  cloud_droplets  )  ql1_l = SUM( ql(nz_urban_t,nys:nyn,nxl:nxr) )
2983
2984#if defined( __parallel )     
2985          IF ( collective_wait )  CALL MPI_BARRIER( comm2d, ierr )
2986          CALL MPI_ALLREDUCE( pt1_l, pt1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
2987          IF ( ierr /= 0 ) THEN
2988              WRITE(9,*) 'Error MPI_AllReduce1:', ierr, pt1_l, pt1
2989              FLUSH(9)
2990          ENDIF
2991
2992          IF ( bulk_cloud_model  .OR.  cloud_droplets ) THEN
2993              CALL MPI_ALLREDUCE( ql1_l, ql1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
2994              IF ( ierr /= 0 ) THEN
2995                  WRITE(9,*) 'Error MPI_AllReduce2:', ierr, ql1_l, ql1
2996                  FLUSH(9)
2997              ENDIF
2998          ENDIF
2999#else
3000          pt1 = pt1_l 
3001          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1 = ql1_l
3002#endif
3003
3004          IF ( bulk_cloud_model  .OR.  cloud_droplets  )  pt1 = pt1 + lv_d_cp / exner(nz_urban_t) * ql1
3005!
3006!--       Finally, divide by number of grid points
3007          pt1 = pt1 / REAL( ( nx + 1 ) * ( ny + 1 ), KIND=wp )
3008       ENDIF
3009!
3010!--    Call clear-sky calculation for each surface orientation.
3011!--    First, horizontal surfaces
3012       surf => surf_lsm_h
3013       CALL radiation_clearsky_surf
3014       surf => surf_usm_h
3015       CALL radiation_clearsky_surf
3016!
3017!--    Vertical surfaces
3018       DO  l = 0, 3
3019          surf => surf_lsm_v(l)
3020          CALL radiation_clearsky_surf
3021          surf => surf_usm_v(l)
3022          CALL radiation_clearsky_surf
3023       ENDDO
3024
3025       CONTAINS
3026
3027          SUBROUTINE radiation_clearsky_surf
3028
3029             IMPLICIT NONE
3030
3031             INTEGER(iwp) ::  i         !< index x-direction
3032             INTEGER(iwp) ::  j         !< index y-direction
3033             INTEGER(iwp) ::  k         !< index z-direction
3034             INTEGER(iwp) ::  m         !< running index for surface elements
3035
3036             IF ( surf%ns < 1 )  RETURN
3037
3038!
3039!--          Calculate radiation fluxes and net radiation (rad_net) assuming
3040!--          homogeneous urban radiation conditions.
3041             IF ( average_radiation ) THEN       
3042
3043                k = nz_urban_t
3044
3045                surf%rad_sw_in  = solar_constant * sky_trans * cos_zenith
3046                surf%rad_sw_out = albedo_urb * surf%rad_sw_in
3047               
3048                surf%rad_lw_in  = emissivity_atm_clsky * sigma_sb * (pt1 * exner(k+1))**4
3049
3050                surf%rad_lw_out = emissivity_urb * sigma_sb * (t_rad_urb)**4   &
3051                                    + (1.0_wp - emissivity_urb) * surf%rad_lw_in
3052
3053                surf%rad_net = surf%rad_sw_in - surf%rad_sw_out                &
3054                             + surf%rad_lw_in - surf%rad_lw_out
3055
3056                surf%rad_lw_out_change_0 = 4.0_wp * emissivity_urb * sigma_sb  &
3057                                           * (t_rad_urb)**3
3058
3059!
3060!--          Calculate radiation fluxes and net radiation (rad_net) for each surface
3061!--          element.
3062             ELSE
3063
3064                DO  m = 1, surf%ns
3065                   i = surf%i(m)
3066                   j = surf%j(m)
3067                   k = surf%k(m)
3068
3069                   surf%rad_sw_in(m) = solar_constant * sky_trans * cos_zenith
3070
3071!
3072!--                Weighted average according to surface fraction.
3073!--                ATTENTION: when radiation interactions are switched on the
3074!--                calculated fluxes below are not actually used as they are
3075!--                overwritten in radiation_interaction.
3076                   surf%rad_sw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
3077                                          surf%albedo(ind_veg_wall,m)          &
3078                                        + surf%frac(ind_pav_green,m) *         &
3079                                          surf%albedo(ind_pav_green,m)         &
3080                                        + surf%frac(ind_wat_win,m)   *         &
3081                                          surf%albedo(ind_wat_win,m) )         &
3082                                        * surf%rad_sw_in(m)
3083
3084                   surf%rad_lw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
3085                                          surf%emissivity(ind_veg_wall,m)      &
3086                                        + surf%frac(ind_pav_green,m) *         &
3087                                          surf%emissivity(ind_pav_green,m)     &
3088                                        + surf%frac(ind_wat_win,m)   *         &
3089                                          surf%emissivity(ind_wat_win,m)       &
3090                                        )                                      &
3091                                        * sigma_sb                             &
3092                                        * ( surf%pt_surface(m) * exner(nzb) )**4
3093
3094                   surf%rad_lw_out_change_0(m) =                               &
3095                                      ( surf%frac(ind_veg_wall,m)  *           &
3096                                        surf%emissivity(ind_veg_wall,m)        &
3097                                      + surf%frac(ind_pav_green,m) *           &
3098                                        surf%emissivity(ind_pav_green,m)       &
3099                                      + surf%frac(ind_wat_win,m)   *           &
3100                                        surf%emissivity(ind_wat_win,m)         &
3101                                      ) * 4.0_wp * sigma_sb                    &
3102                                      * ( surf%pt_surface(m) * exner(nzb) )** 3
3103
3104
3105                   IF ( bulk_cloud_model  .OR.  cloud_droplets  )  THEN
3106                      pt1 = pt(k,j,i) + lv_d_cp / exner(k) * ql(k,j,i)
3107                      surf%rad_lw_in(m)  = emissivity_atm_clsky * sigma_sb * (pt1 * exner(k))**4
3108                   ELSE
3109                      surf%rad_lw_in(m)  = emissivity_atm_clsky * sigma_sb * (pt(k,j,i) * exner(k))**4
3110                   ENDIF
3111
3112                   surf%rad_net(m) = surf%rad_sw_in(m) - surf%rad_sw_out(m)    &
3113                                   + surf%rad_lw_in(m) - surf%rad_lw_out(m)
3114
3115                ENDDO
3116
3117             ENDIF
3118
3119!
3120!--          Fill out values in radiation arrays
3121             DO  m = 1, surf%ns
3122                i = surf%i(m)
3123                j = surf%j(m)
3124                rad_sw_in(0,j,i) = surf%rad_sw_in(m)
3125                rad_sw_out(0,j,i) = surf%rad_sw_out(m)
3126                rad_lw_in(0,j,i) = surf%rad_lw_in(m)
3127                rad_lw_out(0,j,i) = surf%rad_lw_out(m)
3128             ENDDO
3129 
3130          END SUBROUTINE radiation_clearsky_surf
3131
3132    END SUBROUTINE radiation_clearsky
3133
3134
3135!------------------------------------------------------------------------------!
3136! Description:
3137! ------------
3138!> This scheme keeps the prescribed net radiation constant during the run
3139!------------------------------------------------------------------------------!
3140    SUBROUTINE radiation_constant
3141
3142
3143       IMPLICIT NONE
3144
3145       INTEGER(iwp) ::  l         !< running index for surface orientation
3146
3147       REAL(wp)     ::  pt1       !< potential temperature at first grid level or mean value at urban layer top
3148       REAL(wp)     ::  pt1_l     !< potential temperature at first grid level or mean value at urban layer top at local subdomain
3149       REAL(wp)     ::  ql1       !< liquid water mixing ratio at first grid level or mean value at urban layer top
3150       REAL(wp)     ::  ql1_l     !< liquid water mixing ratio at first grid level or mean value at urban layer top at local subdomain
3151
3152       TYPE(surf_type), POINTER ::  surf !< pointer on respective surface type, used to generalize routine
3153
3154!
3155!--    In case averaged radiation is used, calculate mean temperature and
3156!--    liquid water mixing ratio at the urban-layer top.
3157       IF ( average_radiation ) THEN   
3158          pt1   = 0.0_wp
3159          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1   = 0.0_wp
3160
3161          pt1_l = SUM( pt(nz_urban_t,nys:nyn,nxl:nxr) )
3162          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1_l = SUM( ql(nz_urban_t,nys:nyn,nxl:nxr) )
3163
3164#if defined( __parallel )     
3165          IF ( collective_wait )  CALL MPI_BARRIER( comm2d, ierr )
3166          CALL MPI_ALLREDUCE( pt1_l, pt1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
3167          IF ( ierr /= 0 ) THEN
3168              WRITE(9,*) 'Error MPI_AllReduce3:', ierr, pt1_l, pt1
3169              FLUSH(9)
3170          ENDIF
3171          IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
3172             CALL MPI_ALLREDUCE( ql1_l, ql1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
3173             IF ( ierr /= 0 ) THEN
3174                 WRITE(9,*) 'Error MPI_AllReduce4:', ierr, ql1_l, ql1
3175                 FLUSH(9)
3176             ENDIF
3177          ENDIF
3178#else
3179          pt1 = pt1_l
3180          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1 = ql1_l
3181#endif
3182          IF ( bulk_cloud_model  .OR.  cloud_droplets )  pt1 = pt1 + lv_d_cp / exner(nz_urban_t+1) * ql1
3183!
3184!--       Finally, divide by number of grid points
3185          pt1 = pt1 / REAL( ( nx + 1 ) * ( ny + 1 ), KIND=wp )
3186       ENDIF
3187
3188!
3189!--    First, horizontal surfaces
3190       surf => surf_lsm_h
3191       CALL radiation_constant_surf
3192       surf => surf_usm_h
3193       CALL radiation_constant_surf
3194!
3195!--    Vertical surfaces
3196       DO  l = 0, 3
3197          surf => surf_lsm_v(l)
3198          CALL radiation_constant_surf
3199          surf => surf_usm_v(l)
3200          CALL radiation_constant_surf
3201       ENDDO
3202
3203       CONTAINS
3204
3205          SUBROUTINE radiation_constant_surf
3206
3207             IMPLICIT NONE
3208
3209             INTEGER(iwp) ::  i         !< index x-direction
3210             INTEGER(iwp) ::  ioff      !< offset between surface element and adjacent grid point along x
3211             INTEGER(iwp) ::  j         !< index y-direction
3212             INTEGER(iwp) ::  joff      !< offset between surface element and adjacent grid point along y
3213             INTEGER(iwp) ::  k         !< index z-direction
3214             INTEGER(iwp) ::  koff      !< offset between surface element and adjacent grid point along z
3215             INTEGER(iwp) ::  m         !< running index for surface elements
3216
3217             IF ( surf%ns < 1 )  RETURN
3218
3219!--          Calculate homogenoeus urban radiation fluxes
3220             IF ( average_radiation ) THEN
3221
3222                surf%rad_net = net_radiation
3223
3224                surf%rad_lw_in  = emissivity_atm_clsky * sigma_sb * (pt1 * exner(nz_urban_t+1))**4
3225
3226                surf%rad_lw_out = emissivity_urb * sigma_sb * (t_rad_urb)**4   &
3227                                    + ( 1.0_wp - emissivity_urb )             & ! shouldn't be this a bulk value -- emissivity_urb?
3228                                    * surf%rad_lw_in
3229
3230                surf%rad_lw_out_change_0 = 4.0_wp * emissivity_urb * sigma_sb  &
3231                                           * t_rad_urb**3
3232
3233                surf%rad_sw_in = ( surf%rad_net - surf%rad_lw_in               &
3234                                     + surf%rad_lw_out )                       &
3235                                     / ( 1.0_wp - albedo_urb )
3236
3237                surf%rad_sw_out =  albedo_urb * surf%rad_sw_in
3238
3239!
3240!--          Calculate radiation fluxes for each surface element
3241             ELSE
3242!
3243!--             Determine index offset between surface element and adjacent
3244!--             atmospheric grid point
3245                ioff = surf%ioff
3246                joff = surf%joff
3247                koff = surf%koff
3248
3249!
3250!--             Prescribe net radiation and estimate the remaining radiative fluxes
3251                DO  m = 1, surf%ns
3252                   i = surf%i(m)
3253                   j = surf%j(m)
3254                   k = surf%k(m)
3255
3256                   surf%rad_net(m) = net_radiation
3257
3258                   IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
3259                      pt1 = pt(k,j,i) + lv_d_cp / exner(k) * ql(k,j,i)
3260                      surf%rad_lw_in(m)  = emissivity_atm_clsky * sigma_sb * (pt1 * exner(k))**4
3261                   ELSE
3262                      surf%rad_lw_in(m)  = emissivity_atm_clsky * sigma_sb *                 &
3263                                             ( pt(k,j,i) * exner(k) )**4
3264                   ENDIF
3265
3266!
3267!--                Weighted average according to surface fraction.
3268                   surf%rad_lw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
3269                                          surf%emissivity(ind_veg_wall,m)      &
3270                                        + surf%frac(ind_pav_green,m) *         &
3271                                          surf%emissivity(ind_pav_green,m)     &
3272                                        + surf%frac(ind_wat_win,m)   *         &
3273                                          surf%emissivity(ind_wat_win,m)       &
3274                                        )                                      &
3275                                      * sigma_sb                               &
3276                                      * ( surf%pt_surface(m) * exner(nzb) )**4
3277
3278                   surf%rad_sw_in(m) = ( surf%rad_net(m) - surf%rad_lw_in(m)   &
3279                                       + surf%rad_lw_out(m) )                  &
3280                                       / ( 1.0_wp -                            &
3281                                          ( surf%frac(ind_veg_wall,m)  *       &
3282                                            surf%albedo(ind_veg_wall,m)        &
3283                                         +  surf%frac(ind_pav_green,m) *       &
3284                                            surf%albedo(ind_pav_green,m)       &
3285                                         +  surf%frac(ind_wat_win,m)   *       &
3286                                            surf%albedo(ind_wat_win,m) )       &
3287                                         )
3288
3289                   surf%rad_sw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
3290                                          surf%albedo(ind_veg_wall,m)          &
3291                                        + surf%frac(ind_pav_green,m) *         &
3292                                          surf%albedo(ind_pav_green,m)         &
3293                                        + surf%frac(ind_wat_win,m)   *         &
3294                                          surf%albedo(ind_wat_win,m) )         &
3295                                      * surf%rad_sw_in(m)
3296
3297                ENDDO
3298
3299             ENDIF
3300
3301!
3302!--          Fill out values in radiation arrays
3303             DO  m = 1, surf%ns
3304                i = surf%i(m)
3305                j = surf%j(m)
3306                rad_sw_in(0,j,i) = surf%rad_sw_in(m)
3307                rad_sw_out(0,j,i) = surf%rad_sw_out(m)
3308                rad_lw_in(0,j,i) = surf%rad_lw_in(m)
3309                rad_lw_out(0,j,i) = surf%rad_lw_out(m)
3310             ENDDO
3311
3312          END SUBROUTINE radiation_constant_surf
3313         
3314
3315    END SUBROUTINE radiation_constant
3316
3317!------------------------------------------------------------------------------!
3318! Description:
3319! ------------
3320!> Header output for radiation model
3321!------------------------------------------------------------------------------!
3322    SUBROUTINE radiation_header ( io )
3323
3324
3325       IMPLICIT NONE
3326 
3327       INTEGER(iwp), INTENT(IN) ::  io            !< Unit of the output file
3328   
3329
3330       
3331!
3332!--    Write radiation model header
3333       WRITE( io, 3 )
3334
3335       IF ( radiation_scheme == "constant" )  THEN
3336          WRITE( io, 4 ) net_radiation
3337       ELSEIF ( radiation_scheme == "clear-sky" )  THEN
3338          WRITE( io, 5 )
3339       ELSEIF ( radiation_scheme == "rrtmg" )  THEN
3340          WRITE( io, 6 )
3341          IF ( .NOT. lw_radiation )  WRITE( io, 10 )
3342          IF ( .NOT. sw_radiation )  WRITE( io, 11 )
3343       ENDIF
3344
3345       IF ( albedo_type_f%from_file  .OR.  vegetation_type_f%from_file  .OR.   &
3346            pavement_type_f%from_file  .OR.  water_type_f%from_file  .OR.      &
3347            building_type_f%from_file )  THEN
3348             WRITE( io, 13 )
3349       ELSE 
3350          IF ( albedo_type == 0 )  THEN
3351             WRITE( io, 7 ) albedo
3352          ELSE
3353             WRITE( io, 8 ) TRIM( albedo_type_name(albedo_type) )
3354          ENDIF
3355       ENDIF
3356       IF ( constant_albedo )  THEN
3357          WRITE( io, 9 )
3358       ENDIF
3359       
3360       WRITE( io, 12 ) dt_radiation
3361 
3362
3363 3 FORMAT (//' Radiation model information:'/                                  &
3364              ' ----------------------------'/)
3365 4 FORMAT ('    --> Using constant net radiation: net_radiation = ', F6.2,     &
3366           // 'W/m**2')
3367 5 FORMAT ('    --> Simple radiation scheme for clear sky is used (no clouds,',&
3368                   ' default)')
3369 6 FORMAT ('    --> RRTMG scheme is used')
3370 7 FORMAT (/'    User-specific surface albedo: albedo =', F6.3)
3371 8 FORMAT (/'    Albedo is set for land surface type: ', A)
3372 9 FORMAT (/'    --> Albedo is fixed during the run')
337310 FORMAT (/'    --> Longwave radiation is disabled')
337411 FORMAT (/'    --> Shortwave radiation is disabled.')
337512 FORMAT  ('    Timestep: dt_radiation = ', F6.2, '  s')
337613 FORMAT (/'    Albedo is set individually for each xy-location, according ', &
3377                 'to given surface type.')
3378
3379
3380    END SUBROUTINE radiation_header
3381   
3382
3383!------------------------------------------------------------------------------!
3384! Description:
3385! ------------
3386!> Parin for &radiation_parameters for radiation model
3387!------------------------------------------------------------------------------!
3388    SUBROUTINE radiation_parin
3389
3390
3391       IMPLICIT NONE
3392
3393       CHARACTER (LEN=80) ::  line  !< dummy string that contains the current line of the parameter file
3394       
3395       NAMELIST /radiation_par/   albedo, albedo_lw_dif, albedo_lw_dir,         &
3396                                  albedo_sw_dif, albedo_sw_dir, albedo_type,    &
3397                                  constant_albedo, dt_radiation, emissivity,    &
3398                                  lw_radiation, max_raytracing_dist,            &
3399                                  min_irrf_value, mrt_geom_human,               &
3400                                  mrt_include_sw, mrt_nlevels,                  &
3401                                  mrt_skip_roof, net_radiation, nrefsteps,      &
3402                                  plant_lw_interact, rad_angular_discretization,&
3403                                  radiation_interactions_on, radiation_scheme,  &
3404                                  raytrace_discrete_azims,                      &
3405                                  raytrace_discrete_elevs, raytrace_mpi_rma,    &
3406                                  skip_time_do_radiation, surface_reflections,  &
3407                                  svfnorm_report_thresh, sw_radiation,          &
3408                                  unscheduled_radiation_calls
3409
3410   
3411       NAMELIST /radiation_parameters/ albedo, albedo_lw_dif, albedo_lw_dir,    &
3412                                  albedo_sw_dif, albedo_sw_dir, albedo_type,    &
3413                                  constant_albedo, dt_radiation, emissivity,    &
3414                                  lw_radiation, max_raytracing_dist,            &
3415                                  min_irrf_value, mrt_geom_human,               &
3416                                  mrt_include_sw, mrt_nlevels,                  &
3417                                  mrt_skip_roof, net_radiation, nrefsteps,      &
3418                                  plant_lw_interact, rad_angular_discretization,&
3419                                  radiation_interactions_on, radiation_scheme,  &
3420                                  raytrace_discrete_azims,                      &
3421                                  raytrace_discrete_elevs, raytrace_mpi_rma,    &
3422                                  skip_time_do_radiation, surface_reflections,  &
3423                                  svfnorm_report_thresh, sw_radiation,          &
3424                                  unscheduled_radiation_calls
3425   
3426       line = ' '
3427       
3428!
3429!--    Try to find radiation model namelist
3430       REWIND ( 11 )
3431       line = ' '
3432       DO WHILE ( INDEX( line, '&radiation_parameters' ) == 0 )
3433          READ ( 11, '(A)', END=12 )  line
3434       ENDDO
3435       BACKSPACE ( 11 )
3436
3437!
3438!--    Read user-defined namelist
3439       READ ( 11, radiation_parameters, ERR = 10 )
3440
3441!
3442!--    Set flag that indicates that the radiation model is switched on
3443       radiation = .TRUE.
3444
3445       GOTO 14
3446
3447 10    BACKSPACE( 11 )
3448       READ( 11 , '(A)') line
3449       CALL parin_fail_message( 'radiation_parameters', line )
3450!
3451!--    Try to find old namelist
3452 12    REWIND ( 11 )
3453       line = ' '
3454       DO WHILE ( INDEX( line, '&radiation_par' ) == 0 )
3455          READ ( 11, '(A)', END=14 )  line
3456       ENDDO
3457       BACKSPACE ( 11 )
3458
3459!
3460!--    Read user-defined namelist
3461       READ ( 11, radiation_par, ERR = 13, END = 14 )
3462
3463       message_string = 'namelist radiation_par is deprecated and will be ' // &
3464                     'removed in near future. Please use namelist ' //         &
3465                     'radiation_parameters instead'
3466       CALL message( 'radiation_parin', 'PA0487', 0, 1, 0, 6, 0 )
3467
3468!
3469!--    Set flag that indicates that the radiation model is switched on
3470       radiation = .TRUE.
3471
3472       IF ( .NOT.  radiation_interactions_on  .AND.  surface_reflections )  THEN
3473          message_string = 'surface_reflections is allowed only when '      // &
3474               'radiation_interactions_on is set to TRUE'
3475          CALL message( 'radiation_parin', 'PA0293',1, 2, 0, 6, 0 )
3476       ENDIF
3477
3478       GOTO 14
3479
3480 13    BACKSPACE( 11 )
3481       READ( 11 , '(A)') line
3482       CALL parin_fail_message( 'radiation_par', line )
3483
3484 14    CONTINUE
3485       
3486    END SUBROUTINE radiation_parin
3487
3488
3489!------------------------------------------------------------------------------!
3490! Description:
3491! ------------
3492!> Implementation of the RRTMG radiation_scheme
3493!------------------------------------------------------------------------------!
3494    SUBROUTINE radiation_rrtmg
3495
3496#if defined ( __rrtmg )
3497       USE indices,                                                            &
3498           ONLY:  nbgp
3499
3500       USE particle_attributes,                                                &
3501           ONLY:  grid_particles, number_of_particles, particles, prt_count
3502
3503       IMPLICIT NONE
3504
3505
3506       INTEGER(iwp) ::  i, j, k, l, m, n !< loop indices
3507       INTEGER(iwp) ::  k_topo_l   !< topography top index
3508       INTEGER(iwp) ::  k_topo     !< topography top index
3509
3510       REAL(wp)     ::  nc_rad, &    !< number concentration of cloud droplets
3511                        s_r2,   &    !< weighted sum over all droplets with r^2
3512                        s_r3         !< weighted sum over all droplets with r^3
3513
3514       REAL(wp), DIMENSION(0:nzt+1) :: pt_av, q_av, ql_av
3515       REAL(wp), DIMENSION(0:0)     :: zenith   !< to provide indexed array
3516!
3517!--    Just dummy arguments
3518       REAL(wp), DIMENSION(:,:,:), ALLOCATABLE :: rrtm_lw_taucld_dum,          &
3519                                                  rrtm_lw_tauaer_dum,          &
3520                                                  rrtm_sw_taucld_dum,          &
3521                                                  rrtm_sw_ssacld_dum,          &
3522                                                  rrtm_sw_asmcld_dum,          &
3523                                                  rrtm_sw_fsfcld_dum,          &
3524                                                  rrtm_sw_tauaer_dum,          &
3525                                                  rrtm_sw_ssaaer_dum,          &
3526                                                  rrtm_sw_asmaer_dum,          &
3527                                                  rrtm_sw_ecaer_dum
3528
3529!
3530!--    Calculate current (cosine of) zenith angle and whether the sun is up
3531       CALL calc_zenith     
3532       zenith(0) = cos_zenith
3533!
3534!--    Calculate surface albedo. In case average radiation is applied,
3535!--    this is not required.
3536#if defined( __netcdf )
3537       IF ( .NOT. constant_albedo )  THEN
3538!
3539!--       Horizontally aligned default, natural and urban surfaces
3540          CALL calc_albedo( surf_lsm_h    )
3541          CALL calc_albedo( surf_usm_h    )
3542!
3543!--       Vertically aligned default, natural and urban surfaces
3544          DO  l = 0, 3
3545             CALL calc_albedo( surf_lsm_v(l) )
3546             CALL calc_albedo( surf_usm_v(l) )
3547          ENDDO
3548       ENDIF
3549#endif
3550
3551!
3552!--    Prepare input data for RRTMG
3553
3554!
3555!--    In case of large scale forcing with surface data, calculate new pressure
3556!--    profile. nzt_rad might be modified by these calls and all required arrays
3557!--    will then be re-allocated
3558       IF ( large_scale_forcing  .AND.  lsf_surf )  THEN
3559          CALL read_sounding_data
3560          CALL read_trace_gas_data
3561       ENDIF
3562
3563
3564       IF ( average_radiation ) THEN
3565
3566          k_topo_l = MINVAL( get_topography_top_index( 's' ) )
3567#if defined( __parallel )
3568          CALL MPI_ALLREDUCE( k_topo_l, k_topo, 1, MPI_INTEGER, MPI_MIN, &
3569                              comm2d, ierr)
3570#else
3571          k_topo = k_topo_l
3572#endif
3573       
3574          rrtm_asdir(1)  = albedo_urb
3575          rrtm_asdif(1)  = albedo_urb
3576          rrtm_aldir(1)  = albedo_urb
3577          rrtm_aldif(1)  = albedo_urb
3578
3579          rrtm_emis = emissivity_urb
3580!
3581!--       Calculate mean pt profile.
3582          CALL calc_mean_profile( pt, 4 )
3583          pt_av = hom(:, 1, 4, 0)
3584         
3585          IF ( humidity )  THEN
3586             CALL calc_mean_profile( q, 41 )
3587             q_av  = hom(:, 1, 41, 0)
3588          ENDIF
3589!
3590!--       Prepare profiles of temperature and H2O volume mixing ratio
3591          rrtm_tlev(0,k_topo+1) = t_rad_urb
3592
3593          IF ( bulk_cloud_model )  THEN
3594
3595             CALL calc_mean_profile( ql, 54 )
3596             ! average ql is now in hom(:, 1, 54, 0)
3597             ql_av = hom(:, 1, 54, 0)
3598             
3599             DO k = nzb+1, nzt+1
3600                rrtm_tlay(0,k) = pt_av(k) * ( (hyp(k) ) / 100000._wp       &
3601                                 )**.286_wp + lv_d_cp * ql_av(k)
3602                rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * (q_av(k) - ql_av(k))
3603             ENDDO
3604          ELSE
3605             DO k = nzb+1, nzt+1
3606                rrtm_tlay(0,k) = pt_av(k) * ( (hyp(k) ) / 100000._wp       &
3607                                 )**.286_wp
3608             ENDDO
3609
3610             IF ( humidity )  THEN
3611                DO k = nzb+1, nzt+1
3612                   rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * q_av(k)
3613                ENDDO
3614             ELSE
3615                rrtm_h2ovmr(0,nzb+1:nzt+1) = 0.0_wp
3616             ENDIF
3617          ENDIF
3618
3619!
3620!--       Avoid temperature/humidity jumps at the top of the PALM domain by
3621!--       linear interpolation from nzt+2 to nzt+7. Jumps are induced by
3622!--       discrepancies between the values in the  domain and those above that
3623!--       are prescribed in RRTMG
3624          DO k = nzt+2, nzt+7
3625             rrtm_tlay(0,k) = rrtm_tlay(0,nzt+1)                            &
3626                           + ( rrtm_tlay(0,nzt+8) - rrtm_tlay(0,nzt+1) )    &
3627                           / ( rrtm_play(0,nzt+8) - rrtm_play(0,nzt+1) )    &
3628                           * ( rrtm_play(0,k) - rrtm_play(0,nzt+1) )
3629
3630             rrtm_h2ovmr(0,k) = rrtm_h2ovmr(0,nzt+1)                        &
3631                           + ( rrtm_h2ovmr(0,nzt+8) - rrtm_h2ovmr(0,nzt+1) )&
3632                           / ( rrtm_play(0,nzt+8)   - rrtm_play(0,nzt+1)   )&
3633                           * ( rrtm_play(0,k) - rrtm_play(0,nzt+1) )
3634
3635          ENDDO
3636
3637!--       Linear interpolate to zw grid. Loop reaches one level further up
3638!--       due to the staggered grid in RRTMG
3639          DO k = k_topo+2, nzt+8
3640             rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k) -        &
3641                                rrtm_tlay(0,k-1))                           &
3642                                / ( rrtm_play(0,k) - rrtm_play(0,k-1) )     &
3643                                * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
3644          ENDDO
3645!
3646!--       Calculate liquid water path and cloud fraction for each column.
3647!--       Note that LWP is required in g/m2 instead of kg/kg m.
3648          rrtm_cldfr  = 0.0_wp
3649          rrtm_reliq  = 0.0_wp
3650          rrtm_cliqwp = 0.0_wp
3651          rrtm_icld   = 0
3652
3653          IF ( bulk_cloud_model )  THEN
3654             DO k = nzb+1, nzt+1
3655                rrtm_cliqwp(0,k) =  ql_av(k) * 1000._wp *                   &
3656                                    (rrtm_plev(0,k) - rrtm_plev(0,k+1))     &
3657                                    * 100._wp / g 
3658
3659                IF ( rrtm_cliqwp(0,k) > 0._wp )  THEN
3660                   rrtm_cldfr(0,k) = 1._wp
3661                   IF ( rrtm_icld == 0 )  rrtm_icld = 1
3662
3663!
3664!--                Calculate cloud droplet effective radius
3665                   rrtm_reliq(0,k) = 1.0E6_wp * ( 3.0_wp * ql_av(k)         &
3666                                     * rho_surface                          &
3667                                     / ( 4.0_wp * pi * nc_const * rho_l )   &
3668                                     )**0.33333333333333_wp                 &
3669                                     * EXP( LOG( sigma_gc )**2 )
3670!
3671!--                Limit effective radius
3672                   IF ( rrtm_reliq(0,k) > 0.0_wp )  THEN
3673                      rrtm_reliq(0,k) = MAX(rrtm_reliq(0,k),2.5_wp)
3674                      rrtm_reliq(0,k) = MIN(rrtm_reliq(0,k),60.0_wp)
3675                   ENDIF
3676                ENDIF
3677             ENDDO
3678          ENDIF
3679
3680!
3681!--       Set surface temperature
3682          rrtm_tsfc = t_rad_urb
3683         
3684          IF ( lw_radiation )  THEN 
3685!
3686!--          Due to technical reasons, copy optical depth to dummy arguments
3687!--          which are allocated on the exact size as the rrtmg_lw is called.
3688!--          As one dimesion is allocated with zero size, compiler complains
3689!--          that rank of the array does not match that of the
3690!--          assumed-shaped arguments in the RRTMG library. In order to
3691!--          avoid this, write to dummy arguments and give pass the entire
3692!--          dummy array. Seems to be the only existing work-around. 
3693             ALLOCATE( rrtm_lw_taucld_dum(1:nbndlw+1,0:0,k_topo+1:nzt_rad+1) )
3694             ALLOCATE( rrtm_lw_tauaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndlw+1) )
3695
3696             rrtm_lw_taucld_dum =                                              &
3697                             rrtm_lw_taucld(1:nbndlw+1,0:0,k_topo+1:nzt_rad+1)
3698             rrtm_lw_tauaer_dum =                                              &
3699                             rrtm_lw_tauaer(0:0,k_topo+1:nzt_rad+1,1:nbndlw+1)
3700         
3701!              CALL rrtmg_lw( 1, nzt_rad      , rrtm_icld    , rrtm_idrv      ,&
3702!              rrtm_play       , rrtm_plev    , rrtm_tlay    , rrtm_tlev      ,&
3703!              rrtm_tsfc       , rrtm_h2ovmr  , rrtm_o3vmr   , rrtm_co2vmr    ,&
3704!              rrtm_ch4vmr     , rrtm_n2ovmr  , rrtm_o2vmr   , rrtm_cfc11vmr  ,&
3705!              rrtm_cfc12vmr   , rrtm_cfc22vmr, rrtm_ccl4vmr , rrtm_emis      ,&
3706!              rrtm_inflglw    , rrtm_iceflglw, rrtm_liqflglw, rrtm_cldfr     ,&
3707!              rrtm_lw_taucld  , rrtm_cicewp  , rrtm_cliqwp  , rrtm_reice     ,&
3708!              rrtm_reliq      , rrtm_lw_tauaer,                               &
3709!              rrtm_lwuflx     , rrtm_lwdflx  , rrtm_lwhr  ,                   &
3710!              rrtm_lwuflxc    , rrtm_lwdflxc , rrtm_lwhrc ,                   &
3711!              rrtm_lwuflx_dt  ,  rrtm_lwuflxc_dt )
3712
3713             CALL rrtmg_lw( 1,                                                 &                                       
3714                            nzt_rad-k_topo,                                    &
3715                            rrtm_icld,                                         &
3716                            rrtm_idrv,                                         &
3717                            rrtm_play(:,k_topo+1:),                   &
3718                            rrtm_plev(:,k_topo+1:),                   &
3719                            rrtm_tlay(:,k_topo+1:),                   &
3720                            rrtm_tlev(:,k_topo+1:),                   &
3721                            rrtm_tsfc,                                         &
3722                            rrtm_h2ovmr(:,k_topo+1:),                 &
3723                            rrtm_o3vmr(:,k_topo+1:),                  &
3724                            rrtm_co2vmr(:,k_topo+1:),                 &
3725                            rrtm_ch4vmr(:,k_topo+1:),                 &
3726                            rrtm_n2ovmr(:,k_topo+1:),                 &
3727                            rrtm_o2vmr(:,k_topo+1:),                  &
3728                            rrtm_cfc11vmr(:,k_topo+1:),               &
3729                            rrtm_cfc12vmr(:,k_topo+1:),               &
3730                            rrtm_cfc22vmr(:,k_topo+1:),               &
3731                            rrtm_ccl4vmr(:,k_topo+1:),                &
3732                            rrtm_emis,                                         &
3733                            rrtm_inflglw,                                      &
3734                            rrtm_iceflglw,                                     &
3735                            rrtm_liqflglw,                                     &
3736                            rrtm_cldfr(:,k_topo+1:),                  &
3737                            rrtm_lw_taucld_dum,                                &
3738                            rrtm_cicewp(:,k_topo+1:),                 &
3739                            rrtm_cliqwp(:,k_topo+1:),                 &
3740                            rrtm_reice(:,k_topo+1:),                  & 
3741                            rrtm_reliq(:,k_topo+1:),                  &
3742                            rrtm_lw_tauaer_dum,                                &
3743                            rrtm_lwuflx(:,k_topo:),                   &
3744                            rrtm_lwdflx(:,k_topo:),                   &
3745                            rrtm_lwhr(:,k_topo+1:),                   &
3746                            rrtm_lwuflxc(:,k_topo:),                  &
3747                            rrtm_lwdflxc(:,k_topo:),                  &
3748                            rrtm_lwhrc(:,k_topo+1:),                  &
3749                            rrtm_lwuflx_dt(:,k_topo:),                &
3750                            rrtm_lwuflxc_dt(:,k_topo:) )
3751                           
3752             DEALLOCATE ( rrtm_lw_taucld_dum )
3753             DEALLOCATE ( rrtm_lw_tauaer_dum )
3754!
3755!--          Save fluxes
3756             DO k = nzb, nzt+1
3757                rad_lw_in(k,:,:)  = rrtm_lwdflx(0,k)
3758                rad_lw_out(k,:,:) = rrtm_lwuflx(0,k)
3759             ENDDO
3760             rad_lw_in_diff(:,:) = rad_lw_in(k_topo,:,:)
3761!
3762!--          Save heating rates (convert from K/d to K/h).
3763!--          Further, even though an aggregated radiation is computed, map
3764!--          signle-column profiles on top of any topography, in order to
3765!--          obtain correct near surface radiation heating/cooling rates.
3766             DO  i = nxl, nxr
3767                DO  j = nys, nyn
3768                   k_topo_l = get_topography_top_index_ji( j, i, 's' )
3769                   DO k = k_topo_l+1, nzt+1
3770                      rad_lw_hr(k,j,i)     = rrtm_lwhr(0,k-k_topo_l)  * d_hours_day
3771                      rad_lw_cs_hr(k,j,i)  = rrtm_lwhrc(0,k-k_topo_l) * d_hours_day
3772                   ENDDO
3773                ENDDO
3774             ENDDO
3775
3776          ENDIF
3777
3778          IF ( sw_radiation .AND. sun_up )  THEN
3779!
3780!--          Due to technical reasons, copy optical depths and other
3781!--          to dummy arguments which are allocated on the exact size as the
3782!--          rrtmg_sw is called.
3783!--          As one dimesion is allocated with zero size, compiler complains
3784!--          that rank of the array does not match that of the
3785!--          assumed-shaped arguments in the RRTMG library. In order to
3786!--          avoid this, write to dummy arguments and give pass the entire
3787!--          dummy array. Seems to be the only existing work-around. 
3788             ALLOCATE( rrtm_sw_taucld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3789             ALLOCATE( rrtm_sw_ssacld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3790             ALLOCATE( rrtm_sw_asmcld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3791             ALLOCATE( rrtm_sw_fsfcld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3792             ALLOCATE( rrtm_sw_tauaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3793             ALLOCATE( rrtm_sw_ssaaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3794             ALLOCATE( rrtm_sw_asmaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3795             ALLOCATE( rrtm_sw_ecaer_dum(0:0,k_topo+1:nzt_rad+1,1:naerec+1)  )
3796     
3797             rrtm_sw_taucld_dum = rrtm_sw_taucld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3798             rrtm_sw_ssacld_dum = rrtm_sw_ssacld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3799             rrtm_sw_asmcld_dum = rrtm_sw_asmcld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3800             rrtm_sw_fsfcld_dum = rrtm_sw_fsfcld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3801             rrtm_sw_tauaer_dum = rrtm_sw_tauaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3802             rrtm_sw_ssaaer_dum = rrtm_sw_ssaaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3803             rrtm_sw_asmaer_dum = rrtm_sw_asmaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3804             rrtm_sw_ecaer_dum  = rrtm_sw_ecaer(0:0,k_topo+1:nzt_rad+1,1:naerec+1)
3805!              CALL rrtmg_sw( 1, nzt_rad      , rrtm_icld     , rrtm_iaer      ,&
3806!              rrtm_play      , rrtm_plev     , rrtm_tlay     , rrtm_tlev      ,&
3807!              rrtm_tsfc      , rrtm_h2ovmr   , rrtm_o3vmr    , rrtm_co2vmr    ,&
3808!              rrtm_ch4vmr    , rrtm_n2ovmr   , rrtm_o2vmr    , rrtm_asdir     ,&
3809!              rrtm_asdif     , rrtm_aldir    , rrtm_aldif    , zenith         ,&
3810!              0.0_wp         , day_of_year   , solar_constant, rrtm_inflgsw   ,&
3811!              rrtm_iceflgsw  , rrtm_liqflgsw , rrtm_cldfr    , rrtm_sw_taucld ,&
3812!              rrtm_sw_ssacld , rrtm_sw_asmcld, rrtm_sw_fsfcld, rrtm_cicewp    ,&
3813!              rrtm_cliqwp    , rrtm_reice    , rrtm_reliq    , rrtm_sw_tauaer ,&
3814!              rrtm_sw_ssaaer , rrtm_sw_asmaer, rrtm_sw_ecaer , rrtm_swuflx    ,&
3815!              rrtm_swdflx    , rrtm_swhr     , rrtm_swuflxc  , rrtm_swdflxc   ,&
3816!              rrtm_swhrc     , rrtm_dirdflux , rrtm_difdflux )
3817             CALL rrtmg_sw( 1,                                                 &
3818                            nzt_rad-k_topo,                                    &
3819                            rrtm_icld,                                         &
3820                            rrtm_iaer,                                         &
3821                            rrtm_play(:,k_topo+1:nzt_rad+1),                   &
3822                            rrtm_plev(:,k_topo+1:nzt_rad+2),                   &
3823                            rrtm_tlay(:,k_topo+1:nzt_rad+1),                   &
3824                            rrtm_tlev(:,k_topo+1:nzt_rad+2),                   &
3825                            rrtm_tsfc,                                         &
3826                            rrtm_h2ovmr(:,k_topo+1:nzt_rad+1),                 &                               
3827                            rrtm_o3vmr(:,k_topo+1:nzt_rad+1),                  &       
3828                            rrtm_co2vmr(:,k_topo+1:nzt_rad+1),                 &
3829                            rrtm_ch4vmr(:,k_topo+1:nzt_rad+1),                 &
3830                            rrtm_n2ovmr(:,k_topo+1:nzt_rad+1),                 &
3831                            rrtm_o2vmr(:,k_topo+1:nzt_rad+1),                  &
3832                            rrtm_asdir,                                        & 
3833                            rrtm_asdif,                                        &
3834                            rrtm_aldir,                                        &
3835                            rrtm_aldif,                                        &
3836                            zenith,                                            &
3837                            0.0_wp,                                            &
3838                            day_of_year,                                       &
3839                            solar_constant,                                    &
3840                            rrtm_inflgsw,                                      &
3841                            rrtm_iceflgsw,                                     &
3842                            rrtm_liqflgsw,                                     &
3843                            rrtm_cldfr(:,k_topo+1:nzt_rad+1),                  &
3844                            rrtm_sw_taucld_dum,                                &
3845                            rrtm_sw_ssacld_dum,                                &
3846                            rrtm_sw_asmcld_dum,                                &
3847                            rrtm_sw_fsfcld_dum,                                &
3848                            rrtm_cicewp(:,k_topo+1:nzt_rad+1),                 &
3849                            rrtm_cliqwp(:,k_topo+1:nzt_rad+1),                 &
3850                            rrtm_reice(:,k_topo+1:nzt_rad+1),                  &
3851                            rrtm_reliq(:,k_topo+1:nzt_rad+1),                  &
3852                            rrtm_sw_tauaer_dum,                                &
3853                            rrtm_sw_ssaaer_dum,                                &
3854                            rrtm_sw_asmaer_dum,                                &
3855                            rrtm_sw_ecaer_dum,                                 &
3856                            rrtm_swuflx(:,k_topo:nzt_rad+1),                   & 
3857                            rrtm_swdflx(:,k_topo:nzt_rad+1),                   & 
3858                            rrtm_swhr(:,k_topo+1:nzt_rad+1),                   & 
3859                            rrtm_swuflxc(:,k_topo:nzt_rad+1),                  & 
3860                            rrtm_swdflxc(:,k_topo:nzt_rad+1),                  &
3861                            rrtm_swhrc(:,k_topo+1:nzt_rad+1),                  &
3862                            rrtm_dirdflux(:,k_topo:nzt_rad+1),                 &
3863                            rrtm_difdflux(:,k_topo:nzt_rad+1) )
3864                           
3865             DEALLOCATE( rrtm_sw_taucld_dum )
3866             DEALLOCATE( rrtm_sw_ssacld_dum )
3867             DEALLOCATE( rrtm_sw_asmcld_dum )
3868             DEALLOCATE( rrtm_sw_fsfcld_dum )
3869             DEALLOCATE( rrtm_sw_tauaer_dum )
3870             DEALLOCATE( rrtm_sw_ssaaer_dum )
3871             DEALLOCATE( rrtm_sw_asmaer_dum )
3872             DEALLOCATE( rrtm_sw_ecaer_dum )
3873 
3874!
3875!--          Save fluxes:
3876!--          - whole domain
3877             DO k = nzb, nzt+1
3878                rad_sw_in(k,:,:)  = rrtm_swdflx(0,k)
3879                rad_sw_out(k,:,:) = rrtm_swuflx(0,k)
3880             ENDDO
3881!--          - direct and diffuse SW at urban-surface-layer (required by RTM)
3882             rad_sw_in_dir(:,:) = rrtm_dirdflux(0,k_topo)
3883             rad_sw_in_diff(:,:) = rrtm_difdflux(0,k_topo)
3884
3885!
3886!--          Save heating rates (convert from K/d to K/s)
3887             DO k = nzb+1, nzt+1
3888                rad_sw_hr(k,:,:)     = rrtm_swhr(0,k)  * d_hours_day
3889                rad_sw_cs_hr(k,:,:)  = rrtm_swhrc(0,k) * d_hours_day
3890             ENDDO
3891!
3892!--       Solar radiation is zero during night
3893          ELSE
3894             rad_sw_in  = 0.0_wp
3895             rad_sw_out = 0.0_wp
3896             rad_sw_in_dir(:,:) = 0.0_wp
3897             rad_sw_in_diff(:,:) = 0.0_wp
3898          ENDIF
3899!
3900!--    RRTMG is called for each (j,i) grid point separately, starting at the
3901!--    highest topography level. Here no RTM is used since average_radiation is false
3902       ELSE
3903!
3904!--       Loop over all grid points
3905          DO i = nxl, nxr
3906             DO j = nys, nyn
3907
3908!
3909!--             Prepare profiles of temperature and H2O volume mixing ratio
3910                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
3911                   rrtm_tlev(0,nzb+1) = surf_lsm_h%pt_surface(m) * exner(nzb)
3912                ENDDO
3913                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
3914                   rrtm_tlev(0,nzb+1) = surf_usm_h%pt_surface(m) * exner(nzb)
3915                ENDDO
3916
3917
3918                IF ( bulk_cloud_model )  THEN
3919                   DO k = nzb+1, nzt+1
3920                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)                    &
3921                                        + lv_d_cp * ql(k,j,i)
3922                      rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * (q(k,j,i) - ql(k,j,i))
3923                   ENDDO
3924                ELSEIF ( cloud_droplets )  THEN
3925                   DO k = nzb+1, nzt+1
3926                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)                     &
3927                                        + lv_d_cp * ql(k,j,i)
3928                      rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * q(k,j,i) 
3929                   ENDDO
3930                ELSE
3931                   DO k = nzb+1, nzt+1
3932                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)
3933                   ENDDO
3934
3935                   IF ( humidity )  THEN
3936                      DO k = nzb+1, nzt+1
3937                         rrtm_h2ovmr(0,k) =  mol_mass_air_d_wv * q(k,j,i)
3938                      ENDDO   
3939                   ELSE
3940                      rrtm_h2ovmr(0,nzb+1:nzt+1) = 0.0_wp
3941                   ENDIF
3942                ENDIF
3943
3944!
3945!--             Avoid temperature/humidity jumps at the top of the LES domain by
3946!--             linear interpolation from nzt+2 to nzt+7
3947                DO k = nzt+2, nzt+7
3948                   rrtm_tlay(0,k) = rrtm_tlay(0,nzt+1)                         &
3949                                 + ( rrtm_tlay(0,nzt+8) - rrtm_tlay(0,nzt+1) ) &
3950                                 / ( rrtm_play(0,nzt+8) - rrtm_play(0,nzt+1) ) &
3951                                 * ( rrtm_play(0,k)     - rrtm_play(0,nzt+1) )
3952
3953                   rrtm_h2ovmr(0,k) = rrtm_h2ovmr(0,nzt+1)                     &
3954                              + ( rrtm_h2ovmr(0,nzt+8) - rrtm_h2ovmr(0,nzt+1) )&
3955                              / ( rrtm_play(0,nzt+8)   - rrtm_play(0,nzt+1)   )&
3956                              * ( rrtm_play(0,k)       - rrtm_play(0,nzt+1) )
3957
3958                ENDDO
3959
3960!--             Linear interpolate to zw grid
3961                DO k = nzb+2, nzt+8
3962                   rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k) -     &
3963                                      rrtm_tlay(0,k-1))                        &
3964                                      / ( rrtm_play(0,k) - rrtm_play(0,k-1) )  &
3965                                      * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
3966                ENDDO
3967
3968
3969!
3970!--             Calculate liquid water path and cloud fraction for each column.
3971!--             Note that LWP is required in g/m2 instead of kg/kg m.
3972                rrtm_cldfr  = 0.0_wp
3973                rrtm_reliq  = 0.0_wp
3974                rrtm_cliqwp = 0.0_wp
3975                rrtm_icld   = 0
3976
3977                IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
3978                   DO k = nzb+1, nzt+1
3979                      rrtm_cliqwp(0,k) =  ql(k,j,i) * 1000.0_wp *              &
3980                                          (rrtm_plev(0,k) - rrtm_plev(0,k+1))  &
3981                                          * 100.0_wp / g 
3982
3983                      IF ( rrtm_cliqwp(0,k) > 0.0_wp )  THEN
3984                         rrtm_cldfr(0,k) = 1.0_wp
3985                         IF ( rrtm_icld == 0 )  rrtm_icld = 1
3986
3987!
3988!--                      Calculate cloud droplet effective radius
3989                         IF ( bulk_cloud_model )  THEN
3990!
3991!--                         Calculete effective droplet radius. In case of using
3992!--                         cloud_scheme = 'morrison' and a non reasonable number
3993!--                         of cloud droplets the inital aerosol number 
3994!--                         concentration is considered.
3995                            IF ( microphysics_morrison )  THEN
3996                               IF ( nc(k,j,i) > 1.0E-20_wp )  THEN
3997                                  nc_rad = nc(k,j,i)
3998                               ELSE
3999                                  nc_rad = na_init
4000                               ENDIF
4001                            ELSE
4002                               nc_rad = nc_const
4003                            ENDIF 
4004
4005                            rrtm_reliq(0,k) = 1.0E6_wp * ( 3.0_wp * ql(k,j,i)     &
4006                                              * rho_surface                       &
4007                                              / ( 4.0_wp * pi * nc_rad * rho_l )  &
4008                                              )**0.33333333333333_wp              &
4009                                              * EXP( LOG( sigma_gc )**2 )
4010
4011                         ELSEIF ( cloud_droplets )  THEN
4012                            number_of_particles = prt_count(k,j,i)
4013
4014                            IF (number_of_particles <= 0)  CYCLE
4015                            particles => grid_particles(k,j,i)%particles(1:number_of_particles)
4016                            s_r2 = 0.0_wp
4017                            s_r3 = 0.0_wp
4018
4019                            DO  n = 1, number_of_particles
4020                               IF ( particles(n)%particle_mask )  THEN
4021                                  s_r2 = s_r2 + particles(n)%radius**2 *       &
4022                                         particles(n)%weight_factor
4023                                  s_r3 = s_r3 + particles(n)%radius**3 *       &
4024                                         particles(n)%weight_factor
4025                               ENDIF
4026                            ENDDO
4027
4028                            IF ( s_r2 > 0.0_wp )  rrtm_reliq(0,k) = s_r3 / s_r2
4029
4030                         ENDIF
4031
4032!
4033!--                      Limit effective radius
4034                         IF ( rrtm_reliq(0,k) > 0.0_wp )  THEN
4035                            rrtm_reliq(0,k) = MAX(rrtm_reliq(0,k),2.5_wp)
4036                            rrtm_reliq(0,k) = MIN(rrtm_reliq(0,k),60.0_wp)
4037                        ENDIF
4038                      ENDIF
4039                   ENDDO
4040                ENDIF
4041
4042!
4043!--             Write surface emissivity and surface temperature at current
4044!--             surface element on RRTMG-shaped array.
4045!--             Please note, as RRTMG is a single column model, surface attributes
4046!--             are only obtained from horizontally aligned surfaces (for
4047!--             simplicity). Taking surface attributes from horizontal and
4048!--             vertical walls would lead to multiple solutions. 
4049!--             Moreover, for natural- and urban-type surfaces, several surface
4050!--             classes can exist at a surface element next to each other.
4051!--             To obtain bulk parameters, apply a weighted average for these
4052!--             surfaces.
4053                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
4054                   rrtm_emis = surf_lsm_h%frac(ind_veg_wall,m)  *              &
4055                               surf_lsm_h%emissivity(ind_veg_wall,m)  +        &
4056                               surf_lsm_h%frac(ind_pav_green,m) *              &
4057                               surf_lsm_h%emissivity(ind_pav_green,m) +        & 
4058                               surf_lsm_h%frac(ind_wat_win,m)   *              &
4059                               surf_lsm_h%emissivity(ind_wat_win,m)
4060                   rrtm_tsfc = surf_lsm_h%pt_surface(m) * exner(nzb)
4061                ENDDO             
4062                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
4063                   rrtm_emis = surf_usm_h%frac(ind_veg_wall,m)  *              &
4064                               surf_usm_h%emissivity(ind_veg_wall,m)  +        &
4065                               surf_usm_h%frac(ind_pav_green,m) *              &
4066                               surf_usm_h%emissivity(ind_pav_green,m) +        & 
4067                               surf_usm_h%frac(ind_wat_win,m)   *              &
4068                               surf_usm_h%emissivity(ind_wat_win,m)
4069                   rrtm_tsfc = surf_usm_h%pt_surface(m) * exner(nzb)
4070                ENDDO
4071!
4072!--             Obtain topography top index (lower bound of RRTMG)
4073                k_topo = get_topography_top_index_ji( j, i, 's' )
4074
4075                IF ( lw_radiation )  THEN
4076!
4077!--                Due to technical reasons, copy optical depth to dummy arguments
4078!--                which are allocated on the exact size as the rrtmg_lw is called.
4079!--                As one dimesion is allocated with zero size, compiler complains
4080!--                that rank of the array does not match that of the
4081!--                assumed-shaped arguments in the RRTMG library. In order to
4082!--                avoid this, write to dummy arguments and give pass the entire
4083!--                dummy array. Seems to be the only existing work-around. 
4084                   ALLOCATE( rrtm_lw_taucld_dum(1:nbndlw+1,0:0,k_topo+1:nzt_rad+1) )
4085                   ALLOCATE( rrtm_lw_tauaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndlw+1) )
4086
4087                   rrtm_lw_taucld_dum =                                        &
4088                               rrtm_lw_taucld(1:nbndlw+1,0:0,k_topo+1:nzt_rad+1)
4089                   rrtm_lw_tauaer_dum =                                        &
4090                               rrtm_lw_tauaer(0:0,k_topo+1:nzt_rad+1,1:nbndlw+1)
4091
4092                   CALL rrtmg_lw( 1,                                           &                                       
4093                                  nzt_rad-k_topo,                              &
4094                                  rrtm_icld,                                   &
4095                                  rrtm_idrv,                                   &
4096                                  rrtm_play(:,k_topo+1:nzt_rad+1),             &
4097                                  rrtm_plev(:,k_topo+1:nzt_rad+2),             &
4098                                  rrtm_tlay(:,k_topo+1:nzt_rad+1),             &
4099                                  rrtm_tlev(:,k_topo+1:nzt_rad+2),             &
4100                                  rrtm_tsfc,                                   &
4101                                  rrtm_h2ovmr(:,k_topo+1:nzt_rad+1),           &
4102                                  rrtm_o3vmr(:,k_topo+1:nzt_rad+1),            &
4103                                  rrtm_co2vmr(:,k_topo+1:nzt_rad+1),           &
4104                                  rrtm_ch4vmr(:,k_topo+1:nzt_rad+1),           &
4105                                  rrtm_n2ovmr(:,k_topo+1:nzt_rad+1),           &
4106                                  rrtm_o2vmr(:,k_topo+1:nzt_rad+1),            &
4107                                  rrtm_cfc11vmr(:,k_topo+1:nzt_rad+1),         &
4108                                  rrtm_cfc12vmr(:,k_topo+1:nzt_rad+1),         &
4109                                  rrtm_cfc22vmr(:,k_topo+1:nzt_rad+1),         &
4110                                  rrtm_ccl4vmr(:,k_topo+1:nzt_rad+1),          &
4111                                  rrtm_emis,                                   &
4112                                  rrtm_inflglw,                                &
4113                                  rrtm_iceflglw,                               &
4114                                  rrtm_liqflglw,                               &
4115                                  rrtm_cldfr(:,k_topo+1:nzt_rad+1),            &
4116                                  rrtm_lw_taucld_dum,                          &
4117                                  rrtm_cicewp(:,k_topo+1:nzt_rad+1),           &
4118                                  rrtm_cliqwp(:,k_topo+1:nzt_rad+1),           &
4119                                  rrtm_reice(:,k_topo+1:nzt_rad+1),            & 
4120                                  rrtm_reliq(:,k_topo+1:nzt_rad+1),            &
4121                                  rrtm_lw_tauaer_dum,                          &
4122                                  rrtm_lwuflx(:,k_topo:nzt_rad+1),             &
4123                                  rrtm_lwdflx(:,k_topo:nzt_rad+1),             &
4124                                  rrtm_lwhr(:,k_topo+1:nzt_rad+1),             &
4125                                  rrtm_lwuflxc(:,k_topo:nzt_rad+1),            &
4126                                  rrtm_lwdflxc(:,k_topo:nzt_rad+1),            &
4127                                  rrtm_lwhrc(:,k_topo+1:nzt_rad+1),            &
4128                                  rrtm_lwuflx_dt(:,k_topo:nzt_rad+1),          &
4129                                  rrtm_lwuflxc_dt(:,k_topo:nzt_rad+1) )
4130
4131                   DEALLOCATE ( rrtm_lw_taucld_dum )
4132                   DEALLOCATE ( rrtm_lw_tauaer_dum )
4133!
4134!--                Save fluxes
4135                   DO k = k_topo, nzt+1
4136                      rad_lw_in(k,j,i)  = rrtm_lwdflx(0,k)
4137                      rad_lw_out(k,j,i) = rrtm_lwuflx(0,k)
4138                   ENDDO
4139
4140!
4141!--                Save heating rates (convert from K/d to K/h)
4142                   DO k = k_topo+1, nzt+1
4143                      rad_lw_hr(k,j,i)     = rrtm_lwhr(0,k-k_topo)  * d_hours_day
4144                      rad_lw_cs_hr(k,j,i)  = rrtm_lwhrc(0,k-k_topo) * d_hours_day
4145                   ENDDO
4146
4147!
4148!--                Save surface radiative fluxes and change in LW heating rate
4149!--                onto respective surface elements
4150!--                Horizontal surfaces
4151                   DO  m = surf_lsm_h%start_index(j,i),                        &
4152                           surf_lsm_h%end_index(j,i)
4153                      surf_lsm_h%rad_lw_in(m)           = rrtm_lwdflx(0,k_topo)
4154                      surf_lsm_h%rad_lw_out(m)          = rrtm_lwuflx(0,k_topo)
4155                      surf_lsm_h%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k_topo)
4156                   ENDDO             
4157                   DO  m = surf_usm_h%start_index(j,i),                        &
4158                           surf_usm_h%end_index(j,i)
4159                      surf_usm_h%rad_lw_in(m)           = rrtm_lwdflx(0,k_topo)
4160                      surf_usm_h%rad_lw_out(m)          = rrtm_lwuflx(0,k_topo)
4161                      surf_usm_h%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k_topo)
4162                   ENDDO 
4163!
4164!--                Vertical surfaces. Fluxes are obtain at vertical level of the
4165!--                respective surface element
4166                   DO  l = 0, 3
4167                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
4168                              surf_lsm_v(l)%end_index(j,i)
4169                         k                                    = surf_lsm_v(l)%k(m)
4170                         surf_lsm_v(l)%rad_lw_in(m)           = rrtm_lwdflx(0,k)
4171                         surf_lsm_v(l)%rad_lw_out(m)          = rrtm_lwuflx(0,k)
4172                         surf_lsm_v(l)%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k)
4173                      ENDDO             
4174                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
4175                              surf_usm_v(l)%end_index(j,i)
4176                         k                                    = surf_usm_v(l)%k(m)
4177                         surf_usm_v(l)%rad_lw_in(m)           = rrtm_lwdflx(0,k)
4178                         surf_usm_v(l)%rad_lw_out(m)          = rrtm_lwuflx(0,k)
4179                         surf_usm_v(l)%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k)
4180                      ENDDO 
4181                   ENDDO
4182
4183                ENDIF
4184
4185                IF ( sw_radiation .AND. sun_up )  THEN
4186!
4187!--                Get albedo for direct/diffusive long/shortwave radiation at
4188!--                current (y,x)-location from surface variables.
4189!--                Only obtain it from horizontal surfaces, as RRTMG is a single
4190!--                column model
4191!--                (Please note, only one loop will entered, controlled by
4192!--                start-end index.)
4193                   DO  m = surf_lsm_h%start_index(j,i),                        &
4194                           surf_lsm_h%end_index(j,i)
4195                      rrtm_asdir(1)  = SUM( surf_lsm_h%frac(:,m) *             &
4196                                            surf_lsm_h%rrtm_asdir(:,m) )
4197                      rrtm_asdif(1)  = SUM( surf_lsm_h%frac(:,m) *             &
4198                                            surf_lsm_h%rrtm_asdif(:,m) )
4199                      rrtm_aldir(1)  = SUM( surf_lsm_h%frac(:,m) *             &
4200                                            surf_lsm_h%rrtm_aldir(:,m) )
4201                      rrtm_aldif(1)  = SUM( surf_lsm_h%frac(:,m) *             &
4202                                            surf_lsm_h%rrtm_aldif(:,m) )
4203                   ENDDO             
4204                   DO  m = surf_usm_h%start_index(j,i),                        &
4205                           surf_usm_h%end_index(j,i)
4206                      rrtm_asdir(1)  = SUM( surf_usm_h%frac(:,m) *             &
4207                                            surf_usm_h%rrtm_asdir(:,m) )
4208                      rrtm_asdif(1)  = SUM( surf_usm_h%frac(:,m) *             &
4209                                            surf_usm_h%rrtm_asdif(:,m) )
4210                      rrtm_aldir(1)  = SUM( surf_usm_h%frac(:,m) *             &
4211                                            surf_usm_h%rrtm_aldir(:,m) )
4212                      rrtm_aldif(1)  = SUM( surf_usm_h%frac(:,m) *             &
4213                                            surf_usm_h%rrtm_aldif(:,m) )
4214                   ENDDO
4215!
4216!--                Due to technical reasons, copy optical depths and other
4217!--                to dummy arguments which are allocated on the exact size as the
4218!--                rrtmg_sw is called.
4219!--                As one dimesion is allocated with zero size, compiler complains
4220!--                that rank of the array does not match that of the
4221!--                assumed-shaped arguments in the RRTMG library. In order to
4222!--                avoid this, write to dummy arguments and give pass the entire
4223!--                dummy array. Seems to be the only existing work-around. 
4224                   ALLOCATE( rrtm_sw_taucld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
4225                   ALLOCATE( rrtm_sw_ssacld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
4226                   ALLOCATE( rrtm_sw_asmcld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
4227                   ALLOCATE( rrtm_sw_fsfcld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
4228                   ALLOCATE( rrtm_sw_tauaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
4229                   ALLOCATE( rrtm_sw_ssaaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
4230                   ALLOCATE( rrtm_sw_asmaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
4231                   ALLOCATE( rrtm_sw_ecaer_dum(0:0,k_topo+1:nzt_rad+1,1:naerec+1)  )
4232     
4233                   rrtm_sw_taucld_dum = rrtm_sw_taucld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
4234                   rrtm_sw_ssacld_dum = rrtm_sw_ssacld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
4235                   rrtm_sw_asmcld_dum = rrtm_sw_asmcld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
4236                   rrtm_sw_fsfcld_dum = rrtm_sw_fsfcld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
4237                   rrtm_sw_tauaer_dum = rrtm_sw_tauaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
4238                   rrtm_sw_ssaaer_dum = rrtm_sw_ssaaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
4239                   rrtm_sw_asmaer_dum = rrtm_sw_asmaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
4240                   rrtm_sw_ecaer_dum  = rrtm_sw_ecaer(0:0,k_topo+1:nzt_rad+1,1:naerec+1)
4241
4242                   CALL rrtmg_sw( 1,                                           &
4243                                  nzt_rad-k_topo,                              &
4244                                  rrtm_icld,                                   &
4245                                  rrtm_iaer,                                   &
4246                                  rrtm_play(:,k_topo+1:nzt_rad+1),             &
4247                                  rrtm_plev(:,k_topo+1:nzt_rad+2),             &
4248                                  rrtm_tlay(:,k_topo+1:nzt_rad+1),             &
4249                                  rrtm_tlev(:,k_topo+1:nzt_rad+2),             &
4250                                  rrtm_tsfc,                                   &
4251                                  rrtm_h2ovmr(:,k_topo+1:nzt_rad+1),           &                               
4252                                  rrtm_o3vmr(:,k_topo+1:nzt_rad+1),            &       
4253                                  rrtm_co2vmr(:,k_topo+1:nzt_rad+1),           &
4254                                  rrtm_ch4vmr(:,k_topo+1:nzt_rad+1),           &
4255                                  rrtm_n2ovmr(:,k_topo+1:nzt_rad+1),           &
4256                                  rrtm_o2vmr(:,k_topo+1:nzt_rad+1),            &
4257                                  rrtm_asdir,                                  & 
4258                                  rrtm_asdif,                                  &
4259                                  rrtm_aldir,                                  &
4260                                  rrtm_aldif,                                  &
4261                                  zenith,                                      &
4262                                  0.0_wp,                                      &
4263                                  day_of_year,                                 &
4264                                  solar_constant,                              &
4265                                  rrtm_inflgsw,                                &
4266                                  rrtm_iceflgsw,                               &
4267                                  rrtm_liqflgsw,                               &
4268                                  rrtm_cldfr(:,k_topo+1:nzt_rad+1),            &
4269                                  rrtm_sw_taucld_dum,                          &
4270                                  rrtm_sw_ssacld_dum,                          &
4271                                  rrtm_sw_asmcld_dum,                          &
4272                                  rrtm_sw_fsfcld_dum,                          &
4273                                  rrtm_cicewp(:,k_topo+1:nzt_rad+1),           &
4274                                  rrtm_cliqwp(:,k_topo+1:nzt_rad+1),           &
4275                                  rrtm_reice(:,k_topo+1:nzt_rad+1),            &
4276                                  rrtm_reliq(:,k_topo+1:nzt_rad+1),            &
4277                                  rrtm_sw_tauaer_dum,                          &
4278                                  rrtm_sw_ssaaer_dum,                          &
4279                                  rrtm_sw_asmaer_dum,                          &
4280                                  rrtm_sw_ecaer_dum,                           &
4281                                  rrtm_swuflx(:,k_topo:nzt_rad+1),             & 
4282                                  rrtm_swdflx(:,k_topo:nzt_rad+1),             & 
4283                                  rrtm_swhr(:,k_topo+1:nzt_rad+1),             & 
4284                                  rrtm_swuflxc(:,k_topo:nzt_rad+1),            & 
4285                                  rrtm_swdflxc(:,k_topo:nzt_rad+1),            &
4286                                  rrtm_swhrc(:,k_topo+1:nzt_rad+1),            &
4287                                  rrtm_dirdflux(:,k_topo:nzt_rad+1),           &
4288                                  rrtm_difdflux(:,k_topo:nzt_rad+1) )
4289
4290                   DEALLOCATE( rrtm_sw_taucld_dum )
4291                   DEALLOCATE( rrtm_sw_ssacld_dum )
4292                   DEALLOCATE( rrtm_sw_asmcld_dum )
4293                   DEALLOCATE( rrtm_sw_fsfcld_dum )
4294                   DEALLOCATE( rrtm_sw_tauaer_dum )
4295                   DEALLOCATE( rrtm_sw_ssaaer_dum )
4296                   DEALLOCATE( rrtm_sw_asmaer_dum )
4297                   DEALLOCATE( rrtm_sw_ecaer_dum )
4298!
4299!--                Save fluxes
4300                   DO k = nzb, nzt+1
4301                      rad_sw_in(k,j,i)  = rrtm_swdflx(0,k)
4302                      rad_sw_out(k,j,i) = rrtm_swuflx(0,k)
4303                   ENDDO
4304!
4305!--                Save heating rates (convert from K/d to K/s)
4306                   DO k = nzb+1, nzt+1
4307                      rad_sw_hr(k,j,i)     = rrtm_swhr(0,k)  * d_hours_day
4308                      rad_sw_cs_hr(k,j,i)  = rrtm_swhrc(0,k) * d_hours_day
4309                   ENDDO
4310
4311!
4312!--                Save surface radiative fluxes onto respective surface elements
4313!--                Horizontal surfaces
4314                   DO  m = surf_lsm_h%start_index(j,i),                        &
4315                           surf_lsm_h%end_index(j,i)
4316                      surf_lsm_h%rad_sw_in(m)     = rrtm_swdflx(0,k_topo)
4317                      surf_lsm_h%rad_sw_out(m)    = rrtm_swuflx(0,k_topo)
4318                   ENDDO             
4319                   DO  m = surf_usm_h%start_index(j,i),                        &
4320                           surf_usm_h%end_index(j,i)
4321                      surf_usm_h%rad_sw_in(m)     = rrtm_swdflx(0,k_topo)
4322                      surf_usm_h%rad_sw_out(m)    = rrtm_swuflx(0,k_topo)
4323                   ENDDO 
4324!
4325!--                Vertical surfaces. Fluxes are obtain at respective vertical
4326!--                level of the surface element
4327                   DO  l = 0, 3
4328                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
4329                              surf_lsm_v(l)%end_index(j,i)
4330                         k                           = surf_lsm_v(l)%k(m)
4331                         surf_lsm_v(l)%rad_sw_in(m)  = rrtm_swdflx(0,k)
4332                         surf_lsm_v(l)%rad_sw_out(m) = rrtm_swuflx(0,k)
4333                      ENDDO             
4334                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
4335                              surf_usm_v(l)%end_index(j,i)
4336                         k                           = surf_usm_v(l)%k(m)
4337                         surf_usm_v(l)%rad_sw_in(m)  = rrtm_swdflx(0,k)
4338                         surf_usm_v(l)%rad_sw_out(m) = rrtm_swuflx(0,k)
4339                      ENDDO 
4340                   ENDDO
4341!
4342!--             Solar radiation is zero during night
4343                ELSE
4344                   rad_sw_in  = 0.0_wp
4345                   rad_sw_out = 0.0_wp
4346!--             !!!!!!!! ATTENSION !!!!!!!!!!!!!!!
4347!--             Surface radiative fluxes should be also set to zero here                 
4348!--                Save surface radiative fluxes onto respective surface elements
4349!--                Horizontal surfaces
4350                   DO  m = surf_lsm_h%start_index(j,i),                        &
4351                           surf_lsm_h%end_index(j,i)
4352                      surf_lsm_h%rad_sw_in(m)     = 0.0_wp
4353                      surf_lsm_h%rad_sw_out(m)    = 0.0_wp
4354                   ENDDO             
4355                   DO  m = surf_usm_h%start_index(j,i),                        &
4356                           surf_usm_h%end_index(j,i)
4357                      surf_usm_h%rad_sw_in(m)     = 0.0_wp
4358                      surf_usm_h%rad_sw_out(m)    = 0.0_wp
4359                   ENDDO 
4360!
4361!--                Vertical surfaces. Fluxes are obtain at respective vertical
4362!--                level of the surface element
4363                   DO  l = 0, 3
4364                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
4365                              surf_lsm_v(l)%end_index(j,i)
4366                         k                           = surf_lsm_v(l)%k(m)
4367                         surf_lsm_v(l)%rad_sw_in(m)  = 0.0_wp
4368                         surf_lsm_v(l)%rad_sw_out(m) = 0.0_wp
4369                      ENDDO             
4370                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
4371                              surf_usm_v(l)%end_index(j,i)
4372                         k                           = surf_usm_v(l)%k(m)
4373                         surf_usm_v(l)%rad_sw_in(m)  = 0.0_wp
4374                         surf_usm_v(l)%rad_sw_out(m) = 0.0_wp
4375                      ENDDO 
4376                   ENDDO
4377                ENDIF
4378
4379             ENDDO
4380          ENDDO
4381
4382       ENDIF
4383!
4384!--    Finally, calculate surface net radiation for surface elements.
4385       IF (  .NOT.  radiation_interactions  ) THEN
4386!--       First, for horizontal surfaces   
4387          DO  m = 1, surf_lsm_h%ns
4388             surf_lsm_h%rad_net(m) = surf_lsm_h%rad_sw_in(m)                   &
4389                                   - surf_lsm_h%rad_sw_out(m)                  &
4390                                   + surf_lsm_h%rad_lw_in(m)                   &
4391                                   - surf_lsm_h%rad_lw_out(m)
4392          ENDDO
4393          DO  m = 1, surf_usm_h%ns
4394             surf_usm_h%rad_net(m) = surf_usm_h%rad_sw_in(m)                   &
4395                                   - surf_usm_h%rad_sw_out(m)                  &
4396                                   + surf_usm_h%rad_lw_in(m)                   &
4397                                   - surf_usm_h%rad_lw_out(m)
4398          ENDDO
4399!
4400!--       Vertical surfaces.
4401!--       Todo: weight with azimuth and zenith angle according to their orientation!
4402          DO  l = 0, 3     
4403             DO  m = 1, surf_lsm_v(l)%ns
4404                surf_lsm_v(l)%rad_net(m) = surf_lsm_v(l)%rad_sw_in(m)          &
4405                                         - surf_lsm_v(l)%rad_sw_out(m)         &
4406                                         + surf_lsm_v(l)%rad_lw_in(m)          &
4407                                         - surf_lsm_v(l)%rad_lw_out(m)
4408             ENDDO
4409             DO  m = 1, surf_usm_v(l)%ns
4410                surf_usm_v(l)%rad_net(m) = surf_usm_v(l)%rad_sw_in(m)          &
4411                                         - surf_usm_v(l)%rad_sw_out(m)         &
4412                                         + surf_usm_v(l)%rad_lw_in(m)          &
4413                                         - surf_usm_v(l)%rad_lw_out(m)
4414             ENDDO
4415          ENDDO
4416       ENDIF
4417
4418
4419       CALL exchange_horiz( rad_lw_in,  nbgp )
4420       CALL exchange_horiz( rad_lw_out, nbgp )
4421       CALL exchange_horiz( rad_lw_hr,    nbgp )
4422       CALL exchange_horiz( rad_lw_cs_hr, nbgp )
4423
4424       CALL exchange_horiz( rad_sw_in,  nbgp )
4425       CALL exchange_horiz( rad_sw_out, nbgp ) 
4426       CALL exchange_horiz( rad_sw_hr,    nbgp )
4427       CALL exchange_horiz( rad_sw_cs_hr, nbgp )
4428
4429#endif
4430
4431    END SUBROUTINE radiation_rrtmg
4432
4433
4434!------------------------------------------------------------------------------!
4435! Description:
4436! ------------
4437!> Calculate the cosine of the zenith angle (variable is called zenith)
4438!------------------------------------------------------------------------------!
4439    SUBROUTINE calc_zenith
4440
4441       IMPLICIT NONE
4442
4443       REAL(wp) ::  declination,  & !< solar declination angle
4444                    hour_angle      !< solar hour angle
4445!
4446!--    Calculate current day and time based on the initial values and simulation
4447!--    time
4448       CALL calc_date_and_time
4449
4450!
4451!--    Calculate solar declination and hour angle   
4452       declination = ASIN( decl_1 * SIN(decl_2 * REAL(day_of_year, KIND=wp) - decl_3) )
4453       hour_angle  = 2.0_wp * pi * (time_utc / 86400.0_wp) + lon - pi
4454
4455!
4456!--    Calculate cosine of solar zenith angle
4457       cos_zenith = SIN(lat) * SIN(declination) + COS(lat) * COS(declination)   &
4458                                            * COS(hour_angle)
4459       cos_zenith = MAX(0.0_wp,cos_zenith)
4460
4461!
4462!--    Calculate solar directional vector
4463       IF ( sun_direction )  THEN
4464
4465!
4466!--       Direction in longitudes equals to sin(solar_azimuth) * sin(zenith)
4467          sun_dir_lon = -SIN(hour_angle) * COS(declination)
4468
4469!
4470!--       Direction in latitues equals to cos(solar_azimuth) * sin(zenith)
4471          sun_dir_lat = SIN(declination) * COS(lat) - COS(hour_angle) &
4472                              * COS(declination) * SIN(lat)
4473       ENDIF
4474
4475!
4476!--    Check if the sun is up (otheriwse shortwave calculations can be skipped)
4477       IF ( cos_zenith > 0.0_wp )  THEN
4478          sun_up = .TRUE.
4479       ELSE
4480          sun_up = .FALSE.
4481       END IF
4482
4483    END SUBROUTINE calc_zenith
4484
4485#if defined ( __rrtmg ) && defined ( __netcdf )
4486!------------------------------------------------------------------------------!
4487! Description:
4488! ------------
4489!> Calculates surface albedo components based on Briegleb (1992) and
4490!> Briegleb et al. (1986)
4491!------------------------------------------------------------------------------!
4492    SUBROUTINE calc_albedo( surf )
4493
4494        IMPLICIT NONE
4495
4496        INTEGER(iwp)    ::  ind_type !< running index surface tiles
4497        INTEGER(iwp)    ::  m        !< running index surface elements
4498
4499        TYPE(surf_type) ::  surf !< treated surfaces
4500
4501        IF ( sun_up  .AND.  .NOT. average_radiation )  THEN
4502
4503           DO  m = 1, surf%ns
4504!
4505!--           Loop over surface elements
4506              DO  ind_type = 0, SIZE( surf%albedo_type, 1 ) - 1
4507           
4508!
4509!--              Ocean
4510                 IF ( surf%albedo_type(ind_type,m) == 1 )  THEN
4511                    surf%rrtm_aldir(ind_type,m) = 0.026_wp /                    &
4512                                                ( cos_zenith**1.7_wp + 0.065_wp )&
4513                                     + 0.15_wp * ( cos_zenith - 0.1_wp )         &
4514                                               * ( cos_zenith - 0.5_wp )         &
4515                                               * ( cos_zenith - 1.0_wp )
4516                    surf%rrtm_asdir(ind_type,m) = surf%rrtm_aldir(ind_type,m)
4517!
4518!--              Snow
4519                 ELSEIF ( surf%albedo_type(ind_type,m) == 16 )  THEN
4520                    IF ( cos_zenith < 0.5_wp )  THEN
4521                       surf%rrtm_aldir(ind_type,m) =                           &
4522                                 0.5_wp * ( 1.0_wp - surf%aldif(ind_type,m) )  &
4523                                        * ( 3.0_wp / ( 1.0_wp + 4.0_wp         &
4524                                        * cos_zenith ) ) - 1.0_wp
4525                       surf%rrtm_asdir(ind_type,m) =                           &
4526                                 0.5_wp * ( 1.0_wp - surf%asdif(ind_type,m) )  &
4527                                        * ( 3.0_wp / ( 1.0_wp + 4.0_wp         &
4528                                        * cos_zenith ) ) - 1.0_wp
4529
4530                       surf%rrtm_aldir(ind_type,m) =                           &
4531                                       MIN(0.98_wp, surf%rrtm_aldir(ind_type,m))
4532                       surf%rrtm_asdir(ind_type,m) =                           &
4533                                       MIN(0.98_wp, surf%rrtm_asdir(ind_type,m))
4534                    ELSE
4535                       surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4536                       surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4537                    ENDIF
4538!
4539!--              Sea ice
4540                 ELSEIF ( surf%albedo_type(ind_type,m) == 15 )  THEN
4541                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4542                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4543
4544!
4545!--              Asphalt
4546                 ELSEIF ( surf%albedo_type(ind_type,m) == 17 )  THEN
4547                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4548                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4549
4550
4551!
4552!--              Bare soil
4553                 ELSEIF ( surf%albedo_type(ind_type,m) == 18 )  THEN
4554                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4555                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4556
4557!
4558!--              Land surfaces
4559                 ELSE
4560                    SELECT CASE ( surf%albedo_type(ind_type,m) )
4561
4562!
4563!--                    Surface types with strong zenith dependence
4564                       CASE ( 1, 2, 3, 4, 11, 12, 13 )
4565                          surf%rrtm_aldir(ind_type,m) =                        &
4566                                surf%aldif(ind_type,m) * 1.4_wp /              &
4567                                           ( 1.0_wp + 0.8_wp * cos_zenith )
4568                          surf%rrtm_asdir(ind_type,m) =                        &
4569                                surf%asdif(ind_type,m) * 1.4_wp /              &
4570                                           ( 1.0_wp + 0.8_wp * cos_zenith )
4571!
4572!--                    Surface types with weak zenith dependence
4573                       CASE ( 5, 6, 7, 8, 9, 10, 14 )
4574                          surf%rrtm_aldir(ind_type,m) =                        &
4575                                surf%aldif(ind_type,m) * 1.1_wp /              &
4576                                           ( 1.0_wp + 0.2_wp * cos_zenith )
4577                          surf%rrtm_asdir(ind_type,m) =                        &
4578                                surf%asdif(ind_type,m) * 1.1_wp /              &
4579                                           ( 1.0_wp + 0.2_wp * cos_zenith )
4580
4581                       CASE DEFAULT
4582
4583                    END SELECT
4584                 ENDIF
4585!
4586!--              Diffusive albedo is taken from Table 2
4587                 surf%rrtm_aldif(ind_type,m) = surf%aldif(ind_type,m)
4588                 surf%rrtm_asdif(ind_type,m) = surf%asdif(ind_type,m)
4589              ENDDO
4590           ENDDO
4591!
4592!--     Set albedo in case of average radiation
4593        ELSEIF ( sun_up  .AND.  average_radiation )  THEN
4594           surf%rrtm_asdir = albedo_urb
4595           surf%rrtm_asdif = albedo_urb
4596           surf%rrtm_aldir = albedo_urb
4597           surf%rrtm_aldif = albedo_urb 
4598!
4599!--     Darkness
4600        ELSE
4601           surf%rrtm_aldir = 0.0_wp
4602           surf%rrtm_asdir = 0.0_wp
4603           surf%rrtm_aldif = 0.0_wp
4604           surf%rrtm_asdif = 0.0_wp
4605        ENDIF
4606
4607    END SUBROUTINE calc_albedo
4608
4609!------------------------------------------------------------------------------!
4610! Description:
4611! ------------
4612!> Read sounding data (pressure and temperature) from RADIATION_DATA.
4613!------------------------------------------------------------------------------!
4614    SUBROUTINE read_sounding_data
4615
4616       IMPLICIT NONE
4617
4618       INTEGER(iwp) :: id,           & !< NetCDF id of input file
4619                       id_dim_zrad,  & !< pressure level id in the NetCDF file
4620                       id_var,       & !< NetCDF variable id
4621                       k,            & !< loop index
4622                       nz_snd,       & !< number of vertical levels in the sounding data
4623                       nz_snd_start, & !< start vertical index for sounding data to be used
4624                       nz_snd_end      !< end vertical index for souding data to be used
4625
4626       REAL(wp) :: t_surface           !< actual surface temperature
4627
4628       REAL(wp), DIMENSION(:), ALLOCATABLE ::  hyp_snd_tmp, & !< temporary hydrostatic pressure profile (sounding)
4629                                               t_snd_tmp      !< temporary temperature profile (sounding)
4630
4631!
4632!--    In case of updates, deallocate arrays first (sufficient to check one
4633!--    array as the others are automatically allocated). This is required
4634!--    because nzt_rad might change during the update
4635       IF ( ALLOCATED ( hyp_snd ) )  THEN
4636          DEALLOCATE( hyp_snd )
4637          DEALLOCATE( t_snd )
4638          DEALLOCATE ( rrtm_play )
4639          DEALLOCATE ( rrtm_plev )
4640          DEALLOCATE ( rrtm_tlay )
4641          DEALLOCATE ( rrtm_tlev )
4642
4643          DEALLOCATE ( rrtm_cicewp )
4644          DEALLOCATE ( rrtm_cldfr )
4645          DEALLOCATE ( rrtm_cliqwp )
4646          DEALLOCATE ( rrtm_reice )
4647          DEALLOCATE ( rrtm_reliq )
4648          DEALLOCATE ( rrtm_lw_taucld )
4649          DEALLOCATE ( rrtm_lw_tauaer )
4650
4651          DEALLOCATE ( rrtm_lwdflx  )
4652          DEALLOCATE ( rrtm_lwdflxc )
4653          DEALLOCATE ( rrtm_lwuflx  )
4654          DEALLOCATE ( rrtm_lwuflxc )
4655          DEALLOCATE ( rrtm_lwuflx_dt )
4656          DEALLOCATE ( rrtm_lwuflxc_dt )
4657          DEALLOCATE ( rrtm_lwhr  )
4658          DEALLOCATE ( rrtm_lwhrc )
4659
4660          DEALLOCATE ( rrtm_sw_taucld )
4661          DEALLOCATE ( rrtm_sw_ssacld )
4662          DEALLOCATE ( rrtm_sw_asmcld )
4663          DEALLOCATE ( rrtm_sw_fsfcld )
4664          DEALLOCATE ( rrtm_sw_tauaer )
4665          DEALLOCATE ( rrtm_sw_ssaaer )
4666          DEALLOCATE ( rrtm_sw_asmaer ) 
4667          DEALLOCATE ( rrtm_sw_ecaer )   
4668 
4669          DEALLOCATE ( rrtm_swdflx  )
4670          DEALLOCATE ( rrtm_swdflxc )
4671          DEALLOCATE ( rrtm_swuflx  )
4672          DEALLOCATE ( rrtm_swuflxc )
4673          DEALLOCATE ( rrtm_swhr  )
4674          DEALLOCATE ( rrtm_swhrc )
4675          DEALLOCATE ( rrtm_dirdflux )
4676          DEALLOCATE ( rrtm_difdflux )
4677
4678       ENDIF
4679
4680!
4681!--    Open file for reading
4682       nc_stat = NF90_OPEN( rrtm_input_file, NF90_NOWRITE, id )
4683       CALL netcdf_handle_error_rad( 'read_sounding_data', 549 )
4684
4685!
4686!--    Inquire dimension of z axis and save in nz_snd
4687       nc_stat = NF90_INQ_DIMID( id, "Pressure", id_dim_zrad )
4688       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim_zrad, len = nz_snd )
4689       CALL netcdf_handle_error_rad( 'read_sounding_data', 551 )
4690
4691!
4692! !--    Allocate temporary array for storing pressure data
4693       ALLOCATE( hyp_snd_tmp(1:nz_snd) )
4694       hyp_snd_tmp = 0.0_wp
4695
4696
4697!--    Read pressure from file
4698       nc_stat = NF90_INQ_VARID( id, "Pressure", id_var )
4699       nc_stat = NF90_GET_VAR( id, id_var, hyp_snd_tmp(:), start = (/1/),      &
4700                               count = (/nz_snd/) )
4701       CALL netcdf_handle_error_rad( 'read_sounding_data', 552 )
4702
4703!
4704!--    Allocate temporary array for storing temperature data
4705       ALLOCATE( t_snd_tmp(1:nz_snd) )
4706       t_snd_tmp = 0.0_wp
4707
4708!
4709!--    Read temperature from file
4710       nc_stat = NF90_INQ_VARID( id, "ReferenceTemperature", id_var )
4711       nc_stat = NF90_GET_VAR( id, id_var, t_snd_tmp(:), start = (/1/),        &
4712                               count = (/nz_snd/) )
4713       CALL netcdf_handle_error_rad( 'read_sounding_data', 553 )
4714
4715!
4716!--    Calculate start of sounding data
4717       nz_snd_start = nz_snd + 1
4718       nz_snd_end   = nz_snd + 1
4719
4720!
4721!--    Start filling vertical dimension at 10hPa above the model domain (hyp is
4722!--    in Pa, hyp_snd in hPa).
4723       DO  k = 1, nz_snd
4724          IF ( hyp_snd_tmp(k) < ( hyp(nzt+1) - 1000.0_wp) * 0.01_wp )  THEN
4725             nz_snd_start = k
4726             EXIT
4727          END IF
4728       END DO
4729
4730       IF ( nz_snd_start <= nz_snd )  THEN
4731          nz_snd_end = nz_snd
4732       END IF
4733
4734
4735!
4736!--    Calculate of total grid points for RRTMG calculations
4737       nzt_rad = nzt + nz_snd_end - nz_snd_start + 1
4738
4739!
4740!--    Save data above LES domain in hyp_snd, t_snd
4741       ALLOCATE( hyp_snd(nzb+1:nzt_rad) )
4742       ALLOCATE( t_snd(nzb+1:nzt_rad)   )
4743       hyp_snd = 0.0_wp
4744       t_snd = 0.0_wp
4745
4746       hyp_snd(nzt+2:nzt_rad) = hyp_snd_tmp(nz_snd_start+1:nz_snd_end)
4747       t_snd(nzt+2:nzt_rad)   = t_snd_tmp(nz_snd_start+1:nz_snd_end)
4748
4749       nc_stat = NF90_CLOSE( id )
4750
4751!
4752!--    Calculate pressure levels on zu and zw grid. Sounding data is added at
4753!--    top of the LES domain. This routine does not consider horizontal or
4754!--    vertical variability of pressure and temperature
4755       ALLOCATE ( rrtm_play(0:0,nzb+1:nzt_rad+1)   )
4756       ALLOCATE ( rrtm_plev(0:0,nzb+1:nzt_rad+2)   )
4757
4758       t_surface = pt_surface * exner(nzb)
4759       DO k = nzb+1, nzt+1
4760          rrtm_play(0,k) = hyp(k) * 0.01_wp
4761          rrtm_plev(0,k) = barometric_formula(zw(k-1),                         &
4762                              pt_surface * exner(nzb), &
4763                              surface_pressure )
4764       ENDDO
4765
4766       DO k = nzt+2, nzt_rad
4767          rrtm_play(0,k) = hyp_snd(k)
4768          rrtm_plev(0,k) = 0.5_wp * ( rrtm_play(0,k) + rrtm_play(0,k-1) )
4769       ENDDO
4770       rrtm_plev(0,nzt_rad+1) = MAX( 0.5 * hyp_snd(nzt_rad),                   &
4771                                   1.5 * hyp_snd(nzt_rad)                      &
4772                                 - 0.5 * hyp_snd(nzt_rad-1) )
4773       rrtm_plev(0,nzt_rad+2)  = MIN( 1.0E-4_wp,                               &
4774                                      0.25_wp * rrtm_plev(0,nzt_rad+1) )
4775
4776       rrtm_play(0,nzt_rad+1) = 0.5 * rrtm_plev(0,nzt_rad+1)
4777
4778!
4779!--    Calculate temperature/humidity levels at top of the LES domain.
4780!--    Currently, the temperature is taken from sounding data (might lead to a
4781!--    temperature jump at interface. To do: Humidity is currently not
4782!--    calculated above the LES domain.
4783       ALLOCATE ( rrtm_tlay(0:0,nzb+1:nzt_rad+1)   )
4784       ALLOCATE ( rrtm_tlev(0:0,nzb+1:nzt_rad+2)   )
4785
4786       DO k = nzt+8, nzt_rad
4787          rrtm_tlay(0,k)   = t_snd(k)
4788       ENDDO
4789       rrtm_tlay(0,nzt_rad+1) = 2.0_wp * rrtm_tlay(0,nzt_rad)                  &
4790                                - rrtm_tlay(0,nzt_rad-1)
4791       DO k = nzt+9, nzt_rad+1
4792          rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k)                &
4793                             - rrtm_tlay(0,k-1))                               &
4794                             / ( rrtm_play(0,k) - rrtm_play(0,k-1) )           &
4795                             * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
4796       ENDDO
4797
4798       rrtm_tlev(0,nzt_rad+2)   = 2.0_wp * rrtm_tlay(0,nzt_rad+1)              &
4799                                  - rrtm_tlev(0,nzt_rad)
4800!
4801!--    Allocate remaining RRTMG arrays
4802       ALLOCATE ( rrtm_cicewp(0:0,nzb+1:nzt_rad+1) )
4803       ALLOCATE ( rrtm_cldfr(0:0,nzb+1:nzt_rad+1) )
4804       ALLOCATE ( rrtm_cliqwp(0:0,nzb+1:nzt_rad+1) )
4805       ALLOCATE ( rrtm_reice(0:0,nzb+1:nzt_rad+1) )
4806       ALLOCATE ( rrtm_reliq(0:0,nzb+1:nzt_rad+1) )
4807       ALLOCATE ( rrtm_lw_taucld(1:nbndlw+1,0:0,nzb+1:nzt_rad+1) )
4808       ALLOCATE ( rrtm_lw_tauaer(0:0,nzb+1:nzt_rad+1,1:nbndlw+1) )
4809       ALLOCATE ( rrtm_sw_taucld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4810       ALLOCATE ( rrtm_sw_ssacld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4811       ALLOCATE ( rrtm_sw_asmcld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4812       ALLOCATE ( rrtm_sw_fsfcld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4813       ALLOCATE ( rrtm_sw_tauaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) )
4814       ALLOCATE ( rrtm_sw_ssaaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) )
4815       ALLOCATE ( rrtm_sw_asmaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) ) 
4816       ALLOCATE ( rrtm_sw_ecaer(0:0,nzb+1:nzt_rad+1,1:naerec+1) )   
4817
4818!
4819!--    The ice phase is currently not considered in PALM
4820       rrtm_cicewp = 0.0_wp
4821       rrtm_reice  = 0.0_wp
4822
4823!
4824!--    Set other parameters (move to NAMELIST parameters in the future)
4825       rrtm_lw_tauaer = 0.0_wp
4826       rrtm_lw_taucld = 0.0_wp
4827       rrtm_sw_taucld = 0.0_wp
4828       rrtm_sw_ssacld = 0.0_wp
4829       rrtm_sw_asmcld = 0.0_wp
4830       rrtm_sw_fsfcld = 0.0_wp
4831       rrtm_sw_tauaer = 0.0_wp
4832       rrtm_sw_ssaaer = 0.0_wp
4833       rrtm_sw_asmaer = 0.0_wp
4834       rrtm_sw_ecaer  = 0.0_wp
4835
4836
4837       ALLOCATE ( rrtm_swdflx(0:0,nzb:nzt_rad+1)  )
4838       ALLOCATE ( rrtm_swuflx(0:0,nzb:nzt_rad+1)  )
4839       ALLOCATE ( rrtm_swhr(0:0,nzb+1:nzt_rad+1)  )
4840       ALLOCATE ( rrtm_swuflxc(0:0,nzb:nzt_rad+1) )
4841       ALLOCATE ( rrtm_swdflxc(0:0,nzb:nzt_rad+1) )
4842       ALLOCATE ( rrtm_swhrc(0:0,nzb+1:nzt_rad+1) )
4843       ALLOCATE ( rrtm_dirdflux(0:0,nzb:nzt_rad+1) )
4844       ALLOCATE ( rrtm_difdflux(0:0,nzb:nzt_rad+1) )
4845
4846       rrtm_swdflx  = 0.0_wp
4847       rrtm_swuflx  = 0.0_wp
4848       rrtm_swhr    = 0.0_wp 
4849       rrtm_swuflxc = 0.0_wp
4850       rrtm_swdflxc = 0.0_wp
4851       rrtm_swhrc   = 0.0_wp
4852       rrtm_dirdflux = 0.0_wp
4853       rrtm_difdflux = 0.0_wp
4854
4855       ALLOCATE ( rrtm_lwdflx(0:0,nzb:nzt_rad+1)  )
4856       ALLOCATE ( rrtm_lwuflx(0:0,nzb:nzt_rad+1)  )
4857       ALLOCATE ( rrtm_lwhr(0:0,nzb+1:nzt_rad+1)  )
4858       ALLOCATE ( rrtm_lwuflxc(0:0,nzb:nzt_rad+1) )
4859       ALLOCATE ( rrtm_lwdflxc(0:0,nzb:nzt_rad+1) )
4860       ALLOCATE ( rrtm_lwhrc(0:0,nzb+1:nzt_rad+1) )
4861
4862       rrtm_lwdflx  = 0.0_wp
4863       rrtm_lwuflx  = 0.0_wp
4864       rrtm_lwhr    = 0.0_wp 
4865       rrtm_lwuflxc = 0.0_wp
4866       rrtm_lwdflxc = 0.0_wp
4867       rrtm_lwhrc   = 0.0_wp
4868
4869       ALLOCATE ( rrtm_lwuflx_dt(0:0,nzb:nzt_rad+1) )
4870       ALLOCATE ( rrtm_lwuflxc_dt(0:0,nzb:nzt_rad+1) )
4871
4872       rrtm_lwuflx_dt = 0.0_wp
4873       rrtm_lwuflxc_dt = 0.0_wp
4874
4875    END SUBROUTINE read_sounding_data
4876
4877
4878!------------------------------------------------------------------------------!
4879! Description:
4880! ------------
4881!> Read trace gas data from file and convert into trace gas paths / volume
4882!> mixing ratios. If a user-defined input file is provided it needs to follow
4883!> the convections used in RRTMG (see respective netCDF files shipped with
4884!> RRTMG)
4885!------------------------------------------------------------------------------!
4886    SUBROUTINE read_trace_gas_data
4887
4888       USE rrsw_ncpar
4889
4890       IMPLICIT NONE
4891
4892       INTEGER(iwp), PARAMETER :: num_trace_gases = 10 !< number of trace gases (absorbers)
4893
4894       CHARACTER(LEN=5), DIMENSION(num_trace_gases), PARAMETER ::              & !< trace gas names
4895           trace_names = (/'O3   ', 'CO2  ', 'CH4  ', 'N2O  ', 'O2   ',        &
4896                           'CFC11', 'CFC12', 'CFC22', 'CCL4 ', 'H2O  '/)
4897
4898       INTEGER(iwp) :: id,     & !< NetCDF id
4899                       k,      & !< loop index
4900                       m,      & !< loop index
4901                       n,      & !< loop index
4902                       nabs,   & !< number of absorbers
4903                       np,     & !< number of pressure levels
4904                       id_abs, & !< NetCDF id of the respective absorber
4905                       id_dim, & !< NetCDF id of asborber's dimension
4906                       id_var    !< NetCDf id ot the absorber
4907
4908       REAL(wp) :: p_mls_l, &    !< pressure lower limit for interpolation
4909                   p_mls_u, &    !< pressure upper limit for interpolation
4910                   p_wgt_l, &    !< pressure weight lower limit for interpolation
4911                   p_wgt_u, &    !< pressure weight upper limit for interpolation
4912                   p_mls_m       !< mean pressure between upper and lower limits
4913
4914
4915       REAL(wp), DIMENSION(:), ALLOCATABLE   ::  p_mls,          & !< pressure levels for the absorbers
4916                                                 rrtm_play_tmp,  & !< temporary array for pressure zu-levels
4917                                                 rrtm_plev_tmp,  & !< temporary array for pressure zw-levels
4918                                                 trace_path_tmp    !< temporary array for storing trace gas path data
4919
4920       REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  trace_mls,      & !< array for storing the absorber amounts
4921                                                 trace_mls_path, & !< array for storing trace gas path data
4922                                                 trace_mls_tmp     !< temporary array for storing trace gas data
4923
4924
4925!
4926!--    In case of updates, deallocate arrays first (sufficient to check one
4927!--    array as the others are automatically allocated)
4928       IF ( ALLOCATED ( rrtm_o3vmr ) )  THEN
4929          DEALLOCATE ( rrtm_o3vmr  )
4930          DEALLOCATE ( rrtm_co2vmr )
4931          DEALLOCATE ( rrtm_ch4vmr )
4932          DEALLOCATE ( rrtm_n2ovmr )
4933          DEALLOCATE ( rrtm_o2vmr  )
4934          DEALLOCATE ( rrtm_cfc11vmr )
4935          DEALLOCATE ( rrtm_cfc12vmr )
4936          DEALLOCATE ( rrtm_cfc22vmr )
4937          DEALLOCATE ( rrtm_ccl4vmr  )
4938          DEALLOCATE ( rrtm_h2ovmr  )     
4939       ENDIF
4940
4941!
4942!--    Allocate trace gas profiles
4943       ALLOCATE ( rrtm_o3vmr(0:0,1:nzt_rad+1)  )
4944       ALLOCATE ( rrtm_co2vmr(0:0,1:nzt_rad+1) )
4945       ALLOCATE ( rrtm_ch4vmr(0:0,1:nzt_rad+1) )
4946       ALLOCATE ( rrtm_n2ovmr(0:0,1:nzt_rad+1) )
4947       ALLOCATE ( rrtm_o2vmr(0:0,1:nzt_rad+1)  )
4948       ALLOCATE ( rrtm_cfc11vmr(0:0,1:nzt_rad+1) )
4949       ALLOCATE ( rrtm_cfc12vmr(0:0,1:nzt_rad+1) )
4950       ALLOCATE ( rrtm_cfc22vmr(0:0,1:nzt_rad+1) )
4951       ALLOCATE ( rrtm_ccl4vmr(0:0,1:nzt_rad+1)  )
4952       ALLOCATE ( rrtm_h2ovmr(0:0,1:nzt_rad+1)  )
4953
4954!
4955!--    Open file for reading
4956       nc_stat = NF90_OPEN( rrtm_input_file, NF90_NOWRITE, id )
4957       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 549 )
4958!
4959!--    Inquire dimension ids and dimensions
4960       nc_stat = NF90_INQ_DIMID( id, "Pressure", id_dim )
4961       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4962       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim, len = np) 
4963       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4964
4965       nc_stat = NF90_INQ_DIMID( id, "Absorber", id_dim )
4966       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4967       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim, len = nabs ) 
4968       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4969   
4970
4971!
4972!--    Allocate pressure, and trace gas arrays     
4973       ALLOCATE( p_mls(1:np) )
4974       ALLOCATE( trace_mls(1:num_trace_gases,1:np) ) 
4975       ALLOCATE( trace_mls_tmp(1:nabs,1:np) ) 
4976
4977
4978       nc_stat = NF90_INQ_VARID( id, "Pressure", id_var )
4979       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4980       nc_stat = NF90_GET_VAR( id, id_var, p_mls )
4981       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4982
4983       nc_stat = NF90_INQ_VARID( id, "AbsorberAmountMLS", id_var )
4984       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4985       nc_stat = NF90_GET_VAR( id, id_var, trace_mls_tmp )
4986       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4987
4988
4989!
4990!--    Write absorber amounts (mls) to trace_mls
4991       DO n = 1, num_trace_gases
4992          CALL getAbsorberIndex( TRIM( trace_names(n) ), id_abs )
4993
4994          trace_mls(n,1:np) = trace_mls_tmp(id_abs,1:np)
4995
4996!
4997!--       Replace missing values by zero
4998          WHERE ( trace_mls(n,:) > 2.0_wp ) 
4999             trace_mls(n,:) = 0.0_wp
5000          END WHERE
5001       END DO
5002
5003       DEALLOCATE ( trace_mls_tmp )
5004
5005       nc_stat = NF90_CLOSE( id )
5006       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 551 )
5007
5008!
5009!--    Add extra pressure level for calculations of the trace gas paths
5010       ALLOCATE ( rrtm_play_tmp(1:nzt_rad+1) )
5011       ALLOCATE ( rrtm_plev_tmp(1:nzt_rad+2) )
5012
5013       rrtm_play_tmp(1:nzt_rad)   = rrtm_play(0,1:nzt_rad) 
5014       rrtm_plev_tmp(1:nzt_rad+1) = rrtm_plev(0,1:nzt_rad+1)
5015       rrtm_play_tmp(nzt_rad+1)   = rrtm_plev(0,nzt_rad+1) * 0.5_wp
5016       rrtm_plev_tmp(nzt_rad+2)   = MIN( 1.0E-4_wp, 0.25_wp                    &
5017                                         * rrtm_plev(0,nzt_rad+1) )
5018 
5019!
5020!--    Calculate trace gas path (zero at surface) with interpolation to the
5021!--    sounding levels
5022       ALLOCATE ( trace_mls_path(1:nzt_rad+2,1:num_trace_gases) )
5023
5024       trace_mls_path(nzb+1,:) = 0.0_wp
5025       
5026       DO k = nzb+2, nzt_rad+2
5027          DO m = 1, num_trace_gases
5028             trace_mls_path(k,m) = trace_mls_path(k-1,m)
5029
5030!
5031!--          When the pressure level is higher than the trace gas pressure
5032!--          level, assume that
5033             IF ( rrtm_plev_tmp(k-1) > p_mls(1) )  THEN             
5034               
5035                trace_mls_path(k,m) = trace_mls_path(k,m) + trace_mls(m,1)     &
5036                                      * ( rrtm_plev_tmp(k-1)                   &
5037                                          - MAX( p_mls(1), rrtm_plev_tmp(k) )  &
5038                                        ) / g
5039             ENDIF
5040
5041!
5042!--          Integrate for each sounding level from the contributing p_mls
5043!--          levels
5044             DO n = 2, np
5045!
5046!--             Limit p_mls so that it is within the model level
5047                p_mls_u = MIN( rrtm_plev_tmp(k-1),                             &
5048                          MAX( rrtm_plev_tmp(k), p_mls(n) ) )
5049                p_mls_l = MIN( rrtm_plev_tmp(k-1),                             &
5050                          MAX( rrtm_plev_tmp(k), p_mls(n-1) ) )
5051
5052                IF ( p_mls_l > p_mls_u )  THEN
5053
5054!
5055!--                Calculate weights for interpolation
5056                   p_mls_m = 0.5_wp * (p_mls_l + p_mls_u)
5057                   p_wgt_u = (p_mls(n-1) - p_mls_m) / (p_mls(n-1) - p_mls(n))
5058                   p_wgt_l = (p_mls_m - p_mls(n))   / (p_mls(n-1) - p_mls(n))
5059
5060!
5061!--                Add level to trace gas path
5062                   trace_mls_path(k,m) = trace_mls_path(k,m)                   &
5063                                         +  ( p_wgt_u * trace_mls(m,n)         &
5064                                            + p_wgt_l * trace_mls(m,n-1) )     &
5065                                         * (p_mls_l - p_mls_u) / g
5066                ENDIF
5067             ENDDO
5068
5069             IF ( rrtm_plev_tmp(k) < p_mls(np) )  THEN
5070                trace_mls_path(k,m) = trace_mls_path(k,m) + trace_mls(m,np)    &
5071                                      * ( MIN( rrtm_plev_tmp(k-1), p_mls(np) ) &
5072                                          - rrtm_plev_tmp(k)                   &
5073                                        ) / g 
5074             ENDIF 
5075          ENDDO
5076       ENDDO
5077
5078
5079!
5080!--    Prepare trace gas path profiles
5081       ALLOCATE ( trace_path_tmp(1:nzt_rad+1) )
5082
5083       DO m = 1, num_trace_gases
5084
5085          trace_path_tmp(1:nzt_rad+1) = ( trace_mls_path(2:nzt_rad+2,m)        &
5086                                       - trace_mls_path(1:nzt_rad+1,m) ) * g   &
5087                                       / ( rrtm_plev_tmp(1:nzt_rad+1)          &
5088                                       - rrtm_plev_tmp(2:nzt_rad+2) )
5089
5090!
5091!--       Save trace gas paths to the respective arrays
5092          SELECT CASE ( TRIM( trace_names(m) ) )
5093
5094             CASE ( 'O3' )
5095
5096                rrtm_o3vmr(0,:) = trace_path_tmp(:)
5097
5098             CASE ( 'CO2' )
5099
5100                rrtm_co2vmr(0,:) = trace_path_tmp(:)
5101
5102             CASE ( 'CH4' )
5103
5104                rrtm_ch4vmr(0,:) = trace_path_tmp(:)
5105
5106             CASE ( 'N2O' )
5107
5108                rrtm_n2ovmr(0,:) = trace_path_tmp(:)
5109
5110             CASE ( 'O2' )
5111
5112                rrtm_o2vmr(0,:) = trace_path_tmp(:)
5113
5114             CASE ( 'CFC11' )
5115
5116                rrtm_cfc11vmr(0,:) = trace_path_tmp(:)
5117
5118             CASE ( 'CFC12' )
5119
5120                rrtm_cfc12vmr(0,:) = trace_path_tmp(:)
5121
5122             CASE ( 'CFC22' )
5123
5124                rrtm_cfc22vmr(0,:) = trace_path_tmp(:)
5125
5126             CASE ( 'CCL4' )
5127
5128                rrtm_ccl4vmr(0,:) = trace_path_tmp(:)
5129
5130             CASE ( 'H2O' )
5131
5132                rrtm_h2ovmr(0,:) = trace_path_tmp(:)
5133               
5134             CASE DEFAULT
5135
5136          END SELECT
5137
5138       ENDDO
5139
5140       DEALLOCATE ( trace_path_tmp )
5141       DEALLOCATE ( trace_mls_path )
5142       DEALLOCATE ( rrtm_play_tmp )
5143       DEALLOCATE ( rrtm_plev_tmp )
5144       DEALLOCATE ( trace_mls )
5145       DEALLOCATE ( p_mls )
5146
5147    END SUBROUTINE read_trace_gas_data
5148
5149
5150    SUBROUTINE netcdf_handle_error_rad( routine_name, errno )
5151
5152       USE control_parameters,                                                 &
5153           ONLY:  message_string
5154
5155       USE NETCDF
5156
5157       USE pegrid
5158
5159       IMPLICIT NONE
5160
5161       CHARACTER(LEN=6) ::  message_identifier
5162       CHARACTER(LEN=*) ::  routine_name
5163
5164       INTEGER(iwp) ::  errno
5165
5166       IF ( nc_stat /= NF90_NOERR )  THEN
5167
5168          WRITE( message_identifier, '(''NC'',I4.4)' )  errno
5169          message_string = TRIM( NF90_STRERROR( nc_stat ) )
5170
5171          CALL message( routine_name, message_identifier, 2, 2, 0, 6, 1 )
5172
5173       ENDIF
5174
5175    END SUBROUTINE netcdf_handle_error_rad
5176#endif
5177
5178
5179!------------------------------------------------------------------------------!
5180! Description:
5181! ------------
5182!> Calculate temperature tendency due to radiative cooling/heating.
5183!> Cache-optimized version.
5184!------------------------------------------------------------------------------!
5185#if defined( __rrtmg )
5186 SUBROUTINE radiation_tendency_ij ( i, j, tend )
5187
5188    IMPLICIT NONE
5189
5190    INTEGER(iwp) :: i, j, k !< loop indices
5191
5192    REAL(wp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg) :: tend !< pt tendency term
5193
5194    IF ( radiation_scheme == 'rrtmg' )  THEN
5195!
5196!--    Calculate tendency based on heating rate
5197       DO k = nzb+1, nzt+1
5198          tend(k,j,i) = tend(k,j,i) + (rad_lw_hr(k,j,i) + rad_sw_hr(k,j,i))    &
5199                                         * d_exner(k) * d_seconds_hour
5200       ENDDO
5201
5202    ENDIF
5203
5204 END SUBROUTINE radiation_tendency_ij
5205#endif
5206
5207
5208!------------------------------------------------------------------------------!
5209! Description:
5210! ------------
5211!> Calculate temperature tendency due to radiative cooling/heating.
5212!> Vector-optimized version
5213!------------------------------------------------------------------------------!
5214#if defined( __rrtmg )
5215 SUBROUTINE radiation_tendency ( tend )
5216
5217    USE indices,                                                               &
5218        ONLY:  nxl, nxr, nyn, nys
5219
5220    IMPLICIT NONE
5221
5222    INTEGER(iwp) :: i, j, k !< loop indices
5223
5224    REAL(wp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg) :: tend !< pt tendency term
5225
5226    IF ( radiation_scheme == 'rrtmg' )  THEN
5227!
5228!--    Calculate tendency based on heating rate
5229       DO  i = nxl, nxr
5230          DO  j = nys, nyn
5231             DO k = nzb+1, nzt+1
5232                tend(k,j,i) = tend(k,j,i) + ( rad_lw_hr(k,j,i)                 &
5233                                          +  rad_sw_hr(k,j,i) ) * d_exner(k)   &
5234                                          * d_seconds_hour
5235             ENDDO
5236          ENDDO
5237       ENDDO
5238    ENDIF
5239
5240 END SUBROUTINE radiation_tendency
5241#endif
5242
5243!------------------------------------------------------------------------------!
5244! Description:
5245! ------------
5246!> This subroutine calculates interaction of the solar radiation
5247!> with urban and land surfaces and updates all surface heatfluxes.
5248!> It calculates also the required parameters for RRTMG lower BC.
5249!>
5250!> For more info. see Resler et al. 2017
5251!>
5252!> The new version 2.0 was radically rewriten, the discretization scheme
5253!> has been changed. This new version significantly improves effectivity
5254!> of the paralelization and the scalability of the model.
5255!------------------------------------------------------------------------------!
5256
5257 SUBROUTINE radiation_interaction
5258
5259     IMPLICIT NONE
5260
5261     INTEGER(iwp)                      :: i, j, k, kk, d, refstep, m, mm, l, ll
5262     INTEGER(iwp)                      :: isurf, isurfsrc, isvf, icsf, ipcgb
5263     INTEGER(iwp)                      :: imrt, imrtf
5264     INTEGER(iwp)                      :: isd                !< solar direction number
5265     INTEGER(iwp)                      :: pc_box_dimshift    !< transform for best accuracy
5266     INTEGER(iwp), DIMENSION(0:3)      :: reorder = (/ 1, 0, 3, 2 /)
5267     
5268     REAL(wp), DIMENSION(3,3)          :: mrot               !< grid rotation matrix (zyx)
5269     REAL(wp), DIMENSION(3,0:nsurf_type):: vnorm             !< face direction normal vectors (zyx)
5270     REAL(wp), DIMENSION(3)            :: sunorig            !< grid rotated solar direction unit vector (zyx)
5271     REAL(wp), DIMENSION(3)            :: sunorig_grid       !< grid squashed solar direction unit vector (zyx)
5272     REAL(wp), DIMENSION(0:nsurf_type) :: costheta           !< direct irradiance factor of solar angle
5273     REAL(wp), DIMENSION(nz_urban_b:nz_urban_t)    :: pchf_prep          !< precalculated factor for canopy temperature tendency
5274     REAL(wp), PARAMETER               :: alpha = 0._wp      !< grid rotation (TODO: synchronize with rotation_angle
5275                                                             !< from netcdf_data_input_mod)
5276     REAL(wp)                          :: pc_box_area, pc_abs_frac, pc_abs_eff
5277     REAL(wp)                          :: asrc               !< area of source face
5278     REAL(wp)                          :: pcrad              !< irradiance from plant canopy
5279     REAL(wp)                          :: pabsswl  = 0.0_wp  !< total absorbed SW radiation energy in local processor (W)
5280     REAL(wp)                          :: pabssw   = 0.0_wp  !< total absorbed SW radiation energy in all processors (W)
5281     REAL(wp)                          :: pabslwl  = 0.0_wp  !< total absorbed LW radiation energy in local processor (W)
5282     REAL(wp)                          :: pabslw   = 0.0_wp  !< total absorbed LW radiation energy in all processors (W)
5283     REAL(wp)                          :: pemitlwl = 0.0_wp  !< total emitted LW radiation energy in all processors (W)
5284     REAL(wp)                          :: pemitlw  = 0.0_wp  !< total emitted LW radiation energy in all processors (W)
5285     REAL(wp)                          :: pinswl   = 0.0_wp  !< total received SW radiation energy in local processor (W)
5286     REAL(wp)                          :: pinsw    = 0.0_wp  !< total received SW radiation energy in all processor (W)
5287     REAL(wp)                          :: pinlwl   = 0.0_wp  !< total received LW radiation energy in local processor (W)
5288     REAL(wp)                          :: pinlw    = 0.0_wp  !< total received LW radiation energy in all processor (W)
5289     REAL(wp)                          :: emiss_sum_surfl    !< sum of emissisivity of surfaces in local processor
5290     REAL(wp)                          :: emiss_sum_surf     !< sum of emissisivity of surfaces in all processor
5291     REAL(wp)                          :: area_surfl         !< total area of surfaces in local processor
5292     REAL(wp)                          :: area_surf          !< total area of surfaces in all processor
5293     REAL(wp)                          :: area_hor           !< total horizontal area of domain in all processor
5294
5295
5296     IF ( debug_output_timestep )  CALL debug_message( 'radiation_interaction', 'start' )
5297
5298     IF ( plant_canopy )  THEN
5299         pchf_prep(:) = r_d * exner(nz_urban_b:nz_urban_t)                                 &
5300                     / (c_p * hyp(nz_urban_b:nz_urban_t) * dx*dy*dz(1)) !< equals to 1 / (rho * c_p * Vbox * T)
5301     ENDIF
5302
5303     sun_direction = .TRUE.
5304     CALL calc_zenith  !< required also for diffusion radiation
5305
5306!--     prepare rotated normal vectors and irradiance factor
5307     vnorm(1,:) = kdir(:)
5308     vnorm(2,:) = jdir(:)
5309     vnorm(3,:) = idir(:)
5310     mrot(1, :) = (/ 1._wp,  0._wp,      0._wp      /)
5311     mrot(2, :) = (/ 0._wp,  COS(alpha), SIN(alpha) /)
5312     mrot(3, :) = (/ 0._wp, -SIN(alpha), COS(alpha) /)
5313     sunorig = (/ cos_zenith, sun_dir_lat, sun_dir_lon /)
5314     sunorig = MATMUL(mrot, sunorig)
5315     DO d = 0, nsurf_type
5316         costheta(d) = DOT_PRODUCT(sunorig, vnorm(:,d))
5317     ENDDO
5318
5319     IF ( cos_zenith > 0 )  THEN
5320!--      now we will "squash" the sunorig vector by grid box size in
5321!--      each dimension, so that this new direction vector will allow us
5322!--      to traverse the ray path within grid coordinates directly
5323         sunorig_grid = (/ sunorig(1)/dz(1), sunorig(2)/dy, sunorig(3)/dx /)
5324!--      sunorig_grid = sunorig_grid / norm2(sunorig_grid)
5325         sunorig_grid = sunorig_grid / SQRT(SUM(sunorig_grid**2))
5326
5327         IF ( npcbl > 0 )  THEN
5328!--         precompute effective box depth with prototype Leaf Area Density
5329            pc_box_dimshift = MAXLOC(ABS(sunorig), 1) - 1
5330            CALL box_absorb(CSHIFT((/dz(1),dy,dx/), pc_box_dimshift),       &
5331                                60, prototype_lad,                          &
5332                                CSHIFT(ABS(sunorig), pc_box_dimshift),      &
5333                                pc_box_area, pc_abs_frac)
5334            pc_box_area = pc_box_area * ABS(sunorig(pc_box_dimshift+1)      &
5335                          / sunorig(1))
5336            pc_abs_eff = LOG(1._wp - pc_abs_frac) / prototype_lad
5337         ENDIF
5338     ENDIF
5339
5340!--  if radiation scheme is not RRTMG, split diffusion and direct part of the solar downward radiation
5341!--  comming from radiation model and store it in 2D arrays
5342     IF (  radiation_scheme /= 'rrtmg'  )  CALL calc_diffusion_radiation
5343
5344!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5345!--     First pass: direct + diffuse irradiance + thermal
5346!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5347     surfinswdir   = 0._wp !nsurfl
5348     surfins       = 0._wp !nsurfl
5349     surfinl       = 0._wp !nsurfl
5350     surfoutsl(:)  = 0.0_wp !start-end
5351     surfoutll(:)  = 0.0_wp !start-end
5352     IF ( nmrtbl > 0 )  THEN
5353        mrtinsw(:) = 0._wp
5354        mrtinlw(:) = 0._wp
5355     ENDIF
5356     surfinlg(:)  = 0._wp !global
5357
5358
5359!--  Set up thermal radiation from surfaces
5360!--  emiss_surf is defined only for surfaces for which energy balance is calculated
5361!--  Workaround: reorder surface data type back on 1D array including all surfaces,
5362!--  which implies to reorder horizontal and vertical surfaces
5363!
5364!--  Horizontal walls
5365     mm = 1
5366     DO  i = nxl, nxr
5367        DO  j = nys, nyn
5368!--           urban
5369           DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
5370              surfoutll(mm) = SUM ( surf_usm_h%frac(:,m) *                  &
5371                                    surf_usm_h%emissivity(:,m) )            &
5372                                  * sigma_sb                                &
5373                                  * surf_usm_h%pt_surface(m)**4
5374              albedo_surf(mm) = SUM ( surf_usm_h%frac(:,m) *                &
5375                                      surf_usm_h%albedo(:,m) )
5376              emiss_surf(mm)  = SUM ( surf_usm_h%frac(:,m) *                &
5377                                      surf_usm_h%emissivity(:,m) )
5378              mm = mm + 1
5379           ENDDO
5380!--           land
5381           DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
5382              surfoutll(mm) = SUM ( surf_lsm_h%frac(:,m) *                  &
5383                                    surf_lsm_h%emissivity(:,m) )            &
5384                                  * sigma_sb                                &
5385                                  * surf_lsm_h%pt_surface(m)**4
5386              albedo_surf(mm) = SUM ( surf_lsm_h%frac(:,m) *                &
5387                                      surf_lsm_h%albedo(:,m) )
5388              emiss_surf(mm)  = SUM ( surf_lsm_h%frac(:,m) *                &
5389                                      surf_lsm_h%emissivity(:,m) )
5390              mm = mm + 1
5391           ENDDO
5392        ENDDO
5393     ENDDO
5394!
5395!--     Vertical walls
5396     DO  i = nxl, nxr
5397        DO  j = nys, nyn
5398           DO  ll = 0, 3
5399              l = reorder(ll)
5400!--              urban
5401              DO  m = surf_usm_v(l)%start_index(j,i),                       &
5402                      surf_usm_v(l)%end_index(j,i)
5403                 surfoutll(mm) = SUM ( surf_usm_v(l)%frac(:,m) *            &
5404                                       surf_usm_v(l)%emissivity(:,m) )      &
5405                                  * sigma_sb                                &
5406                                  * surf_usm_v(l)%pt_surface(m)**4
5407                 albedo_surf(mm) = SUM ( surf_usm_v(l)%frac(:,m) *          &
5408                                         surf_usm_v(l)%albedo(:,m) )
5409                 emiss_surf(mm)  = SUM ( surf_usm_v(l)%frac(:,m) *          &
5410                                         surf_usm_v(l)%emissivity(:,m) )
5411                 mm = mm + 1
5412              ENDDO
5413!--              land
5414              DO  m = surf_lsm_v(l)%start_index(j,i),                       &
5415                      surf_lsm_v(l)%end_index(j,i)
5416                 surfoutll(mm) = SUM ( surf_lsm_v(l)%frac(:,m) *            &
5417                                       surf_lsm_v(l)%emissivity(:,m) )      &
5418                                  * sigma_sb                                &
5419                                  * surf_lsm_v(l)%pt_surface(m)**4
5420                 albedo_surf(mm) = SUM ( surf_lsm_v(l)%frac(:,m) *          &
5421                                         surf_lsm_v(l)%albedo(:,m) )
5422                 emiss_surf(mm)  = SUM ( surf_lsm_v(l)%frac(:,m) *          &
5423                                         surf_lsm_v(l)%emissivity(:,m) )
5424                 mm = mm + 1
5425              ENDDO
5426           ENDDO
5427        ENDDO
5428     ENDDO
5429
5430#if defined( __parallel )
5431!--     might be optimized and gather only values relevant for current processor
5432     CALL MPI_AllGatherv(surfoutll, nsurfl, MPI_REAL, &
5433                         surfoutl, nsurfs, surfstart, MPI_REAL, comm2d, ierr) !nsurf global
5434     IF ( ierr /= 0 ) THEN
5435         WRITE(9,*) 'Error MPI_AllGatherv1:', ierr, SIZE(surfoutll), nsurfl, &
5436                     SIZE(surfoutl), nsurfs, surfstart
5437         FLUSH(9)
5438     ENDIF
5439#else
5440     surfoutl(:) = surfoutll(:) !nsurf global
5441#endif
5442
5443     IF ( surface_reflections)  THEN
5444        DO  isvf = 1, nsvfl
5445           isurf = svfsurf(1, isvf)
5446           k     = surfl(iz, isurf)
5447           j     = surfl(iy, isurf)
5448           i     = surfl(ix, isurf)
5449           isurfsrc = svfsurf(2, isvf)
5450!
5451!--        For surface-to-surface factors we calculate thermal radiation in 1st pass
5452           IF ( plant_lw_interact )  THEN
5453              surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * svf(2,isvf) * surfoutl(isurfsrc)
5454           ELSE
5455              surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * surfoutl(isurfsrc)
5456           ENDIF
5457        ENDDO
5458     ENDIF
5459!
5460!--  diffuse radiation using sky view factor
5461     DO isurf = 1, nsurfl
5462        j = surfl(iy, isurf)
5463        i = surfl(ix, isurf)
5464        surfinswdif(isurf) = rad_sw_in_diff(j,i) * skyvft(isurf)
5465        IF ( plant_lw_interact )  THEN
5466           surfinlwdif(isurf) = rad_lw_in_diff(j,i) * skyvft(isurf)
5467        ELSE
5468           surfinlwdif(isurf) = rad_lw_in_diff(j,i) * skyvf(isurf)
5469        ENDIF
5470     ENDDO
5471!
5472!--  MRT diffuse irradiance
5473     DO  imrt = 1, nmrtbl
5474        j = mrtbl(iy, imrt)
5475        i = mrtbl(ix, imrt)
5476        mrtinsw(imrt) = mrtskyt(imrt) * rad_sw_in_diff(j,i)
5477        mrtinlw(imrt) = mrtsky(imrt) * rad_lw_in_diff(j,i)
5478     ENDDO
5479
5480     !-- direct radiation
5481     IF ( cos_zenith > 0 )  THEN
5482        !--Identify solar direction vector (discretized number) 1)
5483        !--
5484        j = FLOOR(ACOS(cos_zenith) / pi * raytrace_discrete_elevs)
5485        i = MODULO(NINT(ATAN2(sun_dir_lon, sun_dir_lat)               &
5486                        / (2._wp*pi) * raytrace_discrete_azims-.5_wp, iwp), &
5487                   raytrace_discrete_azims)
5488        isd = dsidir_rev(j, i)
5489!-- TODO: check if isd = -1 to report that this solar position is not precalculated
5490        DO isurf = 1, nsurfl
5491           j = surfl(iy, isurf)
5492           i = surfl(ix, isurf)
5493           surfinswdir(isurf) = rad_sw_in_dir(j,i) *                        &
5494                costheta(surfl(id, isurf)) * dsitrans(isurf, isd) / cos_zenith
5495        ENDDO
5496!
5497!--     MRT direct irradiance
5498        DO  imrt = 1, nmrtbl
5499           j = mrtbl(iy, imrt)
5500           i = mrtbl(ix, imrt)
5501           mrtinsw(imrt) = mrtinsw(imrt) + mrtdsit(imrt, isd) * rad_sw_in_dir(j,i) &
5502                                     / cos_zenith / 4._wp ! normal to sphere
5503        ENDDO
5504     ENDIF
5505!
5506!--  MRT first pass thermal
5507     DO  imrtf = 1, nmrtf
5508        imrt = mrtfsurf(1, imrtf)
5509        isurfsrc = mrtfsurf(2, imrtf)
5510        mrtinlw(imrt) = mrtinlw(imrt) + mrtf(imrtf) * surfoutl(isurfsrc)
5511     ENDDO
5512!
5513!--  Absorption in each local plant canopy grid box from the first atmospheric
5514!--  pass of radiation
5515     IF ( npcbl > 0 )  THEN
5516
5517         pcbinswdir(:) = 0._wp
5518         pcbinswdif(:) = 0._wp
5519         pcbinlw(:) = 0._wp
5520
5521         DO icsf = 1, ncsfl
5522             ipcgb = csfsurf(1, icsf)
5523             i = pcbl(ix,ipcgb)
5524             j = pcbl(iy,ipcgb)
5525             k = pcbl(iz,ipcgb)
5526             isurfsrc = csfsurf(2, icsf)
5527
5528             IF ( isurfsrc == -1 )  THEN
5529!
5530!--             Diffuse radiation from sky
5531                pcbinswdif(ipcgb) = csf(1,icsf) * rad_sw_in_diff(j,i)
5532!
5533!--             Absorbed diffuse LW radiation from sky minus emitted to sky
5534                IF ( plant_lw_interact )  THEN
5535                   pcbinlw(ipcgb) = csf(1,icsf)                                  &
5536                                       * (rad_lw_in_diff(j, i)                   &
5537                                          - sigma_sb * (pt(k,j,i)*exner(k))**4)
5538                ENDIF
5539!
5540!--             Direct solar radiation
5541                IF ( cos_zenith > 0 )  THEN
5542!--                Estimate directed box absorption
5543                   pc_abs_frac = 1._wp - exp(pc_abs_eff * lad_s(k,j,i))
5544!
5545!--                isd has already been established, see 1)
5546                   pcbinswdir(ipcgb) = rad_sw_in_dir(j, i) * pc_box_area &
5547                                       * pc_abs_frac * dsitransc(ipcgb, isd)
5548                ENDIF
5549             ELSE
5550                IF ( plant_lw_interact )  THEN
5551!
5552!--                Thermal emission from plan canopy towards respective face
5553                   pcrad = sigma_sb * (pt(k,j,i) * exner(k))**4 * csf(1,icsf)
5554                   surfinlg(isurfsrc) = surfinlg(isurfsrc) + pcrad
5555!
5556!--                Remove the flux above + absorb LW from first pass from surfaces
5557                   asrc = facearea(surf(id, isurfsrc))
5558                   pcbinlw(ipcgb) = pcbinlw(ipcgb)                      &
5559                                    + (csf(1,icsf) * surfoutl(isurfsrc) & ! Absorb from first pass surf emit
5560                                       - pcrad)                         & ! Remove emitted heatflux
5561                                    * asrc
5562                ENDIF
5563             ENDIF
5564         ENDDO
5565
5566         pcbinsw(:) = pcbinswdir(:) + pcbinswdif(:)
5567     ENDIF
5568
5569     IF ( plant_lw_interact )  THEN
5570!
5571!--     Exchange incoming lw radiation from plant canopy
5572#if defined( __parallel )
5573        CALL MPI_Allreduce(MPI_IN_PLACE, surfinlg, nsurf, MPI_REAL, MPI_SUM, comm2d, ierr)
5574        IF ( ierr /= 0 )  THEN
5575           WRITE (9,*) 'Error MPI_Allreduce:', ierr
5576           FLUSH(9)
5577        ENDIF
5578        surfinl(:) = surfinl(:) + surfinlg(surfstart(myid)+1:surfstart(myid+1))
5579#else
5580        surfinl(:) = surfinl(:) + surfinlg(:)
5581#endif
5582     ENDIF
5583
5584     surfins = surfinswdir + surfinswdif
5585     surfinl = surfinl + surfinlwdif
5586     surfinsw = surfins
5587     surfinlw = surfinl
5588     surfoutsw = 0.0_wp
5589     surfoutlw = surfoutll
5590     surfemitlwl = surfoutll
5591
5592     IF ( .NOT.  surface_reflections )  THEN
5593!
5594!--     Set nrefsteps to 0 to disable reflections       
5595        nrefsteps = 0
5596        surfoutsl = albedo_surf * surfins
5597        surfoutll = (1._wp - emiss_surf) * surfinl
5598        surfoutsw = surfoutsw + surfoutsl
5599        surfoutlw = surfoutlw + surfoutll
5600     ENDIF
5601
5602!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5603!--     Next passes - reflections
5604!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5605     DO refstep = 1, nrefsteps
5606
5607         surfoutsl = albedo_surf * surfins
5608!
5609!--      for non-transparent surfaces, longwave albedo is 1 - emissivity
5610         surfoutll = (1._wp - emiss_surf) * surfinl
5611
5612#if defined( __parallel )
5613         CALL MPI_AllGatherv(surfoutsl, nsurfl, MPI_REAL, &
5614             surfouts, nsurfs, surfstart, MPI_REAL, comm2d, ierr)
5615         IF ( ierr /= 0 )  THEN
5616             WRITE(9,*) 'Error MPI_AllGatherv2:', ierr, SIZE(surfoutsl), nsurfl, &
5617                        SIZE(surfouts), nsurfs, surfstart
5618             FLUSH(9)
5619         ENDIF
5620
5621         CALL MPI_AllGatherv(surfoutll, nsurfl, MPI_REAL, &
5622             surfoutl, nsurfs, surfstart, MPI_REAL, comm2d, ierr)
5623         IF ( ierr /= 0 )  THEN
5624             WRITE(9,*) 'Error MPI_AllGatherv3:', ierr, SIZE(surfoutll), nsurfl, &
5625                        SIZE(surfoutl), nsurfs, surfstart
5626             FLUSH(9)
5627         ENDIF
5628
5629#else
5630         surfouts = surfoutsl
5631         surfoutl = surfoutll
5632#endif
5633!
5634!--      Reset for the input from next reflective pass
5635         surfins = 0._wp
5636         surfinl = 0._wp
5637!
5638!--      Reflected radiation
5639         DO isvf = 1, nsvfl
5640             isurf = svfsurf(1, isvf)
5641             isurfsrc = svfsurf(2, isvf)
5642             surfins(isurf) = surfins(isurf) + svf(1,isvf) * svf(2,isvf) * surfouts(isurfsrc)
5643             IF ( plant_lw_interact )  THEN
5644                surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * svf(2,isvf) * surfoutl(isurfsrc)
5645             ELSE
5646                surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * surfoutl(isurfsrc)
5647             ENDIF
5648         ENDDO
5649!
5650!--      NOTE: PC absorbtion and MRT from reflected can both be done at once
5651!--      after all reflections if we do one more MPI_ALLGATHERV on surfout.
5652!--      Advantage: less local computation. Disadvantage: one more collective
5653!--      MPI call.
5654!
5655!--      Radiation absorbed by plant canopy
5656         DO  icsf = 1, ncsfl
5657             ipcgb = csfsurf(1, icsf)
5658             isurfsrc = csfsurf(2, icsf)
5659             IF ( isurfsrc == -1 )  CYCLE ! sky->face only in 1st pass, not here
5660!
5661!--          Calculate source surface area. If the `surf' array is removed
5662!--          before timestepping starts (future version), then asrc must be
5663!--          stored within `csf'
5664             asrc = facearea(surf(id, isurfsrc))
5665             pcbinsw(ipcgb) = pcbinsw(ipcgb) + csf(1,icsf) * surfouts(isurfsrc) * asrc
5666             IF ( plant_lw_interact )  THEN
5667                pcbinlw(ipcgb) = pcbinlw(ipcgb) + csf(1,icsf) * surfoutl(isurfsrc) * asrc
5668             ENDIF
5669         ENDDO
5670!
5671!--      MRT reflected
5672         DO  imrtf = 1, nmrtf
5673            imrt = mrtfsurf(1, imrtf)
5674            isurfsrc = mrtfsurf(2, imrtf)
5675            mrtinsw(imrt) = mrtinsw(imrt) + mrtft(imrtf) * surfouts(isurfsrc)
5676            mrtinlw(imrt) = mrtinlw(imrt) + mrtf(imrtf) * surfoutl(isurfsrc)
5677         ENDDO
5678
5679         surfinsw = surfinsw  + surfins
5680         surfinlw = surfinlw  + surfinl
5681         surfoutsw = surfoutsw + surfoutsl
5682         surfoutlw = surfoutlw + surfoutll
5683
5684     ENDDO ! refstep
5685
5686!--  push heat flux absorbed by plant canopy to respective 3D arrays
5687     IF ( npcbl > 0 )  THEN
5688         pc_heating_rate(:,:,:) = 0.0_wp
5689         DO ipcgb = 1, npcbl
5690             j = pcbl(iy, ipcgb)
5691             i = pcbl(ix, ipcgb)
5692             k = pcbl(iz, ipcgb)
5693!
5694!--          Following expression equals former kk = k - nzb_s_inner(j,i)
5695             kk = k - get_topography_top_index_ji( j, i, 's' )  !- lad arrays are defined flat
5696             pc_heating_rate(kk, j, i) = (pcbinsw(ipcgb) + pcbinlw(ipcgb)) &
5697                 * pchf_prep(k) * pt(k, j, i) !-- = dT/dt
5698         ENDDO
5699
5700         IF ( humidity .AND. plant_canopy_transpiration ) THEN
5701!--          Calculation of plant canopy transpiration rate and correspondidng latent heat rate
5702             pc_transpiration_rate(:,:,:) = 0.0_wp
5703             pc_latent_rate(:,:,:) = 0.0_wp
5704             DO ipcgb = 1, npcbl
5705                 i = pcbl(ix, ipcgb)
5706                 j = pcbl(iy, ipcgb)
5707                 k = pcbl(iz, ipcgb)
5708                 kk = k - get_topography_top_index_ji( j, i, 's' )  !- lad arrays are defined flat
5709                 CALL pcm_calc_transpiration_rate( i, j, k, kk, pcbinsw(ipcgb), pcbinlw(ipcgb), &
5710                                                   pc_transpiration_rate(kk,j,i), pc_latent_rate(kk,j,i) )
5711              ENDDO
5712         ENDIF
5713     ENDIF
5714!
5715!--  Calculate black body MRT (after all reflections)
5716     IF ( nmrtbl > 0 )  THEN
5717        IF ( mrt_include_sw )  THEN
5718           mrt(:) = ((mrtinsw(:) + mrtinlw(:)) / sigma_sb) ** .25_wp
5719        ELSE
5720           mrt(:) = (mrtinlw(:) / sigma_sb) ** .25_wp
5721        ENDIF
5722     ENDIF
5723!
5724!--     Transfer radiation arrays required for energy balance to the respective data types
5725     DO  i = 1, nsurfl
5726        m  = surfl(im,i)
5727!
5728!--     (1) Urban surfaces
5729!--     upward-facing
5730        IF ( surfl(1,i) == iup_u )  THEN
5731           surf_usm_h%rad_sw_in(m)  = surfinsw(i)
5732           surf_usm_h%rad_sw_out(m) = surfoutsw(i)
5733           surf_usm_h%rad_sw_dir(m) = surfinswdir(i)
5734           surf_usm_h%rad_sw_dif(m) = surfinswdif(i)
5735           surf_usm_h%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -        &
5736                                      surfinswdif(i)
5737           surf_usm_h%rad_sw_res(m) = surfins(i)
5738           surf_usm_h%rad_lw_in(m)  = surfinlw(i)
5739           surf_usm_h%rad_lw_out(m) = surfoutlw(i)
5740           surf_usm_h%rad_net(m)    = surfinsw(i) - surfoutsw(i) +          &
5741                                      surfinlw(i) - surfoutlw(i)
5742           surf_usm_h%rad_net_l(m)  = surf_usm_h%rad_net(m)
5743           surf_usm_h%rad_lw_dif(m) = surfinlwdif(i)
5744           surf_usm_h%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5745           surf_usm_h%rad_lw_res(m) = surfinl(i)
5746!
5747!--     northward-facding
5748        ELSEIF ( surfl(1,i) == inorth_u )  THEN
5749           surf_usm_v(0)%rad_sw_in(m)  = surfinsw(i)
5750           surf_usm_v(0)%rad_sw_out(m) = surfoutsw(i)
5751           surf_usm_v(0)%rad_sw_dir(m) = surfinswdir(i)
5752           surf_usm_v(0)%rad_sw_dif(m) = surfinswdif(i)
5753           surf_usm_v(0)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5754                                         surfinswdif(i)
5755           surf_usm_v(0)%rad_sw_res(m) = surfins(i)
5756           surf_usm_v(0)%rad_lw_in(m)  = surfinlw(i)
5757           surf_usm_v(0)%rad_lw_out(m) = surfoutlw(i)
5758           surf_usm_v(0)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5759                                         surfinlw(i) - surfoutlw(i)
5760           surf_usm_v(0)%rad_net_l(m)  = surf_usm_v(0)%rad_net(m)
5761           surf_usm_v(0)%rad_lw_dif(m) = surfinlwdif(i)
5762           surf_usm_v(0)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5763           surf_usm_v(0)%rad_lw_res(m) = surfinl(i)
5764!
5765!--     southward-facding
5766        ELSEIF ( surfl(1,i) == isouth_u )  THEN
5767           surf_usm_v(1)%rad_sw_in(m)  = surfinsw(i)
5768           surf_usm_v(1)%rad_sw_out(m) = surfoutsw(i)
5769           surf_usm_v(1)%rad_sw_dir(m) = surfinswdir(i)
5770           surf_usm_v(1)%rad_sw_dif(m) = surfinswdif(i)
5771           surf_usm_v(1)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5772                                         surfinswdif(i)
5773           surf_usm_v(1)%rad_sw_res(m) = surfins(i)
5774           surf_usm_v(1)%rad_lw_in(m)  = surfinlw(i)
5775           surf_usm_v(1)%rad_lw_out(m) = surfoutlw(i)
5776           surf_usm_v(1)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5777                                         surfinlw(i) - surfoutlw(i)
5778           surf_usm_v(1)%rad_net_l(m)  = surf_usm_v(1)%rad_net(m)
5779           surf_usm_v(1)%rad_lw_dif(m) = surfinlwdif(i)
5780           surf_usm_v(1)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5781           surf_usm_v(1)%rad_lw_res(m) = surfinl(i)
5782!
5783!--     eastward-facing
5784        ELSEIF ( surfl(1,i) == ieast_u )  THEN
5785           surf_usm_v(2)%rad_sw_in(m)  = surfinsw(i)
5786           surf_usm_v(2)%rad_sw_out(m) = surfoutsw(i)
5787           surf_usm_v(2)%rad_sw_dir(m) = surfinswdir(i)
5788           surf_usm_v(2)%rad_sw_dif(m) = surfinswdif(i)
5789           surf_usm_v(2)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5790                                         surfinswdif(i)
5791           surf_usm_v(2)%rad_sw_res(m) = surfins(i)
5792           surf_usm_v(2)%rad_lw_in(m)  = surfinlw(i)
5793           surf_usm_v(2)%rad_lw_out(m) = surfoutlw(i)
5794           surf_usm_v(2)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5795                                         surfinlw(i) - surfoutlw(i)
5796           surf_usm_v(2)%rad_net_l(m)  = surf_usm_v(2)%rad_net(m)
5797           surf_usm_v(2)%rad_lw_dif(m) = surfinlwdif(i)
5798           surf_usm_v(2)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5799           surf_usm_v(2)%rad_lw_res(m) = surfinl(i)
5800!
5801!--     westward-facding
5802        ELSEIF ( surfl(1,i) == iwest_u )  THEN
5803           surf_usm_v(3)%rad_sw_in(m)  = surfinsw(i)
5804           surf_usm_v(3)%rad_sw_out(m) = surfoutsw(i)
5805           surf_usm_v(3)%rad_sw_dir(m) = surfinswdir(i)
5806           surf_usm_v(3)%rad_sw_dif(m) = surfinswdif(i)
5807           surf_usm_v(3)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5808                                         surfinswdif(i)
5809           surf_usm_v(3)%rad_sw_res(m) = surfins(i)
5810           surf_usm_v(3)%rad_lw_in(m)  = surfinlw(i)
5811           surf_usm_v(3)%rad_lw_out(m) = surfoutlw(i)
5812           surf_usm_v(3)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5813                                         surfinlw(i) - surfoutlw(i)
5814           surf_usm_v(3)%rad_net_l(m)  = surf_usm_v(3)%rad_net(m)
5815           surf_usm_v(3)%rad_lw_dif(m) = surfinlwdif(i)
5816           surf_usm_v(3)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5817           surf_usm_v(3)%rad_lw_res(m) = surfinl(i)
5818!
5819!--     (2) land surfaces
5820!--     upward-facing
5821        ELSEIF ( surfl(1,i) == iup_l )  THEN
5822           surf_lsm_h%rad_sw_in(m)  = surfinsw(i)
5823           surf_lsm_h%rad_sw_out(m) = surfoutsw(i)
5824           surf_lsm_h%rad_sw_dir(m) = surfinswdir(i)
5825           surf_lsm_h%rad_sw_dif(m) = surfinswdif(i)
5826           surf_lsm_h%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -        &
5827                                         surfinswdif(i)
5828           surf_lsm_h%rad_sw_res(m) = surfins(i)
5829           surf_lsm_h%rad_lw_in(m)  = surfinlw(i)
5830           surf_lsm_h%rad_lw_out(m) = surfoutlw(i)
5831           surf_lsm_h%rad_net(m)    = surfinsw(i) - surfoutsw(i) +          &
5832                                      surfinlw(i) - surfoutlw(i)
5833           surf_lsm_h%rad_lw_dif(m) = surfinlwdif(i)
5834           surf_lsm_h%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5835           surf_lsm_h%rad_lw_res(m) = surfinl(i)
5836!
5837!--     northward-facding
5838        ELSEIF ( surfl(1,i) == inorth_l )  THEN
5839           surf_lsm_v(0)%rad_sw_in(m)  = surfinsw(i)
5840           surf_lsm_v(0)%rad_sw_out(m) = surfoutsw(i)
5841           surf_lsm_v(0)%rad_sw_dir(m) = surfinswdir(i)
5842           surf_lsm_v(0)%rad_sw_dif(m) = surfinswdif(i)
5843           surf_lsm_v(0)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5844                                         surfinswdif(i)
5845           surf_lsm_v(0)%rad_sw_res(m) = surfins(i)
5846           surf_lsm_v(0)%rad_lw_in(m)  = surfinlw(i)
5847           surf_lsm_v(0)%rad_lw_out(m) = surfoutlw(i)
5848           surf_lsm_v(0)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5849                                         surfinlw(i) - surfoutlw(i)
5850           surf_lsm_v(0)%rad_lw_dif(m) = surfinlwdif(i)
5851           surf_lsm_v(0)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5852           surf_lsm_v(0)%rad_lw_res(m) = surfinl(i)
5853!
5854!--     southward-facding
5855        ELSEIF ( surfl(1,i) == isouth_l )  THEN
5856           surf_lsm_v(1)%rad_sw_in(m)  = surfinsw(i)
5857           surf_lsm_v(1)%rad_sw_out(m) = surfoutsw(i)
5858           surf_lsm_v(1)%rad_sw_dir(m) = surfinswdir(i)
5859           surf_lsm_v(1)%rad_sw_dif(m) = surfinswdif(i)
5860           surf_lsm_v(1)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5861                                         surfinswdif(i)
5862           surf_lsm_v(1)%rad_sw_res(m) = surfins(i)
5863           surf_lsm_v(1)%rad_lw_in(m)  = surfinlw(i)
5864           surf_lsm_v(1)%rad_lw_out(m) = surfoutlw(i)
5865           surf_lsm_v(1)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5866                                         surfinlw(i) - surfoutlw(i)
5867           surf_lsm_v(1)%rad_lw_dif(m) = surfinlwdif(i)
5868           surf_lsm_v(1)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5869           surf_lsm_v(1)%rad_lw_res(m) = surfinl(i)
5870!
5871!--     eastward-facing
5872        ELSEIF ( surfl(1,i) == ieast_l )  THEN
5873           surf_lsm_v(2)%rad_sw_in(m)  = surfinsw(i)
5874           surf_lsm_v(2)%rad_sw_out(m) = surfoutsw(i)
5875           surf_lsm_v(2)%rad_sw_dir(m) = surfinswdir(i)
5876           surf_lsm_v(2)%rad_sw_dif(m) = surfinswdif(i)
5877           surf_lsm_v(2)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5878                                         surfinswdif(i)
5879           surf_lsm_v(2)%rad_sw_res(m) = surfins(i)
5880           surf_lsm_v(2)%rad_lw_in(m)  = surfinlw(i)
5881           surf_lsm_v(2)%rad_lw_out(m) = surfoutlw(i)
5882           surf_lsm_v(2)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5883                                         surfinlw(i) - surfoutlw(i)
5884           surf_lsm_v(2)%rad_lw_dif(m) = surfinlwdif(i)
5885           surf_lsm_v(2)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5886           surf_lsm_v(2)%rad_lw_res(m) = surfinl(i)
5887!
5888!--     westward-facing
5889        ELSEIF ( surfl(1,i) == iwest_l )  THEN
5890           surf_lsm_v(3)%rad_sw_in(m)  = surfinsw(i)
5891           surf_lsm_v(3)%rad_sw_out(m) = surfoutsw(i)
5892           surf_lsm_v(3)%rad_sw_dir(m) = surfinswdir(i)
5893           surf_lsm_v(3)%rad_sw_dif(m) = surfinswdif(i)
5894           surf_lsm_v(3)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5895                                         surfinswdif(i)
5896           surf_lsm_v(3)%rad_sw_res(m) = surfins(i)
5897           surf_lsm_v(3)%rad_lw_in(m)  = surfinlw(i)
5898           surf_lsm_v(3)%rad_lw_out(m) = surfoutlw(i)
5899           surf_lsm_v(3)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5900                                         surfinlw(i) - surfoutlw(i)
5901           surf_lsm_v(3)%rad_lw_dif(m) = surfinlwdif(i)
5902           surf_lsm_v(3)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5903           surf_lsm_v(3)%rad_lw_res(m) = surfinl(i)
5904        ENDIF
5905
5906     ENDDO
5907
5908     DO  m = 1, surf_usm_h%ns
5909        surf_usm_h%surfhf(m) = surf_usm_h%rad_sw_in(m)  +                   &
5910                               surf_usm_h%rad_lw_in(m)  -                   &
5911                               surf_usm_h%rad_sw_out(m) -                   &
5912                               surf_usm_h%rad_lw_out(m)
5913     ENDDO
5914     DO  m = 1, surf_lsm_h%ns
5915        surf_lsm_h%surfhf(m) = surf_lsm_h%rad_sw_in(m)  +                   &
5916                               surf_lsm_h%rad_lw_in(m)  -                   &
5917                               surf_lsm_h%rad_sw_out(m) -                   &
5918                               surf_lsm_h%rad_lw_out(m)
5919     ENDDO
5920
5921     DO  l = 0, 3
5922!--     urban
5923        DO  m = 1, surf_usm_v(l)%ns
5924           surf_usm_v(l)%surfhf(m) = surf_usm_v(l)%rad_sw_in(m)  +          &
5925                                     surf_usm_v(l)%rad_lw_in(m)  -          &
5926                                     surf_usm_v(l)%rad_sw_out(m) -          &
5927                                     surf_usm_v(l)%rad_lw_out(m)
5928        ENDDO
5929!--     land
5930        DO  m = 1, surf_lsm_v(l)%ns
5931           surf_lsm_v(l)%surfhf(m) = surf_lsm_v(l)%rad_sw_in(m)  +          &
5932                                     surf_lsm_v(l)%rad_lw_in(m)  -          &
5933                                     surf_lsm_v(l)%rad_sw_out(m) -          &
5934                                     surf_lsm_v(l)%rad_lw_out(m)
5935
5936        ENDDO
5937     ENDDO
5938!
5939!--  Calculate the average temperature, albedo, and emissivity for urban/land
5940!--  domain when using average_radiation in the respective radiation model
5941
5942!--  calculate horizontal area
5943! !!! ATTENTION!!! uniform grid is assumed here
5944     area_hor = (nx+1) * (ny+1) * dx * dy
5945!
5946!--  absorbed/received SW & LW and emitted LW energy of all physical
5947!--  surfaces (land and urban) in local processor
5948     pinswl = 0._wp
5949     pinlwl = 0._wp
5950     pabsswl = 0._wp
5951     pabslwl = 0._wp
5952     pemitlwl = 0._wp
5953     emiss_sum_surfl = 0._wp
5954     area_surfl = 0._wp
5955     DO  i = 1, nsurfl
5956        d = surfl(id, i)
5957!--  received SW & LW
5958        pinswl = pinswl + (surfinswdir(i) + surfinswdif(i)) * facearea(d)
5959        pinlwl = pinlwl + surfinlwdif(i) * facearea(d)
5960!--   absorbed SW & LW
5961        pabsswl = pabsswl + (1._wp - albedo_surf(i)) *                   &
5962                                                surfinsw(i) * facearea(d)
5963        pabslwl = pabslwl + emiss_surf(i) * surfinlw(i) * facearea(d)
5964!--   emitted LW
5965        pemitlwl = pemitlwl + surfemitlwl(i) * facearea(d)
5966!--   emissivity and area sum
5967        emiss_sum_surfl = emiss_sum_surfl + emiss_surf(i) * facearea(d)
5968        area_surfl = area_surfl + facearea(d)
5969     END DO
5970!
5971!--  add the absorbed SW energy by plant canopy
5972     IF ( npcbl > 0 )  THEN
5973        pabsswl = pabsswl + SUM(pcbinsw)
5974        pabslwl = pabslwl + SUM(pcbinlw)
5975        pinswl = pinswl + SUM(pcbinswdir) + SUM(pcbinswdif)
5976     ENDIF
5977!
5978!--  gather all rad flux energy in all processors
5979#if defined( __parallel )
5980     CALL MPI_ALLREDUCE( pinswl, pinsw, 1, MPI_REAL, MPI_SUM, comm2d, ierr)
5981     IF ( ierr /= 0 ) THEN
5982         WRITE(9,*) 'Error MPI_AllReduce5:', ierr, pinswl, pinsw
5983         FLUSH(9)
5984     ENDIF
5985     CALL MPI_ALLREDUCE( pinlwl, pinlw, 1, MPI_REAL, MPI_SUM, comm2d, ierr)
5986     IF ( ierr /= 0 ) THEN
5987         WRITE(9,*) 'Error MPI_AllReduce6:', ierr, pinlwl, pinlw
5988         FLUSH(9)
5989     ENDIF
5990     CALL MPI_ALLREDUCE( pabsswl, pabssw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5991     IF ( ierr /= 0 ) THEN
5992         WRITE(9,*) 'Error MPI_AllReduce7:', ierr, pabsswl, pabssw
5993         FLUSH(9)
5994     ENDIF
5995     CALL MPI_ALLREDUCE( pabslwl, pabslw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5996     IF ( ierr /= 0 ) THEN
5997         WRITE(9,*) 'Error MPI_AllReduce8:', ierr, pabslwl, pabslw
5998         FLUSH(9)
5999     ENDIF
6000     CALL MPI_ALLREDUCE( pemitlwl, pemitlw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
6001     IF ( ierr /= 0 ) THEN
6002         WRITE(9,*) 'Error MPI_AllReduce8:', ierr, pemitlwl, pemitlw
6003         FLUSH(9)
6004     ENDIF
6005     CALL MPI_ALLREDUCE( emiss_sum_surfl, emiss_sum_surf, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
6006     IF ( ierr /= 0 ) THEN
6007         WRITE(9,*) 'Error MPI_AllReduce9:', ierr, emiss_sum_surfl, emiss_sum_surf
6008         FLUSH(9)
6009     ENDIF
6010     CALL MPI_ALLREDUCE( area_surfl, area_surf, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
6011     IF ( ierr /= 0 ) THEN
6012         WRITE(9,*) 'Error MPI_AllReduce10:', ierr, area_surfl, area_surf
6013         FLUSH(9)
6014     ENDIF
6015#else
6016     pinsw = pinswl
6017     pinlw = pinlwl
6018     pabssw = pabsswl
6019     pabslw = pabslwl
6020     pemitlw = pemitlwl
6021     emiss_sum_surf = emiss_sum_surfl
6022     area_surf = area_surfl
6023#endif
6024
6025!--  (1) albedo
6026     IF ( pinsw /= 0.0_wp )  &
6027          albedo_urb = (pinsw - pabssw) / pinsw
6028!--  (2) average emmsivity
6029     IF ( area_surf /= 0.0_wp ) &
6030          emissivity_urb = emiss_sum_surf / area_surf
6031!
6032!--  Temporally comment out calculation of effective radiative temperature.
6033!--  See below for more explanation.
6034!--  (3) temperature
6035!--   first we calculate an effective horizontal area to account for
6036!--   the effect of vertical surfaces (which contributes to LW emission)
6037!--   We simply use the ratio of the total LW to the incoming LW flux
6038      area_hor = pinlw/rad_lw_in_diff(nyn,nxl)
6039      t_rad_urb = ( (pemitlw - pabslw + emissivity_urb*pinlw) / &
6040           (emissivity_urb*sigma_sb * area_hor) )**0.25_wp
6041
6042     IF ( debug_output_timestep )  CALL debug_message( 'radiation_interaction', 'end' )
6043
6044
6045    CONTAINS
6046
6047!------------------------------------------------------------------------------!
6048!> Calculates radiation absorbed by box with given size and LAD.
6049!>
6050!> Simulates resol**2 rays (by equally spacing a bounding horizontal square
6051!> conatining all possible rays that would cross the box) and calculates
6052!> average transparency per ray. Returns fraction of absorbed radiation flux
6053!> and area for which this fraction is effective.
6054!------------------------------------------------------------------------------!
6055    PURE SUBROUTINE box_absorb(boxsize, resol, dens, uvec, area, absorb)
6056       IMPLICIT NONE
6057
6058       REAL(wp), DIMENSION(3), INTENT(in) :: &
6059            boxsize, &      !< z, y, x size of box in m
6060            uvec            !< z, y, x unit vector of incoming flux
6061       INTEGER(iwp), INTENT(in) :: &
6062            resol           !< No. of rays in x and y dimensions
6063       REAL(wp), INTENT(in) :: &
6064            dens            !< box density (e.g. Leaf Area Density)
6065       REAL(wp), INTENT(out) :: &
6066            area, &         !< horizontal area for flux absorbtion
6067            absorb          !< fraction of absorbed flux
6068       REAL(wp) :: &
6069            xshift, yshift, &
6070            xmin, xmax, ymin, ymax, &
6071            xorig, yorig, &
6072            dx1, dy1, dz1, dx2, dy2, dz2, &
6073            crdist, &
6074            transp
6075       INTEGER(iwp) :: &
6076            i, j
6077
6078       xshift = uvec(3) / uvec(1) * boxsize(1)
6079       xmin = min(0._wp, -xshift)
6080       xmax = boxsize(3) + max(0._wp, -xshift)
6081       yshift = uvec(2) / uvec(1) * boxsize(1)
6082       ymin = min(0._wp, -yshift)
6083       ymax = boxsize(2) + max(0._wp, -yshift)
6084
6085       transp = 0._wp
6086       DO i = 1, resol
6087          xorig = xmin + (xmax-xmin) * (i-.5_wp) / resol
6088          DO j = 1, resol
6089             yorig = ymin + (ymax-ymin) * (j-.5_wp) / resol
6090
6091             dz1 = 0._wp
6092             dz2 = boxsize(1)/uvec(1)
6093
6094             IF ( uvec(2) > 0._wp )  THEN
6095                dy1 = -yorig             / uvec(2) !< crossing with y=0
6096                dy2 = (boxsize(2)-yorig) / uvec(2) !< crossing with y=boxsize(2)
6097             ELSE !uvec(2)==0
6098                dy1 = -huge(1._wp)
6099                dy2 = huge(1._wp)
6100             ENDIF
6101
6102             IF ( uvec(3) > 0._wp )  THEN
6103                dx1 = -xorig             / uvec(3) !< crossing with x=0
6104                dx2 = (boxsize(3)-xorig) / uvec(3) !< crossing with x=boxsize(3)
6105             ELSE !uvec(3)==0
6106                dx1 = -huge(1._wp)
6107                dx2 = huge(1._wp)
6108             ENDIF
6109
6110             crdist = max(0._wp, (min(dz2, dy2, dx2) - max(dz1, dy1, dx1)))
6111             transp = transp + exp(-ext_coef * dens * crdist)
6112          ENDDO
6113       ENDDO
6114       transp = transp / resol**2
6115       area = (boxsize(3)+xshift)*(boxsize(2)+yshift)
6116       absorb = 1._wp - transp
6117
6118    END SUBROUTINE box_absorb
6119
6120!------------------------------------------------------------------------------!
6121! Description:
6122! ------------
6123!> This subroutine splits direct and diffusion dw radiation
6124!> It sould not be called in case the radiation model already does it
6125!> It follows Boland, Ridley & Brown (2008)
6126!------------------------------------------------------------------------------!
6127    SUBROUTINE calc_diffusion_radiation 
6128   
6129        REAL(wp), PARAMETER                          :: lowest_solarUp = 0.1_wp  !< limit the sun elevation to protect stability of the calculation
6130        INTEGER(iwp)                                 :: i, j
6131        REAL(wp)                                     ::  year_angle              !< angle
6132        REAL(wp)                                     ::  etr                     !< extraterestrial radiation
6133        REAL(wp)                                     ::  corrected_solarUp       !< corrected solar up radiation
6134        REAL(wp)                                     ::  horizontalETR           !< horizontal extraterestrial radiation
6135        REAL(wp)                                     ::  clearnessIndex          !< clearness index
6136        REAL(wp)                                     ::  diff_frac               !< diffusion fraction of the radiation
6137
6138       
6139!--     Calculate current day and time based on the initial values and simulation time
6140        year_angle = ( (day_of_year_init * 86400) + time_utc_init              &
6141                        + time_since_reference_point )  * d_seconds_year       &
6142                        * 2.0_wp * pi
6143       
6144        etr = solar_constant * (1.00011_wp +                                   &
6145                          0.034221_wp * cos(year_angle) +                      &
6146                          0.001280_wp * sin(year_angle) +                      &
6147                          0.000719_wp * cos(2.0_wp * year_angle) +             &
6148                          0.000077_wp * sin(2.0_wp * year_angle))
6149       
6150!--   
6151!--     Under a very low angle, we keep extraterestrial radiation at
6152!--     the last small value, therefore the clearness index will be pushed
6153!--     towards 0 while keeping full continuity.
6154!--   
6155        IF ( cos_zenith <= lowest_solarUp )  THEN
6156            corrected_solarUp = lowest_solarUp
6157        ELSE
6158            corrected_solarUp = cos_zenith
6159        ENDIF
6160       
6161        horizontalETR = etr * corrected_solarUp
6162       
6163        DO i = nxl, nxr
6164            DO j = nys, nyn
6165                clearnessIndex = rad_sw_in(0,j,i) / horizontalETR
6166                diff_frac = 1.0_wp / (1.0_wp + exp(-5.0033_wp + 8.6025_wp * clearnessIndex))
6167                rad_sw_in_diff(j,i) = rad_sw_in(0,j,i) * diff_frac
6168                rad_sw_in_dir(j,i)  = rad_sw_in(0,j,i) * (1.0_wp - diff_frac)
6169                rad_lw_in_diff(j,i) = rad_lw_in(0,j,i)
6170            ENDDO
6171        ENDDO
6172       
6173    END SUBROUTINE calc_diffusion_radiation
6174
6175 END SUBROUTINE radiation_interaction
6176   
6177!------------------------------------------------------------------------------!
6178! Description:
6179! ------------
6180!> This subroutine initializes structures needed for radiative transfer
6181!> model. This model calculates transformation processes of the
6182!> radiation inside urban and land canopy layer. The module includes also
6183!> the interaction of the radiation with the resolved plant canopy.
6184!>
6185!> For more info. see Resler et al. 2017
6186!>
6187!> The new version 2.0 was radically rewriten, the discretization scheme
6188!> has been changed. This new version significantly improves effectivity
6189!> of the paralelization and the scalability of the model.
6190!>
6191!------------------------------------------------------------------------------!
6192    SUBROUTINE radiation_interaction_init
6193
6194       USE control_parameters,                                                 &
6195           ONLY:  dz_stretch_level_start
6196           
6197       USE netcdf_data_input_mod,                                              &
6198           ONLY:  leaf_area_density_f
6199
6200       USE plant_canopy_model_mod,                                             &
6201           ONLY:  pch_index, lad_s
6202
6203       IMPLICIT NONE
6204
6205       INTEGER(iwp) :: i, j, k, l, m, d
6206       INTEGER(iwp) :: k_topo     !< vertical index indicating topography top for given (j,i)
6207       INTEGER(iwp) :: nzptl, nzubl, nzutl, isurf, ipcgb, imrt
6208       REAL(wp)     :: mrl
6209#if defined( __parallel )
6210       INTEGER(iwp), DIMENSION(:), POINTER, SAVE ::  gridsurf_rma   !< fortran pointer, but lower bounds are 1
6211       TYPE(c_ptr)                               ::  gridsurf_rma_p !< allocated c pointer
6212       INTEGER(iwp)                              ::  minfo          !< MPI RMA window info handle
6213#endif
6214
6215!
6216!--     precalculate face areas for different face directions using normal vector
6217        DO d = 0, nsurf_type
6218            facearea(d) = 1._wp
6219            IF ( idir(d) == 0 ) facearea(d) = facearea(d) * dx
6220            IF ( jdir(d) == 0 ) facearea(d) = facearea(d) * dy
6221            IF ( kdir(d) == 0 ) facearea(d) = facearea(d) * dz(1)
6222        ENDDO
6223!
6224!--    Find nz_urban_b, nz_urban_t, nz_urban via wall_flag_0 array (nzb_s_inner will be
6225!--    removed later). The following contruct finds the lowest / largest index
6226!--    for any upward-facing wall (see bit 12).
6227       nzubl = MINVAL( get_topography_top_index( 's' ) )
6228       nzutl = MAXVAL( get_topography_top_index( 's' ) )
6229
6230       nzubl = MAX( nzubl, nzb )
6231
6232       IF ( plant_canopy )  THEN
6233!--        allocate needed arrays
6234           ALLOCATE( pct(nys:nyn,nxl:nxr) )
6235           ALLOCATE( pch(nys:nyn,nxl:nxr) )
6236
6237!--        calculate plant canopy height
6238           npcbl = 0
6239           pct   = 0
6240           pch   = 0
6241           DO i = nxl, nxr
6242               DO j = nys, nyn
6243!
6244!--                Find topography top index
6245                   k_topo = get_topography_top_index_ji( j, i, 's' )
6246
6247                   DO k = nzt+1, 0, -1
6248                       IF ( lad_s(k,j,i) /= 0.0_wp )  THEN
6249!--                        we are at the top of the pcs
6250                           pct(j,i) = k + k_topo
6251                           pch(j,i) = k
6252                           npcbl = npcbl + pch(j,i)
6253                           EXIT
6254                       ENDIF
6255                   ENDDO
6256               ENDDO
6257           ENDDO
6258
6259           nzutl = MAX( nzutl, MAXVAL( pct ) )
6260           nzptl = MAXVAL( pct )
6261!--        code of plant canopy model uses parameter pch_index
6262!--        we need to setup it here to right value
6263!--        (pch_index, lad_s and other arrays in PCM are defined flat)
6264           pch_index = MERGE( leaf_area_density_f%nz - 1, MAXVAL( pch ),       &
6265                              leaf_area_density_f%from_file )
6266
6267           prototype_lad = MAXVAL( lad_s ) * .9_wp  !< better be *1.0 if lad is either 0 or maxval(lad) everywhere
6268           IF ( prototype_lad <= 0._wp ) prototype_lad = .3_wp
6269           !WRITE(message_string, '(a,f6.3)') 'Precomputing effective box optical ' &
6270           !    // 'depth using prototype leaf area density = ', prototype_lad
6271           !CALL message('radiation_interaction_init', 'PA0520', 0, 0, -1, 6, 0)
6272       ENDIF
6273
6274       nzutl = MIN( nzutl + nzut_free, nzt )
6275
6276#if defined( __parallel )
6277       CALL MPI_AllReduce(nzubl, nz_urban_b, 1, MPI_INTEGER, MPI_MIN, comm2d, ierr )
6278       IF ( ierr /= 0 ) THEN
6279           WRITE(9,*) 'Error MPI_AllReduce11:', ierr, nzubl, nz_urban_b
6280           FLUSH(9)
6281       ENDIF
6282       CALL MPI_AllReduce(nzutl, nz_urban_t, 1, MPI_INTEGER, MPI_MAX, comm2d, ierr )
6283       IF ( ierr /= 0 ) THEN
6284           WRITE(9,*) 'Error MPI_AllReduce12:', ierr, nzutl, nz_urban_t
6285           FLUSH(9)
6286       ENDIF
6287       CALL MPI_AllReduce(nzptl, nz_plant_t, 1, MPI_INTEGER, MPI_MAX, comm2d, ierr )
6288       IF ( ierr /= 0 ) THEN
6289           WRITE(9,*) 'Error MPI_AllReduce13:', ierr, nzptl, nz_plant_t
6290           FLUSH(9)
6291       ENDIF
6292#else
6293       nz_urban_b = nzubl
6294       nz_urban_t = nzutl
6295       nz_plant_t = nzptl
6296#endif
6297!
6298!--    Stretching (non-uniform grid spacing) is not considered in the radiation
6299!--    model. Therefore, vertical stretching has to be applied above the area
6300!--    where the parts of the radiation model which assume constant grid spacing
6301!--    are active. ABS (...) is required because the default value of
6302!--    dz_stretch_level_start is -9999999.9_wp (negative).
6303       IF ( ABS( dz_stretch_level_start(1) ) <= zw(nz_urban_t) ) THEN
6304          WRITE( message_string, * ) 'The lowest level where vertical ',       &
6305                                     'stretching is applied have to be ',      &
6306                                     'greater than ', zw(nz_urban_t)
6307          CALL message( 'radiation_interaction_init', 'PA0496', 1, 2, 0, 6, 0 )
6308       ENDIF 
6309!
6310!--    global number of urban and plant layers
6311       nz_urban = nz_urban_t - nz_urban_b + 1
6312       nz_plant = nz_plant_t - nz_urban_b + 1
6313!
6314!--    check max_raytracing_dist relative to urban surface layer height
6315       mrl = 2.0_wp * nz_urban * dz(1)
6316!--    set max_raytracing_dist to double the urban surface layer height, if not set
6317       IF ( max_raytracing_dist == -999.0_wp ) THEN
6318          max_raytracing_dist = mrl
6319       ENDIF
6320!--    check if max_raytracing_dist set too low (here we only warn the user. Other
6321!      option is to correct the value again to double the urban surface layer height)
6322       IF ( max_raytracing_dist  <  mrl ) THEN
6323          WRITE(message_string, '(a,f6.1)') 'Max_raytracing_dist is set less than ', &
6324               'double the urban surface layer height, i.e. ', mrl
6325          CALL message('radiation_interaction_init', 'PA0521', 0, 0, -1, 6, 0)
6326       ENDIF
6327!        IF ( max_raytracing_dist <= mrl ) THEN
6328!           IF ( max_raytracing_dist /= -999.0_wp ) THEN
6329! !--          max_raytracing_dist too low
6330!              WRITE(message_string, '(a,f6.1)') 'Max_raytracing_dist too low, ' &
6331!                    // 'override to value ', mrl
6332!              CALL message('radiation_interaction_init', 'PA0521', 0, 0, -1, 6, 0)
6333!           ENDIF
6334!           max_raytracing_dist = mrl
6335!        ENDIF
6336!
6337!--    allocate urban surfaces grid
6338!--    calc number of surfaces in local proc
6339       IF ( debug_output )  CALL debug_message( 'calculation of indices for surfaces', 'info' )
6340
6341       nsurfl = 0
6342!
6343!--    Number of horizontal surfaces including land- and roof surfaces in both USM and LSM. Note that
6344!--    All horizontal surface elements are already counted in surface_mod.
6345       startland = 1
6346       nsurfl    = surf_usm_h%ns + surf_lsm_h%ns
6347       endland   = nsurfl
6348       nlands    = endland - startland + 1
6349
6350!
6351!--    Number of vertical surfaces in both USM and LSM. Note that all vertical surface elements are
6352!--    already counted in surface_mod.
6353       startwall = nsurfl+1
6354       DO  i = 0,3
6355          nsurfl = nsurfl + surf_usm_v(i)%ns + surf_lsm_v(i)%ns
6356       ENDDO
6357       endwall = nsurfl
6358       nwalls  = endwall - startwall + 1
6359       dirstart = (/ startland, startwall, startwall, startwall, startwall /)
6360       dirend = (/ endland, endwall, endwall, endwall, endwall /)
6361
6362!--    fill gridpcbl and pcbl
6363       IF ( npcbl > 0 )  THEN
6364           ALLOCATE( pcbl(iz:ix, 1:npcbl) )
6365           ALLOCATE( gridpcbl(nz_urban_b:nz_plant_t,nys:nyn,nxl:nxr) )
6366           pcbl = -1
6367           gridpcbl(:,:,:) = 0
6368           ipcgb = 0
6369           DO i = nxl, nxr
6370               DO j = nys, nyn
6371!
6372!--                Find topography top index
6373                   k_topo = get_topography_top_index_ji( j, i, 's' )
6374
6375                   DO k = k_topo + 1, pct(j,i)
6376                       ipcgb = ipcgb + 1
6377                       gridpcbl(k,j,i) = ipcgb
6378                       pcbl(:,ipcgb) = (/ k, j, i /)
6379                   ENDDO
6380               ENDDO
6381           ENDDO
6382           ALLOCATE( pcbinsw( 1:npcbl ) )
6383           ALLOCATE( pcbinswdir( 1:npcbl ) )
6384           ALLOCATE( pcbinswdif( 1:npcbl ) )
6385           ALLOCATE( pcbinlw( 1:npcbl ) )
6386       ENDIF
6387
6388!
6389!--    Fill surfl (the ordering of local surfaces given by the following
6390!--    cycles must not be altered, certain file input routines may depend
6391!--    on it).
6392!
6393!--    We allocate the array as linear and then use a two-dimensional pointer
6394!--    into it, because some MPI implementations crash with 2D-allocated arrays.
6395       ALLOCATE(surfl_linear(nidx_surf*nsurfl))
6396       surfl(1:nidx_surf,1:nsurfl) => surfl_linear(1:nidx_surf*nsurfl)
6397       isurf = 0
6398       IF ( rad_angular_discretization )  THEN
6399!
6400!--       Allocate and fill the reverse indexing array gridsurf
6401#if defined( __parallel )
6402!
6403!--       raytrace_mpi_rma is asserted
6404
6405          CALL MPI_Info_create(minfo, ierr)
6406          IF ( ierr /= 0 ) THEN
6407              WRITE(9,*) 'Error MPI_Info_create1:', ierr
6408              FLUSH(9)
6409          ENDIF
6410          CALL MPI_Info_set(minfo, 'accumulate_ordering', 'none', ierr)
6411          IF ( ierr /= 0 ) THEN
6412              WRITE(9,*) 'Error MPI_Info_set1:', ierr
6413              FLUSH(9)
6414          ENDIF
6415          CALL MPI_Info_set(minfo, 'accumulate_ops', 'same_op', ierr)
6416          IF ( ierr /= 0 ) THEN
6417              WRITE(9,*) 'Error MPI_Info_set2:', ierr
6418              FLUSH(9)
6419          ENDIF
6420          CALL MPI_Info_set(minfo, 'same_size', 'true', ierr)
6421          IF ( ierr /= 0 ) THEN
6422              WRITE(9,*) 'Error MPI_Info_set3:', ierr
6423              FLUSH(9)
6424          ENDIF
6425          CALL MPI_Info_set(minfo, 'same_disp_unit', 'true', ierr)
6426          IF ( ierr /= 0 ) THEN
6427              WRITE(9,*) 'Error MPI_Info_set4:', ierr
6428              FLUSH(9)
6429          ENDIF
6430
6431          CALL MPI_Win_allocate(INT(STORAGE_SIZE(1_iwp)/8*nsurf_type_u*nz_urban*nny*nnx, &
6432                                    kind=MPI_ADDRESS_KIND), STORAGE_SIZE(1_iwp)/8,  &
6433                                minfo, comm2d, gridsurf_rma_p, win_gridsurf, ierr)
6434          IF ( ierr /= 0 ) THEN
6435              WRITE(9,*) 'Error MPI_Win_allocate1:', ierr, &
6436                 INT(STORAGE_SIZE(1_iwp)/8*nsurf_type_u*nz_urban*nny*nnx,kind=MPI_ADDRESS_KIND), &
6437                 STORAGE_SIZE(1_iwp)/8, win_gridsurf
6438              FLUSH(9)
6439          ENDIF
6440
6441          CALL MPI_Info_free(minfo, ierr)
6442          IF ( ierr /= 0 ) THEN
6443              WRITE(9,*) 'Error MPI_Info_free1:', ierr
6444              FLUSH(9)
6445          ENDIF
6446
6447!
6448!--       On Intel compilers, calling c_f_pointer to transform a C pointer
6449!--       directly to a multi-dimensional Fotran pointer leads to strange
6450!--       errors on dimension boundaries. However, transforming to a 1D
6451!--       pointer and then redirecting a multidimensional pointer to it works
6452!--       fine.
6453          CALL c_f_pointer(gridsurf_rma_p, gridsurf_rma, (/ nsurf_type_u*nz_urban*nny*nnx /))
6454          gridsurf(0:nsurf_type_u-1, nz_urban_b:nz_urban_t, nys:nyn, nxl:nxr) =>                &
6455                     gridsurf_rma(1:nsurf_type_u*nz_urban*nny*nnx)
6456#else
6457          ALLOCATE(gridsurf(0:nsurf_type_u-1,nz_urban_b:nz_urban_t,nys:nyn,nxl:nxr) )
6458#endif
6459          gridsurf(:,:,:,:) = -999
6460       ENDIF
6461
6462!--    add horizontal surface elements (land and urban surfaces)
6463!--    TODO: add urban overhanging surfaces (idown_u)
6464       DO i = nxl, nxr
6465           DO j = nys, nyn
6466              DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
6467                 k = surf_usm_h%k(m)
6468                 isurf = isurf + 1
6469                 surfl(:,isurf) = (/iup_u,k,j,i,m/)
6470                 IF ( rad_angular_discretization ) THEN
6471                    gridsurf(iup_u,k,j,i) = isurf
6472                 ENDIF
6473              ENDDO
6474
6475              DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6476                 k = surf_lsm_h%k(m)
6477                 isurf = isurf + 1
6478                 surfl(:,isurf) = (/iup_l,k,j,i,m/)
6479                 IF ( rad_angular_discretization ) THEN
6480                    gridsurf(iup_u,k,j,i) = isurf
6481                 ENDIF
6482              ENDDO
6483
6484           ENDDO
6485       ENDDO
6486
6487!--    add vertical surface elements (land and urban surfaces)
6488!--    TODO: remove the hard coding of l = 0 to l = idirection
6489       DO i = nxl, nxr
6490           DO j = nys, nyn
6491              l = 0
6492              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6493                 k = surf_usm_v(l)%k(m)
6494                 isurf = isurf + 1
6495                 surfl(:,isurf) = (/inorth_u,k,j,i,m/)
6496                 IF ( rad_angular_discretization ) THEN
6497                    gridsurf(inorth_u,k,j,i) = isurf
6498                 ENDIF
6499              ENDDO
6500              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6501                 k = surf_lsm_v(l)%k(m)
6502                 isurf = isurf + 1
6503                 surfl(:,isurf) = (/inorth_l,k,j,i,m/)
6504                 IF ( rad_angular_discretization ) THEN
6505                    gridsurf(inorth_u,k,j,i) = isurf
6506                 ENDIF
6507              ENDDO
6508
6509              l = 1
6510              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6511                 k = surf_usm_v(l)%k(m)
6512                 isurf = isurf + 1
6513                 surfl(:,isurf) = (/isouth_u,k,j,i,m/)
6514                 IF ( rad_angular_discretization ) THEN
6515                    gridsurf(isouth_u,k,j,i) = isurf
6516                 ENDIF
6517              ENDDO
6518              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6519                 k = surf_lsm_v(l)%k(m)
6520                 isurf = isurf + 1
6521                 surfl(:,isurf) = (/isouth_l,k,j,i,m/)
6522                 IF ( rad_angular_discretization ) THEN
6523                    gridsurf(isouth_u,k,j,i) = isurf
6524                 ENDIF
6525              ENDDO
6526
6527              l = 2
6528              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6529                 k = surf_usm_v(l)%k(m)
6530                 isurf = isurf + 1
6531                 surfl(:,isurf) = (/ieast_u,k,j,i,m/)
6532                 IF ( rad_angular_discretization ) THEN
6533                    gridsurf(ieast_u,k,j,i) = isurf
6534                 ENDIF
6535              ENDDO
6536              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6537                 k = surf_lsm_v(l)%k(m)
6538                 isurf = isurf + 1
6539                 surfl(:,isurf) = (/ieast_l,k,j,i,m/)
6540                 IF ( rad_angular_discretization ) THEN
6541                    gridsurf(ieast_u,k,j,i) = isurf
6542                 ENDIF
6543              ENDDO
6544
6545              l = 3
6546              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6547                 k = surf_usm_v(l)%k(m)
6548                 isurf = isurf + 1
6549                 surfl(:,isurf) = (/iwest_u,k,j,i,m/)
6550                 IF ( rad_angular_discretization ) THEN
6551                    gridsurf(iwest_u,k,j,i) = isurf
6552                 ENDIF
6553              ENDDO
6554              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6555                 k = surf_lsm_v(l)%k(m)
6556                 isurf = isurf + 1
6557                 surfl(:,isurf) = (/iwest_l,k,j,i,m/)
6558                 IF ( rad_angular_discretization ) THEN
6559                    gridsurf(iwest_u,k,j,i) = isurf
6560                 ENDIF
6561              ENDDO
6562           ENDDO
6563       ENDDO
6564!
6565!--    Add local MRT boxes for specified number of levels
6566       nmrtbl = 0
6567       IF ( mrt_nlevels > 0 )  THEN
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                   nmrtbl = nmrtbl + mrt_nlevels
6577                ENDDO
6578!
6579!--             Dtto for LSM
6580                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6581                   nmrtbl = nmrtbl + mrt_nlevels
6582                ENDDO
6583             ENDDO
6584          ENDDO
6585
6586          ALLOCATE( mrtbl(iz:ix,nmrtbl), mrtsky(nmrtbl), mrtskyt(nmrtbl), &
6587                    mrtinsw(nmrtbl), mrtinlw(nmrtbl), mrt(nmrtbl) )
6588
6589          imrt = 0
6590          DO  i = nxl, nxr
6591             DO  j = nys, nyn
6592                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
6593!
6594!--                Skip roof if requested
6595                   IF ( mrt_skip_roof  .AND.  surf_usm_h%isroof_surf(m) )  CYCLE
6596!
6597!--                Cycle over specified no of levels
6598                   l = surf_usm_h%k(m)
6599                   DO  k = l, l + mrt_nlevels - 1
6600                      imrt = imrt + 1
6601                      mrtbl(:,imrt) = (/k,j,i/)
6602                   ENDDO
6603                ENDDO
6604!
6605!--             Dtto for LSM
6606                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6607                   l = surf_lsm_h%k(m)
6608                   DO  k = l, l + mrt_nlevels - 1
6609                      imrt = imrt + 1
6610                      mrtbl(:,imrt) = (/k,j,i/)
6611                   ENDDO
6612                ENDDO
6613             ENDDO
6614          ENDDO
6615       ENDIF
6616
6617!
6618!--    broadband albedo of the land, roof and wall surface
6619!--    for domain border and sky set artifically to 1.0
6620!--    what allows us to calculate heat flux leaving over
6621!--    side and top borders of the domain
6622       ALLOCATE ( albedo_surf(nsurfl) )
6623       albedo_surf = 1.0_wp
6624!
6625!--    Also allocate further array for emissivity with identical order of
6626!--    surface elements as radiation arrays.
6627       ALLOCATE ( emiss_surf(nsurfl)  )
6628
6629
6630!
6631!--    global array surf of indices of surfaces and displacement index array surfstart
6632       ALLOCATE(nsurfs(0:numprocs-1))
6633
6634#if defined( __parallel )
6635       CALL MPI_Allgather(nsurfl,1,MPI_INTEGER,nsurfs,1,MPI_INTEGER,comm2d,ierr)
6636       IF ( ierr /= 0 ) THEN
6637         WRITE(9,*) 'Error MPI_AllGather1:', ierr, nsurfl, nsurfs
6638         FLUSH(9)
6639     ENDIF
6640
6641#else
6642       nsurfs(0) = nsurfl
6643#endif
6644       ALLOCATE(surfstart(0:numprocs))
6645       k = 0
6646       DO i=0,numprocs-1
6647           surfstart(i) = k
6648           k = k+nsurfs(i)
6649       ENDDO
6650       surfstart(numprocs) = k
6651       nsurf = k
6652!
6653!--    We allocate the array as linear and then use a two-dimensional pointer
6654!--    into it, because some MPI implementations crash with 2D-allocated arrays.
6655       ALLOCATE(surf_linear(nidx_surf*nsurf))
6656       surf(1:nidx_surf,1:nsurf) => surf_linear(1:nidx_surf*nsurf)
6657
6658#if defined( __parallel )
6659       CALL MPI_AllGatherv(surfl_linear, nsurfl*nidx_surf, MPI_INTEGER,    &
6660                           surf_linear, nsurfs*nidx_surf,                  &
6661                           surfstart(0:numprocs-1)*nidx_surf, MPI_INTEGER, &
6662                           comm2d, ierr)
6663       IF ( ierr /= 0 ) THEN
6664           WRITE(9,*) 'Error MPI_AllGatherv4:', ierr, SIZE(surfl_linear),    &
6665                      nsurfl*nidx_surf, SIZE(surf_linear), nsurfs*nidx_surf, &
6666                      surfstart(0:numprocs-1)*nidx_surf
6667           FLUSH(9)
6668       ENDIF
6669#else
6670       surf = surfl
6671#endif
6672
6673!--
6674!--    allocation of the arrays for direct and diffusion radiation
6675       IF ( debug_output )  CALL debug_message( 'allocation of radiation arrays', 'info' )
6676!--    rad_sw_in, rad_lw_in are computed in radiation model,
6677!--    splitting of direct and diffusion part is done
6678!--    in calc_diffusion_radiation for now
6679
6680       ALLOCATE( rad_sw_in_dir(nysg:nyng,nxlg:nxrg) )
6681       ALLOCATE( rad_sw_in_diff(nysg:nyng,nxlg:nxrg) )
6682       ALLOCATE( rad_lw_in_diff(nysg:nyng,nxlg:nxrg) )
6683       rad_sw_in_dir  = 0.0_wp
6684       rad_sw_in_diff = 0.0_wp
6685       rad_lw_in_diff = 0.0_wp
6686
6687!--    allocate radiation arrays
6688       ALLOCATE( surfins(nsurfl) )
6689       ALLOCATE( surfinl(nsurfl) )
6690       ALLOCATE( surfinsw(nsurfl) )
6691       ALLOCATE( surfinlw(nsurfl) )
6692       ALLOCATE( surfinswdir(nsurfl) )
6693       ALLOCATE( surfinswdif(nsurfl) )
6694       ALLOCATE( surfinlwdif(nsurfl) )
6695       ALLOCATE( surfoutsl(nsurfl) )
6696       ALLOCATE( surfoutll(nsurfl) )
6697       ALLOCATE( surfoutsw(nsurfl) )
6698       ALLOCATE( surfoutlw(nsurfl) )
6699       ALLOCATE( surfouts(nsurf) )
6700       ALLOCATE( surfoutl(nsurf) )
6701       ALLOCATE( surfinlg(nsurf) )
6702       ALLOCATE( skyvf(nsurfl) )
6703       ALLOCATE( skyvft(nsurfl) )
6704       ALLOCATE( surfemitlwl(nsurfl) )
6705
6706!
6707!--    In case of average_radiation, aggregated surface albedo and emissivity,
6708!--    also set initial value for t_rad_urb.
6709!--    For now set an arbitrary initial value.
6710       IF ( average_radiation )  THEN
6711          albedo_urb = 0.1_wp
6712          emissivity_urb = 0.9_wp
6713          t_rad_urb = pt_surface
6714       ENDIF
6715
6716    END SUBROUTINE radiation_interaction_init
6717
6718!------------------------------------------------------------------------------!
6719! Description:
6720! ------------
6721!> Calculates shape view factors (SVF), plant sink canopy factors (PCSF),
6722!> sky-view factors, discretized path for direct solar radiation, MRT factors
6723!> and other preprocessed data needed for radiation_interaction.
6724!------------------------------------------------------------------------------!
6725    SUBROUTINE radiation_calc_svf
6726   
6727        IMPLICIT NONE
6728       
6729        INTEGER(iwp)                                  :: i, j, k, d, ip, jp
6730        INTEGER(iwp)                                  :: isvf, ksvf, icsf, kcsf, npcsfl, isvf_surflt, imrt, imrtf, ipcgb
6731        INTEGER(iwp)                                  :: sd, td
6732        INTEGER(iwp)                                  :: iaz, izn      !< azimuth, zenith counters
6733        INTEGER(iwp)                                  :: naz, nzn      !< azimuth, zenith num of steps
6734        REAL(wp)                                      :: az0, zn0      !< starting azimuth/zenith
6735        REAL(wp)                                      :: azs, zns      !< azimuth/zenith cycle step
6736        REAL(wp)                                      :: az1, az2      !< relative azimuth of section borders
6737        REAL(wp)                                      :: azmid         !< ray (center) azimuth
6738        REAL(wp)                                      :: yxlen         !< |yxdir|
6739        REAL(wp), DIMENSION(2)                        :: yxdir         !< y,x *unit* vector of ray direction (in grid units)
6740        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zdirs         !< directions in z (tangent of elevation)
6741        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zcent         !< zenith angle centers
6742        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zbdry         !< zenith angle boundaries
6743        REAL(wp), DIMENSION(:), ALLOCATABLE           :: vffrac        !< view factor fractions for individual rays
6744        REAL(wp), DIMENSION(:), ALLOCATABLE           :: vffrac0       !< dtto (original values)
6745        REAL(wp), DIMENSION(:), ALLOCATABLE           :: ztransp       !< array of transparency in z steps
6746        INTEGER(iwp)                                  :: lowest_free_ray !< index into zdirs
6747        INTEGER(iwp), DIMENSION(:), ALLOCATABLE       :: itarget       !< face indices of detected obstacles
6748        INTEGER(iwp)                                  :: itarg0, itarg1
6749
6750        INTEGER(iwp)                                  :: udim
6751        INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET:: nzterrl_l
6752        INTEGER(iwp), DIMENSION(:,:), POINTER         :: nzterrl
6753        REAL(wp),     DIMENSION(:), ALLOCATABLE,TARGET:: csflt_l, pcsflt_l
6754        REAL(wp),     DIMENSION(:,:), POINTER         :: csflt, pcsflt
6755        INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET:: kcsflt_l,kpcsflt_l
6756        INTEGER(iwp), DIMENSION(:,:), POINTER         :: kcsflt,kpcsflt
6757        INTEGER(iwp), DIMENSION(:), ALLOCATABLE       :: icsflt,dcsflt,ipcsflt,dpcsflt
6758        REAL(wp), DIMENSION(3)                        :: uv
6759        LOGICAL                                       :: visible
6760        REAL(wp), DIMENSION(3)                        :: sa, ta          !< real coordinates z,y,x of source and target
6761        REAL(wp)                                      :: difvf           !< differential view factor
6762        REAL(wp)                                      :: transparency, rirrf, sqdist, svfsum
6763        INTEGER(iwp)                                  :: isurflt, isurfs, isurflt_prev
6764        INTEGER(idp)                                  :: ray_skip_maxdist, ray_skip_minval !< skipped raytracing counts
6765        INTEGER(iwp)                                  :: max_track_len !< maximum 2d track length
6766        INTEGER(iwp)                                  :: minfo
6767        REAL(wp), DIMENSION(:), POINTER, SAVE         :: lad_s_rma       !< fortran 1D pointer
6768        TYPE(c_ptr)                                   :: lad_s_rma_p     !< allocated c pointer
6769#if defined( __parallel )
6770        INTEGER(kind=MPI_ADDRESS_KIND)                :: size_lad_rma
6771#endif
6772!   
6773        INTEGER(iwp), DIMENSION(0:svfnorm_report_num) :: svfnorm_counts
6774
6775
6776!--     calculation of the SVF
6777        CALL location_message( 'calculating view factors for radiation interaction', 'start' )
6778
6779!--     initialize variables and temporary arrays for calculation of svf and csf
6780        nsvfl  = 0
6781        ncsfl  = 0
6782        nsvfla = gasize
6783        msvf   = 1
6784        ALLOCATE( asvf1(nsvfla) )
6785        asvf => asvf1
6786        IF ( plant_canopy )  THEN
6787            ncsfla = gasize
6788            mcsf   = 1
6789            ALLOCATE( acsf1(ncsfla) )
6790            acsf => acsf1
6791        ENDIF
6792        nmrtf = 0
6793        IF ( mrt_nlevels > 0 )  THEN
6794           nmrtfa = gasize
6795           mmrtf = 1
6796           ALLOCATE ( amrtf1(nmrtfa) )
6797           amrtf => amrtf1
6798        ENDIF
6799        ray_skip_maxdist = 0
6800        ray_skip_minval = 0
6801       
6802!--     initialize temporary terrain and plant canopy height arrays (global 2D array!)
6803        ALLOCATE( nzterr(0:(nx+1)*(ny+1)-1) )
6804#if defined( __parallel )
6805        !ALLOCATE( nzterrl(nys:nyn,nxl:nxr) )
6806        ALLOCATE( nzterrl_l((nyn-nys+1)*(nxr-nxl+1)) )
6807        nzterrl(nys:nyn,nxl:nxr) => nzterrl_l(1:(nyn-nys+1)*(nxr-nxl+1))
6808        nzterrl = get_topography_top_index( 's' )
6809        CALL MPI_AllGather( nzterrl_l, nnx*nny, MPI_INTEGER, &
6810                            nzterr, nnx*nny, MPI_INTEGER, comm2d, ierr )
6811        IF ( ierr /= 0 ) THEN
6812            WRITE(9,*) 'Error MPI_AllGather1:', ierr, SIZE(nzterrl_l), nnx*nny, &
6813                       SIZE(nzterr), nnx*nny
6814            FLUSH(9)
6815        ENDIF
6816        DEALLOCATE(nzterrl_l)
6817#else
6818        nzterr = RESHAPE( get_topography_top_index( 's' ), (/(nx+1)*(ny+1)/) )
6819#endif
6820        IF ( plant_canopy )  THEN
6821            ALLOCATE( plantt(0:(nx+1)*(ny+1)-1) )
6822            maxboxesg = nx + ny + nz_plant + 1
6823            max_track_len = nx + ny + 1
6824!--         temporary arrays storing values for csf calculation during raytracing
6825            ALLOCATE( boxes(3, maxboxesg) )
6826            ALLOCATE( crlens(maxboxesg) )
6827
6828#if defined( __parallel )
6829            CALL MPI_AllGather( pct, nnx*nny, MPI_INTEGER, &
6830                                plantt, nnx*nny, MPI_INTEGER, comm2d, ierr )
6831            IF ( ierr /= 0 ) THEN
6832                WRITE(9,*) 'Error MPI_AllGather2:', ierr, SIZE(pct), nnx*nny, &
6833                           SIZE(plantt), nnx*nny
6834                FLUSH(9)
6835            ENDIF
6836
6837!--         temporary arrays storing values for csf calculation during raytracing
6838            ALLOCATE( lad_ip(maxboxesg) )
6839            ALLOCATE( lad_disp(maxboxesg) )
6840
6841            IF ( raytrace_mpi_rma )  THEN
6842                ALLOCATE( lad_s_ray(maxboxesg) )
6843               
6844                ! set conditions for RMA communication
6845                CALL MPI_Info_create(minfo, ierr)
6846                IF ( ierr /= 0 ) THEN
6847                    WRITE(9,*) 'Error MPI_Info_create2:', ierr
6848                    FLUSH(9)
6849                ENDIF
6850                CALL MPI_Info_set(minfo, 'accumulate_ordering', 'none', ierr)
6851                IF ( ierr /= 0 ) THEN
6852                    WRITE(9,*) 'Error MPI_Info_set5:', ierr
6853                    FLUSH(9)
6854                ENDIF
6855                CALL MPI_Info_set(minfo, 'accumulate_ops', 'same_op', ierr)
6856                IF ( ierr /= 0 ) THEN
6857                    WRITE(9,*) 'Error MPI_Info_set6:', ierr
6858                    FLUSH(9)
6859                ENDIF
6860                CALL MPI_Info_set(minfo, 'same_size', 'true', ierr)
6861                IF ( ierr /= 0 ) THEN
6862                    WRITE(9,*) 'Error MPI_Info_set7:', ierr
6863                    FLUSH(9)
6864                ENDIF
6865                CALL MPI_Info_set(minfo, 'same_disp_unit', 'true', ierr)
6866                IF ( ierr /= 0 ) THEN
6867                    WRITE(9,*) 'Error MPI_Info_set8:', ierr
6868                    FLUSH(9)
6869                ENDIF
6870
6871!--             Allocate and initialize the MPI RMA window
6872!--             must be in accordance with allocation of lad_s in plant_canopy_model
6873!--             optimization of memory should be done
6874!--             Argument X of function STORAGE_SIZE(X) needs arbitrary REAL(wp) value, set to 1.0_wp for now
6875                size_lad_rma = STORAGE_SIZE(1.0_wp)/8*nnx*nny*nz_plant
6876                CALL MPI_Win_allocate(size_lad_rma, STORAGE_SIZE(1.0_wp)/8, minfo, comm2d, &
6877                                        lad_s_rma_p, win_lad, ierr)
6878                IF ( ierr /= 0 ) THEN
6879                    WRITE(9,*) 'Error MPI_Win_allocate2:', ierr, size_lad_rma, &
6880                                STORAGE_SIZE(1.0_wp)/8, win_lad
6881                    FLUSH(9)
6882                ENDIF
6883                CALL c_f_pointer(lad_s_rma_p, lad_s_rma, (/ nz_plant*nny*nnx /))
6884                sub_lad(nz_urban_b:nz_plant_t, nys:nyn, nxl:nxr) => lad_s_rma(1:nz_plant*nny*nnx)
6885            ELSE
6886                ALLOCATE(sub_lad(nz_urban_b:nz_plant_t, nys:nyn, nxl:nxr))
6887            ENDIF
6888#else
6889            plantt = RESHAPE( pct(nys:nyn,nxl:nxr), (/(nx+1)*(ny+1)/) )
6890            ALLOCATE(sub_lad(nz_urban_b:nz_plant_t, nys:nyn, nxl:nxr))
6891#endif
6892            plantt_max = MAXVAL(plantt)
6893            ALLOCATE( rt2_track(2, max_track_len), rt2_track_lad(nz_urban_b:plantt_max, max_track_len), &
6894                      rt2_track_dist(0:max_track_len), rt2_dist(plantt_max-nz_urban_b+2) )
6895
6896            sub_lad(:,:,:) = 0._wp
6897            DO i = nxl, nxr
6898                DO j = nys, nyn
6899                    k = get_topography_top_index_ji( j, i, 's' )
6900
6901                    sub_lad(k:nz_plant_t, j, i) = lad_s(0:nz_plant_t-k, j, i)
6902                ENDDO
6903            ENDDO
6904
6905#if defined( __parallel )
6906            IF ( raytrace_mpi_rma )  THEN
6907                CALL MPI_Info_free(minfo, ierr)
6908                IF ( ierr /= 0 ) THEN
6909                    WRITE(9,*) 'Error MPI_Info_free2:', ierr
6910                    FLUSH(9)
6911                ENDIF
6912                CALL MPI_Win_lock_all(0, win_lad, ierr)
6913                IF ( ierr /= 0 ) THEN
6914                    WRITE(9,*) 'Error MPI_Win_lock_all1:', ierr, win_lad
6915                    FLUSH(9)
6916                ENDIF
6917               
6918            ELSE
6919                ALLOCATE( sub_lad_g(0:(nx+1)*(ny+1)*nz_plant-1) )
6920                CALL MPI_AllGather( sub_lad, nnx*nny*nz_plant, MPI_REAL, &
6921                                    sub_lad_g, nnx*nny*nz_plant, MPI_REAL, comm2d, ierr )
6922                IF ( ierr /= 0 ) THEN
6923                    WRITE(9,*) 'Error MPI_AllGather3:', ierr, SIZE(sub_lad), &
6924                                nnx*nny*nz_plant, SIZE(sub_lad_g), nnx*nny*nz_plant
6925                    FLUSH(9)
6926                ENDIF
6927            ENDIF
6928#endif
6929        ENDIF
6930
6931!--     prepare the MPI_Win for collecting the surface indices
6932!--     from the reverse index arrays gridsurf from processors of target surfaces
6933#if defined( __parallel )
6934        IF ( rad_angular_discretization )  THEN
6935!
6936!--         raytrace_mpi_rma is asserted
6937            CALL MPI_Win_lock_all(0, win_gridsurf, ierr)
6938            IF ( ierr /= 0 ) THEN
6939                WRITE(9,*) 'Error MPI_Win_lock_all2:', ierr, win_gridsurf
6940                FLUSH(9)
6941            ENDIF
6942        ENDIF
6943#endif
6944
6945
6946        !--Directions opposite to face normals are not even calculated,
6947        !--they must be preset to 0
6948        !--
6949        dsitrans(:,:) = 0._wp
6950       
6951        DO isurflt = 1, nsurfl
6952!--         determine face centers
6953            td = surfl(id, isurflt)
6954            ta = (/ REAL(surfl(iz, isurflt), wp) - 0.5_wp * kdir(td),  &
6955                      REAL(surfl(iy, isurflt), wp) - 0.5_wp * jdir(td),  &
6956                      REAL(surfl(ix, isurflt), wp) - 0.5_wp * idir(td)  /)
6957
6958            !--Calculate sky view factor and raytrace DSI paths
6959            skyvf(isurflt) = 0._wp
6960            skyvft(isurflt) = 0._wp
6961
6962            !--Select a proper half-sphere for 2D raytracing
6963            SELECT CASE ( td )
6964               CASE ( iup_u, iup_l )
6965                  az0 = 0._wp
6966                  naz = raytrace_discrete_azims
6967                  azs = 2._wp * pi / REAL(naz, wp)
6968                  zn0 = 0._wp
6969                  nzn = raytrace_discrete_elevs / 2
6970                  zns = pi / 2._wp / REAL(nzn, wp)
6971               CASE ( isouth_u, isouth_l )
6972                  az0 = pi / 2._wp
6973                  naz = raytrace_discrete_azims / 2
6974                  azs = pi / REAL(naz, wp)
6975                  zn0 = 0._wp
6976                  nzn = raytrace_discrete_elevs
6977                  zns = pi / REAL(nzn, wp)
6978               CASE ( inorth_u, inorth_l )
6979                  az0 = - pi / 2._wp
6980                  naz = raytrace_discrete_azims / 2
6981                  azs = pi / REAL(naz, wp)
6982                  zn0 = 0._wp
6983                  nzn = raytrace_discrete_elevs
6984                  zns = pi / REAL(nzn, wp)
6985               CASE ( iwest_u, iwest_l )
6986                  az0 = pi
6987                  naz = raytrace_discrete_azims / 2
6988                  azs = pi / REAL(naz, wp)
6989                  zn0 = 0._wp
6990                  nzn = raytrace_discrete_elevs
6991                  zns = pi / REAL(nzn, wp)
6992               CASE ( ieast_u, ieast_l )
6993                  az0 = 0._wp
6994                  naz = raytrace_discrete_azims / 2
6995                  azs = pi / REAL(naz, wp)
6996                  zn0 = 0._wp
6997                  nzn = raytrace_discrete_elevs
6998                  zns = pi / REAL(nzn, wp)
6999               CASE DEFAULT
7000                  WRITE(message_string, *) 'ERROR: the surface type ', td,     &
7001                                           ' is not supported for calculating',&
7002                                           ' SVF'
7003                  CALL message( 'radiation_calc_svf', 'PA0488', 1, 2, 0, 6, 0 )
7004            END SELECT
7005
7006            ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), zbdry(0:nzn), vffrac(1:nzn*naz), &
7007                       ztransp(1:nzn*naz), itarget(1:nzn*naz) )   !FIXME allocate itarget only
7008                                                                  !in case of rad_angular_discretization
7009
7010            itarg0 = 1
7011            itarg1 = nzn
7012            zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
7013            zbdry(:) = (/( zn0+REAL(izn,wp)*zns, izn=0, nzn )/)
7014            IF ( td == iup_u  .OR.  td == iup_l )  THEN
7015               vffrac(1:nzn) = (COS(2 * zbdry(0:nzn-1)) - COS(2 * zbdry(1:nzn))) / 2._wp / REAL(naz, wp)
7016!
7017!--            For horizontal target, vf fractions are constant per azimuth
7018               DO iaz = 1, naz-1
7019                  vffrac(iaz*nzn+1:(iaz+1)*nzn) = vffrac(1:nzn)
7020               ENDDO
7021!--            sum of whole vffrac equals 1, verified
7022            ENDIF
7023!
7024!--         Calculate sky-view factor and direct solar visibility using 2D raytracing
7025            DO iaz = 1, naz
7026               azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
7027               IF ( td /= iup_u  .AND.  td /= iup_l )  THEN
7028                  az2 = REAL(iaz, wp) * azs - pi/2._wp
7029                  az1 = az2 - azs
7030                  !TODO precalculate after 1st line
7031                  vffrac(itarg0:itarg1) = (SIN(az2) - SIN(az1))               &
7032                              * (zbdry(1:nzn) - zbdry(0:nzn-1)                &
7033                                 + SIN(zbdry(0:nzn-1))*COS(zbdry(0:nzn-1))    &
7034                                 - SIN(zbdry(1:nzn))*COS(zbdry(1:nzn)))       &
7035                              / (2._wp * pi)
7036!--               sum of whole vffrac equals 1, verified
7037               ENDIF
7038               yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
7039               yxlen = SQRT(SUM(yxdir(:)**2))
7040               zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
7041               yxdir(:) = yxdir(:) / yxlen
7042
7043               CALL raytrace_2d(ta, yxdir, nzn, zdirs,                        &
7044                                    surfstart(myid) + isurflt, facearea(td),  &
7045                                    vffrac(itarg0:itarg1), .TRUE., .TRUE.,    &
7046                                    .FALSE., lowest_free_ray,                 &
7047                                    ztransp(itarg0:itarg1),                   &
7048                                    itarget(itarg0:itarg1))
7049
7050               skyvf(isurflt) = skyvf(isurflt) + &
7051                                SUM(vffrac(itarg0:itarg0+lowest_free_ray-1))
7052               skyvft(isurflt) = skyvft(isurflt) + &
7053                                 SUM(ztransp(itarg0:itarg0+lowest_free_ray-1) &
7054                                             * vffrac(itarg0:itarg0+lowest_free_ray-1))
7055 
7056!--            Save direct solar transparency
7057               j = MODULO(NINT(azmid/                                          &
7058                               (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
7059                          raytrace_discrete_azims)
7060
7061               DO k = 1, raytrace_discrete_elevs/2
7062                  i = dsidir_rev(k-1, j)
7063                  IF ( i /= -1  .AND.  k <= lowest_free_ray )  &
7064                     dsitrans(isurflt, i) = ztransp(itarg0+k-1)
7065               ENDDO
7066
7067!
7068!--            Advance itarget indices
7069               itarg0 = itarg1 + 1
7070               itarg1 = itarg1 + nzn
7071            ENDDO
7072
7073            IF ( rad_angular_discretization )  THEN
7074!--            sort itarget by face id
7075               CALL quicksort_itarget(itarget,vffrac,ztransp,1,nzn*naz)
7076!
7077!--            For aggregation, we need fractions multiplied by transmissivities
7078               ztransp(:) = vffrac(:) * ztransp(:)
7079!
7080!--            find the first valid position
7081               itarg0 = 1
7082               DO WHILE ( itarg0 <= nzn*naz )
7083                  IF ( itarget(itarg0) /= -1 )  EXIT
7084                  itarg0 = itarg0 + 1
7085               ENDDO
7086
7087               DO  i = itarg0, nzn*naz
7088!
7089!--               For duplicate values, only sum up vf fraction value
7090                  IF ( i < nzn*naz )  THEN
7091                     IF ( itarget(i+1) == itarget(i) )  THEN
7092                        vffrac(i+1) = vffrac(i+1) + vffrac(i)
7093                        ztransp(i+1) = ztransp(i+1) + ztransp(i)
7094                        CYCLE
7095                     ENDIF
7096                  ENDIF
7097!
7098!--               write to the svf array
7099                  nsvfl = nsvfl + 1
7100!--               check dimmension of asvf array and enlarge it if needed
7101                  IF ( nsvfla < nsvfl )  THEN
7102                     k = CEILING(REAL(nsvfla, kind=wp) * grow_factor)
7103                     IF ( msvf == 0 )  THEN
7104                        msvf = 1
7105                        ALLOCATE( asvf1(k) )
7106                        asvf => asvf1
7107                        asvf1(1:nsvfla) = asvf2
7108                        DEALLOCATE( asvf2 )
7109                     ELSE
7110                        msvf = 0
7111                        ALLOCATE( asvf2(k) )
7112                        asvf => asvf2
7113                        asvf2(1:nsvfla) = asvf1
7114                        DEALLOCATE( asvf1 )
7115                     ENDIF
7116
7117                     IF ( debug_output )  THEN
7118                        WRITE( debug_string, '(A,3I12)' ) 'Grow asvf:', nsvfl, nsvfla, k
7119                        CALL debug_message( debug_string, 'info' )
7120                     ENDIF
7121                     
7122                     nsvfla = k
7123                  ENDIF
7124!--               write svf values into the array
7125                  asvf(nsvfl)%isurflt = isurflt
7126                  asvf(nsvfl)%isurfs = itarget(i)
7127                  asvf(nsvfl)%rsvf = vffrac(i)
7128                  asvf(nsvfl)%rtransp = ztransp(i) / vffrac(i)
7129               END DO
7130
7131            ENDIF ! rad_angular_discretization
7132
7133            DEALLOCATE ( zdirs, zcent, zbdry, vffrac, ztransp, itarget ) !FIXME itarget shall be allocated only
7134                                                                  !in case of rad_angular_discretization
7135!
7136!--         Following calculations only required for surface_reflections
7137            IF ( surface_reflections  .AND.  .NOT. rad_angular_discretization )  THEN
7138
7139               DO  isurfs = 1, nsurf
7140                  IF ( .NOT.  surface_facing(surfl(ix, isurflt), surfl(iy, isurflt), &
7141                     surfl(iz, isurflt), surfl(id, isurflt), &
7142                     surf(ix, isurfs), surf(iy, isurfs), &
7143                     surf(iz, isurfs), surf(id, isurfs)) )  THEN
7144                     CYCLE
7145                  ENDIF
7146                 
7147                  sd = surf(id, isurfs)
7148                  sa = (/ REAL(surf(iz, isurfs), wp) - 0.5_wp * kdir(sd),  &
7149                          REAL(surf(iy, isurfs), wp) - 0.5_wp * jdir(sd),  &
7150                          REAL(surf(ix, isurfs), wp) - 0.5_wp * idir(sd)  /)
7151
7152!--               unit vector source -> target
7153                  uv = (/ (ta(1)-sa(1))*dz(1), (ta(2)-sa(2))*dy, (ta(3)-sa(3))*dx /)
7154                  sqdist = SUM(uv(:)**2)
7155                  uv = uv / SQRT(sqdist)
7156
7157!--               reject raytracing above max distance
7158                  IF ( SQRT(sqdist) > max_raytracing_dist ) THEN
7159                     ray_skip_maxdist = ray_skip_maxdist + 1
7160                     CYCLE
7161                  ENDIF
7162                 
7163                  difvf = dot_product((/ kdir(sd), jdir(sd), idir(sd) /), uv) & ! cosine of source normal and direction
7164                      * dot_product((/ kdir(td), jdir(td), idir(td) /), -uv) &  ! cosine of target normal and reverse direction
7165                      / (pi * sqdist) ! square of distance between centers
7166!
7167!--               irradiance factor (our unshaded shape view factor) = view factor per differential target area * source area
7168                  rirrf = difvf * facearea(sd)
7169
7170!--               reject raytracing for potentially too small view factor values
7171                  IF ( rirrf < min_irrf_value ) THEN
7172                      ray_skip_minval = ray_skip_minval + 1
7173                      CYCLE
7174                  ENDIF
7175
7176!--               raytrace + process plant canopy sinks within
7177                  CALL raytrace(sa, ta, isurfs, difvf, facearea(td), .TRUE., &
7178                                visible, transparency)
7179
7180                  IF ( .NOT.  visible ) CYCLE
7181                 ! rsvf = rirrf * transparency
7182
7183!--               write to the svf array
7184                  nsvfl = nsvfl + 1
7185!--               check dimmension of asvf array and enlarge it if needed
7186                  IF ( nsvfla < nsvfl )  THEN
7187                     k = CEILING(REAL(nsvfla, kind=wp) * grow_factor)
7188                     IF ( msvf == 0 )  THEN
7189                        msvf = 1
7190                        ALLOCATE( asvf1(k) )
7191                        asvf => asvf1
7192                        asvf1(1:nsvfla) = asvf2
7193                        DEALLOCATE( asvf2 )
7194                     ELSE
7195                        msvf = 0
7196                        ALLOCATE( asvf2(k) )
7197                        asvf => asvf2
7198                        asvf2(1:nsvfla) = asvf1
7199                        DEALLOCATE( asvf1 )
7200                     ENDIF
7201
7202                     IF ( debug_output )  THEN
7203                        WRITE( debug_string, '(A,3I12)' ) 'Grow asvf:', nsvfl, nsvfla, k
7204                        CALL debug_message( debug_string, 'info' )
7205                     ENDIF
7206                     
7207                     nsvfla = k
7208                  ENDIF
7209!--               write svf values into the array
7210                  asvf(nsvfl)%isurflt = isurflt
7211                  asvf(nsvfl)%isurfs = isurfs
7212                  asvf(nsvfl)%rsvf = rirrf !we postopne multiplication by transparency
7213                  asvf(nsvfl)%rtransp = transparency !a.k.a. Direct Irradiance Factor
7214               ENDDO
7215            ENDIF
7216        ENDDO
7217
7218!--
7219!--     Raytrace to canopy boxes to fill dsitransc TODO optimize
7220        dsitransc(:,:) = 0._wp
7221        az0 = 0._wp
7222        naz = raytrace_discrete_azims
7223        azs = 2._wp * pi / REAL(naz, wp)
7224        zn0 = 0._wp
7225        nzn = raytrace_discrete_elevs / 2
7226        zns = pi / 2._wp / REAL(nzn, wp)
7227        ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), vffrac(1:nzn), ztransp(1:nzn), &
7228               itarget(1:nzn) )
7229        zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
7230        vffrac(:) = 0._wp
7231
7232        DO  ipcgb = 1, npcbl
7233           ta = (/ REAL(pcbl(iz, ipcgb), wp),  &
7234                   REAL(pcbl(iy, ipcgb), wp),  &
7235                   REAL(pcbl(ix, ipcgb), wp) /)
7236!--        Calculate direct solar visibility using 2D raytracing
7237           DO  iaz = 1, naz
7238              azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
7239              yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
7240              yxlen = SQRT(SUM(yxdir(:)**2))
7241              zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
7242              yxdir(:) = yxdir(:) / yxlen
7243              CALL raytrace_2d(ta, yxdir, nzn, zdirs,                                &
7244                                   -999, -999._wp, vffrac, .FALSE., .FALSE., .TRUE., &
7245                                   lowest_free_ray, ztransp, itarget)
7246
7247!--           Save direct solar transparency
7248              j = MODULO(NINT(azmid/                                         &
7249                             (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
7250                         raytrace_discrete_azims)
7251              DO  k = 1, raytrace_discrete_elevs/2
7252                 i = dsidir_rev(k-1, j)
7253                 IF ( i /= -1  .AND.  k <= lowest_free_ray ) &
7254                    dsitransc(ipcgb, i) = ztransp(k)
7255              ENDDO
7256           ENDDO
7257        ENDDO
7258        DEALLOCATE ( zdirs, zcent, vffrac, ztransp, itarget )
7259!--
7260!--     Raytrace to MRT boxes
7261        IF ( nmrtbl > 0 )  THEN
7262           mrtdsit(:,:) = 0._wp
7263           mrtsky(:) = 0._wp
7264           mrtskyt(:) = 0._wp
7265           az0 = 0._wp
7266           naz = raytrace_discrete_azims
7267           azs = 2._wp * pi / REAL(naz, wp)
7268           zn0 = 0._wp
7269           nzn = raytrace_discrete_elevs
7270           zns = pi / REAL(nzn, wp)
7271           ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), zbdry(0:nzn), vffrac(1:nzn*naz), vffrac0(1:nzn), &
7272                      ztransp(1:nzn*naz), itarget(1:nzn*naz) )   !FIXME allocate itarget only
7273                                                                 !in case of rad_angular_discretization
7274
7275           zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
7276           zbdry(:) = (/( zn0+REAL(izn,wp)*zns, izn=0, nzn )/)
7277           vffrac0(:) = (COS(zbdry(0:nzn-1)) - COS(zbdry(1:nzn))) / 2._wp / REAL(naz, wp)
7278           !
7279           !--Modify direction weights to simulate human body (lower weight for top-down)
7280           IF ( mrt_geom_human )  THEN
7281              vffrac0(:) = vffrac0(:) * MAX(0._wp, SIN(zcent(:))*0.88_wp + COS(zcent(:))*0.12_wp)
7282              vffrac0(:) = vffrac0(:) / (SUM(vffrac0) * REAL(naz, wp))
7283           ENDIF
7284
7285           DO  imrt = 1, nmrtbl
7286              ta = (/ REAL(mrtbl(iz, imrt), wp),  &
7287                      REAL(mrtbl(iy, imrt), wp),  &
7288                      REAL(mrtbl(ix, imrt), wp) /)
7289!
7290!--           vf fractions are constant per azimuth
7291              DO iaz = 0, naz-1
7292                 vffrac(iaz*nzn+1:(iaz+1)*nzn) = vffrac0(:)
7293              ENDDO
7294!--           sum of whole vffrac equals 1, verified
7295              itarg0 = 1
7296              itarg1 = nzn
7297!
7298!--           Calculate sky-view factor and direct solar visibility using 2D raytracing
7299              DO  iaz = 1, naz
7300                 azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
7301                 yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
7302                 yxlen = SQRT(SUM(yxdir(:)**2))
7303                 zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
7304                 yxdir(:) = yxdir(:) / yxlen
7305
7306                 CALL raytrace_2d(ta, yxdir, nzn, zdirs,                         &
7307                                  -999, -999._wp, vffrac(itarg0:itarg1), .TRUE., &
7308                                  .FALSE., .TRUE., lowest_free_ray,              &
7309                                  ztransp(itarg0:itarg1),                        &
7310                                  itarget(itarg0:itarg1))
7311
7312!--              Sky view factors for MRT
7313                 mrtsky(imrt) = mrtsky(imrt) + &
7314                                  SUM(vffrac(itarg0:itarg0+lowest_free_ray-1))
7315                 mrtskyt(imrt) = mrtskyt(imrt) + &
7316                                   SUM(ztransp(itarg0:itarg0+lowest_free_ray-1) &
7317                                               * vffrac(itarg0:itarg0+lowest_free_ray-1))
7318!--              Direct solar transparency for MRT
7319                 j = MODULO(NINT(azmid/                                         &
7320                                (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
7321                            raytrace_discrete_azims)
7322                 DO  k = 1, raytrace_discrete_elevs/2
7323                    i = dsidir_rev(k-1, j)
7324                    IF ( i /= -1  .AND.  k <= lowest_free_ray ) &
7325                       mrtdsit(imrt, i) = ztransp(itarg0+k-1)
7326                 ENDDO
7327!
7328!--              Advance itarget indices
7329                 itarg0 = itarg1 + 1
7330                 itarg1 = itarg1 + nzn
7331              ENDDO
7332
7333!--           sort itarget by face id
7334              CALL quicksort_itarget(itarget,vffrac,ztransp,1,nzn*naz)
7335!
7336!--           find the first valid position
7337              itarg0 = 1
7338              DO WHILE ( itarg0 <= nzn*naz )
7339                 IF ( itarget(itarg0) /= -1 )  EXIT
7340                 itarg0 = itarg0 + 1
7341              ENDDO
7342
7343              DO  i = itarg0, nzn*naz
7344!
7345!--              For duplicate values, only sum up vf fraction value
7346                 IF ( i < nzn*naz )  THEN
7347                    IF ( itarget(i+1) == itarget(i) )  THEN
7348                       vffrac(i+1) = vffrac(i+1) + vffrac(i)
7349                       CYCLE
7350                    ENDIF
7351                 ENDIF
7352!
7353!--              write to the mrtf array
7354                 nmrtf = nmrtf + 1
7355!--              check dimmension of mrtf array and enlarge it if needed
7356                 IF ( nmrtfa < nmrtf )  THEN
7357                    k = CEILING(REAL(nmrtfa, kind=wp) * grow_factor)
7358                    IF ( mmrtf == 0 )  THEN
7359                       mmrtf = 1
7360                       ALLOCATE( amrtf1(k) )
7361                       amrtf => amrtf1
7362                       amrtf1(1:nmrtfa) = amrtf2
7363                       DEALLOCATE( amrtf2 )
7364                    ELSE
7365                       mmrtf = 0
7366                       ALLOCATE( amrtf2(k) )
7367                       amrtf => amrtf2
7368                       amrtf2(1:nmrtfa) = amrtf1
7369                       DEALLOCATE( amrtf1 )
7370                    ENDIF
7371
7372                    IF ( debug_output )  THEN
7373                       WRITE( debug_string, '(A,3I12)' ) 'Grow amrtf:', nmrtf, nmrtfa, k
7374                       CALL debug_message( debug_string, 'info' )
7375                    ENDIF
7376
7377                    nmrtfa = k
7378                 ENDIF
7379!--              write mrtf values into the array
7380                 amrtf(nmrtf)%isurflt = imrt
7381                 amrtf(nmrtf)%isurfs = itarget(i)
7382                 amrtf(nmrtf)%rsvf = vffrac(i)
7383                 amrtf(nmrtf)%rtransp = ztransp(i)
7384              ENDDO ! itarg
7385
7386           ENDDO ! imrt
7387           DEALLOCATE ( zdirs, zcent, zbdry, vffrac, vffrac0, ztransp, itarget )
7388!
7389!--        Move MRT factors to final arrays
7390           ALLOCATE ( mrtf(nmrtf), mrtft(nmrtf), mrtfsurf(2,nmrtf) )
7391           DO  imrtf = 1, nmrtf
7392              mrtf(imrtf) = amrtf(imrtf)%rsvf
7393              mrtft(imrtf) = amrtf(imrtf)%rsvf * amrtf(imrtf)%rtransp
7394              mrtfsurf(:,imrtf) = (/amrtf(imrtf)%isurflt, amrtf(imrtf)%isurfs /)
7395           ENDDO
7396           IF ( ALLOCATED(amrtf1) )  DEALLOCATE( amrtf1 )
7397           IF ( ALLOCATED(amrtf2) )  DEALLOCATE( amrtf2 )
7398        ENDIF ! nmrtbl > 0
7399
7400        IF ( rad_angular_discretization )  THEN
7401#if defined( __parallel )
7402!--        finalize MPI_RMA communication established to get global index of the surface from grid indices
7403!--        flush all MPI window pending requests
7404           CALL MPI_Win_flush_all(win_gridsurf, ierr)
7405           IF ( ierr /= 0 ) THEN
7406               WRITE(9,*) 'Error MPI_Win_flush_all1:', ierr, win_gridsurf
7407               FLUSH(9)
7408           ENDIF
7409!--        unlock MPI window
7410           CALL MPI_Win_unlock_all(win_gridsurf, ierr)
7411           IF ( ierr /= 0 ) THEN
7412               WRITE(9,*) 'Error MPI_Win_unlock_all1:', ierr, win_gridsurf
7413               FLUSH(9)
7414           ENDIF
7415!--        free MPI window
7416           CALL MPI_Win_free(win_gridsurf, ierr)
7417           IF ( ierr /= 0 ) THEN
7418               WRITE(9,*) 'Error MPI_Win_free1:', ierr, win_gridsurf
7419               FLUSH(9)
7420           ENDIF
7421#else
7422           DEALLOCATE ( gridsurf )
7423#endif
7424        ENDIF
7425
7426        IF ( debug_output )  CALL debug_message( 'waiting for completion of SVF and CSF calculation in all processes', 'info' )
7427
7428!--     deallocate temporary global arrays
7429        DEALLOCATE(nzterr)
7430       
7431        IF ( plant_canopy )  THEN
7432!--         finalize mpi_rma communication and deallocate temporary arrays
7433#if defined( __parallel )
7434            IF ( raytrace_mpi_rma )  THEN
7435                CALL MPI_Win_flush_all(win_lad, ierr)
7436                IF ( ierr /= 0 ) THEN
7437                    WRITE(9,*) 'Error MPI_Win_flush_all2:', ierr, win_lad
7438                    FLUSH(9)
7439                ENDIF
7440!--             unlock MPI window
7441                CALL MPI_Win_unlock_all(win_lad, ierr)
7442                IF ( ierr /= 0 ) THEN
7443                    WRITE(9,*) 'Error MPI_Win_unlock_all2:', ierr, win_lad
7444                    FLUSH(9)
7445                ENDIF
7446!--             free MPI window
7447                CALL MPI_Win_free(win_lad, ierr)
7448                IF ( ierr /= 0 ) THEN
7449                    WRITE(9,*) 'Error MPI_Win_free2:', ierr, win_lad
7450                    FLUSH(9)
7451                ENDIF
7452!--             deallocate temporary arrays storing values for csf calculation during raytracing
7453                DEALLOCATE( lad_s_ray )
7454!--             sub_lad is the pointer to lad_s_rma in case of raytrace_mpi_rma
7455!--             and must not be deallocated here
7456            ELSE
7457                DEALLOCATE(sub_lad)
7458                DEALLOCATE(sub_lad_g)
7459            ENDIF
7460#else
7461            DEALLOCATE(sub_lad)
7462#endif
7463            DEALLOCATE( boxes )
7464            DEALLOCATE( crlens )
7465            DEALLOCATE( plantt )
7466            DEALLOCATE( rt2_track, rt2_track_lad, rt2_track_dist, rt2_dist )
7467        ENDIF
7468
7469        IF ( debug_output )  CALL debug_message( 'calculation of the complete SVF array', 'info' )
7470
7471        IF ( rad_angular_discretization )  THEN
7472           IF ( debug_output )  CALL debug_message( 'Load svf from the structure array to plain arrays', 'info' )
7473           ALLOCATE( svf(ndsvf,nsvfl) )
7474           ALLOCATE( svfsurf(idsvf,nsvfl) )
7475
7476           DO isvf = 1, nsvfl
7477               svf(:, isvf) = (/ asvf(isvf)%rsvf, asvf(isvf)%rtransp /)
7478               svfsurf(:, isvf) = (/ asvf(isvf)%isurflt, asvf(isvf)%isurfs /)
7479           ENDDO
7480        ELSE
7481           IF ( debug_output )  CALL debug_message( 'Start SVF sort', 'info' )
7482!--        sort svf ( a version of quicksort )
7483           CALL quicksort_svf(asvf,1,nsvfl)
7484
7485           !< load svf from the structure array to plain arrays
7486           IF ( debug_output )  CALL debug_message( 'Load svf from the structure array to plain arrays', 'info' )
7487           ALLOCATE( svf(ndsvf,nsvfl) )
7488           ALLOCATE( svfsurf(idsvf,nsvfl) )
7489           svfnorm_counts(:) = 0._wp
7490           isurflt_prev = -1
7491           ksvf = 1
7492           svfsum = 0._wp
7493           DO isvf = 1, nsvfl
7494!--            normalize svf per target face
7495               IF ( asvf(ksvf)%isurflt /= isurflt_prev )  THEN
7496                   IF ( isurflt_prev /= -1  .AND.  svfsum /= 0._wp )  THEN
7497                       !< update histogram of logged svf normalization values
7498                       i = searchsorted(svfnorm_report_thresh, svfsum / (1._wp-skyvf(isurflt_prev)))
7499                       svfnorm_counts(i) = svfnorm_counts(i) + 1
7500
7501                       svf(1, isvf_surflt:isvf-1) = svf(1, isvf_surflt:isvf-1) / svfsum * (1._wp-skyvf(isurflt_prev))
7502                   ENDIF
7503                   isurflt_prev = asvf(ksvf)%isurflt
7504                   isvf_surflt = isvf
7505                   svfsum = asvf(ksvf)%rsvf !?? / asvf(ksvf)%rtransp
7506               ELSE
7507                   svfsum = svfsum + asvf(ksvf)%rsvf !?? / asvf(ksvf)%rtransp
7508               ENDIF
7509
7510               svf(:, isvf) = (/ asvf(ksvf)%rsvf, asvf(ksvf)%rtransp /)
7511               svfsurf(:, isvf) = (/ asvf(ksvf)%isurflt, asvf(ksvf)%isurfs /)
7512
7513!--            next element
7514               ksvf = ksvf + 1
7515           ENDDO
7516
7517           IF ( isurflt_prev /= -1  .AND.  svfsum /= 0._wp )  THEN
7518               i = searchsorted(svfnorm_report_thresh, svfsum / (1._wp-skyvf(isurflt_prev)))
7519               svfnorm_counts(i) = svfnorm_counts(i) + 1
7520
7521               svf(1, isvf_surflt:nsvfl) = svf(1, isvf_surflt:nsvfl) / svfsum * (1._wp-skyvf(isurflt_prev))
7522           ENDIF
7523           WRITE(9, *) 'SVF normalization histogram:', svfnorm_counts,  &
7524                       'on thresholds:', svfnorm_report_thresh(1:svfnorm_report_num), '(val < thresh <= val)'
7525           !TODO we should be able to deallocate skyvf, from now on we only need skyvft
7526        ENDIF ! rad_angular_discretization
7527
7528!--     deallocate temporary asvf array
7529!--     DEALLOCATE(asvf) - ifort has a problem with deallocation of allocatable target
7530!--     via pointing pointer - we need to test original targets
7531        IF ( ALLOCATED(asvf1) )  THEN
7532            DEALLOCATE(asvf1)
7533        ENDIF
7534        IF ( ALLOCATED(asvf2) )  THEN
7535            DEALLOCATE(asvf2)
7536        ENDIF
7537
7538        npcsfl = 0
7539        IF ( plant_canopy )  THEN
7540
7541            IF ( debug_output )  CALL debug_message( 'Calculation of the complete CSF array', 'info' )
7542!--         sort and merge csf for the last time, keeping the array size to minimum
7543            CALL merge_and_grow_csf(-1)
7544           
7545!--         aggregate csb among processors
7546!--         allocate necessary arrays
7547            udim = max(ncsfl,1)
7548            ALLOCATE( csflt_l(ndcsf*udim) )
7549            csflt(1:ndcsf,1:udim) => csflt_l(1:ndcsf*udim)
7550            ALLOCATE( kcsflt_l(kdcsf*udim) )
7551            kcsflt(1:kdcsf,1:udim) => kcsflt_l(1:kdcsf*udim)
7552            ALLOCATE( icsflt(0:numprocs-1) )
7553            ALLOCATE( dcsflt(0:numprocs-1) )
7554            ALLOCATE( ipcsflt(0:numprocs-1) )
7555            ALLOCATE( dpcsflt(0:numprocs-1) )
7556           
7557!--         fill out arrays of csf values and
7558!--         arrays of number of elements and displacements
7559!--         for particular precessors
7560            icsflt = 0
7561            dcsflt = 0
7562            ip = -1
7563            j = -1
7564            d = 0
7565            DO kcsf = 1, ncsfl
7566                j = j+1
7567                IF ( acsf(kcsf)%ip /= ip )  THEN
7568!--                 new block of the processor
7569!--                 number of elements of previous block
7570                    IF ( ip>=0) icsflt(ip) = j
7571                    d = d+j
7572!--                 blank blocks
7573                    DO jp = ip+1, acsf(kcsf)%ip-1
7574!--                     number of elements is zero, displacement is equal to previous
7575                        icsflt(jp) = 0
7576                        dcsflt(jp) = d
7577                    ENDDO
7578!--                 the actual block
7579                    ip = acsf(kcsf)%ip
7580                    dcsflt(ip) = d
7581                    j = 0
7582                ENDIF
7583                csflt(1,kcsf) = acsf(kcsf)%rcvf
7584!--             fill out integer values of itz,ity,itx,isurfs
7585                kcsflt(1,kcsf) = acsf(kcsf)%itz
7586                kcsflt(2,kcsf) = acsf(kcsf)%ity
7587                kcsflt(3,kcsf) = acsf(kcsf)%itx
7588                kcsflt(4,kcsf) = acsf(kcsf)%isurfs
7589            ENDDO
7590!--         last blank blocks at the end of array
7591            j = j+1
7592            IF ( ip>=0 ) icsflt(ip) = j
7593            d = d+j
7594            DO jp = ip+1, numprocs-1
7595!--             number of elements is zero, displacement is equal to previous
7596                icsflt(jp) = 0
7597                dcsflt(jp) = d
7598            ENDDO
7599           
7600!--         deallocate temporary acsf array
7601!--         DEALLOCATE(acsf) - ifort has a problem with deallocation of allocatable target
7602!--         via pointing pointer - we need to test original targets
7603            IF ( ALLOCATED(acsf1) )  THEN
7604                DEALLOCATE(acsf1)
7605            ENDIF
7606            IF ( ALLOCATED(acsf2) )  THEN
7607                DEALLOCATE(acsf2)
7608            ENDIF
7609                   
7610#if defined( __parallel )
7611!--         scatter and gather the number of elements to and from all processor
7612!--         and calculate displacements
7613            IF ( debug_output )  CALL debug_message( 'Scatter and gather the number of elements to and from all processor', 'info' )
7614
7615            CALL MPI_AlltoAll(icsflt,1,MPI_INTEGER,ipcsflt,1,MPI_INTEGER,comm2d, ierr)
7616
7617            IF ( ierr /= 0 ) THEN
7618                WRITE(9,*) 'Error MPI_AlltoAll1:', ierr, SIZE(icsflt), SIZE(ipcsflt)
7619                FLUSH(9)
7620            ENDIF
7621
7622            npcsfl = SUM(ipcsflt)
7623            d = 0
7624            DO i = 0, numprocs-1
7625                dpcsflt(i) = d
7626                d = d + ipcsflt(i)
7627            ENDDO
7628
7629!--         exchange csf fields between processors
7630            IF ( debug_output )  CALL debug_message( 'Exchange csf fields between processors', 'info' )
7631            udim = max(npcsfl,1)
7632            ALLOCATE( pcsflt_l(ndcsf*udim) )
7633            pcsflt(1:ndcsf,1:udim) => pcsflt_l(1:ndcsf*udim)
7634            ALLOCATE( kpcsflt_l(kdcsf*udim) )
7635            kpcsflt(1:kdcsf,1:udim) => kpcsflt_l(1:kdcsf*udim)
7636            CALL MPI_AlltoAllv(csflt_l, ndcsf*icsflt, ndcsf*dcsflt, MPI_REAL, &
7637                pcsflt_l, ndcsf*ipcsflt, ndcsf*dpcsflt, MPI_REAL, comm2d, ierr)
7638            IF ( ierr /= 0 ) THEN
7639                WRITE(9,*) 'Error MPI_AlltoAllv1:', ierr, SIZE(ipcsflt), ndcsf*icsflt, &
7640                            ndcsf*dcsflt, SIZE(pcsflt_l),ndcsf*ipcsflt, ndcsf*dpcsflt
7641                FLUSH(9)
7642            ENDIF
7643
7644            CALL MPI_AlltoAllv(kcsflt_l, kdcsf*icsflt, kdcsf*dcsflt, MPI_INTEGER, &
7645                kpcsflt_l, kdcsf*ipcsflt, kdcsf*dpcsflt, MPI_INTEGER, comm2d, ierr)
7646            IF ( ierr /= 0 ) THEN
7647                WRITE(9,*) 'Error MPI_AlltoAllv2:', ierr, SIZE(kcsflt_l),kdcsf*icsflt, &
7648                           kdcsf*dcsflt, SIZE(kpcsflt_l), kdcsf*ipcsflt, kdcsf*dpcsflt
7649                FLUSH(9)
7650            ENDIF
7651           
7652#else
7653            npcsfl = ncsfl
7654            ALLOCATE( pcsflt(ndcsf,max(npcsfl,ndcsf)) )
7655            ALLOCATE( kpcsflt(kdcsf,max(npcsfl,kdcsf)) )
7656            pcsflt = csflt
7657            kpcsflt = kcsflt
7658#endif
7659
7660!--         deallocate temporary arrays
7661            DEALLOCATE( csflt_l )
7662            DEALLOCATE( kcsflt_l )
7663            DEALLOCATE( icsflt )
7664            DEALLOCATE( dcsflt )
7665            DEALLOCATE( ipcsflt )
7666            DEALLOCATE( dpcsflt )
7667
7668!--         sort csf ( a version of quicksort )
7669            IF ( debug_output )  CALL debug_message( 'Sort csf', 'info' )
7670            CALL quicksort_csf2(kpcsflt, pcsflt, 1, npcsfl)
7671
7672!--         aggregate canopy sink factor records with identical box & source
7673!--         againg across all values from all processors
7674            IF ( debug_output )  CALL debug_message( 'Aggregate canopy sink factor records with identical box', 'info' )
7675
7676            IF ( npcsfl > 0 )  THEN
7677                icsf = 1 !< reading index
7678                kcsf = 1 !< writing index
7679                DO WHILE (icsf < npcsfl)
7680!--                 here kpcsf(kcsf) already has values from kpcsf(icsf)
7681                    IF ( kpcsflt(3,icsf) == kpcsflt(3,icsf+1)  .AND.  &
7682                         kpcsflt(2,icsf) == kpcsflt(2,icsf+1)  .AND.  &
7683                         kpcsflt(1,icsf) == kpcsflt(1,icsf+1)  .AND.  &
7684                         kpcsflt(4,icsf) == kpcsflt(4,icsf+1) )  THEN
7685
7686                        pcsflt(1,kcsf) = pcsflt(1,kcsf) + pcsflt(1,icsf+1)
7687
7688!--                     advance reading index, keep writing index
7689                        icsf = icsf + 1
7690                    ELSE
7691!--                     not identical, just advance and copy
7692                        icsf = icsf + 1
7693                        kcsf = kcsf + 1
7694                        kpcsflt(:,kcsf) = kpcsflt(:,icsf)
7695                        pcsflt(:,kcsf) = pcsflt(:,icsf)
7696                    ENDIF
7697                ENDDO
7698!--             last written item is now also the last item in valid part of array
7699                npcsfl = kcsf
7700            ENDIF
7701
7702            ncsfl = npcsfl
7703            IF ( ncsfl > 0 )  THEN
7704                ALLOCATE( csf(ndcsf,ncsfl) )
7705                ALLOCATE( csfsurf(idcsf,ncsfl) )
7706                DO icsf = 1, ncsfl
7707                    csf(:,icsf) = pcsflt(:,icsf)
7708                    csfsurf(1,icsf) =  gridpcbl(kpcsflt(1,icsf),kpcsflt(2,icsf),kpcsflt(3,icsf))
7709                    csfsurf(2,icsf) =  kpcsflt(4,icsf)
7710                ENDDO
7711            ENDIF
7712           
7713!--         deallocation of temporary arrays
7714            IF ( npcbl > 0 )  DEALLOCATE( gridpcbl )
7715            DEALLOCATE( pcsflt_l )
7716            DEALLOCATE( kpcsflt_l )
7717            IF ( debug_output )  CALL debug_message( 'End of aggregate csf', 'info' )
7718           
7719        ENDIF
7720
7721#if defined( __parallel )
7722        CALL MPI_BARRIER( comm2d, ierr )
7723#endif
7724        CALL location_message( 'calculating view factors for radiation interaction', 'finished' )
7725
7726        RETURN  !todo: remove
7727       
7728!        WRITE( message_string, * )  &
7729!            'I/O error when processing shape view factors / ',  &
7730!            'plant canopy sink factors / direct irradiance factors.'
7731!        CALL message( 'init_urban_surface', 'PA0502', 2, 2, 0, 6, 0 )
7732       
7733    END SUBROUTINE radiation_calc_svf
7734
7735   
7736!------------------------------------------------------------------------------!
7737! Description:
7738! ------------
7739!> Raytracing for detecting obstacles and calculating compound canopy sink
7740!> factors. (A simple obstacle detection would only need to process faces in
7741!> 3 dimensions without any ordering.)
7742!> Assumtions:
7743!> -----------
7744!> 1. The ray always originates from a face midpoint (only one coordinate equals
7745!>    *.5, i.e. wall) and doesn't travel parallel to the surface (that would mean
7746!>    shape factor=0). Therefore, the ray may never travel exactly along a face
7747!>    or an edge.
7748!> 2. From grid bottom to urban surface top the grid has to be *equidistant*
7749!>    within each of the dimensions, including vertical (but the resolution
7750!>    doesn't need to be the same in all three dimensions).
7751!------------------------------------------------------------------------------!
7752    SUBROUTINE raytrace(src, targ, isrc, difvf, atarg, create_csf, visible, transparency)
7753        IMPLICIT NONE
7754
7755        REAL(wp), DIMENSION(3), INTENT(in)     :: src, targ    !< real coordinates z,y,x
7756        INTEGER(iwp), INTENT(in)               :: isrc         !< index of source face for csf
7757        REAL(wp), INTENT(in)                   :: difvf        !< differential view factor for csf
7758        REAL(wp), INTENT(in)                   :: atarg        !< target surface area for csf
7759        LOGICAL, INTENT(in)                    :: create_csf   !< whether to generate new CSFs during raytracing
7760        LOGICAL, INTENT(out)                   :: visible
7761        REAL(wp), INTENT(out)                  :: transparency !< along whole path
7762        INTEGER(iwp)                           :: i, k, d
7763        INTEGER(iwp)                           :: seldim       !< dimension to be incremented
7764        INTEGER(iwp)                           :: ncsb         !< no of written plant canopy sinkboxes
7765        INTEGER(iwp)                           :: maxboxes     !< max no of gridboxes visited
7766        REAL(wp)                               :: distance     !< euclidean along path
7767        REAL(wp)                               :: crlen        !< length of gridbox crossing
7768        REAL(wp)                               :: lastdist     !< beginning of current crossing
7769        REAL(wp)                               :: nextdist     !< end of current crossing
7770        REAL(wp)                               :: realdist     !< distance in meters per unit distance
7771        REAL(wp)                               :: crmid        !< midpoint of crossing
7772        REAL(wp)                               :: cursink      !< sink factor for current canopy box
7773        REAL(wp), DIMENSION(3)                 :: delta        !< path vector
7774        REAL(wp), DIMENSION(3)                 :: uvect        !< unit vector
7775        REAL(wp), DIMENSION(3)                 :: dimnextdist  !< distance for each dimension increments
7776        INTEGER(iwp), DIMENSION(3)             :: box          !< gridbox being crossed
7777        INTEGER(iwp), DIMENSION(3)             :: dimnext      !< next dimension increments along path
7778        INTEGER(iwp), DIMENSION(3)             :: dimdelta     !< dimension direction = +- 1
7779        INTEGER(iwp)                           :: px, py       !< number of processors in x and y dir before
7780                                                               !< the processor in the question
7781        INTEGER(iwp)                           :: ip           !< number of processor where gridbox reside
7782        INTEGER(iwp)                           :: ig           !< 1D index of gridbox in global 2D array
7783       
7784        REAL(wp)                               :: eps = 1E-10_wp !< epsilon for value comparison
7785        REAL(wp)                               :: lad_s_target   !< recieved lad_s of particular grid box
7786
7787!
7788!--     Maximum number of gridboxes visited equals to maximum number of boundaries crossed in each dimension plus one. That's also
7789!--     the maximum number of plant canopy boxes written. We grow the acsf array accordingly using exponential factor.
7790        maxboxes = SUM(ABS(NINT(targ, iwp) - NINT(src, iwp))) + 1
7791        IF ( plant_canopy  .AND.  ncsfl + maxboxes > ncsfla )  THEN
7792!--         use this code for growing by fixed exponential increments (equivalent to case where ncsfl always increases by 1)
7793!--         k = CEILING(grow_factor ** real(CEILING(log(real(ncsfl + maxboxes, kind=wp)) &
7794!--                                                / log(grow_factor)), kind=wp))
7795!--         or use this code to simply always keep some extra space after growing
7796            k = CEILING(REAL(ncsfl + maxboxes, kind=wp) * grow_factor)
7797
7798            CALL merge_and_grow_csf(k)
7799        ENDIF
7800       
7801        transparency = 1._wp
7802        ncsb = 0
7803
7804        delta(:) = targ(:) - src(:)
7805        distance = SQRT(SUM(delta(:)**2))
7806        IF ( distance == 0._wp )  THEN
7807            visible = .TRUE.
7808            RETURN
7809        ENDIF
7810        uvect(:) = delta(:) / distance
7811        realdist = SQRT(SUM( (uvect(:)*(/dz(1),dy,dx/))**2 ))
7812
7813        lastdist = 0._wp
7814
7815!--     Since all face coordinates have values *.5 and we'd like to use
7816!--     integers, all these have .5 added
7817        DO d = 1, 3
7818            IF ( uvect(d) == 0._wp )  THEN
7819                dimnext(d) = 999999999
7820                dimdelta(d) = 999999999
7821                dimnextdist(d) = 1.0E20_wp
7822            ELSE IF ( uvect(d) > 0._wp )  THEN
7823                dimnext(d) = CEILING(src(d) + .5_wp)
7824                dimdelta(d) = 1
7825                dimnextdist(d) = (dimnext(d) - .5_wp - src(d)) / uvect(d)
7826            ELSE
7827                dimnext(d) = FLOOR(src(d) + .5_wp)
7828                dimdelta(d) = -1
7829                dimnextdist(d) = (dimnext(d) - .5_wp - src(d)) / uvect(d)
7830            ENDIF
7831        ENDDO
7832
7833        DO
7834!--         along what dimension will the next wall crossing be?
7835            seldim = minloc(dimnextdist, 1)
7836            nextdist = dimnextdist(seldim)
7837            IF ( nextdist > distance ) nextdist = distance
7838
7839            crlen = nextdist - lastdist
7840            IF ( crlen > .001_wp )  THEN
7841                crmid = (lastdist + nextdist) * .5_wp
7842                box = NINT(src(:) + uvect(:) * crmid, iwp)
7843
7844!--             calculate index of the grid with global indices (box(2),box(3))
7845!--             in the array nzterr and plantt and id of the coresponding processor
7846                px = box(3)/nnx
7847                py = box(2)/nny
7848                ip = px*pdims(2)+py
7849                ig = ip*nnx*nny + (box(3)-px*nnx)*nny + box(2)-py*nny
7850                IF ( box(1) <= nzterr(ig) )  THEN
7851                    visible = .FALSE.
7852                    RETURN
7853                ENDIF
7854
7855                IF ( plant_canopy )  THEN
7856                    IF ( box(1) <= plantt(ig) )  THEN
7857                        ncsb = ncsb + 1
7858                        boxes(:,ncsb) = box
7859                        crlens(ncsb) = crlen
7860#if defined( __parallel )
7861                        lad_ip(ncsb) = ip
7862                        lad_disp(ncsb) = (box(3)-px*nnx)*(nny*nz_plant) + (box(2)-py*nny)*nz_plant + box(1)-nz_urban_b
7863#endif
7864                    ENDIF
7865                ENDIF
7866            ENDIF
7867
7868            IF ( ABS(distance - nextdist) < eps )  EXIT
7869            lastdist = nextdist
7870            dimnext(seldim) = dimnext(seldim) + dimdelta(seldim)
7871            dimnextdist(seldim) = (dimnext(seldim) - .5_wp - src(seldim)) / uvect(seldim)
7872        ENDDO
7873       
7874        IF ( plant_canopy )  THEN
7875#if defined( __parallel )
7876            IF ( raytrace_mpi_rma )  THEN
7877!--             send requests for lad_s to appropriate processor
7878                CALL cpu_log( log_point_s(77), 'rad_rma_lad', 'start' )
7879                DO i = 1, ncsb
7880                    CALL MPI_Get(lad_s_ray(i), 1, MPI_REAL, lad_ip(i), lad_disp(i), &
7881                                 1, MPI_REAL, win_lad, ierr)
7882                    IF ( ierr /= 0 )  THEN
7883                        WRITE(9,*) 'Error MPI_Get1:', ierr, lad_s_ray(i), &
7884                                   lad_ip(i), lad_disp(i), win_lad
7885                        FLUSH(9)
7886                    ENDIF
7887                ENDDO
7888               
7889!--             wait for all pending local requests complete
7890                CALL MPI_Win_flush_local_all(win_lad, ierr)
7891                IF ( ierr /= 0 )  THEN
7892                    WRITE(9,*) 'Error MPI_Win_flush_local_all1:', ierr, win_lad
7893                    FLUSH(9)
7894                ENDIF
7895                CALL cpu_log( log_point_s(77), 'rad_rma_lad', 'stop' )
7896               
7897            ENDIF
7898#endif
7899
7900!--         calculate csf and transparency
7901            DO i = 1, ncsb
7902#if defined( __parallel )
7903                IF ( raytrace_mpi_rma )  THEN
7904                    lad_s_target = lad_s_ray(i)
7905                ELSE
7906                    lad_s_target = sub_lad_g(lad_ip(i)*nnx*nny*nz_plant + lad_disp(i))
7907                ENDIF
7908#else
7909                lad_s_target = sub_lad(boxes(1,i),boxes(2,i),boxes(3,i))
7910#endif
7911                cursink = 1._wp - exp(-ext_coef * lad_s_target * crlens(i)*realdist)
7912
7913                IF ( create_csf )  THEN
7914!--                 write svf values into the array
7915                    ncsfl = ncsfl + 1
7916                    acsf(ncsfl)%ip = lad_ip(i)
7917                    acsf(ncsfl)%itx = boxes(3,i)
7918                    acsf(ncsfl)%ity = boxes(2,i)
7919                    acsf(ncsfl)%itz = boxes(1,i)
7920                    acsf(ncsfl)%isurfs = isrc
7921                    acsf(ncsfl)%rcvf = cursink*transparency*difvf*atarg
7922                ENDIF  !< create_csf
7923
7924                transparency = transparency * (1._wp - cursink)
7925               
7926            ENDDO
7927        ENDIF
7928       
7929        visible = .TRUE.
7930
7931    END SUBROUTINE raytrace
7932   
7933 
7934!------------------------------------------------------------------------------!
7935! Description:
7936! ------------
7937!> A new, more efficient version of ray tracing algorithm that processes a whole
7938!> arc instead of a single ray.
7939!>
7940!> In all comments, horizon means tangent of horizon angle, i.e.
7941!> vertical_delta / horizontal_distance
7942!------------------------------------------------------------------------------!
7943   SUBROUTINE raytrace_2d(origin, yxdir, nrays, zdirs, iorig, aorig, vffrac,  &
7944                              calc_svf, create_csf, skip_1st_pcb,             &
7945                              lowest_free_ray, transparency, itarget)
7946      IMPLICIT NONE
7947
7948      REAL(wp), DIMENSION(3), INTENT(IN)     ::  origin        !< z,y,x coordinates of ray origin
7949      REAL(wp), DIMENSION(2), INTENT(IN)     ::  yxdir         !< y,x *unit* vector of ray direction (in grid units)
7950      INTEGER(iwp)                           ::  nrays         !< number of rays (z directions) to raytrace
7951      REAL(wp), DIMENSION(nrays), INTENT(IN) ::  zdirs         !< list of z directions to raytrace (z/hdist, grid, zenith->nadir)
7952      INTEGER(iwp), INTENT(in)               ::  iorig         !< index of origin face for csf
7953      REAL(wp), INTENT(in)                   ::  aorig         !< origin face area for csf
7954      REAL(wp), DIMENSION(nrays), INTENT(in) ::  vffrac        !< view factor fractions of each ray for csf
7955      LOGICAL, INTENT(in)                    ::  calc_svf      !< whether to calculate SFV (identify obstacle surfaces)
7956      LOGICAL, INTENT(in)                    ::  create_csf    !< whether to create canopy sink factors
7957      LOGICAL, INTENT(in)                    ::  skip_1st_pcb  !< whether to skip first plant canopy box during raytracing
7958      INTEGER(iwp), INTENT(out)              ::  lowest_free_ray !< index into zdirs
7959      REAL(wp), DIMENSION(nrays), INTENT(OUT) ::  transparency !< transparencies of zdirs paths
7960      INTEGER(iwp), DIMENSION(nrays), INTENT(OUT) ::  itarget  !< global indices of target faces for zdirs
7961
7962      INTEGER(iwp), DIMENSION(nrays)         ::  target_procs
7963      REAL(wp)                               ::  horizon       !< highest horizon found after raytracing (z/hdist)
7964      INTEGER(iwp)                           ::  i, k, l, d
7965      INTEGER(iwp)                           ::  seldim       !< dimension to be incremented
7966      REAL(wp), DIMENSION(2)                 ::  yxorigin     !< horizontal copy of origin (y,x)
7967      REAL(wp)                               ::  distance     !< euclidean along path
7968      REAL(wp)                               ::  lastdist     !< beginning of current crossing
7969      REAL(wp)                               ::  nextdist     !< end of current crossing
7970      REAL(wp)                               ::  crmid        !< midpoint of crossing
7971      REAL(wp)                               ::  horz_entry   !< horizon at entry to column
7972      REAL(wp)                               ::  horz_exit    !< horizon at exit from column
7973      REAL(wp)                               ::  bdydim       !< boundary for current dimension
7974      REAL(wp), DIMENSION(2)                 ::  crossdist    !< distances to boundary for dimensions
7975      REAL(wp), DIMENSION(2)                 ::  dimnextdist  !< distance for each dimension increments
7976      INTEGER(iwp), DIMENSION(2)             ::  column       !< grid column being crossed
7977      INTEGER(iwp), DIMENSION(2)             ::  dimnext      !< next dimension increments along path
7978      INTEGER(iwp), DIMENSION(2)             ::  dimdelta     !< dimension direction = +- 1
7979      INTEGER(iwp)                           ::  px, py       !< number of processors in x and y dir before
7980                                                              !< the processor in the question
7981      INTEGER(iwp)                           ::  ip           !< number of processor where gridbox reside
7982      INTEGER(iwp)                           ::  ig           !< 1D index of gridbox in global 2D array
7983      INTEGER(iwp)                           ::  wcount       !< RMA window item count
7984      INTEGER(iwp)                           ::  maxboxes     !< max no of CSF created
7985      INTEGER(iwp)                           ::  nly          !< maximum  plant canopy height
7986      INTEGER(iwp)                           ::  ntrack
7987     
7988      INTEGER(iwp)                           ::  zb0
7989      INTEGER(iwp)                           ::  zb1
7990      INTEGER(iwp)                           ::  nz
7991      INTEGER(iwp)                           ::  iz
7992      INTEGER(iwp)                           ::  zsgn
7993      INTEGER(iwp)                           ::  lowest_lad   !< lowest column cell for which we need LAD
7994      INTEGER(iwp)                           ::  lastdir      !< wall direction before hitting this column
7995      INTEGER(iwp), DIMENSION(2)             ::  lastcolumn
7996
7997#if defined( __parallel )
7998      INTEGER(MPI_ADDRESS_KIND)              ::  wdisp        !< RMA window displacement
7999#endif
8000     
8001      REAL(wp)                               ::  eps = 1E-10_wp !< epsilon for value comparison
8002      REAL(wp)                               ::  zbottom, ztop !< urban surface boundary in real numbers
8003      REAL(wp)                               ::  zorig         !< z coordinate of ray column entry
8004      REAL(wp)                               ::  zexit         !< z coordinate of ray column exit
8005      REAL(wp)                               ::  qdist         !< ratio of real distance to z coord difference
8006      REAL(wp)                               ::  dxxyy         !< square of real horizontal distance
8007      REAL(wp)                               ::  curtrans      !< transparency of current PC box crossing
8008     
8009
8010     
8011      yxorigin(:) = origin(2:3)
8012      transparency(:) = 1._wp !-- Pre-set the all rays to transparent before reducing
8013      horizon = -HUGE(1._wp)
8014      lowest_free_ray = nrays
8015      IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
8016         ALLOCATE(target_surfl(nrays))
8017         target_surfl(:) = -1
8018         lastdir = -999
8019         lastcolumn(:) = -999
8020      ENDIF
8021
8022!--   Determine distance to boundary (in 2D xy)
8023      IF ( yxdir(1) > 0._wp )  THEN
8024         bdydim = ny + .5_wp !< north global boundary
8025         crossdist(1) = (bdydim - yxorigin(1)) / yxdir(1)
8026      ELSEIF ( yxdir(1) == 0._wp )  THEN
8027         crossdist(1) = HUGE(1._wp)
8028      ELSE
8029          bdydim = -.5_wp !< south global boundary
8030          crossdist(1) = (bdydim - yxorigin(1)) / yxdir(1)
8031      ENDIF
8032
8033      IF ( yxdir(2) > 0._wp )  THEN
8034          bdydim = nx + .5_wp !< east global boundary
8035          crossdist(2) = (bdydim - yxorigin(2)) / yxdir(2)
8036      ELSEIF ( yxdir(2) == 0._wp )  THEN
8037         crossdist(2) = HUGE(1._wp)
8038      ELSE
8039          bdydim = -.5_wp !< west global boundary
8040          crossdist(2) = (bdydim - yxorigin(2)) / yxdir(2)
8041      ENDIF
8042      distance = minval(crossdist, 1)
8043
8044      IF ( plant_canopy )  THEN
8045         rt2_track_dist(0) = 0._wp
8046         rt2_track_lad(:,:) = 0._wp
8047         nly = plantt_max - nz_urban_b + 1
8048      ENDIF
8049
8050      lastdist = 0._wp
8051
8052!--   Since all face coordinates have values *.5 and we'd like to use
8053!--   integers, all these have .5 added
8054      DO  d = 1, 2
8055          IF ( yxdir(d) == 0._wp )  THEN
8056              dimnext(d) = HUGE(1_iwp)
8057              dimdelta(d) = HUGE(1_iwp)
8058              dimnextdist(d) = HUGE(1._wp)
8059          ELSE IF ( yxdir(d) > 0._wp )  THEN
8060              dimnext(d) = FLOOR(yxorigin(d) + .5_wp) + 1
8061              dimdelta(d) = 1
8062              dimnextdist(d) = (dimnext(d) - .5_wp - yxorigin(d)) / yxdir(d)
8063          ELSE
8064              dimnext(d) = CEILING(yxorigin(d) + .5_wp) - 1
8065              dimdelta(d) = -1
8066              dimnextdist(d) = (dimnext(d) - .5_wp - yxorigin(d)) / yxdir(d)
8067          ENDIF
8068      ENDDO
8069
8070      ntrack = 0
8071      DO
8072!--      along what dimension will the next wall crossing be?
8073         seldim = minloc(dimnextdist, 1)
8074         nextdist = dimnextdist(seldim)
8075         IF ( nextdist > distance )  nextdist = distance
8076
8077         IF ( nextdist > lastdist )  THEN
8078            ntrack = ntrack + 1
8079            crmid = (lastdist + nextdist) * .5_wp
8080            column = NINT(yxorigin(:) + yxdir(:) * crmid, iwp)
8081
8082!--         calculate index of the grid with global indices (column(1),column(2))
8083!--         in the array nzterr and plantt and id of the coresponding processor
8084            px = column(2)/nnx
8085            py = column(1)/nny
8086            ip = px*pdims(2)+py
8087            ig = ip*nnx*nny + (column(2)-px*nnx)*nny + column(1)-py*nny
8088
8089            IF ( lastdist == 0._wp )  THEN
8090               horz_entry = -HUGE(1._wp)
8091            ELSE
8092               horz_entry = (REAL(nzterr(ig), wp) + .5_wp - origin(1)) / lastdist
8093            ENDIF
8094            horz_exit = (REAL(nzterr(ig), wp) + .5_wp - origin(1)) / nextdist
8095
8096            IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
8097!
8098!--            Identify vertical obstacles hit by rays in current column
8099               DO WHILE ( lowest_free_ray > 0 )
8100                  IF ( zdirs(lowest_free_ray) > horz_entry )  EXIT
8101!
8102!--               This may only happen after 1st column, so lastdir and lastcolumn are valid
8103                  CALL request_itarget(lastdir,                                         &
8104                        CEILING(-0.5_wp + origin(1) + zdirs(lowest_free_ray)*lastdist), &
8105                        lastcolumn(1), lastcolumn(2),                                   &
8106                        target_surfl(lowest_free_ray), target_procs(lowest_free_ray))
8107                  lowest_free_ray = lowest_free_ray - 1
8108               ENDDO
8109!
8110!--            Identify horizontal obstacles hit by rays in current column
8111               DO WHILE ( lowest_free_ray > 0 )
8112                  IF ( zdirs(lowest_free_ray) > horz_exit )  EXIT
8113                  CALL request_itarget(iup_u, nzterr(ig)+1, column(1), column(2), &
8114                                       target_surfl(lowest_free_ray),           &
8115                                       target_procs(lowest_free_ray))
8116                  lowest_free_ray = lowest_free_ray - 1
8117               ENDDO
8118            ENDIF
8119
8120            horizon = MAX(horizon, horz_entry, horz_exit)
8121
8122            IF ( plant_canopy )  THEN
8123               rt2_track(:, ntrack) = column(:)
8124               rt2_track_dist(ntrack) = nextdist
8125            ENDIF
8126         ENDIF
8127
8128         IF ( nextdist + eps >= distance )  EXIT
8129
8130         IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
8131!
8132!--         Save wall direction of coming building column (= this air column)
8133            IF ( seldim == 1 )  THEN
8134               IF ( dimdelta(seldim) == 1 )  THEN
8135                  lastdir = isouth_u
8136               ELSE
8137                  lastdir = inorth_u
8138               ENDIF
8139            ELSE
8140               IF ( dimdelta(seldim) == 1 )  THEN
8141                  lastdir = iwest_u
8142               ELSE
8143                  lastdir = ieast_u
8144               ENDIF
8145            ENDIF
8146            lastcolumn = column
8147         ENDIF
8148         lastdist = nextdist
8149         dimnext(seldim) = dimnext(seldim) + dimdelta(seldim)
8150         dimnextdist(seldim) = (dimnext(seldim) - .5_wp - yxorigin(seldim)) / yxdir(seldim)
8151      ENDDO
8152
8153      IF ( plant_canopy )  THEN
8154!--      Request LAD WHERE applicable
8155!--     
8156#if defined( __parallel )
8157         IF ( raytrace_mpi_rma )  THEN
8158!--         send requests for lad_s to appropriate processor
8159            !CALL cpu_log( log_point_s(77), 'usm_init_rma', 'start' )
8160            DO  i = 1, ntrack
8161               px = rt2_track(2,i)/nnx
8162               py = rt2_track(1,i)/nny
8163               ip = px*pdims(2)+py
8164               ig = ip*nnx*nny + (rt2_track(2,i)-px*nnx)*nny + rt2_track(1,i)-py*nny
8165
8166               IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
8167!
8168!--               For fixed view resolution, we need plant canopy even for rays
8169!--               to opposing surfaces
8170                  lowest_lad = nzterr(ig) + 1
8171               ELSE
8172!
8173!--               We only need LAD for rays directed above horizon (to sky)
8174                  lowest_lad = CEILING( -0.5_wp + origin(1) +            &
8175                                    MIN( horizon * rt2_track_dist(i-1),  & ! entry
8176                                         horizon * rt2_track_dist(i)   ) ) ! exit
8177               ENDIF
8178!
8179!--            Skip asking for LAD where all plant canopy is under requested level
8180               IF ( plantt(ig) < lowest_lad )  CYCLE
8181
8182               wdisp = (rt2_track(2,i)-px*nnx)*(nny*nz_plant) + (rt2_track(1,i)-py*nny)*nz_plant + lowest_lad-nz_urban_b
8183               wcount = plantt(ig)-lowest_lad+1
8184               ! TODO send request ASAP - even during raytracing
8185               CALL MPI_Get(rt2_track_lad(lowest_lad:plantt(ig), i), wcount, MPI_REAL, ip,    &
8186                            wdisp, wcount, MPI_REAL, win_lad, ierr)
8187               IF ( ierr /= 0 )  THEN
8188                  WRITE(9,*) 'Error MPI_Get2:', ierr, rt2_track_lad(lowest_lad:plantt(ig), i), &
8189                             wcount, ip, wdisp, win_lad
8190                  FLUSH(9)
8191               ENDIF
8192            ENDDO
8193
8194!--         wait for all pending local requests complete
8195            ! TODO WAIT selectively for each column later when needed
8196            CALL MPI_Win_flush_local_all(win_lad, ierr)
8197            IF ( ierr /= 0 )  THEN
8198               WRITE(9,*) 'Error MPI_Win_flush_local_all2:', ierr, win_lad
8199               FLUSH(9)
8200            ENDIF
8201            !CALL cpu_log( log_point_s(77), 'usm_init_rma', 'stop' )
8202
8203         ELSE ! raytrace_mpi_rma = .F.
8204            DO  i = 1, ntrack
8205               px = rt2_track(2,i)/nnx
8206               py = rt2_track(1,i)/nny
8207               ip = px*pdims(2)+py
8208               ig = ip*nnx*nny*nz_plant + (rt2_track(2,i)-px*nnx)*(nny*nz_plant) + (rt2_track(1,i)-py*nny)*nz_plant
8209               rt2_track_lad(nz_urban_b:plantt_max, i) = sub_lad_g(ig:ig+nly-1)
8210            ENDDO
8211         ENDIF
8212#else
8213         DO  i = 1, ntrack
8214            rt2_track_lad(nz_urban_b:plantt_max, i) = sub_lad(rt2_track(1,i), rt2_track(2,i), nz_urban_b:plantt_max)
8215         ENDDO
8216#endif
8217      ENDIF ! plant_canopy
8218
8219      IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
8220#if defined( __parallel )
8221!--      wait for all gridsurf requests to complete
8222         CALL MPI_Win_flush_local_all(win_gridsurf, ierr)
8223         IF ( ierr /= 0 )  THEN
8224            WRITE(9,*) 'Error MPI_Win_flush_local_all3:', ierr, win_gridsurf
8225            FLUSH(9)
8226         ENDIF
8227#endif
8228!
8229!--      recalculate local surf indices into global ones
8230         DO i = 1, nrays
8231            IF ( target_surfl(i) == -1 )  THEN
8232               itarget(i) = -1
8233            ELSE
8234               itarget(i) = target_surfl(i) + surfstart(target_procs(i))
8235            ENDIF
8236         ENDDO
8237         
8238         DEALLOCATE( target_surfl )
8239         
8240      ELSE
8241         itarget(:) = -1
8242      ENDIF ! rad_angular_discretization
8243
8244      IF ( plant_canopy )  THEN
8245!--      Skip the PCB around origin if requested (for MRT, the PCB might not be there)
8246!--     
8247         IF ( skip_1st_pcb  .AND.  NINT(origin(1)) <= plantt_max )  THEN
8248            rt2_track_lad(NINT(origin(1), iwp), 1) = 0._wp
8249         ENDIF
8250
8251!--      Assert that we have space allocated for CSFs
8252!--     
8253         maxboxes = (ntrack + MAX(CEILING(origin(1)-.5_wp) - nz_urban_b,          &
8254                                  nz_urban_t - CEILING(origin(1)-.5_wp))) * nrays
8255         IF ( ncsfl + maxboxes > ncsfla )  THEN
8256!--         use this code for growing by fixed exponential increments (equivalent to case where ncsfl always increases by 1)
8257!--         k = CEILING(grow_factor ** real(CEILING(log(real(ncsfl + maxboxes, kind=wp)) &
8258!--                                                / log(grow_factor)), kind=wp))
8259!--         or use this code to simply always keep some extra space after growing
8260            k = CEILING(REAL(ncsfl + maxboxes, kind=wp) * grow_factor)
8261            CALL merge_and_grow_csf(k)
8262         ENDIF
8263
8264!--      Calculate transparencies and store new CSFs
8265!--     
8266         zbottom = REAL(nz_urban_b, wp) - .5_wp
8267         ztop = REAL(plantt_max, wp) + .5_wp
8268
8269!--      Reverse direction of radiation (face->sky), only when calc_svf
8270!--     
8271         IF ( calc_svf )  THEN
8272            DO  i = 1, ntrack ! for each column
8273               dxxyy = ((dy*yxdir(1))**2 + (dx*yxdir(2))**2) * (rt2_track_dist(i)-rt2_track_dist(i-1))**2
8274               px = rt2_track(2,i)/nnx
8275               py = rt2_track(1,i)/nny
8276               ip = px*pdims(2)+py
8277
8278               DO  k = 1, nrays ! for each ray
8279!
8280!--               NOTE 6778:
8281!--               With traditional svf discretization, CSFs under the horizon
8282!--               (i.e. for surface to surface radiation)  are created in
8283!--               raytrace(). With rad_angular_discretization, we must create
8284!--               CSFs under horizon only for one direction, otherwise we would
8285!--               have duplicate amount of energy. Although we could choose
8286!--               either of the two directions (they differ only by
8287!--               discretization error with no bias), we choose the the backward
8288!--               direction, because it tends to cumulate high canopy sink
8289!--               factors closer to raytrace origin, i.e. it should potentially
8290!--               cause less moiree.
8291                  IF ( .NOT. rad_angular_discretization )  THEN
8292                     IF ( zdirs(k) <= horizon )  CYCLE
8293                  ENDIF
8294
8295                  zorig = origin(1) + zdirs(k) * rt2_track_dist(i-1)
8296                  IF ( zorig <= zbottom  .OR.  zorig >= ztop )  CYCLE
8297
8298                  zsgn = INT(SIGN(1._wp, zdirs(k)), iwp)
8299                  rt2_dist(1) = 0._wp
8300                  IF ( zdirs(k) == 0._wp )  THEN ! ray is exactly horizontal
8301                     nz = 2
8302                     rt2_dist(nz) = SQRT(dxxyy)
8303                     iz = CEILING(-.5_wp + zorig, iwp)
8304                  ELSE
8305                     zexit = MIN(MAX(origin(1) + zdirs(k) * rt2_track_dist(i), zbottom), ztop)
8306
8307                     zb0 = FLOOR(  zorig * zsgn - .5_wp) + 1  ! because it must be greater than orig
8308                     zb1 = CEILING(zexit * zsgn - .5_wp) - 1  ! because it must be smaller than exit
8309                     nz = MAX(zb1 - zb0 + 3, 2)
8310                     rt2_dist(nz) = SQRT(((zexit-zorig)*dz(1))**2 + dxxyy)
8311                     qdist = rt2_dist(nz) / (zexit-zorig)
8312                     rt2_dist(2:nz-1) = (/( ((REAL(l, wp) + .5_wp) * zsgn - zorig) * qdist , l = zb0, zb1 )/)
8313                     iz = zb0 * zsgn
8314                  ENDIF
8315
8316                  DO  l = 2, nz
8317                     IF ( rt2_track_lad(iz, i) > 0._wp )  THEN
8318                        curtrans = exp(-ext_coef * rt2_track_lad(iz, i) * (rt2_dist(l)-rt2_dist(l-1)))
8319
8320                        IF ( create_csf )  THEN
8321                           ncsfl = ncsfl + 1
8322                           acsf(ncsfl)%ip = ip
8323                           acsf(ncsfl)%itx = rt2_track(2,i)
8324                           acsf(ncsfl)%ity = rt2_track(1,i)
8325                           acsf(ncsfl)%itz = iz
8326                           acsf(ncsfl)%isurfs = iorig
8327                           acsf(ncsfl)%rcvf = (1._wp - curtrans)*transparency(k)*vffrac(k)
8328                        ENDIF
8329
8330                        transparency(k) = transparency(k) * curtrans
8331                     ENDIF
8332                     iz = iz + zsgn
8333                  ENDDO ! l = 1, nz - 1
8334               ENDDO ! k = 1, nrays
8335            ENDDO ! i = 1, ntrack
8336
8337            transparency(1:lowest_free_ray) = 1._wp !-- Reset rays above horizon to transparent (see NOTE 6778)
8338         ENDIF
8339
8340!--      Forward direction of radiation (sky->face), always
8341!--     
8342         DO  i = ntrack, 1, -1 ! for each column backwards
8343            dxxyy = ((dy*yxdir(1))**2 + (dx*yxdir(2))**2) * (rt2_track_dist(i)-rt2_track_dist(i-1))**2
8344            px = rt2_track(2,i)/nnx
8345            py = rt2_track(1,i)/nny
8346            ip = px*pdims(2)+py
8347
8348            DO  k = 1, nrays ! for each ray
8349!
8350!--            See NOTE 6778 above
8351               IF ( zdirs(k) <= horizon )  CYCLE
8352
8353               zexit = origin(1) + zdirs(k) * rt2_track_dist(i-1)
8354               IF ( zexit <= zbottom  .OR.  zexit >= ztop )  CYCLE
8355
8356               zsgn = -INT(SIGN(1._wp, zdirs(k)), iwp)
8357               rt2_dist(1) = 0._wp
8358               IF ( zdirs(k) == 0._wp )  THEN ! ray is exactly horizontal
8359                  nz = 2
8360                  rt2_dist(nz) = SQRT(dxxyy)
8361                  iz = NINT(zexit, iwp)
8362               ELSE
8363                  zorig = MIN(MAX(origin(1) + zdirs(k) * rt2_track_dist(i), zbottom), ztop)
8364
8365                  zb0 = FLOOR(  zorig * zsgn - .5_wp) + 1  ! because it must be greater than orig
8366                  zb1 = CEILING(zexit * zsgn - .5_wp) - 1  ! because it must be smaller than exit
8367                  nz = MAX(zb1 - zb0 + 3, 2)
8368                  rt2_dist(nz) = SQRT(((zexit-zorig)*dz(1))**2 + dxxyy)
8369                  qdist = rt2_dist(nz) / (zexit-zorig)
8370                  rt2_dist(2:nz-1) = (/( ((REAL(l, wp) + .5_wp) * zsgn - zorig) * qdist , l = zb0, zb1 )/)
8371                  iz = zb0 * zsgn
8372               ENDIF
8373
8374               DO  l = 2, nz
8375                  IF ( rt2_track_lad(iz, i) > 0._wp )  THEN
8376                     curtrans = exp(-ext_coef * rt2_track_lad(iz, i) * (rt2_dist(l)-rt2_dist(l-1)))
8377
8378                     IF ( create_csf )  THEN
8379                        ncsfl = ncsfl + 1
8380                        acsf(ncsfl)%ip = ip
8381                        acsf(ncsfl)%itx = rt2_track(2,i)
8382                        acsf(ncsfl)%ity = rt2_track(1,i)
8383                        acsf(ncsfl)%itz = iz
8384                        IF ( itarget(k) /= -1 ) STOP 1 !FIXME remove after test
8385                        acsf(ncsfl)%isurfs = -1
8386                        acsf(ncsfl)%rcvf = (1._wp - curtrans)*transparency(k)*aorig*vffrac(k)
8387                     ENDIF  ! create_csf
8388
8389                     transparency(k) = transparency(k) * curtrans
8390                  ENDIF
8391                  iz = iz + zsgn
8392               ENDDO ! l = 1, nz - 1
8393            ENDDO ! k = 1, nrays
8394         ENDDO ! i = 1, ntrack
8395      ENDIF ! plant_canopy
8396
8397      IF ( .NOT. (rad_angular_discretization  .AND.  calc_svf) )  THEN
8398!
8399!--      Just update lowest_free_ray according to horizon
8400         DO WHILE ( lowest_free_ray > 0 )
8401            IF ( zdirs(lowest_free_ray) > horizon )  EXIT
8402            lowest_free_ray = lowest_free_ray - 1
8403         ENDDO
8404      ENDIF
8405
8406   CONTAINS
8407
8408      SUBROUTINE request_itarget( d, z, y, x, isurfl, iproc )
8409
8410         INTEGER(iwp), INTENT(in)            ::  d, z, y, x
8411         INTEGER(iwp), TARGET, INTENT(out)   ::  isurfl
8412         INTEGER(iwp), INTENT(out)           ::  iproc
8413#if defined( __parallel )
8414#else
8415         INTEGER(iwp)                        ::  target_displ  !< index of the grid in the local gridsurf array
8416#endif
8417         INTEGER(iwp)                        ::  px, py        !< number of processors in x and y direction
8418                                                               !< before the processor in the question
8419#if defined( __parallel )
8420         INTEGER(KIND=MPI_ADDRESS_KIND)      ::  target_displ  !< index of the grid in the local gridsurf array
8421
8422!
8423!--      Calculate target processor and index in the remote local target gridsurf array
8424         px = x / nnx
8425         py = y / nny
8426         iproc = px * pdims(2) + py
8427         target_displ = ((x-px*nnx) * nny + y - py*nny ) * nz_urban * nsurf_type_u +&
8428                        ( z-nz_urban_b ) * nsurf_type_u + d
8429!
8430!--      Send MPI_Get request to obtain index target_surfl(i)
8431         CALL MPI_GET( isurfl, 1, MPI_INTEGER, iproc, target_displ,            &
8432                       1, MPI_INTEGER, win_gridsurf, ierr)
8433         IF ( ierr /= 0 )  THEN
8434            WRITE( 9,* ) 'Error MPI_Get3:', ierr, isurfl, iproc, target_displ, &
8435                         win_gridsurf
8436            FLUSH( 9 )
8437         ENDIF
8438#else
8439!--      set index target_surfl(i)
8440         isurfl = gridsurf(d,z,y,x)
8441#endif
8442
8443      END SUBROUTINE request_itarget
8444
8445   END SUBROUTINE raytrace_2d
8446 
8447
8448!------------------------------------------------------------------------------!
8449!
8450! Description:
8451! ------------
8452!> Calculates apparent solar positions for all timesteps and stores discretized
8453!> positions.
8454!------------------------------------------------------------------------------!
8455   SUBROUTINE radiation_presimulate_solar_pos
8456
8457      IMPLICIT NONE
8458
8459      INTEGER(iwp)                              ::  it, i, j
8460      INTEGER(iwp)                              ::  day_of_month_prev,month_of_year_prev
8461      REAL(wp)                                  ::  tsrp_prev
8462      REAL(wp)                                  ::  simulated_time_prev
8463      REAL(wp), DIMENSION(:,:), ALLOCATABLE     ::  dsidir_tmp       !< dsidir_tmp[:,i] = unit vector of i-th
8464                                                                     !< appreant solar direction
8465
8466      ALLOCATE ( dsidir_rev(0:raytrace_discrete_elevs/2-1,                 &
8467                            0:raytrace_discrete_azims-1) )
8468      dsidir_rev(:,:) = -1
8469      ALLOCATE ( dsidir_tmp(3,                                             &
8470                     raytrace_discrete_elevs/2*raytrace_discrete_azims) )
8471      ndsidir = 0
8472
8473!
8474!--   We will artificialy update time_since_reference_point and return to
8475!--   true value later
8476      tsrp_prev = time_since_reference_point
8477      simulated_time_prev = simulated_time
8478      day_of_month_prev = day_of_month
8479      month_of_year_prev = month_of_year
8480      sun_direction = .TRUE.
8481
8482!
8483!--   initialize the simulated_time
8484      simulated_time = 0._wp
8485!
8486!--   Process spinup time if configured
8487      IF ( spinup_time > 0._wp )  THEN
8488         DO  it = 0, CEILING(spinup_time / dt_spinup)
8489            time_since_reference_point = -spinup_time + REAL(it, wp) * dt_spinup
8490            simulated_time = simulated_time + dt_spinup
8491            CALL simulate_pos
8492         ENDDO
8493      ENDIF
8494!
8495!--   Process simulation time
8496      DO  it = 0, CEILING(( end_time - spinup_time ) / dt_radiation)
8497         time_since_reference_point = REAL(it, wp) * dt_radiation
8498         simulated_time = simulated_time + dt_radiation
8499         CALL simulate_pos
8500      ENDDO
8501!
8502!--   Return date and time to its original values
8503      time_since_reference_point = tsrp_prev
8504      simulated_time = simulated_time_prev
8505      day_of_month = day_of_month_prev
8506      month_of_year = month_of_year_prev
8507      CALL init_date_and_time
8508
8509!--   Allocate global vars which depend on ndsidir
8510      ALLOCATE ( dsidir ( 3, ndsidir ) )
8511      dsidir(:,:) = dsidir_tmp(:, 1:ndsidir)
8512      DEALLOCATE ( dsidir_tmp )
8513
8514      ALLOCATE ( dsitrans(nsurfl, ndsidir) )
8515      ALLOCATE ( dsitransc(npcbl, ndsidir) )
8516      IF ( nmrtbl > 0 )  ALLOCATE ( mrtdsit(nmrtbl, ndsidir) )
8517
8518      WRITE ( message_string, * ) 'Precalculated', ndsidir, ' solar positions', &
8519                                  ' from', it, ' timesteps.'
8520      CALL message( 'radiation_presimulate_solar_pos', 'UI0013', 0, 0, 0, 6, 0 )
8521
8522      CONTAINS
8523
8524      !------------------------------------------------------------------------!
8525      ! Description:
8526      ! ------------
8527      !> Simuates a single position
8528      !------------------------------------------------------------------------!
8529      SUBROUTINE simulate_pos
8530         IMPLICIT NONE
8531!
8532!--      Update apparent solar position based on modified t_s_r_p
8533         CALL calc_zenith
8534         IF ( cos_zenith > 0 )  THEN
8535!--         
8536!--         Identify solar direction vector (discretized number) 1)
8537            i = MODULO(NINT(ATAN2(sun_dir_lon, sun_dir_lat)               &
8538                            / (2._wp*pi) * raytrace_discrete_azims-.5_wp, iwp), &
8539                       raytrace_discrete_azims)
8540            j = FLOOR(ACOS(cos_zenith) / pi * raytrace_discrete_elevs)
8541            IF ( dsidir_rev(j, i) == -1 )  THEN
8542               ndsidir = ndsidir + 1
8543               dsidir_tmp(:, ndsidir) =                                              &
8544                     (/ COS((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs), &
8545                        SIN((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs)  &
8546                      * COS((REAL(i,wp)+.5_wp) * 2_wp*pi / raytrace_discrete_azims), &
8547                        SIN((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs)  &
8548                      * SIN((REAL(i,wp)+.5_wp) * 2_wp*pi / raytrace_discrete_azims) /)
8549               dsidir_rev(j, i) = ndsidir
8550            ENDIF
8551         ENDIF
8552      END SUBROUTINE simulate_pos
8553
8554   END SUBROUTINE radiation_presimulate_solar_pos
8555
8556
8557
8558!------------------------------------------------------------------------------!
8559! Description:
8560! ------------
8561!> Determines whether two faces are oriented towards each other. Since the
8562!> surfaces follow the gird box surfaces, it checks first whether the two surfaces
8563!> are directed in the same direction, then it checks if the two surfaces are
8564!> located in confronted direction but facing away from each other, e.g. <--| |-->
8565!------------------------------------------------------------------------------!
8566    PURE LOGICAL FUNCTION surface_facing(x, y, z, d, x2, y2, z2, d2)
8567        IMPLICIT NONE
8568        INTEGER(iwp),   INTENT(in)  :: x, y, z, d, x2, y2, z2, d2
8569     
8570        surface_facing = .FALSE.
8571
8572!-- first check: are the two surfaces directed in the same direction
8573        IF ( (d==iup_u  .OR.  d==iup_l )                             &
8574             .AND. (d2==iup_u  .OR. d2==iup_l) ) RETURN
8575        IF ( (d==isouth_u  .OR.  d==isouth_l ) &
8576             .AND.  (d2==isouth_u  .OR.  d2==isouth_l) ) RETURN
8577        IF ( (d==inorth_u  .OR.  d==inorth_l ) &
8578             .AND.  (d2==inorth_u  .OR.  d2==inorth_l) ) RETURN
8579        IF ( (d==iwest_u  .OR.  d==iwest_l )     &
8580             .AND.  (d2==iwest_u  .OR.  d2==iwest_l ) ) RETURN
8581        IF ( (d==ieast_u  .OR.  d==ieast_l )     &
8582             .AND.  (d2==ieast_u  .OR.  d2==ieast_l ) ) RETURN
8583
8584!-- second check: are surfaces facing away from each other
8585        SELECT CASE (d)
8586            CASE (iup_u, iup_l)                     !< upward facing surfaces
8587                IF ( z2 < z ) RETURN
8588            CASE (isouth_u, isouth_l)               !< southward facing surfaces
8589                IF ( y2 > y ) RETURN
8590            CASE (inorth_u, inorth_l)               !< northward facing surfaces
8591                IF ( y2 < y ) RETURN
8592            CASE (iwest_u, iwest_l)                 !< westward facing surfaces
8593                IF ( x2 > x ) RETURN
8594            CASE (ieast_u, ieast_l)                 !< eastward facing surfaces
8595                IF ( x2 < x ) RETURN
8596        END SELECT
8597
8598        SELECT CASE (d2)
8599            CASE (iup_u)                            !< ground, roof
8600                IF ( z < z2 ) RETURN
8601            CASE (isouth_u, isouth_l)               !< south facing
8602                IF ( y > y2 ) RETURN
8603            CASE (inorth_u, inorth_l)               !< north facing
8604                IF ( y < y2 ) RETURN
8605            CASE (iwest_u, iwest_l)                 !< west facing
8606                IF ( x > x2 ) RETURN
8607            CASE (ieast_u, ieast_l)                 !< east facing
8608                IF ( x < x2 ) RETURN
8609            CASE (-1)
8610                CONTINUE
8611        END SELECT
8612
8613        surface_facing = .TRUE.
8614       
8615    END FUNCTION surface_facing
8616
8617
8618!------------------------------------------------------------------------------!
8619!
8620! Description:
8621! ------------
8622!> Reads svf, svfsurf, csf, csfsurf and mrt factors data from saved file
8623!> SVF means sky view factors and CSF means canopy sink factors
8624!------------------------------------------------------------------------------!
8625    SUBROUTINE radiation_read_svf
8626
8627       IMPLICIT NONE
8628       
8629       CHARACTER(rad_version_len)   :: rad_version_field
8630       
8631       INTEGER(iwp)                 :: i
8632       INTEGER(iwp)                 :: ndsidir_from_file = 0
8633       INTEGER(iwp)                 :: npcbl_from_file = 0
8634       INTEGER(iwp)                 :: nsurfl_from_file = 0
8635       INTEGER(iwp)                 :: nmrtbl_from_file = 0
8636
8637
8638       CALL location_message( 'reading view factors for radiation interaction', 'start' )
8639
8640       DO  i = 0, io_blocks-1
8641          IF ( i == io_group )  THEN
8642
8643!
8644!--          numprocs_previous_run is only known in case of reading restart
8645!--          data. If a new initial run which reads svf data is started the
8646!--          following query will be skipped
8647             IF ( initializing_actions == 'read_restart_data' ) THEN
8648
8649                IF ( numprocs_previous_run /= numprocs ) THEN
8650                   WRITE( message_string, * ) 'A different number of ',        &
8651                                              'processors between the run ',   &
8652                                              'that has written the svf data ',&
8653                                              'and the one that will read it ',&
8654                                              'is not allowed' 
8655                   CALL message( 'check_open', 'PA0491', 1, 2, 0, 6, 0 )
8656                ENDIF
8657
8658             ENDIF
8659             
8660!
8661!--          Open binary file
8662             CALL check_open( 88 )
8663
8664!
8665!--          read and check version
8666             READ ( 88 ) rad_version_field
8667             IF ( TRIM(rad_version_field) /= TRIM(rad_version) )  THEN
8668                 WRITE( message_string, * ) 'Version of binary SVF file "',    &
8669                             TRIM(rad_version_field), '" does not match ',     &
8670                             'the version of model "', TRIM(rad_version), '"'
8671                 CALL message( 'radiation_read_svf', 'PA0482', 1, 2, 0, 6, 0 )
8672             ENDIF
8673             
8674!
8675!--          read nsvfl, ncsfl, nsurfl, nmrtf
8676             READ ( 88 ) nsvfl, ncsfl, nsurfl_from_file, npcbl_from_file,      &
8677                         ndsidir_from_file, nmrtbl_from_file, nmrtf
8678             
8679             IF ( nsvfl < 0  .OR.  ncsfl < 0 )  THEN
8680                 WRITE( message_string, * ) 'Wrong number of SVF or CSF'
8681                 CALL message( 'radiation_read_svf', 'PA0483', 1, 2, 0, 6, 0 )
8682             ELSE
8683                 WRITE(debug_string,*)   'Number of SVF, CSF, and nsurfl ',    &
8684                                         'to read', nsvfl, ncsfl,              &
8685                                         nsurfl_from_file
8686                 IF ( debug_output )  CALL debug_message( debug_string, 'info' )
8687             ENDIF
8688             
8689             IF ( nsurfl_from_file /= nsurfl )  THEN
8690                 WRITE( message_string, * ) 'nsurfl from SVF file does not ',  &
8691                                            'match calculated nsurfl from ',   &
8692                                            'radiation_interaction_init'
8693                 CALL message( 'radiation_read_svf', 'PA0490', 1, 2, 0, 6, 0 )
8694             ENDIF
8695             
8696             IF ( npcbl_from_file /= npcbl )  THEN
8697                 WRITE( message_string, * ) 'npcbl from SVF file does not ',   &
8698                                            'match calculated npcbl from ',    &
8699                                            'radiation_interaction_init'
8700                 CALL message( 'radiation_read_svf', 'PA0493', 1, 2, 0, 6, 0 )
8701             ENDIF
8702             
8703             IF ( ndsidir_from_file /= ndsidir )  THEN
8704                 WRITE( message_string, * ) 'ndsidir from SVF file does not ', &
8705                                            'match calculated ndsidir from ',  &
8706                                            'radiation_presimulate_solar_pos'
8707                 CALL message( 'radiation_read_svf', 'PA0494', 1, 2, 0, 6, 0 )
8708             ENDIF
8709             IF ( nmrtbl_from_file /= nmrtbl )  THEN
8710                 WRITE( message_string, * ) 'nmrtbl from SVF file does not ',  &
8711                                            'match calculated nmrtbl from ',   &
8712                                            'radiation_interaction_init'
8713                 CALL message( 'radiation_read_svf', 'PA0494', 1, 2, 0, 6, 0 )
8714             ELSE
8715                 WRITE(debug_string,*) 'Number of nmrtf to read ', nmrtf
8716                 IF ( debug_output )  CALL debug_message( debug_string, 'info' )
8717             ENDIF
8718             
8719!
8720!--          Arrays skyvf, skyvft, dsitrans and dsitransc are allready
8721!--          allocated in radiation_interaction_init and
8722!--          radiation_presimulate_solar_pos
8723             IF ( nsurfl > 0 )  THEN
8724                READ(88) skyvf
8725                READ(88) skyvft
8726                READ(88) dsitrans 
8727             ENDIF
8728             
8729             IF ( plant_canopy  .AND.  npcbl > 0 ) THEN
8730                READ ( 88 )  dsitransc
8731             ENDIF
8732             
8733!
8734!--          The allocation of svf, svfsurf, csf, csfsurf, mrtf, mrtft, and
8735!--          mrtfsurf happens in routine radiation_calc_svf which is not
8736!--          called if the program enters radiation_read_svf. Therefore
8737!--          these arrays has to allocate in the following
8738             IF ( nsvfl > 0 )  THEN
8739                ALLOCATE( svf(ndsvf,nsvfl) )
8740                ALLOCATE( svfsurf(idsvf,nsvfl) )
8741                READ(88) svf
8742                READ(88) svfsurf
8743             ENDIF
8744
8745             IF ( plant_canopy  .AND.  ncsfl > 0 )  THEN
8746                ALLOCATE( csf(ndcsf,ncsfl) )
8747                ALLOCATE( csfsurf(idcsf,ncsfl) )
8748                READ(88) csf
8749                READ(88) csfsurf
8750             ENDIF
8751
8752             IF ( nmrtbl > 0 )  THEN
8753                READ(88) mrtsky
8754                READ(88) mrtskyt
8755                READ(88) mrtdsit
8756             ENDIF
8757
8758             IF ( nmrtf > 0 )  THEN
8759                ALLOCATE ( mrtf(nmrtf) )
8760                ALLOCATE ( mrtft(nmrtf) )
8761                ALLOCATE ( mrtfsurf(2,nmrtf) )
8762                READ(88) mrtf
8763                READ(88) mrtft
8764                READ(88) mrtfsurf
8765             ENDIF
8766             
8767!
8768!--          Close binary file                 
8769             CALL close_file( 88 )
8770               
8771          ENDIF
8772#if defined( __parallel )
8773          CALL MPI_BARRIER( comm2d, ierr )
8774#endif
8775       ENDDO
8776
8777       CALL location_message( 'reading view factors for radiation interaction', 'finished' )
8778
8779
8780    END SUBROUTINE radiation_read_svf
8781
8782
8783!------------------------------------------------------------------------------!
8784!
8785! Description:
8786! ------------
8787!> Subroutine stores svf, svfsurf, csf, csfsurf and mrt data to a file.
8788!------------------------------------------------------------------------------!
8789    SUBROUTINE radiation_write_svf
8790
8791       IMPLICIT NONE
8792       
8793       INTEGER(iwp)        :: i
8794
8795
8796       CALL location_message( 'writing view factors for radiation interaction', 'start' )
8797
8798       DO  i = 0, io_blocks-1
8799          IF ( i == io_group )  THEN
8800!
8801!--          Open binary file
8802             CALL check_open( 89 )
8803
8804             WRITE ( 89 )  rad_version
8805             WRITE ( 89 )  nsvfl, ncsfl, nsurfl, npcbl, ndsidir, nmrtbl, nmrtf
8806             IF ( nsurfl > 0 ) THEN
8807                WRITE ( 89 )  skyvf
8808                WRITE ( 89 )  skyvft
8809                WRITE ( 89 )  dsitrans
8810             ENDIF
8811             IF ( npcbl > 0 ) THEN
8812                WRITE ( 89 )  dsitransc
8813             ENDIF
8814             IF ( nsvfl > 0 ) THEN
8815                WRITE ( 89 )  svf
8816                WRITE ( 89 )  svfsurf
8817             ENDIF
8818             IF ( plant_canopy  .AND.  ncsfl > 0 )  THEN
8819                 WRITE ( 89 )  csf
8820                 WRITE ( 89 )  csfsurf
8821             ENDIF
8822             IF ( nmrtbl > 0 )  THEN
8823                WRITE ( 89 ) mrtsky
8824                WRITE ( 89 ) mrtskyt
8825                WRITE ( 89 ) mrtdsit
8826             ENDIF
8827             IF ( nmrtf > 0 )  THEN
8828                 WRITE ( 89 )  mrtf
8829                 WRITE ( 89 )  mrtft               
8830                 WRITE ( 89 )  mrtfsurf
8831             ENDIF
8832!
8833!--          Close binary file                 
8834             CALL close_file( 89 )
8835
8836          ENDIF
8837#if defined( __parallel )
8838          CALL MPI_BARRIER( comm2d, ierr )
8839#endif
8840       ENDDO
8841
8842       CALL location_message( 'writing view factors for radiation interaction', 'finished' )
8843
8844
8845    END SUBROUTINE radiation_write_svf
8846
8847
8848!------------------------------------------------------------------------------!
8849!
8850! Description:
8851! ------------
8852!> Block of auxiliary subroutines:
8853!> 1. quicksort and corresponding comparison
8854!> 2. merge_and_grow_csf for implementation of "dynamical growing"
8855!>    array for csf
8856!------------------------------------------------------------------------------!
8857!-- quicksort.f -*-f90-*-
8858!-- Author: t-nissie, adaptation J.Resler
8859!-- License: GPLv3
8860!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8861    RECURSIVE SUBROUTINE quicksort_itarget(itarget, vffrac, ztransp, first, last)
8862        IMPLICIT NONE
8863        INTEGER(iwp), DIMENSION(:), INTENT(INOUT)   :: itarget
8864        REAL(wp), DIMENSION(:), INTENT(INOUT)       :: vffrac, ztransp
8865        INTEGER(iwp), INTENT(IN)                    :: first, last
8866        INTEGER(iwp)                                :: x, t
8867        INTEGER(iwp)                                :: i, j
8868        REAL(wp)                                    :: tr
8869
8870        IF ( first>=last ) RETURN
8871        x = itarget((first+last)/2)
8872        i = first
8873        j = last
8874        DO
8875            DO WHILE ( itarget(i) < x )
8876               i=i+1
8877            ENDDO
8878            DO WHILE ( x < itarget(j) )
8879                j=j-1
8880            ENDDO
8881            IF ( i >= j ) EXIT
8882            t = itarget(i);  itarget(i) = itarget(j);  itarget(j) = t
8883            tr = vffrac(i);  vffrac(i) = vffrac(j);  vffrac(j) = tr
8884            tr = ztransp(i);  ztransp(i) = ztransp(j);  ztransp(j) = tr
8885            i=i+1
8886            j=j-1
8887        ENDDO
8888        IF ( first < i-1 ) CALL quicksort_itarget(itarget, vffrac, ztransp, first, i-1)
8889        IF ( j+1 < last )  CALL quicksort_itarget(itarget, vffrac, ztransp, j+1, last)
8890    END SUBROUTINE quicksort_itarget
8891
8892    PURE FUNCTION svf_lt(svf1,svf2) result (res)
8893      TYPE (t_svf), INTENT(in) :: svf1,svf2
8894      LOGICAL                  :: res
8895      IF ( svf1%isurflt < svf2%isurflt  .OR.    &
8896          (svf1%isurflt == svf2%isurflt  .AND.  svf1%isurfs < svf2%isurfs) )  THEN
8897          res = .TRUE.
8898      ELSE
8899          res = .FALSE.
8900      ENDIF
8901    END FUNCTION svf_lt
8902
8903
8904!-- quicksort.f -*-f90-*-
8905!-- Author: t-nissie, adaptation J.Resler
8906!-- License: GPLv3
8907!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8908    RECURSIVE SUBROUTINE quicksort_svf(svfl, first, last)
8909        IMPLICIT NONE
8910        TYPE(t_svf), DIMENSION(:), INTENT(INOUT)  :: svfl
8911        INTEGER(iwp), INTENT(IN)                  :: first, last
8912        TYPE(t_svf)                               :: x, t
8913        INTEGER(iwp)                              :: i, j
8914
8915        IF ( first>=last ) RETURN
8916        x = svfl( (first+last) / 2 )
8917        i = first
8918        j = last
8919        DO
8920            DO while ( svf_lt(svfl(i),x) )
8921               i=i+1
8922            ENDDO
8923            DO while ( svf_lt(x,svfl(j)) )
8924                j=j-1
8925            ENDDO
8926            IF ( i >= j ) EXIT
8927            t = svfl(i);  svfl(i) = svfl(j);  svfl(j) = t
8928            i=i+1
8929            j=j-1
8930        ENDDO
8931        IF ( first < i-1 ) CALL quicksort_svf(svfl, first, i-1)
8932        IF ( j+1 < last )  CALL quicksort_svf(svfl, j+1, last)
8933    END SUBROUTINE quicksort_svf
8934
8935    PURE FUNCTION csf_lt(csf1,csf2) result (res)
8936      TYPE (t_csf), INTENT(in) :: csf1,csf2
8937      LOGICAL                  :: res
8938      IF ( csf1%ip < csf2%ip  .OR.    &
8939           (csf1%ip == csf2%ip  .AND.  csf1%itx < csf2%itx)  .OR.  &
8940           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity < csf2%ity)  .OR.  &
8941           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity == csf2%ity  .AND.   &
8942            csf1%itz < csf2%itz)  .OR.  &
8943           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity == csf2%ity  .AND.   &
8944            csf1%itz == csf2%itz  .AND.  csf1%isurfs < csf2%isurfs) )  THEN
8945          res = .TRUE.
8946      ELSE
8947          res = .FALSE.
8948      ENDIF
8949    END FUNCTION csf_lt
8950
8951
8952!-- quicksort.f -*-f90-*-
8953!-- Author: t-nissie, adaptation J.Resler
8954!-- License: GPLv3
8955!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8956    RECURSIVE SUBROUTINE quicksort_csf(csfl, first, last)
8957        IMPLICIT NONE
8958        TYPE(t_csf), DIMENSION(:), INTENT(INOUT)  :: csfl
8959        INTEGER(iwp), INTENT(IN)                  :: first, last
8960        TYPE(t_csf)                               :: x, t
8961        INTEGER(iwp)                              :: i, j
8962
8963        IF ( first>=last ) RETURN
8964        x = csfl( (first+last)/2 )
8965        i = first
8966        j = last
8967        DO
8968            DO while ( csf_lt(csfl(i),x) )
8969                i=i+1
8970            ENDDO
8971            DO while ( csf_lt(x,csfl(j)) )
8972                j=j-1
8973            ENDDO
8974            IF ( i >= j ) EXIT
8975            t = csfl(i);  csfl(i) = csfl(j);  csfl(j) = t
8976            i=i+1
8977            j=j-1
8978        ENDDO
8979        IF ( first < i-1 ) CALL quicksort_csf(csfl, first, i-1)
8980        IF ( j+1 < last )  CALL quicksort_csf(csfl, j+1, last)
8981    END SUBROUTINE quicksort_csf
8982
8983   
8984!------------------------------------------------------------------------------!
8985!
8986! Description:
8987! ------------
8988!> Grows the CSF array exponentially after it is full. During that, the ray
8989!> canopy sink factors with common source face and target plant canopy grid
8990!> cell are merged together so that the size doesn't grow out of control.
8991!------------------------------------------------------------------------------!
8992    SUBROUTINE merge_and_grow_csf(newsize)
8993        INTEGER(iwp), INTENT(in)                :: newsize  !< new array size after grow, must be >= ncsfl
8994                                                            !< or -1 to shrink to minimum
8995        INTEGER(iwp)                            :: iread, iwrite
8996        TYPE(t_csf), DIMENSION(:), POINTER      :: acsfnew
8997
8998
8999        IF ( newsize == -1 )  THEN
9000!--         merge in-place
9001            acsfnew => acsf
9002        ELSE
9003!--         allocate new array
9004            IF ( mcsf == 0 )  THEN
9005                ALLOCATE( acsf1(newsize) )
9006                acsfnew => acsf1
9007            ELSE
9008                ALLOCATE( acsf2(newsize) )
9009                acsfnew => acsf2
9010            ENDIF
9011        ENDIF
9012
9013        IF ( ncsfl >= 1 )  THEN
9014!--         sort csf in place (quicksort)
9015            CALL quicksort_csf(acsf,1,ncsfl)
9016
9017!--         while moving to a new array, aggregate canopy sink factor records with identical box & source
9018            acsfnew(1) = acsf(1)
9019            iwrite = 1
9020            DO iread = 2, ncsfl
9021!--             here acsf(kcsf) already has values from acsf(icsf)
9022                IF ( acsfnew(iwrite)%itx == acsf(iread)%itx &
9023                         .AND.  acsfnew(iwrite)%ity == acsf(iread)%ity &
9024                         .AND.  acsfnew(iwrite)%itz == acsf(iread)%itz &
9025                         .AND.  acsfnew(iwrite)%isurfs == acsf(iread)%isurfs )  THEN
9026
9027                    acsfnew(iwrite)%rcvf = acsfnew(iwrite)%rcvf + acsf(iread)%rcvf
9028!--                 advance reading index, keep writing index
9029                ELSE
9030!--                 not identical, just advance and copy
9031                    iwrite = iwrite + 1
9032                    acsfnew(iwrite) = acsf(iread)
9033                ENDIF
9034            ENDDO
9035            ncsfl = iwrite
9036        ENDIF
9037
9038        IF ( newsize == -1 )  THEN
9039!--         allocate new array and copy shrinked data
9040            IF ( mcsf == 0 )  THEN
9041                ALLOCATE( acsf1(ncsfl) )
9042                acsf1(1:ncsfl) = acsf2(1:ncsfl)
9043            ELSE
9044                ALLOCATE( acsf2(ncsfl) )
9045                acsf2(1:ncsfl) = acsf1(1:ncsfl)
9046            ENDIF
9047        ENDIF
9048
9049!--     deallocate old array
9050        IF ( mcsf == 0 )  THEN
9051            mcsf = 1
9052            acsf => acsf1
9053            DEALLOCATE( acsf2 )
9054        ELSE
9055            mcsf = 0
9056            acsf => acsf2
9057            DEALLOCATE( acsf1 )
9058        ENDIF
9059        ncsfla = newsize
9060
9061        IF ( debug_output )  THEN
9062           WRITE( debug_string, '(A,2I12)' ) 'Grow acsf2:', ncsfl, ncsfla
9063           CALL debug_message( debug_string, 'info' )
9064        ENDIF
9065
9066    END SUBROUTINE merge_and_grow_csf
9067
9068   
9069!-- quicksort.f -*-f90-*-
9070!-- Author: t-nissie, adaptation J.Resler
9071!-- License: GPLv3
9072!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
9073    RECURSIVE SUBROUTINE quicksort_csf2(kpcsflt, pcsflt, first, last)
9074        IMPLICIT NONE
9075        INTEGER(iwp), DIMENSION(:,:), INTENT(INOUT)  :: kpcsflt
9076        REAL(wp), DIMENSION(:,:), INTENT(INOUT)      :: pcsflt
9077        INTEGER(iwp), INTENT(IN)                     :: first, last
9078        REAL(wp), DIMENSION(ndcsf)                   :: t2
9079        INTEGER(iwp), DIMENSION(kdcsf)               :: x, t1
9080        INTEGER(iwp)                                 :: i, j
9081
9082        IF ( first>=last ) RETURN
9083        x = kpcsflt(:, (first+last)/2 )
9084        i = first
9085        j = last
9086        DO
9087            DO while ( csf_lt2(kpcsflt(:,i),x) )
9088                i=i+1
9089            ENDDO
9090            DO while ( csf_lt2(x,kpcsflt(:,j)) )
9091                j=j-1
9092            ENDDO
9093            IF ( i >= j ) EXIT
9094            t1 = kpcsflt(:,i);  kpcsflt(:,i) = kpcsflt(:,j);  kpcsflt(:,j) = t1
9095            t2 = pcsflt(:,i);  pcsflt(:,i) = pcsflt(:,j);  pcsflt(:,j) = t2
9096            i=i+1
9097            j=j-1
9098        ENDDO
9099        IF ( first < i-1 ) CALL quicksort_csf2(kpcsflt, pcsflt, first, i-1)
9100        IF ( j+1 < last )  CALL quicksort_csf2(kpcsflt, pcsflt, j+1, last)
9101    END SUBROUTINE quicksort_csf2
9102   
9103
9104    PURE FUNCTION csf_lt2(item1, item2) result(res)
9105        INTEGER(iwp), DIMENSION(kdcsf), INTENT(in)  :: item1, item2
9106        LOGICAL                                     :: res
9107        res = ( (item1(3) < item2(3))                                                        &
9108             .OR.  (item1(3) == item2(3)  .AND.  item1(2) < item2(2))                            &
9109             .OR.  (item1(3) == item2(3)  .AND.  item1(2) == item2(2)  .AND.  item1(1) < item2(1)) &
9110             .OR.  (item1(3) == item2(3)  .AND.  item1(2) == item2(2)  .AND.  item1(1) == item2(1) &
9111                 .AND.  item1(4) < item2(4)) )
9112    END FUNCTION csf_lt2
9113
9114    PURE FUNCTION searchsorted(athresh, val) result(ind)
9115        REAL(wp), DIMENSION(:), INTENT(IN)  :: athresh
9116        REAL(wp), INTENT(IN)                :: val
9117        INTEGER(iwp)                        :: ind
9118        INTEGER(iwp)                        :: i
9119
9120        DO i = LBOUND(athresh, 1), UBOUND(athresh, 1)
9121            IF ( val < athresh(i) ) THEN
9122                ind = i - 1
9123                RETURN
9124            ENDIF
9125        ENDDO
9126        ind = UBOUND(athresh, 1)
9127    END FUNCTION searchsorted
9128
9129
9130!------------------------------------------------------------------------------!
9131!
9132! Description:
9133! ------------
9134!> Subroutine for averaging 3D data
9135!------------------------------------------------------------------------------!
9136SUBROUTINE radiation_3d_data_averaging( mode, variable )
9137 
9138
9139    USE control_parameters
9140
9141    USE indices
9142
9143    USE kinds
9144
9145    IMPLICIT NONE
9146
9147    CHARACTER (LEN=*) ::  mode    !<
9148    CHARACTER (LEN=*) :: variable !<
9149
9150    LOGICAL      ::  match_lsm !< flag indicating natural-type surface
9151    LOGICAL      ::  match_usm !< flag indicating urban-type surface
9152   
9153    INTEGER(iwp) ::  i !<
9154    INTEGER(iwp) ::  j !<
9155    INTEGER(iwp) ::  k !<
9156    INTEGER(iwp) ::  l, m !< index of current surface element
9157
9158    INTEGER(iwp)                                       :: ids, idsint_u, idsint_l, isurf
9159    CHARACTER(LEN=varnamelength)                       :: var
9160
9161!-- find the real name of the variable
9162    ids = -1
9163    l = -1
9164    var = TRIM(variable)
9165    DO i = 0, nd-1
9166        k = len(TRIM(var))
9167        j = len(TRIM(dirname(i)))
9168        IF ( k-j+1 >= 1_iwp ) THEN
9169           IF ( TRIM(var(k-j+1:k)) == TRIM(dirname(i)) )  THEN
9170               ids = i
9171               idsint_u = dirint_u(ids)
9172               idsint_l = dirint_l(ids)
9173               var = var(:k-j)
9174               EXIT
9175           ENDIF
9176        ENDIF
9177    ENDDO
9178    IF ( ids == -1 )  THEN
9179        var = TRIM(variable)
9180    ENDIF
9181
9182    IF ( mode == 'allocate' )  THEN
9183
9184       SELECT CASE ( TRIM( var ) )
9185!--          block of large scale (e.g. RRTMG) radiation output variables
9186             CASE ( 'rad_net*' )
9187                IF ( .NOT. ALLOCATED( rad_net_av ) )  THEN
9188                   ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
9189                ENDIF
9190                rad_net_av = 0.0_wp
9191             
9192             CASE ( 'rad_lw_in*' )
9193                IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) )  THEN
9194                   ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
9195                ENDIF
9196                rad_lw_in_xy_av = 0.0_wp
9197               
9198             CASE ( 'rad_lw_out*' )
9199                IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) )  THEN
9200                   ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
9201                ENDIF
9202                rad_lw_out_xy_av = 0.0_wp
9203               
9204             CASE ( 'rad_sw_in*' )
9205                IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) )  THEN
9206                   ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
9207                ENDIF
9208                rad_sw_in_xy_av = 0.0_wp
9209               
9210             CASE ( 'rad_sw_out*' )
9211                IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) )  THEN
9212                   ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
9213                ENDIF
9214                rad_sw_out_xy_av = 0.0_wp               
9215
9216             CASE ( 'rad_lw_in' )
9217                IF ( .NOT. ALLOCATED( rad_lw_in_av ) )  THEN
9218                   ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9219                ENDIF
9220                rad_lw_in_av = 0.0_wp
9221
9222             CASE ( 'rad_lw_out' )
9223                IF ( .NOT. ALLOCATED( rad_lw_out_av ) )  THEN
9224                   ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9225                ENDIF
9226                rad_lw_out_av = 0.0_wp
9227
9228             CASE ( 'rad_lw_cs_hr' )
9229                IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) )  THEN
9230                   ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9231                ENDIF
9232                rad_lw_cs_hr_av = 0.0_wp
9233
9234             CASE ( 'rad_lw_hr' )
9235                IF ( .NOT. ALLOCATED( rad_lw_hr_av ) )  THEN
9236                   ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9237                ENDIF
9238                rad_lw_hr_av = 0.0_wp
9239
9240             CASE ( 'rad_sw_in' )
9241                IF ( .NOT. ALLOCATED( rad_sw_in_av ) )  THEN
9242                   ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9243                ENDIF
9244                rad_sw_in_av = 0.0_wp
9245
9246             CASE ( 'rad_sw_out' )
9247                IF ( .NOT. ALLOCATED( rad_sw_out_av ) )  THEN
9248                   ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9249                ENDIF
9250                rad_sw_out_av = 0.0_wp
9251
9252             CASE ( 'rad_sw_cs_hr' )
9253                IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) )  THEN
9254                   ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9255                ENDIF
9256                rad_sw_cs_hr_av = 0.0_wp
9257
9258             CASE ( 'rad_sw_hr' )
9259                IF ( .NOT. ALLOCATED( rad_sw_hr_av ) )  THEN
9260                   ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9261                ENDIF
9262                rad_sw_hr_av = 0.0_wp
9263
9264!--          block of RTM output variables
9265             CASE ( 'rtm_rad_net' )
9266!--              array of complete radiation balance
9267                 IF ( .NOT.  ALLOCATED(surfradnet_av) )  THEN
9268                     ALLOCATE( surfradnet_av(nsurfl) )
9269                     surfradnet_av = 0.0_wp
9270                 ENDIF
9271
9272             CASE ( 'rtm_rad_insw' )
9273!--                 array of sw radiation falling to surface after i-th reflection
9274                 IF ( .NOT.  ALLOCATED(surfinsw_av) )  THEN
9275                     ALLOCATE( surfinsw_av(nsurfl) )
9276                     surfinsw_av = 0.0_wp
9277                 ENDIF
9278
9279             CASE ( 'rtm_rad_inlw' )
9280!--                 array of lw radiation falling to surface after i-th reflection
9281                 IF ( .NOT.  ALLOCATED(surfinlw_av) )  THEN
9282                     ALLOCATE( surfinlw_av(nsurfl) )
9283                     surfinlw_av = 0.0_wp
9284                 ENDIF
9285
9286             CASE ( 'rtm_rad_inswdir' )
9287!--                 array of direct sw radiation falling to surface from sun
9288                 IF ( .NOT.  ALLOCATED(surfinswdir_av) )  THEN
9289                     ALLOCATE( surfinswdir_av(nsurfl) )
9290                     surfinswdir_av = 0.0_wp
9291                 ENDIF
9292
9293             CASE ( 'rtm_rad_inswdif' )
9294!--                 array of difusion sw radiation falling to surface from sky and borders of the domain
9295                 IF ( .NOT.  ALLOCATED(surfinswdif_av) )  THEN
9296                     ALLOCATE( surfinswdif_av(nsurfl) )
9297                     surfinswdif_av = 0.0_wp
9298                 ENDIF
9299
9300             CASE ( 'rtm_rad_inswref' )
9301!--                 array of sw radiation falling to surface from reflections
9302                 IF ( .NOT.  ALLOCATED(surfinswref_av) )  THEN
9303                     ALLOCATE( surfinswref_av(nsurfl) )
9304                     surfinswref_av = 0.0_wp
9305                 ENDIF
9306
9307             CASE ( 'rtm_rad_inlwdif' )
9308!--                 array of sw radiation falling to surface after i-th reflection
9309                IF ( .NOT.  ALLOCATED(surfinlwdif_av) )  THEN
9310                     ALLOCATE( surfinlwdif_av(nsurfl) )
9311                     surfinlwdif_av = 0.0_wp
9312                 ENDIF
9313
9314             CASE ( 'rtm_rad_inlwref' )
9315!--                 array of lw radiation falling to surface from reflections
9316                 IF ( .NOT.  ALLOCATED(surfinlwref_av) )  THEN
9317                     ALLOCATE( surfinlwref_av(nsurfl) )
9318                     surfinlwref_av = 0.0_wp
9319                 ENDIF
9320
9321             CASE ( 'rtm_rad_outsw' )
9322!--                 array of sw radiation emitted from surface after i-th reflection
9323                 IF ( .NOT.  ALLOCATED(surfoutsw_av) )  THEN
9324                     ALLOCATE( surfoutsw_av(nsurfl) )
9325                     surfoutsw_av = 0.0_wp
9326                 ENDIF
9327
9328             CASE ( 'rtm_rad_outlw' )
9329!--                 array of lw radiation emitted from surface after i-th reflection
9330                 IF ( .NOT.  ALLOCATED(surfoutlw_av) )  THEN
9331                     ALLOCATE( surfoutlw_av(nsurfl) )
9332                     surfoutlw_av = 0.0_wp
9333                 ENDIF
9334             CASE ( 'rtm_rad_ressw' )
9335!--                 array of residua of sw radiation absorbed in surface after last reflection
9336                 IF ( .NOT.  ALLOCATED(surfins_av) )  THEN
9337                     ALLOCATE( surfins_av(nsurfl) )
9338                     surfins_av = 0.0_wp
9339                 ENDIF
9340
9341             CASE ( 'rtm_rad_reslw' )
9342!--                 array of residua of lw radiation absorbed in surface after last reflection
9343                 IF ( .NOT.  ALLOCATED(surfinl_av) )  THEN
9344                     ALLOCATE( surfinl_av(nsurfl) )
9345                     surfinl_av = 0.0_wp
9346                 ENDIF
9347
9348             CASE ( 'rtm_rad_pc_inlw' )
9349!--                 array of of lw radiation absorbed in plant canopy
9350                 IF ( .NOT.  ALLOCATED(pcbinlw_av) )  THEN
9351                     ALLOCATE( pcbinlw_av(1:npcbl) )
9352                     pcbinlw_av = 0.0_wp
9353                 ENDIF
9354
9355             CASE ( 'rtm_rad_pc_insw' )
9356!--                 array of of sw radiation absorbed in plant canopy
9357                 IF ( .NOT.  ALLOCATED(pcbinsw_av) )  THEN
9358                     ALLOCATE( pcbinsw_av(1:npcbl) )
9359                     pcbinsw_av = 0.0_wp
9360                 ENDIF
9361
9362             CASE ( 'rtm_rad_pc_inswdir' )
9363!--                 array of of direct sw radiation absorbed in plant canopy
9364                 IF ( .NOT.  ALLOCATED(pcbinswdir_av) )  THEN
9365                     ALLOCATE( pcbinswdir_av(1:npcbl) )
9366                     pcbinswdir_av = 0.0_wp
9367                 ENDIF
9368
9369             CASE ( 'rtm_rad_pc_inswdif' )
9370!--                 array of of diffuse sw radiation absorbed in plant canopy
9371                 IF ( .NOT.  ALLOCATED(pcbinswdif_av) )  THEN
9372                     ALLOCATE( pcbinswdif_av(1:npcbl) )
9373                     pcbinswdif_av = 0.0_wp
9374                 ENDIF
9375
9376             CASE ( 'rtm_rad_pc_inswref' )
9377!--                 array of of reflected sw radiation absorbed in plant canopy
9378                 IF ( .NOT.  ALLOCATED(pcbinswref_av) )  THEN
9379                     ALLOCATE( pcbinswref_av(1:npcbl) )
9380                     pcbinswref_av = 0.0_wp
9381                 ENDIF
9382
9383             CASE ( 'rtm_mrt_sw' )
9384                IF ( .NOT. ALLOCATED( mrtinsw_av ) )  THEN
9385                   ALLOCATE( mrtinsw_av(nmrtbl) )
9386                ENDIF
9387                mrtinsw_av = 0.0_wp
9388
9389             CASE ( 'rtm_mrt_lw' )
9390                IF ( .NOT. ALLOCATED( mrtinlw_av ) )  THEN
9391                   ALLOCATE( mrtinlw_av(nmrtbl) )
9392                ENDIF
9393                mrtinlw_av = 0.0_wp
9394
9395             CASE ( 'rtm_mrt' )
9396                IF ( .NOT. ALLOCATED( mrt_av ) )  THEN
9397                   ALLOCATE( mrt_av(nmrtbl) )
9398                ENDIF
9399                mrt_av = 0.0_wp
9400
9401          CASE DEFAULT
9402             CONTINUE
9403
9404       END SELECT
9405
9406    ELSEIF ( mode == 'sum' )  THEN
9407
9408       SELECT CASE ( TRIM( var ) )
9409!--       block of large scale (e.g. RRTMG) radiation output variables
9410          CASE ( 'rad_net*' )
9411             IF ( ALLOCATED( rad_net_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_net_av(j,i) = rad_net_av(j,i) +                   &
9422                                         surf_lsm_h%rad_net(m)
9423                      ELSEIF ( match_usm )  THEN
9424                         m = surf_usm_h%end_index(j,i)
9425                         rad_net_av(j,i) = rad_net_av(j,i) +                   &
9426                                         surf_usm_h%rad_net(m)
9427                      ENDIF
9428                   ENDDO
9429                ENDDO
9430             ENDIF
9431
9432          CASE ( 'rad_lw_in*' )
9433             IF ( ALLOCATED( rad_lw_in_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_in_xy_av(j,i) = rad_lw_in_xy_av(j,i) +         &
9444                                         surf_lsm_h%rad_lw_in(m)
9445                      ELSEIF ( match_usm )  THEN
9446                         m = surf_usm_h%end_index(j,i)
9447                         rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i) +         &
9448                                         surf_usm_h%rad_lw_in(m)
9449                      ENDIF
9450                   ENDDO
9451                ENDDO
9452             ENDIF
9453             
9454          CASE ( 'rad_lw_out*' )
9455             IF ( ALLOCATED( rad_lw_out_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_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i) +       &
9466                                                 surf_lsm_h%rad_lw_out(m)
9467                      ELSEIF ( match_usm )  THEN
9468                         m = surf_usm_h%end_index(j,i)
9469                         rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i) +       &
9470                                                 surf_usm_h%rad_lw_out(m)
9471                      ENDIF
9472                   ENDDO
9473                ENDDO
9474             ENDIF
9475             
9476          CASE ( 'rad_sw_in*' )
9477             IF ( ALLOCATED( rad_sw_in_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_in_xy_av(j,i) = rad_sw_in_xy_av(j,i) +         &
9488                                                surf_lsm_h%rad_sw_in(m)
9489                      ELSEIF ( match_usm )  THEN
9490                         m = surf_usm_h%end_index(j,i)
9491                         rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i) +         &
9492                                                surf_usm_h%rad_sw_in(m)
9493                      ENDIF
9494                   ENDDO
9495                ENDDO
9496             ENDIF
9497             
9498          CASE ( 'rad_sw_out*' )
9499             IF ( ALLOCATED( rad_sw_out_xy_av ) ) THEN
9500                DO  i = nxl, nxr
9501                   DO  j = nys, nyn
9502                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9503                                  surf_lsm_h%end_index(j,i)
9504                      match_usm = surf_usm_h%start_index(j,i) <=               &
9505                                  surf_usm_h%end_index(j,i)
9506
9507                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9508                         m = surf_lsm_h%end_index(j,i)
9509                         rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i) +       &
9510                                                 surf_lsm_h%rad_sw_out(m)
9511                      ELSEIF ( match_usm )  THEN
9512                         m = surf_usm_h%end_index(j,i)
9513                         rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i) +       &
9514                                                 surf_usm_h%rad_sw_out(m)
9515                      ENDIF
9516                   ENDDO
9517                ENDDO
9518             ENDIF
9519             
9520          CASE ( 'rad_lw_in' )
9521             IF ( ALLOCATED( rad_lw_in_av ) ) THEN
9522                DO  i = nxlg, nxrg
9523                   DO  j = nysg, nyng
9524                      DO  k = nzb, nzt+1
9525                         rad_lw_in_av(k,j,i) = rad_lw_in_av(k,j,i)             &
9526                                               + rad_lw_in(k,j,i)
9527                      ENDDO
9528                   ENDDO
9529                ENDDO
9530             ENDIF
9531
9532          CASE ( 'rad_lw_out' )
9533             IF ( ALLOCATED( rad_lw_out_av ) ) THEN
9534                DO  i = nxlg, nxrg
9535                   DO  j = nysg, nyng
9536                      DO  k = nzb, nzt+1
9537                         rad_lw_out_av(k,j,i) = rad_lw_out_av(k,j,i)           &
9538                                                + rad_lw_out(k,j,i)
9539                      ENDDO
9540                   ENDDO
9541                ENDDO
9542             ENDIF
9543
9544          CASE ( 'rad_lw_cs_hr' )
9545             IF ( ALLOCATED( rad_lw_cs_hr_av ) ) THEN
9546                DO  i = nxlg, nxrg
9547                   DO  j = nysg, nyng
9548                      DO  k = nzb, nzt+1
9549                         rad_lw_cs_hr_av(k,j,i) = rad_lw_cs_hr_av(k,j,i)       &
9550                                                  + rad_lw_cs_hr(k,j,i)
9551                      ENDDO
9552                   ENDDO
9553                ENDDO
9554             ENDIF
9555
9556          CASE ( 'rad_lw_hr' )
9557             IF ( ALLOCATED( rad_lw_hr_av ) ) THEN
9558                DO  i = nxlg, nxrg
9559                   DO  j = nysg, nyng
9560                      DO  k = nzb, nzt+1
9561                         rad_lw_hr_av(k,j,i) = rad_lw_hr_av(k,j,i)             &
9562                                               + rad_lw_hr(k,j,i)
9563                      ENDDO
9564                   ENDDO
9565                ENDDO
9566             ENDIF
9567
9568          CASE ( 'rad_sw_in' )
9569             IF ( ALLOCATED( rad_sw_in_av ) ) THEN
9570                DO  i = nxlg, nxrg
9571                   DO  j = nysg, nyng
9572                      DO  k = nzb, nzt+1
9573                         rad_sw_in_av(k,j,i) = rad_sw_in_av(k,j,i)             &
9574                                               + rad_sw_in(k,j,i)
9575                      ENDDO
9576                   ENDDO
9577                ENDDO
9578             ENDIF
9579
9580          CASE ( 'rad_sw_out' )
9581             IF ( ALLOCATED( rad_sw_out_av ) ) THEN
9582                DO  i = nxlg, nxrg
9583                   DO  j = nysg, nyng
9584                      DO  k = nzb, nzt+1
9585                         rad_sw_out_av(k,j,i) = rad_sw_out_av(k,j,i)           &
9586                                                + rad_sw_out(k,j,i)
9587                      ENDDO
9588                   ENDDO
9589                ENDDO
9590             ENDIF
9591
9592          CASE ( 'rad_sw_cs_hr' )
9593             IF ( ALLOCATED( rad_sw_cs_hr_av ) ) THEN
9594                DO  i = nxlg, nxrg
9595                   DO  j = nysg, nyng
9596                      DO  k = nzb, nzt+1
9597                         rad_sw_cs_hr_av(k,j,i) = rad_sw_cs_hr_av(k,j,i)       &
9598                                                  + rad_sw_cs_hr(k,j,i)
9599                      ENDDO
9600                   ENDDO
9601                ENDDO
9602             ENDIF
9603
9604          CASE ( 'rad_sw_hr' )
9605             IF ( ALLOCATED( rad_sw_hr_av ) ) THEN
9606                DO  i = nxlg, nxrg
9607                   DO  j = nysg, nyng
9608                      DO  k = nzb, nzt+1
9609                         rad_sw_hr_av(k,j,i) = rad_sw_hr_av(k,j,i)             &
9610                                               + rad_sw_hr(k,j,i)
9611                      ENDDO
9612                   ENDDO
9613                ENDDO
9614             ENDIF
9615
9616!--       block of RTM output variables
9617          CASE ( 'rtm_rad_net' )
9618!--           array of complete radiation balance
9619              DO isurf = dirstart(ids), dirend(ids)
9620                 IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9621                    surfradnet_av(isurf) = surfinsw(isurf) - surfoutsw(isurf) +  surfinlw(isurf) - surfoutlw(isurf)
9622                 ENDIF
9623              ENDDO
9624
9625          CASE ( 'rtm_rad_insw' )
9626!--           array of sw radiation falling to surface after i-th reflection
9627              DO isurf = dirstart(ids), dirend(ids)
9628                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9629                      surfinsw_av(isurf) = surfinsw_av(isurf) + surfinsw(isurf)
9630                  ENDIF
9631              ENDDO
9632
9633          CASE ( 'rtm_rad_inlw' )
9634!--           array of lw radiation falling to surface after i-th reflection
9635              DO isurf = dirstart(ids), dirend(ids)
9636                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9637                      surfinlw_av(isurf) = surfinlw_av(isurf) + surfinlw(isurf)
9638                  ENDIF
9639              ENDDO
9640
9641          CASE ( 'rtm_rad_inswdir' )
9642!--           array of direct sw radiation falling to surface from sun
9643              DO isurf = dirstart(ids), dirend(ids)
9644                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9645                      surfinswdir_av(isurf) = surfinswdir_av(isurf) + surfinswdir(isurf)
9646                  ENDIF
9647              ENDDO
9648
9649          CASE ( 'rtm_rad_inswdif' )
9650!--           array of difusion sw radiation falling to surface from sky and borders of the domain
9651              DO isurf = dirstart(ids), dirend(ids)
9652                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9653                      surfinswdif_av(isurf) = surfinswdif_av(isurf) + surfinswdif(isurf)
9654                  ENDIF
9655              ENDDO
9656
9657          CASE ( 'rtm_rad_inswref' )
9658!--           array of sw radiation falling to surface from reflections
9659              DO isurf = dirstart(ids), dirend(ids)
9660                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9661                      surfinswref_av(isurf) = surfinswref_av(isurf) + surfinsw(isurf) - &
9662                                          surfinswdir(isurf) - surfinswdif(isurf)
9663                  ENDIF
9664              ENDDO
9665
9666
9667          CASE ( 'rtm_rad_inlwdif' )
9668!--           array of sw radiation falling to surface after i-th reflection
9669              DO isurf = dirstart(ids), dirend(ids)
9670                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9671                      surfinlwdif_av(isurf) = surfinlwdif_av(isurf) + surfinlwdif(isurf)
9672                  ENDIF
9673              ENDDO
9674!
9675          CASE ( 'rtm_rad_inlwref' )
9676!--           array of lw radiation falling to surface from reflections
9677              DO isurf = dirstart(ids), dirend(ids)
9678                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9679                      surfinlwref_av(isurf) = surfinlwref_av(isurf) + &
9680                                          surfinlw(isurf) - surfinlwdif(isurf)
9681                  ENDIF
9682              ENDDO
9683
9684          CASE ( 'rtm_rad_outsw' )
9685!--           array of sw radiation emitted from surface after i-th reflection
9686              DO isurf = dirstart(ids), dirend(ids)
9687                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9688                      surfoutsw_av(isurf) = surfoutsw_av(isurf) + surfoutsw(isurf)
9689                  ENDIF
9690              ENDDO
9691
9692          CASE ( 'rtm_rad_outlw' )
9693!--           array of lw radiation emitted from surface after i-th reflection
9694              DO isurf = dirstart(ids), dirend(ids)
9695                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9696                      surfoutlw_av(isurf) = surfoutlw_av(isurf) + surfoutlw(isurf)
9697                  ENDIF
9698              ENDDO
9699
9700          CASE ( 'rtm_rad_ressw' )
9701!--           array of residua of sw radiation absorbed in surface after last reflection
9702              DO isurf = dirstart(ids), dirend(ids)
9703                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9704                      surfins_av(isurf) = surfins_av(isurf) + surfins(isurf)
9705                  ENDIF
9706              ENDDO
9707
9708          CASE ( 'rtm_rad_reslw' )
9709!--           array of residua of lw radiation absorbed in surface after last reflection
9710              DO isurf = dirstart(ids), dirend(ids)
9711                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9712                      surfinl_av(isurf) = surfinl_av(isurf) + surfinl(isurf)
9713                  ENDIF
9714              ENDDO
9715
9716          CASE ( 'rtm_rad_pc_inlw' )
9717              DO l = 1, npcbl
9718                 pcbinlw_av(l) = pcbinlw_av(l) + pcbinlw(l)
9719              ENDDO
9720
9721          CASE ( 'rtm_rad_pc_insw' )
9722              DO l = 1, npcbl
9723                 pcbinsw_av(l) = pcbinsw_av(l) + pcbinsw(l)
9724              ENDDO
9725
9726          CASE ( 'rtm_rad_pc_inswdir' )
9727              DO l = 1, npcbl
9728                 pcbinswdir_av(l) = pcbinswdir_av(l) + pcbinswdir(l)
9729              ENDDO
9730
9731          CASE ( 'rtm_rad_pc_inswdif' )
9732              DO l = 1, npcbl
9733                 pcbinswdif_av(l) = pcbinswdif_av(l) + pcbinswdif(l)
9734              ENDDO
9735
9736          CASE ( 'rtm_rad_pc_inswref' )
9737              DO l = 1, npcbl
9738                 pcbinswref_av(l) = pcbinswref_av(l) + pcbinsw(l) - pcbinswdir(l) - pcbinswdif(l)
9739              ENDDO
9740
9741          CASE ( 'rad_mrt_sw' )
9742             IF ( ALLOCATED( mrtinsw_av ) )  THEN
9743                mrtinsw_av(:) = mrtinsw_av(:) + mrtinsw(:)
9744             ENDIF
9745
9746          CASE ( 'rad_mrt_lw' )
9747             IF ( ALLOCATED( mrtinlw_av ) )  THEN
9748                mrtinlw_av(:) = mrtinlw_av(:) + mrtinlw(:)
9749             ENDIF
9750
9751          CASE ( 'rad_mrt' )
9752             IF ( ALLOCATED( mrt_av ) )  THEN
9753                mrt_av(:) = mrt_av(:) + mrt(:)
9754             ENDIF
9755
9756          CASE DEFAULT
9757             CONTINUE
9758
9759       END SELECT
9760
9761    ELSEIF ( mode == 'average' )  THEN
9762
9763       SELECT CASE ( TRIM( var ) )
9764!--       block of large scale (e.g. RRTMG) radiation output variables
9765          CASE ( 'rad_net*' )
9766             IF ( ALLOCATED( rad_net_av ) ) THEN
9767                DO  i = nxlg, nxrg
9768                   DO  j = nysg, nyng
9769                      rad_net_av(j,i) = rad_net_av(j,i)                        &
9770                                        / REAL( average_count_3d, KIND=wp )
9771                   ENDDO
9772                ENDDO
9773             ENDIF
9774             
9775          CASE ( 'rad_lw_in*' )
9776             IF ( ALLOCATED( rad_lw_in_xy_av ) ) THEN
9777                DO  i = nxlg, nxrg
9778                   DO  j = nysg, nyng
9779                      rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i)              &
9780                                        / REAL( average_count_3d, KIND=wp )
9781                   ENDDO
9782                ENDDO
9783             ENDIF
9784             
9785          CASE ( 'rad_lw_out*' )
9786             IF ( ALLOCATED( rad_lw_out_xy_av ) ) THEN
9787                DO  i = nxlg, nxrg
9788                   DO  j = nysg, nyng
9789                      rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i)            &
9790                                        / REAL( average_count_3d, KIND=wp )
9791                   ENDDO
9792                ENDDO
9793             ENDIF
9794             
9795          CASE ( 'rad_sw_in*' )
9796             IF ( ALLOCATED( rad_sw_in_xy_av ) ) THEN
9797                DO  i = nxlg, nxrg
9798                   DO  j = nysg, nyng
9799                      rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i)              &
9800                                        / REAL( average_count_3d, KIND=wp )
9801                   ENDDO
9802                ENDDO
9803             ENDIF
9804             
9805          CASE ( 'rad_sw_out*' )
9806             IF ( ALLOCATED( rad_sw_out_xy_av ) ) THEN
9807                DO  i = nxlg, nxrg
9808                   DO  j = nysg, nyng
9809                      rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i)             &
9810                                        / REAL( average_count_3d, KIND=wp )
9811                   ENDDO
9812                ENDDO
9813             ENDIF
9814
9815          CASE ( 'rad_lw_in' )
9816             IF ( ALLOCATED( rad_lw_in_av ) ) THEN
9817                DO  i = nxlg, nxrg
9818                   DO  j = nysg, nyng
9819                      DO  k = nzb, nzt+1
9820                         rad_lw_in_av(k,j,i) = rad_lw_in_av(k,j,i)             &
9821                                               / REAL( average_count_3d, KIND=wp )
9822                      ENDDO
9823                   ENDDO
9824                ENDDO
9825             ENDIF
9826
9827          CASE ( 'rad_lw_out' )
9828             IF ( ALLOCATED( rad_lw_out_av ) ) THEN
9829                DO  i = nxlg, nxrg
9830                   DO  j = nysg, nyng
9831                      DO  k = nzb, nzt+1
9832                         rad_lw_out_av(k,j,i) = rad_lw_out_av(k,j,i)           &
9833                                                / REAL( average_count_3d, KIND=wp )
9834                      ENDDO
9835                   ENDDO
9836                ENDDO
9837             ENDIF
9838
9839          CASE ( 'rad_lw_cs_hr' )
9840             IF ( ALLOCATED( rad_lw_cs_hr_av ) ) THEN
9841                DO  i = nxlg, nxrg
9842                   DO  j = nysg, nyng
9843                      DO  k = nzb, nzt+1
9844                         rad_lw_cs_hr_av(k,j,i) = rad_lw_cs_hr_av(k,j,i)       &
9845                                                / REAL( average_count_3d, KIND=wp )
9846                      ENDDO
9847                   ENDDO
9848                ENDDO
9849             ENDIF
9850
9851          CASE ( 'rad_lw_hr' )
9852             IF ( ALLOCATED( rad_lw_hr_av ) ) THEN
9853                DO  i = nxlg, nxrg
9854                   DO  j = nysg, nyng
9855                      DO  k = nzb, nzt+1
9856                         rad_lw_hr_av(k,j,i) = rad_lw_hr_av(k,j,i)             &
9857                                               / REAL( average_count_3d, KIND=wp )
9858                      ENDDO
9859                   ENDDO
9860                ENDDO
9861             ENDIF
9862
9863          CASE ( 'rad_sw_in' )
9864             IF ( ALLOCATED( rad_sw_in_av ) ) THEN
9865                DO  i = nxlg, nxrg
9866                   DO  j = nysg, nyng
9867                      DO  k = nzb, nzt+1
9868                         rad_sw_in_av(k,j,i) = rad_sw_in_av(k,j,i)             &
9869                                               / REAL( average_count_3d, KIND=wp )
9870                      ENDDO
9871                   ENDDO
9872                ENDDO
9873             ENDIF
9874
9875          CASE ( 'rad_sw_out' )
9876             IF ( ALLOCATED( rad_sw_out_av ) ) THEN
9877                DO  i = nxlg, nxrg
9878                   DO  j = nysg, nyng
9879                      DO  k = nzb, nzt+1
9880                         rad_sw_out_av(k,j,i) = rad_sw_out_av(k,j,i)           &
9881                                                / REAL( average_count_3d, KIND=wp )
9882                      ENDDO
9883                   ENDDO
9884                ENDDO
9885             ENDIF
9886
9887          CASE ( 'rad_sw_cs_hr' )
9888             IF ( ALLOCATED( rad_sw_cs_hr_av ) ) THEN
9889                DO  i = nxlg, nxrg
9890                   DO  j = nysg, nyng
9891                      DO  k = nzb, nzt+1
9892                         rad_sw_cs_hr_av(k,j,i) = rad_sw_cs_hr_av(k,j,i)       &
9893                                                / REAL( average_count_3d, KIND=wp )
9894                      ENDDO
9895                   ENDDO
9896                ENDDO
9897             ENDIF
9898
9899          CASE ( 'rad_sw_hr' )
9900             IF ( ALLOCATED( rad_sw_hr_av ) ) THEN
9901                DO  i = nxlg, nxrg
9902                   DO  j = nysg, nyng
9903                      DO  k = nzb, nzt+1
9904                         rad_sw_hr_av(k,j,i) = rad_sw_hr_av(k,j,i)             &
9905                                               / REAL( average_count_3d, KIND=wp )
9906                      ENDDO
9907                   ENDDO
9908                ENDDO
9909             ENDIF
9910
9911!--       block of RTM output variables
9912          CASE ( 'rtm_rad_net' )
9913!--           array of complete radiation balance
9914              DO isurf = dirstart(ids), dirend(ids)
9915                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9916                      surfradnet_av(isurf) = surfinsw_av(isurf) / REAL( average_count_3d, kind=wp )
9917                  ENDIF
9918              ENDDO
9919
9920          CASE ( 'rtm_rad_insw' )
9921!--           array of sw radiation falling to surface after i-th reflection
9922              DO isurf = dirstart(ids), dirend(ids)
9923                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9924                      surfinsw_av(isurf) = surfinsw_av(isurf) / REAL( average_count_3d, kind=wp )
9925                  ENDIF
9926              ENDDO
9927
9928          CASE ( 'rtm_rad_inlw' )
9929!--           array of lw radiation falling to surface after i-th reflection
9930              DO isurf = dirstart(ids), dirend(ids)
9931                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9932                      surfinlw_av(isurf) = surfinlw_av(isurf) / REAL( average_count_3d, kind=wp )
9933                  ENDIF
9934              ENDDO
9935
9936          CASE ( 'rtm_rad_inswdir' )
9937!--           array of direct sw radiation falling to surface from sun
9938              DO isurf = dirstart(ids), dirend(ids)
9939                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9940                      surfinswdir_av(isurf) = surfinswdir_av(isurf) / REAL( average_count_3d, kind=wp )
9941                  ENDIF
9942              ENDDO
9943
9944          CASE ( 'rtm_rad_inswdif' )
9945!--           array of difusion sw radiation falling to surface from sky and borders of the domain
9946              DO isurf = dirstart(ids), dirend(ids)
9947                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9948                      surfinswdif_av(isurf) = surfinswdif_av(isurf) / REAL( average_count_3d, kind=wp )
9949                  ENDIF
9950              ENDDO
9951
9952          CASE ( 'rtm_rad_inswref' )
9953!--           array of sw radiation falling to surface from reflections
9954              DO isurf = dirstart(ids), dirend(ids)
9955                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9956                      surfinswref_av(isurf) = surfinswref_av(isurf) / REAL( average_count_3d, kind=wp )
9957                  ENDIF
9958              ENDDO
9959
9960          CASE ( 'rtm_rad_inlwdif' )
9961!--           array of sw radiation falling to surface after i-th reflection
9962              DO isurf = dirstart(ids), dirend(ids)
9963                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9964                      surfinlwdif_av(isurf) = surfinlwdif_av(isurf) / REAL( average_count_3d, kind=wp )
9965                  ENDIF
9966              ENDDO
9967
9968          CASE ( 'rtm_rad_inlwref' )
9969!--           array of lw radiation falling to surface from reflections
9970              DO isurf = dirstart(ids), dirend(ids)
9971                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9972                      surfinlwref_av(isurf) = surfinlwref_av(isurf) / REAL( average_count_3d, kind=wp )
9973                  ENDIF
9974              ENDDO
9975
9976          CASE ( 'rtm_rad_outsw' )
9977!--           array of sw radiation emitted from surface after i-th reflection
9978              DO isurf = dirstart(ids), dirend(ids)
9979                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9980                      surfoutsw_av(isurf) = surfoutsw_av(isurf) / REAL( average_count_3d, kind=wp )
9981                  ENDIF
9982              ENDDO
9983
9984          CASE ( 'rtm_rad_outlw' )
9985!--           array of lw radiation emitted from surface after i-th reflection
9986              DO isurf = dirstart(ids), dirend(ids)
9987                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9988                      surfoutlw_av(isurf) = surfoutlw_av(isurf) / REAL( average_count_3d, kind=wp )
9989                  ENDIF
9990              ENDDO
9991
9992          CASE ( 'rtm_rad_ressw' )
9993!--           array of residua of sw radiation absorbed in surface after last reflection
9994              DO isurf = dirstart(ids), dirend(ids)
9995                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9996                      surfins_av(isurf) = surfins_av(isurf) / REAL( average_count_3d, kind=wp )
9997                  ENDIF
9998              ENDDO
9999
10000          CASE ( 'rtm_rad_reslw' )
10001!--           array of residua of lw radiation absorbed in surface after last reflection
10002              DO isurf = dirstart(ids), dirend(ids)
10003                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10004                      surfinl_av(isurf) = surfinl_av(isurf) / REAL( average_count_3d, kind=wp )
10005                  ENDIF
10006              ENDDO
10007
10008          CASE ( 'rtm_rad_pc_inlw' )
10009              DO l = 1, npcbl
10010                 pcbinlw_av(:) = pcbinlw_av(:) / REAL( average_count_3d, kind=wp )
10011              ENDDO
10012
10013          CASE ( 'rtm_rad_pc_insw' )
10014              DO l = 1, npcbl
10015                 pcbinsw_av(:) = pcbinsw_av(:) / REAL( average_count_3d, kind=wp )
10016              ENDDO
10017
10018          CASE ( 'rtm_rad_pc_inswdir' )
10019              DO l = 1, npcbl
10020                 pcbinswdir_av(:) = pcbinswdir_av(:) / REAL( average_count_3d, kind=wp )
10021              ENDDO
10022
10023          CASE ( 'rtm_rad_pc_inswdif' )
10024              DO l = 1, npcbl
10025                 pcbinswdif_av(:) = pcbinswdif_av(:) / REAL( average_count_3d, kind=wp )
10026              ENDDO
10027
10028          CASE ( 'rtm_rad_pc_inswref' )
10029              DO l = 1, npcbl
10030                 pcbinswref_av(:) = pcbinswref_av(:) / REAL( average_count_3d, kind=wp )
10031              ENDDO
10032
10033          CASE ( 'rad_mrt_lw' )
10034             IF ( ALLOCATED( mrtinlw_av ) )  THEN
10035                mrtinlw_av(:) = mrtinlw_av(:) / REAL( average_count_3d, KIND=wp )
10036             ENDIF
10037
10038          CASE ( 'rad_mrt' )
10039             IF ( ALLOCATED( mrt_av ) )  THEN
10040                mrt_av(:) = mrt_av(:) / REAL( average_count_3d, KIND=wp )
10041             ENDIF
10042
10043       END SELECT
10044
10045    ENDIF
10046
10047END SUBROUTINE radiation_3d_data_averaging
10048
10049
10050!------------------------------------------------------------------------------!
10051!
10052! Description:
10053! ------------
10054!> Subroutine defining appropriate grid for netcdf variables.
10055!> It is called out from subroutine netcdf.
10056!------------------------------------------------------------------------------!
10057SUBROUTINE radiation_define_netcdf_grid( variable, found, grid_x, grid_y, grid_z )
10058   
10059    IMPLICIT NONE
10060
10061    CHARACTER (LEN=*), INTENT(IN)  ::  variable    !<
10062    LOGICAL, INTENT(OUT)           ::  found       !<
10063    CHARACTER (LEN=*), INTENT(OUT) ::  grid_x      !<
10064    CHARACTER (LEN=*), INTENT(OUT) ::  grid_y      !<
10065    CHARACTER (LEN=*), INTENT(OUT) ::  grid_z      !<
10066
10067    CHARACTER (len=varnamelength)  :: var
10068
10069    found  = .TRUE.
10070
10071!
10072!-- Check for the grid
10073    var = TRIM(variable)
10074!-- RTM directional variables
10075    IF ( var(1:12) == 'rtm_rad_net_'  .OR.  var(1:13) == 'rtm_rad_insw_'  .OR.          &
10076         var(1:13) == 'rtm_rad_inlw_'  .OR.  var(1:16) == 'rtm_rad_inswdir_'  .OR.      &
10077         var(1:16) == 'rtm_rad_inswdif_'  .OR.  var(1:16) == 'rtm_rad_inswref_'  .OR.   &
10078         var(1:16) == 'rtm_rad_inlwdif_'  .OR.  var(1:16) == 'rtm_rad_inlwref_'  .OR.   &
10079         var(1:14) == 'rtm_rad_outsw_'  .OR.  var(1:14) == 'rtm_rad_outlw_'  .OR.       &
10080         var(1:14) == 'rtm_rad_ressw_'  .OR.  var(1:14) == 'rtm_rad_reslw_'  .OR.       &
10081         var == 'rtm_rad_pc_inlw'  .OR.                                                 &
10082         var == 'rtm_rad_pc_insw'  .OR.  var == 'rtm_rad_pc_inswdir'  .OR.              &
10083         var == 'rtm_rad_pc_inswdif'  .OR.  var == 'rtm_rad_pc_inswref'  .OR.           &
10084         var(1:7) == 'rtm_svf'  .OR.  var(1:7) == 'rtm_dif'  .OR.                       &
10085         var(1:9) == 'rtm_skyvf' .OR. var(1:10) == 'rtm_skyvft'  .OR.                   &
10086         var(1:12) == 'rtm_surfalb_'  .OR.  var(1:13) == 'rtm_surfemis_'  .OR.          &
10087         var == 'rtm_mrt'  .OR.  var ==  'rtm_mrt_sw'  .OR.  var == 'rtm_mrt_lw' )  THEN
10088
10089         found = .TRUE.
10090         grid_x = 'x'
10091         grid_y = 'y'
10092         grid_z = 'zu'
10093    ELSE
10094
10095       SELECT CASE ( TRIM( var ) )
10096
10097          CASE ( 'rad_lw_cs_hr', 'rad_lw_hr', 'rad_sw_cs_hr', 'rad_sw_hr',        &
10098                 'rad_lw_cs_hr_xy', 'rad_lw_hr_xy', 'rad_sw_cs_hr_xy',            &
10099                 'rad_sw_hr_xy', 'rad_lw_cs_hr_xz', 'rad_lw_hr_xz',               &
10100                 'rad_sw_cs_hr_xz', 'rad_sw_hr_xz', 'rad_lw_cs_hr_yz',            &
10101                 'rad_lw_hr_yz', 'rad_sw_cs_hr_yz', 'rad_sw_hr_yz',               &
10102                 'rad_mrt', 'rad_mrt_sw', 'rad_mrt_lw' )
10103             grid_x = 'x'
10104             grid_y = 'y'
10105             grid_z = 'zu'
10106
10107          CASE ( 'rad_lw_in', 'rad_lw_out', 'rad_sw_in', 'rad_sw_out',            &
10108                 'rad_lw_in_xy', 'rad_lw_out_xy', 'rad_sw_in_xy','rad_sw_out_xy', &
10109                 'rad_lw_in_xz', 'rad_lw_out_xz', 'rad_sw_in_xz','rad_sw_out_xz', &
10110                 'rad_lw_in_yz', 'rad_lw_out_yz', 'rad_sw_in_yz','rad_sw_out_yz' )
10111             grid_x = 'x'
10112             grid_y = 'y'
10113             grid_z = 'zw'
10114
10115
10116          CASE DEFAULT
10117             found  = .FALSE.
10118             grid_x = 'none'
10119             grid_y = 'none'
10120             grid_z = 'none'
10121
10122           END SELECT
10123       ENDIF
10124
10125    END SUBROUTINE radiation_define_netcdf_grid
10126
10127!------------------------------------------------------------------------------!
10128!
10129! Description:
10130! ------------
10131!> Subroutine defining 2D output variables
10132!------------------------------------------------------------------------------!
10133 SUBROUTINE radiation_data_output_2d( av, variable, found, grid, mode,         &
10134                                      local_pf, two_d, nzb_do, nzt_do )
10135 
10136    USE indices
10137
10138    USE kinds
10139
10140
10141    IMPLICIT NONE
10142
10143    CHARACTER (LEN=*) ::  grid     !<
10144    CHARACTER (LEN=*) ::  mode     !<
10145    CHARACTER (LEN=*) ::  variable !<
10146
10147    INTEGER(iwp) ::  av !<
10148    INTEGER(iwp) ::  i  !<
10149    INTEGER(iwp) ::  j  !<
10150    INTEGER(iwp) ::  k  !<
10151    INTEGER(iwp) ::  m  !< index of surface element at grid point (j,i)
10152    INTEGER(iwp) ::  nzb_do   !<
10153    INTEGER(iwp) ::  nzt_do   !<
10154
10155    LOGICAL      ::  found !<
10156    LOGICAL      ::  two_d !< flag parameter that indicates 2D variables (horizontal cross sections)
10157
10158    REAL(wp) ::  fill_value = -999.0_wp    !< value for the _FillValue attribute
10159
10160    REAL(wp), DIMENSION(nxl:nxr,nys:nyn,nzb_do:nzt_do) ::  local_pf !<
10161
10162    found = .TRUE.
10163
10164    SELECT CASE ( TRIM( variable ) )
10165
10166       CASE ( 'rad_net*_xy' )        ! 2d-array
10167          IF ( av == 0 ) THEN
10168             DO  i = nxl, nxr
10169                DO  j = nys, nyn
10170!
10171!--                Obtain rad_net from its respective surface type
10172!--                Natural-type surfaces
10173                   DO  m = surf_lsm_h%start_index(j,i),                        &
10174                           surf_lsm_h%end_index(j,i) 
10175                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_net(m)
10176                   ENDDO
10177!
10178!--                Urban-type surfaces
10179                   DO  m = surf_usm_h%start_index(j,i),                        &
10180                           surf_usm_h%end_index(j,i) 
10181                      local_pf(i,j,nzb+1) = surf_usm_h%rad_net(m)
10182                   ENDDO
10183                ENDDO
10184             ENDDO
10185          ELSE
10186             IF ( .NOT. ALLOCATED( rad_net_av ) ) THEN
10187                ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
10188                rad_net_av = REAL( fill_value, KIND = wp )
10189             ENDIF
10190             DO  i = nxl, nxr
10191                DO  j = nys, nyn 
10192                   local_pf(i,j,nzb+1) = rad_net_av(j,i)
10193                ENDDO
10194             ENDDO
10195          ENDIF
10196          two_d = .TRUE.
10197          grid = 'zu1'
10198         
10199       CASE ( 'rad_lw_in*_xy' )        ! 2d-array
10200          IF ( av == 0 ) THEN
10201             DO  i = nxl, nxr
10202                DO  j = nys, nyn
10203!
10204!--                Obtain rad_net from its respective surface type
10205!--                Natural-type surfaces
10206                   DO  m = surf_lsm_h%start_index(j,i),                        &
10207                           surf_lsm_h%end_index(j,i) 
10208                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_lw_in(m)
10209                   ENDDO
10210!
10211!--                Urban-type surfaces
10212                   DO  m = surf_usm_h%start_index(j,i),                        &
10213                           surf_usm_h%end_index(j,i) 
10214                      local_pf(i,j,nzb+1) = surf_usm_h%rad_lw_in(m)
10215                   ENDDO
10216                ENDDO
10217             ENDDO
10218          ELSE
10219             IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) ) THEN
10220                ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
10221                rad_lw_in_xy_av = REAL( fill_value, KIND = wp )
10222             ENDIF
10223             DO  i = nxl, nxr
10224                DO  j = nys, nyn 
10225                   local_pf(i,j,nzb+1) = rad_lw_in_xy_av(j,i)
10226                ENDDO
10227             ENDDO
10228          ENDIF
10229          two_d = .TRUE.
10230          grid = 'zu1'
10231         
10232       CASE ( 'rad_lw_out*_xy' )        ! 2d-array
10233          IF ( av == 0 ) THEN
10234             DO  i = nxl, nxr
10235                DO  j = nys, nyn
10236!
10237!--                Obtain rad_net from its respective surface type
10238!--                Natural-type surfaces
10239                   DO  m = surf_lsm_h%start_index(j,i),                        &
10240                           surf_lsm_h%end_index(j,i) 
10241                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_lw_out(m)
10242                   ENDDO
10243!
10244!--                Urban-type surfaces
10245                   DO  m = surf_usm_h%start_index(j,i),                        &
10246                           surf_usm_h%end_index(j,i) 
10247                      local_pf(i,j,nzb+1) = surf_usm_h%rad_lw_out(m)
10248                   ENDDO
10249                ENDDO
10250             ENDDO
10251          ELSE
10252             IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) ) THEN
10253                ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
10254                rad_lw_out_xy_av = REAL( fill_value, KIND = wp )
10255             ENDIF
10256             DO  i = nxl, nxr
10257                DO  j = nys, nyn 
10258                   local_pf(i,j,nzb+1) = rad_lw_out_xy_av(j,i)
10259                ENDDO
10260             ENDDO
10261          ENDIF
10262          two_d = .TRUE.
10263          grid = 'zu1'
10264         
10265       CASE ( 'rad_sw_in*_xy' )        ! 2d-array
10266          IF ( av == 0 ) THEN
10267             DO  i = nxl, nxr
10268                DO  j = nys, nyn
10269!
10270!--                Obtain rad_net from its respective surface type
10271!--                Natural-type surfaces
10272                   DO  m = surf_lsm_h%start_index(j,i),                        &
10273                           surf_lsm_h%end_index(j,i) 
10274                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_sw_in(m)
10275                   ENDDO
10276!
10277!--                Urban-type surfaces
10278                   DO  m = surf_usm_h%start_index(j,i),                        &
10279                           surf_usm_h%end_index(j,i) 
10280                      local_pf(i,j,nzb+1) = surf_usm_h%rad_sw_in(m)
10281                   ENDDO
10282                ENDDO
10283             ENDDO
10284          ELSE
10285             IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) ) THEN
10286                ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
10287                rad_sw_in_xy_av = REAL( fill_value, KIND = wp )
10288             ENDIF
10289             DO  i = nxl, nxr
10290                DO  j = nys, nyn 
10291                   local_pf(i,j,nzb+1) = rad_sw_in_xy_av(j,i)
10292                ENDDO
10293             ENDDO
10294          ENDIF
10295          two_d = .TRUE.
10296          grid = 'zu1'
10297         
10298       CASE ( 'rad_sw_out*_xy' )        ! 2d-array
10299          IF ( av == 0 ) THEN
10300             DO  i = nxl, nxr
10301                DO  j = nys, nyn
10302!
10303!--                Obtain rad_net from its respective surface type
10304!--                Natural-type surfaces
10305                   DO  m = surf_lsm_h%start_index(j,i),                        &
10306                           surf_lsm_h%end_index(j,i) 
10307                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_sw_out(m)
10308                   ENDDO
10309!
10310!--                Urban-type surfaces
10311                   DO  m = surf_usm_h%start_index(j,i),                        &
10312                           surf_usm_h%end_index(j,i) 
10313                      local_pf(i,j,nzb+1) = surf_usm_h%rad_sw_out(m)
10314                   ENDDO
10315                ENDDO
10316             ENDDO
10317          ELSE
10318             IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) ) THEN
10319                ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
10320                rad_sw_out_xy_av = REAL( fill_value, KIND = wp )
10321             ENDIF
10322             DO  i = nxl, nxr
10323                DO  j = nys, nyn 
10324                   local_pf(i,j,nzb+1) = rad_sw_out_xy_av(j,i)
10325                ENDDO
10326             ENDDO
10327          ENDIF
10328          two_d = .TRUE.
10329          grid = 'zu1'         
10330         
10331       CASE ( 'rad_lw_in_xy', 'rad_lw_in_xz', 'rad_lw_in_yz' )
10332          IF ( av == 0 ) THEN
10333             DO  i = nxl, nxr
10334                DO  j = nys, nyn
10335                   DO  k = nzb_do, nzt_do
10336                      local_pf(i,j,k) = rad_lw_in(k,j,i)
10337                   ENDDO
10338                ENDDO
10339             ENDDO
10340          ELSE
10341            IF ( .NOT. ALLOCATED( rad_lw_in_av ) ) THEN
10342               ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10343               rad_lw_in_av = REAL( fill_value, KIND = wp )
10344            ENDIF
10345             DO  i = nxl, nxr
10346                DO  j = nys, nyn 
10347                   DO  k = nzb_do, nzt_do
10348                      local_pf(i,j,k) = rad_lw_in_av(k,j,i)
10349                   ENDDO
10350                ENDDO
10351             ENDDO
10352          ENDIF
10353          IF ( mode == 'xy' )  grid = 'zu'
10354
10355       CASE ( 'rad_lw_out_xy', 'rad_lw_out_xz', 'rad_lw_out_yz' )
10356          IF ( av == 0 ) THEN
10357             DO  i = nxl, nxr
10358                DO  j = nys, nyn
10359                   DO  k = nzb_do, nzt_do
10360                      local_pf(i,j,k) = rad_lw_out(k,j,i)
10361                   ENDDO
10362                ENDDO
10363             ENDDO
10364          ELSE
10365            IF ( .NOT. ALLOCATED( rad_lw_out_av ) ) THEN
10366               ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10367               rad_lw_out_av = REAL( fill_value, KIND = wp )
10368            ENDIF
10369             DO  i = nxl, nxr
10370                DO  j = nys, nyn 
10371                   DO  k = nzb_do, nzt_do
10372                      local_pf(i,j,k) = rad_lw_out_av(k,j,i)
10373                   ENDDO
10374                ENDDO
10375             ENDDO
10376          ENDIF   
10377          IF ( mode == 'xy' )  grid = 'zu'
10378
10379       CASE ( 'rad_lw_cs_hr_xy', 'rad_lw_cs_hr_xz', 'rad_lw_cs_hr_yz' )
10380          IF ( av == 0 ) THEN
10381             DO  i = nxl, nxr
10382                DO  j = nys, nyn
10383                   DO  k = nzb_do, nzt_do
10384                      local_pf(i,j,k) = rad_lw_cs_hr(k,j,i)
10385                   ENDDO
10386                ENDDO
10387             ENDDO
10388          ELSE
10389            IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) ) THEN
10390               ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10391               rad_lw_cs_hr_av = REAL( fill_value, KIND = wp )
10392            ENDIF
10393             DO  i = nxl, nxr
10394                DO  j = nys, nyn 
10395                   DO  k = nzb_do, nzt_do
10396                      local_pf(i,j,k) = rad_lw_cs_hr_av(k,j,i)
10397                   ENDDO
10398                ENDDO
10399             ENDDO
10400          ENDIF
10401          IF ( mode == 'xy' )  grid = 'zw'
10402
10403       CASE ( 'rad_lw_hr_xy', 'rad_lw_hr_xz', 'rad_lw_hr_yz' )
10404          IF ( av == 0 ) THEN
10405             DO  i = nxl, nxr
10406                DO  j = nys, nyn
10407                   DO  k = nzb_do, nzt_do
10408                      local_pf(i,j,k) = rad_lw_hr(k,j,i)
10409                   ENDDO
10410                ENDDO
10411             ENDDO
10412          ELSE
10413            IF ( .NOT. ALLOCATED( rad_lw_hr_av ) ) THEN
10414               ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10415               rad_lw_hr_av= REAL( fill_value, KIND = wp )
10416            ENDIF
10417             DO  i = nxl, nxr
10418                DO  j = nys, nyn 
10419                   DO  k = nzb_do, nzt_do
10420                      local_pf(i,j,k) = rad_lw_hr_av(k,j,i)
10421                   ENDDO
10422                ENDDO
10423             ENDDO
10424          ENDIF
10425          IF ( mode == 'xy' )  grid = 'zw'
10426
10427       CASE ( 'rad_sw_in_xy', 'rad_sw_in_xz', 'rad_sw_in_yz' )
10428          IF ( av == 0 ) THEN
10429             DO  i = nxl, nxr
10430                DO  j = nys, nyn
10431                   DO  k = nzb_do, nzt_do
10432                      local_pf(i,j,k) = rad_sw_in(k,j,i)
10433                   ENDDO
10434                ENDDO
10435             ENDDO
10436          ELSE
10437            IF ( .NOT. ALLOCATED( rad_sw_in_av ) ) THEN
10438               ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10439               rad_sw_in_av = REAL( fill_value, KIND = wp )
10440            ENDIF
10441             DO  i = nxl, nxr
10442                DO  j = nys, nyn 
10443                   DO  k = nzb_do, nzt_do
10444                      local_pf(i,j,k) = rad_sw_in_av(k,j,i)
10445                   ENDDO
10446                ENDDO
10447             ENDDO
10448          ENDIF
10449          IF ( mode == 'xy' )  grid = 'zu'
10450
10451       CASE ( 'rad_sw_out_xy', 'rad_sw_out_xz', 'rad_sw_out_yz' )
10452          IF ( av == 0 ) THEN
10453             DO  i = nxl, nxr
10454                DO  j = nys, nyn
10455                   DO  k = nzb_do, nzt_do
10456                      local_pf(i,j,k) = rad_sw_out(k,j,i)
10457                   ENDDO
10458                ENDDO
10459             ENDDO
10460          ELSE
10461            IF ( .NOT. ALLOCATED( rad_sw_out_av ) ) THEN
10462               ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10463               rad_sw_out_av = REAL( fill_value, KIND = wp )
10464            ENDIF
10465             DO  i = nxl, nxr
10466                DO  j = nys, nyn 
10467                   DO  k = nzb, nzt+1
10468                      local_pf(i,j,k) = rad_sw_out_av(k,j,i)
10469                   ENDDO
10470                ENDDO
10471             ENDDO
10472          ENDIF
10473          IF ( mode == 'xy' )  grid = 'zu'
10474
10475       CASE ( 'rad_sw_cs_hr_xy', 'rad_sw_cs_hr_xz', 'rad_sw_cs_hr_yz' )
10476          IF ( av == 0 ) THEN
10477             DO  i = nxl, nxr
10478                DO  j = nys, nyn
10479                   DO  k = nzb_do, nzt_do
10480                      local_pf(i,j,k) = rad_sw_cs_hr(k,j,i)
10481                   ENDDO
10482                ENDDO
10483             ENDDO
10484          ELSE
10485            IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) ) THEN
10486               ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10487               rad_sw_cs_hr_av = REAL( fill_value, KIND = wp )
10488            ENDIF
10489             DO  i = nxl, nxr
10490                DO  j = nys, nyn 
10491                   DO  k = nzb_do, nzt_do
10492                      local_pf(i,j,k) = rad_sw_cs_hr_av(k,j,i)
10493                   ENDDO
10494                ENDDO
10495             ENDDO
10496          ENDIF
10497          IF ( mode == 'xy' )  grid = 'zw'
10498
10499       CASE ( 'rad_sw_hr_xy', 'rad_sw_hr_xz', 'rad_sw_hr_yz' )
10500          IF ( av == 0 ) THEN
10501             DO  i = nxl, nxr
10502                DO  j = nys, nyn
10503                   DO  k = nzb_do, nzt_do
10504                      local_pf(i,j,k) = rad_sw_hr(k,j,i)
10505                   ENDDO
10506                ENDDO
10507             ENDDO
10508          ELSE
10509            IF ( .NOT. ALLOCATED( rad_sw_hr_av ) ) THEN
10510               ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10511               rad_sw_hr_av = REAL( fill_value, KIND = wp )
10512            ENDIF
10513             DO  i = nxl, nxr
10514                DO  j = nys, nyn 
10515                   DO  k = nzb_do, nzt_do
10516                      local_pf(i,j,k) = rad_sw_hr_av(k,j,i)
10517                   ENDDO
10518                ENDDO
10519             ENDDO
10520          ENDIF
10521          IF ( mode == 'xy' )  grid = 'zw'
10522
10523       CASE DEFAULT
10524          found = .FALSE.
10525          grid  = 'none'
10526
10527    END SELECT
10528 
10529 END SUBROUTINE radiation_data_output_2d
10530
10531
10532!------------------------------------------------------------------------------!
10533!
10534! Description:
10535! ------------
10536!> Subroutine defining 3D output variables
10537!------------------------------------------------------------------------------!
10538 SUBROUTINE radiation_data_output_3d( av, variable, found, local_pf, nzb_do, nzt_do )
10539 
10540
10541    USE indices
10542
10543    USE kinds
10544
10545
10546    IMPLICIT NONE
10547
10548    CHARACTER (LEN=*) ::  variable !<
10549
10550    INTEGER(iwp) ::  av          !<
10551    INTEGER(iwp) ::  i, j, k, l  !<
10552    INTEGER(iwp) ::  nzb_do      !<
10553    INTEGER(iwp) ::  nzt_do      !<
10554
10555    LOGICAL      ::  found       !<
10556
10557    REAL(wp)     ::  fill_value = -999.0_wp    !< value for the _FillValue attribute
10558
10559    REAL(sp), DIMENSION(nxl:nxr,nys:nyn,nzb_do:nzt_do) ::  local_pf !<
10560
10561    CHARACTER (len=varnamelength)                   :: var, surfid
10562    INTEGER(iwp)                                    :: ids,idsint_u,idsint_l,isurf,isvf,isurfs,isurflt,ipcgb
10563    INTEGER(iwp)                                    :: is, js, ks, istat
10564
10565    found = .TRUE.
10566    var = TRIM(variable)
10567
10568!-- check if variable belongs to radiation related variables (starts with rad or rtm)
10569    IF ( len(var) < 3_iwp  )  THEN
10570       found = .FALSE.
10571       RETURN
10572    ENDIF
10573   
10574    IF ( var(1:3) /= 'rad'  .AND.  var(1:3) /= 'rtm' )  THEN
10575       found = .FALSE.
10576       RETURN
10577    ENDIF
10578
10579    ids = -1
10580    DO i = 0, nd-1
10581        k = len(TRIM(var))
10582        j = len(TRIM(dirname(i)))
10583        IF ( k-j+1 >= 1_iwp ) THEN
10584           IF ( TRIM(var(k-j+1:k)) == TRIM(dirname(i)) )  THEN
10585              ids = i
10586              idsint_u = dirint_u(ids)
10587              idsint_l = dirint_l(ids)
10588              var = var(:k-j)
10589              EXIT
10590           ENDIF
10591        ENDIF
10592    ENDDO
10593    IF ( ids == -1 )  THEN
10594        var = TRIM(variable)
10595    ENDIF
10596
10597    IF ( (var(1:8) == 'rtm_svf_'  .OR.  var(1:8) == 'rtm_dif_')  .AND.  len(TRIM(var)) >= 13 )  THEN
10598!--     svf values to particular surface
10599        surfid = var(9:)
10600        i = index(surfid,'_')
10601        j = index(surfid(i+1:),'_')
10602        READ(surfid(1:i-1),*, iostat=istat ) is
10603        IF ( istat == 0 )  THEN
10604            READ(surfid(i+1:i+j-1),*, iostat=istat ) js
10605        ENDIF
10606        IF ( istat == 0 )  THEN
10607            READ(surfid(i+j+1:),*, iostat=istat ) ks
10608        ENDIF
10609        IF ( istat == 0 )  THEN
10610            var = var(1:7)
10611        ENDIF
10612    ENDIF
10613
10614    local_pf = fill_value
10615
10616    SELECT CASE ( TRIM( var ) )
10617!--   block of large scale radiation model (e.g. RRTMG) output variables
10618      CASE ( 'rad_sw_in' )
10619         IF ( av == 0 )  THEN
10620            DO  i = nxl, nxr
10621               DO  j = nys, nyn
10622                  DO  k = nzb_do, nzt_do
10623                     local_pf(i,j,k) = rad_sw_in(k,j,i)
10624                  ENDDO
10625               ENDDO
10626            ENDDO
10627         ELSE
10628            IF ( .NOT. ALLOCATED( rad_sw_in_av ) ) THEN
10629               ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10630               rad_sw_in_av = REAL( fill_value, KIND = wp )
10631            ENDIF
10632            DO  i = nxl, nxr
10633               DO  j = nys, nyn
10634                  DO  k = nzb_do, nzt_do
10635                     local_pf(i,j,k) = rad_sw_in_av(k,j,i)
10636                  ENDDO
10637               ENDDO
10638            ENDDO
10639         ENDIF
10640
10641      CASE ( 'rad_sw_out' )
10642         IF ( av == 0 )  THEN
10643            DO  i = nxl, nxr
10644               DO  j = nys, nyn
10645                  DO  k = nzb_do, nzt_do
10646                     local_pf(i,j,k) = rad_sw_out(k,j,i)
10647                  ENDDO
10648               ENDDO
10649            ENDDO
10650         ELSE
10651            IF ( .NOT. ALLOCATED( rad_sw_out_av ) ) THEN
10652               ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10653               rad_sw_out_av = REAL( fill_value, KIND = wp )
10654            ENDIF
10655            DO  i = nxl, nxr
10656               DO  j = nys, nyn
10657                  DO  k = nzb_do, nzt_do
10658                     local_pf(i,j,k) = rad_sw_out_av(k,j,i)
10659                  ENDDO
10660               ENDDO
10661            ENDDO
10662         ENDIF
10663
10664      CASE ( 'rad_sw_cs_hr' )
10665         IF ( av == 0 )  THEN
10666            DO  i = nxl, nxr
10667               DO  j = nys, nyn
10668                  DO  k = nzb_do, nzt_do
10669                     local_pf(i,j,k) = rad_sw_cs_hr(k,j,i)
10670                  ENDDO
10671               ENDDO
10672            ENDDO
10673         ELSE
10674            IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) ) THEN
10675               ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10676               rad_sw_cs_hr_av = REAL( fill_value, KIND = wp )
10677            ENDIF
10678            DO  i = nxl, nxr
10679               DO  j = nys, nyn
10680                  DO  k = nzb_do, nzt_do
10681                     local_pf(i,j,k) = rad_sw_cs_hr_av(k,j,i)
10682                  ENDDO
10683               ENDDO
10684            ENDDO
10685         ENDIF
10686
10687      CASE ( 'rad_sw_hr' )
10688         IF ( av == 0 )  THEN
10689            DO  i = nxl, nxr
10690               DO  j = nys, nyn
10691                  DO  k = nzb_do, nzt_do
10692                     local_pf(i,j,k) = rad_sw_hr(k,j,i)
10693                  ENDDO
10694               ENDDO
10695            ENDDO
10696         ELSE
10697            IF ( .NOT. ALLOCATED( rad_sw_hr_av ) ) THEN
10698               ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10699               rad_sw_hr_av = REAL( fill_value, KIND = wp )
10700            ENDIF
10701            DO  i = nxl, nxr
10702               DO  j = nys, nyn
10703                  DO  k = nzb_do, nzt_do
10704                     local_pf(i,j,k) = rad_sw_hr_av(k,j,i)
10705                  ENDDO
10706               ENDDO
10707            ENDDO
10708         ENDIF
10709
10710      CASE ( 'rad_lw_in' )
10711         IF ( av == 0 )  THEN
10712            DO  i = nxl, nxr
10713               DO  j = nys, nyn
10714                  DO  k = nzb_do, nzt_do
10715                     local_pf(i,j,k) = rad_lw_in(k,j,i)
10716                  ENDDO
10717               ENDDO
10718            ENDDO
10719         ELSE
10720            IF ( .NOT. ALLOCATED( rad_lw_in_av ) ) THEN
10721               ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10722               rad_lw_in_av = REAL( fill_value, KIND = wp )
10723            ENDIF
10724            DO  i = nxl, nxr
10725               DO  j = nys, nyn
10726                  DO  k = nzb_do, nzt_do
10727                     local_pf(i,j,k) = rad_lw_in_av(k,j,i)
10728                  ENDDO
10729               ENDDO
10730            ENDDO
10731         ENDIF
10732
10733      CASE ( 'rad_lw_out' )
10734         IF ( av == 0 )  THEN
10735            DO  i = nxl, nxr
10736               DO  j = nys, nyn
10737                  DO  k = nzb_do, nzt_do
10738                     local_pf(i,j,k) = rad_lw_out(k,j,i)
10739                  ENDDO
10740               ENDDO
10741            ENDDO
10742         ELSE
10743            IF ( .NOT. ALLOCATED( rad_lw_out_av ) ) THEN
10744               ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10745               rad_lw_out_av = REAL( fill_value, KIND = wp )
10746            ENDIF
10747            DO  i = nxl, nxr
10748               DO  j = nys, nyn
10749                  DO  k = nzb_do, nzt_do
10750                     local_pf(i,j,k) = rad_lw_out_av(k,j,i)
10751                  ENDDO
10752               ENDDO
10753            ENDDO
10754         ENDIF
10755
10756      CASE ( 'rad_lw_cs_hr' )
10757         IF ( av == 0 )  THEN
10758            DO  i = nxl, nxr
10759               DO  j = nys, nyn
10760                  DO  k = nzb_do, nzt_do
10761                     local_pf(i,j,k) = rad_lw_cs_hr(k,j,i)
10762                  ENDDO
10763               ENDDO
10764            ENDDO
10765         ELSE
10766            IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) ) THEN
10767               ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10768               rad_lw_cs_hr_av = REAL( fill_value, KIND = wp )
10769            ENDIF
10770            DO  i = nxl, nxr
10771               DO  j = nys, nyn
10772                  DO  k = nzb_do, nzt_do
10773                     local_pf(i,j,k) = rad_lw_cs_hr_av(k,j,i)
10774                  ENDDO
10775               ENDDO
10776            ENDDO
10777         ENDIF
10778
10779      CASE ( 'rad_lw_hr' )
10780         IF ( av == 0 )  THEN
10781            DO  i = nxl, nxr
10782               DO  j = nys, nyn
10783                  DO  k = nzb_do, nzt_do
10784                     local_pf(i,j,k) = rad_lw_hr(k,j,i)
10785                  ENDDO
10786               ENDDO
10787            ENDDO
10788         ELSE
10789            IF ( .NOT. ALLOCATED( rad_lw_hr_av ) ) THEN
10790               ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10791              rad_lw_hr_av = REAL( fill_value, KIND = wp )
10792            ENDIF
10793            DO  i = nxl, nxr
10794               DO  j = nys, nyn
10795                  DO  k = nzb_do, nzt_do
10796                     local_pf(i,j,k) = rad_lw_hr_av(k,j,i)
10797                  ENDDO
10798               ENDDO
10799            ENDDO
10800         ENDIF
10801
10802      CASE ( 'rtm_rad_net' )
10803!--     array of complete radiation balance
10804         DO isurf = dirstart(ids), dirend(ids)
10805            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10806               IF ( av == 0 )  THEN
10807                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = &
10808                         surfinsw(isurf) - surfoutsw(isurf) +  surfinlw(isurf) - surfoutlw(isurf)
10809               ELSE
10810                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfradnet_av(isurf)
10811               ENDIF
10812            ENDIF
10813         ENDDO
10814
10815      CASE ( 'rtm_rad_insw' )
10816!--      array of sw radiation falling to surface after i-th reflection
10817         DO isurf = dirstart(ids), dirend(ids)
10818            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10819               IF ( av == 0 )  THEN
10820                 local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinsw(isurf)
10821               ELSE
10822                 local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinsw_av(isurf)
10823               ENDIF
10824            ENDIF
10825         ENDDO
10826
10827      CASE ( 'rtm_rad_inlw' )
10828!--      array of lw radiation falling to surface after i-th reflection
10829         DO isurf = dirstart(ids), dirend(ids)
10830            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10831               IF ( av == 0 )  THEN
10832                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlw(isurf)
10833               ELSE
10834                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlw_av(isurf)
10835               ENDIF
10836             ENDIF
10837         ENDDO
10838
10839      CASE ( 'rtm_rad_inswdir' )
10840!--      array of direct sw radiation falling to surface from sun
10841         DO isurf = dirstart(ids), dirend(ids)
10842            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10843               IF ( av == 0 )  THEN
10844                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdir(isurf)
10845               ELSE
10846                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdir_av(isurf)
10847               ENDIF
10848            ENDIF
10849         ENDDO
10850
10851      CASE ( 'rtm_rad_inswdif' )
10852!--      array of difusion sw radiation falling to surface from sky and borders of the domain
10853         DO isurf = dirstart(ids), dirend(ids)
10854            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10855               IF ( av == 0 )  THEN
10856                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdif(isurf)
10857               ELSE
10858                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdif_av(isurf)
10859               ENDIF
10860            ENDIF
10861         ENDDO
10862
10863      CASE ( 'rtm_rad_inswref' )
10864!--      array of sw radiation falling to surface from reflections
10865         DO isurf = dirstart(ids), dirend(ids)
10866            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10867               IF ( av == 0 )  THEN
10868                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = &
10869                    surfinsw(isurf) - surfinswdir(isurf) - surfinswdif(isurf)
10870               ELSE
10871                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswref_av(isurf)
10872               ENDIF
10873            ENDIF
10874         ENDDO
10875
10876      CASE ( 'rtm_rad_inlwdif' )
10877!--      array of difusion lw radiation falling to surface from sky and borders of the domain
10878         DO isurf = dirstart(ids), dirend(ids)
10879            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10880               IF ( av == 0 )  THEN
10881                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlwdif(isurf)
10882               ELSE
10883                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlwdif_av(isurf)
10884               ENDIF
10885            ENDIF
10886         ENDDO
10887
10888      CASE ( 'rtm_rad_inlwref' )
10889!--      array of lw radiation falling to surface from reflections
10890         DO isurf = dirstart(ids), dirend(ids)
10891            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10892               IF ( av == 0 )  THEN
10893                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlw(isurf) - surfinlwdif(isurf)
10894               ELSE
10895                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlwref_av(isurf)
10896               ENDIF
10897            ENDIF
10898         ENDDO
10899
10900      CASE ( 'rtm_rad_outsw' )
10901!--      array of sw radiation emitted from surface after i-th reflection
10902         DO isurf = dirstart(ids), dirend(ids)
10903            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10904               IF ( av == 0 )  THEN
10905                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutsw(isurf)
10906               ELSE
10907                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutsw_av(isurf)
10908               ENDIF
10909            ENDIF
10910         ENDDO
10911
10912      CASE ( 'rtm_rad_outlw' )
10913!--      array of lw radiation emitted from surface after i-th reflection
10914         DO isurf = dirstart(ids), dirend(ids)
10915            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10916               IF ( av == 0 )  THEN
10917                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutlw(isurf)
10918               ELSE
10919                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutlw_av(isurf)
10920               ENDIF
10921            ENDIF
10922         ENDDO
10923
10924      CASE ( 'rtm_rad_ressw' )
10925!--      average of array of residua of sw radiation absorbed in surface after last reflection
10926         DO isurf = dirstart(ids), dirend(ids)
10927            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10928               IF ( av == 0 )  THEN
10929                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfins(isurf)
10930               ELSE
10931                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfins_av(isurf)
10932               ENDIF
10933            ENDIF
10934         ENDDO
10935
10936      CASE ( 'rtm_rad_reslw' )
10937!--      average of array of residua of lw radiation absorbed in surface after last reflection
10938         DO isurf = dirstart(ids), dirend(ids)
10939            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10940               IF ( av == 0 )  THEN
10941                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinl(isurf)
10942               ELSE
10943                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinl_av(isurf)
10944               ENDIF
10945            ENDIF
10946         ENDDO
10947
10948      CASE ( 'rtm_rad_pc_inlw' )
10949!--      array of lw radiation absorbed by plant canopy
10950         DO ipcgb = 1, npcbl
10951            IF ( av == 0 )  THEN
10952               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinlw(ipcgb)
10953            ELSE
10954               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinlw_av(ipcgb)
10955            ENDIF
10956         ENDDO
10957
10958      CASE ( 'rtm_rad_pc_insw' )
10959!--      array of sw radiation absorbed by plant canopy
10960         DO ipcgb = 1, npcbl
10961            IF ( av == 0 )  THEN
10962              local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinsw(ipcgb)
10963            ELSE
10964              local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinsw_av(ipcgb)
10965            ENDIF
10966         ENDDO
10967
10968      CASE ( 'rtm_rad_pc_inswdir' )
10969!--      array of direct sw radiation absorbed by plant canopy
10970         DO ipcgb = 1, npcbl
10971            IF ( av == 0 )  THEN
10972               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdir(ipcgb)
10973            ELSE
10974               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdir_av(ipcgb)
10975            ENDIF
10976         ENDDO
10977
10978      CASE ( 'rtm_rad_pc_inswdif' )
10979!--      array of diffuse sw radiation absorbed by plant canopy
10980         DO ipcgb = 1, npcbl
10981            IF ( av == 0 )  THEN
10982               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdif(ipcgb)
10983            ELSE
10984               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdif_av(ipcgb)
10985            ENDIF
10986         ENDDO
10987
10988      CASE ( 'rtm_rad_pc_inswref' )
10989!--      array of reflected sw radiation absorbed by plant canopy
10990         DO ipcgb = 1, npcbl
10991            IF ( av == 0 )  THEN
10992               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = &
10993                                    pcbinsw(ipcgb) - pcbinswdir(ipcgb) - pcbinswdif(ipcgb)
10994            ELSE
10995               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswref_av(ipcgb)
10996            ENDIF
10997         ENDDO
10998
10999      CASE ( 'rtm_mrt_sw' )
11000         local_pf = REAL( fill_value, KIND = wp )
11001         IF ( av == 0 )  THEN
11002            DO  l = 1, nmrtbl
11003               local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinsw(l)
11004            ENDDO
11005         ELSE
11006            IF ( ALLOCATED( mrtinsw_av ) ) THEN
11007               DO  l = 1, nmrtbl
11008                  local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinsw_av(l)
11009               ENDDO
11010            ENDIF
11011         ENDIF
11012
11013      CASE ( 'rtm_mrt_lw' )
11014         local_pf = REAL( fill_value, KIND = wp )
11015         IF ( av == 0 )  THEN
11016            DO  l = 1, nmrtbl
11017               local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinlw(l)
11018            ENDDO
11019         ELSE
11020            IF ( ALLOCATED( mrtinlw_av ) ) THEN
11021               DO  l = 1, nmrtbl
11022                  local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinlw_av(l)
11023               ENDDO
11024            ENDIF
11025         ENDIF
11026
11027      CASE ( 'rtm_mrt' )
11028         local_pf = REAL( fill_value, KIND = wp )
11029         IF ( av == 0 )  THEN
11030            DO  l = 1, nmrtbl
11031               local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrt(l)
11032            ENDDO
11033         ELSE
11034            IF ( ALLOCATED( mrt_av ) ) THEN
11035               DO  l = 1, nmrtbl
11036                  local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrt_av(l)
11037               ENDDO
11038            ENDIF
11039         ENDIF
11040!         
11041!--   block of RTM output variables
11042!--   variables are intended mainly for debugging and detailed analyse purposes
11043      CASE ( 'rtm_skyvf' )
11044!     
11045!--      sky view factor
11046         DO isurf = dirstart(ids), dirend(ids)
11047            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
11048               local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = skyvf(isurf)
11049            ENDIF
11050         ENDDO
11051
11052      CASE ( 'rtm_skyvft' )
11053!
11054!--      sky view factor
11055         DO isurf = dirstart(ids), dirend(ids)
11056            IF ( surfl(id,isurf) == ids )  THEN
11057               local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = skyvft(isurf)
11058            ENDIF
11059         ENDDO
11060
11061      CASE ( 'rtm_svf', 'rtm_dif' )
11062!
11063!--      shape view factors or iradiance factors to selected surface
11064         IF ( TRIM(var)=='rtm_svf' )  THEN
11065             k = 1
11066         ELSE
11067             k = 2
11068         ENDIF
11069         DO isvf = 1, nsvfl
11070            isurflt = svfsurf(1, isvf)
11071            isurfs = svfsurf(2, isvf)
11072
11073            IF ( surf(ix,isurfs) == is  .AND.  surf(iy,isurfs) == js  .AND. surf(iz,isurfs) == ks  .AND. &
11074                 (surf(id,isurfs) == idsint_u .OR. surfl(id,isurfs) == idsint_l ) ) THEN
11075!
11076!--            correct source surface
11077               local_pf(surfl(ix,isurflt),surfl(iy,isurflt),surfl(iz,isurflt)) = svf(k,isvf)
11078            ENDIF
11079         ENDDO
11080
11081      CASE ( 'rtm_surfalb' )
11082!
11083!--      surface albedo
11084         DO isurf = dirstart(ids), dirend(ids)
11085            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
11086               local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = albedo_surf(isurf)
11087            ENDIF
11088         ENDDO
11089
11090      CASE ( 'rtm_surfemis' )
11091!
11092!--      surface emissivity, weighted average
11093         DO isurf = dirstart(ids), dirend(ids)
11094            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
11095               local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = emiss_surf(isurf)
11096            ENDIF
11097         ENDDO
11098
11099      CASE DEFAULT
11100         found = .FALSE.
11101
11102    END SELECT
11103
11104
11105 END SUBROUTINE radiation_data_output_3d
11106
11107!------------------------------------------------------------------------------!
11108!
11109! Description:
11110! ------------
11111!> Subroutine defining masked data output
11112!------------------------------------------------------------------------------!
11113 SUBROUTINE radiation_data_output_mask( av, variable, found, local_pf, mid )
11114 
11115    USE control_parameters
11116       
11117    USE indices
11118   
11119    USE kinds
11120   
11121
11122    IMPLICIT NONE
11123
11124    CHARACTER (LEN=*) ::  variable   !<
11125
11126    CHARACTER(LEN=5) ::  grid        !< flag to distinquish between staggered grids
11127
11128    INTEGER(iwp) ::  av              !<
11129    INTEGER(iwp) ::  i               !<
11130    INTEGER(iwp) ::  j               !<
11131    INTEGER(iwp) ::  k               !<
11132    INTEGER(iwp) ::  mid             !< masked output running index
11133    INTEGER(iwp) ::  topo_top_ind    !< k index of highest horizontal surface
11134
11135    LOGICAL ::  found                !< true if output array was found
11136    LOGICAL ::  resorted             !< true if array is resorted
11137
11138
11139    REAL(wp),                                                                  &
11140       DIMENSION(mask_size_l(mid,1),mask_size_l(mid,2),mask_size_l(mid,3)) ::  &
11141          local_pf   !<
11142
11143    REAL(wp), DIMENSION(:,:,:), POINTER ::  to_be_resorted  !< points to array which needs to be resorted for output
11144
11145
11146    found    = .TRUE.
11147    grid     = 's'
11148    resorted = .FALSE.
11149
11150    SELECT CASE ( TRIM( variable ) )
11151
11152
11153       CASE ( 'rad_lw_in' )
11154          IF ( av == 0 )  THEN
11155             to_be_resorted => rad_lw_in
11156          ELSE
11157             to_be_resorted => rad_lw_in_av
11158          ENDIF
11159
11160       CASE ( 'rad_lw_out' )
11161          IF ( av == 0 )  THEN
11162             to_be_resorted => rad_lw_out
11163          ELSE
11164             to_be_resorted => rad_lw_out_av
11165          ENDIF
11166
11167       CASE ( 'rad_lw_cs_hr' )
11168          IF ( av == 0 )  THEN
11169             to_be_resorted => rad_lw_cs_hr
11170          ELSE
11171             to_be_resorted => rad_lw_cs_hr_av
11172          ENDIF
11173
11174       CASE ( 'rad_lw_hr' )
11175          IF ( av == 0 )  THEN
11176             to_be_resorted => rad_lw_hr
11177          ELSE
11178             to_be_resorted => rad_lw_hr_av
11179          ENDIF
11180
11181       CASE ( 'rad_sw_in' )
11182          IF ( av == 0 )  THEN
11183             to_be_resorted => rad_sw_in
11184          ELSE
11185             to_be_resorted => rad_sw_in_av
11186          ENDIF
11187
11188       CASE ( 'rad_sw_out' )
11189          IF ( av == 0 )  THEN
11190             to_be_resorted => rad_sw_out
11191          ELSE
11192             to_be_resorted => rad_sw_out_av
11193          ENDIF
11194
11195       CASE ( 'rad_sw_cs_hr' )
11196          IF ( av == 0 )  THEN
11197             to_be_resorted => rad_sw_cs_hr
11198          ELSE
11199             to_be_resorted => rad_sw_cs_hr_av
11200          ENDIF
11201
11202       CASE ( 'rad_sw_hr' )
11203          IF ( av == 0 )  THEN
11204             to_be_resorted => rad_sw_hr
11205          ELSE
11206             to_be_resorted => rad_sw_hr_av
11207          ENDIF
11208
11209       CASE DEFAULT
11210          found = .FALSE.
11211
11212    END SELECT
11213
11214!
11215!-- Resort the array to be output, if not done above
11216    IF ( found  .AND.  .NOT. resorted )  THEN
11217       IF ( .NOT. mask_surface(mid) )  THEN
11218!
11219!--       Default masked output
11220          DO  i = 1, mask_size_l(mid,1)
11221             DO  j = 1, mask_size_l(mid,2)
11222                DO  k = 1, mask_size_l(mid,3)
11223                   local_pf(i,j,k) =  to_be_resorted(mask_k(mid,k), &
11224                                      mask_j(mid,j),mask_i(mid,i))
11225                ENDDO
11226             ENDDO
11227          ENDDO
11228
11229       ELSE
11230!
11231!--       Terrain-following masked output
11232          DO  i = 1, mask_size_l(mid,1)
11233             DO  j = 1, mask_size_l(mid,2)
11234!
11235!--             Get k index of highest horizontal surface
11236                topo_top_ind = get_topography_top_index_ji( mask_j(mid,j), &
11237                                                            mask_i(mid,i), &
11238                                                            grid )
11239!
11240!--             Save output array
11241                DO  k = 1, mask_size_l(mid,3)
11242                   local_pf(i,j,k) = to_be_resorted(                       &
11243                                          MIN( topo_top_ind+mask_k(mid,k), &
11244                                               nzt+1 ),                    &
11245                                          mask_j(mid,j),                   &
11246                                          mask_i(mid,i)                     )
11247                ENDDO
11248             ENDDO
11249          ENDDO
11250
11251       ENDIF
11252    ENDIF
11253
11254
11255
11256 END SUBROUTINE radiation_data_output_mask
11257
11258
11259!------------------------------------------------------------------------------!
11260! Description:
11261! ------------
11262!> Subroutine writes local (subdomain) restart data
11263!------------------------------------------------------------------------------!
11264 SUBROUTINE radiation_wrd_local
11265
11266
11267    IMPLICIT NONE
11268
11269
11270    IF ( ALLOCATED( rad_net_av ) )  THEN
11271       CALL wrd_write_string( 'rad_net_av' )
11272       WRITE ( 14 )  rad_net_av
11273    ENDIF
11274   
11275    IF ( ALLOCATED( rad_lw_in_xy_av ) )  THEN
11276       CALL wrd_write_string( 'rad_lw_in_xy_av' )
11277       WRITE ( 14 )  rad_lw_in_xy_av
11278    ENDIF
11279   
11280    IF ( ALLOCATED( rad_lw_out_xy_av ) )  THEN
11281       CALL wrd_write_string( 'rad_lw_out_xy_av' )
11282       WRITE ( 14 )  rad_lw_out_xy_av
11283    ENDIF
11284   
11285    IF ( ALLOCATED( rad_sw_in_xy_av ) )  THEN
11286       CALL wrd_write_string( 'rad_sw_in_xy_av' )
11287       WRITE ( 14 )  rad_sw_in_xy_av
11288    ENDIF
11289   
11290    IF ( ALLOCATED( rad_sw_out_xy_av ) )  THEN
11291       CALL wrd_write_string( 'rad_sw_out_xy_av' )
11292       WRITE ( 14 )  rad_sw_out_xy_av
11293    ENDIF
11294
11295    IF ( ALLOCATED( rad_lw_in ) )  THEN
11296       CALL wrd_write_string( 'rad_lw_in' )
11297       WRITE ( 14 )  rad_lw_in
11298    ENDIF
11299
11300    IF ( ALLOCATED( rad_lw_in_av ) )  THEN
11301       CALL wrd_write_string( 'rad_lw_in_av' )
11302       WRITE ( 14 )  rad_lw_in_av
11303    ENDIF
11304
11305    IF ( ALLOCATED( rad_lw_out ) )  THEN
11306       CALL wrd_write_string( 'rad_lw_out' )
11307       WRITE ( 14 )  rad_lw_out
11308    ENDIF
11309
11310    IF ( ALLOCATED( rad_lw_out_av) )  THEN
11311       CALL wrd_write_string( 'rad_lw_out_av' )
11312       WRITE ( 14 )  rad_lw_out_av
11313    ENDIF
11314
11315    IF ( ALLOCATED( rad_lw_cs_hr) )  THEN
11316       CALL wrd_write_string( 'rad_lw_cs_hr' )
11317       WRITE ( 14 )  rad_lw_cs_hr
11318    ENDIF
11319
11320    IF ( ALLOCATED( rad_lw_cs_hr_av) )  THEN
11321       CALL wrd_write_string( 'rad_lw_cs_hr_av' )
11322       WRITE ( 14 )  rad_lw_cs_hr_av
11323    ENDIF
11324
11325    IF ( ALLOCATED( rad_lw_hr) )  THEN
11326       CALL wrd_write_string( 'rad_lw_hr' )
11327       WRITE ( 14 )  rad_lw_hr
11328    ENDIF
11329
11330    IF ( ALLOCATED( rad_lw_hr_av) )  THEN
11331       CALL wrd_write_string( 'rad_lw_hr_av' )
11332       WRITE ( 14 )  rad_lw_hr_av
11333    ENDIF
11334
11335    IF ( ALLOCATED( rad_sw_in) )  THEN
11336       CALL wrd_write_string( 'rad_sw_in' )
11337       WRITE ( 14 )  rad_sw_in
11338    ENDIF
11339
11340    IF ( ALLOCATED( rad_sw_in_av) )  THEN
11341       CALL wrd_write_string( 'rad_sw_in_av' )
11342       WRITE ( 14 )  rad_sw_in_av
11343    ENDIF
11344
11345    IF ( ALLOCATED( rad_sw_out) )  THEN
11346       CALL wrd_write_string( 'rad_sw_out' )
11347       WRITE ( 14 )  rad_sw_out
11348    ENDIF
11349
11350    IF ( ALLOCATED( rad_sw_out_av) )  THEN
11351       CALL wrd_write_string( 'rad_sw_out_av' )
11352       WRITE ( 14 )  rad_sw_out_av
11353    ENDIF
11354
11355    IF ( ALLOCATED( rad_sw_cs_hr) )  THEN
11356       CALL wrd_write_string( 'rad_sw_cs_hr' )
11357       WRITE ( 14 )  rad_sw_cs_hr
11358    ENDIF
11359
11360    IF ( ALLOCATED( rad_sw_cs_hr_av) )  THEN
11361       CALL wrd_write_string( 'rad_sw_cs_hr_av' )
11362       WRITE ( 14 )  rad_sw_cs_hr_av
11363    ENDIF
11364
11365    IF ( ALLOCATED( rad_sw_hr) )  THEN
11366       CALL wrd_write_string( 'rad_sw_hr' )
11367       WRITE ( 14 )  rad_sw_hr
11368    ENDIF
11369
11370    IF ( ALLOCATED( rad_sw_hr_av) )  THEN
11371       CALL wrd_write_string( 'rad_sw_hr_av' )
11372       WRITE ( 14 )  rad_sw_hr_av
11373    ENDIF
11374
11375
11376 END SUBROUTINE radiation_wrd_local
11377
11378!------------------------------------------------------------------------------!
11379! Description:
11380! ------------
11381!> Subroutine reads local (subdomain) restart data
11382!------------------------------------------------------------------------------!
11383 SUBROUTINE radiation_rrd_local( k, nxlf, nxlc, nxl_on_file, nxrf, nxrc,       &
11384                                nxr_on_file, nynf, nync, nyn_on_file, nysf,    &
11385                                nysc, nys_on_file, tmp_2d, tmp_3d, found )
11386 
11387
11388    USE control_parameters
11389       
11390    USE indices
11391   
11392    USE kinds
11393   
11394    USE pegrid
11395
11396
11397    IMPLICIT NONE
11398
11399    INTEGER(iwp) ::  k               !<
11400    INTEGER(iwp) ::  nxlc            !<
11401    INTEGER(iwp) ::  nxlf            !<
11402    INTEGER(iwp) ::  nxl_on_file     !<
11403    INTEGER(iwp) ::  nxrc            !<
11404    INTEGER(iwp) ::  nxrf            !<
11405    INTEGER(iwp) ::  nxr_on_file     !<
11406    INTEGER(iwp) ::  nync            !<
11407    INTEGER(iwp) ::  nynf            !<
11408    INTEGER(iwp) ::  nyn_on_file     !<
11409    INTEGER(iwp) ::  nysc            !<
11410    INTEGER(iwp) ::  nysf            !<
11411    INTEGER(iwp) ::  nys_on_file     !<
11412
11413    LOGICAL, INTENT(OUT)  :: found
11414
11415    REAL(wp), DIMENSION(nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_2d   !<
11416
11417    REAL(wp), DIMENSION(nzb:nzt+1,nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_3d   !<
11418
11419    REAL(wp), DIMENSION(0:0,nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_3d2   !<
11420
11421
11422    found = .TRUE.
11423
11424
11425    SELECT CASE ( restart_string(1:length) )
11426
11427       CASE ( 'rad_net_av' )
11428          IF ( .NOT. ALLOCATED( rad_net_av ) )  THEN
11429             ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
11430          ENDIF 
11431          IF ( k == 1 )  READ ( 13 )  tmp_2d
11432          rad_net_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =           &
11433                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11434                       
11435       CASE ( 'rad_lw_in_xy_av' )
11436          IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) )  THEN
11437             ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
11438          ENDIF 
11439          IF ( k == 1 )  READ ( 13 )  tmp_2d
11440          rad_lw_in_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =      &
11441                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11442                       
11443       CASE ( 'rad_lw_out_xy_av' )
11444          IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) )  THEN
11445             ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
11446          ENDIF 
11447          IF ( k == 1 )  READ ( 13 )  tmp_2d
11448          rad_lw_out_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =     &
11449                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11450                       
11451       CASE ( 'rad_sw_in_xy_av' )
11452          IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) )  THEN
11453             ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
11454          ENDIF 
11455          IF ( k == 1 )  READ ( 13 )  tmp_2d
11456          rad_sw_in_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =      &
11457                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11458                       
11459       CASE ( 'rad_sw_out_xy_av' )
11460          IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) )  THEN
11461             ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
11462          ENDIF 
11463          IF ( k == 1 )  READ ( 13 )  tmp_2d
11464          rad_sw_out_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =     &
11465                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11466                       
11467       CASE ( 'rad_lw_in' )
11468          IF ( .NOT. ALLOCATED( rad_lw_in ) )  THEN
11469             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11470                  radiation_scheme == 'constant')  THEN
11471                ALLOCATE( rad_lw_in(0:0,nysg:nyng,nxlg:nxrg) )
11472             ELSE
11473                ALLOCATE( rad_lw_in(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(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(:,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_in_av' )
11490          IF ( .NOT. ALLOCATED( rad_lw_in_av ) )  THEN
11491             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11492                  radiation_scheme == 'constant')  THEN
11493                ALLOCATE( rad_lw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
11494             ELSE
11495                ALLOCATE( rad_lw_in_av(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_in_av(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_in_av(:,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' )
11512          IF ( .NOT. ALLOCATED( rad_lw_out ) )  THEN
11513             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11514                  radiation_scheme == 'constant')  THEN
11515                ALLOCATE( rad_lw_out(0:0,nysg:nyng,nxlg:nxrg) )
11516             ELSE
11517                ALLOCATE( rad_lw_out(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(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(:,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_out_av' )
11534          IF ( .NOT. ALLOCATED( rad_lw_out_av ) )  THEN
11535             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11536                  radiation_scheme == 'constant')  THEN
11537                ALLOCATE( rad_lw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
11538             ELSE
11539                ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11540             ENDIF
11541          ENDIF 
11542          IF ( k == 1 )  THEN
11543             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11544                  radiation_scheme == 'constant')  THEN
11545                READ ( 13 )  tmp_3d2
11546                rad_lw_out_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) &
11547                   = tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11548             ELSE
11549                READ ( 13 )  tmp_3d
11550                rad_lw_out_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &
11551                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11552             ENDIF
11553          ENDIF
11554
11555       CASE ( 'rad_lw_cs_hr' )
11556          IF ( .NOT. ALLOCATED( rad_lw_cs_hr ) )  THEN
11557             ALLOCATE( rad_lw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11558          ENDIF
11559          IF ( k == 1 )  READ ( 13 )  tmp_3d
11560          rad_lw_cs_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11561                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11562
11563       CASE ( 'rad_lw_cs_hr_av' )
11564          IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) )  THEN
11565             ALLOCATE( rad_lw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11566          ENDIF
11567          IF ( k == 1 )  READ ( 13 )  tmp_3d
11568          rad_lw_cs_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11569                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11570
11571       CASE ( 'rad_lw_hr' )
11572          IF ( .NOT. ALLOCATED( rad_lw_hr ) )  THEN
11573             ALLOCATE( rad_lw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11574          ENDIF
11575          IF ( k == 1 )  READ ( 13 )  tmp_3d
11576          rad_lw_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =           &
11577                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11578
11579       CASE ( 'rad_lw_hr_av' )
11580          IF ( .NOT. ALLOCATED( rad_lw_hr_av ) )  THEN
11581             ALLOCATE( rad_lw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11582          ENDIF
11583          IF ( k == 1 )  READ ( 13 )  tmp_3d
11584          rad_lw_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11585                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11586
11587       CASE ( 'rad_sw_in' )
11588          IF ( .NOT. ALLOCATED( rad_sw_in ) )  THEN
11589             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11590                  radiation_scheme == 'constant')  THEN
11591                ALLOCATE( rad_sw_in(0:0,nysg:nyng,nxlg:nxrg) )
11592             ELSE
11593                ALLOCATE( rad_sw_in(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(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(:,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_in_av' )
11610          IF ( .NOT. ALLOCATED( rad_sw_in_av ) )  THEN
11611             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11612                  radiation_scheme == 'constant')  THEN
11613                ALLOCATE( rad_sw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
11614             ELSE
11615                ALLOCATE( rad_sw_in_av(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_in_av(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_in_av(:,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' )
11632          IF ( .NOT. ALLOCATED( rad_sw_out ) )  THEN
11633             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11634                  radiation_scheme == 'constant')  THEN
11635                ALLOCATE( rad_sw_out(0:0,nysg:nyng,nxlg:nxrg) )
11636             ELSE
11637                ALLOCATE( rad_sw_out(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(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(:,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_out_av' )
11654          IF ( .NOT. ALLOCATED( rad_sw_out_av ) )  THEN
11655             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11656                  radiation_scheme == 'constant')  THEN
11657                ALLOCATE( rad_sw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
11658             ELSE
11659                ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11660             ENDIF
11661          ENDIF 
11662          IF ( k == 1 )  THEN
11663             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11664                  radiation_scheme == 'constant')  THEN
11665                READ ( 13 )  tmp_3d2
11666                rad_sw_out_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) &
11667                   = tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11668             ELSE
11669                READ ( 13 )  tmp_3d
11670                rad_sw_out_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &
11671                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11672             ENDIF
11673          ENDIF
11674
11675       CASE ( 'rad_sw_cs_hr' )
11676          IF ( .NOT. ALLOCATED( rad_sw_cs_hr ) )  THEN
11677             ALLOCATE( rad_sw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11678          ENDIF
11679          IF ( k == 1 )  READ ( 13 )  tmp_3d
11680          rad_sw_cs_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11681                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11682
11683       CASE ( 'rad_sw_cs_hr_av' )
11684          IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) )  THEN
11685             ALLOCATE( rad_sw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11686          ENDIF
11687          IF ( k == 1 )  READ ( 13 )  tmp_3d
11688          rad_sw_cs_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11689                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11690
11691       CASE ( 'rad_sw_hr' )
11692          IF ( .NOT. ALLOCATED( rad_sw_hr ) )  THEN
11693             ALLOCATE( rad_sw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11694          ENDIF
11695          IF ( k == 1 )  READ ( 13 )  tmp_3d
11696          rad_sw_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =           &
11697                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11698
11699       CASE ( 'rad_sw_hr_av' )
11700          IF ( .NOT. ALLOCATED( rad_sw_hr_av ) )  THEN
11701             ALLOCATE( rad_sw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11702          ENDIF
11703          IF ( k == 1 )  READ ( 13 )  tmp_3d
11704          rad_lw_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11705                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11706
11707       CASE DEFAULT
11708
11709          found = .FALSE.
11710
11711    END SELECT
11712
11713 END SUBROUTINE radiation_rrd_local
11714
11715
11716 END MODULE radiation_model_mod
Note: See TracBrowser for help on using the repository browser.