Index: palm/trunk/UTIL/inifor/Makefile
===================================================================
--- palm/trunk/UTIL/inifor/Makefile	(revision 3401)
+++ palm/trunk/UTIL/inifor/Makefile	(revision 3447)
@@ -25,4 +25,7 @@
 # -----------------
 # $Id$
+# Renamed source files for compatibilty with PALM build system 
+# 
+# 3395 2018-10-22 17:32:49Z eckhard
 # Updated build order
 # 
@@ -50,5 +53,8 @@
 TEST_PATH = $(PROJECT_PATH)/tests
 
-MODULES = $(SRC_PATH)/defs.mod $(SRC_PATH)/types.mod $(SRC_PATH)/util.mod $(SRC_PATH)/control.mod $(SRC_PATH)/transform.mod $(SRC_PATH)/io.mod $(SRC_PATH)/grid.mod
+MODULES = $(SRC_PATH)/inifor_defs.mod $(SRC_PATH)/inifor_types.mod \
+		  $(SRC_PATH)/inifor_util.mod $(SRC_PATH)/inifor_control.mod \
+		  $(SRC_PATH)/inifor_transform.mod $(SRC_PATH)/inifor_io.mod \
+		  $(SRC_PATH)/inifor_grid.mod
 SOURCES = $(MODULES:%.mod=%.f90) $(SRC_PATH)/$(PROJECT).f90
 OBJECTS = $(SOURCES:%.f90=%.o)
Index: palm/trunk/UTIL/inifor/Makefile.gnu
===================================================================
--- palm/trunk/UTIL/inifor/Makefile.gnu	(revision 3401)
+++ palm/trunk/UTIL/inifor/Makefile.gnu	(revision 3447)
@@ -25,4 +25,7 @@
 # -----------------
 # $Id$
+# Renamed source files for compatibilty with PALM build system 
+# 
+# 3395 2018-10-22 17:32:49Z eckhard
 # Updated build order
 # 
@@ -51,5 +54,8 @@
 TEST_PATH = $(PROJECT_PATH)/tests
 
-MODULES = $(SRC_PATH)/defs.mod $(SRC_PATH)/types.mod $(SRC_PATH)/util.mod $(SRC_PATH)/control.mod $(SRC_PATH)/transform.mod $(SRC_PATH)/io.mod $(SRC_PATH)/grid.mod
+MODULES = $(SRC_PATH)/inifor_defs.mod $(SRC_PATH)/inifor_types.mod \
+		  $(SRC_PATH)/inifor_util.mod $(SRC_PATH)/inifor_control.mod \
+		  $(SRC_PATH)/inifor_transform.mod $(SRC_PATH)/inifor_io.mod \
+		  $(SRC_PATH)/inifor_grid.mod
 SOURCES = $(MODULES:%.mod=%.f90) $(SRC_PATH)/$(PROJECT).f90
 OBJECTS = $(SOURCES:%.f90=%.o)
Index: palm/trunk/UTIL/inifor/Makefile.ifort
===================================================================
--- palm/trunk/UTIL/inifor/Makefile.ifort	(revision 3401)
+++ palm/trunk/UTIL/inifor/Makefile.ifort	(revision 3447)
@@ -25,4 +25,7 @@
 # -----------------
 # $Id$
+# Renamed source files for compatibilty with PALM build system 
+# 
+# 3395 2018-10-22 17:32:49Z eckhard
 # Updated build order
 # 
@@ -51,5 +54,8 @@
 TEST_PATH = $(PROJECT_PATH)/tests
 
-MODULES = $(SRC_PATH)/defs.mod $(SRC_PATH)/types.mod $(SRC_PATH)/util.mod $(SRC_PATH)/control.mod $(SRC_PATH)/transform.mod $(SRC_PATH)/io.mod $(SRC_PATH)/grid.mod
+MODULES = $(SRC_PATH)/inifor_defs.mod $(SRC_PATH)/inifor_types.mod \
+		  $(SRC_PATH)/inifor_util.mod $(SRC_PATH)/inifor_control.mod \
+		  $(SRC_PATH)/inifor_transform.mod $(SRC_PATH)/inifor_io.mod \
+		  $(SRC_PATH)/inifor_grid.mod
 SOURCES = $(MODULES:%.mod=%.f90) $(SRC_PATH)/$(PROJECT).f90
 OBJECTS = $(SOURCES:%.f90=%.o)
Index: palm/trunk/UTIL/inifor/src/control.f90
===================================================================
--- palm/trunk/UTIL/inifor/src/control.f90	(revision 3401)
+++ 	(revision )
@@ -1,200 +1,0 @@
-!> @file src/control.f90
-!------------------------------------------------------------------------------!
-! This file is part of the PALM model system.
-!
-! PALM is free software: you can redistribute it and/or modify it under the
-! terms of the GNU General Public License as published by the Free Software
-! Foundation, either version 3 of the License, or (at your option) any later
-! version.
-!
-! PALM is distributed in the hope that it will be useful, but WITHOUT ANY
-! WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-! A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
-!
-! You should have received a copy of the GNU General Public License along with
-! PALM. If not, see <http://www.gnu.org/licenses/>.
-!
-! Copyright 2017-2018 Leibniz Universitaet Hannover
-! Copyright 2017-2018 Deutscher Wetterdienst Offenbach
-!------------------------------------------------------------------------------!
-!
-! Current revisions:
-! -----------------
-! 
-! 
-! Former revisions:
-! -----------------
-! $Id$
-! Suppress debugging messages unless --debug option is given
-! 
-!
-! 3183 2018-07-27 14:25:55Z suehring
-! Added version and copyright output
-! 
-! 
-! 3182 2018-07-27 13:36:03Z suehring
-! Initial revision
-!
-! 
-!
-! Authors:
-! --------
-! @author Eckhard Kadasch
-!
-! Description:
-! ------------
-!> The control module provides routines for timing INIFOR and writing runtime
-!> feedback to the terminal and a log file.
-!------------------------------------------------------------------------------!
- MODULE control
-
-    USE defs,                                                                  &
-        ONLY:  LNAME, dp, VERSION, COPYRIGHT
-
-    USE util,                                                                  &
-        ONLY:  real_to_str, real_to_str_f
-
-    IMPLICIT NONE
-
-    CHARACTER (LEN=5000) ::  message = ''
-
- CONTAINS
-
-    SUBROUTINE report(routine, message, debug)
-
-       CHARACTER(LEN=*), INTENT(IN)  ::  routine
-       CHARACTER(LEN=*), INTENT(IN)  ::  message
-       LOGICAL, OPTIONAL, INTENT(IN) ::  debug
-       INTEGER                       ::  u
-       LOGICAL, SAVE                 ::  is_first_run = .TRUE.
-       LOGICAL                       ::  suppress_message
-
-
-       IF (is_first_run)  THEN
-          OPEN( NEWUNIT=u, FILE='inifor.log', STATUS='replace' )
-          is_first_run = .FALSE.
-       ELSE
-          OPEN( NEWUNIT=u, FILE='inifor.log', POSITION='append', STATUS='old' )
-       END IF
-          
-
-       suppress_message = .FALSE.
-       IF (PRESENT(debug))  THEN
-          IF (.NOT. debug)  suppress_message = .TRUE.
-       END IF
-
-       IF (.NOT. suppress_message)  THEN
-          PRINT *, "inifor: " // TRIM(message) // "  [ " // TRIM(routine) // " ]"
-          WRITE(u, *)  TRIM(message) // "  [ " // TRIM(routine) // " ]"
-       END IF
-
-       CLOSE(u)
-
-    END SUBROUTINE report
-
-
-    SUBROUTINE warn(routine, message)
-
-       CHARACTER(LEN=*), INTENT(IN) ::  routine
-       CHARACTER(LEN=*), INTENT(IN) ::  message
-
-       CALL report(routine, "WARNING: " // TRIM(message))
-
-    END SUBROUTINE warn
-
-
-    SUBROUTINE abort(routine, message)
-
-       CHARACTER(LEN=*), INTENT(IN) ::  routine
-       CHARACTER(LEN=*), INTENT(IN) ::  message
-
-       CALL report(routine, "ERROR: " // TRIM(message) // " Stopping.")
-       STOP
-
-    END SUBROUTINE abort
-
-
-    SUBROUTINE print_version()
-       PRINT *, "INIFOR " // VERSION
-       PRINT *, COPYRIGHT
-    END SUBROUTINE print_version
-
-
-    SUBROUTINE run_control(mode, budget)
-
-       CHARACTER(LEN=*), INTENT(IN) ::  mode, budget
-       REAL(dp), SAVE               ::  t0, t1
-       REAL(dp), SAVE               ::  t_comp=0.0_dp, &
-                                        t_alloc=0.0_dp, &
-                                        t_init=0.0_dp, &
-                                        t_read=0.0_dp, &
-                                        t_total=0.0_dp, &
-                                        t_write=0.0_dp
-       CHARACTER(LEN=*), PARAMETER  ::  fmt='(F6.2)'
-
-
-       SELECT CASE(TRIM(mode))
-
-       CASE('init')
-          CALL CPU_TIME(t0)
-
-       CASE('time')
-
-          CALL CPU_TIME(t1)
-
-          SELECT CASE(TRIM(budget))
-
-             CASE('alloc')
-                t_alloc = t_alloc + t1 - t0
-
-             CASE('init')
-                t_init = t_init + t1 - t0
-
-             CASE('read')
-                t_read = t_read + t1 - t0
-
-             CASE('write')
-                t_write = t_write + t1 - t0
-
-             CASE('comp')
-                t_comp = t_comp + t1 - t0
-
-             CASE DEFAULT
-                CALL abort('run_control', "Time Budget '" // TRIM(mode) // "' is not supported.")
-
-          END SELECT
-
-          t0 = t1
-
-       CASE('report')
-           t_total = t_init + t_read + t_write + t_comp
-
-           CALL report('run_control', " *** CPU time ***")
-
-           CALL report('run_control', "Initialization: " // real_to_str(t_init)  // &
-                       " s (" // TRIM(real_to_str(100*t_init/t_total, fmt))      // " %)")
-
-           CALL report('run_control', "(De-)Allocation:" // real_to_str(t_alloc)  // &
-                       " s (" // TRIM(real_to_str(100*t_alloc/t_total, fmt))      // " %)")
-
-           CALL report('run_control', "Reading data:   " // real_to_str(t_read)  // &
-                       " s (" // TRIM(real_to_str(100*t_read/t_total, fmt))      // " %)")
-
-           CALL report('run_control', "Writing data:   " // real_to_str(t_write) // &
-                       " s (" // TRIM(real_to_str(100*t_write/t_total, fmt))     // " %)")
-
-           CALL report('run_control', "Computation:    " // real_to_str(t_comp)  // &
-                       " s (" // TRIM(real_to_str(100*t_comp/t_total, fmt))      // " %)")
-
-           CALL report('run_control', "Total:          " // real_to_str(t_total) // &
-                       " s (" // TRIM(real_to_str(100*t_total/t_total, fmt))     // " %)")
-
-       CASE DEFAULT
-          CALL abort('run_control', "Mode '" // TRIM(mode) // "' is not supported.")
-
-       END SELECT
-
-    END SUBROUTINE run_control
-
- END MODULE
-
Index: palm/trunk/UTIL/inifor/src/defs.f90
===================================================================
--- palm/trunk/UTIL/inifor/src/defs.f90	(revision 3401)
+++ 	(revision )
@@ -1,96 +1,0 @@
-!> @file src/defs.f90
-!------------------------------------------------------------------------------!
-! This file is part of the PALM model system.
-!
-! PALM is free software: you can redistribute it and/or modify it under the
-! terms of the GNU General Public License as published by the Free Software
-! Foundation, either version 3 of the License, or (at your option) any later
-! version.
-!
-! PALM is distributed in the hope that it will be useful, but WITHOUT ANY
-! WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-! A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
-!
-! You should have received a copy of the GNU General Public License along with
-! PALM. If not, see <http://www.gnu.org/licenses/>.
-!
-! Copyright 2017-2018 Leibniz Universitaet Hannover
-! Copyright 2017-2018 Deutscher Wetterdienst Offenbach
-!------------------------------------------------------------------------------!
-!
-! Current revisions:
-! -----------------
-! 
-! 
-! Former revisions:
-! -----------------
-! $Id$
-! New parameters for computation of geostrophic winds
-! Bumped INIFOR version number
-! 
-! 
-! 3183 2018-07-27 14:25:55Z suehring
-! Updated defaults for soil extrapolation steps and nudging time-scale
-! Improved handling of the start date string
-! Added gas constant for water vapor
-! Bumped INIFOR version number
-! 
-! 
-! 3182 2018-07-27 13:36:03Z suehring
-! Initial revision
-!
-! 
-!
-! Authors:
-! --------
-! @author Eckhard Kadasch
-!
-! Description:
-! ------------
-!> The defs module provides global constants used in INIFOR.
-!------------------------------------------------------------------------------!
- MODULE defs
- 
- IMPLICIT NONE
- 
- ! Parameters for type definitions
- INTEGER, PARAMETER  ::  dp    = 8   !< double precision (8 bytes = 64 bits)
- INTEGER, PARAMETER  ::  sp    = 4   !< single precision (4 bytes = 32 bits)
- INTEGER, PARAMETER  ::  hp    = 2   !< half precision (2 bytes = 16 bits)
- INTEGER, PARAMETER  ::  PATH  = 140 !< length of file path strings
- INTEGER, PARAMETER  ::  LNAME = 150 !< length of long name strings
- INTEGER, PARAMETER  ::  SNAME = 40  !< length of short name strings
- INTEGER, PARAMETER  ::  DATE  = 10  !< length of date strings
-
- ! Trigonomentry
- REAL(dp), PARAMETER ::  PI = 3.14159265358979323846264338_dp !< Ratio of a circle's circumference to its diamter [-]
- REAL(dp), PARAMETER ::  TO_RADIANS = PI / 180.0_dp           !< Conversion factor from degrees to radiant [-]
- REAL(dp), PARAMETER ::  TO_DEGREES = 180.0_dp / PI           !< Conversion factor from radians to degrees [-]
-
- ! COSMO-DE parameters
- INTEGER, PARAMETER  ::  WATER_ID = 9                         !< Integer corresponding to the water soil type in COSMO-DE [-]
- REAL(dp), PARAMETER ::  EARTH_RADIUS = 6371229.0_dp          !< Earth radius used in COSMO-DE [m]
- REAL(dp), PARAMETER ::  P_SL = 1e5_dp                        !< Reference pressure for computation of COSMO-DE's basic state pressure [Pa]
- REAL(dp), PARAMETER ::  T_SL = 288.15_dp                     !< Reference temperature for computation of COSMO-DE's basic state pressure [K]
- REAL(dp), PARAMETER ::  BETA = 42.0_dp                       !< logarithmic lapse rate, dT / d ln(p), for computation of COSMO-DE's basic state pressure [K]
- REAL(dp), PARAMETER ::  RD   = 287.05_dp                     !< specific gas constant of dry air, used in computation of COSMO-DE's basic state [J/kg/K]
- REAL(dp), PARAMETER ::  RV   = 461.51_dp                     !< specific gas constant of water vapor [J/kg/K]
- REAL(dp), PARAMETER ::  G    = 9.80665_dp                    !< acceleration of Earth's gravity, used in computation of COSMO-DE's basic state [m/s/s]
- REAL(dp), PARAMETER ::  RHO_L = 1e3_dp                       !< density of liquid water, used to convert W_SO from [kg/m^2] to [m^3/m^3], in [kg/m^3]
- REAL(dp), PARAMETER ::  HECTO = 100_dp                       !< unit conversion factor from hPa to Pa
-
- ! PALM-4U parameters
- REAL(dp), PARAMETER ::  OMEGA   = 7.29e-5_dp                 !< angular velocity of Earth's rotation [s^-1]
- REAL(dp), PARAMETER ::  P_REF   = 1e5_dp                     !< Reference pressure for potential temperature [Pa]
- REAL(dp), PARAMETER ::  RD_PALM = 287.0_dp                   !< specific gas constant of dry air, used in computation of PALM-4U's potential temperature [J/kg/K]
- REAL(dp), PARAMETER ::  CP_PALM = 1005.0_dp                  !< heat capacity of dry air at constant pressure, used in computation of PALM-4U's potential temperature [J/kg/K]
-
- ! INIFOR parameters
- INTEGER, PARAMETER          ::  FILL_ITERATIONS = 5          !< Number of iterations for extrapolating soil data into COSMO-DE water cells [-]
- INTEGER, PARAMETER          ::  FORCING_STEP = 1             !< Number of hours between forcing time steps [h]
- REAL(dp), PARAMETER         ::  NUDGING_TAU = 21600.0_dp     !< Nudging relaxation time scale [s]
- CHARACTER(LEN=*), PARAMETER ::  VERSION = '1.4.0'            !< INIFOR version number
- CHARACTER(LEN=*), PARAMETER ::  COPYRIGHT = 'Copyright 2017-2018 Leibniz Universitaet Hannover' // &
-     NEW_LINE(' ') // ' Copyright 2017-2018 Deutscher Wetterdienst Offenbach' !< Copyright notice
-
- END MODULE defs
Index: palm/trunk/UTIL/inifor/src/get_netcdf_variable.inc
===================================================================
--- palm/trunk/UTIL/inifor/src/get_netcdf_variable.inc	(revision 3401)
+++ 	(revision )
@@ -1,118 +1,0 @@
-!> @file src/get_netcdf_variable.inc
-!------------------------------------------------------------------------------!
-! This file is part of the PALM model system.
-!
-! PALM is free software: you can redistribute it and/or modify it under the
-! terms of the GNU General Public License as published by the Free Software
-! Foundation, either version 3 of the License, or (at your option) any later
-! version.
-!
-! PALM is distributed in the hope that it will be useful, but WITHOUT ANY
-! WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-! A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
-!
-! You should have received a copy of the GNU General Public License along with
-! PALM. If not, see <http://www.gnu.org/licenses/>.
-!
-! Copyright 2017-2018 Leibniz Universitaet Hannover
-! Copyright 2017-2018 Deutscher Wetterdienst Offenbach
-!------------------------------------------------------------------------------!
-!
-! Current revisions:
-! -----------------
-! 
-! 
-! Former revisions:
-! -----------------
-! $Id$
-! Initial revision
-! 
-! 
-! 
-!
-! 
-!
-! Authors:
-! --------
-! @author Eckhard Kadasch
-!
-! Description:
-! ------------
-!> This file provides the implementation of the io.f90 subroutines
-!> get_netcdf_variable_int() and get_netcdf_variable_real(). Both routines
-!> differ only in the type of the netCDF variable to be read and otherwise share
-!> their functionality. In order to avoid duplicating code, both routines source
-!> the implementation below using Fortran's INCLUDE statement.
-!> 
-!------------------------------------------------------------------------------!
- INTEGER ::  i, ncid, start(3)
-
- ! Read in_var NetCDF attributes
- IF ( nf90_open( TRIM(in_file), NF90_NOWRITE, ncid ) .EQ. NF90_NOERR .AND. &
-      nf90_inq_varid( ncid, in_var % name, in_var % varid ) .EQ. NF90_NOERR )  THEN
-
-    CALL check(nf90_get_att(ncid, in_var % varid, "long_name", in_var % long_name))
-    CALL check(nf90_get_att(ncid, in_var % varid, "units", in_var % units))
-
-    ! Read in_var NetCDF dimensions
-    CALL check(nf90_inquire_variable( ncid, in_var % varid,              &
-                                      ndims  = in_var % ndim,            &
-                                      dimids = in_var % dimids ))
-                                  
-    DO i = 1, in_var % ndim
-       CALL check(nf90_inquire_dimension( ncid, in_var % dimids(i),      &
-                                          name = in_var % dimname(i),    &
-                                          len  = in_var % dimlen(i) ))
-    END DO
-
-    start = (/ 1, 1, 1 /)
-    IF ( TRIM(in_var % name) .EQ. 'T_SO' )  THEN
-       ! Skip depth = 0.0 for T_SO and reduce number of depths from 9 to 8
-       in_var % dimlen(3) = in_var % dimlen(3) - 1
-
-       ! Start reading from second level, e.g. depth = 0.005 instead of 0.0
-       start(3) = 2
-    END IF
-
-    SELECT CASE(in_var % ndim)
-
-    CASE (2)
-
-       ALLOCATE( buffer( in_var % dimlen(1),                             &
-                         in_var % dimlen(2),                             &
-                         1 ) )
-
-    CASE (3, 4)
-
-       ALLOCATE( buffer( in_var % dimlen(1),                             &
-                         in_var % dimlen(2),                             &
-                         in_var % dimlen(3) ) )
-
-    CASE DEFAULT
-
-       message = "Failed reading NetCDF variable " //                    &
-          TRIM(in_var % name) // " with " // TRIM(str(in_var%ndim)) //   &
-          " dimensions because only two- and and three-dimensional" //   &
-          " variables are supported."
-       CALL abort('get_netcdf_variable', message) 
-
-    END SELECT
- CALL run_control('time', 'alloc')
-          
-    ! TODO: Check for matching dimensions of buffer and var
-    CALL check(nf90_get_var( ncid, in_var % varid, buffer,               &
-                             start = start,                              &
-                             count = in_var % dimlen(1:3) ) )
-
- CALL run_control('time', 'read')
- ELSE
-
-    message = "Failed to read '" // TRIM(in_var % name) // &
-       "' from file '" // TRIM(in_file) // "'."
-    CALL report('get_netcdf_variable', message)
-
- END IF
-
- CALL check(nf90_close(ncid))
-
- CALL run_control('time', 'read')
Index: palm/trunk/UTIL/inifor/src/grid.f90
===================================================================
--- palm/trunk/UTIL/inifor/src/grid.f90	(revision 3401)
+++ 	(revision )
@@ -1,3924 +1,0 @@
-!> @file src/grid.f90
-!------------------------------------------------------------------------------!
-! This file is part of the PALM model system.
-!
-! PALM is free software: you can redistribute it and/or modify it under the
-! terms of the GNU General Public License as published by the Free Software
-! Foundation, either version 3 of the License, or (at your option) any later
-! version.
-!
-! PALM is distributed in the hope that it will be useful, but WITHOUT ANY
-! WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-! A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
-!
-! You should have received a copy of the GNU General Public License along with
-! PALM. If not, see <http://www.gnu.org/licenses/>.
-!
-! Copyright 2017-2018 Leibniz Universitaet Hannover
-! Copyright 2017-2018 Deutscher Wetterdienst Offenbach
-!------------------------------------------------------------------------------!
-!
-! Current revisions:
-! -----------------
-! 
-! 
-! Former revisions:
-! -----------------
-! $Id$
-! Added computation of geostrophic winds form COSMO pressure fields
-! Introduced averaging grids and internal 'output' variables for computation of
-!     geostrophic and large-scale forcings
-! Merged qv, uv and vg output variables and 'temperature' IO group into new
-!     'thermodynamics' IP group
-! Cleaned up terminal output, show some messages only with --debug option
-! Improved variable naming and readability
-! 
-! 
-! 3183 2018-07-27 14:25:55Z suehring
-! Introduced new PALM grid stretching
-! Updated variable names and metadata for PIDS v1.9 compatibility
-! Better compatibility with older Intel compilers:
-! - avoiding implicit array allocation with new get_netcdf_variable()
-!   subroutine instead of function
-! Improved command line interface:
-! - Produce forcing variables when '-mode profile' is being used
-! - Renamend initial-condition mode variable 'mode' to 'ic_mode'
-! - Improved handling of the start date string
-! Removed unnecessary variables and routines
-!
-! 
-! 3182 2018-07-27 13:36:03Z suehring
-! Initial revision
-!
-! 
-!
-! Authors:
-! --------
-! @author Eckhard Kadasch
-!
-!------------------------------------------------------------------------------!
-! Description:
-! ------------
-!> The grid module contains all variables and routines to specify and work with
-!> the numerical grids in INIFOR. By convention, all angles are stored in
-!> radians.
-!------------------------------------------------------------------------------!
-
- MODULE grid
-
-    USE control
-    USE defs,                                                                  &
-        ONLY:  DATE, EARTH_RADIUS, TO_RADIANS, TO_DEGREES, PI, dp, hp, sp,     &
-               SNAME, LNAME, PATH, FORCING_STEP, WATER_ID, FILL_ITERATIONS,    &
-               BETA, P_SL, T_SL, BETA, RD, RV, G, P_REF, RD_PALM, CP_PALM,     &
-               RHO_L, OMEGA, HECTO
-    USE io,                                                                    &
-        ONLY:  get_netcdf_variable, get_netcdf_attribute,                      &
-               parse_command_line_arguments, validate_config
-    USE netcdf,                                                                &
-        ONLY:  NF90_MAX_NAME, NF90_MAX_VAR_DIMS
-    USE transform,                                                             &
-        ONLY:  average_2d, rotate_to_cosmo, find_horizontal_neighbours,&
-               compute_horizontal_interp_weights,                              &
-               find_vertical_neighbours_and_weights_interp,                    &
-               find_vertical_neighbours_and_weights_average, interpolate_2d,   &
-               gamma_from_hemisphere, phic_to_phin, lamc_to_lamn,              &
-               project, centre_velocities, phi2phirot, rla2rlarot, uv2uvrot,   &
-               phirot2phi, rlarot2rla
-    USE types
-    USE util
-    
-    IMPLICIT NONE
-    
-    SAVE
-    
-    REAL(dp) ::  averaging_angle   = 0.0_dp       !< latitudal and longitudal width of averaging regions [rad]
-    REAL(dp) ::  averaging_width_ns = 0.0_dp       !< longitudal width of averaging regions [m]
-    REAL(dp) ::  averaging_width_ew = 0.0_dp       !< latitudal width of averaging regions [m]
-    REAL(dp) ::  phi_equat         = 0.0_dp       !< latitude of rotated equator of COSMO-DE grid [rad]
-    REAL(dp) ::  phi_n             = 0.0_dp       !< latitude of rotated pole of COSMO-DE grid [rad]
-    REAL(dp) ::  lambda_n          = 0.0_dp       !< longitude of rotaded pole of COSMO-DE grid [rad]
-    REAL(dp) ::  phi_c             = 0.0_dp       !< rotated-grid latitude of the center of the PALM domain [rad]
-    REAL(dp) ::  lambda_c          = 0.0_dp       !< rotated-grid longitude of the centre of the PALM domain [rad]
-    REAL(dp) ::  phi_cn            = 0.0_dp       !< latitude of the rotated pole relative to the COSMO-DE grid [rad]
-    REAL(dp) ::  lambda_cn         = 0.0_dp       !< longitude of the rotated pole relative to the COSMO-DE grid [rad]
-    REAL(dp) ::  lam_centre        = 0.0_dp       !< longitude of the PLAM domain centre in the source (COSMO rotated-pole) system [rad]
-    REAL(dp) ::  phi_centre        = 0.0_dp       !< latitude of the PLAM domain centre in the source (COSMO rotated-pole) system [rad]
-    REAL(dp) ::  lam_east          = 0.0_dp       !< longitude of the east central-averaging-domain boundary in the source (COSMO rotated-pole) system [rad]
-    REAL(dp) ::  lam_west          = 0.0_dp       !< longitude of the west central-averaging-domain boundary in the source (COSMO rotated-pole) system [rad]
-    REAL(dp) ::  phi_north         = 0.0_dp       !< latitude of the north central-averaging-domain boundary in the source (COSMO rotated-pole) system [rad]
-    REAL(dp) ::  phi_south         = 0.0_dp       !< latitude of the south central-averaging-domain boundary in the source (COSMO rotated-pole) system [rad]
-    REAL(dp) ::  gam               = 0.0_dp       !< angle for working around phirot2phi/rlarot2rla bug
-    REAL(dp) ::  dx                = 0.0_dp       !< PALM-4U grid spacing in x direction [m]
-    REAL(dp) ::  dy                = 0.0_dp       !< PALM-4U grid spacing in y direction [m]
-    REAL(dp) ::  dz(10)            = -1.0_dp      !< PALM-4U grid spacing in z direction [m]
-    REAL(dp) ::  dz_max            = 1000.0_dp    !< maximum vertical grid spacing [m]
-    REAL(dp) ::  dz_stretch_factor = 1.08_dp      !< factor for vertical grid stretching [m]
-    REAL(dp) ::  dz_stretch_level  = -9999999.9_dp!< height above which the vertical grid will be stretched [m]
-    REAL(dp) ::  dz_stretch_level_start(9) = -9999999.9_dp !< namelist parameter
-    REAL(dp) ::  dz_stretch_level_end(9) = 9999999.9_dp !< namelist parameter
-    REAL(dp) ::  dz_stretch_factor_array(9) = 1.08_dp !< namelist parameter
-    REAL(dp) ::  dxi               = 0.0_dp       !< inverse PALM-4U grid spacing in x direction [m^-1]
-    REAL(dp) ::  dyi               = 0.0_dp       !< inverse PALM-4U grid spacing in y direction [m^-1]
-    REAL(dp) ::  dzi               = 0.0_dp       !< inverse PALM-4U grid spacing in z direction [m^-1]
-    REAL(dp) ::  f3                = 0.0_dp       !< Coriolis parameter
-    REAL(dp) ::  lx                = 0.0_dp       !< PALM-4U domain size in x direction [m]
-    REAL(dp) ::  ly                = 0.0_dp       !< PALM-4U domain size in y direction [m]
-    REAL(dp) ::  p0                = 0.0_dp       !< PALM-4U surface pressure, at z0 [Pa]
-    REAL(dp) ::  x0                = 0.0_dp       !< x coordinate of PALM-4U Earth tangent [m] 
-    REAL(dp) ::  y0                = 0.0_dp       !< y coordinate of PALM-4U Earth tangent [m] 
-    REAL(dp) ::  z0                = 0.0_dp       !< Elevation of the PALM-4U domain above sea level [m]
-    REAL(dp) ::  z_top             = 0.0_dp       !< height of the scalar top boundary [m]
-    REAL(dp) ::  zw_top            = 0.0_dp       !< height of the vertical velocity top boundary [m]
-    REAL(dp) ::  lonmin            = 0.0_dp       !< Minimunm longitude of COSMO-DE's rotated-pole grid
-    REAL(dp) ::  lonmax            = 0.0_dp       !< Maximum longitude of COSMO-DE's rotated-pole grid
-    REAL(dp) ::  latmin            = 0.0_dp       !< Minimunm latitude of COSMO-DE's rotated-pole grid
-    REAL(dp) ::  latmax            = 0.0_dp       !< Maximum latitude of COSMO-DE's rotated-pole grid
-    REAL(dp) ::  latitude          = 0.0_dp       !< geographical latitude of the PALM-4U origin, from inipar namelist [deg]
-    REAL(dp) ::  longitude         = 0.0_dp       !< geographical longitude of the PALM-4U origin, from inipar namelist [deg]
-    REAL(dp) ::  origin_lat        = 0.0_dp       !< geographical latitude of the PALM-4U origin, from static driver netCDF file [deg]
-    REAL(dp) ::  origin_lon        = 0.0_dp       !< geographical longitude of the PALM-4U origin, from static driver netCDF file [deg]
-    REAL(dp) ::  rotation_angle    = 0.0_dp       !< clockwise angle the PALM-4U north is rotated away from geographical north [deg]
-    REAL(dp) ::  end_time          = 0.0_dp       !< PALM-4U simulation time [s]
-
-    REAL(dp), DIMENSION(:,:,:), ALLOCATABLE, TARGET ::  hhl             !< heights of half layers (cell faces) above sea level in COSMO-DE, read in from external file
-    REAL(dp), DIMENSION(:,:,:), ALLOCATABLE, TARGET ::  hfl             !< heights of full layers (cell centres) above sea level in COSMO-DE, computed as arithmetic average of hhl
-    REAL(dp), DIMENSION(:), ALLOCATABLE, TARGET     ::  depths          !< COSMO-DE's TERRA-ML soil layer depths
-    REAL(dp), DIMENSION(:), ALLOCATABLE, TARGET     ::  d_depth_rho_inv !< COSMO-DE's TERRA-ML soil layer thicknesses
-    REAL(dp), DIMENSION(:), ALLOCATABLE, TARGET     ::  rlon            !< longitudes of COSMO-DE's rotated-pole grid
-    REAL(dp), DIMENSION(:), ALLOCATABLE, TARGET     ::  rlat            !< latitudes of COSMO-DE's rotated-pole grid
-    REAL(dp), DIMENSION(:), ALLOCATABLE, TARGET     ::  time            !< output times 
-    REAL(dp), DIMENSION(:), ALLOCATABLE, TARGET     ::  x               !< base palm grid x coordinate vector pointed to by grid_definitions
-    REAL(dp), DIMENSION(:), ALLOCATABLE, TARGET     ::  xu              !< base palm grid xu coordinate vector pointed to by grid_definitions
-    REAL(dp), DIMENSION(:), ALLOCATABLE, TARGET     ::  y               !< base palm grid y coordinate vector pointed to by grid_definitions
-    REAL(dp), DIMENSION(:), ALLOCATABLE, TARGET     ::  yv              !< base palm grid yv coordinate vector pointed to by grid_definitions
-    REAL(dp), DIMENSION(:), ALLOCATABLE, TARGET     ::  z_column        !< base palm grid z coordinate vector including the top boundary coordinate (entire column)
-    REAL(dp), DIMENSION(:), ALLOCATABLE, TARGET     ::  zw_column       !< base palm grid zw coordinate vector including the top boundary coordinate (entire column)
-    REAL(dp), DIMENSION(:), ALLOCATABLE, TARGET     ::  z               !< base palm grid z coordinate vector pointed to by grid_definitions
-    REAL(dp), DIMENSION(:), ALLOCATABLE, TARGET     ::  zw              !< base palm grid zw coordinate vector pointed to by grid_definitions
-
-    INTEGER(hp), DIMENSION(:,:,:), ALLOCATABLE, TARGET ::  soiltyp      !< COSMO-DE soil type map
-    INTEGER ::  dz_stretch_level_end_index(9)               !< vertical grid level index until which the vertical grid spacing is stretched
-    INTEGER ::  dz_stretch_level_start_index(9)             !< vertical grid level index above which the vertical grid spacing is stretched
-    INTEGER ::  nt    !< number of output time steps
-    INTEGER ::  nx    !< number of PALM-4U grid points in x direction
-    INTEGER ::  ny    !< number of PALM-4U grid points in y direction
-    INTEGER ::  nz    !< number of PALM-4U grid points in z direction
-    INTEGER ::  nlon  !< number of longitudal points in target grid (COSMO-DE)
-    INTEGER ::  nlat  !< number of latitudal points in target grid (COSMO-DE)
-    INTEGER ::  nlev  !< number of levels in target grid (COSMO-DE)
-    INTEGER ::  layers !< number of COSMO-DE soil layers
-    INTEGER ::  start_hour_flow         !< start of flow forcing in number of hours relative to start_date
-    INTEGER ::  start_hour_soil         !< start of soil forcing in number of hours relative to start_date, typically equals start_hour_flow
-    INTEGER ::  start_hour_radiation    !< start of radiation forcing in number of hours relative to start_date, 0 to 2 hours before start_hour_flow to reconstruct hourly averages from one- to three hourly averages of the input data
-    INTEGER ::  start_hour_soilmoisture !< start of forcing for the soil moisture spin-up in number of hours relative to start_date, typically -672 (-4 weeks)
-    INTEGER ::  end_hour  !< simulation time in hours
-    INTEGER ::  end_hour_soilmoisture  !< end of soil moisture spin-up in hours relative to start_hour_flow
-    INTEGER ::  step_hour !< number of hours between forcing time steps
-
-    LOGICAL ::  init_variables_required
-    LOGICAL ::  boundary_variables_required
-    LOGICAL ::  ls_forcing_variables_required
-    LOGICAL ::  profile_grids_required
-
-    TYPE(nc_var), ALLOCATABLE, TARGET ::  input_var_table(:)  !< table of input variables
-    TYPE(nc_var), ALLOCATABLE, TARGET ::  output_var_table(:) !< table of input variables
-    TYPE(nc_var)                      ::  cosmo_var           !< COSMO-DE dummy variable, used for reading HHL, rlon, rlat
-
-    TYPE(grid_definition), TARGET ::  palm_grid                       !< PALM-4U grid in the target system (COSMO-DE rotated-pole)
-    TYPE(grid_definition), TARGET ::  palm_intermediate               !< PALM-4U grid with coarse vertical grid wiht levels interpolated from COSMO-DE grid
-    TYPE(grid_definition), TARGET ::  cosmo_grid                      !< target system (COSMO-DE rotated-pole)
-    TYPE(grid_definition), TARGET ::  scalars_east_grid               !< 
-    TYPE(grid_definition), TARGET ::  scalars_west_grid               !< 
-    TYPE(grid_definition), TARGET ::  scalars_north_grid              !< 
-    TYPE(grid_definition), TARGET ::  scalars_south_grid              !< 
-    TYPE(grid_definition), TARGET ::  scalars_top_grid                !< 
-    TYPE(grid_definition), TARGET ::  scalars_east_intermediate       !< 
-    TYPE(grid_definition), TARGET ::  scalars_west_intermediate       !< 
-    TYPE(grid_definition), TARGET ::  scalars_north_intermediate      !< 
-    TYPE(grid_definition), TARGET ::  scalars_south_intermediate      !< 
-    TYPE(grid_definition), TARGET ::  scalars_top_intermediate        !< 
-    TYPE(grid_definition), TARGET ::  u_initial_grid                  !< 
-    TYPE(grid_definition), TARGET ::  u_east_grid                     !< 
-    TYPE(grid_definition), TARGET ::  u_west_grid                     !< 
-    TYPE(grid_definition), TARGET ::  u_north_grid                    !< 
-    TYPE(grid_definition), TARGET ::  u_south_grid                    !< 
-    TYPE(grid_definition), TARGET ::  u_top_grid                      !< 
-    TYPE(grid_definition), TARGET ::  u_initial_intermediate          !<
-    TYPE(grid_definition), TARGET ::  u_east_intermediate             !< 
-    TYPE(grid_definition), TARGET ::  u_west_intermediate             !< 
-    TYPE(grid_definition), TARGET ::  u_north_intermediate            !< 
-    TYPE(grid_definition), TARGET ::  u_south_intermediate            !< 
-    TYPE(grid_definition), TARGET ::  u_top_intermediate              !< 
-    TYPE(grid_definition), TARGET ::  v_initial_grid                  !< 
-    TYPE(grid_definition), TARGET ::  v_east_grid                     !< 
-    TYPE(grid_definition), TARGET ::  v_west_grid                     !< 
-    TYPE(grid_definition), TARGET ::  v_north_grid                    !< 
-    TYPE(grid_definition), TARGET ::  v_south_grid                    !< 
-    TYPE(grid_definition), TARGET ::  v_top_grid                      !< 
-    TYPE(grid_definition), TARGET ::  v_initial_intermediate          !<
-    TYPE(grid_definition), TARGET ::  v_east_intermediate             !< 
-    TYPE(grid_definition), TARGET ::  v_west_intermediate             !< 
-    TYPE(grid_definition), TARGET ::  v_north_intermediate            !< 
-    TYPE(grid_definition), TARGET ::  v_south_intermediate            !< 
-    TYPE(grid_definition), TARGET ::  v_top_intermediate              !< 
-    TYPE(grid_definition), TARGET ::  w_initial_grid                  !< 
-    TYPE(grid_definition), TARGET ::  w_east_grid                     !< 
-    TYPE(grid_definition), TARGET ::  w_west_grid                     !< 
-    TYPE(grid_definition), TARGET ::  w_north_grid                    !< 
-    TYPE(grid_definition), TARGET ::  w_south_grid                    !< 
-    TYPE(grid_definition), TARGET ::  w_top_grid                      !< 
-    TYPE(grid_definition), TARGET ::  w_initial_intermediate          !<
-    TYPE(grid_definition), TARGET ::  w_east_intermediate             !< 
-    TYPE(grid_definition), TARGET ::  w_west_intermediate             !< 
-    TYPE(grid_definition), TARGET ::  w_north_intermediate            !< 
-    TYPE(grid_definition), TARGET ::  w_south_intermediate            !< 
-    TYPE(grid_definition), TARGET ::  w_top_intermediate              !< 
-
-    TYPE(grid_definition), TARGET ::  north_averaged_scalar_profile
-    TYPE(grid_definition), TARGET ::  south_averaged_scalar_profile
-    TYPE(grid_definition), TARGET ::  west_averaged_scalar_profile
-    TYPE(grid_definition), TARGET ::  east_averaged_scalar_profile
-    TYPE(grid_definition), TARGET ::  averaged_scalar_profile
-    TYPE(grid_definition), TARGET ::  averaged_w_profile
-
-    TYPE(io_group), ALLOCATABLE, TARGET ::  io_group_list(:)  !< List of I/O groups, which group together output variables that share the same input variable
- 
-    NAMELIST /inipar/ nx, ny, nz, dx, dy, dz, longitude, latitude,             &
-                      dz_max, dz_stretch_factor, dz_stretch_level,             & !< old grid stretching parameters
-                      dz_stretch_level_start, dz_stretch_level_end               !< new grid stretching parameters
-    NAMELIST /d3par/  end_time
-    
-    CHARACTER(LEN=LNAME) ::  nc_source_text     = ''  !< Text describing the source of the output data, e.g. 'COSMO-DE analysis from ...'
-    CHARACTER(LEN=PATH), ALLOCATABLE, DIMENSION(:) ::  flow_files
-    CHARACTER(LEN=PATH), ALLOCATABLE, DIMENSION(:) ::  soil_moisture_files
-    CHARACTER(LEN=PATH), ALLOCATABLE, DIMENSION(:) ::  soil_files
-    CHARACTER(LEN=PATH), ALLOCATABLE, DIMENSION(:) ::  radiation_files
-    CHARACTER(LEN=SNAME) ::  input_prefix         !< Prefix of input files, e.g. 'laf' for COSMO-DE analyses
-    CHARACTER(LEN=SNAME) ::  flow_prefix          !< Prefix of flow input files, e.g. 'laf' for COSMO-DE analyses
-    CHARACTER(LEN=SNAME) ::  soil_prefix          !< Prefix of soil input files, e.g. 'laf' for COSMO-DE analyses
-    CHARACTER(LEN=SNAME) ::  radiation_prefix     !< Prefix of radiation input files, e.g. 'laf' for COSMO-DE analyses
-    CHARACTER(LEN=SNAME) ::  soilmoisture_prefix  !< Prefix of input files for soil moisture spin-up, e.g. 'laf' for COSMO-DE analyses
-    CHARACTER(LEN=SNAME) ::  flow_suffix          !< Suffix of flow input files, e.g. 'flow'
-    CHARACTER(LEN=SNAME) ::  soil_suffix          !< Suffix of soil input files, e.g. 'soil'
-    CHARACTER(LEN=SNAME) ::  radiation_suffix     !< Suffix of radiation input files, e.g. 'radiation'
-    CHARACTER(LEN=SNAME) ::  soilmoisture_suffix  !< Suffix of input files for soil moisture spin-up, e.g. 'soilmoisture'
-                          
-    TYPE(nc_file) ::  output_file
-
-    TYPE(inifor_config) ::  cfg !< Container of INIFOR configuration
-
- CONTAINS
-    
-    SUBROUTINE setup_parameters()
-       INTEGER ::  k
-
-!
-!------------------------------------------------------------------------------
-! Section 1: Define default parameters
-!------------------------------------------------------------------------------
-       cfg % start_date = '2013072100'
-       end_hour = 2
-       start_hour_soil = -2
-       start_hour_soilmoisture = - (4 * 7 * 24) - 2
-
-       lonmin =  -5.0_dp * TO_RADIANS
-       lonmax =   5.5_dp * TO_RADIANS
-       latmin =  -5.0_dp * TO_RADIANS
-       latmax =   6.5_dp * TO_RADIANS
-
-       ! COSMO-DE default rotated pole
-       phi_n     =   40.0_dp * TO_RADIANS
-       phi_equat =   50.0_dp * TO_RADIANS
-       lambda_n  = -170.0_dp * TO_RADIANS
-
-       ! COMSMO-DE soil layers
-       layers = 8    
-       ALLOCATE( depths(layers), d_depth_rho_inv(layers) )
-       depths = (/0.005_dp, 0.02_dp, 0.06_dp, 0.18_dp, 0.54_dp, 1.62_dp, 4.86_dp, 14.58_dp/)
-       d_depth_rho_inv = 1.0_dp / &
-          ( (/0.01_dp, 0.02_dp, 0.06_dp, 0.18_dp, 0.54_dp, 1.62_dp, 4.86_dp, 14.58_dp/) * RHO_L )
-
-       ! Defaultmain centre (_c) of the PALM-4U grid in the geographical system (_g)
-       origin_lat = 52.325079_dp * TO_RADIANS ! south-west of Berlin, origin used for the Dec 2017 showcase simulation
-       origin_lon = 13.082744_dp * TO_RADIANS
-       cfg % z0 = 35.0_dp
-
-       ! Default atmospheric parameters
-       cfg % ug = 0.0_dp
-       cfg % vg = 0.0_dp
-       cfg % p0 = P_SL
-
-       ! Parameters for file names
-       start_hour_flow = 0
-       start_hour_soil = 0
-       start_hour_radiation = 0
-       start_hour_soilmoisture = start_hour_flow - 2
-       end_hour_soilmoisture = start_hour_flow
-       step_hour = FORCING_STEP
-
-       input_prefix = 'laf'  ! 'laf' for COSMO-DE analyses
-       cfg % flow_prefix = input_prefix
-       cfg % input_prefix = input_prefix
-       cfg % soil_prefix = input_prefix
-       cfg % radiation_prefix = input_prefix
-       cfg % soilmoisture_prefix  = input_prefix
-
-       flow_suffix = '-flow'
-       soil_suffix = '-soil'
-       radiation_suffix = '-rad'
-       soilmoisture_suffix = '-soilmoisture'
-
-       cfg % debug = .FALSE.
-       cfg % averaging_angle = 2.0_dp
-!
-!------------------------------------------------------------------------------
-! Section 2: Read command-line arguments, namelist, and grid parameters
-!------------------------------------------------------------------------------
-
-       ! Set default paths and modes
-       cfg % input_path         = './'
-       cfg % hhl_file           = ''
-       cfg % soiltyp_file       = ''
-       cfg % namelist_file      = './namelist'
-       cfg % static_driver_file = ''
-       cfg % output_file = './palm-4u-input.nc'
-       cfg % ic_mode = 'volume'
-       cfg % bc_mode = 'real'
-       cfg % averaging_mode = 'level'
-
-       ! Overwrite defaults with user configuration
-       CALL parse_command_line_arguments( cfg )
-
-       flow_prefix = TRIM(cfg % input_prefix)
-       radiation_prefix = TRIM(cfg % input_prefix)
-       soil_prefix = TRIM(cfg % input_prefix)
-       soilmoisture_prefix = TRIM(cfg % input_prefix)
-       IF (cfg % flow_prefix_is_set)  flow_prefix = TRIM(cfg % flow_prefix)
-       IF (cfg % radiation_prefix_is_set)  radiation_prefix = TRIM(cfg % radiation_prefix)
-       IF (cfg % soil_prefix_is_set)  soil_prefix = TRIM(cfg % soil_prefix)
-       IF (cfg % soilmoisture_prefix_is_set)  soilmoisture_prefix = TRIM(cfg % soilmoisture_prefix)
-
-       output_file % name = cfg % output_file
-       z0 = cfg % z0
-       p0 = cfg % p0
-
-       init_variables_required = .TRUE.
-       boundary_variables_required = TRIM( cfg % bc_mode ) == 'real'
-       ls_forcing_variables_required = TRIM( cfg % bc_mode ) == 'ideal'
-
-       IF ( ls_forcing_variables_required )  THEN
-          message = "Averaging of large-scale forcing profiles " //            &
-                    "has not been implemented, yet."
-          CALL abort('setup_parameters', message)
-       END IF
-
-
-       ! Set default file paths, if not specified by user.
-       CALL normalize_path(cfg % input_path)
-       IF (TRIM(cfg % hhl_file) == '')  cfg % hhl_file = TRIM(cfg % input_path) // 'hhl.nc'
-       IF (TRIM(cfg % soiltyp_file) == '')  cfg % soiltyp_file = TRIM(cfg % input_path) // 'soil.nc'
-
-       CALL validate_config( cfg ) 
-
-       CALL report('setup_parameters', "initialization mode: " // TRIM(cfg % ic_mode))
-       CALL report('setup_parameters', "       forcing mode: " // TRIM(cfg % bc_mode))
-       CALL report('setup_parameters', "          data path: " // TRIM(cfg % input_path))
-       CALL report('setup_parameters', "           hhl file: " // TRIM(cfg % hhl_file))
-       CALL report('setup_parameters', "       soiltyp file: " // TRIM(cfg % soiltyp_file))
-       CALL report('setup_parameters', "      namelist file: " // TRIM(cfg % namelist_file))
-       CALL report('setup_parameters', "   output data file: " // TRIM(output_file % name))
-
- CALL run_control('time', 'init')
-       ! Read in namelist parameters
-       OPEN(10, FILE=cfg % namelist_file)
-       READ(10, NML=inipar) ! nx, ny, nz, dx, dy, dz
-       READ(10, NML=d3par)  ! end_time
-       CLOSE(10)
- CALL run_control('time', 'read')
-
-       end_hour = CEILING( end_time / 3600.0 * step_hour )
-
-       ! Generate input file lists
-       CALL get_input_file_list(                                               &
-          cfg % start_date, start_hour_flow, end_hour, step_hour,              &
-          cfg % input_path, flow_prefix, flow_suffix, flow_files)
-       CALL get_input_file_list(                                               &
-          cfg % start_date, start_hour_soil, end_hour, step_hour,              &
-          cfg % input_path, soil_prefix, soil_suffix, soil_files)
-       CALL get_input_file_list(                                               &
-          cfg % start_date, start_hour_radiation, end_hour, step_hour,         &
-          cfg % input_path, radiation_prefix, radiation_suffix, radiation_files)
-       CALL get_input_file_list(                                               &
-          cfg % start_date, start_hour_soilmoisture, end_hour_soilmoisture, step_hour, &
-          cfg % input_path, soilmoisture_prefix, soilmoisture_suffix, soil_moisture_files)
-
-!
-!------------------------------------------------------------------------------
-! Section 3: Check for consistency
-!------------------------------------------------------------------------------
-
-!
-!------------------------------------------------------------------------------
-! Section 4: Compute additional parameters
-!------------------------------------------------------------------------------
-!------------------------------------------------------------------------------
-! Section 4.1: COSMO-DE parameters
-!------------------------------------------------------------------------------
-
-
- CALL run_control('time', 'init')
-       ! Read COSMO-DE soil type map
-       cosmo_var % name = 'SOILTYP'
-       CALL get_netcdf_variable(cfg % soiltyp_file, cosmo_var, soiltyp)
-
-       message = 'Reading PALM-4U origin from'
-       IF (TRIM(cfg % static_driver_file) .NE. '')  THEN
-
-          origin_lon = get_netcdf_attribute(cfg % static_driver_file, 'origin_lon')
-          origin_lat = get_netcdf_attribute(cfg % static_driver_file, 'origin_lat')
-
-          message = TRIM(message) // " static driver file '"                   &
-                                  // TRIM(cfg % static_driver_file) // "'"
-
-
-       ELSE
-
-          origin_lon = longitude
-          origin_lat = latitude
-
-          message = TRIM(message) // " namlist file '"                         &
-                                  // TRIM(cfg % namelist_file) // "'"
-
-       END IF
-       origin_lon = origin_lon * TO_RADIANS
-       origin_lat = origin_lat * TO_RADIANS
-
-       CALL report('setup_parameters', message)
-
-
-       ! Read in COSMO-DE heights of half layers (vertical cell faces)
-       cosmo_var % name = 'HHL'
-       CALL get_netcdf_variable(cfg % hhl_file, cosmo_var, hhl)
- CALL run_control('time', 'read')
-
-       CALL reverse(hhl)
-       nlon = SIZE(hhl, 1)
-       nlat = SIZE(hhl, 2)
-       nlev = SIZE(hhl, 3)
-
- CALL run_control('time', 'comp')
-
-       ! Appoximate COSMO-DE heights of full layers (cell centres)
-       ALLOCATE( hfl(nlon, nlat, nlev-1) )
- CALL run_control('time', 'alloc')
-       DO k = 1, nlev-1
-          hfl(:,:,k) = 0.5_dp * ( hhl(:,:,k) +                                 &
-                                  hhl(:,:,k+1) )
-       END DO
-
-!------------------------------------------------------------------------------
-! Section 4.2: PALM-4U parameters
-!------------------------------------------------------------------------------
-       ! PALM-4U domain extents
-       lx = (nx+1) * dx
-       ly = (ny+1) * dy
-       
-       ! PALM-4U point of Earth tangency
-       x0 = 0.0_dp
-       y0 = 0.0_dp
-
-       ! time vector
-       nt = CEILING(end_time / (step_hour * 3600.0_dp)) + 1
-       ALLOCATE( time(nt) )
-       CALL linspace(0.0_dp, 3600.0_dp * (nt-1), time)
-       output_file % time => time
- CALL run_control('time', 'init')
-
-! Convert the PALM-4U origin coordinates to COSMO's rotated-pole grid
-       phi_c    = TO_RADIANS *                                                 &
-                  phi2phirot( origin_lat * TO_DEGREES, origin_lon * TO_DEGREES,&
-                              phi_n * TO_DEGREES, lambda_n * TO_DEGREES )
-       lambda_c = TO_RADIANS *                                                 &
-                  rla2rlarot( origin_lat * TO_DEGREES, origin_lon * TO_DEGREES,&
-                              phi_n * TO_DEGREES, lambda_n * TO_DEGREES,     &
-                              0.0_dp )
-
-! Set gamma according to whether PALM domain is in the northern or southern
-! hemisphere of the COSMO-DE rotated-pole system. Gamma assumes either the
-! value 0 or PI and is needed to work around around a bug in the rotated-pole
-! coordinate transformations.
-       gam = gamma_from_hemisphere(origin_lat, phi_equat)
-
-! Compute the north pole of the rotated-pole grid centred at the PALM-4U domain
-! centre. The resulting (phi_cn, lambda_cn) are coordinates in COSMO-DE's
-! rotated-pole grid.
-       phi_cn    = phic_to_phin(phi_c) 
-       lambda_cn = lamc_to_lamn(phi_c, lambda_c) 
-
-       message =   "PALM-4U origin:" // NEW_LINE('') // &
-          "           lon (lambda) = " // &
-          TRIM(real_to_str_f(origin_lon * TO_DEGREES)) // " deg"// NEW_LINE(' ') //&
-          "           lat (phi   ) = " // &
-          TRIM(real_to_str_f(origin_lat * TO_DEGREES)) // " deg (geographical)" // NEW_LINE(' ') //&
-          "           lon (lambda) = " // &
-          TRIM(real_to_str_f(lambda_c * TO_DEGREES)) // " deg" // NEW_LINE(' ') // &
-          "           lat (phi   ) = " // &
-          TRIM(real_to_str_f(phi_c * TO_DEGREES)) // " deg (COSMO-DE rotated-pole)"
-      CALL report ('setup_parameters', message)
-
-       message = "North pole of the rotated COSMO-DE system:" // NEW_LINE(' ') // &
-          "           lon (lambda) = " // &
-          TRIM(real_to_str_f(lambda_n * TO_DEGREES)) // " deg" // NEW_LINE(' ') //&
-          "           lat (phi   ) = " // &
-          TRIM(real_to_str_f(phi_n * TO_DEGREES)) // " deg (geographical)"
-       CALL report ('setup_parameters', message)
-          
-       message = "North pole of the rotated palm system:" // NEW_LINE(' ') // &
-          "           lon (lambda) = " // &
-          TRIM(real_to_str_f(lambda_cn * TO_DEGREES)) // " deg" // NEW_LINE(' ') // &
-          "           lat (phi   ) = " // &
-          TRIM(real_to_str_f(phi_cn * TO_DEGREES)) // " deg (COSMO-DE rotated-pole)"
-       CALL report ('setup_parameters', message)
-
- CALL run_control('time', 'comp')
-
-!------------------------------------------------------------------------------
-! Section 4.3: INIFOR averaging domains
-!------------------------------------------------------------------------------
-
-    ! Compute coordiantes of the PALM centre in the source (COSMO) system
-    phi_centre = phirot2phi(                                                   &
-       phirot = project(0.5_dp*ly, y0, EARTH_RADIUS) * TO_DEGREES,             &
-       rlarot = project(0.5_dp*lx, x0, EARTH_RADIUS) * TO_DEGREES,             &
-       polphi = phi_cn * TO_DEGREES, pollam = lambda_cn * TO_DEGREES,          &
-       polgam = gam * TO_DEGREES                                               &
-    ) * TO_RADIANS
-
-    lam_centre = rlarot2rla(                                                   &
-       phirot = project(0.5_dp*ly, y0, EARTH_RADIUS) * TO_DEGREES,             &
-       rlarot = project(0.5_dp*lx, x0, EARTH_RADIUS) * TO_DEGREES,             &
-       polphi = phi_cn * TO_DEGREES, pollam = lambda_cn * TO_DEGREES,          &
-       polgam = gam * TO_DEGREES                                               &
-    ) * TO_RADIANS
-
-    message = "PALM-4U centre:" // NEW_LINE('') // &
-       "           lon (lambda) = " // &
-       TRIM(real_to_str_f(lam_centre * TO_DEGREES)) // " deg" // NEW_LINE(' ') // &
-       "           lat (phi   ) = " // &
-       TRIM(real_to_str_f(phi_centre * TO_DEGREES)) // " deg (COSMO-DE rotated-pole)"
-    CALL report( 'setup_parameters', message )
-
-
-    ! Compute boundaries of the central averaging box
-    averaging_angle = cfg % averaging_angle * TO_RADIANS
-    lam_east = lam_centre + 0.5_dp * averaging_angle
-    lam_west = lam_centre - 0.5_dp * averaging_angle
-    phi_north = phi_centre + 0.5_dp * averaging_angle
-    phi_south = phi_centre - 0.5_dp * averaging_angle
-    averaging_width_ew = averaging_angle * COS(phi_centre) * EARTH_RADIUS
-    averaging_width_ns = averaging_angle * EARTH_RADIUS
-
-    ! Coriolis parameter
-    f3 = 2.0_dp * OMEGA * SIN(                                                 &
-       TO_RADIANS*phirot2phi( phi_centre * TO_DEGREES, lam_centre * TO_DEGREES,&
-                              phi_n * TO_DEGREES, lambda_n * TO_DEGREES,       &
-                              gam * TO_DEGREES )                               &
-       )
-
-    END SUBROUTINE setup_parameters
-
-
-!------------------------------------------------------------------------------!
-! Description:
-! ------------
-!> Initializes the COSMO-DE, PALM-4U, PALM-4U boundary grids.
-!------------------------------------------------------------------------------!
-    SUBROUTINE setup_grids() ! setup_grids(inifor_settings(with nx, ny, nz,...))
-       CHARACTER ::  interp_mode
-
-!------------------------------------------------------------------------------
-! Section 0: Define base PALM-4U grid coordinate vectors
-!------------------------------------------------------------------------------
-       ! palm x y z, we allocate the column to nz+1 in order to include the top
-       ! scalar boundary. The interpolation grids will be associated with
-       ! a shorter column that omits the top element.
-       
-       ALLOCATE( x(0:nx), y(0:ny), z(1:nz), z_column(1:nz+1) )
-       CALL linspace(0.5_dp * dx, lx - 0.5_dp * dx, x)
-       CALL linspace(0.5_dp * dy, ly - 0.5_dp * dy, y)
-       CALL stretched_z(z_column, dz, dz_max=dz_max,                           &
-                        dz_stretch_factor=dz_stretch_factor,                   &
-                        dz_stretch_level=dz_stretch_level,                     &
-                        dz_stretch_level_start=dz_stretch_level_start,         &
-                        dz_stretch_level_end=dz_stretch_level_end,             &
-                        dz_stretch_factor_array=dz_stretch_factor_array)
-       z(1:nz) = z_column(1:nz)
-       z_top = z_column(nz+1)
-
-       ! palm xu yv zw, compared to the scalar grid, velocity coordinates
-       ! contain one element less.
-       ALLOCATE( xu(1:nx),  yv(1:ny), zw(1:nz-1), zw_column(1:nz))
-       CALL linspace(dx, lx - dx, xu)
-       CALL linspace(dy, ly - dy, yv)
-       CALL midpoints(z_column, zw_column)
-       zw(1:nz-1) = zw_column(1:nz-1)
-       zw_top     = zw_column(nz)
-
-
-!------------------------------------------------------------------------------
-! Section 1: Define initialization and boundary grids
-!------------------------------------------------------------------------------
-       CALL init_grid_definition('palm', grid=palm_grid,                       &
-               xmin=0.0_dp, xmax=lx,                                           &
-               ymin=0.0_dp, ymax=ly,                                           &
-               x0=x0, y0=y0, z0=z0,                      &
-               nx=nx, ny=ny, nz=nz, z=z, zw=zw, ic_mode=cfg % ic_mode)
-
-       ! Subtracting 1 because arrays will be allocated with nlon + 1 elements.
-       CALL init_grid_definition('cosmo-de', grid=cosmo_grid,                  &
-               xmin=lonmin, xmax=lonmax,                                       &
-               ymin=latmin, ymax=latmax,                                       &
-               x0=x0, y0=y0, z0=0.0_dp,             &
-               nx=nlon-1, ny=nlat-1, nz=nlev-1)
-
-! Define intermediate grid. This is the same as palm_grid except with a much
-! coarser vertical grid. The vertical levels are interpolated in each PALM-4U
-! column from COSMO-DE's secondary levels. The main levels are then computed as
-! the averages of the bounding secondary levels.
-       CALL init_grid_definition('palm intermediate', grid=palm_intermediate,  &
-               xmin=0.0_dp, xmax=lx,                                           &
-               ymin=0.0_dp, ymax=ly,                                           &
-               x0=x0, y0=y0, z0=z0,                      &
-               nx=nx, ny=ny, nz=nlev-2)
-
-       CALL init_grid_definition('boundary', grid=u_initial_grid,              &
-               xmin = dx, xmax = lx - dx,                                      &
-               ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy,                    &
-               x0=x0, y0=y0, z0 = z0,                                          &
-               nx = nx-1, ny = ny, nz = nz,                                    &
-               z=z, ic_mode=cfg % ic_mode)
-
-       CALL init_grid_definition('boundary', grid=v_initial_grid,              &
-               xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx,                    &
-               ymin = dy, ymax = ly - dy,                                      &
-               x0=x0, y0=y0, z0 = z0,                                          &
-               nx = nx, ny = ny-1, nz = nz,                                    &
-               z=z, ic_mode=cfg % ic_mode)
-
-       CALL init_grid_definition('boundary', grid=w_initial_grid,              &
-               xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx,                    &
-               ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy,                    &
-               x0=x0, y0=y0, z0 = z0,                                          &
-               nx = nx, ny = ny, nz = nz-1,                                    &
-               z=zw, ic_mode=cfg % ic_mode)
-
-       CALL init_grid_definition('boundary intermediate', grid=u_initial_intermediate,      &
-               xmin = dx, xmax = lx - dx,                                      &
-               ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy,                    &
-               x0=x0, y0=y0, z0 = z0,                                          &
-               nx = nx-1, ny = ny, nz = nlev - 2)
-
-       CALL init_grid_definition('boundary intermediate', grid=v_initial_intermediate,      &
-               xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx,                    &
-               ymin = dy, ymax = ly - dy,                                      &
-               x0=x0, y0=y0, z0 = z0,                                          &
-               nx = nx, ny = ny-1, nz = nlev - 2)
-
-       CALL init_grid_definition('boundary intermediate', grid=w_initial_intermediate,      &
-               xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx,                    &
-               ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy,                    &
-               x0=x0, y0=y0, z0 = z0,                                          &
-               nx = nx, ny = ny, nz = nlev - 1)
-
-      IF (boundary_variables_required)  THEN
-!
-!------------------------------------------------------------------------------
-! Section 2: Define PALM-4U boundary grids
-!------------------------------------------------------------------------------
-          CALL init_grid_definition('boundary', grid=scalars_east_grid,           &
-                  xmin = lx + 0.5_dp * dx, xmax = lx + 0.5_dp * dx,               &
-                  ymin =  0.5_dp * dy, ymax = ly - 0.5_dp * dy,                   &
-                  x0=x0, y0=y0, z0 = z0,                                          &
-                  nx = 0, ny = ny, nz = nz, z=z)
-
-          CALL init_grid_definition('boundary', grid=scalars_west_grid,           &
-                  xmin = -0.5_dp * dx, xmax = -0.5_dp * dx,                       &
-                  ymin =  0.5_dp * dy, ymax = ly - 0.5_dp * dy,                   &
-                  x0=x0, y0=y0, z0 = z0,                                          &
-                  nx = 0, ny = ny, nz = nz, z=z)
-
-          CALL init_grid_definition('boundary', grid=scalars_north_grid,          &
-                  xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx,                    &
-                  ymin = ly + 0.5_dp * dy, ymax = ly + 0.5_dp * dy,               &
-                  x0=x0, y0=y0, z0 = z0,                                          &
-                  nx = nx, ny = 0, nz = nz, z=z)
-
-          CALL init_grid_definition('boundary', grid=scalars_south_grid,          &
-                  xmin =  0.5_dp * dx, xmax = lx - 0.5_dp * dx,                   &
-                  ymin = -0.5_dp * dy, ymax = -0.5_dp * dy,                       &
-                  x0=x0, y0=y0, z0 = z0,                                          &
-                  nx = nx, ny = 0, nz = nz, z=z)
-
-          CALL init_grid_definition('boundary', grid=scalars_top_grid,            &
-                  xmin =  0.5_dp * dx, xmax = lx - 0.5_dp * dx,                   &
-                  ymin =  0.5_dp * dy, ymax = ly - 0.5_dp * dy,                   &
-                  x0=x0, y0=y0, z0 = z0,                                          &
-                  nx = nx, ny = ny, nz = 1, z=(/z_top/))
-
-          CALL init_grid_definition('boundary', grid=u_east_grid,                 &
-                  xmin = lx, xmax = lx,                                           &
-                  ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy,                    &
-                  x0=x0, y0=y0, z0 = z0,                                          &
-                  nx = 0, ny = ny, nz = nz, z=z)
-
-          CALL init_grid_definition('boundary', grid=u_west_grid,                 &
-                  xmin = 0.0_dp, xmax = 0.0_dp,                                   &
-                  ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy,                    &
-                  x0=x0, y0=y0, z0 = z0,                                          &
-                  nx = 0, ny = ny, nz = nz, z=z)
-
-          CALL init_grid_definition('boundary', grid=u_north_grid,                &
-                  xmin = dx, xmax = lx - dx,                                      &
-                  ymin = ly + 0.5_dp * dy, ymax = ly + 0.5_dp * dy,               &
-                  x0=x0, y0=y0, z0 = z0,                                          &
-                  nx = nx-1, ny = 0, nz = nz, z=z)
-    
-          CALL init_grid_definition('boundary', grid=u_south_grid,                &
-                  xmin = dx, xmax = lx - dx,                                      &
-                  ymin = -0.5_dp * dy, ymax = -0.5_dp * dy,                       &
-                  x0=x0, y0=y0, z0 = z0,                                          &
-                  nx = nx-1, ny = 0, nz = nz, z=z)
-
-          CALL init_grid_definition('boundary', grid=u_top_grid,                  &
-                  xmin = dx, xmax = lx - dx,                                      &
-                  ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy,                    &
-                  x0=x0, y0=y0, z0 = z0,                                          &
-                  nx = nx-1, ny = ny, nz = 1, z=(/z_top/))
-
-          CALL init_grid_definition('boundary', grid=v_east_grid,                 &
-                  xmin = lx + 0.5_dp * dx, xmax = lx + 0.5_dp * dx,               &
-                  ymin = dy, ymax = ly - dy,                                      &
-                  x0=x0, y0=y0, z0 = z0,                                          &
-                  nx = 0, ny = ny-1, nz = nz, z=z)
-
-          CALL init_grid_definition('boundary', grid=v_west_grid,                 &
-                  xmin = -0.5_dp * dx, xmax = -0.5_dp * dx,                       &
-                  ymin = dy, ymax = ly - dy,                                      &
-                  x0=x0, y0=y0, z0 = z0,                                          &
-                  nx = 0, ny = ny-1, nz = nz, z=z)
-
-          CALL init_grid_definition('boundary', grid=v_north_grid,                &
-                  xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx,                    &
-                  ymin = ly, ymax = ly,                                           &
-                  x0=x0, y0=y0, z0 = z0,                                          &
-                  nx = nx, ny = 0, nz = nz, z=z)
-
-          CALL init_grid_definition('boundary', grid=v_south_grid,                &
-                  xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx,                    &
-                  ymin = 0.0_dp, ymax = 0.0_dp,                                   &
-                  x0=x0, y0=y0, z0 = z0,                                          &
-                  nx = nx, ny = 0, nz = nz, z=z)
-
-          CALL init_grid_definition('boundary', grid=v_top_grid,                  &
-                  xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx,                    &
-                  ymin = dy, ymax = ly - dy,                                      &
-                  x0=x0, y0=y0, z0 = z0,                                          &
-                  nx = nx, ny = ny-1, nz = 1, z=(/z_top/))
-
-          CALL init_grid_definition('boundary', grid=w_east_grid,                 &
-                  xmin = lx + 0.5_dp * dx, xmax = lx + 0.5_dp * dx,               &
-                  ymin =  0.5_dp * dy, ymax = ly - 0.5_dp * dy,                   &
-                  x0=x0, y0=y0, z0 = z0,                                          &
-                  nx = 0, ny = ny, nz = nz - 1, z=zw)
-
-          CALL init_grid_definition('boundary', grid=w_west_grid,                 &
-                  xmin = -0.5_dp * dx, xmax = -0.5_dp * dx,                       &
-                  ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy,                    &
-                  x0=x0, y0=y0, z0 = z0,                                          &
-                  nx = 0, ny = ny, nz = nz - 1, z=zw)
-
-          CALL init_grid_definition('boundary', grid=w_north_grid,                &
-                  xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx,                    &
-                  ymin = ly + 0.5_dp * dy, ymax = ly + 0.5_dp * dy,               &
-                  x0=x0, y0=y0, z0 = z0,                                          &
-                  nx = nx, ny = 0, nz = nz - 1, z=zw)
-
-          CALL init_grid_definition('boundary', grid=w_south_grid,                &
-                  xmin =  0.5_dp * dx, xmax = lx - 0.5_dp * dx,                   &
-                  ymin = -0.5_dp * dy, ymax = -0.5_dp * dy,                       &
-                  x0=x0, y0=y0, z0 = z0,                                          &
-                  nx = nx, ny = 0, nz = nz - 1, z=zw)
-
-          CALL init_grid_definition('boundary', grid=w_top_grid,                  &
-                  xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx,                    &
-                  ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy,                    &
-                  x0=x0, y0=y0, z0 = z0,                                          &
-                  nx = nx, ny = ny, nz = 1, z=(/zw_top/))
-
-          CALL init_grid_definition('boundary intermediate', grid=scalars_east_intermediate,   &
-                  xmin = lx + 0.5_dp * dx, xmax = lx + 0.5_dp * dx,               &
-                  ymin =  0.5_dp * dy, ymax = ly - 0.5_dp * dy,                   &
-                  x0=x0, y0=y0, z0 = z0,                                          &
-                  nx = 0, ny = ny, nz = nlev - 2)
-
-          CALL init_grid_definition('boundary intermediate', grid=scalars_west_intermediate,   &
-                  xmin = -0.5_dp * dx, xmax = -0.5_dp * dx,                       &
-                  ymin =  0.5_dp * dy, ymax = ly - 0.5_dp * dy,                   &
-                  x0=x0, y0=y0, z0 = z0,                                          &
-                  nx = 0, ny = ny, nz = nlev - 2)
-
-          CALL init_grid_definition('boundary intermediate', grid=scalars_north_intermediate,  &
-                  xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx,                    &
-                  ymin = ly + 0.5_dp * dy, ymax = ly + 0.5_dp * dy,               &
-                  x0=x0, y0=y0, z0 = z0,                                          &
-                  nx = nx, ny = 0, nz = nlev - 2)
-
-          CALL init_grid_definition('boundary intermediate', grid=scalars_south_intermediate,  &
-                  xmin =  0.5_dp * dx, xmax = lx - 0.5_dp * dx,                   &
-                  ymin = -0.5_dp * dy, ymax = -0.5_dp * dy,                       &
-                  x0=x0, y0=y0, z0 = z0,                                          &
-                  nx = nx, ny = 0, nz = nlev - 2)
-
-          CALL init_grid_definition('boundary intermediate', grid=scalars_top_intermediate,    &
-                  xmin =  0.5_dp * dx, xmax = lx - 0.5_dp * dx,                   &
-                  ymin =  0.5_dp * dy, ymax = ly - 0.5_dp * dy,                   &
-                  x0=x0, y0=y0, z0 = z0,                                          &
-                  nx = nx, ny = ny, nz = nlev - 2)
-
-          CALL init_grid_definition('boundary intermediate', grid=u_east_intermediate,         &
-                  xmin = lx, xmax = lx,                                           &
-                  ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy,                    &
-                  x0=x0, y0=y0, z0 = z0,                                          &
-                  nx = 0, ny = ny, nz = nlev - 2)
-
-          CALL init_grid_definition('boundary intermediate', grid=u_west_intermediate,         &
-                  xmin = 0.0_dp, xmax = 0.0_dp,                                   &
-                  ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy,                    &
-                  x0=x0, y0=y0, z0 = z0,                                          &
-                  nx = 0, ny = ny, nz = nlev - 2)
-
-          CALL init_grid_definition('boundary intermediate', grid=u_north_intermediate,        &
-                  xmin = dx, xmax = lx - dx,                                      &
-                  ymin = ly + 0.5_dp * dy, ymax = ly + 0.5_dp * dy,               &
-                  x0=x0, y0=y0, z0 = z0,                                          &
-                  nx = nx-1, ny = 0, nz = nlev - 2)
-
-          CALL init_grid_definition('boundary intermediate', grid=u_south_intermediate,        &
-                  xmin = dx, xmax = lx - dx,                                      &
-                  ymin = -0.5_dp * dy, ymax = -0.5_dp * dy,                       &
-                  x0=x0, y0=y0, z0 = z0,                                          &
-                  nx = nx-1, ny = 0, nz = nlev - 2)
-
-          CALL init_grid_definition('boundary intermediate', grid=u_top_intermediate,          &
-                  xmin = dx, xmax = lx - dx,                                      &
-                  ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy,                    &
-                  x0=x0, y0=y0, z0 = z0,                                          &
-                  nx = nx-1, ny = ny, nz = nlev - 2)
-
-          CALL init_grid_definition('boundary intermediate', grid=v_east_intermediate,         &
-                  xmin = lx + 0.5_dp * dx, xmax = lx + 0.5_dp * dx,               &
-                  ymin = dy, ymax = ly - dy,                                      &
-                  x0=x0, y0=y0, z0 = z0,                                          &
-                  nx = 0, ny = ny-1, nz = nlev - 2)
-
-          CALL init_grid_definition('boundary intermediate', grid=v_west_intermediate,         &
-                  xmin = -0.5_dp * dx, xmax = -0.5_dp * dx,                       &
-                  ymin = dy, ymax = ly - dy,                                      &
-                  x0=x0, y0=y0, z0 = z0,                                          &
-                  nx = 0, ny = ny-1, nz = nlev - 2)
-
-          CALL init_grid_definition('boundary intermediate', grid=v_north_intermediate,        &
-                  xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx,                    &
-                  ymin = ly, ymax = ly,                                           &
-                  x0=x0, y0=y0, z0 = z0,                                          &
-                  nx = nx, ny = 0, nz = nlev - 2)
-
-          CALL init_grid_definition('boundary intermediate', grid=v_south_intermediate,        &
-                  xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx,                    &
-                  ymin = 0.0_dp, ymax = 0.0_dp,                                   &
-                  x0=x0, y0=y0, z0 = z0,                                          &
-                  nx = nx, ny = 0, nz = nlev - 2)
-
-          CALL init_grid_definition('boundary intermediate', grid=v_top_intermediate,          &
-                  xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx,                    &
-                  ymin = dy, ymax = ly - dy,                                      &
-                  x0=x0, y0=y0, z0 = z0,                                          &
-                  nx = nx, ny = ny-1, nz = nlev - 2)
-
-          CALL init_grid_definition('boundary intermediate', grid=w_east_intermediate,         &
-                  xmin = lx + 0.5_dp * dx, xmax = lx + 0.5_dp * dx,               &
-                  ymin =  0.5_dp * dy, ymax = ly - 0.5_dp * dy,                   &
-                  x0=x0, y0=y0, z0 = z0,                                          &
-                  nx = 0, ny = ny, nz = nlev - 1)
-
-          CALL init_grid_definition('boundary intermediate', grid=w_west_intermediate,         &
-                  xmin = -0.5_dp * dx, xmax = -0.5_dp * dx,                       &
-                  ymin =  0.5_dp * dy, ymax = ly - 0.5_dp * dy,                   &
-                  x0=x0, y0=y0, z0 = z0,                                          &
-                  nx = 0, ny = ny, nz = nlev - 1)
-
-          CALL init_grid_definition('boundary intermediate', grid=w_north_intermediate,        &
-                  xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx,                    &
-                  ymin = ly + 0.5_dp * dy, ymax = ly + 0.5_dp * dy,               &
-                  x0=x0, y0=y0, z0 = z0,                                          &
-                  nx = nx, ny = 0, nz = nlev - 1)
-
-          CALL init_grid_definition('boundary intermediate', grid=w_south_intermediate,        &
-                  xmin =  0.5_dp * dx, xmax = lx - 0.5_dp * dx,                   &
-                  ymin = -0.5_dp * dy, ymax = -0.5_dp * dy,                       &
-                  x0=x0, y0=y0, z0 = z0,                                          &
-                  nx = nx, ny = 0, nz = nlev - 1)
-
-          CALL init_grid_definition('boundary intermediate', grid=w_top_intermediate,          &
-                  xmin =  0.5_dp * dx, xmax = lx - 0.5_dp * dx,                   &
-                  ymin =  0.5_dp * dy, ymax = ly - 0.5_dp * dy,                   &
-                  x0=x0, y0=y0, z0 = z0,                                          &
-                  nx = nx, ny = ny, nz = nlev - 1)
-       END IF
-
-!                                                                              
-!------------------------------------------------------------------------------
-! Section 3: Define profile grids
-!------------------------------------------------------------------------------
-
-       CALL init_averaging_grid(averaged_scalar_profile, cosmo_grid,           &
-               x = 0.5_dp * lx, y = 0.5_dp * ly, z = z, z0 = z0,               &
-               lonmin = lam_west, lonmax = lam_east,                           &
-               latmin = phi_south, latmax = phi_north,                         &
-               kind='scalar')
-
-       CALL init_averaging_grid(averaged_w_profile, cosmo_grid,                &
-               x = 0.5_dp * lx, y = 0.5_dp * ly, z = zw, z0 = z0,              &
-               lonmin = lam_west, lonmax = lam_east,                           &
-               latmin = phi_south, latmax = phi_north,                         &
-               kind='w')
-
-       CALL init_averaging_grid(south_averaged_scalar_profile, cosmo_grid,     &
-               x = 0.5_dp * lx, y = 0.5_dp * ly, z = z, z0 = z0,               &
-               lonmin = lam_west, lonmax = lam_east,                           &
-               latmin = phi_centre - averaging_angle,                          &
-               latmax = phi_centre,                                            &
-               kind='scalar')
-
-       CALL init_averaging_grid(north_averaged_scalar_profile, cosmo_grid,     &
-               x = 0.5_dp * lx, y = 0.5_dp * ly, z = z, z0 = z0,               &
-               lonmin = lam_west, lonmax = lam_east,                           &
-               latmin = phi_centre,                                            &
-               latmax = phi_centre + averaging_angle,                          &
-               kind='scalar')
-
-       CALL init_averaging_grid(west_averaged_scalar_profile, cosmo_grid,      &
-               x = 0.5_dp * lx, y = 0.5_dp * ly, z = z, z0 = z0,               &
-               lonmin = lam_centre - averaging_angle,                          &
-               lonmax = lam_centre,                                            &
-               latmin = phi_south, latmax = phi_north,                         &
-               kind='scalar')
-
-       CALL init_averaging_grid(east_averaged_scalar_profile, cosmo_grid,      &
-               x = 0.5_dp * lx, y = 0.5_dp * ly, z = z, z0 = z0,               &
-               lonmin = lam_centre,                                            &
-               lonmax = lam_centre + averaging_angle,                          &
-               latmin = phi_south, latmax = phi_north,                         &
-               kind='scalar')
-
-       profile_grids_required = ( TRIM(cfg % ic_mode) == 'profile' .OR.        &
-                                  TRIM(cfg % bc_mode) == 'ideal' )
-
-       !IF (profile_grids_required)  THEN
-       !   ! Here, I use the 'boundary' kind, so the vertical coordinate uses the
-       !   ! PALM z coordinate.
-       !   CALL init_grid_definition('boundary', grid=scalar_profile_grid,      &
-       !           xmin = 0.5_dp * lx, xmax = 0.5_dp * lx,                      &
-       !           ymin = 0.5_dp * ly, ymax = 0.5_dp * ly,                      &
-       !           x0=x0, y0=y0, z0 = z0,                                       &
-       !           nx = 0, ny = 0, nz = nz, z=z)
-
-       !   CALL init_grid_definition('boundary', grid=w_profile_grid,           &
-       !           xmin = 0.5_dp * lx, xmax = 0.5_dp * lx,                      &
-       !           ymin = 0.5_dp * ly, ymax = 0.5_dp * ly,                      &
-       !           x0=x0, y0=y0, z0 = z0,                                       &
-       !           nx = 0, ny = 0, nz = nz - 1, z=zw)
-
-       !   CALL init_grid_definition('boundary', grid=scalar_profile_intermediate,&
-       !           xmin = 0.5_dp * lx, xmax = 0.5_dp * lx,                      &
-       !           ymin = 0.5_dp * ly, ymax = 0.5_dp * ly,                      &
-       !           x0=x0, y0=y0, z0 = z0,                                       &
-       !           nx = 0, ny = 0, nz = nlev - 2, z=z)
-
-       !   CALL init_grid_definition('boundary', grid=w_profile_intermediate,   &
-       !           xmin = 0.5_dp * lx, xmax = 0.5_dp * lx,                      &
-       !           ymin = 0.5_dp * ly, ymax = 0.5_dp * ly,                      &
-       !           x0=x0, y0=y0, z0 = z0,                                       &
-       !           nx = 0, ny = 0, nz = nlev - 2, z=zw)
-       !END IF
-
-!                                                                              
-!------------------------------------------------------------------------------
-! Section 4: Precompute neighbours and weights for interpolation              
-!------------------------------------------------------------------------------
-       interp_mode = 's'
-       CALL setup_interpolation(cosmo_grid, palm_grid, palm_intermediate, interp_mode, ic_mode=cfg % ic_mode)
-       IF (boundary_variables_required)  THEN
-          CALL setup_interpolation(cosmo_grid, scalars_east_grid, scalars_east_intermediate, interp_mode)
-          CALL setup_interpolation(cosmo_grid, scalars_west_grid, scalars_west_intermediate, interp_mode)
-          CALL setup_interpolation(cosmo_grid, scalars_north_grid, scalars_north_intermediate, interp_mode)
-          CALL setup_interpolation(cosmo_grid, scalars_south_grid, scalars_south_intermediate, interp_mode)
-          CALL setup_interpolation(cosmo_grid, scalars_top_grid, scalars_top_intermediate, interp_mode)
-       END IF
-
-       interp_mode = 'u'
-       CALL setup_interpolation(cosmo_grid, u_initial_grid, u_initial_intermediate, interp_mode, ic_mode=cfg % ic_mode)
-       IF (boundary_variables_required)  THEN
-          CALL setup_interpolation(cosmo_grid, u_east_grid, u_east_intermediate, interp_mode)
-          CALL setup_interpolation(cosmo_grid, u_west_grid, u_west_intermediate, interp_mode)
-          CALL setup_interpolation(cosmo_grid, u_north_grid, u_north_intermediate, interp_mode)
-          CALL setup_interpolation(cosmo_grid, u_south_grid, u_south_intermediate, interp_mode)
-          CALL setup_interpolation(cosmo_grid, u_top_grid, u_top_intermediate, interp_mode)
-       END IF
-
-       interp_mode = 'v'
-       CALL setup_interpolation(cosmo_grid, v_initial_grid, v_initial_intermediate, interp_mode, ic_mode=cfg % ic_mode)
-       IF (boundary_variables_required)  THEN
-          CALL setup_interpolation(cosmo_grid, v_east_grid, v_east_intermediate, interp_mode)
-          CALL setup_interpolation(cosmo_grid, v_west_grid, v_west_intermediate, interp_mode)
-          CALL setup_interpolation(cosmo_grid, v_north_grid, v_north_intermediate, interp_mode)
-          CALL setup_interpolation(cosmo_grid, v_south_grid, v_south_intermediate, interp_mode)
-          CALL setup_interpolation(cosmo_grid, v_top_grid, v_top_intermediate, interp_mode)
-       END IF
-
-       interp_mode = 'w'
-       CALL setup_interpolation(cosmo_grid, w_initial_grid, w_initial_intermediate, interp_mode, ic_mode=cfg % ic_mode)
-       IF (boundary_variables_required)  THEN
-          CALL setup_interpolation(cosmo_grid, w_east_grid, w_east_intermediate, interp_mode)
-          CALL setup_interpolation(cosmo_grid, w_west_grid, w_west_intermediate, interp_mode)
-          CALL setup_interpolation(cosmo_grid, w_north_grid, w_north_intermediate, interp_mode)
-          CALL setup_interpolation(cosmo_grid, w_south_grid, w_south_intermediate, interp_mode)
-          CALL setup_interpolation(cosmo_grid, w_top_grid, w_top_intermediate, interp_mode)
-       END IF
-
-       IF (TRIM(cfg % ic_mode) == 'profile')  THEN
-           !TODO: remove this conditional if not needed. 
-       END IF
-        
-
-    END SUBROUTINE setup_grids
-
-
-    SUBROUTINE setup_interpolation(cosmo_grid, grid, intermediate_grid, kind, ic_mode)
-
-       TYPE(grid_definition), INTENT(IN), TARGET    ::  cosmo_grid
-       TYPE(grid_definition), INTENT(INOUT), TARGET ::  grid, intermediate_grid
-       CHARACTER, INTENT(IN)                        ::  kind
-       CHARACTER(LEN=*), INTENT(IN), OPTIONAL       ::  ic_mode
-
-       REAL(dp), DIMENSION(:), POINTER     ::  cosmo_lat, cosmo_lon
-       REAL(dp), DIMENSION(:,:,:), POINTER ::  cosmo_h
-
-       LOGICAL :: setup_volumetric
-
-!------------------------------------------------------------------------------
-! Section 1: Horizontal interpolation                                        
-!------------------------------------------------------------------------------
-       ! Select horizontal coordinates according to kind of points (s/w, u, v)
-       SELECT CASE(kind)
-
-       CASE('s') ! scalars
-
-          cosmo_lat => cosmo_grid % lat
-          cosmo_lon => cosmo_grid % lon
-          cosmo_h   => cosmo_grid % hfl
-
-       CASE('w') ! vertical velocity
-
-          cosmo_lat => cosmo_grid % lat
-          cosmo_lon => cosmo_grid % lon
-          cosmo_h   => cosmo_grid % hhl
-
-       CASE('u') ! x velocity
-
-          cosmo_lat => cosmo_grid % lat
-          cosmo_lon => cosmo_grid % lonu
-          cosmo_h   => cosmo_grid % hfl
-
-       CASE('v') ! y velocity
-
-          cosmo_lat => cosmo_grid % latv
-          cosmo_lon => cosmo_grid % lon
-          cosmo_h   => cosmo_grid % hfl
-
-       CASE DEFAULT
-
-          message = "Interpolation quantity '" // kind // "' is not supported."
-          CALL abort('setup_interpolation', message)
-
-       END SELECT
-
-       CALL find_horizontal_neighbours(cosmo_lat, cosmo_lon,                   &
-          intermediate_grid % clat, intermediate_grid % clon,                  &
-          intermediate_grid % ii, intermediate_grid % jj)
-
-       CALL compute_horizontal_interp_weights(cosmo_lat, cosmo_lon,            &
-          intermediate_grid % clat, intermediate_grid % clon,                  &
-          intermediate_grid % ii, intermediate_grid % jj,                      &
-          intermediate_grid % w_horiz)
-
-!------------------------------------------------------------------------------
-! Section 2: Vertical interpolation
-!------------------------------------------------------------------------------
-
-       ! If profile initialization is chosen, we--somewhat counterintuitively--
-       ! don't need to compute vertical interpolation weights. At least, we
-       ! don't need them on the intermediate grid, which fills the entire PALM
-       ! domain volume. Instead we need vertical weights for the intermediate
-       ! profile grids, which get computed in setup_averaging().
-       setup_volumetric = .TRUE.
-       IF (PRESENT(ic_mode))  THEN
-          IF (TRIM(ic_mode) == 'profile')  setup_volumetric = .FALSE.
-       END IF
-
-       IF (setup_volumetric)  THEN
-          ALLOCATE( intermediate_grid % h(0:intermediate_grid % nx,            &
-                                          0:intermediate_grid % ny,            &
-                                          0:intermediate_grid % nz) ) 
-          intermediate_grid % h(:,:,:) = - EARTH_RADIUS
-
-          ! For w points, use hhl, for scalars use hfl
-          ! compute the full heights for the intermediate grids
-          CALL interpolate_2d(cosmo_h, intermediate_grid % h, intermediate_grid)
-          CALL find_vertical_neighbours_and_weights_interp(grid, intermediate_grid)
-       END IF
-       
-    END SUBROUTINE setup_interpolation
-
-!------------------------------------------------------------------------------!
-! Description:
-! ------------
-!> Initializes grid_definition-type variables.
-!> 
-!> Input parameters:
-!> -----------------
-!> kind : Grid kind, distinguishes between PALM-4U and COSMO-DE grids
-!>    as well as grids covering the boundary surfaces. Valid kinds are:
-!>       - 'palm'
-!>       - 'cosmo-de'
-!>       - 'eastwest-scalar'
-!> 
-!> <xyx>min, <xyz>max : Domain minima and maxima in x, y, and z direction. Note
-!>    that these values do not necessarily translate to the outmost coordinates
-!>    of the generated grid but rather refer to the extent of the underlying
-!>    PALM-4U computational domain (i.e. the outer cell faces). The coordinates
-!>    of the generated grid will be inferred from this information taking into
-!>    account the initialization mode ic_mode. For example, the coordinates of a
-!>    boundary grid initialized using mode 'eastwest-scalar' will be located in
-!>    planes one half grid point outwards of xmin and xmax.
-!>
-!> z0 : Elevation of the PALM-4U domain above sea level [m]
-!>
-!> n<xyz> : Number of grod points in x, y, and z direction
-!>
-!> Output parameters:
-!> ------------------
-!> grid : Grid variable to be initialized.
-!------------------------------------------------------------------------------!
-    SUBROUTINE init_grid_definition(kind, xmin, xmax, ymin, ymax,              &
-                                    x0, y0, z0, nx, ny, nz, z, zw, grid, ic_mode)
-        CHARACTER(LEN=*), INTENT(IN)           ::  kind
-        CHARACTER(LEN=*), INTENT(IN), OPTIONAL ::  ic_mode
-        INTEGER, INTENT(IN)                    ::  nx, ny, nz
-        REAL(dp), INTENT(IN)                   ::  xmin, xmax, ymin, ymax
-        REAL(dp), INTENT(IN)                   ::  x0, y0, z0
-        REAL(dp), INTENT(IN), TARGET, OPTIONAL ::  z(:)
-        REAL(dp), INTENT(IN), TARGET, OPTIONAL ::  zw(:)
-        TYPE(grid_definition), INTENT(INOUT)   ::  grid
-
-        grid % nx = nx
-        grid % ny = ny
-        grid % nz = nz
-
-        grid % lx = xmax - xmin
-        grid % ly = ymax - ymin
-
-        grid % x0 = x0
-        grid % y0 = y0
-        grid % z0 = z0
-
-        SELECT CASE( TRIM (kind) )
-
-        CASE('boundary')
-
-           IF (.NOT.PRESENT(z))  THEN
-              message = "z has not been passed but is required for 'boundary' grids"
-              CALL abort('init_grid_definition', message)
-           END IF
-
-           ALLOCATE( grid % x(0:nx) )
-           CALL linspace(xmin, xmax, grid % x)
-
-           ALLOCATE( grid % y(0:ny) )
-           CALL linspace(ymin, ymax, grid % y)
-
-           grid % z => z
-
-           ! Allocate neighbour indices and weights
-           IF (TRIM(ic_mode) .NE. 'profile')  THEN
-              ALLOCATE( grid % kk(0:nx, 0:ny, 1:nz, 2) )
-              grid % kk(:,:,:,:) = -1
-
-              ALLOCATE( grid % w_verti(0:nx, 0:ny, 1:nz, 2) )
-              grid % w_verti(:,:,:,:) = 0.0_dp
-           END IF
-        
-        CASE('boundary intermediate')
-
-           ALLOCATE( grid % x(0:nx) )
-           CALL linspace(xmin, xmax, grid % x)
-
-           ALLOCATE( grid % y(0:ny) )
-           CALL linspace(ymin, ymax, grid % y)
-
-           ALLOCATE( grid % clon(0:nx, 0:ny), grid % clat(0:nx, 0:ny)  )
-
-           CALL rotate_to_cosmo(                                               &
-              phir = project( grid % y, y0, EARTH_RADIUS ) ,                   & ! = plate-carree latitude
-              lamr = project( grid % x, x0, EARTH_RADIUS ) ,                   & ! = plate-carree longitude
-              phip = phi_cn, lamp = lambda_cn,                                 &
-              phi  = grid % clat,                                              &
-              lam  = grid % clon,                                              &
-              gam  = gam                                                       &
-           )
-
-           ! Allocate neighbour indices and weights
-           ALLOCATE( grid % ii(0:nx, 0:ny, 4),                                 &
-                     grid % jj(0:nx, 0:ny, 4) )
-           grid % ii(:,:,:)   = -1
-           grid % jj(:,:,:)   = -1
-
-           ALLOCATE( grid % w_horiz(0:nx, 0:ny, 4) )
-           grid % w_horiz(:,:,:)   = 0.0_dp
-        
-        ! This mode initializes a Cartesian PALM-4U grid and adds the
-        ! corresponding latitudes and longitudes of the rotated pole grid.
-        CASE('palm')
-
-           IF (.NOT.PRESENT(z))  THEN
-              message = "z has not been passed but is required for 'palm' grids"
-              CALL abort('init_grid_definition', message)
-           END IF
-
-           IF (.NOT.PRESENT(zw))  THEN
-              message = "zw has not been passed but is required for 'palm' grids"
-              CALL abort('init_grid_definition', message)
-           END IF
-
-           grid % name(1) = 'x and lon'
-           grid % name(2) = 'y and lat'
-           grid % name(3) = 'z'
-
-           !TODO: Remove use of global dx, dy, dz variables. Consider
-           !TODO:   associating global x,y, and z arrays.
-           ALLOCATE( grid % x(0:nx),   grid % y(0:ny) )
-           ALLOCATE( grid % xu(1:nx),  grid % yv(1:ny) )
-           CALL linspace(xmin + 0.5_dp* dx, xmax - 0.5_dp* dx, grid % x)
-           CALL linspace(ymin + 0.5_dp* dy, ymax - 0.5_dp* dy, grid % y)
-           grid % z => z
-           CALL linspace(xmin +  dx, xmax -  dx, grid % xu)
-           CALL linspace(ymin +  dy, ymax -  dy, grid % yv)
-           grid % zw => zw
-
-           grid % depths => depths
-
-           ! Allocate neighbour indices and weights
-           IF (TRIM(ic_mode) .NE. 'profile')  THEN
-              ALLOCATE( grid % kk(0:nx, 0:ny, 1:nz, 2) )
-              grid % kk(:,:,:,:) = -1
-
-              ALLOCATE( grid % w_verti(0:nx, 0:ny, 1:nz, 2) )
-              grid % w_verti(:,:,:,:) = 0.0_dp
-           END IF
-
-        CASE('palm intermediate')
-
-           grid % name(1) = 'x and lon'
-           grid % name(2) = 'y and lat'
-           grid % name(3) = 'interpolated hhl or hfl'
-
-           !TODO: Remove use of global dx, dy, dz variables. Consider
-           !TODO:   associating global x,y, and z arrays.
-           ALLOCATE( grid % x(0:nx),   grid % y(0:ny) )
-           ALLOCATE( grid % xu(1:nx),  grid % yv(1:ny) )
-           CALL linspace(xmin + 0.5_dp*dx, xmax - 0.5_dp*dx, grid % x)
-           CALL linspace(ymin + 0.5_dp*dy, ymax - 0.5_dp*dy, grid % y)
-           CALL linspace(xmin + dx, xmax - dx, grid % xu)
-           CALL linspace(ymin + dy, ymax - dy, grid % yv)
-
-           grid % depths => depths
-
-           ! Allocate rotated-pole coordinates, clon is for (c)osmo-de (lon)gitude
-           ALLOCATE( grid % clon(0:nx, 0:ny),   grid % clat(0:nx, 0:ny)  )
-           ALLOCATE( grid % clonu(1:nx, 0:ny),  grid % clatu(1:nx, 0:ny) )
-           ALLOCATE( grid % clonv(0:nx, 1:ny),  grid % clatv(0:nx, 1:ny) )
-
-           ! Compute rotated-pole coordinates of...
-           ! ... PALM-4U centres
-           CALL rotate_to_cosmo(                                               &
-              phir = project( grid % y, y0, EARTH_RADIUS ) , & ! = plate-carree latitude
-              lamr = project( grid % x, x0, EARTH_RADIUS ) , & ! = plate-carree longitude
-              phip = phi_cn, lamp = lambda_cn,                                 &
-              phi  = grid % clat,                                              &
-              lam  = grid % clon,                                              &
-              gam  = gam                                                       &
-           )
-
-           ! ... PALM-4U u winds
-           CALL rotate_to_cosmo(                                               &
-              phir = project( grid % y,  y0, EARTH_RADIUS ), & ! = plate-carree latitude
-              lamr = project( grid % xu, x0, EARTH_RADIUS ), & ! = plate-carree longitude
-              phip = phi_cn, lamp = lambda_cn,                                 &
-              phi  = grid % clatu,                                             &
-              lam  = grid % clonu,                                             &
-              gam  = gam                                                       &
-           )
-
-           ! ... PALM-4U v winds
-           CALL rotate_to_cosmo(                                               &
-              phir = project( grid % yv, y0, EARTH_RADIUS ), & ! = plate-carree latitude
-              lamr = project( grid % x,  x0, EARTH_RADIUS ), & ! = plate-carree longitude
-              phip = phi_cn, lamp = lambda_cn,                                 &
-              phi  = grid % clatv,                                             &
-              lam  = grid % clonv,                                             &
-              gam  = gam                                                       &
-           )
-
-           ! Allocate neighbour indices and weights
-           ALLOCATE( grid % ii(0:nx, 0:ny, 4),                                 &
-                     grid % jj(0:nx, 0:ny, 4) )
-           grid % ii(:,:,:)   = -1
-           grid % jj(:,:,:)   = -1
-
-           ALLOCATE( grid % w_horiz(0:nx, 0:ny, 4) )
-           grid % w_horiz(:,:,:)   = 0.0_dp
-
-        CASE('cosmo-de')
-           grid % name(1) = 'rlon'         ! of COMSO-DE cell centres (scalars)
-           grid % name(2) = 'rlat'         ! of COMSO-DE cell centres (scalars)
-           grid % name(3) = 'height'
-
-           ALLOCATE( grid % lon(0:nx),   grid % lat(0:ny)  )
-           ALLOCATE( grid % lonu(0:nx),  grid % latv(0:ny) )
-
-           CALL linspace(xmin, xmax, grid % lon)
-           CALL linspace(ymin, ymax, grid % lat)
-           grid % lonu(:) = grid % lon + 0.5_dp * (grid % lx / grid % nx)
-           grid % latv(:) = grid % lat + 0.5_dp * (grid % ly / grid % ny)
-
-           ! Point to heights of half levels (hhl) and compute heights of full
-           ! levels (hfl) as arithmetic averages
-           grid % hhl => hhl
-           grid % hfl => hfl
-           grid % depths => depths
-
-        CASE DEFAULT
-            message = "Grid kind '" // TRIM(kind) // "' is not recognized."
-            CALL abort('init_grid_definition', message)
-
-        END SELECT
-
-    END SUBROUTINE init_grid_definition
-
-
-!------------------------------------------------------------------------------!
-! Description:
-! ------------
-!> Initializes averagin_grid-type variables.
-!> 
-!> Input parameters:
-!> -----------------
-!>
-!> cosmo_grid : grid_definition-type varieble initialized as 'cosmo-de' grid
-!>    providing longitudes and latitudes of the parent grid
-!>
-!> x, y : location of the profile to be averaged in the PALM system [m]
-!>
-!> z : vertical grid coordinates of the profile in the PALM system [m]
-!>
-!> <lat/lon><min/max>: boundaries of the averaging region in the parent system,
-!>    i.e. the COSMO-DE rotated-pole system. [rad]
-!>
-!> kind : kind of quantity to be averaged using this averaging grid.
-!>    Destinguishes COSMO-DE scalar and w-velocity levels. Note that finding the
-!>    parent/COSMO columns for the region in get_cosmo_averaging_region() is
-!>    independent of 'kind' b/ecause INIFOR uses column-centred u and v velocity
-!>    components, which are computed in the preprocessing step.
-!>
-!> Output parameters:
-!> ------------------
-!> avg_grid : averaging_grid variable to be initialized.
-!------------------------------------------------------------------------------!
-    SUBROUTINE init_averaging_grid(avg_grid, cosmo_grid, x, y, z, z0,          &
-       lonmin, lonmax, latmin, latmax, kind)
-
-       TYPE(grid_definition), INTENT(INOUT) ::  avg_grid
-       TYPE(grid_definition), INTENT(IN)    ::  cosmo_grid
-       REAL(dp), INTENT(IN)                 ::  x, y, z0
-       REAL(dp), INTENT(IN), TARGET         ::  z(:)
-       REAL(dp), INTENT(IN)                 ::  lonmin, lonmax, latmin, latmax
-
-       CHARACTER(LEN=*), INTENT(IN)         ::  kind
-
-       LOGICAL                              :: level_based_averaging
-
-       INTEGER :: i, j
-
-       ALLOCATE( avg_grid % x(1) )
-       ALLOCATE( avg_grid % y(1) )
-       avg_grid % x(1) = x
-       avg_grid % y(1) = y
-       avg_grid % z => z
-       avg_grid % z0 = z0
-
-       avg_grid % nz = SIZE(z, 1)
-
-       ALLOCATE( avg_grid % lon(2) )
-       ALLOCATE( avg_grid % lat(2) )
-       avg_grid % lon(1:2) = (/lonmin, lonmax/)
-       avg_grid % lat(1:2) = (/latmin, latmax/)
-
-       avg_grid % kind = TRIM(kind)
-
-       ! Find and store COSMO columns that fall into the coordinate range
-       ! given by avg_grid % clon, % clat
-       CALL get_cosmo_averaging_region(avg_grid, cosmo_grid)
-
-       ALLOCATE (avg_grid % kkk(avg_grid % n_columns, avg_grid % nz, 2) )
-       ALLOCATE (avg_grid % w(avg_grid % n_columns, avg_grid % nz, 2) )
-       ! Compute average COSMO levels in the averaging region
-       SELECT CASE(avg_grid % kind)
-
-       CASE('scalar', 'u', 'v')
-          avg_grid % cosmo_h => cosmo_grid % hfl
-
-       CASE('w')
-          avg_grid % cosmo_h => cosmo_grid % hhl
-
-       CASE DEFAULT
-          message = "Averaging grid kind '" // TRIM(avg_grid % kind) // &
-                    "' is not supported. Use 'scalar', 'u', or 'v'."
-          CALL abort('get_cosmo_averaging_region', message)
-
-       END SELECT
-
-       ! For level-besed averaging, compute average heights
-       level_based_averaging = .TRUE.
-       IF (level_based_averaging)  THEN
-          ALLOCATE(avg_grid % h(1,1,SIZE(avg_grid % cosmo_h, 3)) )
- 
-          CALL average_2d(avg_grid % cosmo_h, avg_grid % h(1,1,:),                            &
-                          avg_grid % iii, avg_grid % jjj)
-       END IF
-
-       ! Copy averaged grid to all COSMO columnts, leads to computing the same
-       ! vertical interpolation weights for all columns and to COSMO grid level
-       ! based averaging onto the averaged COSMO heights.
-       IF ( TRIM(cfg % averaging_mode) == 'level' )  THEN
-          FORALL(                                                              &
-             i=1:SIZE(avg_grid % cosmo_h, 1),                                  &
-             j=1:SIZE(avg_grid % cosmo_h, 2)                                   &
-          )   avg_grid % cosmo_h(i,j,:) = avg_grid % h(1,1,:)
-       END IF
-
-       ! Compute vertical weights and neighbours
-       CALL find_vertical_neighbours_and_weights_average(avg_grid)
-
-    END SUBROUTINE init_averaging_grid
-
-
-    SUBROUTINE get_cosmo_averaging_region(avg_grid, cosmo_grid)
-       TYPE(grid_definition), INTENT(INOUT)         ::  avg_grid
-       TYPE(grid_definition), TARGET, INTENT(IN)    ::  cosmo_grid
-
-       REAL(dp), DIMENSION(:), POINTER              ::  cosmo_lon, cosmo_lat
-       REAL(dp)                                     ::  dlon, dlat
-
-       INTEGER ::  i, j, imin, imax, jmin, jmax, l, nx, ny
-
-
-       SELECT CASE( TRIM(avg_grid % kind) )
-
-       CASE('scalar', 'w')
-          cosmo_lon => cosmo_grid % lon
-          cosmo_lat => cosmo_grid % lat
-
-       CASE('u')
-          cosmo_lon => cosmo_grid % lonu
-          cosmo_lat => cosmo_grid % lat
-
-       CASE('v')
-          cosmo_lon => cosmo_grid % lon
-          cosmo_lat => cosmo_grid % latv
-
-       CASE DEFAULT
-          message = "Averaging grid kind '" // TRIM(avg_grid % kind) // &
-                    "' is not supported. Use 'scalar', 'u', or 'v'."
-          CALL abort('get_cosmo_averaging_region', message)
-
-       END SELECT
-
-
-       ! FIXME: make dlon, dlat parameters of the grid_defintion type
-       dlon = cosmo_lon(1) - cosmo_lon(0)
-       dlat = cosmo_lat(1) - cosmo_lat(0)
-
-       imin = CEILING( (avg_grid % lon(1) - cosmo_lon(0)) / dlon )
-       imax = FLOOR(   (avg_grid % lon(2) - cosmo_lon(0)) / dlon )
-
-       jmin = CEILING( (avg_grid % lat(1) - cosmo_lat(0)) / dlat )
-       jmax = FLOOR(   (avg_grid % lat(2) - cosmo_lat(0)) / dlat )
-       
-       message = "Averaging over "//                                           &
-                 TRIM(str(imin)) // " < i < " // TRIM(str(imax)) //            &
-                 " and " //                                                    &
-                 TRIM(str(jmin)) // " < j < " // TRIM(str(jmax))
-       CALL report( 'get_cosmo_averaging_region', message )
-
-       nx = imax - imin + 1
-       ny = jmax - jmin + 1
-       avg_grid % n_columns = nx * ny
-
-       ALLOCATE( avg_grid % iii(avg_grid % n_columns),                                 &
-                 avg_grid % jjj(avg_grid % n_columns) )
-
-       l = 0
-       DO j = jmin, jmax
-       DO i = imin, imax
-          l = l + 1
-          avg_grid % iii(l) = i
-          avg_grid % jjj(l) = j
-       END DO
-       END DO
-
-    END SUBROUTINE get_cosmo_averaging_region
-
-
-!------------------------------------------------------------------------------!
-! Description:
-! ------------
-!> PALM's stretched vertical grid generator. Forked from PALM revision 3139, see
-!> https://palm.muk.uni-hannover.de/trac/browser/palm/trunk/SOURCE/init_grid.f90?rev=3139
-!> 
-!> This routine computes the levels of scalar points. The levels of the velocity
-!> points are then obtained as the midpoints inbetween using the INIFOR routine
-!> 'modpoints'.
-!------------------------------------------------------------------------------!
-    SUBROUTINE stretched_z(z, dz, dz_max, dz_stretch_factor, dz_stretch_level, &
-                           dz_stretch_level_start, dz_stretch_level_end,       &
-                           dz_stretch_factor_array)
-
-       REAL(dp), DIMENSION(:), INTENT(INOUT) ::  z, dz, dz_stretch_factor_array
-       REAL(dp), DIMENSION(:), INTENT(INOUT) ::  dz_stretch_level_start, dz_stretch_level_end
-       REAL(dp), INTENT(IN) ::  dz_max, dz_stretch_factor, dz_stretch_level
-
-       INTEGER ::  number_stretch_level_start        !< number of user-specified start levels for stretching
-       INTEGER ::  number_stretch_level_end          !< number of user-specified end levels for stretching
-
-       REAL(dp), DIMENSION(:), ALLOCATABLE ::  min_dz_stretch_level_end
-       REAL(dp) ::  dz_level_end, dz_stretched
-
-       INTEGER ::  dz_stretch_level_end_index(9)               !< vertical grid level index until which the vertical grid spacing is stretched
-       INTEGER ::  dz_stretch_level_start_index(9)             !< vertical grid level index above which the vertical grid spacing is stretched
-       INTEGER ::  dz_stretch_level_index = 0
-       INTEGER ::  k, n, number_dz
-!
-!-- Compute height of u-levels from constant grid length and dz stretch factors
-       IF ( dz(1) == -1.0_dp )  THEN
-          message = 'missing dz'
-          CALL abort( 'stretched_z', message)
-       ELSEIF ( dz(1) <= 0.0_dp )  THEN
-          WRITE( message, * ) 'dz=', dz(1),' <= 0.0'
-          CALL abort( 'stretched_z', message)
-       ENDIF
-
-!
-!-- Initialize dz_stretch_level_start with the value of dz_stretch_level
-!-- if it was set by the user
-       IF ( dz_stretch_level /= -9999999.9_dp ) THEN
-          dz_stretch_level_start(1) = dz_stretch_level
-       ENDIF
-       
-!
-!-- Determine number of dz values and stretching levels specified by the
-!-- user to allow right controlling of the stretching mechanism and to
-!-- perform error checks. The additional requirement that dz /= dz_max
-!-- for counting number of user-specified dz values is necessary. Otherwise
-!-- restarts would abort if the old stretching mechanism with dz_stretch_level
-!-- is used (Attention: The user is not allowed to specify a dz value equal
-!-- to the default of dz_max = 999.0). 
-       number_dz = COUNT( dz /= -1.0_dp .AND. dz /= dz_max )
-       number_stretch_level_start = COUNT( dz_stretch_level_start /=           &
-                                           -9999999.9_dp )
-       number_stretch_level_end = COUNT( dz_stretch_level_end /=               &
-                                         9999999.9_dp )
-
-!
-!-- The number of specified end levels +1 has to be the same than the number 
-!-- of specified dz values
-       IF ( number_dz /= number_stretch_level_end + 1 ) THEN
-          WRITE( message, * ) 'The number of values for dz = ',                &
-                              number_dz, 'has to be the same than ',           &
-                              'the number of values for ',                     &
-                              'dz_stretch_level_end + 1 = ',                   &
-                              number_stretch_level_end+1
-          CALL abort( 'stretched_z', message)
-       ENDIF
-    
-!
-!--    The number of specified start levels has to be the same or one less than 
-!--    the number of specified dz values
-       IF ( number_dz /= number_stretch_level_start + 1 .AND.                  &
-            number_dz /= number_stretch_level_start ) THEN
-          WRITE( message, * ) 'The number of values for dz = ',         &
-                              number_dz, 'has to be the same or one ', &
-                              'more than& the number of values for ',  &
-                              'dz_stretch_level_start = ',             &
-                              number_stretch_level_start
-          CALL abort( 'stretched_z', message)
-       ENDIF
-    
-!--    The number of specified start levels has to be the same or one more than 
-!--    the number of specified end levels
-       IF ( number_stretch_level_start /= number_stretch_level_end + 1 .AND.   &
-            number_stretch_level_start /= number_stretch_level_end ) THEN
-          WRITE( message, * ) 'The number of values for ',              &
-                              'dz_stretch_level_start = ',              &
-                              dz_stretch_level_start, 'has to be the ',&
-                              'same or one more than& the number of ', &
-                              'values for dz_stretch_level_end = ',    &
-                              number_stretch_level_end
-          CALL abort( 'stretched_z', message)
-       ENDIF
-
-!
-!-- Initialize dz for the free atmosphere with the value of dz_max
-       IF ( dz(number_stretch_level_start+1) == -1.0_dp .AND.                     &
-            number_stretch_level_start /= 0 ) THEN 
-          dz(number_stretch_level_start+1) = dz_max
-       ENDIF
-       
-!
-!-- Initialize the stretching factor if (infinitely) stretching in the free 
-!-- atmosphere is desired (dz_stretch_level_end was not specified for the 
-!-- free atmosphere)
-       IF ( number_stretch_level_start == number_stretch_level_end + 1 ) THEN 
-          dz_stretch_factor_array(number_stretch_level_start) =                   &
-          dz_stretch_factor
-       ENDIF
-
-!-- Allocation of arrays for stretching
-       ALLOCATE( min_dz_stretch_level_end(number_stretch_level_start) )
-
-!
-!--    The stretching region has to be large enough to allow for a smooth
-!--    transition between two different grid spacings
-       DO n = 1, number_stretch_level_start
-          min_dz_stretch_level_end(n) = dz_stretch_level_start(n) +            &
-                                        4 * MAX( dz(n),dz(n+1) )
-       ENDDO
-
-       IF ( ANY( min_dz_stretch_level_end(1:number_stretch_level_start) >      &
-                 dz_stretch_level_end(1:number_stretch_level_start) ) ) THEN
-       !IF ( ANY( min_dz_stretch_level_end >      &
-       !          dz_stretch_level_end ) ) THEN
-             message = 'Each dz_stretch_level_end has to be larger '  // &
-                       'than its corresponding value for ' //            &
-                       'dz_stretch_level_start + 4*MAX(dz(n),dz(n+1)) '//&
-                       'to allow for smooth grid stretching'
-             CALL abort('stretched_z', message)
-       ENDIF
-       
-!
-!--    Stretching must not be applied within the prandtl_layer 
-!--    (first two grid points). For the default case dz_stretch_level_start 
-!--    is negative. Therefore the absolut value is checked here.
-       IF ( ANY( ABS( dz_stretch_level_start ) < dz(1) * 1.5_dp ) ) THEN
-          WRITE( message, * ) 'Eeach dz_stretch_level_start has to be ',&
-                              'larger than ', dz(1) * 1.5
-             CALL abort( 'stretched_z', message)
-       ENDIF
-
-!
-!--    The stretching has to start and end on a grid level. Therefore 
-!--    user-specified values have to ''interpolate'' to the next lowest level
-       IF ( number_stretch_level_start /= 0 ) THEN
-          dz_stretch_level_start(1) = INT( (dz_stretch_level_start(1) -        &
-                                            dz(1)/2.0) / dz(1) )               &
-                                      * dz(1) + dz(1)/2.0
-       ENDIF
-       
-       IF ( number_stretch_level_start > 1 ) THEN
-          DO n = 2, number_stretch_level_start
-             dz_stretch_level_start(n) = INT( dz_stretch_level_start(n) /      &
-                                              dz(n) ) * dz(n)
-          ENDDO
-       ENDIF
-       
-       IF ( number_stretch_level_end /= 0 ) THEN
-          DO n = 1, number_stretch_level_end
-             dz_stretch_level_end(n) = INT( dz_stretch_level_end(n) /          &
-                                            dz(n+1) ) * dz(n+1)
-          ENDDO
-       ENDIF
- 
-!
-!--    Determine stretching factor if necessary
-       IF ( number_stretch_level_end >= 1 ) THEN 
-          CALL calculate_stretching_factor( number_stretch_level_end, dz,      & 
-                                            dz_stretch_factor,                 &
-                                            dz_stretch_factor_array,           &   
-                                            dz_stretch_level_end,              &
-                                            dz_stretch_level_start )
-       ENDIF
-
-       z(1) = dz(1) * 0.5_dp
-!
-       dz_stretch_level_index = n
-       dz_stretched = dz(1)
-       DO  k = 2, n
-
-          IF ( dz_stretch_level <= z(k-1)  .AND.  dz_stretched < dz_max )  THEN
-
-             dz_stretched = dz_stretched * dz_stretch_factor
-             dz_stretched = MIN( dz_stretched, dz_max )
-
-             IF ( dz_stretch_level_index == n ) dz_stretch_level_index = k-1
-
-          ENDIF
-
-          z(k) = z(k-1) + dz_stretched
-
-       ENDDO
-!--    Determine u and v height levels considering the possibility of grid
-!--    stretching in several heights.
-       n = 1
-       dz_stretch_level_start_index(:) = UBOUND(z, 1)
-       dz_stretch_level_end_index(:) = UBOUND(z, 1)
-       dz_stretched = dz(1)
-
-!--    The default value of dz_stretch_level_start is negative, thus the first
-!--    condition is always true. Hence, the second condition is necessary.
-       DO  k = 2, UBOUND(z, 1)
-          IF ( dz_stretch_level_start(n) <= z(k-1) .AND.                      &
-               dz_stretch_level_start(n) /= -9999999.9_dp ) THEN
-             dz_stretched = dz_stretched * dz_stretch_factor_array(n)
-             
-             IF ( dz(n) > dz(n+1) ) THEN
-                dz_stretched = MAX( dz_stretched, dz(n+1) ) !Restrict dz_stretched to the user-specified (higher) dz
-             ELSE
-                dz_stretched = MIN( dz_stretched, dz(n+1) ) !Restrict dz_stretched to the user-specified (lower) dz
-             ENDIF
-             
-             IF ( dz_stretch_level_start_index(n) == UBOUND(z, 1) )            &
-             dz_stretch_level_start_index(n) = k-1
-             
-          ENDIF
-          
-          z(k) = z(k-1) + dz_stretched
-          
-!
-!--       Make sure that the stretching ends exactly at dz_stretch_level_end 
-          dz_level_end = ABS( z(k) - dz_stretch_level_end(n) ) 
-          
-          IF ( dz_level_end < dz(n+1)/3.0 ) THEN
-             z(k) = dz_stretch_level_end(n)
-             dz_stretched = dz(n+1)
-             dz_stretch_level_end_index(n) = k
-             n = n + 1             
-          ENDIF
-       ENDDO
-
-       DEALLOCATE( min_dz_stretch_level_end )
-
-    END SUBROUTINE stretched_z
-
-
-! Description: [PALM subroutine]
-! -----------------------------------------------------------------------------!
-!> Calculation of the stretching factor through an iterative method. Ideas were 
-!> taken from the paper "Regional stretched grid generation and its application
-!> to the NCAR RegCM (1999)". Normally, no analytic solution exists because the
-!> system of equations has two variables (r,l) but four requirements 
-!> (l=integer, r=[0,88;1,2], Eq(6), Eq(5) starting from index j=1) which
-!> results into an overdetermined system. 
-!------------------------------------------------------------------------------!
- SUBROUTINE calculate_stretching_factor( number_end, dz, dz_stretch_factor,    &
-                                         dz_stretch_factor_array,              &   
-                                         dz_stretch_level_end,                 &
-                                         dz_stretch_level_start )
- 
-    REAL(dp), DIMENSION(:), INTENT(IN)    ::  dz
-    REAL(dp), DIMENSION(:), INTENT(INOUT) ::  dz_stretch_factor_array
-    REAL(dp), DIMENSION(:), INTENT(IN)    ::  dz_stretch_level_end, dz_stretch_level_start
-    REAL(dp)                              ::  dz_stretch_factor
-  
-    INTEGER ::  iterations  !< number of iterations until stretch_factor_lower/upper_limit is reached  
-    INTEGER ::  l_rounded   !< after l_rounded grid levels dz(n) is strechted to dz(n+1) with stretch_factor_2 
-    INTEGER ::  n           !< loop variable for stretching
-    
-    INTEGER, INTENT(IN) ::  number_end !< number of user-specified end levels for stretching
-        
-    REAL(dp) ::  delta_l               !< absolute difference between l and l_rounded
-    REAL(dp) ::  delta_stretch_factor  !< absolute difference between stretch_factor_1 and stretch_factor_2
-    REAL(dp) ::  delta_total_new       !< sum of delta_l and delta_stretch_factor for the next iteration (should be as small as possible) 
-    REAL(dp) ::  delta_total_old       !< sum of delta_l and delta_stretch_factor for the last iteration 
-    REAL(dp) ::  distance              !< distance between dz_stretch_level_start and dz_stretch_level_end (stretching region)
-    REAL(dp) ::  l                     !< value that fulfil Eq. (5) in the paper mentioned above together with stretch_factor_1 exactly
-    REAL(dp) ::  numerator             !< numerator of the quotient
-    REAL(dp) ::  stretch_factor_1      !< stretching factor that fulfil Eq. (5) togehter with l exactly
-    REAL(dp) ::  stretch_factor_2      !< stretching factor that fulfil Eq. (6) togehter with l_rounded exactly
-    
-    REAL(dp) ::  dz_stretch_factor_array_2(9) = 1.08_dp  !< Array that contains all stretch_factor_2 that belongs to stretch_factor_1 
-    
-    REAL(dp), PARAMETER ::  stretch_factor_interval = 1.0E-06  !< interval for sampling possible stretching factors
-    REAL(dp), PARAMETER ::  stretch_factor_lower_limit = 0.88  !< lowest possible stretching factor
-    REAL(dp), PARAMETER ::  stretch_factor_upper_limit = 1.12  !< highest possible stretching factor
- 
- 
-    l = 0
-    DO  n = 1, number_end
-    
-       iterations = 1
-       stretch_factor_1 = 1.0 
-       stretch_factor_2 = 1.0
-       delta_total_old = 1.0
-       
-       IF ( dz(n) > dz(n+1) ) THEN
-          DO WHILE ( stretch_factor_1 >= stretch_factor_lower_limit ) 
-             
-             stretch_factor_1 = 1.0 - iterations * stretch_factor_interval
-             distance = ABS( dz_stretch_level_end(n) -                   &
-                        dz_stretch_level_start(n) ) 
-             numerator = distance*stretch_factor_1/dz(n) +               &
-                         stretch_factor_1 - distance/dz(n)
-             
-             IF ( numerator > 0.0 ) THEN
-                l = LOG( numerator ) / LOG( stretch_factor_1 ) - 1.0
-                l_rounded = NINT( l )
-                delta_l = ABS( l_rounded - l ) / l
-             ENDIF
-             
-             stretch_factor_2 = EXP( LOG( dz(n+1)/dz(n) ) / (l_rounded) )
-             
-             delta_stretch_factor = ABS( stretch_factor_1 -              &
-                                         stretch_factor_2 ) /            &
-                                    stretch_factor_2
-             
-             delta_total_new = delta_l + delta_stretch_factor
-
-!
-!--                stretch_factor_1 is taken to guarantee that the stretching
-!--                procedure ends as close as possible to dz_stretch_level_end.
-!--                stretch_factor_2 would guarantee that the stretched dz(n) is
-!--                equal to dz(n+1) after l_rounded grid levels.
-             IF (delta_total_new < delta_total_old) THEN
-                dz_stretch_factor_array(n) = stretch_factor_1
-                dz_stretch_factor_array_2(n) = stretch_factor_2
-                delta_total_old = delta_total_new
-             ENDIF
-             
-             iterations = iterations + 1
-            
-          ENDDO
-             
-       ELSEIF ( dz(n) < dz(n+1) ) THEN 
-          DO WHILE ( stretch_factor_1 <= stretch_factor_upper_limit )
-                     
-             stretch_factor_1 = 1.0 + iterations * stretch_factor_interval
-             distance = ABS( dz_stretch_level_end(n) -                      &
-                        dz_stretch_level_start(n) ) 
-             numerator = distance*stretch_factor_1/dz(n) +                  &
-                         stretch_factor_1 - distance/dz(n)
-             
-             l = LOG( numerator ) / LOG( stretch_factor_1 ) - 1.0
-             l_rounded = NINT( l )
-             delta_l = ABS( l_rounded - l ) / l
-             
-             stretch_factor_2 = EXP( LOG( dz(n+1)/dz(n) ) / (l_rounded) )
-
-             delta_stretch_factor = ABS( stretch_factor_1 -                 &
-                                        stretch_factor_2 ) /                &
-                                        stretch_factor_2
-             
-             delta_total_new = delta_l + delta_stretch_factor
-             
-!
-!--                stretch_factor_1 is taken to guarantee that the stretching
-!--                procedure ends as close as possible to dz_stretch_level_end.
-!--                stretch_factor_2 would guarantee that the stretched dz(n) is
-!--                equal to dz(n+1) after l_rounded grid levels.
-             IF (delta_total_new < delta_total_old) THEN
-                dz_stretch_factor_array(n) = stretch_factor_1
-                dz_stretch_factor_array_2(n) = stretch_factor_2
-                delta_total_old = delta_total_new
-             ENDIF
-             
-             iterations = iterations + 1
-          ENDDO
-          
-       ELSE
-          message = 'Two adjacent values of dz must be different'
-          CALL abort( 'calculate_stretching_factor', message)
-       ENDIF
-
-!
-!--    Check if also the second stretching factor fits into the allowed
-!--    interval. If not, print a warning for the user.
-       IF ( dz_stretch_factor_array_2(n) < stretch_factor_lower_limit .OR.     & 
-            dz_stretch_factor_array_2(n) > stretch_factor_upper_limit ) THEN
-          WRITE( message, * ) 'stretch_factor_2 = ',                    &
-                                     dz_stretch_factor_array_2(n), ' which is',&
-                                     ' responsible for exactly reaching& dz =',&
-                                      dz(n+1), 'after a specific amount of',   & 
-                                     ' grid levels& exceeds the upper',        &
-                                     ' limit =', stretch_factor_upper_limit,   &
-                                     ' &or lower limit = ',                    &
-                                     stretch_factor_lower_limit
-          CALL abort( 'calculate_stretching_factor', message )
-            
-       ENDIF
-    ENDDO
-        
- END SUBROUTINE calculate_stretching_factor
-
-    SUBROUTINE midpoints(z, zw)
-
-        REAL(dp), INTENT(IN)  ::  z(0:)
-        REAL(dp), INTENT(OUT) ::  zw(1:)
-
-        INTEGER ::  k
-
-        DO k = 1, UBOUND(zw, 1)
-           zw(k) = 0.5_dp * (z(k-1) + z(k))
-        END DO
-
-    END SUBROUTINE midpoints
-
-
-    SUBROUTINE setup_io_groups()
-
-       INTEGER ::  ngroups
-
-       ngroups = 16
-       ALLOCATE( io_group_list(ngroups) )
-       
-       !soil temp
-       io_group_list(1) = init_io_group(                                       &
-          in_files = soil_files,                                               &
-          out_vars = output_var_table(1:1),                                    &
-          in_var_list = input_var_table(1:1),                                  &
-          kind = 'soil-temperature'                                            &
-       )
-
-       !soil water
-       io_group_list(2) = init_io_group(                                       &
-          in_files = soil_files,                                               &
-          out_vars = output_var_table(2:2),                                    &
-          in_var_list = input_var_table(2:2),                                  &
-          kind = 'soil-water'                                                  &
-       )
-
-       !potential temperature, surface pressure, specific humidity including
-       !nudging and subsidence, and geostrophic winds ug, vg
-       io_group_list(3) = init_io_group(                                       &
-          in_files = flow_files,                                               &
-          out_vars = [output_var_table(56:64),                                 & ! internal averaged density and pressure profiles
-                      output_var_table(3:8), output_var_table(9:14),           &
-                      output_var_table(42:42), output_var_table(43:44),        &
-                      output_var_table(49:51), output_var_table(52:54)],       &
-          in_var_list = (/input_var_table(3), input_var_table(17),             & ! T, P, QV
-                          input_var_table(4) /),                               &
-          kind = 'thermodynamics',                                             &
-          n_output_quantities = 4                                              & ! P, Theta, Rho, qv
-       )
-
-       !Moved to therodynamic io_group
-       !io_group_list(4) = init_io_group(                                       &
-       !   in_files = flow_files,                                               &
-       !   out_vars = [output_var_table(9:14), output_var_table(52:54)],        &
-       !   in_var_list = input_var_table(4:4),                                  &
-       !   kind = 'scalar'                                                      &
-       !)
-
-       !u and v velocity, ug anv vg moved to thermodynamic io group. 
-       io_group_list(5) = init_io_group(                                       &
-          in_files = flow_files,                                               &
-          out_vars = [output_var_table(15:26), output_var_table(45:46)],       &
-          !out_vars = output_var_table(15:20),                                  &
-          in_var_list = input_var_table(5:6),                                  &
-          !in_var_list = input_var_table(5:5),                                  &
-          kind = 'velocities'                                                  &
-       )
-   
-       !!v velocity, deprecated!
-       !io_group_list(6) = init_io_group(                                       &
-       !   in_files = flow_files,                                               &
-       !   out_vars = output_var_table(21:26),                                  &
-       !   in_var_list = input_var_table(6:6),                                  &
-       !   kind = 'horizontal velocity'                                         &
-       !)
-       !io_group_list(6) % to_be_processed = .FALSE.
-   
-       !w velocity and subsidence and w nudging
-       io_group_list(7) = init_io_group(                                       &
-          in_files = flow_files,                                               &
-          out_vars = [output_var_table(27:32), output_var_table(47:48)],       &
-          in_var_list = input_var_table(7:7),                                  &
-          kind = 'scalar'                                                      &
-       )
-
-       !rain
-       io_group_list(8) = init_io_group(                                       &
-          in_files = soil_moisture_files,                                      &
-          out_vars = output_var_table(33:33),                                  &
-          in_var_list = input_var_table(8:8),                                  &
-          kind = 'accumulated'                                                 &
-       )
-       io_group_list(8) % to_be_processed = .FALSE.
-
-       !snow
-       io_group_list(9) = init_io_group(                                       &
-          in_files = soil_moisture_files,                                      &
-          out_vars = output_var_table(34:34),                                  &
-          in_var_list = input_var_table(9:9),                                  &
-          kind = 'accumulated'                                                 &
-       )
-       io_group_list(9) % to_be_processed = .FALSE.
-
-       !graupel
-       io_group_list(10) = init_io_group(                                      &
-          in_files = soil_moisture_files,                                      &
-          out_vars = output_var_table(35:35),                                  &
-          in_var_list = input_var_table(10:10),                                &
-          kind = 'accumulated'                                                 &
-       )
-       io_group_list(10) % to_be_processed = .FALSE.
-
-       !evapotranspiration
-       io_group_list(11) = init_io_group(                                      &
-          in_files = soil_moisture_files,                                      &
-          out_vars = output_var_table(37:37),                                  &
-          in_var_list = input_var_table(11:11),                                &
-          kind = 'accumulated'                                                 &
-       )
-       io_group_list(11) % to_be_processed = .FALSE.
-
-       !2m air temperature
-       io_group_list(12) = init_io_group(                                      &
-          in_files = soil_moisture_files,                                      &
-          out_vars = output_var_table(36:36),                                  &
-          in_var_list = input_var_table(12:12),                                &
-          kind = 'surface'                                                     &
-       )
-
-       !incoming diffusive sw flux
-       io_group_list(13) = init_io_group(                                      &
-          in_files = radiation_files,                                          &
-          out_vars = output_var_table(38:38),                                  &
-          in_var_list = input_var_table(13:13),                                &
-          kind = 'running average'                                             &
-       )
-       io_group_list(13) % to_be_processed = .FALSE.
-
-       !incoming direct sw flux
-       io_group_list(14) = init_io_group(                                      &
-          in_files = radiation_files,                                          &
-          out_vars = output_var_table(39:39),                                  &
-          in_var_list = input_var_table(14:14),                                &
-          kind = 'running average'                                             &
-       )
-       io_group_list(14) % to_be_processed = .FALSE.
-
-       !sw radiation balance
-       io_group_list(15) = init_io_group(                                      &
-          in_files = radiation_files,                                          &
-          out_vars = output_var_table(40:40),                                  &
-          in_var_list = input_var_table(15:15),                                &
-          kind = 'running average'                                             &
-       )
-       io_group_list(15) % to_be_processed = .FALSE.
-
-       !lw radiation balance
-       io_group_list(16) = init_io_group(                                      &
-          in_files = radiation_files,                                          &
-          out_vars = output_var_table(41:41),                                  &
-          in_var_list = input_var_table(16:16),                                &
-          kind = 'running average'                                             &
-       )
-       io_group_list(16) % to_be_processed = .FALSE.
-
-    END SUBROUTINE setup_io_groups
-
-
-    FUNCTION init_io_group(in_files, out_vars, in_var_list, kind,              &
-                           n_output_quantities) RESULT(group)
-       CHARACTER(LEN=PATH), INTENT(IN) ::  in_files(:)
-       CHARACTER(LEN=*), INTENT(IN)    ::  kind
-       TYPE(nc_var), INTENT(IN)        ::  out_vars(:)
-       TYPE(nc_var), INTENT(IN)        ::  in_var_list(:)
-       INTEGER, OPTIONAL               ::  n_output_quantities
-
-       TYPE(io_group)                  ::  group
-
-       group % nt = SIZE(in_files)
-       group % nv = SIZE(out_vars)
-       group % n_inputs = SIZE(in_var_list)
-       group % kind = TRIM(kind)
-
-       IF ( PRESENT(n_output_quantities) )  THEN
-          group % n_output_quantities = n_output_quantities
-       ELSE
-          group % n_output_quantities = group % n_inputs
-       END IF
-
-       ALLOCATE(group % in_var_list(group % n_inputs))
-       ALLOCATE(group % in_files(group % nt))
-       ALLOCATE(group % out_vars(group % nv))
-
-       group % in_var_list = in_var_list
-       group % in_files = in_files
-       group % out_vars = out_vars
-       group % to_be_processed = .TRUE.
-
-    END FUNCTION init_io_group
-
-
-!------------------------------------------------------------------------------!
-! Description:
-! ------------
-!> Deallocates all allocated variables.
-!------------------------------------------------------------------------------!
-    SUBROUTINE fini_grids()
-
-       CALL report('fini_grids', 'Deallocating grids', cfg % debug)
-       
-       DEALLOCATE(x, y, z, xu, yv, zw, z_column, zw_column)
-
-       DEALLOCATE(palm_grid%x,  palm_grid%y,  palm_grid%z,                     &
-                  palm_grid%xu, palm_grid%yv, palm_grid%zw,                    &
-                  palm_grid%clon,  palm_grid%clat,                             &
-                  palm_grid%clonu, palm_grid%clatu)
-
-       DEALLOCATE(palm_intermediate%x,  palm_intermediate%y,  palm_intermediate%z, &
-                  palm_intermediate%xu, palm_intermediate%yv, palm_intermediate%zw,&
-                  palm_intermediate%clon,  palm_intermediate%clat,             &  
-                  palm_intermediate%clonu, palm_intermediate%clatu)
-
-       DEALLOCATE(cosmo_grid%lon,  cosmo_grid%lat,                             &
-                  cosmo_grid%lonu, cosmo_grid%latv,                            &
-                  cosmo_grid%hfl)
-
-    END SUBROUTINE fini_grids
-
-
-!------------------------------------------------------------------------------!
-! Description:
-! ------------
-!> Initializes the the variable list.
-!------------------------------------------------------------------------------!
-    SUBROUTINE setup_variable_tables(ic_mode)
-       CHARACTER(LEN=*), INTENT(IN) ::  ic_mode
-       INTEGER                      ::  n_invar = 0  !< number of variables in the input variable table
-       INTEGER                      ::  n_outvar = 0 !< number of variables in the output variable table
-       TYPE(nc_var), POINTER        ::  var
-
-       IF (TRIM(cfg % start_date) == '')  THEN
-          message = 'Simulation start date has not been set.'
-          CALL abort('setup_variable_tables', message)
-       END IF
-
-       nc_source_text = 'COSMO-DE analysis from ' // TRIM(cfg % start_date)
-
-       n_invar = 17
-       n_outvar = 64
-       ALLOCATE( input_var_table(n_invar) )
-       ALLOCATE( output_var_table(n_outvar) )
-
-!
-!------------------------------------------------------------------------------
-!- Section 1: NetCDF input variables
-!------------------------------------------------------------------------------
-       var => input_var_table(1)
-       var % name = 'T_SO'
-       var % to_be_processed = .TRUE.
-       var % is_upside_down = .FALSE.
-
-       var => input_var_table(2)
-       var % name = 'W_SO'
-       var % to_be_processed = .TRUE.
-       var % is_upside_down = .FALSE.
-
-       var => input_var_table(3)
-       var % name = 'T'
-       var % to_be_processed = .TRUE.
-       var % is_upside_down = .TRUE.
-
-       var => input_var_table(4)
-       var % name = 'QV'
-       var % to_be_processed = .TRUE.
-       var % is_upside_down = .TRUE.
-
-       var => input_var_table(5)
-       var % name = 'U'
-       var % to_be_processed = .TRUE.
-       var % is_upside_down = .TRUE.
-
-       var => input_var_table(6)
-       var % name = 'V'
-       var % to_be_processed = .TRUE.
-       var % is_upside_down = .TRUE.
-
-       var => input_var_table(7)
-       var % name = 'W'
-       var % to_be_processed = .TRUE.
-       var % is_upside_down = .TRUE.
-
-       var => input_var_table(8)
-       var % name = 'RAIN_GSP'
-       var % to_be_processed = .TRUE.
-       var % is_upside_down = .FALSE.
-
-       var => input_var_table(9)
-       var % name = 'SNOW_GSP'
-       var % to_be_processed = .TRUE.
-       var % is_upside_down = .FALSE.
-
-       var => input_var_table(10)
-       var % name = 'GRAU_GSP'
-       var % to_be_processed = .TRUE.
-       var % is_upside_down = .FALSE.
-
-       var => input_var_table(11)
-       var % name = 'AEVAP_S'
-       var % to_be_processed = .TRUE.
-       var % is_upside_down = .FALSE.
-
-       var => input_var_table(12)
-       var % name = 'T_2M'
-       var % to_be_processed = .TRUE.
-       var % is_upside_down = .FALSE.
-
-       var => input_var_table(13)
-       var % name = 'ASWDIFD_S'
-       var % to_be_processed = .TRUE.
-       var % is_upside_down = .FALSE.
-
-       var => input_var_table(14)
-       var % name = 'ASWDIR_S'
-       var % to_be_processed = .TRUE.
-       var % is_upside_down = .FALSE.
-
-       var => input_var_table(15)
-       var % name = 'ASOB_S'
-       var % to_be_processed = .TRUE.
-       var % is_upside_down = .FALSE.
-
-       var => input_var_table(16)
-       var % name = 'ATHB_S'
-       var % to_be_processed = .TRUE.
-       var % is_upside_down = .FALSE.
-
-       var => input_var_table(17)
-       var % name = 'P'
-       var % to_be_processed = .TRUE.
-       var % is_upside_down = .TRUE.
-
-!
-!------------------------------------------------------------------------------
-!- Section 2: NetCDF output variables
-!------------------------------------------------------------------------------
-!
-!------------------------------------------------------------------------------
-! Section 2.1: Realistic forcings, i.e. 3D initial and boundary conditions
-!------------------------------------------------------------------------------
-       output_var_table(1) = init_nc_var(                                      &
-          name              = 'init_soil_t',                                   &
-          std_name          = "",                                              &
-          long_name         = "initial soil temperature",                      &
-          units             = "K",                                             &
-          kind              = "init soil",                                     &
-          input_id          = 1,                                               &
-          output_file       = output_file,                                     &
-          grid              = palm_grid,                                       &
-          intermediate_grid = palm_intermediate                                &
-       )
-
-       output_var_table(2) = init_nc_var(                                      &
-          name              = 'init_soil_m',                                   &
-          std_name          = "",                                              &
-          long_name         = "initial soil moisture",                         &
-          units             = "m^3/m^3",                                       &
-          kind              = "init soil",                                     &
-          input_id          = 1,                                               &
-          output_file       = output_file,                                     &
-          grid              = palm_grid,                                       &
-          intermediate_grid = palm_intermediate                                &
-       )
-
-       output_var_table(3) = init_nc_var(                                      &
-          name              = 'init_atmosphere_pt',                            &
-          std_name          = "",                                              &
-          long_name         = "initial potential temperature",                 &
-          units             = "K",                                             &
-          kind              = "init scalar",                                   &
-          input_id          = 1,                                               & ! first in (T, p) IO group
-          output_file       = output_file,                                     &
-          grid              = palm_grid,                                       &
-          intermediate_grid = palm_intermediate,                               &
-          is_profile = (TRIM(ic_mode) == 'profile')                            &
-       )
-       IF (TRIM(ic_mode) == 'profile')  THEN
-          output_var_table(3) % averaging_grid => averaged_scalar_profile
-       END IF
-
-       output_var_table(4) = init_nc_var(                                      &
-          name              = 'ls_forcing_left_pt',                            &
-          std_name          = "",                                              &
-          long_name         = "large-scale forcing for left model boundary for the potential temperature", &
-          units             = "K",                                             &
-          kind              = "left scalar",                                   &
-          input_id          = 1,                                               &
-          grid              = scalars_west_grid,                               &
-          intermediate_grid = scalars_west_intermediate,                       &
-          output_file = output_file                                            &
-       )
-
-       output_var_table(5) = init_nc_var(                                      &
-          name              = 'ls_forcing_right_pt',                           &
-          std_name          = "",                                              &
-          long_name         = "large-scale forcing for right model boundary for the potential temperature", &
-          units             = "K",                                             &
-          kind              = "right scalar",                                  &
-          input_id          = 1,                                               &
-          grid              = scalars_east_grid,                               &
-          intermediate_grid = scalars_east_intermediate,                       &
-          output_file = output_file                                            &
-       )
-
-       output_var_table(6) = init_nc_var(                                      &
-          name              = 'ls_forcing_north_pt',                           &
-          std_name          = "",                                              &
-          long_name         = "large-scale forcing for north model boundary for the potential temperature", &
-          units             = "K",                                             &
-          kind              = "north scalar",                                  &
-          input_id          = 1,                                               &
-          grid              = scalars_north_grid,                              &
-          intermediate_grid = scalars_north_intermediate,                      &
-          output_file = output_file                                            &
-       )
-
-       output_var_table(7) = init_nc_var(                                      &
-          name              = 'ls_forcing_south_pt',                           &
-          std_name          = "",                                              &
-          long_name         = "large-scale forcing for south model boundary for the potential temperature", &
-          units             = "K",                                             &
-          kind              = "south scalar",                                  &
-          input_id          = 1,                                               &
-          grid              = scalars_south_grid,                              &
-          intermediate_grid = scalars_south_intermediate,                      &
-          output_file = output_file                                            &
-       )
-
-       output_var_table(8) = init_nc_var(                                      &
-          name              = 'ls_forcing_top_pt',                             &
-          std_name          = "",                                              &
-          long_name         = "large-scale forcing for top model boundary for the potential temperature", &
-          units             = "K",                                             &
-          kind              = "top scalar",                                    &
-          input_id          = 1,                                               &
-          grid              = scalars_top_grid,                                &
-          intermediate_grid = scalars_top_intermediate,                        &
-          output_file = output_file                                            &
-       )
-
-       output_var_table(9) = init_nc_var(                                      &
-          name              = 'init_atmosphere_qv',                            &
-          std_name          = "",                                              &
-          long_name         = "initial specific humidity",                     &
-          units             = "kg/kg",                                         &
-          kind              = "init scalar",                                   &
-          input_id          = 3,                                               &
-          output_file       = output_file,                                     &
-          grid              = palm_grid,                                       &
-          intermediate_grid = palm_intermediate,                               &
-          is_profile = (TRIM(ic_mode) == 'profile')                            &
-       )
-       IF (TRIM(ic_mode) == 'profile')  THEN
-          output_var_table(9) % averaging_grid => averaged_scalar_profile
-       END IF
-
-       output_var_table(10) = init_nc_var(                                     &
-          name              = 'ls_forcing_left_qv',                            &
-          std_name          = "",                                              &
-          long_name         = "large-scale forcing for left model boundary for the specific humidity", &
-          units             = "kg/kg",                                         &
-          kind              = "left scalar",                                   &
-          input_id          = 3,                                               &
-          output_file       = output_file,                                     &
-          grid              = scalars_west_grid,                               &
-          intermediate_grid = scalars_west_intermediate                        &
-       )
-
-       output_var_table(11) = init_nc_var(                                     &
-          name              = 'ls_forcing_right_qv',                           &
-          std_name          = "",                                              &
-          long_name         = "large-scale forcing for right model boundary for the specific humidity", &
-          units             = "kg/kg",                                         &
-          kind              = "right scalar",                                  &
-          input_id          = 3,                                               &
-          output_file       = output_file,                                     &
-          grid              = scalars_east_grid,                               &
-          intermediate_grid = scalars_east_intermediate                        &
-       )
-
-       output_var_table(12) = init_nc_var(                                     &
-          name              = 'ls_forcing_north_qv',                           &
-          std_name          = "",                                              &
-          long_name         = "large-scale forcing for north model boundary for the specific humidity", &
-          units             = "kg/kg",                                         &
-          kind              = "north scalar",                                  &
-          input_id          = 3,                                               &
-          output_file       = output_file,                                     &
-          grid              = scalars_north_grid,                              &
-          intermediate_grid = scalars_north_intermediate                       &
-       )
-
-       output_var_table(13) = init_nc_var(                                     &
-          name              = 'ls_forcing_south_qv',                           &
-          std_name          = "",                                              &
-          long_name         = "large-scale forcing for south model boundary for the specific humidity", &
-          units             = "kg/kg",                                         &
-          kind              = "south scalar",                                  &
-          input_id          = 3,                                               &
-          output_file       = output_file,                                     &
-          grid              = scalars_south_grid,                              &
-          intermediate_grid = scalars_south_intermediate                       &
-       )
-
-       output_var_table(14) = init_nc_var(                                     &
-          name              = 'ls_forcing_top_qv',                             &
-          std_name          = "",                                              &
-          long_name         = "large-scale forcing for top model boundary for the specific humidity", &
-          units             = "kg/kg",                                         &
-          kind              = "top scalar",                                    &
-          input_id          = 3,                                               &
-          output_file       = output_file,                                     &
-          grid              = scalars_top_grid,                                &
-          intermediate_grid = scalars_top_intermediate                         &
-       )
-
-       output_var_table(15) = init_nc_var(                                     &
-          name              = 'init_atmosphere_u',                             &
-          std_name          = "",                                              &
-          long_name         = "initial wind component in x direction",         &
-          units             = "m/s",                                           &
-          kind              = "init u",                                        &
-          input_id          = 1,                                               & ! first in (U, V) I/O group
-          output_file       = output_file,                                     &
-          grid              = u_initial_grid,                                  &
-          intermediate_grid = u_initial_intermediate,                          &
-          is_profile = (TRIM(ic_mode) == 'profile')                            &
-       )
-       IF (TRIM(ic_mode) == 'profile')  THEN
-          output_var_table(15) % averaging_grid => averaged_scalar_profile
-       END IF 
-
-       output_var_table(16) = init_nc_var(                                     &
-          name              = 'ls_forcing_left_u',                             &
-          std_name          = "",                                              &
-          long_name         = "large-scale forcing for left model boundary for the wind component in x direction", &
-          units             = "m/s",                                           &
-          kind              = "left u",                                        &
-          input_id          = 1,                                               & ! first in (U, V) I/O group
-          output_file       = output_file,                                     &
-          grid              = u_west_grid,                                     &
-          intermediate_grid = u_west_intermediate                              &
-       )
-
-       output_var_table(17) = init_nc_var(                                     &
-          name              = 'ls_forcing_right_u',                            &
-          std_name          = "",                                              &
-          long_name         = "large-scale forcing for right model boundary for the wind component in x direction", &
-          units             = "m/s",                                           &
-          kind              = "right u",                                       &
-          input_id          = 1,                                               & ! first in (U, V) I/O group
-          output_file       = output_file,                                     &
-          grid              = u_east_grid,                                     &
-          intermediate_grid = u_east_intermediate                              &
-       )
-
-       output_var_table(18) = init_nc_var(                                     &
-          name              = 'ls_forcing_north_u',                            &
-          std_name          = "",                                              &
-          long_name         = "large-scale forcing for north model boundary for the wind component in x direction", &
-          units             = "m/s",                                           &
-          kind              = "north u",                                       &
-          input_id          = 1,                                               & ! first in (U, V) I/O group
-          output_file       = output_file,                                     &
-          grid              = u_north_grid,                                    &
-          intermediate_grid = u_north_intermediate                             &
-       )
-
-       output_var_table(19) = init_nc_var(                                     &
-          name              = 'ls_forcing_south_u',                            &
-          std_name          = "",                                              &
-          long_name         = "large-scale forcing for south model boundary for the wind component in x direction", &
-          units             = "m/s",                                           &
-          kind              = "south u",                                       &
-          input_id          = 1,                                               & ! first in (U, V) I/O group
-          output_file       = output_file,                                     &
-          grid              = u_south_grid,                                    &
-          intermediate_grid = u_south_intermediate                             &
-       )
-
-       output_var_table(20) = init_nc_var(                                     &
-          name              = 'ls_forcing_top_u',                              &
-          std_name          = "",                                              &
-          long_name         = "large-scale forcing for top model boundary for the wind component in x direction", &
-          units             = "m/s",                                           &
-          kind              = "top u",                                         &
-          input_id          = 1,                                               & ! first in (U, V) I/O group
-          output_file       = output_file,                                     &
-          grid              = u_top_grid,                                      &
-          intermediate_grid = u_top_intermediate                               &
-       )
-
-       output_var_table(21) = init_nc_var(                                     &
-          name              = 'init_atmosphere_v',                             &
-          std_name          = "",                                              &
-          long_name         = "initial wind component in y direction",         &
-          units             = "m/s",                                           &
-          kind              = "init v",                                        &
-          input_id          = 2,                                               & ! second in (U, V) I/O group
-          output_file       = output_file,                                     &
-          grid              = v_initial_grid,                                  &
-          intermediate_grid = v_initial_intermediate,                          &
-          is_profile = (TRIM(ic_mode) == 'profile')                            &
-       )
-       IF (TRIM(ic_mode) == 'profile')  THEN
-          output_var_table(21) % averaging_grid => averaged_scalar_profile
-       END IF
-
-       output_var_table(22) = init_nc_var(                                     &
-          name              = 'ls_forcing_left_v',                             &
-          std_name          = "",                                              &
-          long_name         = "large-scale forcing for left model boundary for the wind component in y direction", &
-          units             = "m/s",                                           &
-          kind              = "right v",                                       &
-          input_id          = 2,                                               & ! second in (U, V) I/O group
-          output_file       = output_file,                                     &
-          grid              = v_west_grid,                                     &
-          intermediate_grid = v_west_intermediate                              &
-       )
-
-       output_var_table(23) = init_nc_var(                                     &
-          name              = 'ls_forcing_right_v',                            &
-          std_name          = "",                                              &
-          long_name         = "large-scale forcing for right model boundary for the wind component in y direction", &
-          units             = "m/s",                                           &
-          kind              = "right v",                                       &
-          input_id          = 2,                                               & ! second in (U, V) I/O group
-          output_file       = output_file,                                     &
-          grid              = v_east_grid,                                     &
-          intermediate_grid = v_east_intermediate                              &
-       )
-
-       output_var_table(24) = init_nc_var(                                     &
-          name              = 'ls_forcing_north_v',                            &
-          std_name          = "",                                              &
-          long_name         = "large-scale forcing for north model boundary for the wind component in y direction", &
-          units             = "m/s",                                           &
-          kind              = "north v",                                       &
-          input_id          = 2,                                               & ! second in (U, V) I/O group
-          output_file       = output_file,                                     &
-          grid              = v_north_grid,                                    &
-          intermediate_grid = v_north_intermediate                             &
-       )
-
-       output_var_table(25) = init_nc_var(                                     &
-          name              = 'ls_forcing_south_v',                            &
-          std_name          = "",                                              &
-          long_name         = "large-scale forcing for south model boundary for the wind component in y direction", &
-          units             = "m/s",                                           &
-          kind              = "south v",                                       &
-          input_id          = 2,                                               & ! second in (U, V) I/O group
-          output_file       = output_file,                                     &
-          grid              = v_south_grid,                                    &
-          intermediate_grid = v_south_intermediate                             &
-       )
-
-       output_var_table(26) = init_nc_var(                                     &
-          name              = 'ls_forcing_top_v',                              &
-          std_name          = "",                                              &
-          long_name         = "large-scale forcing for top model boundary for the wind component in y direction", &
-          units             = "m/s",                                           &
-          kind              = "top v",                                         &
-          input_id          = 2,                                               & ! second in (U, V) I/O group
-          output_file       = output_file,                                     &
-          grid              = v_top_grid,                                      &
-          intermediate_grid = v_top_intermediate                               &
-       )
-
-       output_var_table(27) = init_nc_var(                                     &
-          name              = 'init_atmosphere_w',                             &
-          std_name          = "",                                              &
-          long_name         = "initial wind component in z direction",         &
-          units             = "m/s",                                           &
-          kind              = "init w",                                        &
-          input_id          = 1,                                               &
-          output_file       = output_file,                                     &
-          grid              = w_initial_grid,                                  &
-          intermediate_grid = w_initial_intermediate,                          &
-          is_profile = (TRIM(ic_mode) == 'profile')                            &
-       )
-       IF (TRIM(ic_mode) == 'profile')  THEN
-          output_var_table(27) % averaging_grid => averaged_w_profile
-       END IF
-
-       output_var_table(28) = init_nc_var(                                     &
-          name              = 'ls_forcing_left_w',                             &
-          std_name          = "",                                              &
-          long_name         = "large-scale forcing for left model boundary for the wind component in z direction", &
-          units             = "m/s",                                           &
-          kind              = "left w",                                        &
-          input_id          = 1,                                               &
-          output_file       = output_file,                                     &
-          grid              = w_west_grid,                                     &
-          intermediate_grid = w_west_intermediate                              &
-       )
-
-       output_var_table(29) = init_nc_var(                                     &
-          name              = 'ls_forcing_right_w',                            &
-          std_name          = "",                                              &
-          long_name         = "large-scale forcing for right model boundary for the wind component in z direction", &
-          units             = "m/s",                                           &
-          kind              = "right w",                                       &
-          input_id          = 1,                                               &
-          output_file       = output_file,                                     &
-          grid              = w_east_grid,                                     &
-          intermediate_grid = w_east_intermediate                              &
-       )
-
-       output_var_table(30) = init_nc_var(                                     &
-          name              = 'ls_forcing_north_w',                            &
-          std_name          = "",                                              &
-          long_name         = "large-scale forcing for north model boundary for the wind component in z direction", &
-          units             = "m/s",                                           &
-          kind              = "north w",                                       &
-          input_id          = 1,                                               &
-          output_file       = output_file,                                     &
-          grid              = w_north_grid,                                    &
-          intermediate_grid = w_north_intermediate                             &
-       )
-
-       output_var_table(31) = init_nc_var(                                     &
-          name              = 'ls_forcing_south_w',                            &
-          std_name          = "",                                              &
-          long_name         = "large-scale forcing for south model boundary for the wind component in z direction", &
-          units             = "m/s",                                           &
-          kind              = "south w",                                       &
-          input_id          = 1,                                               &
-          output_file       = output_file,                                     &
-          grid              = w_south_grid,                                    &
-          intermediate_grid = w_south_intermediate                             &
-       )
-
-       output_var_table(32) = init_nc_var(                                     &
-          name              = 'ls_forcing_top_w',                              &
-          std_name          = "",                                              &
-          long_name         = "large-scale forcing for top model boundary for the wind component in z direction", &
-          units             = "m/s",                                           &
-          kind              = "top w",                                         &
-          input_id          = 1,                                               &
-          output_file       = output_file,                                     &
-          grid              = w_top_grid,                                      &
-          intermediate_grid = w_top_intermediate                               &
-       )
-
-       output_var_table(33) = init_nc_var(                                     &
-          name              = 'ls_forcing_soil_rain',                          &
-          std_name          = "",                                              &
-          long_name         = "large-scale forcing rain",                      &
-          units             = "kg/m2",                                         &
-          kind              = "surface forcing",                               &
-          input_id          = 1,                                               &
-          output_file       = output_file,                                     &
-          grid              = palm_grid,                                       &
-          intermediate_grid = palm_intermediate                                &
-       )
-
-       output_var_table(34) = init_nc_var(                                     &
-          name              = 'ls_forcing_soil_snow',                          &
-          std_name          = "",                                              &
-          long_name         = "large-scale forcing snow",                      &
-          units             = "kg/m2",                                         &
-          kind              = "surface forcing",                               &
-          input_id          = 1,                                               &
-          output_file       = output_file,                                     &
-          grid              = palm_grid,                                       &
-          intermediate_grid = palm_intermediate                                &
-       )
-
-       output_var_table(35) = init_nc_var(                                     &
-          name              = 'ls_forcing_soil_graupel',                       &
-          std_name          = "",                                              &
-          long_name         = "large-scale forcing graupel",                   &
-          units             = "kg/m2",                                         &
-          kind              = "surface forcing",                               &
-          input_id          = 1,                                               &
-          output_file       = output_file,                                     &
-          grid              = palm_grid,                                       &
-          intermediate_grid = palm_intermediate                                &
-       )
-
-       output_var_table(36) = init_nc_var(                                     &
-          name              = 'ls_forcing_soil_t_2m',                          &
-          std_name          = "",                                              &
-          long_name         = "large-scale forcing 2m air temperature",        &
-          units             = "kg/m2",                                         &
-          kind              = "surface forcing",                               &
-          input_id          = 1,                                               &
-          output_file       = output_file,                                     &
-          grid              = palm_grid,                                       &
-          intermediate_grid = palm_intermediate                                &
-       )
-
-       output_var_table(37) = init_nc_var(                                     &
-          name              = 'ls_forcing_soil_evap',                          &
-          std_name          = "",                                              &
-          long_name         = "large-scale forcing evapo-transpiration",       &
-          units             = "kg/m2",                                         &
-          kind              = "surface forcing",                               &
-          input_id          = 1,                                               &
-          output_file       = output_file,                                     &
-          grid              = palm_grid,                                       &
-          intermediate_grid = palm_intermediate                                &
-       )
-       ! Radiation fluxes and balances
-       output_var_table(38) = init_nc_var(                                     &
-          name              = 'rad_swd_dif_0',                                 &
-          std_name          = "",                                              &
-          long_name         = "incoming diffuse shortwave radiative flux at the surface", &
-          units             = "W/m2",                                          &
-          kind              = "surface forcing",                               &
-          input_id          = 1,                                               &
-          output_file       = output_file,                                     &
-          grid              = palm_grid,                                       &
-          intermediate_grid = palm_intermediate                                &
-       )
-
-       output_var_table(39) = init_nc_var(                                     &
-          name              = 'rad_swd_dir_0',                                 &
-          std_name          = "",                                              &
-          long_name         = "incoming direct shortwave radiative flux at the surface", &
-          units             = "W/m2",                                          &
-          kind              = "surface forcing",                               &
-          input_id          = 1,                                               &
-          output_file       = output_file,                                     &
-          grid              = palm_grid,                                       &
-          intermediate_grid = palm_intermediate                                &
-       )
-
-       output_var_table(40) = init_nc_var(                                     &
-          name              = 'rad_sw_bal_0',                                  &
-          std_name          = "",                                              &
-          long_name         = "shortwave radiation balance at the surface",    &
-          units             = "W/m2",                                          &
-          kind              = "surface forcing",                               &
-          input_id          = 1,                                               &
-          output_file       = output_file,                                     &
-          grid              = palm_grid,                                       &
-          intermediate_grid = palm_intermediate                                &
-       )
-
-       output_var_table(41) = init_nc_var(                                     &
-          name              = 'rad_lw_bal_0',                                  &
-          std_name          = "",                                              &
-          long_name         = "longwave radiation balance at the surface",     &
-          units             = "W/m2",                                          &
-          kind              = "surface forcing",                               &
-          input_id          = 1,                                               &
-          output_file       = output_file,                                     &
-          grid              = palm_grid,                                       &
-          intermediate_grid = palm_intermediate                                &
-       )
-!
-!------------------------------------------------------------------------------
-! Section 2.2: Idealized large-scale forcings
-!------------------------------------------------------------------------------
-       output_var_table(42) = init_nc_var(                                     &
-          name              = 'surface_forcing_surface_pressure',              &
-          std_name          = "",                                              &
-          long_name         = "surface pressure",                              &
-          units             = "Pa",                                            &
-          kind              = "time series",                                   &
-          input_id          = 2,                                               & ! second in (T, p) I/O group
-          output_file       = output_file,                                     &
-          grid              = palm_grid,                                       &
-          intermediate_grid = palm_intermediate                                &
-       )
-       output_var_table(42) % averaging_grid => averaged_scalar_profile
-
-       output_var_table(43) = init_nc_var(                                     &
-          name              = 'ls_forcing_ug',                                 &
-          std_name          = "",                                              &
-          long_name         = "geostrophic wind (u component)",                &
-          units             = "m/s",                                           &
-          kind              = "geostrophic",                                   &
-          input_id          = 1,                                               &
-          output_file       = output_file,                                     &
-          grid              = averaged_scalar_profile,                         &
-          intermediate_grid = averaged_scalar_profile                          &
-       )
-
-       output_var_table(44) = init_nc_var(                                     &
-          name              = 'ls_forcing_vg',                                 &
-          std_name          = "",                                              &
-          long_name         = "geostrophic wind (v component)",                &
-          units             = "m/s",                                           &
-          kind              = "geostrophic",                                   &
-          input_id          = 1,                                               &
-          output_file       = output_file,                                     &
-          grid              = averaged_scalar_profile,                         &
-          intermediate_grid = averaged_scalar_profile                          &
-       )
-
-       output_var_table(45) = init_nc_var(                                     &
-          name              = 'nudging_u',                                     &
-          std_name          = "",                                              &
-          long_name         = "wind component in x direction",                 &
-          units             = "m/s",                                           &
-          kind              = "geostrophic",                                   &
-          input_id          = 1,                                               &
-          output_file       = output_file,                                     &
-          grid              = averaged_scalar_profile,                         &
-          intermediate_grid = averaged_scalar_profile                          &
-       )
-       output_var_table(45) % to_be_processed = ls_forcing_variables_required
-
-       output_var_table(46) = init_nc_var(                                     &
-          name              = 'nudging_v',                                     &
-          std_name          = "",                                              &
-          long_name         = "wind component in y direction",                 &
-          units             = "m/s",                                           &
-          kind              = "large-scale scalar forcing",                    &
-          input_id          = 1,                                               &
-          output_file       = output_file,                                     &
-          grid              = averaged_scalar_profile,                         &
-          intermediate_grid = averaged_scalar_profile                          &
-       )
-       output_var_table(46) % to_be_processed = ls_forcing_variables_required
-
-       output_var_table(47) = init_nc_var(                                     &
-          name              = 'ls_forcing_sub_w',                              &
-          std_name          = "",                                              &
-          long_name         = "subsidence velocity of w",                      &
-          units             = "m/s",                                           &
-          kind              = "large-scale w forcing",                         &
-          input_id          = 1,                                               &
-          output_file       = output_file,                                     &
-          grid              = averaged_scalar_profile,                         &
-          intermediate_grid = averaged_scalar_profile                          &
-       )
-       output_var_table(47) % to_be_processed = ls_forcing_variables_required
-
-       output_var_table(48) = init_nc_var(                                     &
-          name              = 'nudging_w',                                     &
-          std_name          = "",                                              &
-          long_name         = "wind component in w direction",                 &
-          units             = "m/s",                                           &
-          kind              = "large-scale w forcing",                         &
-          input_id          = 1,                                               &
-          output_file       = output_file,                                     &
-          grid              = averaged_w_profile,                              &
-          intermediate_grid = averaged_w_profile                               &
-       )
-       output_var_table(48) % to_be_processed = ls_forcing_variables_required
-
-
-       output_var_table(49) = init_nc_var(                                     &
-          name              = 'ls_forcing_adv_pt',                             &
-          std_name          = "",                                              &
-          long_name         = "advection of potential temperature",            &
-          units             = "K/s",                                           &
-          kind              = "large-scale scalar forcing",                    &
-          input_id          = 1,                                               &
-          output_file       = output_file,                                     &
-          grid              = averaged_scalar_profile,                         &
-          intermediate_grid = averaged_scalar_profile                          &
-       )
-       output_var_table(49) % to_be_processed = ls_forcing_variables_required
-
-       output_var_table(50) = init_nc_var(                                     &
-          name              = 'ls_forcing_sub_pt',                             &
-          std_name          = "",                                              &
-          long_name         = "subsidence velocity of potential temperature",  &
-          units             = "K/s",                                           &
-          kind              = "large-scale scalar forcing",                    &
-          input_id          = 1,                                               &
-          output_file       = output_file,                                     &
-          grid              = averaged_scalar_profile,                         &
-          intermediate_grid = averaged_scalar_profile                          &
-       )
-       output_var_table(50) % to_be_processed = ls_forcing_variables_required
-
-       output_var_table(51) = init_nc_var(                                     &
-          name              = 'nudging_pt',                                    &
-          std_name          = "",                                              &
-          long_name         = "potential temperature",                         &
-          units             = "K",                                             &
-          kind              = "large-scale scalar forcing",                    &
-          input_id          = 1,                                               &
-          output_file       = output_file,                                     &
-          grid              = averaged_scalar_profile,                         &
-          intermediate_grid = averaged_scalar_profile                          &
-       )
-       output_var_table(51) % to_be_processed = ls_forcing_variables_required
-
-       output_var_table(52) = init_nc_var(                                     &
-          name              = 'ls_forcing_adv_qv',                             &
-          std_name          = "",                                              &
-          long_name         = "advection of specific humidity",                &
-          units             = "kg/kg/s",                                       &
-          kind              = "large-scale scalar forcing",                    &
-          input_id          = 3,                                               &
-          output_file       = output_file,                                     &
-          grid              = averaged_scalar_profile,                         &
-          intermediate_grid = averaged_scalar_profile                          &
-       )
-       output_var_table(52) % to_be_processed = ls_forcing_variables_required
-
-
-       output_var_table(53) = init_nc_var(                                     &
-          name              = 'ls_forcing_sub_qv',                             &
-          std_name          = "",                                              &
-          long_name         = "subsidence velocity of specific humidity",      &
-          units             = "kg/kg/s",                                       &
-          kind              = "large-scale scalar forcing",                    &
-          input_id          = 3,                                               &
-          output_file       = output_file,                                     &
-          grid              = averaged_scalar_profile,                         &
-          intermediate_grid = averaged_scalar_profile                          &
-       )
-       output_var_table(53) % to_be_processed = ls_forcing_variables_required
-
-       output_var_table(54) = init_nc_var(                                     &
-          name              = 'nudging_qv',                                    &
-          std_name          = "",                                              &
-          long_name         = "specific humidity",                             &
-          units             = "kg/kg",                                         &
-          kind              = "large-scale scalar forcing",                    &
-          input_id          = 3,                                               &
-          output_file       = output_file,                                     &
-          grid              = averaged_scalar_profile,                         &
-          intermediate_grid = averaged_scalar_profile                          &
-       )
-       output_var_table(54) % to_be_processed = ls_forcing_variables_required
-
-       output_var_table(55) = init_nc_var(                                     &
-          name              = 'nudging_tau',                                   &
-          std_name          = "",                                              &
-          long_name         = "nudging relaxation time scale",                 &
-          units             = "s",                                             &
-          kind              = "constant scalar profile",                       &
-          input_id          = 1,                                               &
-          output_file       = output_file,                                     &
-          grid              = averaged_scalar_profile,                         &
-          intermediate_grid = averaged_scalar_profile                          &
-       )
-       output_var_table(55) % to_be_processed = ls_forcing_variables_required
-
-
-       output_var_table(56) = init_nc_var(                                     &
-          name              = 'internal_density_centre',                              &
-          std_name          = "",                                              &
-          long_name         = "",                                              &
-          units             = "",                                              &
-          kind              = "internal profile",                              &
-          input_id          = 4,                                               &
-          output_file       = output_file,                                     &
-          grid              = averaged_scalar_profile,                         &
-          intermediate_grid = averaged_scalar_profile                          &
-       )
-       output_var_table(56) % averaging_grid => averaged_scalar_profile
-
-
-       output_var_table(57) = init_nc_var(                                     &
-          name              = 'internal_density_north',                       &
-          std_name          = "",                                              &
-          long_name         = "",                                              &
-          units             = "",                                              &
-          kind              = "internal profile",                              &
-          input_id          = 4,                                               &
-          output_file       = output_file,                                     &
-          grid              = north_averaged_scalar_profile,                   &
-          intermediate_grid = north_averaged_scalar_profile                    &
-       )
-       output_var_table(57) % averaging_grid => north_averaged_scalar_profile
-       output_var_table(57) % to_be_processed = .NOT. cfg % ug_is_set
-
-
-       output_var_table(58) = init_nc_var(                                     &
-          name              = 'internal_density_south',                       &
-          std_name          = "",                                              &
-          long_name         = "",                                              &
-          units             = "",                                              &
-          kind              = "internal profile",                              &
-          input_id          = 4,                                               &
-          output_file       = output_file,                                     &
-          grid              = south_averaged_scalar_profile,                   &
-          intermediate_grid = south_averaged_scalar_profile                    &
-       )
-       output_var_table(58) % averaging_grid => south_averaged_scalar_profile
-       output_var_table(58) % to_be_processed = .NOT. cfg % ug_is_set
-
-
-       output_var_table(59) = init_nc_var(                                     &
-          name              = 'internal_density_east',                        &
-          std_name          = "",                                              &
-          long_name         = "",                                              &
-          units             = "",                                              &
-          kind              = "internal profile",                              &
-          input_id          = 4,                                               &
-          output_file       = output_file,                                     &
-          grid              = east_averaged_scalar_profile,                    &
-          intermediate_grid = east_averaged_scalar_profile                     &
-       )
-       output_var_table(59) % averaging_grid => east_averaged_scalar_profile
-       output_var_table(59) % to_be_processed = .NOT. cfg % ug_is_set
-
-
-       output_var_table(60) = init_nc_var(                                     &
-          name              = 'internal_density_west',                        &
-          std_name          = "",                                              &
-          long_name         = "",                                              &
-          units             = "",                                              &
-          kind              = "internal profile",                              &
-          input_id          = 4,                                               &
-          output_file       = output_file,                                     &
-          grid              = west_averaged_scalar_profile,                    &
-          intermediate_grid = west_averaged_scalar_profile                     &
-       )
-       output_var_table(60) % averaging_grid => west_averaged_scalar_profile
-       output_var_table(60) % to_be_processed = .NOT. cfg % ug_is_set
-
-       output_var_table(61) = init_nc_var(                                     &
-          name              = 'internal_pressure_north',                       &
-          std_name          = "",                                              &
-          long_name         = "",                                              &
-          units             = "",                                              &
-          kind              = "internal profile",                              &
-          input_id          = 2,                                               &
-          output_file       = output_file,                                     &
-          grid              = north_averaged_scalar_profile,                   &
-          intermediate_grid = north_averaged_scalar_profile                    &
-       )
-       output_var_table(61) % averaging_grid => north_averaged_scalar_profile
-       output_var_table(61) % to_be_processed = .NOT. cfg % ug_is_set
-
-
-       output_var_table(62) = init_nc_var(                                     &
-          name              = 'internal_pressure_south',                       &
-          std_name          = "",                                              &
-          long_name         = "",                                              &
-          units             = "",                                              &
-          kind              = "internal profile",                              &
-          input_id          = 2,                                               &
-          output_file       = output_file,                                     &
-          grid              = south_averaged_scalar_profile,                   &
-          intermediate_grid = south_averaged_scalar_profile                    &
-       )
-       output_var_table(62) % averaging_grid => south_averaged_scalar_profile
-       output_var_table(62) % to_be_processed = .NOT. cfg % ug_is_set
-
-
-       output_var_table(63) = init_nc_var(                                     &
-          name              = 'internal_pressure_east',                        &
-          std_name          = "",                                              &
-          long_name         = "",                                              &
-          units             = "",                                              &
-          kind              = "internal profile",                              &
-          input_id          = 2,                                               &
-          output_file       = output_file,                                     &
-          grid              = east_averaged_scalar_profile,                    &
-          intermediate_grid = east_averaged_scalar_profile                     &
-       )
-       output_var_table(63) % averaging_grid => east_averaged_scalar_profile
-       output_var_table(63) % to_be_processed = .NOT. cfg % ug_is_set
-
-
-       output_var_table(64) = init_nc_var(                                     &
-          name              = 'internal_pressure_west',                        &
-          std_name          = "",                                              &
-          long_name         = "",                                              &
-          units             = "",                                              &
-          kind              = "internal profile",                              &
-          input_id          = 2,                                               &
-          output_file       = output_file,                                     &
-          grid              = west_averaged_scalar_profile,                    &
-          intermediate_grid = west_averaged_scalar_profile                     &
-       )
-       output_var_table(64) % averaging_grid => west_averaged_scalar_profile
-       output_var_table(64) % to_be_processed = .NOT. cfg % ug_is_set
-
-       ! Attributes shared among all variables
-       output_var_table(:) % source = nc_source_text
-
-
-    END SUBROUTINE setup_variable_tables
-
-
-!------------------------------------------------------------------------------!
-! Description:
-! ------------
-!> Initializes and nc_var varible with the given parameters. The 'kind'
-!> parameter is used to infer the correct netCDF IDs and the level of detail,
-!> 'lod', as defined by the PALM-4U input data standard.
-!------------------------------------------------------------------------------!
-    FUNCTION init_nc_var(name, std_name, long_name, units, kind, input_id,     &
-                         grid, intermediate_grid, output_file, is_profile)     &
-       RESULT(var)
-
-       CHARACTER(LEN=*), INTENT(IN)      ::  name, std_name, long_name, units, kind
-       INTEGER, INTENT(IN)               ::  input_id
-       TYPE(grid_definition), INTENT(IN), TARGET ::  grid, intermediate_grid
-       TYPE(nc_file), INTENT(IN)         ::  output_file
-       LOGICAL, INTENT(IN), OPTIONAL     ::  is_profile
-
-       CHARACTER(LEN=LNAME)              ::  out_var_kind 
-       TYPE(nc_var)                      ::  var
-
-       out_var_kind = TRIM(kind)
-
-       IF (PRESENT(is_profile))  THEN
-          IF (is_profile)  out_var_kind = TRIM(kind) // ' profile'
-       END IF
-
-       var % name              = name
-       var % standard_name     = std_name
-       var % long_name         = long_name
-       var % units             = units
-       var % kind              = TRIM(out_var_kind)
-       var % input_id          = input_id
-       var % nt                = SIZE (output_file % time)
-       var % grid              => grid
-       var % intermediate_grid => intermediate_grid
-
-       SELECT CASE( TRIM(out_var_kind) )
-
-       !TODO: Using global module variables 'init_variables_required' and
-       !TODO: 'boundary_variables_required'. Encapsulate in settings type
-       !TODO: and pass into init_nc_var.
-       CASE( 'init soil' )
-          var % nt              = 1
-          var % lod             = 2
-          var % ndim            = 3
-          var % dimids(1:3)     = output_file % dimids_soil
-          var % dimvarids(1:3)  = output_file % dimvarids_soil
-          var % to_be_processed = init_variables_required
-          var % is_internal     = .FALSE.
-          var % task            = "interpolate_2d"
-
-       CASE( 'init scalar' )
-          var % nt              = 1
-          var % lod             = 2
-          var % ndim            = 3
-          var % dimids(1:3)     = output_file % dimids_scl
-          var % dimvarids(1:3)  = output_file % dimvarids_scl
-          var % to_be_processed = init_variables_required
-          var % is_internal     = .FALSE.
-          var % task            = "interpolate_3d"
-
-       CASE( 'init u' )
-          var % nt              = 1
-          var % lod             = 2
-          var % ndim            = 3
-          var % dimids(1)       = output_file % dimids_vel(1)
-          var % dimids(2)       = output_file % dimids_scl(2)
-          var % dimids(3)       = output_file % dimids_scl(3)
-          var % dimvarids(1)    = output_file % dimvarids_vel(1)
-          var % dimvarids(2)    = output_file % dimvarids_scl(2)
-          var % dimvarids(3)    = output_file % dimvarids_scl(3)
-          var % to_be_processed = init_variables_required
-          var % is_internal     = .FALSE.
-          var % task            = "interpolate_3d"
-
-       CASE( 'init v' )
-          var % nt              = 1
-          var % lod             = 2
-          var % ndim            = 3
-          var % dimids(1)       = output_file % dimids_scl(1)
-          var % dimids(2)       = output_file % dimids_vel(2)
-          var % dimids(3)       = output_file % dimids_scl(3)
-          var % dimvarids(1)    = output_file % dimvarids_scl(1)
-          var % dimvarids(2)    = output_file % dimvarids_vel(2)
-          var % dimvarids(3)    = output_file % dimvarids_scl(3)
-          var % to_be_processed = init_variables_required
-          var % is_internal     = .FALSE.
-          var % task            = "interpolate_3d"
-
-       CASE( 'init w' )
-          var % nt              = 1
-          var % lod             = 2
-          var % ndim            = 3
-          var % dimids(1)       = output_file % dimids_scl(1)
-          var % dimids(2)       = output_file % dimids_scl(2)
-          var % dimids(3)       = output_file % dimids_vel(3)
-          var % dimvarids(1)    = output_file % dimvarids_scl(1)
-          var % dimvarids(2)    = output_file % dimvarids_scl(2)
-          var % dimvarids(3)    = output_file % dimvarids_vel(3)
-          var % to_be_processed = init_variables_required
-          var % is_internal     = .FALSE.
-          var % task            = "interpolate_3d"
-
-       CASE( 'init scalar profile', 'init u profile', 'init v profile')
-          var % nt              = 1
-          var % lod             = 1
-          var % ndim            = 1
-          var % dimids(1)       = output_file % dimids_scl(3)    !z
-          var % dimvarids(1)    = output_file % dimvarids_scl(3) !z
-          var % to_be_processed = init_variables_required
-          var % is_internal     = .FALSE.
-          var % task            = "average profile"
-
-       CASE( 'init w profile')
-          var % nt              = 1
-          var % lod             = 1
-          var % ndim            = 1
-          var % dimids(1)       = output_file % dimids_vel(3)    !z
-          var % dimvarids(1)    = output_file % dimvarids_vel(3) !z
-          var % to_be_processed = init_variables_required
-          var % is_internal     = .FALSE.
-          var % task            = "average profile"
-
-       CASE( 'surface forcing' )
-          var % lod             = -1
-          var % ndim            = 3
-          var % dimids(3)       = output_file % dimid_time
-          var % dimids(1:2)     = output_file % dimids_soil(1:2)
-          var % dimvarids(3)    = output_file % dimvarid_time
-          var % dimvarids(1:2)  = output_file % dimvarids_soil(1:2)
-          var % to_be_processed = boundary_variables_required
-          var % is_internal     = .FALSE.
-          var % task            = "interpolate_2d"
-
-       CASE( 'left scalar', 'right scalar') ! same as right
-          var % lod             = -1
-          var % ndim            = 3
-          var % dimids(3)       = output_file % dimid_time
-          var % dimids(1)       = output_file % dimids_scl(2)
-          var % dimids(2)       = output_file % dimids_scl(3)
-          var % dimvarids(3)    = output_file % dimvarid_time
-          var % dimvarids(1)    = output_file % dimvarids_scl(2)
-          var % dimvarids(2)    = output_file % dimvarids_scl(3)
-          var % to_be_processed = boundary_variables_required
-          var % is_internal     = .FALSE.
-          var % task            = "interpolate_3d"
-
-       CASE( 'north scalar', 'south scalar') ! same as south
-          var % lod             = -1
-          var % ndim            = 3
-          var % dimids(3)       = output_file % dimid_time
-          var % dimids(1)       = output_file % dimids_scl(1)
-          var % dimids(2)       = output_file % dimids_scl(3)
-          var % dimvarids(3)    = output_file % dimvarid_time
-          var % dimvarids(1)    = output_file % dimvarids_scl(1)
-          var % dimvarids(2)    = output_file % dimvarids_scl(3)
-          var % to_be_processed = boundary_variables_required
-          var % is_internal     = .FALSE.
-          var % task            = "interpolate_3d"
-
-       CASE( 'top scalar', 'top w' )
-          var % lod             = -1
-          var % ndim            = 3
-          var % dimids(3)       = output_file % dimid_time
-          var % dimids(1)       = output_file % dimids_scl(1)
-          var % dimids(2)       = output_file % dimids_scl(2)
-          var % dimvarids(3)    = output_file % dimvarid_time
-          var % dimvarids(1)    = output_file % dimvarids_scl(1)
-          var % dimvarids(2)    = output_file % dimvarids_scl(2)
-          var % to_be_processed = boundary_variables_required
-          var % is_internal     = .FALSE.
-          var % task            = "interpolate_3d"
-
-       CASE( 'left u', 'right u' )
-          var % lod             = -1
-          var % ndim            = 3
-          var % dimids(3)       = output_file % dimid_time
-          var % dimids(1)       = output_file % dimids_scl(2)
-          var % dimids(2)       = output_file % dimids_scl(3)
-          var % dimvarids(3)    = output_file % dimvarid_time
-          var % dimvarids(1)    = output_file % dimvarids_scl(2)
-          var % dimvarids(2)    = output_file % dimvarids_scl(3)
-          var % to_be_processed = boundary_variables_required
-          var % is_internal     = .FALSE.
-          var % task            = "interpolate_3d"
-
-       CASE( 'north u', 'south u' )
-          var % lod             = -1
-          var % ndim            = 3
-          var % dimids(3)       = output_file % dimid_time    !t
-          var % dimids(1)       = output_file % dimids_vel(1) !x
-          var % dimids(2)       = output_file % dimids_scl(3) !z
-          var % dimvarids(3)    = output_file % dimvarid_time
-          var % dimvarids(1)    = output_file % dimvarids_vel(1)
-          var % dimvarids(2)    = output_file % dimvarids_scl(3)
-          var % to_be_processed = boundary_variables_required
-          var % is_internal     = .FALSE.
-          var % task            = "interpolate_3d"
-
-       CASE( 'top u' )
-          var % lod             = -1
-          var % ndim            = 3
-          var % dimids(3)       = output_file % dimid_time    !t
-          var % dimids(1)       = output_file % dimids_vel(1) !x
-          var % dimids(2)       = output_file % dimids_scl(2) !z
-          var % dimvarids(3)    = output_file % dimvarid_time
-          var % dimvarids(1)    = output_file % dimvarids_vel(1)
-          var % dimvarids(2)    = output_file % dimvarids_scl(2)
-          var % to_be_processed = boundary_variables_required
-          var % is_internal     = .FALSE.
-          var % task            = "interpolate_3d"
-
-       CASE( 'left v', 'right v' )
-          var % lod             = -1
-          var % ndim            = 3
-          var % dimids(3)       = output_file % dimid_time
-          var % dimids(1)       = output_file % dimids_vel(2)
-          var % dimids(2)       = output_file % dimids_scl(3)
-          var % dimvarids(3)    = output_file % dimvarid_time
-          var % dimvarids(1)    = output_file % dimvarids_vel(2)
-          var % dimvarids(2)    = output_file % dimvarids_scl(3)
-          var % to_be_processed = boundary_variables_required
-          var % is_internal     = .FALSE.
-          var % task            = "interpolate_3d"
-
-       CASE( 'north v', 'south v' )
-          var % lod             = -1
-          var % ndim            = 3
-          var % dimids(3)       = output_file % dimid_time    !t
-          var % dimids(1)       = output_file % dimids_scl(1) !x
-          var % dimids(2)       = output_file % dimids_scl(3) !z
-          var % dimvarids(3)    = output_file % dimvarid_time
-          var % dimvarids(1)    = output_file % dimvarids_scl(1)
-          var % dimvarids(2)    = output_file % dimvarids_scl(3)
-          var % to_be_processed = boundary_variables_required
-          var % is_internal     = .FALSE.
-          var % task            = "interpolate_3d"
-
-       CASE( 'top v' )
-          var % lod             = -1
-          var % ndim            = 3
-          var % dimids(3)       = output_file % dimid_time    !t
-          var % dimids(1)       = output_file % dimids_scl(1) !x
-          var % dimids(2)       = output_file % dimids_vel(2) !z
-          var % dimvarids(3)    = output_file % dimvarid_time
-          var % dimvarids(1)    = output_file % dimvarids_scl(1)
-          var % dimvarids(2)    = output_file % dimvarids_vel(2)
-          var % to_be_processed = boundary_variables_required
-          var % is_internal     = .FALSE.
-          var % task            = "interpolate_3d"
-
-       CASE( 'left w', 'right w')
-          var % lod             = -1
-          var % ndim            = 3
-          var % dimids(3)       = output_file % dimid_time
-          var % dimids(1)       = output_file % dimids_scl(2)
-          var % dimids(2)       = output_file % dimids_vel(3)
-          var % dimvarids(3)    = output_file % dimvarid_time
-          var % dimvarids(1)    = output_file % dimvarids_scl(2)
-          var % dimvarids(2)    = output_file % dimvarids_vel(3)
-          var % to_be_processed = boundary_variables_required
-          var % is_internal     = .FALSE.
-          var % task            = "interpolate_3d"
-
-       CASE( 'north w', 'south w' )
-          var % lod             = -1
-          var % ndim            = 3
-          var % dimids(3)       = output_file % dimid_time    !t
-          var % dimids(1)       = output_file % dimids_scl(1) !x
-          var % dimids(2)       = output_file % dimids_vel(3) !z
-          var % dimvarids(3)    = output_file % dimvarid_time
-          var % dimvarids(1)    = output_file % dimvarids_scl(1)
-          var % dimvarids(2)    = output_file % dimvarids_vel(3)
-          var % to_be_processed = boundary_variables_required
-          var % is_internal     = .FALSE.
-          var % task            = "interpolate_3d"
-
-       CASE( 'time series' )
-          var % lod             = 0
-          var % ndim            = 1
-          var % dimids(1)       = output_file % dimid_time    !t
-          var % dimvarids(1)    = output_file % dimvarid_time
-          var % to_be_processed = .TRUE.
-          var % is_internal     = .FALSE.
-          var % task            = "average profile"
-
-       CASE( 'constant scalar profile' )
-          var % lod             = -1
-          var % ndim            = 2
-          var % dimids(2)       = output_file % dimid_time    !t
-          var % dimids(1)       = output_file % dimids_scl(3) !z
-          var % dimvarids(2)    = output_file % dimvarid_time
-          var % dimvarids(1)    = output_file % dimvarids_scl(3)
-          var % to_be_processed = .TRUE.
-          var % is_internal     = .FALSE.
-          var % task            = "set profile"
-
-       CASE( 'large-scale scalar forcing' )
-          var % lod             = -1
-          var % ndim            = 2
-          var % dimids(2)       = output_file % dimid_time    !t
-          var % dimids(1)       = output_file % dimids_scl(3) !z
-          var % dimvarids(2)    = output_file % dimvarid_time
-          var % dimvarids(1)    = output_file % dimvarids_scl(3)
-          var % to_be_processed = ls_forcing_variables_required
-          var % is_internal     = .FALSE.
-          var % task            = "average large-scale profile"
-
-       CASE( 'geostrophic' )
-          var % lod             = -1
-          var % ndim            = 2
-          var % dimids(2)       = output_file % dimid_time    !t
-          var % dimids(1)       = output_file % dimids_scl(3) !z
-          var % dimvarids(2)    = output_file % dimvarid_time
-          var % dimvarids(1)    = output_file % dimvarids_scl(3)
-          var % to_be_processed = .TRUE.
-          var % is_internal     = .FALSE.
-          var % task            = "geostrophic winds"
-
-       CASE( 'large-scale w forcing' )
-          var % lod             = -1
-          var % ndim            = 2
-          var % dimids(2)       = output_file % dimid_time    !t
-          var % dimids(1)       = output_file % dimids_vel(3) !z
-          var % dimvarids(2)    = output_file % dimvarid_time
-          var % dimvarids(1)    = output_file % dimvarids_vel(3)
-          var % to_be_processed = ls_forcing_variables_required
-          var % is_internal     = .FALSE.
-          var % task            = "average large-scale profile"
-
-       CASE( 'internal profile' )
-          var % lod             = -1
-          var % ndim            = 2
-          var % dimids(2)       = output_file % dimid_time    !t
-          var % dimids(1)       = output_file % dimids_scl(3) !z
-          var % dimvarids(2)    = output_file % dimvarid_time
-          var % dimvarids(1)    = output_file % dimvarids_scl(3)
-          var % to_be_processed = .TRUE.
-          var % is_internal     = .TRUE.
-          var % task            = "internal profile"
-
-       CASE DEFAULT
-           message = "Variable kind '" // TRIM(kind) // "' not recognized."
-           CALL abort ('init_nc_var', message)
-
-       END SELECT
-
-    END FUNCTION init_nc_var
-
-
-    SUBROUTINE fini_variables()
-
-       CALL report('fini_variables', 'Deallocating variable table', cfg % debug)
-       DEALLOCATE( input_var_table )
-
-    END SUBROUTINE fini_variables
-
-
-    SUBROUTINE fini_io_groups()
-
-       CALL report('fini_io_groups', 'Deallocating IO groups', cfg % debug)
-       DEALLOCATE( io_group_list )
-
-    END SUBROUTINE fini_io_groups
-
-
-    SUBROUTINE fini_file_lists()
-       
-       CALL report('fini_file_lists', 'Deallocating file lists', cfg % debug)
-       DEALLOCATE( flow_files, soil_files, radiation_files, soil_moisture_files )
-
-    END SUBROUTINE fini_file_lists
-
-
-    SUBROUTINE get_input_file_list(start_date_string, start_hour, end_hour,        &
-                                   step_hour, path, prefix, suffix, file_list)
-
-       CHARACTER (LEN=DATE), INTENT(IN) ::  start_date_string
-       CHARACTER (LEN=*),    INTENT(IN) ::  prefix, suffix, path
-       INTEGER,              INTENT(IN) ::  start_hour, end_hour, step_hour
-       CHARACTER(LEN=*), ALLOCATABLE, INTENT(INOUT) ::  file_list(:)
-
-       INTEGER             ::  number_of_intervals, hour, i
-       CHARACTER(LEN=DATE) ::  date_string
-
-       number_of_intervals = CEILING( REAL(end_hour - start_hour) / step_hour )
-       ALLOCATE( file_list(number_of_intervals + 1) )
-
-       DO i = 0, number_of_intervals
-          hour = start_hour + i * step_hour
-          date_string = add_hours_to(start_date_string, hour)
-
-          file_list(i+1) = TRIM(path) // TRIM(prefix) // TRIM(date_string) //    &
-                           TRIM(suffix) // '.nc'
-          message = "Set up input file name '" // TRIM(file_list(i+1)) //"'"
-          CALL report('input_file_list', message)
-       END DO
-
-    END SUBROUTINE get_input_file_list
-
-
-!------------------------------------------------------------------------------!
-! Description:
-! ------------
-!> Carries out any physical conversion of the quantities in the given input
-!> buffer needed to obtain the quantity required by PALM-4U. For instance, 
-!> velocities are rotated to the PALM-4U coordinate system and the potential
-!> temperature is computed from the absolute temperature and pressure.
-!>
-!> Note, that the preprocessing does not include any grid change. The result
-!> array will match a COSMO-DE scalar array.
-!------------------------------------------------------------------------------!
-    SUBROUTINE preprocess(group, input_buffer, cosmo_grid, iter)
-
-       TYPE(io_group), INTENT(INOUT), TARGET       ::  group
-       TYPE(container), INTENT(INOUT), ALLOCATABLE ::  input_buffer(:)
-       TYPE(grid_definition), INTENT(IN)           ::  cosmo_grid
-       INTEGER, INTENT(IN)                         ::  iter
-       
-       REAL(dp), ALLOCATABLE                       ::  basic_state_pressure(:)
-       TYPE(container), ALLOCATABLE                ::  preprocess_buffer(:)
-       INTEGER                                     ::  hour, dt
-       INTEGER                                     ::  i, j, k
-       INTEGER                                     ::  nx, ny, nz
-       
-       input_buffer(:) % is_preprocessed = .FALSE.
-        
-       SELECT CASE( group % kind )
-       
-       CASE( 'velocities' )
-          ! Allocate a compute buffer with the same number of arrays as the input
-          ALLOCATE( preprocess_buffer( SIZE(input_buffer) ) )
-
-          ! Allocate u and v arrays with scalar dimensions
-          nx = SIZE(input_buffer(1) % array, 1)
-          ny = SIZE(input_buffer(1) % array, 2)
-          nz = SIZE(input_buffer(1) % array, 3)
-          ALLOCATE( preprocess_buffer(1) % array(nx, ny, nz) ) ! u buffer
-          ALLOCATE( preprocess_buffer(2) % array(nx, ny, nz) ) ! v buffer
-
- CALL run_control('time', 'alloc')
-
-          ! interpolate U and V to centres
-          CALL centre_velocities( u_face = input_buffer(1) % array,            &
-                                  v_face = input_buffer(2) % array,            &
-                                  u_centre = preprocess_buffer(1) % array,     &
-                                  v_centre = preprocess_buffer(2) % array )
-          
-          cfg % rotation_method = 'rotated-pole'
-          SELECT CASE(cfg % rotation_method)
-
-          CASE('rotated-pole')
-             ! rotate U and V to PALM-4U orientation and overwrite U and V with
-             ! rotated velocities
-             DO k = 1, nz
-             DO j = 1, ny
-             DO i = 1, nx
-                CALL uv2uvrot( urot = preprocess_buffer(1) % array(i,j,k),     &
-                               vrot = preprocess_buffer(2) % array(i,j,k),     &
-                               rlat = cosmo_grid % lat(j-1),                   &
-                               rlon = cosmo_grid % lon(i-1),                   &
-                               pollat = phi_cn,                                &
-                               pollon = lambda_cn,                             &
-                               u = input_buffer(1) % array(i,j,k),             &
-                               v = input_buffer(2) % array(i,j,k) )
-             END DO
-             END DO
-             END DO
-
-          CASE DEFAULT
-             message = "Rotation method '" // TRIM(cfg % rotation_method) //   &
-                "' not recognized."
-             CALL abort('preprocess', message)
-
-          END SELECT
-
-          ! set values 
-          input_buffer(1) % array(1,:,:) = 0.0_dp
-          input_buffer(2) % array(1,:,:) = 0.0_dp
-          input_buffer(1) % array(:,1,:) = 0.0_dp
-          input_buffer(2) % array(:,1,:) = 0.0_dp
-
-          input_buffer(1:2) % is_preprocessed = .TRUE.
- CALL run_control('time', 'comp')
-
-          DEALLOCATE( preprocess_buffer )
- CALL run_control('time', 'alloc')
-
-          message = "Input buffers for group '" // TRIM(group % kind) // "'"//&
-             " preprocessed sucessfully."
-          CALL report('preprocess', message)
-       
-       CASE( 'thermodynamics' ) ! T, P, QV
-          nx = SIZE(input_buffer(1) % array, 1)
-          ny = SIZE(input_buffer(1) % array, 2)
-          nz = SIZE(input_buffer(1) % array, 3)
-
-          ! Compute absolute pressure if presure perturbation has been read in.
-          IF ( TRIM(group % in_var_list(2) % name) == 'PP' )  THEN
-             message = "Absolute pressure, P, not available, " //              &
-                       "computing from pressure preturbation PP."
-             CALL report('preprocess', message)
-
-             ALLOCATE( basic_state_pressure(1:nz) )
- CALL run_control('time', 'alloc')
-
-             DO j = 1, ny
-             DO i = 1, nx
-
-                CALL get_basic_state(cosmo_grid % hfl(i,j,:), BETA, P_SL, T_SL,&
-                                     RD, G, basic_state_pressure)
-
-                input_buffer (2) % array(i,j,:) =                              &
-                   HECTO * input_buffer (2) % array(i,j,:) +                   &
-                   basic_state_pressure(:)
-
-             END DO
-             END DO
- CALL run_control('time', 'comp')
-
-             DEALLOCATE( basic_state_pressure )
- CALL run_control('time', 'alloc')
-
-             group % in_var_list(2) % name = 'P'
-
-          END IF
-          ! pressure
-          input_buffer(2) % is_preprocessed = .TRUE.
-
-          ! Copy temperature to last input buffer array
-          ALLOCATE(                                                            &
-              input_buffer( group % n_output_quantities ) % array (nx, ny, nz) &
-          )
-          input_buffer(group % n_output_quantities) % array(:,:,:) =           &
-              input_buffer(1) % array(:,:,:)
-
-          ! Convert absolute to potential temperature
-          CALL potential_temperature(                                          &
-             t = input_buffer(1) % array(:,:,:),                               &
-             p = input_buffer(2) % array(:,:,:),                               &
-             p_ref = P_REF,                                                    &
-             r = RD_PALM,                                                      &
-             cp = CP_PALM                                                      &
-          )
-
-          ! potential temperature
-          input_buffer(1) % is_preprocessed = .TRUE.
-
-          ! Convert temperature copy to density
-          CALL moist_density(                                                  &
-             t_rho = input_buffer(group % n_output_quantities) % array(:,:,:), &
-             p = input_buffer(2) % array(:,:,:),                               &
-             qv = input_buffer(3) % array(:,:,:),                              &
-             rd = RD,                                                          &
-             rv = RV                                                           &
-          )
-
-          ! qv
-          input_buffer(3) % is_preprocessed = .TRUE.
-
-          ! density
-          input_buffer(group % n_output_quantities) % is_preprocessed = .TRUE.
-
-
-          message = "Input buffers for group '" // TRIM(group % kind) // "'"//&
-             " preprocessed sucessfully."
-          CALL report('preprocess', message)
- CALL run_control('time', 'comp')
-       
-       CASE( 'scalar' ) ! S or W
-          input_buffer(:) % is_preprocessed = .TRUE.
- CALL run_control('time', 'comp')
-
-       CASE( 'soil-temperature' ) ! 
-          
-          CALL fill_water_cells(soiltyp, input_buffer(1) % array, &
-                                SIZE(input_buffer(1) % array, 3), &
-                                FILL_ITERATIONS)
-          input_buffer(:) % is_preprocessed = .TRUE.
- CALL run_control('time', 'comp')
-
-       CASE( 'soil-water' ) ! 
-
-          CALL fill_water_cells(soiltyp, input_buffer(1) % array, &
-                                SIZE(input_buffer(1) % array, 3), &
-                                FILL_ITERATIONS)
-
-          nx = SIZE(input_buffer(1) % array, 1)
-          ny = SIZE(input_buffer(1) % array, 2)
-          nz = SIZE(input_buffer(1) % array, 3)
-
-          DO k = 1, nz
-          DO j = 1, ny
-          DO i = 1, nx
-             input_buffer(1) % array(i,j,k) =                                  &
-                 input_buffer(1) % array(i,j,k) * d_depth_rho_inv(k)
-          END DO
-          END DO
-          END DO
-
-          message = "Converted soil water from [kg/m^2] to [m^3/m^3]"
-          CALL report('preprocess', message)
-
-          input_buffer(:) % is_preprocessed = .TRUE.
- CALL run_control('time', 'comp')
-
-       CASE( 'surface' ) ! 
-          input_buffer(:) % is_preprocessed = .TRUE.
- CALL run_control('time', 'comp')
-
-       CASE( 'accumulated' ) ! 
-          message = "De-accumulating '" // TRIM(group % in_var_list(1) % name) //&
-                    "' in iteration " // TRIM(str(iter)) 
-          CALL report('preprocess', message)
-
-          hour = iter - 1
-          dt = MODULO(hour, 3) + 1 ! averaging period
-          SELECT CASE(dt)
-
-          CASE(1)
-             !input has been accumulated over one hour. Leave as is
-             !input_buffer(1) % array(:,:,:) carrries one-hour integral
-
-          CASE(2)
-             !input has been accumulated over two hours. Subtract previous step
-             !input_buffer(1) % array(:,:,:) carrries one-hour integral
-             !input_buffer(2) % array(:,:,:) carrries two-hour integral
-             CALL deaverage(                                                   &
-                      avg_1 = input_buffer(1) % array(:,:,:), t1 = 1.0_dp,     &
-                      avg_2 = input_buffer(2) % array(:,:,:), t2 = 1.0_dp,     &
-                      avg_3 = input_buffer(1) % array(:,:,:), t3 = 1.0_dp )
-             !input_buffer(1) % array(:,:,:) carrries one-hour integral of second hour
-
-          CASE(3)
-             !input has been accumulated over three hours. Subtract previous step
-             !input_buffer(1) % array(:,:,:) carrries three-hour integral
-             !input_buffer(2) % array(:,:,:) still carrries two-hour integral
-             CALL deaverage(                                                   &
-                     avg_1 = input_buffer(2) % array(:,:,:), t1 = 1.0_dp,      &
-                     avg_2 = input_buffer(1) % array(:,:,:), t2 = 1.0_dp,      &
-                     avg_3 = input_buffer(1) % array(:,:,:), t3 = 1.0_dp )
-             !input_buffer(1) % array(:,:,:) carrries one-hour integral of third hourA
-
-          CASE DEFAULT
-             message = "Invalid averaging period '" // TRIM(str(dt)) // " hours"
-             CALL abort('preprocess', message)
-
-          END SELECT
-          input_buffer(:) % is_preprocessed = .TRUE.
- CALL run_control('time', 'comp')
-
-       CASE( 'running average' ) ! 
-          message = "De-averaging '" // TRIM(group % in_var_list(1) % name) //   &
-                    "' in iteration " // TRIM(str(iter)) 
-          CALL report('preprocess', message)
-
-          hour = iter - 1
-          dt = MODULO(hour, 3) + 1 ! averaging period
-          SELECT CASE(dt)
-
-          CASE(1)
-             !input has been accumulated over one hour. Leave as is
-             !input_buffer(1) % array(:,:,:) carrries one-hour integral
-
-          CASE(2)
-             !input has been accumulated over two hours. Subtract previous step
-             !input_buffer(1) % array(:,:,:) carrries one-hour integral
-             !input_buffer(2) % array(:,:,:) carrries two-hour integral
-             CALL deaverage( input_buffer(1) % array(:,:,:), 1.0_dp,           &
-                             input_buffer(2) % array(:,:,:), 2.0_dp,           &
-                             input_buffer(1) % array(:,:,:), 1.0_dp)
-             !input_buffer(1) % array(:,:,:) carrries one-hour integral of second hour
-
-          CASE(3)
-             !input has been accumulated over three hours. Subtract previous step
-             !input_buffer(1) % array(:,:,:) carrries three-hour integral
-             !input_buffer(2) % array(:,:,:) still carrries two-hour integral
-             CALL deaverage( input_buffer(2) % array(:,:,:), 2.0_dp,           &
-                             input_buffer(1) % array(:,:,:), 3.0_dp,           &
-                             input_buffer(1) % array(:,:,:), 1.0_dp)
-             !input_buffer(1) % array(:,:,:) carrries one-hour integral of third hourA
-
-          CASE DEFAULT
-             message = "Invalid averaging period '" // TRIM(str(dt)) // " hours"
-             CALL abort('preprocess', message)
-
-          END SELECT
-          input_buffer(:) % is_preprocessed = .TRUE.
-
-       CASE DEFAULT
-          message = "IO group kind '" // TRIM(group % kind) // "' is not supported."
-          CALL abort('prerpocess', message)
-
-       END SELECT
- CALL run_control('time', 'comp')
-
-    END SUBROUTINE preprocess
-
-
-! Description:
-! ------------
-!> Computes average soil values in COSMO-DE water cells from neighbouring
-!> non-water cells. This is done as a preprocessing step for the COSMO-DE
-!> soil input arrays, which contain unphysical values for water cells.
-!>
-!> This routine computes the average of up to all nine neighbouring cells
-!> or keeps the original value, if not at least one non-water neightbour
-!> is available.
-!>
-!> By repeatedly applying this step, soil data can be extrapolated into
-!> 'water' regions occupying multiple cells, one cell per iteration.
-!> 
-!> Input parameters:
-!> -----------------
-!> soiltyp : 2d map of COSMO-DE soil types
-!> nz : number of layers in the COSMO-DE soil
-!> niter : number iterations
-!> 
-!> Output parameters:
-!> ------------------
-!> array : the soil array (i.e. water content or temperature)
-!------------------------------------------------------------------------------!
-    SUBROUTINE fill_water_cells(soiltyp, array, nz, niter)
-       INTEGER(hp), DIMENSION(:,:,:), INTENT(IN) :: soiltyp
-       REAL(dp), DIMENSION(:,:,:), INTENT(INOUT) :: array
-       INTEGER, INTENT(IN)                       :: nz, niter
-
-       REAL(dp), DIMENSION(nz)                   :: column
-       INTEGER(hp), DIMENSION(:,:), ALLOCATABLE  :: old_soiltyp, new_soiltyp
-       INTEGER                                   :: l, i, j, nx, ny, n_cells, ii, jj, iter
-       INTEGER, DIMENSION(8)                     :: di, dj
-
-       nx = SIZE(array, 1)
-       ny = SIZE(array, 2)
-       di = (/ -1, -1, -1, 0,  0,  1, 1, 1 /)
-       dj = (/ -1,  0,  1, -1, 1, -1, 0, 1 /)
-
-       ALLOCATE(old_soiltyp(SIZE(soiltyp,1), &
-                            SIZE(soiltyp,2) ))
-
-       ALLOCATE(new_soiltyp(SIZE(soiltyp,1), &
-                            SIZE(soiltyp,2) ))
-
-       old_soiltyp(:,:) = soiltyp(:,:,1)
-       new_soiltyp(:,:) = soiltyp(:,:,1)
-
-       DO iter = 1, niter
-
-          DO j = 1, ny
-          DO i = 1, nx
-          
-             IF (old_soiltyp(i,j) == WATER_ID)  THEN 
-
-                n_cells = 0
-                column(:) = 0.0_dp
-                DO l = 1, SIZE(di)
-
-                   ii = MIN(nx, MAX(1, i + di(l)))
-                   jj = MIN(ny, MAX(1, j + dj(l)))
-
-                   IF (old_soiltyp(ii,jj) .NE. WATER_ID)  THEN
-                      n_cells = n_cells + 1
-                      column(:) = column(:) + array(ii,jj,:)
-                   END IF
-
-                END DO
-
-                ! Overwrite if at least one non-water neighbour cell is available
-                IF (n_cells > 0)  THEN
-                   array(i,j,:) = column(:) / n_cells
-                   new_soiltyp(i,j) = 0
-                END IF
-
-             END IF
-
-          END DO
-          END DO
-
-          old_soiltyp(:,:) = new_soiltyp(:,:)
-
-       END DO
-
-       DEALLOCATE(old_soiltyp, new_soiltyp)
-
-    END SUBROUTINE fill_water_cells
-
- END MODULE grid
Index: palm/trunk/UTIL/inifor/src/inifor_control.f90
===================================================================
--- palm/trunk/UTIL/inifor/src/inifor_control.f90	(revision 3447)
+++ palm/trunk/UTIL/inifor/src/inifor_control.f90	(revision 3447)
@@ -0,0 +1,204 @@
+!> @file src/inifor_control.f90
+!------------------------------------------------------------------------------!
+! This file is part of the PALM model system.
+!
+! PALM is free software: you can redistribute it and/or modify it under the
+! terms of the GNU General Public License as published by the Free Software
+! Foundation, either version 3 of the License, or (at your option) any later
+! version.
+!
+! PALM is distributed in the hope that it will be useful, but WITHOUT ANY
+! WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+! A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+!
+! You should have received a copy of the GNU General Public License along with
+! PALM. If not, see <http://www.gnu.org/licenses/>.
+!
+! Copyright 2017-2018 Leibniz Universitaet Hannover
+! Copyright 2017-2018 Deutscher Wetterdienst Offenbach
+!------------------------------------------------------------------------------!
+!
+! Current revisions:
+! -----------------
+! 
+! 
+! Former revisions:
+! -----------------
+! $Id$
+! Renamed source files for compatibilty with PALM build system
+!
+! 
+! 3395 2018-10-22 17:32:49Z eckhard
+! Suppress debugging messages unless --debug option is given
+! 
+!
+! 3183 2018-07-27 14:25:55Z suehring
+! Added version and copyright output
+! 
+! 
+! 3182 2018-07-27 13:36:03Z suehring
+! Initial revision
+!
+! 
+!
+! Authors:
+! --------
+! @author Eckhard Kadasch
+!
+! Description:
+! ------------
+!> The control module provides routines for timing INIFOR and writing runtime
+!> feedback to the terminal and a log file.
+!------------------------------------------------------------------------------!
+ MODULE control
+
+    USE defs,                                                                  &
+        ONLY:  LNAME, dp, VERSION, COPYRIGHT
+
+    USE util,                                                                  &
+        ONLY:  real_to_str, real_to_str_f
+
+    IMPLICIT NONE
+
+    CHARACTER (LEN=5000) ::  message = ''
+
+ CONTAINS
+
+    SUBROUTINE report(routine, message, debug)
+
+       CHARACTER(LEN=*), INTENT(IN)  ::  routine
+       CHARACTER(LEN=*), INTENT(IN)  ::  message
+       LOGICAL, OPTIONAL, INTENT(IN) ::  debug
+       INTEGER                       ::  u
+       LOGICAL, SAVE                 ::  is_first_run = .TRUE.
+       LOGICAL                       ::  suppress_message
+
+
+       IF (is_first_run)  THEN
+          OPEN( NEWUNIT=u, FILE='inifor.log', STATUS='replace' )
+          is_first_run = .FALSE.
+       ELSE
+          OPEN( NEWUNIT=u, FILE='inifor.log', POSITION='append', STATUS='old' )
+       END IF
+          
+
+       suppress_message = .FALSE.
+       IF (PRESENT(debug))  THEN
+          IF (.NOT. debug)  suppress_message = .TRUE.
+       END IF
+
+       IF (.NOT. suppress_message)  THEN
+          PRINT *, "inifor: " // TRIM(message) // "  [ " // TRIM(routine) // " ]"
+          WRITE(u, *)  TRIM(message) // "  [ " // TRIM(routine) // " ]"
+       END IF
+
+       CLOSE(u)
+
+    END SUBROUTINE report
+
+
+    SUBROUTINE warn(routine, message)
+
+       CHARACTER(LEN=*), INTENT(IN) ::  routine
+       CHARACTER(LEN=*), INTENT(IN) ::  message
+
+       CALL report(routine, "WARNING: " // TRIM(message))
+
+    END SUBROUTINE warn
+
+
+    SUBROUTINE abort(routine, message)
+
+       CHARACTER(LEN=*), INTENT(IN) ::  routine
+       CHARACTER(LEN=*), INTENT(IN) ::  message
+
+       CALL report(routine, "ERROR: " // TRIM(message) // " Stopping.")
+       STOP
+
+    END SUBROUTINE abort
+
+
+    SUBROUTINE print_version()
+       PRINT *, "INIFOR " // VERSION
+       PRINT *, COPYRIGHT
+    END SUBROUTINE print_version
+
+
+    SUBROUTINE run_control(mode, budget)
+
+       CHARACTER(LEN=*), INTENT(IN) ::  mode, budget
+       REAL(dp), SAVE               ::  t0, t1
+       REAL(dp), SAVE               ::  t_comp=0.0_dp, &
+                                        t_alloc=0.0_dp, &
+                                        t_init=0.0_dp, &
+                                        t_read=0.0_dp, &
+                                        t_total=0.0_dp, &
+                                        t_write=0.0_dp
+       CHARACTER(LEN=*), PARAMETER  ::  fmt='(F6.2)'
+
+
+       SELECT CASE(TRIM(mode))
+
+       CASE('init')
+          CALL CPU_TIME(t0)
+
+       CASE('time')
+
+          CALL CPU_TIME(t1)
+
+          SELECT CASE(TRIM(budget))
+
+             CASE('alloc')
+                t_alloc = t_alloc + t1 - t0
+
+             CASE('init')
+                t_init = t_init + t1 - t0
+
+             CASE('read')
+                t_read = t_read + t1 - t0
+
+             CASE('write')
+                t_write = t_write + t1 - t0
+
+             CASE('comp')
+                t_comp = t_comp + t1 - t0
+
+             CASE DEFAULT
+                CALL abort('run_control', "Time Budget '" // TRIM(mode) // "' is not supported.")
+
+          END SELECT
+
+          t0 = t1
+
+       CASE('report')
+           t_total = t_init + t_read + t_write + t_comp
+
+           CALL report('run_control', " *** CPU time ***")
+
+           CALL report('run_control', "Initialization: " // real_to_str(t_init)  // &
+                       " s (" // TRIM(real_to_str(100*t_init/t_total, fmt))      // " %)")
+
+           CALL report('run_control', "(De-)Allocation:" // real_to_str(t_alloc)  // &
+                       " s (" // TRIM(real_to_str(100*t_alloc/t_total, fmt))      // " %)")
+
+           CALL report('run_control', "Reading data:   " // real_to_str(t_read)  // &
+                       " s (" // TRIM(real_to_str(100*t_read/t_total, fmt))      // " %)")
+
+           CALL report('run_control', "Writing data:   " // real_to_str(t_write) // &
+                       " s (" // TRIM(real_to_str(100*t_write/t_total, fmt))     // " %)")
+
+           CALL report('run_control', "Computation:    " // real_to_str(t_comp)  // &
+                       " s (" // TRIM(real_to_str(100*t_comp/t_total, fmt))      // " %)")
+
+           CALL report('run_control', "Total:          " // real_to_str(t_total) // &
+                       " s (" // TRIM(real_to_str(100*t_total/t_total, fmt))     // " %)")
+
+       CASE DEFAULT
+          CALL abort('run_control', "Mode '" // TRIM(mode) // "' is not supported.")
+
+       END SELECT
+
+    END SUBROUTINE run_control
+
+ END MODULE
+
Index: palm/trunk/UTIL/inifor/src/inifor_defs.f90
===================================================================
--- palm/trunk/UTIL/inifor/src/inifor_defs.f90	(revision 3447)
+++ palm/trunk/UTIL/inifor/src/inifor_defs.f90	(revision 3447)
@@ -0,0 +1,100 @@
+!> @file src/inifor_defs.f90
+!------------------------------------------------------------------------------!
+! This file is part of the PALM model system.
+!
+! PALM is free software: you can redistribute it and/or modify it under the
+! terms of the GNU General Public License as published by the Free Software
+! Foundation, either version 3 of the License, or (at your option) any later
+! version.
+!
+! PALM is distributed in the hope that it will be useful, but WITHOUT ANY
+! WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+! A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+!
+! You should have received a copy of the GNU General Public License along with
+! PALM. If not, see <http://www.gnu.org/licenses/>.
+!
+! Copyright 2017-2018 Leibniz Universitaet Hannover
+! Copyright 2017-2018 Deutscher Wetterdienst Offenbach
+!------------------------------------------------------------------------------!
+!
+! Current revisions:
+! -----------------
+! 
+! 
+! Former revisions:
+! -----------------
+! $Id$
+! Renamed source files for compatibilty with PALM build system
+! 
+! 
+! 3395 2018-10-22 17:32:49Z eckhard
+! New parameters for computation of geostrophic winds
+! Bumped INIFOR version number
+! 
+! 
+! 3183 2018-07-27 14:25:55Z suehring
+! Updated defaults for soil extrapolation steps and nudging time-scale
+! Improved handling of the start date string
+! Added gas constant for water vapor
+! Bumped INIFOR version number
+! 
+! 
+! 3182 2018-07-27 13:36:03Z suehring
+! Initial revision
+!
+! 
+!
+! Authors:
+! --------
+! @author Eckhard Kadasch
+!
+! Description:
+! ------------
+!> The defs module provides global constants used in INIFOR.
+!------------------------------------------------------------------------------!
+ MODULE defs
+ 
+ IMPLICIT NONE
+ 
+ ! Parameters for type definitions
+ INTEGER, PARAMETER  ::  dp    = 8   !< double precision (8 bytes = 64 bits)
+ INTEGER, PARAMETER  ::  sp    = 4   !< single precision (4 bytes = 32 bits)
+ INTEGER, PARAMETER  ::  hp    = 2   !< half precision (2 bytes = 16 bits)
+ INTEGER, PARAMETER  ::  PATH  = 140 !< length of file path strings
+ INTEGER, PARAMETER  ::  LNAME = 150 !< length of long name strings
+ INTEGER, PARAMETER  ::  SNAME = 40  !< length of short name strings
+ INTEGER, PARAMETER  ::  DATE  = 10  !< length of date strings
+
+ ! Trigonomentry
+ REAL(dp), PARAMETER ::  PI = 3.14159265358979323846264338_dp !< Ratio of a circle's circumference to its diamter [-]
+ REAL(dp), PARAMETER ::  TO_RADIANS = PI / 180.0_dp           !< Conversion factor from degrees to radiant [-]
+ REAL(dp), PARAMETER ::  TO_DEGREES = 180.0_dp / PI           !< Conversion factor from radians to degrees [-]
+
+ ! COSMO-DE parameters
+ INTEGER, PARAMETER  ::  WATER_ID = 9                         !< Integer corresponding to the water soil type in COSMO-DE [-]
+ REAL(dp), PARAMETER ::  EARTH_RADIUS = 6371229.0_dp          !< Earth radius used in COSMO-DE [m]
+ REAL(dp), PARAMETER ::  P_SL = 1e5_dp                        !< Reference pressure for computation of COSMO-DE's basic state pressure [Pa]
+ REAL(dp), PARAMETER ::  T_SL = 288.15_dp                     !< Reference temperature for computation of COSMO-DE's basic state pressure [K]
+ REAL(dp), PARAMETER ::  BETA = 42.0_dp                       !< logarithmic lapse rate, dT / d ln(p), for computation of COSMO-DE's basic state pressure [K]
+ REAL(dp), PARAMETER ::  RD   = 287.05_dp                     !< specific gas constant of dry air, used in computation of COSMO-DE's basic state [J/kg/K]
+ REAL(dp), PARAMETER ::  RV   = 461.51_dp                     !< specific gas constant of water vapor [J/kg/K]
+ REAL(dp), PARAMETER ::  G    = 9.80665_dp                    !< acceleration of Earth's gravity, used in computation of COSMO-DE's basic state [m/s/s]
+ REAL(dp), PARAMETER ::  RHO_L = 1e3_dp                       !< density of liquid water, used to convert W_SO from [kg/m^2] to [m^3/m^3], in [kg/m^3]
+ REAL(dp), PARAMETER ::  HECTO = 100_dp                       !< unit conversion factor from hPa to Pa
+
+ ! PALM-4U parameters
+ REAL(dp), PARAMETER ::  OMEGA   = 7.29e-5_dp                 !< angular velocity of Earth's rotation [s^-1]
+ REAL(dp), PARAMETER ::  P_REF   = 1e5_dp                     !< Reference pressure for potential temperature [Pa]
+ REAL(dp), PARAMETER ::  RD_PALM = 287.0_dp                   !< specific gas constant of dry air, used in computation of PALM-4U's potential temperature [J/kg/K]
+ REAL(dp), PARAMETER ::  CP_PALM = 1005.0_dp                  !< heat capacity of dry air at constant pressure, used in computation of PALM-4U's potential temperature [J/kg/K]
+
+ ! INIFOR parameters
+ INTEGER, PARAMETER          ::  FILL_ITERATIONS = 5          !< Number of iterations for extrapolating soil data into COSMO-DE water cells [-]
+ INTEGER, PARAMETER          ::  FORCING_STEP = 1             !< Number of hours between forcing time steps [h]
+ REAL(dp), PARAMETER         ::  NUDGING_TAU = 21600.0_dp     !< Nudging relaxation time scale [s]
+ CHARACTER(LEN=*), PARAMETER ::  VERSION = '1.4.0'            !< INIFOR version number
+ CHARACTER(LEN=*), PARAMETER ::  COPYRIGHT = 'Copyright 2017-2018 Leibniz Universitaet Hannover' // &
+     NEW_LINE(' ') // ' Copyright 2017-2018 Deutscher Wetterdienst Offenbach' !< Copyright notice
+
+ END MODULE defs
Index: palm/trunk/UTIL/inifor/src/inifor_grid.f90
===================================================================
--- palm/trunk/UTIL/inifor/src/inifor_grid.f90	(revision 3447)
+++ palm/trunk/UTIL/inifor/src/inifor_grid.f90	(revision 3447)
@@ -0,0 +1,3928 @@
+!> @file src/inifor_grid.f90
+!------------------------------------------------------------------------------!
+! This file is part of the PALM model system.
+!
+! PALM is free software: you can redistribute it and/or modify it under the
+! terms of the GNU General Public License as published by the Free Software
+! Foundation, either version 3 of the License, or (at your option) any later
+! version.
+!
+! PALM is distributed in the hope that it will be useful, but WITHOUT ANY
+! WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+! A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+!
+! You should have received a copy of the GNU General Public License along with
+! PALM. If not, see <http://www.gnu.org/licenses/>.
+!
+! Copyright 2017-2018 Leibniz Universitaet Hannover
+! Copyright 2017-2018 Deutscher Wetterdienst Offenbach
+!------------------------------------------------------------------------------!
+!
+! Current revisions:
+! -----------------
+! 
+! 
+! Former revisions:
+! -----------------
+! $Id$
+! Renamed source files for compatibilty with PALM build system
+! 
+! 
+! 3395 2018-10-22 17:32:49Z eckhard
+! Added computation of geostrophic winds form COSMO pressure fields
+! Introduced averaging grids and internal 'output' variables for computation of
+!     geostrophic and large-scale forcings
+! Merged qv, uv and vg output variables and 'temperature' IO group into new
+!     'thermodynamics' IP group
+! Cleaned up terminal output, show some messages only with --debug option
+! Improved variable naming and readability
+! 
+! 
+! 3183 2018-07-27 14:25:55Z suehring
+! Introduced new PALM grid stretching
+! Updated variable names and metadata for PIDS v1.9 compatibility
+! Better compatibility with older Intel compilers:
+! - avoiding implicit array allocation with new get_netcdf_variable()
+!   subroutine instead of function
+! Improved command line interface:
+! - Produce forcing variables when '-mode profile' is being used
+! - Renamend initial-condition mode variable 'mode' to 'ic_mode'
+! - Improved handling of the start date string
+! Removed unnecessary variables and routines
+!
+! 
+! 3182 2018-07-27 13:36:03Z suehring
+! Initial revision
+!
+! 
+!
+! Authors:
+! --------
+! @author Eckhard Kadasch
+!
+!------------------------------------------------------------------------------!
+! Description:
+! ------------
+!> The grid module contains all variables and routines to specify and work with
+!> the numerical grids in INIFOR. By convention, all angles are stored in
+!> radians.
+!------------------------------------------------------------------------------!
+
+ MODULE grid
+
+    USE control
+    USE defs,                                                                  &
+        ONLY:  DATE, EARTH_RADIUS, TO_RADIANS, TO_DEGREES, PI, dp, hp, sp,     &
+               SNAME, LNAME, PATH, FORCING_STEP, WATER_ID, FILL_ITERATIONS,    &
+               BETA, P_SL, T_SL, BETA, RD, RV, G, P_REF, RD_PALM, CP_PALM,     &
+               RHO_L, OMEGA, HECTO
+    USE io,                                                                    &
+        ONLY:  get_netcdf_variable, get_netcdf_attribute,                      &
+               parse_command_line_arguments, validate_config
+    USE netcdf,                                                                &
+        ONLY:  NF90_MAX_NAME, NF90_MAX_VAR_DIMS
+    USE transform,                                                             &
+        ONLY:  average_2d, rotate_to_cosmo, find_horizontal_neighbours,&
+               compute_horizontal_interp_weights,                              &
+               find_vertical_neighbours_and_weights_interp,                    &
+               find_vertical_neighbours_and_weights_average, interpolate_2d,   &
+               gamma_from_hemisphere, phic_to_phin, lamc_to_lamn,              &
+               project, centre_velocities, phi2phirot, rla2rlarot, uv2uvrot,   &
+               phirot2phi, rlarot2rla
+    USE types
+    USE util
+    
+    IMPLICIT NONE
+    
+    SAVE
+    
+    REAL(dp) ::  averaging_angle   = 0.0_dp       !< latitudal and longitudal width of averaging regions [rad]
+    REAL(dp) ::  averaging_width_ns = 0.0_dp       !< longitudal width of averaging regions [m]
+    REAL(dp) ::  averaging_width_ew = 0.0_dp       !< latitudal width of averaging regions [m]
+    REAL(dp) ::  phi_equat         = 0.0_dp       !< latitude of rotated equator of COSMO-DE grid [rad]
+    REAL(dp) ::  phi_n             = 0.0_dp       !< latitude of rotated pole of COSMO-DE grid [rad]
+    REAL(dp) ::  lambda_n          = 0.0_dp       !< longitude of rotaded pole of COSMO-DE grid [rad]
+    REAL(dp) ::  phi_c             = 0.0_dp       !< rotated-grid latitude of the center of the PALM domain [rad]
+    REAL(dp) ::  lambda_c          = 0.0_dp       !< rotated-grid longitude of the centre of the PALM domain [rad]
+    REAL(dp) ::  phi_cn            = 0.0_dp       !< latitude of the rotated pole relative to the COSMO-DE grid [rad]
+    REAL(dp) ::  lambda_cn         = 0.0_dp       !< longitude of the rotated pole relative to the COSMO-DE grid [rad]
+    REAL(dp) ::  lam_centre        = 0.0_dp       !< longitude of the PLAM domain centre in the source (COSMO rotated-pole) system [rad]
+    REAL(dp) ::  phi_centre        = 0.0_dp       !< latitude of the PLAM domain centre in the source (COSMO rotated-pole) system [rad]
+    REAL(dp) ::  lam_east          = 0.0_dp       !< longitude of the east central-averaging-domain boundary in the source (COSMO rotated-pole) system [rad]
+    REAL(dp) ::  lam_west          = 0.0_dp       !< longitude of the west central-averaging-domain boundary in the source (COSMO rotated-pole) system [rad]
+    REAL(dp) ::  phi_north         = 0.0_dp       !< latitude of the north central-averaging-domain boundary in the source (COSMO rotated-pole) system [rad]
+    REAL(dp) ::  phi_south         = 0.0_dp       !< latitude of the south central-averaging-domain boundary in the source (COSMO rotated-pole) system [rad]
+    REAL(dp) ::  gam               = 0.0_dp       !< angle for working around phirot2phi/rlarot2rla bug
+    REAL(dp) ::  dx                = 0.0_dp       !< PALM-4U grid spacing in x direction [m]
+    REAL(dp) ::  dy                = 0.0_dp       !< PALM-4U grid spacing in y direction [m]
+    REAL(dp) ::  dz(10)            = -1.0_dp      !< PALM-4U grid spacing in z direction [m]
+    REAL(dp) ::  dz_max            = 1000.0_dp    !< maximum vertical grid spacing [m]
+    REAL(dp) ::  dz_stretch_factor = 1.08_dp      !< factor for vertical grid stretching [m]
+    REAL(dp) ::  dz_stretch_level  = -9999999.9_dp!< height above which the vertical grid will be stretched [m]
+    REAL(dp) ::  dz_stretch_level_start(9) = -9999999.9_dp !< namelist parameter
+    REAL(dp) ::  dz_stretch_level_end(9) = 9999999.9_dp !< namelist parameter
+    REAL(dp) ::  dz_stretch_factor_array(9) = 1.08_dp !< namelist parameter
+    REAL(dp) ::  dxi               = 0.0_dp       !< inverse PALM-4U grid spacing in x direction [m^-1]
+    REAL(dp) ::  dyi               = 0.0_dp       !< inverse PALM-4U grid spacing in y direction [m^-1]
+    REAL(dp) ::  dzi               = 0.0_dp       !< inverse PALM-4U grid spacing in z direction [m^-1]
+    REAL(dp) ::  f3                = 0.0_dp       !< Coriolis parameter
+    REAL(dp) ::  lx                = 0.0_dp       !< PALM-4U domain size in x direction [m]
+    REAL(dp) ::  ly                = 0.0_dp       !< PALM-4U domain size in y direction [m]
+    REAL(dp) ::  p0                = 0.0_dp       !< PALM-4U surface pressure, at z0 [Pa]
+    REAL(dp) ::  x0                = 0.0_dp       !< x coordinate of PALM-4U Earth tangent [m] 
+    REAL(dp) ::  y0                = 0.0_dp       !< y coordinate of PALM-4U Earth tangent [m] 
+    REAL(dp) ::  z0                = 0.0_dp       !< Elevation of the PALM-4U domain above sea level [m]
+    REAL(dp) ::  z_top             = 0.0_dp       !< height of the scalar top boundary [m]
+    REAL(dp) ::  zw_top            = 0.0_dp       !< height of the vertical velocity top boundary [m]
+    REAL(dp) ::  lonmin            = 0.0_dp       !< Minimunm longitude of COSMO-DE's rotated-pole grid
+    REAL(dp) ::  lonmax            = 0.0_dp       !< Maximum longitude of COSMO-DE's rotated-pole grid
+    REAL(dp) ::  latmin            = 0.0_dp       !< Minimunm latitude of COSMO-DE's rotated-pole grid
+    REAL(dp) ::  latmax            = 0.0_dp       !< Maximum latitude of COSMO-DE's rotated-pole grid
+    REAL(dp) ::  latitude          = 0.0_dp       !< geographical latitude of the PALM-4U origin, from inipar namelist [deg]
+    REAL(dp) ::  longitude         = 0.0_dp       !< geographical longitude of the PALM-4U origin, from inipar namelist [deg]
+    REAL(dp) ::  origin_lat        = 0.0_dp       !< geographical latitude of the PALM-4U origin, from static driver netCDF file [deg]
+    REAL(dp) ::  origin_lon        = 0.0_dp       !< geographical longitude of the PALM-4U origin, from static driver netCDF file [deg]
+    REAL(dp) ::  rotation_angle    = 0.0_dp       !< clockwise angle the PALM-4U north is rotated away from geographical north [deg]
+    REAL(dp) ::  end_time          = 0.0_dp       !< PALM-4U simulation time [s]
+
+    REAL(dp), DIMENSION(:,:,:), ALLOCATABLE, TARGET ::  hhl             !< heights of half layers (cell faces) above sea level in COSMO-DE, read in from external file
+    REAL(dp), DIMENSION(:,:,:), ALLOCATABLE, TARGET ::  hfl             !< heights of full layers (cell centres) above sea level in COSMO-DE, computed as arithmetic average of hhl
+    REAL(dp), DIMENSION(:), ALLOCATABLE, TARGET     ::  depths          !< COSMO-DE's TERRA-ML soil layer depths
+    REAL(dp), DIMENSION(:), ALLOCATABLE, TARGET     ::  d_depth_rho_inv !< COSMO-DE's TERRA-ML soil layer thicknesses
+    REAL(dp), DIMENSION(:), ALLOCATABLE, TARGET     ::  rlon            !< longitudes of COSMO-DE's rotated-pole grid
+    REAL(dp), DIMENSION(:), ALLOCATABLE, TARGET     ::  rlat            !< latitudes of COSMO-DE's rotated-pole grid
+    REAL(dp), DIMENSION(:), ALLOCATABLE, TARGET     ::  time            !< output times 
+    REAL(dp), DIMENSION(:), ALLOCATABLE, TARGET     ::  x               !< base palm grid x coordinate vector pointed to by grid_definitions
+    REAL(dp), DIMENSION(:), ALLOCATABLE, TARGET     ::  xu              !< base palm grid xu coordinate vector pointed to by grid_definitions
+    REAL(dp), DIMENSION(:), ALLOCATABLE, TARGET     ::  y               !< base palm grid y coordinate vector pointed to by grid_definitions
+    REAL(dp), DIMENSION(:), ALLOCATABLE, TARGET     ::  yv              !< base palm grid yv coordinate vector pointed to by grid_definitions
+    REAL(dp), DIMENSION(:), ALLOCATABLE, TARGET     ::  z_column        !< base palm grid z coordinate vector including the top boundary coordinate (entire column)
+    REAL(dp), DIMENSION(:), ALLOCATABLE, TARGET     ::  zw_column       !< base palm grid zw coordinate vector including the top boundary coordinate (entire column)
+    REAL(dp), DIMENSION(:), ALLOCATABLE, TARGET     ::  z               !< base palm grid z coordinate vector pointed to by grid_definitions
+    REAL(dp), DIMENSION(:), ALLOCATABLE, TARGET     ::  zw              !< base palm grid zw coordinate vector pointed to by grid_definitions
+
+    INTEGER(hp), DIMENSION(:,:,:), ALLOCATABLE, TARGET ::  soiltyp      !< COSMO-DE soil type map
+    INTEGER ::  dz_stretch_level_end_index(9)               !< vertical grid level index until which the vertical grid spacing is stretched
+    INTEGER ::  dz_stretch_level_start_index(9)             !< vertical grid level index above which the vertical grid spacing is stretched
+    INTEGER ::  nt    !< number of output time steps
+    INTEGER ::  nx    !< number of PALM-4U grid points in x direction
+    INTEGER ::  ny    !< number of PALM-4U grid points in y direction
+    INTEGER ::  nz    !< number of PALM-4U grid points in z direction
+    INTEGER ::  nlon  !< number of longitudal points in target grid (COSMO-DE)
+    INTEGER ::  nlat  !< number of latitudal points in target grid (COSMO-DE)
+    INTEGER ::  nlev  !< number of levels in target grid (COSMO-DE)
+    INTEGER ::  layers !< number of COSMO-DE soil layers
+    INTEGER ::  start_hour_flow         !< start of flow forcing in number of hours relative to start_date
+    INTEGER ::  start_hour_soil         !< start of soil forcing in number of hours relative to start_date, typically equals start_hour_flow
+    INTEGER ::  start_hour_radiation    !< start of radiation forcing in number of hours relative to start_date, 0 to 2 hours before start_hour_flow to reconstruct hourly averages from one- to three hourly averages of the input data
+    INTEGER ::  start_hour_soilmoisture !< start of forcing for the soil moisture spin-up in number of hours relative to start_date, typically -672 (-4 weeks)
+    INTEGER ::  end_hour  !< simulation time in hours
+    INTEGER ::  end_hour_soilmoisture  !< end of soil moisture spin-up in hours relative to start_hour_flow
+    INTEGER ::  step_hour !< number of hours between forcing time steps
+
+    LOGICAL ::  init_variables_required
+    LOGICAL ::  boundary_variables_required
+    LOGICAL ::  ls_forcing_variables_required
+    LOGICAL ::  profile_grids_required
+
+    TYPE(nc_var), ALLOCATABLE, TARGET ::  input_var_table(:)  !< table of input variables
+    TYPE(nc_var), ALLOCATABLE, TARGET ::  output_var_table(:) !< table of input variables
+    TYPE(nc_var)                      ::  cosmo_var           !< COSMO-DE dummy variable, used for reading HHL, rlon, rlat
+
+    TYPE(grid_definition), TARGET ::  palm_grid                       !< PALM-4U grid in the target system (COSMO-DE rotated-pole)
+    TYPE(grid_definition), TARGET ::  palm_intermediate               !< PALM-4U grid with coarse vertical grid wiht levels interpolated from COSMO-DE grid
+    TYPE(grid_definition), TARGET ::  cosmo_grid                      !< target system (COSMO-DE rotated-pole)
+    TYPE(grid_definition), TARGET ::  scalars_east_grid               !< 
+    TYPE(grid_definition), TARGET ::  scalars_west_grid               !< 
+    TYPE(grid_definition), TARGET ::  scalars_north_grid              !< 
+    TYPE(grid_definition), TARGET ::  scalars_south_grid              !< 
+    TYPE(grid_definition), TARGET ::  scalars_top_grid                !< 
+    TYPE(grid_definition), TARGET ::  scalars_east_intermediate       !< 
+    TYPE(grid_definition), TARGET ::  scalars_west_intermediate       !< 
+    TYPE(grid_definition), TARGET ::  scalars_north_intermediate      !< 
+    TYPE(grid_definition), TARGET ::  scalars_south_intermediate      !< 
+    TYPE(grid_definition), TARGET ::  scalars_top_intermediate        !< 
+    TYPE(grid_definition), TARGET ::  u_initial_grid                  !< 
+    TYPE(grid_definition), TARGET ::  u_east_grid                     !< 
+    TYPE(grid_definition), TARGET ::  u_west_grid                     !< 
+    TYPE(grid_definition), TARGET ::  u_north_grid                    !< 
+    TYPE(grid_definition), TARGET ::  u_south_grid                    !< 
+    TYPE(grid_definition), TARGET ::  u_top_grid                      !< 
+    TYPE(grid_definition), TARGET ::  u_initial_intermediate          !<
+    TYPE(grid_definition), TARGET ::  u_east_intermediate             !< 
+    TYPE(grid_definition), TARGET ::  u_west_intermediate             !< 
+    TYPE(grid_definition), TARGET ::  u_north_intermediate            !< 
+    TYPE(grid_definition), TARGET ::  u_south_intermediate            !< 
+    TYPE(grid_definition), TARGET ::  u_top_intermediate              !< 
+    TYPE(grid_definition), TARGET ::  v_initial_grid                  !< 
+    TYPE(grid_definition), TARGET ::  v_east_grid                     !< 
+    TYPE(grid_definition), TARGET ::  v_west_grid                     !< 
+    TYPE(grid_definition), TARGET ::  v_north_grid                    !< 
+    TYPE(grid_definition), TARGET ::  v_south_grid                    !< 
+    TYPE(grid_definition), TARGET ::  v_top_grid                      !< 
+    TYPE(grid_definition), TARGET ::  v_initial_intermediate          !<
+    TYPE(grid_definition), TARGET ::  v_east_intermediate             !< 
+    TYPE(grid_definition), TARGET ::  v_west_intermediate             !< 
+    TYPE(grid_definition), TARGET ::  v_north_intermediate            !< 
+    TYPE(grid_definition), TARGET ::  v_south_intermediate            !< 
+    TYPE(grid_definition), TARGET ::  v_top_intermediate              !< 
+    TYPE(grid_definition), TARGET ::  w_initial_grid                  !< 
+    TYPE(grid_definition), TARGET ::  w_east_grid                     !< 
+    TYPE(grid_definition), TARGET ::  w_west_grid                     !< 
+    TYPE(grid_definition), TARGET ::  w_north_grid                    !< 
+    TYPE(grid_definition), TARGET ::  w_south_grid                    !< 
+    TYPE(grid_definition), TARGET ::  w_top_grid                      !< 
+    TYPE(grid_definition), TARGET ::  w_initial_intermediate          !<
+    TYPE(grid_definition), TARGET ::  w_east_intermediate             !< 
+    TYPE(grid_definition), TARGET ::  w_west_intermediate             !< 
+    TYPE(grid_definition), TARGET ::  w_north_intermediate            !< 
+    TYPE(grid_definition), TARGET ::  w_south_intermediate            !< 
+    TYPE(grid_definition), TARGET ::  w_top_intermediate              !< 
+
+    TYPE(grid_definition), TARGET ::  north_averaged_scalar_profile
+    TYPE(grid_definition), TARGET ::  south_averaged_scalar_profile
+    TYPE(grid_definition), TARGET ::  west_averaged_scalar_profile
+    TYPE(grid_definition), TARGET ::  east_averaged_scalar_profile
+    TYPE(grid_definition), TARGET ::  averaged_scalar_profile
+    TYPE(grid_definition), TARGET ::  averaged_w_profile
+
+    TYPE(io_group), ALLOCATABLE, TARGET ::  io_group_list(:)  !< List of I/O groups, which group together output variables that share the same input variable
+ 
+    NAMELIST /inipar/ nx, ny, nz, dx, dy, dz, longitude, latitude,             &
+                      dz_max, dz_stretch_factor, dz_stretch_level,             & !< old grid stretching parameters
+                      dz_stretch_level_start, dz_stretch_level_end               !< new grid stretching parameters
+    NAMELIST /d3par/  end_time
+    
+    CHARACTER(LEN=LNAME) ::  nc_source_text     = ''  !< Text describing the source of the output data, e.g. 'COSMO-DE analysis from ...'
+    CHARACTER(LEN=PATH), ALLOCATABLE, DIMENSION(:) ::  flow_files
+    CHARACTER(LEN=PATH), ALLOCATABLE, DIMENSION(:) ::  soil_moisture_files
+    CHARACTER(LEN=PATH), ALLOCATABLE, DIMENSION(:) ::  soil_files
+    CHARACTER(LEN=PATH), ALLOCATABLE, DIMENSION(:) ::  radiation_files
+    CHARACTER(LEN=SNAME) ::  input_prefix         !< Prefix of input files, e.g. 'laf' for COSMO-DE analyses
+    CHARACTER(LEN=SNAME) ::  flow_prefix          !< Prefix of flow input files, e.g. 'laf' for COSMO-DE analyses
+    CHARACTER(LEN=SNAME) ::  soil_prefix          !< Prefix of soil input files, e.g. 'laf' for COSMO-DE analyses
+    CHARACTER(LEN=SNAME) ::  radiation_prefix     !< Prefix of radiation input files, e.g. 'laf' for COSMO-DE analyses
+    CHARACTER(LEN=SNAME) ::  soilmoisture_prefix  !< Prefix of input files for soil moisture spin-up, e.g. 'laf' for COSMO-DE analyses
+    CHARACTER(LEN=SNAME) ::  flow_suffix          !< Suffix of flow input files, e.g. 'flow'
+    CHARACTER(LEN=SNAME) ::  soil_suffix          !< Suffix of soil input files, e.g. 'soil'
+    CHARACTER(LEN=SNAME) ::  radiation_suffix     !< Suffix of radiation input files, e.g. 'radiation'
+    CHARACTER(LEN=SNAME) ::  soilmoisture_suffix  !< Suffix of input files for soil moisture spin-up, e.g. 'soilmoisture'
+                          
+    TYPE(nc_file) ::  output_file
+
+    TYPE(inifor_config) ::  cfg !< Container of INIFOR configuration
+
+ CONTAINS
+    
+    SUBROUTINE setup_parameters()
+       INTEGER ::  k
+
+!
+!------------------------------------------------------------------------------
+! Section 1: Define default parameters
+!------------------------------------------------------------------------------
+       cfg % start_date = '2013072100'
+       end_hour = 2
+       start_hour_soil = -2
+       start_hour_soilmoisture = - (4 * 7 * 24) - 2
+
+       lonmin =  -5.0_dp * TO_RADIANS
+       lonmax =   5.5_dp * TO_RADIANS
+       latmin =  -5.0_dp * TO_RADIANS
+       latmax =   6.5_dp * TO_RADIANS
+
+       ! COSMO-DE default rotated pole
+       phi_n     =   40.0_dp * TO_RADIANS
+       phi_equat =   50.0_dp * TO_RADIANS
+       lambda_n  = -170.0_dp * TO_RADIANS
+
+       ! COMSMO-DE soil layers
+       layers = 8    
+       ALLOCATE( depths(layers), d_depth_rho_inv(layers) )
+       depths = (/0.005_dp, 0.02_dp, 0.06_dp, 0.18_dp, 0.54_dp, 1.62_dp, 4.86_dp, 14.58_dp/)
+       d_depth_rho_inv = 1.0_dp / &
+          ( (/0.01_dp, 0.02_dp, 0.06_dp, 0.18_dp, 0.54_dp, 1.62_dp, 4.86_dp, 14.58_dp/) * RHO_L )
+
+       ! Defaultmain centre (_c) of the PALM-4U grid in the geographical system (_g)
+       origin_lat = 52.325079_dp * TO_RADIANS ! south-west of Berlin, origin used for the Dec 2017 showcase simulation
+       origin_lon = 13.082744_dp * TO_RADIANS
+       cfg % z0 = 35.0_dp
+
+       ! Default atmospheric parameters
+       cfg % ug = 0.0_dp
+       cfg % vg = 0.0_dp
+       cfg % p0 = P_SL
+
+       ! Parameters for file names
+       start_hour_flow = 0
+       start_hour_soil = 0
+       start_hour_radiation = 0
+       start_hour_soilmoisture = start_hour_flow - 2
+       end_hour_soilmoisture = start_hour_flow
+       step_hour = FORCING_STEP
+
+       input_prefix = 'laf'  ! 'laf' for COSMO-DE analyses
+       cfg % flow_prefix = input_prefix
+       cfg % input_prefix = input_prefix
+       cfg % soil_prefix = input_prefix
+       cfg % radiation_prefix = input_prefix
+       cfg % soilmoisture_prefix  = input_prefix
+
+       flow_suffix = '-flow'
+       soil_suffix = '-soil'
+       radiation_suffix = '-rad'
+       soilmoisture_suffix = '-soilmoisture'
+
+       cfg % debug = .FALSE.
+       cfg % averaging_angle = 2.0_dp
+!
+!------------------------------------------------------------------------------
+! Section 2: Read command-line arguments, namelist, and grid parameters
+!------------------------------------------------------------------------------
+
+       ! Set default paths and modes
+       cfg % input_path         = './'
+       cfg % hhl_file           = ''
+       cfg % soiltyp_file       = ''
+       cfg % namelist_file      = './namelist'
+       cfg % static_driver_file = ''
+       cfg % output_file = './palm-4u-input.nc'
+       cfg % ic_mode = 'volume'
+       cfg % bc_mode = 'real'
+       cfg % averaging_mode = 'level'
+
+       ! Overwrite defaults with user configuration
+       CALL parse_command_line_arguments( cfg )
+
+       flow_prefix = TRIM(cfg % input_prefix)
+       radiation_prefix = TRIM(cfg % input_prefix)
+       soil_prefix = TRIM(cfg % input_prefix)
+       soilmoisture_prefix = TRIM(cfg % input_prefix)
+       IF (cfg % flow_prefix_is_set)  flow_prefix = TRIM(cfg % flow_prefix)
+       IF (cfg % radiation_prefix_is_set)  radiation_prefix = TRIM(cfg % radiation_prefix)
+       IF (cfg % soil_prefix_is_set)  soil_prefix = TRIM(cfg % soil_prefix)
+       IF (cfg % soilmoisture_prefix_is_set)  soilmoisture_prefix = TRIM(cfg % soilmoisture_prefix)
+
+       output_file % name = cfg % output_file
+       z0 = cfg % z0
+       p0 = cfg % p0
+
+       init_variables_required = .TRUE.
+       boundary_variables_required = TRIM( cfg % bc_mode ) == 'real'
+       ls_forcing_variables_required = TRIM( cfg % bc_mode ) == 'ideal'
+
+       IF ( ls_forcing_variables_required )  THEN
+          message = "Averaging of large-scale forcing profiles " //            &
+                    "has not been implemented, yet."
+          CALL abort('setup_parameters', message)
+       END IF
+
+
+       ! Set default file paths, if not specified by user.
+       CALL normalize_path(cfg % input_path)
+       IF (TRIM(cfg % hhl_file) == '')  cfg % hhl_file = TRIM(cfg % input_path) // 'hhl.nc'
+       IF (TRIM(cfg % soiltyp_file) == '')  cfg % soiltyp_file = TRIM(cfg % input_path) // 'soil.nc'
+
+       CALL validate_config( cfg ) 
+
+       CALL report('setup_parameters', "initialization mode: " // TRIM(cfg % ic_mode))
+       CALL report('setup_parameters', "       forcing mode: " // TRIM(cfg % bc_mode))
+       CALL report('setup_parameters', "          data path: " // TRIM(cfg % input_path))
+       CALL report('setup_parameters', "           hhl file: " // TRIM(cfg % hhl_file))
+       CALL report('setup_parameters', "       soiltyp file: " // TRIM(cfg % soiltyp_file))
+       CALL report('setup_parameters', "      namelist file: " // TRIM(cfg % namelist_file))
+       CALL report('setup_parameters', "   output data file: " // TRIM(output_file % name))
+
+ CALL run_control('time', 'init')
+       ! Read in namelist parameters
+       OPEN(10, FILE=cfg % namelist_file)
+       READ(10, NML=inipar) ! nx, ny, nz, dx, dy, dz
+       READ(10, NML=d3par)  ! end_time
+       CLOSE(10)
+ CALL run_control('time', 'read')
+
+       end_hour = CEILING( end_time / 3600.0 * step_hour )
+
+       ! Generate input file lists
+       CALL get_input_file_list(                                               &
+          cfg % start_date, start_hour_flow, end_hour, step_hour,              &
+          cfg % input_path, flow_prefix, flow_suffix, flow_files)
+       CALL get_input_file_list(                                               &
+          cfg % start_date, start_hour_soil, end_hour, step_hour,              &
+          cfg % input_path, soil_prefix, soil_suffix, soil_files)
+       CALL get_input_file_list(                                               &
+          cfg % start_date, start_hour_radiation, end_hour, step_hour,         &
+          cfg % input_path, radiation_prefix, radiation_suffix, radiation_files)
+       CALL get_input_file_list(                                               &
+          cfg % start_date, start_hour_soilmoisture, end_hour_soilmoisture, step_hour, &
+          cfg % input_path, soilmoisture_prefix, soilmoisture_suffix, soil_moisture_files)
+
+!
+!------------------------------------------------------------------------------
+! Section 3: Check for consistency
+!------------------------------------------------------------------------------
+
+!
+!------------------------------------------------------------------------------
+! Section 4: Compute additional parameters
+!------------------------------------------------------------------------------
+!------------------------------------------------------------------------------
+! Section 4.1: COSMO-DE parameters
+!------------------------------------------------------------------------------
+
+
+ CALL run_control('time', 'init')
+       ! Read COSMO-DE soil type map
+       cosmo_var % name = 'SOILTYP'
+       CALL get_netcdf_variable(cfg % soiltyp_file, cosmo_var, soiltyp)
+
+       message = 'Reading PALM-4U origin from'
+       IF (TRIM(cfg % static_driver_file) .NE. '')  THEN
+
+          origin_lon = get_netcdf_attribute(cfg % static_driver_file, 'origin_lon')
+          origin_lat = get_netcdf_attribute(cfg % static_driver_file, 'origin_lat')
+
+          message = TRIM(message) // " static driver file '"                   &
+                                  // TRIM(cfg % static_driver_file) // "'"
+
+
+       ELSE
+
+          origin_lon = longitude
+          origin_lat = latitude
+
+          message = TRIM(message) // " namlist file '"                         &
+                                  // TRIM(cfg % namelist_file) // "'"
+
+       END IF
+       origin_lon = origin_lon * TO_RADIANS
+       origin_lat = origin_lat * TO_RADIANS
+
+       CALL report('setup_parameters', message)
+
+
+       ! Read in COSMO-DE heights of half layers (vertical cell faces)
+       cosmo_var % name = 'HHL'
+       CALL get_netcdf_variable(cfg % hhl_file, cosmo_var, hhl)
+ CALL run_control('time', 'read')
+
+       CALL reverse(hhl)
+       nlon = SIZE(hhl, 1)
+       nlat = SIZE(hhl, 2)
+       nlev = SIZE(hhl, 3)
+
+ CALL run_control('time', 'comp')
+
+       ! Appoximate COSMO-DE heights of full layers (cell centres)
+       ALLOCATE( hfl(nlon, nlat, nlev-1) )
+ CALL run_control('time', 'alloc')
+       DO k = 1, nlev-1
+          hfl(:,:,k) = 0.5_dp * ( hhl(:,:,k) +                                 &
+                                  hhl(:,:,k+1) )
+       END DO
+
+!------------------------------------------------------------------------------
+! Section 4.2: PALM-4U parameters
+!------------------------------------------------------------------------------
+       ! PALM-4U domain extents
+       lx = (nx+1) * dx
+       ly = (ny+1) * dy
+       
+       ! PALM-4U point of Earth tangency
+       x0 = 0.0_dp
+       y0 = 0.0_dp
+
+       ! time vector
+       nt = CEILING(end_time / (step_hour * 3600.0_dp)) + 1
+       ALLOCATE( time(nt) )
+       CALL linspace(0.0_dp, 3600.0_dp * (nt-1), time)
+       output_file % time => time
+ CALL run_control('time', 'init')
+
+! Convert the PALM-4U origin coordinates to COSMO's rotated-pole grid
+       phi_c    = TO_RADIANS *                                                 &
+                  phi2phirot( origin_lat * TO_DEGREES, origin_lon * TO_DEGREES,&
+                              phi_n * TO_DEGREES, lambda_n * TO_DEGREES )
+       lambda_c = TO_RADIANS *                                                 &
+                  rla2rlarot( origin_lat * TO_DEGREES, origin_lon * TO_DEGREES,&
+                              phi_n * TO_DEGREES, lambda_n * TO_DEGREES,     &
+                              0.0_dp )
+
+! Set gamma according to whether PALM domain is in the northern or southern
+! hemisphere of the COSMO-DE rotated-pole system. Gamma assumes either the
+! value 0 or PI and is needed to work around around a bug in the rotated-pole
+! coordinate transformations.
+       gam = gamma_from_hemisphere(origin_lat, phi_equat)
+
+! Compute the north pole of the rotated-pole grid centred at the PALM-4U domain
+! centre. The resulting (phi_cn, lambda_cn) are coordinates in COSMO-DE's
+! rotated-pole grid.
+       phi_cn    = phic_to_phin(phi_c) 
+       lambda_cn = lamc_to_lamn(phi_c, lambda_c) 
+
+       message =   "PALM-4U origin:" // NEW_LINE('') // &
+          "           lon (lambda) = " // &
+          TRIM(real_to_str_f(origin_lon * TO_DEGREES)) // " deg"// NEW_LINE(' ') //&
+          "           lat (phi   ) = " // &
+          TRIM(real_to_str_f(origin_lat * TO_DEGREES)) // " deg (geographical)" // NEW_LINE(' ') //&
+          "           lon (lambda) = " // &
+          TRIM(real_to_str_f(lambda_c * TO_DEGREES)) // " deg" // NEW_LINE(' ') // &
+          "           lat (phi   ) = " // &
+          TRIM(real_to_str_f(phi_c * TO_DEGREES)) // " deg (COSMO-DE rotated-pole)"
+      CALL report ('setup_parameters', message)
+
+       message = "North pole of the rotated COSMO-DE system:" // NEW_LINE(' ') // &
+          "           lon (lambda) = " // &
+          TRIM(real_to_str_f(lambda_n * TO_DEGREES)) // " deg" // NEW_LINE(' ') //&
+          "           lat (phi   ) = " // &
+          TRIM(real_to_str_f(phi_n * TO_DEGREES)) // " deg (geographical)"
+       CALL report ('setup_parameters', message)
+          
+       message = "North pole of the rotated palm system:" // NEW_LINE(' ') // &
+          "           lon (lambda) = " // &
+          TRIM(real_to_str_f(lambda_cn * TO_DEGREES)) // " deg" // NEW_LINE(' ') // &
+          "           lat (phi   ) = " // &
+          TRIM(real_to_str_f(phi_cn * TO_DEGREES)) // " deg (COSMO-DE rotated-pole)"
+       CALL report ('setup_parameters', message)
+
+ CALL run_control('time', 'comp')
+
+!------------------------------------------------------------------------------
+! Section 4.3: INIFOR averaging domains
+!------------------------------------------------------------------------------
+
+    ! Compute coordiantes of the PALM centre in the source (COSMO) system
+    phi_centre = phirot2phi(                                                   &
+       phirot = project(0.5_dp*ly, y0, EARTH_RADIUS) * TO_DEGREES,             &
+       rlarot = project(0.5_dp*lx, x0, EARTH_RADIUS) * TO_DEGREES,             &
+       polphi = phi_cn * TO_DEGREES, pollam = lambda_cn * TO_DEGREES,          &
+       polgam = gam * TO_DEGREES                                               &
+    ) * TO_RADIANS
+
+    lam_centre = rlarot2rla(                                                   &
+       phirot = project(0.5_dp*ly, y0, EARTH_RADIUS) * TO_DEGREES,             &
+       rlarot = project(0.5_dp*lx, x0, EARTH_RADIUS) * TO_DEGREES,             &
+       polphi = phi_cn * TO_DEGREES, pollam = lambda_cn * TO_DEGREES,          &
+       polgam = gam * TO_DEGREES                                               &
+    ) * TO_RADIANS
+
+    message = "PALM-4U centre:" // NEW_LINE('') // &
+       "           lon (lambda) = " // &
+       TRIM(real_to_str_f(lam_centre * TO_DEGREES)) // " deg" // NEW_LINE(' ') // &
+       "           lat (phi   ) = " // &
+       TRIM(real_to_str_f(phi_centre * TO_DEGREES)) // " deg (COSMO-DE rotated-pole)"
+    CALL report( 'setup_parameters', message )
+
+
+    ! Compute boundaries of the central averaging box
+    averaging_angle = cfg % averaging_angle * TO_RADIANS
+    lam_east = lam_centre + 0.5_dp * averaging_angle
+    lam_west = lam_centre - 0.5_dp * averaging_angle
+    phi_north = phi_centre + 0.5_dp * averaging_angle
+    phi_south = phi_centre - 0.5_dp * averaging_angle
+    averaging_width_ew = averaging_angle * COS(phi_centre) * EARTH_RADIUS
+    averaging_width_ns = averaging_angle * EARTH_RADIUS
+
+    ! Coriolis parameter
+    f3 = 2.0_dp * OMEGA * SIN(                                                 &
+       TO_RADIANS*phirot2phi( phi_centre * TO_DEGREES, lam_centre * TO_DEGREES,&
+                              phi_n * TO_DEGREES, lambda_n * TO_DEGREES,       &
+                              gam * TO_DEGREES )                               &
+       )
+
+    END SUBROUTINE setup_parameters
+
+
+!------------------------------------------------------------------------------!
+! Description:
+! ------------
+!> Initializes the COSMO-DE, PALM-4U, PALM-4U boundary grids.
+!------------------------------------------------------------------------------!
+    SUBROUTINE setup_grids() ! setup_grids(inifor_settings(with nx, ny, nz,...))
+       CHARACTER ::  interp_mode
+
+!------------------------------------------------------------------------------
+! Section 0: Define base PALM-4U grid coordinate vectors
+!------------------------------------------------------------------------------
+       ! palm x y z, we allocate the column to nz+1 in order to include the top
+       ! scalar boundary. The interpolation grids will be associated with
+       ! a shorter column that omits the top element.
+       
+       ALLOCATE( x(0:nx), y(0:ny), z(1:nz), z_column(1:nz+1) )
+       CALL linspace(0.5_dp * dx, lx - 0.5_dp * dx, x)
+       CALL linspace(0.5_dp * dy, ly - 0.5_dp * dy, y)
+       CALL stretched_z(z_column, dz, dz_max=dz_max,                           &
+                        dz_stretch_factor=dz_stretch_factor,                   &
+                        dz_stretch_level=dz_stretch_level,                     &
+                        dz_stretch_level_start=dz_stretch_level_start,         &
+                        dz_stretch_level_end=dz_stretch_level_end,             &
+                        dz_stretch_factor_array=dz_stretch_factor_array)
+       z(1:nz) = z_column(1:nz)
+       z_top = z_column(nz+1)
+
+       ! palm xu yv zw, compared to the scalar grid, velocity coordinates
+       ! contain one element less.
+       ALLOCATE( xu(1:nx),  yv(1:ny), zw(1:nz-1), zw_column(1:nz))
+       CALL linspace(dx, lx - dx, xu)
+       CALL linspace(dy, ly - dy, yv)
+       CALL midpoints(z_column, zw_column)
+       zw(1:nz-1) = zw_column(1:nz-1)
+       zw_top     = zw_column(nz)
+
+
+!------------------------------------------------------------------------------
+! Section 1: Define initialization and boundary grids
+!------------------------------------------------------------------------------
+       CALL init_grid_definition('palm', grid=palm_grid,                       &
+               xmin=0.0_dp, xmax=lx,                                           &
+               ymin=0.0_dp, ymax=ly,                                           &
+               x0=x0, y0=y0, z0=z0,                      &
+               nx=nx, ny=ny, nz=nz, z=z, zw=zw, ic_mode=cfg % ic_mode)
+
+       ! Subtracting 1 because arrays will be allocated with nlon + 1 elements.
+       CALL init_grid_definition('cosmo-de', grid=cosmo_grid,                  &
+               xmin=lonmin, xmax=lonmax,                                       &
+               ymin=latmin, ymax=latmax,                                       &
+               x0=x0, y0=y0, z0=0.0_dp,             &
+               nx=nlon-1, ny=nlat-1, nz=nlev-1)
+
+! Define intermediate grid. This is the same as palm_grid except with a much
+! coarser vertical grid. The vertical levels are interpolated in each PALM-4U
+! column from COSMO-DE's secondary levels. The main levels are then computed as
+! the averages of the bounding secondary levels.
+       CALL init_grid_definition('palm intermediate', grid=palm_intermediate,  &
+               xmin=0.0_dp, xmax=lx,                                           &
+               ymin=0.0_dp, ymax=ly,                                           &
+               x0=x0, y0=y0, z0=z0,                      &
+               nx=nx, ny=ny, nz=nlev-2)
+
+       CALL init_grid_definition('boundary', grid=u_initial_grid,              &
+               xmin = dx, xmax = lx - dx,                                      &
+               ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy,                    &
+               x0=x0, y0=y0, z0 = z0,                                          &
+               nx = nx-1, ny = ny, nz = nz,                                    &
+               z=z, ic_mode=cfg % ic_mode)
+
+       CALL init_grid_definition('boundary', grid=v_initial_grid,              &
+               xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx,                    &
+               ymin = dy, ymax = ly - dy,                                      &
+               x0=x0, y0=y0, z0 = z0,                                          &
+               nx = nx, ny = ny-1, nz = nz,                                    &
+               z=z, ic_mode=cfg % ic_mode)
+
+       CALL init_grid_definition('boundary', grid=w_initial_grid,              &
+               xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx,                    &
+               ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy,                    &
+               x0=x0, y0=y0, z0 = z0,                                          &
+               nx = nx, ny = ny, nz = nz-1,                                    &
+               z=zw, ic_mode=cfg % ic_mode)
+
+       CALL init_grid_definition('boundary intermediate', grid=u_initial_intermediate,      &
+               xmin = dx, xmax = lx - dx,                                      &
+               ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy,                    &
+               x0=x0, y0=y0, z0 = z0,                                          &
+               nx = nx-1, ny = ny, nz = nlev - 2)
+
+       CALL init_grid_definition('boundary intermediate', grid=v_initial_intermediate,      &
+               xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx,                    &
+               ymin = dy, ymax = ly - dy,                                      &
+               x0=x0, y0=y0, z0 = z0,                                          &
+               nx = nx, ny = ny-1, nz = nlev - 2)
+
+       CALL init_grid_definition('boundary intermediate', grid=w_initial_intermediate,      &
+               xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx,                    &
+               ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy,                    &
+               x0=x0, y0=y0, z0 = z0,                                          &
+               nx = nx, ny = ny, nz = nlev - 1)
+
+      IF (boundary_variables_required)  THEN
+!
+!------------------------------------------------------------------------------
+! Section 2: Define PALM-4U boundary grids
+!------------------------------------------------------------------------------
+          CALL init_grid_definition('boundary', grid=scalars_east_grid,           &
+                  xmin = lx + 0.5_dp * dx, xmax = lx + 0.5_dp * dx,               &
+                  ymin =  0.5_dp * dy, ymax = ly - 0.5_dp * dy,                   &
+                  x0=x0, y0=y0, z0 = z0,                                          &
+                  nx = 0, ny = ny, nz = nz, z=z)
+
+          CALL init_grid_definition('boundary', grid=scalars_west_grid,           &
+                  xmin = -0.5_dp * dx, xmax = -0.5_dp * dx,                       &
+                  ymin =  0.5_dp * dy, ymax = ly - 0.5_dp * dy,                   &
+                  x0=x0, y0=y0, z0 = z0,                                          &
+                  nx = 0, ny = ny, nz = nz, z=z)
+
+          CALL init_grid_definition('boundary', grid=scalars_north_grid,          &
+                  xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx,                    &
+                  ymin = ly + 0.5_dp * dy, ymax = ly + 0.5_dp * dy,               &
+                  x0=x0, y0=y0, z0 = z0,                                          &
+                  nx = nx, ny = 0, nz = nz, z=z)
+
+          CALL init_grid_definition('boundary', grid=scalars_south_grid,          &
+                  xmin =  0.5_dp * dx, xmax = lx - 0.5_dp * dx,                   &
+                  ymin = -0.5_dp * dy, ymax = -0.5_dp * dy,                       &
+                  x0=x0, y0=y0, z0 = z0,                                          &
+                  nx = nx, ny = 0, nz = nz, z=z)
+
+          CALL init_grid_definition('boundary', grid=scalars_top_grid,            &
+                  xmin =  0.5_dp * dx, xmax = lx - 0.5_dp * dx,                   &
+                  ymin =  0.5_dp * dy, ymax = ly - 0.5_dp * dy,                   &
+                  x0=x0, y0=y0, z0 = z0,                                          &
+                  nx = nx, ny = ny, nz = 1, z=(/z_top/))
+
+          CALL init_grid_definition('boundary', grid=u_east_grid,                 &
+                  xmin = lx, xmax = lx,                                           &
+                  ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy,                    &
+                  x0=x0, y0=y0, z0 = z0,                                          &
+                  nx = 0, ny = ny, nz = nz, z=z)
+
+          CALL init_grid_definition('boundary', grid=u_west_grid,                 &
+                  xmin = 0.0_dp, xmax = 0.0_dp,                                   &
+                  ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy,                    &
+                  x0=x0, y0=y0, z0 = z0,                                          &
+                  nx = 0, ny = ny, nz = nz, z=z)
+
+          CALL init_grid_definition('boundary', grid=u_north_grid,                &
+                  xmin = dx, xmax = lx - dx,                                      &
+                  ymin = ly + 0.5_dp * dy, ymax = ly + 0.5_dp * dy,               &
+                  x0=x0, y0=y0, z0 = z0,                                          &
+                  nx = nx-1, ny = 0, nz = nz, z=z)
+    
+          CALL init_grid_definition('boundary', grid=u_south_grid,                &
+                  xmin = dx, xmax = lx - dx,                                      &
+                  ymin = -0.5_dp * dy, ymax = -0.5_dp * dy,                       &
+                  x0=x0, y0=y0, z0 = z0,                                          &
+                  nx = nx-1, ny = 0, nz = nz, z=z)
+
+          CALL init_grid_definition('boundary', grid=u_top_grid,                  &
+                  xmin = dx, xmax = lx - dx,                                      &
+                  ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy,                    &
+                  x0=x0, y0=y0, z0 = z0,                                          &
+                  nx = nx-1, ny = ny, nz = 1, z=(/z_top/))
+
+          CALL init_grid_definition('boundary', grid=v_east_grid,                 &
+                  xmin = lx + 0.5_dp * dx, xmax = lx + 0.5_dp * dx,               &
+                  ymin = dy, ymax = ly - dy,                                      &
+                  x0=x0, y0=y0, z0 = z0,                                          &
+                  nx = 0, ny = ny-1, nz = nz, z=z)
+
+          CALL init_grid_definition('boundary', grid=v_west_grid,                 &
+                  xmin = -0.5_dp * dx, xmax = -0.5_dp * dx,                       &
+                  ymin = dy, ymax = ly - dy,                                      &
+                  x0=x0, y0=y0, z0 = z0,                                          &
+                  nx = 0, ny = ny-1, nz = nz, z=z)
+
+          CALL init_grid_definition('boundary', grid=v_north_grid,                &
+                  xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx,                    &
+                  ymin = ly, ymax = ly,                                           &
+                  x0=x0, y0=y0, z0 = z0,                                          &
+                  nx = nx, ny = 0, nz = nz, z=z)
+
+          CALL init_grid_definition('boundary', grid=v_south_grid,                &
+                  xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx,                    &
+                  ymin = 0.0_dp, ymax = 0.0_dp,                                   &
+                  x0=x0, y0=y0, z0 = z0,                                          &
+                  nx = nx, ny = 0, nz = nz, z=z)
+
+          CALL init_grid_definition('boundary', grid=v_top_grid,                  &
+                  xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx,                    &
+                  ymin = dy, ymax = ly - dy,                                      &
+                  x0=x0, y0=y0, z0 = z0,                                          &
+                  nx = nx, ny = ny-1, nz = 1, z=(/z_top/))
+
+          CALL init_grid_definition('boundary', grid=w_east_grid,                 &
+                  xmin = lx + 0.5_dp * dx, xmax = lx + 0.5_dp * dx,               &
+                  ymin =  0.5_dp * dy, ymax = ly - 0.5_dp * dy,                   &
+                  x0=x0, y0=y0, z0 = z0,                                          &
+                  nx = 0, ny = ny, nz = nz - 1, z=zw)
+
+          CALL init_grid_definition('boundary', grid=w_west_grid,                 &
+                  xmin = -0.5_dp * dx, xmax = -0.5_dp * dx,                       &
+                  ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy,                    &
+                  x0=x0, y0=y0, z0 = z0,                                          &
+                  nx = 0, ny = ny, nz = nz - 1, z=zw)
+
+          CALL init_grid_definition('boundary', grid=w_north_grid,                &
+                  xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx,                    &
+                  ymin = ly + 0.5_dp * dy, ymax = ly + 0.5_dp * dy,               &
+                  x0=x0, y0=y0, z0 = z0,                                          &
+                  nx = nx, ny = 0, nz = nz - 1, z=zw)
+
+          CALL init_grid_definition('boundary', grid=w_south_grid,                &
+                  xmin =  0.5_dp * dx, xmax = lx - 0.5_dp * dx,                   &
+                  ymin = -0.5_dp * dy, ymax = -0.5_dp * dy,                       &
+                  x0=x0, y0=y0, z0 = z0,                                          &
+                  nx = nx, ny = 0, nz = nz - 1, z=zw)
+
+          CALL init_grid_definition('boundary', grid=w_top_grid,                  &
+                  xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx,                    &
+                  ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy,                    &
+                  x0=x0, y0=y0, z0 = z0,                                          &
+                  nx = nx, ny = ny, nz = 1, z=(/zw_top/))
+
+          CALL init_grid_definition('boundary intermediate', grid=scalars_east_intermediate,   &
+                  xmin = lx + 0.5_dp * dx, xmax = lx + 0.5_dp * dx,               &
+                  ymin =  0.5_dp * dy, ymax = ly - 0.5_dp * dy,                   &
+                  x0=x0, y0=y0, z0 = z0,                                          &
+                  nx = 0, ny = ny, nz = nlev - 2)
+
+          CALL init_grid_definition('boundary intermediate', grid=scalars_west_intermediate,   &
+                  xmin = -0.5_dp * dx, xmax = -0.5_dp * dx,                       &
+                  ymin =  0.5_dp * dy, ymax = ly - 0.5_dp * dy,                   &
+                  x0=x0, y0=y0, z0 = z0,                                          &
+                  nx = 0, ny = ny, nz = nlev - 2)
+
+          CALL init_grid_definition('boundary intermediate', grid=scalars_north_intermediate,  &
+                  xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx,                    &
+                  ymin = ly + 0.5_dp * dy, ymax = ly + 0.5_dp * dy,               &
+                  x0=x0, y0=y0, z0 = z0,                                          &
+                  nx = nx, ny = 0, nz = nlev - 2)
+
+          CALL init_grid_definition('boundary intermediate', grid=scalars_south_intermediate,  &
+                  xmin =  0.5_dp * dx, xmax = lx - 0.5_dp * dx,                   &
+                  ymin = -0.5_dp * dy, ymax = -0.5_dp * dy,                       &
+                  x0=x0, y0=y0, z0 = z0,                                          &
+                  nx = nx, ny = 0, nz = nlev - 2)
+
+          CALL init_grid_definition('boundary intermediate', grid=scalars_top_intermediate,    &
+                  xmin =  0.5_dp * dx, xmax = lx - 0.5_dp * dx,                   &
+                  ymin =  0.5_dp * dy, ymax = ly - 0.5_dp * dy,                   &
+                  x0=x0, y0=y0, z0 = z0,                                          &
+                  nx = nx, ny = ny, nz = nlev - 2)
+
+          CALL init_grid_definition('boundary intermediate', grid=u_east_intermediate,         &
+                  xmin = lx, xmax = lx,                                           &
+                  ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy,                    &
+                  x0=x0, y0=y0, z0 = z0,                                          &
+                  nx = 0, ny = ny, nz = nlev - 2)
+
+          CALL init_grid_definition('boundary intermediate', grid=u_west_intermediate,         &
+                  xmin = 0.0_dp, xmax = 0.0_dp,                                   &
+                  ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy,                    &
+                  x0=x0, y0=y0, z0 = z0,                                          &
+                  nx = 0, ny = ny, nz = nlev - 2)
+
+          CALL init_grid_definition('boundary intermediate', grid=u_north_intermediate,        &
+                  xmin = dx, xmax = lx - dx,                                      &
+                  ymin = ly + 0.5_dp * dy, ymax = ly + 0.5_dp * dy,               &
+                  x0=x0, y0=y0, z0 = z0,                                          &
+                  nx = nx-1, ny = 0, nz = nlev - 2)
+
+          CALL init_grid_definition('boundary intermediate', grid=u_south_intermediate,        &
+                  xmin = dx, xmax = lx - dx,                                      &
+                  ymin = -0.5_dp * dy, ymax = -0.5_dp * dy,                       &
+                  x0=x0, y0=y0, z0 = z0,                                          &
+                  nx = nx-1, ny = 0, nz = nlev - 2)
+
+          CALL init_grid_definition('boundary intermediate', grid=u_top_intermediate,          &
+                  xmin = dx, xmax = lx - dx,                                      &
+                  ymin = 0.5_dp * dy, ymax = ly - 0.5_dp * dy,                    &
+                  x0=x0, y0=y0, z0 = z0,                                          &
+                  nx = nx-1, ny = ny, nz = nlev - 2)
+
+          CALL init_grid_definition('boundary intermediate', grid=v_east_intermediate,         &
+                  xmin = lx + 0.5_dp * dx, xmax = lx + 0.5_dp * dx,               &
+                  ymin = dy, ymax = ly - dy,                                      &
+                  x0=x0, y0=y0, z0 = z0,                                          &
+                  nx = 0, ny = ny-1, nz = nlev - 2)
+
+          CALL init_grid_definition('boundary intermediate', grid=v_west_intermediate,         &
+                  xmin = -0.5_dp * dx, xmax = -0.5_dp * dx,                       &
+                  ymin = dy, ymax = ly - dy,                                      &
+                  x0=x0, y0=y0, z0 = z0,                                          &
+                  nx = 0, ny = ny-1, nz = nlev - 2)
+
+          CALL init_grid_definition('boundary intermediate', grid=v_north_intermediate,        &
+                  xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx,                    &
+                  ymin = ly, ymax = ly,                                           &
+                  x0=x0, y0=y0, z0 = z0,                                          &
+                  nx = nx, ny = 0, nz = nlev - 2)
+
+          CALL init_grid_definition('boundary intermediate', grid=v_south_intermediate,        &
+                  xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx,                    &
+                  ymin = 0.0_dp, ymax = 0.0_dp,                                   &
+                  x0=x0, y0=y0, z0 = z0,                                          &
+                  nx = nx, ny = 0, nz = nlev - 2)
+
+          CALL init_grid_definition('boundary intermediate', grid=v_top_intermediate,          &
+                  xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx,                    &
+                  ymin = dy, ymax = ly - dy,                                      &
+                  x0=x0, y0=y0, z0 = z0,                                          &
+                  nx = nx, ny = ny-1, nz = nlev - 2)
+
+          CALL init_grid_definition('boundary intermediate', grid=w_east_intermediate,         &
+                  xmin = lx + 0.5_dp * dx, xmax = lx + 0.5_dp * dx,               &
+                  ymin =  0.5_dp * dy, ymax = ly - 0.5_dp * dy,                   &
+                  x0=x0, y0=y0, z0 = z0,                                          &
+                  nx = 0, ny = ny, nz = nlev - 1)
+
+          CALL init_grid_definition('boundary intermediate', grid=w_west_intermediate,         &
+                  xmin = -0.5_dp * dx, xmax = -0.5_dp * dx,                       &
+                  ymin =  0.5_dp * dy, ymax = ly - 0.5_dp * dy,                   &
+                  x0=x0, y0=y0, z0 = z0,                                          &
+                  nx = 0, ny = ny, nz = nlev - 1)
+
+          CALL init_grid_definition('boundary intermediate', grid=w_north_intermediate,        &
+                  xmin = 0.5_dp * dx, xmax = lx - 0.5_dp * dx,                    &
+                  ymin = ly + 0.5_dp * dy, ymax = ly + 0.5_dp * dy,               &
+                  x0=x0, y0=y0, z0 = z0,                                          &
+                  nx = nx, ny = 0, nz = nlev - 1)
+
+          CALL init_grid_definition('boundary intermediate', grid=w_south_intermediate,        &
+                  xmin =  0.5_dp * dx, xmax = lx - 0.5_dp * dx,                   &
+                  ymin = -0.5_dp * dy, ymax = -0.5_dp * dy,                       &
+                  x0=x0, y0=y0, z0 = z0,                                          &
+                  nx = nx, ny = 0, nz = nlev - 1)
+
+          CALL init_grid_definition('boundary intermediate', grid=w_top_intermediate,          &
+                  xmin =  0.5_dp * dx, xmax = lx - 0.5_dp * dx,                   &
+                  ymin =  0.5_dp * dy, ymax = ly - 0.5_dp * dy,                   &
+                  x0=x0, y0=y0, z0 = z0,                                          &
+                  nx = nx, ny = ny, nz = nlev - 1)
+       END IF
+
+!                                                                              
+!------------------------------------------------------------------------------
+! Section 3: Define profile grids
+!------------------------------------------------------------------------------
+
+       CALL init_averaging_grid(averaged_scalar_profile, cosmo_grid,           &
+               x = 0.5_dp * lx, y = 0.5_dp * ly, z = z, z0 = z0,               &
+               lonmin = lam_west, lonmax = lam_east,                           &
+               latmin = phi_south, latmax = phi_north,                         &
+               kind='scalar')
+
+       CALL init_averaging_grid(averaged_w_profile, cosmo_grid,                &
+               x = 0.5_dp * lx, y = 0.5_dp * ly, z = zw, z0 = z0,              &
+               lonmin = lam_west, lonmax = lam_east,                           &
+               latmin = phi_south, latmax = phi_north,                         &
+               kind='w')
+
+       CALL init_averaging_grid(south_averaged_scalar_profile, cosmo_grid,     &
+               x = 0.5_dp * lx, y = 0.5_dp * ly, z = z, z0 = z0,               &
+               lonmin = lam_west, lonmax = lam_east,                           &
+               latmin = phi_centre - averaging_angle,                          &
+               latmax = phi_centre,                                            &
+               kind='scalar')
+
+       CALL init_averaging_grid(north_averaged_scalar_profile, cosmo_grid,     &
+               x = 0.5_dp * lx, y = 0.5_dp * ly, z = z, z0 = z0,               &
+               lonmin = lam_west, lonmax = lam_east,                           &
+               latmin = phi_centre,                                            &
+               latmax = phi_centre + averaging_angle,                          &
+               kind='scalar')
+
+       CALL init_averaging_grid(west_averaged_scalar_profile, cosmo_grid,      &
+               x = 0.5_dp * lx, y = 0.5_dp * ly, z = z, z0 = z0,               &
+               lonmin = lam_centre - averaging_angle,                          &
+               lonmax = lam_centre,                                            &
+               latmin = phi_south, latmax = phi_north,                         &
+               kind='scalar')
+
+       CALL init_averaging_grid(east_averaged_scalar_profile, cosmo_grid,      &
+               x = 0.5_dp * lx, y = 0.5_dp * ly, z = z, z0 = z0,               &
+               lonmin = lam_centre,                                            &
+               lonmax = lam_centre + averaging_angle,                          &
+               latmin = phi_south, latmax = phi_north,                         &
+               kind='scalar')
+
+       profile_grids_required = ( TRIM(cfg % ic_mode) == 'profile' .OR.        &
+                                  TRIM(cfg % bc_mode) == 'ideal' )
+
+       !IF (profile_grids_required)  THEN
+       !   ! Here, I use the 'boundary' kind, so the vertical coordinate uses the
+       !   ! PALM z coordinate.
+       !   CALL init_grid_definition('boundary', grid=scalar_profile_grid,      &
+       !           xmin = 0.5_dp * lx, xmax = 0.5_dp * lx,                      &
+       !           ymin = 0.5_dp * ly, ymax = 0.5_dp * ly,                      &
+       !           x0=x0, y0=y0, z0 = z0,                                       &
+       !           nx = 0, ny = 0, nz = nz, z=z)
+
+       !   CALL init_grid_definition('boundary', grid=w_profile_grid,           &
+       !           xmin = 0.5_dp * lx, xmax = 0.5_dp * lx,                      &
+       !           ymin = 0.5_dp * ly, ymax = 0.5_dp * ly,                      &
+       !           x0=x0, y0=y0, z0 = z0,                                       &
+       !           nx = 0, ny = 0, nz = nz - 1, z=zw)
+
+       !   CALL init_grid_definition('boundary', grid=scalar_profile_intermediate,&
+       !           xmin = 0.5_dp * lx, xmax = 0.5_dp * lx,                      &
+       !           ymin = 0.5_dp * ly, ymax = 0.5_dp * ly,                      &
+       !           x0=x0, y0=y0, z0 = z0,                                       &
+       !           nx = 0, ny = 0, nz = nlev - 2, z=z)
+
+       !   CALL init_grid_definition('boundary', grid=w_profile_intermediate,   &
+       !           xmin = 0.5_dp * lx, xmax = 0.5_dp * lx,                      &
+       !           ymin = 0.5_dp * ly, ymax = 0.5_dp * ly,                      &
+       !           x0=x0, y0=y0, z0 = z0,                                       &
+       !           nx = 0, ny = 0, nz = nlev - 2, z=zw)
+       !END IF
+
+!                                                                              
+!------------------------------------------------------------------------------
+! Section 4: Precompute neighbours and weights for interpolation              
+!------------------------------------------------------------------------------
+       interp_mode = 's'
+       CALL setup_interpolation(cosmo_grid, palm_grid, palm_intermediate, interp_mode, ic_mode=cfg % ic_mode)
+       IF (boundary_variables_required)  THEN
+          CALL setup_interpolation(cosmo_grid, scalars_east_grid, scalars_east_intermediate, interp_mode)
+          CALL setup_interpolation(cosmo_grid, scalars_west_grid, scalars_west_intermediate, interp_mode)
+          CALL setup_interpolation(cosmo_grid, scalars_north_grid, scalars_north_intermediate, interp_mode)
+          CALL setup_interpolation(cosmo_grid, scalars_south_grid, scalars_south_intermediate, interp_mode)
+          CALL setup_interpolation(cosmo_grid, scalars_top_grid, scalars_top_intermediate, interp_mode)
+       END IF
+
+       interp_mode = 'u'
+       CALL setup_interpolation(cosmo_grid, u_initial_grid, u_initial_intermediate, interp_mode, ic_mode=cfg % ic_mode)
+       IF (boundary_variables_required)  THEN
+          CALL setup_interpolation(cosmo_grid, u_east_grid, u_east_intermediate, interp_mode)
+          CALL setup_interpolation(cosmo_grid, u_west_grid, u_west_intermediate, interp_mode)
+          CALL setup_interpolation(cosmo_grid, u_north_grid, u_north_intermediate, interp_mode)
+          CALL setup_interpolation(cosmo_grid, u_south_grid, u_south_intermediate, interp_mode)
+          CALL setup_interpolation(cosmo_grid, u_top_grid, u_top_intermediate, interp_mode)
+       END IF
+
+       interp_mode = 'v'
+       CALL setup_interpolation(cosmo_grid, v_initial_grid, v_initial_intermediate, interp_mode, ic_mode=cfg % ic_mode)
+       IF (boundary_variables_required)  THEN
+          CALL setup_interpolation(cosmo_grid, v_east_grid, v_east_intermediate, interp_mode)
+          CALL setup_interpolation(cosmo_grid, v_west_grid, v_west_intermediate, interp_mode)
+          CALL setup_interpolation(cosmo_grid, v_north_grid, v_north_intermediate, interp_mode)
+          CALL setup_interpolation(cosmo_grid, v_south_grid, v_south_intermediate, interp_mode)
+          CALL setup_interpolation(cosmo_grid, v_top_grid, v_top_intermediate, interp_mode)
+       END IF
+
+       interp_mode = 'w'
+       CALL setup_interpolation(cosmo_grid, w_initial_grid, w_initial_intermediate, interp_mode, ic_mode=cfg % ic_mode)
+       IF (boundary_variables_required)  THEN
+          CALL setup_interpolation(cosmo_grid, w_east_grid, w_east_intermediate, interp_mode)
+          CALL setup_interpolation(cosmo_grid, w_west_grid, w_west_intermediate, interp_mode)
+          CALL setup_interpolation(cosmo_grid, w_north_grid, w_north_intermediate, interp_mode)
+          CALL setup_interpolation(cosmo_grid, w_south_grid, w_south_intermediate, interp_mode)
+          CALL setup_interpolation(cosmo_grid, w_top_grid, w_top_intermediate, interp_mode)
+       END IF
+
+       IF (TRIM(cfg % ic_mode) == 'profile')  THEN
+           !TODO: remove this conditional if not needed. 
+       END IF
+        
+
+    END SUBROUTINE setup_grids
+
+
+    SUBROUTINE setup_interpolation(cosmo_grid, grid, intermediate_grid, kind, ic_mode)
+
+       TYPE(grid_definition), INTENT(IN), TARGET    ::  cosmo_grid
+       TYPE(grid_definition), INTENT(INOUT), TARGET ::  grid, intermediate_grid
+       CHARACTER, INTENT(IN)                        ::  kind
+       CHARACTER(LEN=*), INTENT(IN), OPTIONAL       ::  ic_mode
+
+       REAL(dp), DIMENSION(:), POINTER     ::  cosmo_lat, cosmo_lon
+       REAL(dp), DIMENSION(:,:,:), POINTER ::  cosmo_h
+
+       LOGICAL :: setup_volumetric
+
+!------------------------------------------------------------------------------
+! Section 1: Horizontal interpolation                                        
+!------------------------------------------------------------------------------
+       ! Select horizontal coordinates according to kind of points (s/w, u, v)
+       SELECT CASE(kind)
+
+       CASE('s') ! scalars
+
+          cosmo_lat => cosmo_grid % lat
+          cosmo_lon => cosmo_grid % lon
+          cosmo_h   => cosmo_grid % hfl
+
+       CASE('w') ! vertical velocity
+
+          cosmo_lat => cosmo_grid % lat
+          cosmo_lon => cosmo_grid % lon
+          cosmo_h   => cosmo_grid % hhl
+
+       CASE('u') ! x velocity
+
+          cosmo_lat => cosmo_grid % lat
+          cosmo_lon => cosmo_grid % lonu
+          cosmo_h   => cosmo_grid % hfl
+
+       CASE('v') ! y velocity
+
+          cosmo_lat => cosmo_grid % latv
+          cosmo_lon => cosmo_grid % lon
+          cosmo_h   => cosmo_grid % hfl
+
+       CASE DEFAULT
+
+          message = "Interpolation quantity '" // kind // "' is not supported."
+          CALL abort('setup_interpolation', message)
+
+       END SELECT
+
+       CALL find_horizontal_neighbours(cosmo_lat, cosmo_lon,                   &
+          intermediate_grid % clat, intermediate_grid % clon,                  &
+          intermediate_grid % ii, intermediate_grid % jj)
+
+       CALL compute_horizontal_interp_weights(cosmo_lat, cosmo_lon,            &
+          intermediate_grid % clat, intermediate_grid % clon,                  &
+          intermediate_grid % ii, intermediate_grid % jj,                      &
+          intermediate_grid % w_horiz)
+
+!------------------------------------------------------------------------------
+! Section 2: Vertical interpolation
+!------------------------------------------------------------------------------
+
+       ! If profile initialization is chosen, we--somewhat counterintuitively--
+       ! don't need to compute vertical interpolation weights. At least, we
+       ! don't need them on the intermediate grid, which fills the entire PALM
+       ! domain volume. Instead we need vertical weights for the intermediate
+       ! profile grids, which get computed in setup_averaging().
+       setup_volumetric = .TRUE.
+       IF (PRESENT(ic_mode))  THEN
+          IF (TRIM(ic_mode) == 'profile')  setup_volumetric = .FALSE.
+       END IF
+
+       IF (setup_volumetric)  THEN
+          ALLOCATE( intermediate_grid % h(0:intermediate_grid % nx,            &
+                                          0:intermediate_grid % ny,            &
+                                          0:intermediate_grid % nz) ) 
+          intermediate_grid % h(:,:,:) = - EARTH_RADIUS
+
+          ! For w points, use hhl, for scalars use hfl
+          ! compute the full heights for the intermediate grids
+          CALL interpolate_2d(cosmo_h, intermediate_grid % h, intermediate_grid)
+          CALL find_vertical_neighbours_and_weights_interp(grid, intermediate_grid)
+       END IF
+       
+    END SUBROUTINE setup_interpolation
+
+!------------------------------------------------------------------------------!
+! Description:
+! ------------
+!> Initializes grid_definition-type variables.
+!> 
+!> Input parameters:
+!> -----------------
+!> kind : Grid kind, distinguishes between PALM-4U and COSMO-DE grids
+!>    as well as grids covering the boundary surfaces. Valid kinds are:
+!>       - 'palm'
+!>       - 'cosmo-de'
+!>       - 'eastwest-scalar'
+!> 
+!> <xyx>min, <xyz>max : Domain minima and maxima in x, y, and z direction. Note
+!>    that these values do not necessarily translate to the outmost coordinates
+!>    of the generated grid but rather refer to the extent of the underlying
+!>    PALM-4U computational domain (i.e. the outer cell faces). The coordinates
+!>    of the generated grid will be inferred from this information taking into
+!>    account the initialization mode ic_mode. For example, the coordinates of a
+!>    boundary grid initialized using mode 'eastwest-scalar' will be located in
+!>    planes one half grid point outwards of xmin and xmax.
+!>
+!> z0 : Elevation of the PALM-4U domain above sea level [m]
+!>
+!> n<xyz> : Number of grod points in x, y, and z direction
+!>
+!> Output parameters:
+!> ------------------
+!> grid : Grid variable to be initialized.
+!------------------------------------------------------------------------------!
+    SUBROUTINE init_grid_definition(kind, xmin, xmax, ymin, ymax,              &
+                                    x0, y0, z0, nx, ny, nz, z, zw, grid, ic_mode)
+        CHARACTER(LEN=*), INTENT(IN)           ::  kind
+        CHARACTER(LEN=*), INTENT(IN), OPTIONAL ::  ic_mode
+        INTEGER, INTENT(IN)                    ::  nx, ny, nz
+        REAL(dp), INTENT(IN)                   ::  xmin, xmax, ymin, ymax
+        REAL(dp), INTENT(IN)                   ::  x0, y0, z0
+        REAL(dp), INTENT(IN), TARGET, OPTIONAL ::  z(:)
+        REAL(dp), INTENT(IN), TARGET, OPTIONAL ::  zw(:)
+        TYPE(grid_definition), INTENT(INOUT)   ::  grid
+
+        grid % nx = nx
+        grid % ny = ny
+        grid % nz = nz
+
+        grid % lx = xmax - xmin
+        grid % ly = ymax - ymin
+
+        grid % x0 = x0
+        grid % y0 = y0
+        grid % z0 = z0
+
+        SELECT CASE( TRIM (kind) )
+
+        CASE('boundary')
+
+           IF (.NOT.PRESENT(z))  THEN
+              message = "z has not been passed but is required for 'boundary' grids"
+              CALL abort('init_grid_definition', message)
+           END IF
+
+           ALLOCATE( grid % x(0:nx) )
+           CALL linspace(xmin, xmax, grid % x)
+
+           ALLOCATE( grid % y(0:ny) )
+           CALL linspace(ymin, ymax, grid % y)
+
+           grid % z => z
+
+           ! Allocate neighbour indices and weights
+           IF (TRIM(ic_mode) .NE. 'profile')  THEN
+              ALLOCATE( grid % kk(0:nx, 0:ny, 1:nz, 2) )
+              grid % kk(:,:,:,:) = -1
+
+              ALLOCATE( grid % w_verti(0:nx, 0:ny, 1:nz, 2) )
+              grid % w_verti(:,:,:,:) = 0.0_dp
+           END IF
+        
+        CASE('boundary intermediate')
+
+           ALLOCATE( grid % x(0:nx) )
+           CALL linspace(xmin, xmax, grid % x)
+
+           ALLOCATE( grid % y(0:ny) )
+           CALL linspace(ymin, ymax, grid % y)
+
+           ALLOCATE( grid % clon(0:nx, 0:ny), grid % clat(0:nx, 0:ny)  )
+
+           CALL rotate_to_cosmo(                                               &
+              phir = project( grid % y, y0, EARTH_RADIUS ) ,                   & ! = plate-carree latitude
+              lamr = project( grid % x, x0, EARTH_RADIUS ) ,                   & ! = plate-carree longitude
+              phip = phi_cn, lamp = lambda_cn,                                 &
+              phi  = grid % clat,                                              &
+              lam  = grid % clon,                                              &
+              gam  = gam                                                       &
+           )
+
+           ! Allocate neighbour indices and weights
+           ALLOCATE( grid % ii(0:nx, 0:ny, 4),                                 &
+                     grid % jj(0:nx, 0:ny, 4) )
+           grid % ii(:,:,:)   = -1
+           grid % jj(:,:,:)   = -1
+
+           ALLOCATE( grid % w_horiz(0:nx, 0:ny, 4) )
+           grid % w_horiz(:,:,:)   = 0.0_dp
+        
+        ! This mode initializes a Cartesian PALM-4U grid and adds the
+        ! corresponding latitudes and longitudes of the rotated pole grid.
+        CASE('palm')
+
+           IF (.NOT.PRESENT(z))  THEN
+              message = "z has not been passed but is required for 'palm' grids"
+              CALL abort('init_grid_definition', message)
+           END IF
+
+           IF (.NOT.PRESENT(zw))  THEN
+              message = "zw has not been passed but is required for 'palm' grids"
+              CALL abort('init_grid_definition', message)
+           END IF
+
+           grid % name(1) = 'x and lon'
+           grid % name(2) = 'y and lat'
+           grid % name(3) = 'z'
+
+           !TODO: Remove use of global dx, dy, dz variables. Consider
+           !TODO:   associating global x,y, and z arrays.
+           ALLOCATE( grid % x(0:nx),   grid % y(0:ny) )
+           ALLOCATE( grid % xu(1:nx),  grid % yv(1:ny) )
+           CALL linspace(xmin + 0.5_dp* dx, xmax - 0.5_dp* dx, grid % x)
+           CALL linspace(ymin + 0.5_dp* dy, ymax - 0.5_dp* dy, grid % y)
+           grid % z => z
+           CALL linspace(xmin +  dx, xmax -  dx, grid % xu)
+           CALL linspace(ymin +  dy, ymax -  dy, grid % yv)
+           grid % zw => zw
+
+           grid % depths => depths
+
+           ! Allocate neighbour indices and weights
+           IF (TRIM(ic_mode) .NE. 'profile')  THEN
+              ALLOCATE( grid % kk(0:nx, 0:ny, 1:nz, 2) )
+              grid % kk(:,:,:,:) = -1
+
+              ALLOCATE( grid % w_verti(0:nx, 0:ny, 1:nz, 2) )
+              grid % w_verti(:,:,:,:) = 0.0_dp
+           END IF
+
+        CASE('palm intermediate')
+
+           grid % name(1) = 'x and lon'
+           grid % name(2) = 'y and lat'
+           grid % name(3) = 'interpolated hhl or hfl'
+
+           !TODO: Remove use of global dx, dy, dz variables. Consider
+           !TODO:   associating global x,y, and z arrays.
+           ALLOCATE( grid % x(0:nx),   grid % y(0:ny) )
+           ALLOCATE( grid % xu(1:nx),  grid % yv(1:ny) )
+           CALL linspace(xmin + 0.5_dp*dx, xmax - 0.5_dp*dx, grid % x)
+           CALL linspace(ymin + 0.5_dp*dy, ymax - 0.5_dp*dy, grid % y)
+           CALL linspace(xmin + dx, xmax - dx, grid % xu)
+           CALL linspace(ymin + dy, ymax - dy, grid % yv)
+
+           grid % depths => depths
+
+           ! Allocate rotated-pole coordinates, clon is for (c)osmo-de (lon)gitude
+           ALLOCATE( grid % clon(0:nx, 0:ny),   grid % clat(0:nx, 0:ny)  )
+           ALLOCATE( grid % clonu(1:nx, 0:ny),  grid % clatu(1:nx, 0:ny) )
+           ALLOCATE( grid % clonv(0:nx, 1:ny),  grid % clatv(0:nx, 1:ny) )
+
+           ! Compute rotated-pole coordinates of...
+           ! ... PALM-4U centres
+           CALL rotate_to_cosmo(                                               &
+              phir = project( grid % y, y0, EARTH_RADIUS ) , & ! = plate-carree latitude
+              lamr = project( grid % x, x0, EARTH_RADIUS ) , & ! = plate-carree longitude
+              phip = phi_cn, lamp = lambda_cn,                                 &
+              phi  = grid % clat,                                              &
+              lam  = grid % clon,                                              &
+              gam  = gam                                                       &
+           )
+
+           ! ... PALM-4U u winds
+           CALL rotate_to_cosmo(                                               &
+              phir = project( grid % y,  y0, EARTH_RADIUS ), & ! = plate-carree latitude
+              lamr = project( grid % xu, x0, EARTH_RADIUS ), & ! = plate-carree longitude
+              phip = phi_cn, lamp = lambda_cn,                                 &
+              phi  = grid % clatu,                                             &
+              lam  = grid % clonu,                                             &
+              gam  = gam                                                       &
+           )
+
+           ! ... PALM-4U v winds
+           CALL rotate_to_cosmo(                                               &
+              phir = project( grid % yv, y0, EARTH_RADIUS ), & ! = plate-carree latitude
+              lamr = project( grid % x,  x0, EARTH_RADIUS ), & ! = plate-carree longitude
+              phip = phi_cn, lamp = lambda_cn,                                 &
+              phi  = grid % clatv,                                             &
+              lam  = grid % clonv,                                             &
+              gam  = gam                                                       &
+           )
+
+           ! Allocate neighbour indices and weights
+           ALLOCATE( grid % ii(0:nx, 0:ny, 4),                                 &
+                     grid % jj(0:nx, 0:ny, 4) )
+           grid % ii(:,:,:)   = -1
+           grid % jj(:,:,:)   = -1
+
+           ALLOCATE( grid % w_horiz(0:nx, 0:ny, 4) )
+           grid % w_horiz(:,:,:)   = 0.0_dp
+
+        CASE('cosmo-de')
+           grid % name(1) = 'rlon'         ! of COMSO-DE cell centres (scalars)
+           grid % name(2) = 'rlat'         ! of COMSO-DE cell centres (scalars)
+           grid % name(3) = 'height'
+
+           ALLOCATE( grid % lon(0:nx),   grid % lat(0:ny)  )
+           ALLOCATE( grid % lonu(0:nx),  grid % latv(0:ny) )
+
+           CALL linspace(xmin, xmax, grid % lon)
+           CALL linspace(ymin, ymax, grid % lat)
+           grid % lonu(:) = grid % lon + 0.5_dp * (grid % lx / grid % nx)
+           grid % latv(:) = grid % lat + 0.5_dp * (grid % ly / grid % ny)
+
+           ! Point to heights of half levels (hhl) and compute heights of full
+           ! levels (hfl) as arithmetic averages
+           grid % hhl => hhl
+           grid % hfl => hfl
+           grid % depths => depths
+
+        CASE DEFAULT
+            message = "Grid kind '" // TRIM(kind) // "' is not recognized."
+            CALL abort('init_grid_definition', message)
+
+        END SELECT
+
+    END SUBROUTINE init_grid_definition
+
+
+!------------------------------------------------------------------------------!
+! Description:
+! ------------
+!> Initializes averagin_grid-type variables.
+!> 
+!> Input parameters:
+!> -----------------
+!>
+!> cosmo_grid : grid_definition-type varieble initialized as 'cosmo-de' grid
+!>    providing longitudes and latitudes of the parent grid
+!>
+!> x, y : location of the profile to be averaged in the PALM system [m]
+!>
+!> z : vertical grid coordinates of the profile in the PALM system [m]
+!>
+!> <lat/lon><min/max>: boundaries of the averaging region in the parent system,
+!>    i.e. the COSMO-DE rotated-pole system. [rad]
+!>
+!> kind : kind of quantity to be averaged using this averaging grid.
+!>    Destinguishes COSMO-DE scalar and w-velocity levels. Note that finding the
+!>    parent/COSMO columns for the region in get_cosmo_averaging_region() is
+!>    independent of 'kind' b/ecause INIFOR uses column-centred u and v velocity
+!>    components, which are computed in the preprocessing step.
+!>
+!> Output parameters:
+!> ------------------
+!> avg_grid : averaging_grid variable to be initialized.
+!------------------------------------------------------------------------------!
+    SUBROUTINE init_averaging_grid(avg_grid, cosmo_grid, x, y, z, z0,          &
+       lonmin, lonmax, latmin, latmax, kind)
+
+       TYPE(grid_definition), INTENT(INOUT) ::  avg_grid
+       TYPE(grid_definition), INTENT(IN)    ::  cosmo_grid
+       REAL(dp), INTENT(IN)                 ::  x, y, z0
+       REAL(dp), INTENT(IN), TARGET         ::  z(:)
+       REAL(dp), INTENT(IN)                 ::  lonmin, lonmax, latmin, latmax
+
+       CHARACTER(LEN=*), INTENT(IN)         ::  kind
+
+       LOGICAL                              :: level_based_averaging
+
+       INTEGER :: i, j
+
+       ALLOCATE( avg_grid % x(1) )
+       ALLOCATE( avg_grid % y(1) )
+       avg_grid % x(1) = x
+       avg_grid % y(1) = y
+       avg_grid % z => z
+       avg_grid % z0 = z0
+
+       avg_grid % nz = SIZE(z, 1)
+
+       ALLOCATE( avg_grid % lon(2) )
+       ALLOCATE( avg_grid % lat(2) )
+       avg_grid % lon(1:2) = (/lonmin, lonmax/)
+       avg_grid % lat(1:2) = (/latmin, latmax/)
+
+       avg_grid % kind = TRIM(kind)
+
+       ! Find and store COSMO columns that fall into the coordinate range
+       ! given by avg_grid % clon, % clat
+       CALL get_cosmo_averaging_region(avg_grid, cosmo_grid)
+
+       ALLOCATE (avg_grid % kkk(avg_grid % n_columns, avg_grid % nz, 2) )
+       ALLOCATE (avg_grid % w(avg_grid % n_columns, avg_grid % nz, 2) )
+       ! Compute average COSMO levels in the averaging region
+       SELECT CASE(avg_grid % kind)
+
+       CASE('scalar', 'u', 'v')
+          avg_grid % cosmo_h => cosmo_grid % hfl
+
+       CASE('w')
+          avg_grid % cosmo_h => cosmo_grid % hhl
+
+       CASE DEFAULT
+          message = "Averaging grid kind '" // TRIM(avg_grid % kind) // &
+                    "' is not supported. Use 'scalar', 'u', or 'v'."
+          CALL abort('get_cosmo_averaging_region', message)
+
+       END SELECT
+
+       ! For level-besed averaging, compute average heights
+       level_based_averaging = .TRUE.
+       IF (level_based_averaging)  THEN
+          ALLOCATE(avg_grid % h(1,1,SIZE(avg_grid % cosmo_h, 3)) )
+ 
+          CALL average_2d(avg_grid % cosmo_h, avg_grid % h(1,1,:),                            &
+                          avg_grid % iii, avg_grid % jjj)
+       END IF
+
+       ! Copy averaged grid to all COSMO columnts, leads to computing the same
+       ! vertical interpolation weights for all columns and to COSMO grid level
+       ! based averaging onto the averaged COSMO heights.
+       IF ( TRIM(cfg % averaging_mode) == 'level' )  THEN
+          FORALL(                                                              &
+             i=1:SIZE(avg_grid % cosmo_h, 1),                                  &
+             j=1:SIZE(avg_grid % cosmo_h, 2)                                   &
+          )   avg_grid % cosmo_h(i,j,:) = avg_grid % h(1,1,:)
+       END IF
+
+       ! Compute vertical weights and neighbours
+       CALL find_vertical_neighbours_and_weights_average(avg_grid)
+
+    END SUBROUTINE init_averaging_grid
+
+
+    SUBROUTINE get_cosmo_averaging_region(avg_grid, cosmo_grid)
+       TYPE(grid_definition), INTENT(INOUT)         ::  avg_grid
+       TYPE(grid_definition), TARGET, INTENT(IN)    ::  cosmo_grid
+
+       REAL(dp), DIMENSION(:), POINTER              ::  cosmo_lon, cosmo_lat
+       REAL(dp)                                     ::  dlon, dlat
+
+       INTEGER ::  i, j, imin, imax, jmin, jmax, l, nx, ny
+
+
+       SELECT CASE( TRIM(avg_grid % kind) )
+
+       CASE('scalar', 'w')
+          cosmo_lon => cosmo_grid % lon
+          cosmo_lat => cosmo_grid % lat
+
+       CASE('u')
+          cosmo_lon => cosmo_grid % lonu
+          cosmo_lat => cosmo_grid % lat
+
+       CASE('v')
+          cosmo_lon => cosmo_grid % lon
+          cosmo_lat => cosmo_grid % latv
+
+       CASE DEFAULT
+          message = "Averaging grid kind '" // TRIM(avg_grid % kind) // &
+                    "' is not supported. Use 'scalar', 'u', or 'v'."
+          CALL abort('get_cosmo_averaging_region', message)
+
+       END SELECT
+
+
+       ! FIXME: make dlon, dlat parameters of the grid_defintion type
+       dlon = cosmo_lon(1) - cosmo_lon(0)
+       dlat = cosmo_lat(1) - cosmo_lat(0)
+
+       imin = CEILING( (avg_grid % lon(1) - cosmo_lon(0)) / dlon )
+       imax = FLOOR(   (avg_grid % lon(2) - cosmo_lon(0)) / dlon )
+
+       jmin = CEILING( (avg_grid % lat(1) - cosmo_lat(0)) / dlat )
+       jmax = FLOOR(   (avg_grid % lat(2) - cosmo_lat(0)) / dlat )
+       
+       message = "Averaging over "//                                           &
+                 TRIM(str(imin)) // " < i < " // TRIM(str(imax)) //            &
+                 " and " //                                                    &
+                 TRIM(str(jmin)) // " < j < " // TRIM(str(jmax))
+       CALL report( 'get_cosmo_averaging_region', message )
+
+       nx = imax - imin + 1
+       ny = jmax - jmin + 1
+       avg_grid % n_columns = nx * ny
+
+       ALLOCATE( avg_grid % iii(avg_grid % n_columns),                                 &
+                 avg_grid % jjj(avg_grid % n_columns) )
+
+       l = 0
+       DO j = jmin, jmax
+       DO i = imin, imax
+          l = l + 1
+          avg_grid % iii(l) = i
+          avg_grid % jjj(l) = j
+       END DO
+       END DO
+
+    END SUBROUTINE get_cosmo_averaging_region
+
+
+!------------------------------------------------------------------------------!
+! Description:
+! ------------
+!> PALM's stretched vertical grid generator. Forked from PALM revision 3139, see
+!> https://palm.muk.uni-hannover.de/trac/browser/palm/trunk/SOURCE/init_grid.f90?rev=3139
+!> 
+!> This routine computes the levels of scalar points. The levels of the velocity
+!> points are then obtained as the midpoints inbetween using the INIFOR routine
+!> 'modpoints'.
+!------------------------------------------------------------------------------!
+    SUBROUTINE stretched_z(z, dz, dz_max, dz_stretch_factor, dz_stretch_level, &
+                           dz_stretch_level_start, dz_stretch_level_end,       &
+                           dz_stretch_factor_array)
+
+       REAL(dp), DIMENSION(:), INTENT(INOUT) ::  z, dz, dz_stretch_factor_array
+       REAL(dp), DIMENSION(:), INTENT(INOUT) ::  dz_stretch_level_start, dz_stretch_level_end
+       REAL(dp), INTENT(IN) ::  dz_max, dz_stretch_factor, dz_stretch_level
+
+       INTEGER ::  number_stretch_level_start        !< number of user-specified start levels for stretching
+       INTEGER ::  number_stretch_level_end          !< number of user-specified end levels for stretching
+
+       REAL(dp), DIMENSION(:), ALLOCATABLE ::  min_dz_stretch_level_end
+       REAL(dp) ::  dz_level_end, dz_stretched
+
+       INTEGER ::  dz_stretch_level_end_index(9)               !< vertical grid level index until which the vertical grid spacing is stretched
+       INTEGER ::  dz_stretch_level_start_index(9)             !< vertical grid level index above which the vertical grid spacing is stretched
+       INTEGER ::  dz_stretch_level_index = 0
+       INTEGER ::  k, n, number_dz
+!
+!-- Compute height of u-levels from constant grid length and dz stretch factors
+       IF ( dz(1) == -1.0_dp )  THEN
+          message = 'missing dz'
+          CALL abort( 'stretched_z', message)
+       ELSEIF ( dz(1) <= 0.0_dp )  THEN
+          WRITE( message, * ) 'dz=', dz(1),' <= 0.0'
+          CALL abort( 'stretched_z', message)
+       ENDIF
+
+!
+!-- Initialize dz_stretch_level_start with the value of dz_stretch_level
+!-- if it was set by the user
+       IF ( dz_stretch_level /= -9999999.9_dp ) THEN
+          dz_stretch_level_start(1) = dz_stretch_level
+       ENDIF
+       
+!
+!-- Determine number of dz values and stretching levels specified by the
+!-- user to allow right controlling of the stretching mechanism and to
+!-- perform error checks. The additional requirement that dz /= dz_max
+!-- for counting number of user-specified dz values is necessary. Otherwise
+!-- restarts would abort if the old stretching mechanism with dz_stretch_level
+!-- is used (Attention: The user is not allowed to specify a dz value equal
+!-- to the default of dz_max = 999.0). 
+       number_dz = COUNT( dz /= -1.0_dp .AND. dz /= dz_max )
+       number_stretch_level_start = COUNT( dz_stretch_level_start /=           &
+                                           -9999999.9_dp )
+       number_stretch_level_end = COUNT( dz_stretch_level_end /=               &
+                                         9999999.9_dp )
+
+!
+!-- The number of specified end levels +1 has to be the same than the number 
+!-- of specified dz values
+       IF ( number_dz /= number_stretch_level_end + 1 ) THEN
+          WRITE( message, * ) 'The number of values for dz = ',                &
+                              number_dz, 'has to be the same than ',           &
+                              'the number of values for ',                     &
+                              'dz_stretch_level_end + 1 = ',                   &
+                              number_stretch_level_end+1
+          CALL abort( 'stretched_z', message)
+       ENDIF
+    
+!
+!--    The number of specified start levels has to be the same or one less than 
+!--    the number of specified dz values
+       IF ( number_dz /= number_stretch_level_start + 1 .AND.                  &
+            number_dz /= number_stretch_level_start ) THEN
+          WRITE( message, * ) 'The number of values for dz = ',         &
+                              number_dz, 'has to be the same or one ', &
+                              'more than& the number of values for ',  &
+                              'dz_stretch_level_start = ',             &
+                              number_stretch_level_start
+          CALL abort( 'stretched_z', message)
+       ENDIF
+    
+!--    The number of specified start levels has to be the same or one more than 
+!--    the number of specified end levels
+       IF ( number_stretch_level_start /= number_stretch_level_end + 1 .AND.   &
+            number_stretch_level_start /= number_stretch_level_end ) THEN
+          WRITE( message, * ) 'The number of values for ',              &
+                              'dz_stretch_level_start = ',              &
+                              dz_stretch_level_start, 'has to be the ',&
+                              'same or one more than& the number of ', &
+                              'values for dz_stretch_level_end = ',    &
+                              number_stretch_level_end
+          CALL abort( 'stretched_z', message)
+       ENDIF
+
+!
+!-- Initialize dz for the free atmosphere with the value of dz_max
+       IF ( dz(number_stretch_level_start+1) == -1.0_dp .AND.                     &
+            number_stretch_level_start /= 0 ) THEN 
+          dz(number_stretch_level_start+1) = dz_max
+       ENDIF
+       
+!
+!-- Initialize the stretching factor if (infinitely) stretching in the free 
+!-- atmosphere is desired (dz_stretch_level_end was not specified for the 
+!-- free atmosphere)
+       IF ( number_stretch_level_start == number_stretch_level_end + 1 ) THEN 
+          dz_stretch_factor_array(number_stretch_level_start) =                   &
+          dz_stretch_factor
+       ENDIF
+
+!-- Allocation of arrays for stretching
+       ALLOCATE( min_dz_stretch_level_end(number_stretch_level_start) )
+
+!
+!--    The stretching region has to be large enough to allow for a smooth
+!--    transition between two different grid spacings
+       DO n = 1, number_stretch_level_start
+          min_dz_stretch_level_end(n) = dz_stretch_level_start(n) +            &
+                                        4 * MAX( dz(n),dz(n+1) )
+       ENDDO
+
+       IF ( ANY( min_dz_stretch_level_end(1:number_stretch_level_start) >      &
+                 dz_stretch_level_end(1:number_stretch_level_start) ) ) THEN
+       !IF ( ANY( min_dz_stretch_level_end >      &
+       !          dz_stretch_level_end ) ) THEN
+             message = 'Each dz_stretch_level_end has to be larger '  // &
+                       'than its corresponding value for ' //            &
+                       'dz_stretch_level_start + 4*MAX(dz(n),dz(n+1)) '//&
+                       'to allow for smooth grid stretching'
+             CALL abort('stretched_z', message)
+       ENDIF
+       
+!
+!--    Stretching must not be applied within the prandtl_layer 
+!--    (first two grid points). For the default case dz_stretch_level_start 
+!--    is negative. Therefore the absolut value is checked here.
+       IF ( ANY( ABS( dz_stretch_level_start ) < dz(1) * 1.5_dp ) ) THEN
+          WRITE( message, * ) 'Eeach dz_stretch_level_start has to be ',&
+                              'larger than ', dz(1) * 1.5
+             CALL abort( 'stretched_z', message)
+       ENDIF
+
+!
+!--    The stretching has to start and end on a grid level. Therefore 
+!--    user-specified values have to ''interpolate'' to the next lowest level
+       IF ( number_stretch_level_start /= 0 ) THEN
+          dz_stretch_level_start(1) = INT( (dz_stretch_level_start(1) -        &
+                                            dz(1)/2.0) / dz(1) )               &
+                                      * dz(1) + dz(1)/2.0
+       ENDIF
+       
+       IF ( number_stretch_level_start > 1 ) THEN
+          DO n = 2, number_stretch_level_start
+             dz_stretch_level_start(n) = INT( dz_stretch_level_start(n) /      &
+                                              dz(n) ) * dz(n)
+          ENDDO
+       ENDIF
+       
+       IF ( number_stretch_level_end /= 0 ) THEN
+          DO n = 1, number_stretch_level_end
+             dz_stretch_level_end(n) = INT( dz_stretch_level_end(n) /          &
+                                            dz(n+1) ) * dz(n+1)
+          ENDDO
+       ENDIF
+ 
+!
+!--    Determine stretching factor if necessary
+       IF ( number_stretch_level_end >= 1 ) THEN 
+          CALL calculate_stretching_factor( number_stretch_level_end, dz,      & 
+                                            dz_stretch_factor,                 &
+                                            dz_stretch_factor_array,           &   
+                                            dz_stretch_level_end,              &
+                                            dz_stretch_level_start )
+       ENDIF
+
+       z(1) = dz(1) * 0.5_dp
+!
+       dz_stretch_level_index = n
+       dz_stretched = dz(1)
+       DO  k = 2, n
+
+          IF ( dz_stretch_level <= z(k-1)  .AND.  dz_stretched < dz_max )  THEN
+
+             dz_stretched = dz_stretched * dz_stretch_factor
+             dz_stretched = MIN( dz_stretched, dz_max )
+
+             IF ( dz_stretch_level_index == n ) dz_stretch_level_index = k-1
+
+          ENDIF
+
+          z(k) = z(k-1) + dz_stretched
+
+       ENDDO
+!--    Determine u and v height levels considering the possibility of grid
+!--    stretching in several heights.
+       n = 1
+       dz_stretch_level_start_index(:) = UBOUND(z, 1)
+       dz_stretch_level_end_index(:) = UBOUND(z, 1)
+       dz_stretched = dz(1)
+
+!--    The default value of dz_stretch_level_start is negative, thus the first
+!--    condition is always true. Hence, the second condition is necessary.
+       DO  k = 2, UBOUND(z, 1)
+          IF ( dz_stretch_level_start(n) <= z(k-1) .AND.                      &
+               dz_stretch_level_start(n) /= -9999999.9_dp ) THEN
+             dz_stretched = dz_stretched * dz_stretch_factor_array(n)
+             
+             IF ( dz(n) > dz(n+1) ) THEN
+                dz_stretched = MAX( dz_stretched, dz(n+1) ) !Restrict dz_stretched to the user-specified (higher) dz
+             ELSE
+                dz_stretched = MIN( dz_stretched, dz(n+1) ) !Restrict dz_stretched to the user-specified (lower) dz
+             ENDIF
+             
+             IF ( dz_stretch_level_start_index(n) == UBOUND(z, 1) )            &
+             dz_stretch_level_start_index(n) = k-1
+             
+          ENDIF
+          
+          z(k) = z(k-1) + dz_stretched
+          
+!
+!--       Make sure that the stretching ends exactly at dz_stretch_level_end 
+          dz_level_end = ABS( z(k) - dz_stretch_level_end(n) ) 
+          
+          IF ( dz_level_end < dz(n+1)/3.0 ) THEN
+             z(k) = dz_stretch_level_end(n)
+             dz_stretched = dz(n+1)
+             dz_stretch_level_end_index(n) = k
+             n = n + 1             
+          ENDIF
+       ENDDO
+
+       DEALLOCATE( min_dz_stretch_level_end )
+
+    END SUBROUTINE stretched_z
+
+
+! Description: [PALM subroutine]
+! -----------------------------------------------------------------------------!
+!> Calculation of the stretching factor through an iterative method. Ideas were 
+!> taken from the paper "Regional stretched grid generation and its application
+!> to the NCAR RegCM (1999)". Normally, no analytic solution exists because the
+!> system of equations has two variables (r,l) but four requirements 
+!> (l=integer, r=[0,88;1,2], Eq(6), Eq(5) starting from index j=1) which
+!> results into an overdetermined system. 
+!------------------------------------------------------------------------------!
+ SUBROUTINE calculate_stretching_factor( number_end, dz, dz_stretch_factor,    &
+                                         dz_stretch_factor_array,              &   
+                                         dz_stretch_level_end,                 &
+                                         dz_stretch_level_start )
+ 
+    REAL(dp), DIMENSION(:), INTENT(IN)    ::  dz
+    REAL(dp), DIMENSION(:), INTENT(INOUT) ::  dz_stretch_factor_array
+    REAL(dp), DIMENSION(:), INTENT(IN)    ::  dz_stretch_level_end, dz_stretch_level_start
+    REAL(dp)                              ::  dz_stretch_factor
+  
+    INTEGER ::  iterations  !< number of iterations until stretch_factor_lower/upper_limit is reached  
+    INTEGER ::  l_rounded   !< after l_rounded grid levels dz(n) is strechted to dz(n+1) with stretch_factor_2 
+    INTEGER ::  n           !< loop variable for stretching
+    
+    INTEGER, INTENT(IN) ::  number_end !< number of user-specified end levels for stretching
+        
+    REAL(dp) ::  delta_l               !< absolute difference between l and l_rounded
+    REAL(dp) ::  delta_stretch_factor  !< absolute difference between stretch_factor_1 and stretch_factor_2
+    REAL(dp) ::  delta_total_new       !< sum of delta_l and delta_stretch_factor for the next iteration (should be as small as possible) 
+    REAL(dp) ::  delta_total_old       !< sum of delta_l and delta_stretch_factor for the last iteration 
+    REAL(dp) ::  distance              !< distance between dz_stretch_level_start and dz_stretch_level_end (stretching region)
+    REAL(dp) ::  l                     !< value that fulfil Eq. (5) in the paper mentioned above together with stretch_factor_1 exactly
+    REAL(dp) ::  numerator             !< numerator of the quotient
+    REAL(dp) ::  stretch_factor_1      !< stretching factor that fulfil Eq. (5) togehter with l exactly
+    REAL(dp) ::  stretch_factor_2      !< stretching factor that fulfil Eq. (6) togehter with l_rounded exactly
+    
+    REAL(dp) ::  dz_stretch_factor_array_2(9) = 1.08_dp  !< Array that contains all stretch_factor_2 that belongs to stretch_factor_1 
+    
+    REAL(dp), PARAMETER ::  stretch_factor_interval = 1.0E-06  !< interval for sampling possible stretching factors
+    REAL(dp), PARAMETER ::  stretch_factor_lower_limit = 0.88  !< lowest possible stretching factor
+    REAL(dp), PARAMETER ::  stretch_factor_upper_limit = 1.12  !< highest possible stretching factor
+ 
+ 
+    l = 0
+    DO  n = 1, number_end
+    
+       iterations = 1
+       stretch_factor_1 = 1.0 
+       stretch_factor_2 = 1.0
+       delta_total_old = 1.0
+       
+       IF ( dz(n) > dz(n+1) ) THEN
+          DO WHILE ( stretch_factor_1 >= stretch_factor_lower_limit ) 
+             
+             stretch_factor_1 = 1.0 - iterations * stretch_factor_interval
+             distance = ABS( dz_stretch_level_end(n) -                   &
+                        dz_stretch_level_start(n) ) 
+             numerator = distance*stretch_factor_1/dz(n) +               &
+                         stretch_factor_1 - distance/dz(n)
+             
+             IF ( numerator > 0.0 ) THEN
+                l = LOG( numerator ) / LOG( stretch_factor_1 ) - 1.0
+                l_rounded = NINT( l )
+                delta_l = ABS( l_rounded - l ) / l
+             ENDIF
+             
+             stretch_factor_2 = EXP( LOG( dz(n+1)/dz(n) ) / (l_rounded) )
+             
+             delta_stretch_factor = ABS( stretch_factor_1 -              &
+                                         stretch_factor_2 ) /            &
+                                    stretch_factor_2
+             
+             delta_total_new = delta_l + delta_stretch_factor
+
+!
+!--                stretch_factor_1 is taken to guarantee that the stretching
+!--                procedure ends as close as possible to dz_stretch_level_end.
+!--                stretch_factor_2 would guarantee that the stretched dz(n) is
+!--                equal to dz(n+1) after l_rounded grid levels.
+             IF (delta_total_new < delta_total_old) THEN
+                dz_stretch_factor_array(n) = stretch_factor_1
+                dz_stretch_factor_array_2(n) = stretch_factor_2
+                delta_total_old = delta_total_new
+             ENDIF
+             
+             iterations = iterations + 1
+            
+          ENDDO
+             
+       ELSEIF ( dz(n) < dz(n+1) ) THEN 
+          DO WHILE ( stretch_factor_1 <= stretch_factor_upper_limit )
+                     
+             stretch_factor_1 = 1.0 + iterations * stretch_factor_interval
+             distance = ABS( dz_stretch_level_end(n) -                      &
+                        dz_stretch_level_start(n) ) 
+             numerator = distance*stretch_factor_1/dz(n) +                  &
+                         stretch_factor_1 - distance/dz(n)
+             
+             l = LOG( numerator ) / LOG( stretch_factor_1 ) - 1.0
+             l_rounded = NINT( l )
+             delta_l = ABS( l_rounded - l ) / l
+             
+             stretch_factor_2 = EXP( LOG( dz(n+1)/dz(n) ) / (l_rounded) )
+
+             delta_stretch_factor = ABS( stretch_factor_1 -                 &
+                                        stretch_factor_2 ) /                &
+                                        stretch_factor_2
+             
+             delta_total_new = delta_l + delta_stretch_factor
+             
+!
+!--                stretch_factor_1 is taken to guarantee that the stretching
+!--                procedure ends as close as possible to dz_stretch_level_end.
+!--                stretch_factor_2 would guarantee that the stretched dz(n) is
+!--                equal to dz(n+1) after l_rounded grid levels.
+             IF (delta_total_new < delta_total_old) THEN
+                dz_stretch_factor_array(n) = stretch_factor_1
+                dz_stretch_factor_array_2(n) = stretch_factor_2
+                delta_total_old = delta_total_new
+             ENDIF
+             
+             iterations = iterations + 1
+          ENDDO
+          
+       ELSE
+          message = 'Two adjacent values of dz must be different'
+          CALL abort( 'calculate_stretching_factor', message)
+       ENDIF
+
+!
+!--    Check if also the second stretching factor fits into the allowed
+!--    interval. If not, print a warning for the user.
+       IF ( dz_stretch_factor_array_2(n) < stretch_factor_lower_limit .OR.     & 
+            dz_stretch_factor_array_2(n) > stretch_factor_upper_limit ) THEN
+          WRITE( message, * ) 'stretch_factor_2 = ',                    &
+                                     dz_stretch_factor_array_2(n), ' which is',&
+                                     ' responsible for exactly reaching& dz =',&
+                                      dz(n+1), 'after a specific amount of',   & 
+                                     ' grid levels& exceeds the upper',        &
+                                     ' limit =', stretch_factor_upper_limit,   &
+                                     ' &or lower limit = ',                    &
+                                     stretch_factor_lower_limit
+          CALL abort( 'calculate_stretching_factor', message )
+            
+       ENDIF
+    ENDDO
+        
+ END SUBROUTINE calculate_stretching_factor
+
+    SUBROUTINE midpoints(z, zw)
+
+        REAL(dp), INTENT(IN)  ::  z(0:)
+        REAL(dp), INTENT(OUT) ::  zw(1:)
+
+        INTEGER ::  k
+
+        DO k = 1, UBOUND(zw, 1)
+           zw(k) = 0.5_dp * (z(k-1) + z(k))
+        END DO
+
+    END SUBROUTINE midpoints
+
+
+    SUBROUTINE setup_io_groups()
+
+       INTEGER ::  ngroups
+
+       ngroups = 16
+       ALLOCATE( io_group_list(ngroups) )
+       
+       !soil temp
+       io_group_list(1) = init_io_group(                                       &
+          in_files = soil_files,                                               &
+          out_vars = output_var_table(1:1),                                    &
+          in_var_list = input_var_table(1:1),                                  &
+          kind = 'soil-temperature'                                            &
+       )
+
+       !soil water
+       io_group_list(2) = init_io_group(                                       &
+          in_files = soil_files,                                               &
+          out_vars = output_var_table(2:2),                                    &
+          in_var_list = input_var_table(2:2),                                  &
+          kind = 'soil-water'                                                  &
+       )
+
+       !potential temperature, surface pressure, specific humidity including
+       !nudging and subsidence, and geostrophic winds ug, vg
+       io_group_list(3) = init_io_group(                                       &
+          in_files = flow_files,                                               &
+          out_vars = [output_var_table(56:64),                                 & ! internal averaged density and pressure profiles
+                      output_var_table(3:8), output_var_table(9:14),           &
+                      output_var_table(42:42), output_var_table(43:44),        &
+                      output_var_table(49:51), output_var_table(52:54)],       &
+          in_var_list = (/input_var_table(3), input_var_table(17),             & ! T, P, QV
+                          input_var_table(4) /),                               &
+          kind = 'thermodynamics',                                             &
+          n_output_quantities = 4                                              & ! P, Theta, Rho, qv
+       )
+
+       !Moved to therodynamic io_group
+       !io_group_list(4) = init_io_group(                                       &
+       !   in_files = flow_files,                                               &
+       !   out_vars = [output_var_table(9:14), output_var_table(52:54)],        &
+       !   in_var_list = input_var_table(4:4),                                  &
+       !   kind = 'scalar'                                                      &
+       !)
+
+       !u and v velocity, ug anv vg moved to thermodynamic io group. 
+       io_group_list(5) = init_io_group(                                       &
+          in_files = flow_files,                                               &
+          out_vars = [output_var_table(15:26), output_var_table(45:46)],       &
+          !out_vars = output_var_table(15:20),                                  &
+          in_var_list = input_var_table(5:6),                                  &
+          !in_var_list = input_var_table(5:5),                                  &
+          kind = 'velocities'                                                  &
+       )
+   
+       !!v velocity, deprecated!
+       !io_group_list(6) = init_io_group(                                       &
+       !   in_files = flow_files,                                               &
+       !   out_vars = output_var_table(21:26),                                  &
+       !   in_var_list = input_var_table(6:6),                                  &
+       !   kind = 'horizontal velocity'                                         &
+       !)
+       !io_group_list(6) % to_be_processed = .FALSE.
+   
+       !w velocity and subsidence and w nudging
+       io_group_list(7) = init_io_group(                                       &
+          in_files = flow_files,                                               &
+          out_vars = [output_var_table(27:32), output_var_table(47:48)],       &
+          in_var_list = input_var_table(7:7),                                  &
+          kind = 'scalar'                                                      &
+       )
+
+       !rain
+       io_group_list(8) = init_io_group(                                       &
+          in_files = soil_moisture_files,                                      &
+          out_vars = output_var_table(33:33),                                  &
+          in_var_list = input_var_table(8:8),                                  &
+          kind = 'accumulated'                                                 &
+       )
+       io_group_list(8) % to_be_processed = .FALSE.
+
+       !snow
+       io_group_list(9) = init_io_group(                                       &
+          in_files = soil_moisture_files,                                      &
+          out_vars = output_var_table(34:34),                                  &
+          in_var_list = input_var_table(9:9),                                  &
+          kind = 'accumulated'                                                 &
+       )
+       io_group_list(9) % to_be_processed = .FALSE.
+
+       !graupel
+       io_group_list(10) = init_io_group(                                      &
+          in_files = soil_moisture_files,                                      &
+          out_vars = output_var_table(35:35),                                  &
+          in_var_list = input_var_table(10:10),                                &
+          kind = 'accumulated'                                                 &
+       )
+       io_group_list(10) % to_be_processed = .FALSE.
+
+       !evapotranspiration
+       io_group_list(11) = init_io_group(                                      &
+          in_files = soil_moisture_files,                                      &
+          out_vars = output_var_table(37:37),                                  &
+          in_var_list = input_var_table(11:11),                                &
+          kind = 'accumulated'                                                 &
+       )
+       io_group_list(11) % to_be_processed = .FALSE.
+
+       !2m air temperature
+       io_group_list(12) = init_io_group(                                      &
+          in_files = soil_moisture_files,                                      &
+          out_vars = output_var_table(36:36),                                  &
+          in_var_list = input_var_table(12:12),                                &
+          kind = 'surface'                                                     &
+       )
+
+       !incoming diffusive sw flux
+       io_group_list(13) = init_io_group(                                      &
+          in_files = radiation_files,                                          &
+          out_vars = output_var_table(38:38),                                  &
+          in_var_list = input_var_table(13:13),                                &
+          kind = 'running average'                                             &
+       )
+       io_group_list(13) % to_be_processed = .FALSE.
+
+       !incoming direct sw flux
+       io_group_list(14) = init_io_group(                                      &
+          in_files = radiation_files,                                          &
+          out_vars = output_var_table(39:39),                                  &
+          in_var_list = input_var_table(14:14),                                &
+          kind = 'running average'                                             &
+       )
+       io_group_list(14) % to_be_processed = .FALSE.
+
+       !sw radiation balance
+       io_group_list(15) = init_io_group(                                      &
+          in_files = radiation_files,                                          &
+          out_vars = output_var_table(40:40),                                  &
+          in_var_list = input_var_table(15:15),                                &
+          kind = 'running average'                                             &
+       )
+       io_group_list(15) % to_be_processed = .FALSE.
+
+       !lw radiation balance
+       io_group_list(16) = init_io_group(                                      &
+          in_files = radiation_files,                                          &
+          out_vars = output_var_table(41:41),                                  &
+          in_var_list = input_var_table(16:16),                                &
+          kind = 'running average'                                             &
+       )
+       io_group_list(16) % to_be_processed = .FALSE.
+
+    END SUBROUTINE setup_io_groups
+
+
+    FUNCTION init_io_group(in_files, out_vars, in_var_list, kind,              &
+                           n_output_quantities) RESULT(group)
+       CHARACTER(LEN=PATH), INTENT(IN) ::  in_files(:)
+       CHARACTER(LEN=*), INTENT(IN)    ::  kind
+       TYPE(nc_var), INTENT(IN)        ::  out_vars(:)
+       TYPE(nc_var), INTENT(IN)        ::  in_var_list(:)
+       INTEGER, OPTIONAL               ::  n_output_quantities
+
+       TYPE(io_group)                  ::  group
+
+       group % nt = SIZE(in_files)
+       group % nv = SIZE(out_vars)
+       group % n_inputs = SIZE(in_var_list)
+       group % kind = TRIM(kind)
+
+       IF ( PRESENT(n_output_quantities) )  THEN
+          group % n_output_quantities = n_output_quantities
+       ELSE
+          group % n_output_quantities = group % n_inputs
+       END IF
+
+       ALLOCATE(group % in_var_list(group % n_inputs))
+       ALLOCATE(group % in_files(group % nt))
+       ALLOCATE(group % out_vars(group % nv))
+
+       group % in_var_list = in_var_list
+       group % in_files = in_files
+       group % out_vars = out_vars
+       group % to_be_processed = .TRUE.
+
+    END FUNCTION init_io_group
+
+
+!------------------------------------------------------------------------------!
+! Description:
+! ------------
+!> Deallocates all allocated variables.
+!------------------------------------------------------------------------------!
+    SUBROUTINE fini_grids()
+
+       CALL report('fini_grids', 'Deallocating grids', cfg % debug)
+       
+       DEALLOCATE(x, y, z, xu, yv, zw, z_column, zw_column)
+
+       DEALLOCATE(palm_grid%x,  palm_grid%y,  palm_grid%z,                     &
+                  palm_grid%xu, palm_grid%yv, palm_grid%zw,                    &
+                  palm_grid%clon,  palm_grid%clat,                             &
+                  palm_grid%clonu, palm_grid%clatu)
+
+       DEALLOCATE(palm_intermediate%x,  palm_intermediate%y,  palm_intermediate%z, &
+                  palm_intermediate%xu, palm_intermediate%yv, palm_intermediate%zw,&
+                  palm_intermediate%clon,  palm_intermediate%clat,             &  
+                  palm_intermediate%clonu, palm_intermediate%clatu)
+
+       DEALLOCATE(cosmo_grid%lon,  cosmo_grid%lat,                             &
+                  cosmo_grid%lonu, cosmo_grid%latv,                            &
+                  cosmo_grid%hfl)
+
+    END SUBROUTINE fini_grids
+
+
+!------------------------------------------------------------------------------!
+! Description:
+! ------------
+!> Initializes the the variable list.
+!------------------------------------------------------------------------------!
+    SUBROUTINE setup_variable_tables(ic_mode)
+       CHARACTER(LEN=*), INTENT(IN) ::  ic_mode
+       INTEGER                      ::  n_invar = 0  !< number of variables in the input variable table
+       INTEGER                      ::  n_outvar = 0 !< number of variables in the output variable table
+       TYPE(nc_var), POINTER        ::  var
+
+       IF (TRIM(cfg % start_date) == '')  THEN
+          message = 'Simulation start date has not been set.'
+          CALL abort('setup_variable_tables', message)
+       END IF
+
+       nc_source_text = 'COSMO-DE analysis from ' // TRIM(cfg % start_date)
+
+       n_invar = 17
+       n_outvar = 64
+       ALLOCATE( input_var_table(n_invar) )
+       ALLOCATE( output_var_table(n_outvar) )
+
+!
+!------------------------------------------------------------------------------
+!- Section 1: NetCDF input variables
+!------------------------------------------------------------------------------
+       var => input_var_table(1)
+       var % name = 'T_SO'
+       var % to_be_processed = .TRUE.
+       var % is_upside_down = .FALSE.
+
+       var => input_var_table(2)
+       var % name = 'W_SO'
+       var % to_be_processed = .TRUE.
+       var % is_upside_down = .FALSE.
+
+       var => input_var_table(3)
+       var % name = 'T'
+       var % to_be_processed = .TRUE.
+       var % is_upside_down = .TRUE.
+
+       var => input_var_table(4)
+       var % name = 'QV'
+       var % to_be_processed = .TRUE.
+       var % is_upside_down = .TRUE.
+
+       var => input_var_table(5)
+       var % name = 'U'
+       var % to_be_processed = .TRUE.
+       var % is_upside_down = .TRUE.
+
+       var => input_var_table(6)
+       var % name = 'V'
+       var % to_be_processed = .TRUE.
+       var % is_upside_down = .TRUE.
+
+       var => input_var_table(7)
+       var % name = 'W'
+       var % to_be_processed = .TRUE.
+       var % is_upside_down = .TRUE.
+
+       var => input_var_table(8)
+       var % name = 'RAIN_GSP'
+       var % to_be_processed = .TRUE.
+       var % is_upside_down = .FALSE.
+
+       var => input_var_table(9)
+       var % name = 'SNOW_GSP'
+       var % to_be_processed = .TRUE.
+       var % is_upside_down = .FALSE.
+
+       var => input_var_table(10)
+       var % name = 'GRAU_GSP'
+       var % to_be_processed = .TRUE.
+       var % is_upside_down = .FALSE.
+
+       var => input_var_table(11)
+       var % name = 'AEVAP_S'
+       var % to_be_processed = .TRUE.
+       var % is_upside_down = .FALSE.
+
+       var => input_var_table(12)
+       var % name = 'T_2M'
+       var % to_be_processed = .TRUE.
+       var % is_upside_down = .FALSE.
+
+       var => input_var_table(13)
+       var % name = 'ASWDIFD_S'
+       var % to_be_processed = .TRUE.
+       var % is_upside_down = .FALSE.
+
+       var => input_var_table(14)
+       var % name = 'ASWDIR_S'
+       var % to_be_processed = .TRUE.
+       var % is_upside_down = .FALSE.
+
+       var => input_var_table(15)
+       var % name = 'ASOB_S'
+       var % to_be_processed = .TRUE.
+       var % is_upside_down = .FALSE.
+
+       var => input_var_table(16)
+       var % name = 'ATHB_S'
+       var % to_be_processed = .TRUE.
+       var % is_upside_down = .FALSE.
+
+       var => input_var_table(17)
+       var % name = 'P'
+       var % to_be_processed = .TRUE.
+       var % is_upside_down = .TRUE.
+
+!
+!------------------------------------------------------------------------------
+!- Section 2: NetCDF output variables
+!------------------------------------------------------------------------------
+!
+!------------------------------------------------------------------------------
+! Section 2.1: Realistic forcings, i.e. 3D initial and boundary conditions
+!------------------------------------------------------------------------------
+       output_var_table(1) = init_nc_var(                                      &
+          name              = 'init_soil_t',                                   &
+          std_name          = "",                                              &
+          long_name         = "initial soil temperature",                      &
+          units             = "K",                                             &
+          kind              = "init soil",                                     &
+          input_id          = 1,                                               &
+          output_file       = output_file,                                     &
+          grid              = palm_grid,                                       &
+          intermediate_grid = palm_intermediate                                &
+       )
+
+       output_var_table(2) = init_nc_var(                                      &
+          name              = 'init_soil_m',                                   &
+          std_name          = "",                                              &
+          long_name         = "initial soil moisture",                         &
+          units             = "m^3/m^3",                                       &
+          kind              = "init soil",                                     &
+          input_id          = 1,                                               &
+          output_file       = output_file,                                     &
+          grid              = palm_grid,                                       &
+          intermediate_grid = palm_intermediate                                &
+       )
+
+       output_var_table(3) = init_nc_var(                                      &
+          name              = 'init_atmosphere_pt',                            &
+          std_name          = "",                                              &
+          long_name         = "initial potential temperature",                 &
+          units             = "K",                                             &
+          kind              = "init scalar",                                   &
+          input_id          = 1,                                               & ! first in (T, p) IO group
+          output_file       = output_file,                                     &
+          grid              = palm_grid,                                       &
+          intermediate_grid = palm_intermediate,                               &
+          is_profile = (TRIM(ic_mode) == 'profile')                            &
+       )
+       IF (TRIM(ic_mode) == 'profile')  THEN
+          output_var_table(3) % averaging_grid => averaged_scalar_profile
+       END IF
+
+       output_var_table(4) = init_nc_var(                                      &
+          name              = 'ls_forcing_left_pt',                            &
+          std_name          = "",                                              &
+          long_name         = "large-scale forcing for left model boundary for the potential temperature", &
+          units             = "K",                                             &
+          kind              = "left scalar",                                   &
+          input_id          = 1,                                               &
+          grid              = scalars_west_grid,                               &
+          intermediate_grid = scalars_west_intermediate,                       &
+          output_file = output_file                                            &
+       )
+
+       output_var_table(5) = init_nc_var(                                      &
+          name              = 'ls_forcing_right_pt',                           &
+          std_name          = "",                                              &
+          long_name         = "large-scale forcing for right model boundary for the potential temperature", &
+          units             = "K",                                             &
+          kind              = "right scalar",                                  &
+          input_id          = 1,                                               &
+          grid              = scalars_east_grid,                               &
+          intermediate_grid = scalars_east_intermediate,                       &
+          output_file = output_file                                            &
+       )
+
+       output_var_table(6) = init_nc_var(                                      &
+          name              = 'ls_forcing_north_pt',                           &
+          std_name          = "",                                              &
+          long_name         = "large-scale forcing for north model boundary for the potential temperature", &
+          units             = "K",                                             &
+          kind              = "north scalar",                                  &
+          input_id          = 1,                                               &
+          grid              = scalars_north_grid,                              &
+          intermediate_grid = scalars_north_intermediate,                      &
+          output_file = output_file                                            &
+       )
+
+       output_var_table(7) = init_nc_var(                                      &
+          name              = 'ls_forcing_south_pt',                           &
+          std_name          = "",                                              &
+          long_name         = "large-scale forcing for south model boundary for the potential temperature", &
+          units             = "K",                                             &
+          kind              = "south scalar",                                  &
+          input_id          = 1,                                               &
+          grid              = scalars_south_grid,                              &
+          intermediate_grid = scalars_south_intermediate,                      &
+          output_file = output_file                                            &
+       )
+
+       output_var_table(8) = init_nc_var(                                      &
+          name              = 'ls_forcing_top_pt',                             &
+          std_name          = "",                                              &
+          long_name         = "large-scale forcing for top model boundary for the potential temperature", &
+          units             = "K",                                             &
+          kind              = "top scalar",                                    &
+          input_id          = 1,                                               &
+          grid              = scalars_top_grid,                                &
+          intermediate_grid = scalars_top_intermediate,                        &
+          output_file = output_file                                            &
+       )
+
+       output_var_table(9) = init_nc_var(                                      &
+          name              = 'init_atmosphere_qv',                            &
+          std_name          = "",                                              &
+          long_name         = "initial specific humidity",                     &
+          units             = "kg/kg",                                         &
+          kind              = "init scalar",                                   &
+          input_id          = 3,                                               &
+          output_file       = output_file,                                     &
+          grid              = palm_grid,                                       &
+          intermediate_grid = palm_intermediate,                               &
+          is_profile = (TRIM(ic_mode) == 'profile')                            &
+       )
+       IF (TRIM(ic_mode) == 'profile')  THEN
+          output_var_table(9) % averaging_grid => averaged_scalar_profile
+       END IF
+
+       output_var_table(10) = init_nc_var(                                     &
+          name              = 'ls_forcing_left_qv',                            &
+          std_name          = "",                                              &
+          long_name         = "large-scale forcing for left model boundary for the specific humidity", &
+          units             = "kg/kg",                                         &
+          kind              = "left scalar",                                   &
+          input_id          = 3,                                               &
+          output_file       = output_file,                                     &
+          grid              = scalars_west_grid,                               &
+          intermediate_grid = scalars_west_intermediate                        &
+       )
+
+       output_var_table(11) = init_nc_var(                                     &
+          name              = 'ls_forcing_right_qv',                           &
+          std_name          = "",                                              &
+          long_name         = "large-scale forcing for right model boundary for the specific humidity", &
+          units             = "kg/kg",                                         &
+          kind              = "right scalar",                                  &
+          input_id          = 3,                                               &
+          output_file       = output_file,                                     &
+          grid              = scalars_east_grid,                               &
+          intermediate_grid = scalars_east_intermediate                        &
+       )
+
+       output_var_table(12) = init_nc_var(                                     &
+          name              = 'ls_forcing_north_qv',                           &
+          std_name          = "",                                              &
+          long_name         = "large-scale forcing for north model boundary for the specific humidity", &
+          units             = "kg/kg",                                         &
+          kind              = "north scalar",                                  &
+          input_id          = 3,                                               &
+          output_file       = output_file,                                     &
+          grid              = scalars_north_grid,                              &
+          intermediate_grid = scalars_north_intermediate                       &
+       )
+
+       output_var_table(13) = init_nc_var(                                     &
+          name              = 'ls_forcing_south_qv',                           &
+          std_name          = "",                                              &
+          long_name         = "large-scale forcing for south model boundary for the specific humidity", &
+          units             = "kg/kg",                                         &
+          kind              = "south scalar",                                  &
+          input_id          = 3,                                               &
+          output_file       = output_file,                                     &
+          grid              = scalars_south_grid,                              &
+          intermediate_grid = scalars_south_intermediate                       &
+       )
+
+       output_var_table(14) = init_nc_var(                                     &
+          name              = 'ls_forcing_top_qv',                             &
+          std_name          = "",                                              &
+          long_name         = "large-scale forcing for top model boundary for the specific humidity", &
+          units             = "kg/kg",                                         &
+          kind              = "top scalar",                                    &
+          input_id          = 3,                                               &
+          output_file       = output_file,                                     &
+          grid              = scalars_top_grid,                                &
+          intermediate_grid = scalars_top_intermediate                         &
+       )
+
+       output_var_table(15) = init_nc_var(                                     &
+          name              = 'init_atmosphere_u',                             &
+          std_name          = "",                                              &
+          long_name         = "initial wind component in x direction",         &
+          units             = "m/s",                                           &
+          kind              = "init u",                                        &
+          input_id          = 1,                                               & ! first in (U, V) I/O group
+          output_file       = output_file,                                     &
+          grid              = u_initial_grid,                                  &
+          intermediate_grid = u_initial_intermediate,                          &
+          is_profile = (TRIM(ic_mode) == 'profile')                            &
+       )
+       IF (TRIM(ic_mode) == 'profile')  THEN
+          output_var_table(15) % averaging_grid => averaged_scalar_profile
+       END IF 
+
+       output_var_table(16) = init_nc_var(                                     &
+          name              = 'ls_forcing_left_u',                             &
+          std_name          = "",                                              &
+          long_name         = "large-scale forcing for left model boundary for the wind component in x direction", &
+          units             = "m/s",                                           &
+          kind              = "left u",                                        &
+          input_id          = 1,                                               & ! first in (U, V) I/O group
+          output_file       = output_file,                                     &
+          grid              = u_west_grid,                                     &
+          intermediate_grid = u_west_intermediate                              &
+       )
+
+       output_var_table(17) = init_nc_var(                                     &
+          name              = 'ls_forcing_right_u',                            &
+          std_name          = "",                                              &
+          long_name         = "large-scale forcing for right model boundary for the wind component in x direction", &
+          units             = "m/s",                                           &
+          kind              = "right u",                                       &
+          input_id          = 1,                                               & ! first in (U, V) I/O group
+          output_file       = output_file,                                     &
+          grid              = u_east_grid,                                     &
+          intermediate_grid = u_east_intermediate                              &
+       )
+
+       output_var_table(18) = init_nc_var(                                     &
+          name              = 'ls_forcing_north_u',                            &
+          std_name          = "",                                              &
+          long_name         = "large-scale forcing for north model boundary for the wind component in x direction", &
+          units             = "m/s",                                           &
+          kind              = "north u",                                       &
+          input_id          = 1,                                               & ! first in (U, V) I/O group
+          output_file       = output_file,                                     &
+          grid              = u_north_grid,                                    &
+          intermediate_grid = u_north_intermediate                             &
+       )
+
+       output_var_table(19) = init_nc_var(                                     &
+          name              = 'ls_forcing_south_u',                            &
+          std_name          = "",                                              &
+          long_name         = "large-scale forcing for south model boundary for the wind component in x direction", &
+          units             = "m/s",                                           &
+          kind              = "south u",                                       &
+          input_id          = 1,                                               & ! first in (U, V) I/O group
+          output_file       = output_file,                                     &
+          grid              = u_south_grid,                                    &
+          intermediate_grid = u_south_intermediate                             &
+       )
+
+       output_var_table(20) = init_nc_var(                                     &
+          name              = 'ls_forcing_top_u',                              &
+          std_name          = "",                                              &
+          long_name         = "large-scale forcing for top model boundary for the wind component in x direction", &
+          units             = "m/s",                                           &
+          kind              = "top u",                                         &
+          input_id          = 1,                                               & ! first in (U, V) I/O group
+          output_file       = output_file,                                     &
+          grid              = u_top_grid,                                      &
+          intermediate_grid = u_top_intermediate                               &
+       )
+
+       output_var_table(21) = init_nc_var(                                     &
+          name              = 'init_atmosphere_v',                             &
+          std_name          = "",                                              &
+          long_name         = "initial wind component in y direction",         &
+          units             = "m/s",                                           &
+          kind              = "init v",                                        &
+          input_id          = 2,                                               & ! second in (U, V) I/O group
+          output_file       = output_file,                                     &
+          grid              = v_initial_grid,                                  &
+          intermediate_grid = v_initial_intermediate,                          &
+          is_profile = (TRIM(ic_mode) == 'profile')                            &
+       )
+       IF (TRIM(ic_mode) == 'profile')  THEN
+          output_var_table(21) % averaging_grid => averaged_scalar_profile
+       END IF
+
+       output_var_table(22) = init_nc_var(                                     &
+          name              = 'ls_forcing_left_v',                             &
+          std_name          = "",                                              &
+          long_name         = "large-scale forcing for left model boundary for the wind component in y direction", &
+          units             = "m/s",                                           &
+          kind              = "right v",                                       &
+          input_id          = 2,                                               & ! second in (U, V) I/O group
+          output_file       = output_file,                                     &
+          grid              = v_west_grid,                                     &
+          intermediate_grid = v_west_intermediate                              &
+       )
+
+       output_var_table(23) = init_nc_var(                                     &
+          name              = 'ls_forcing_right_v',                            &
+          std_name          = "",                                              &
+          long_name         = "large-scale forcing for right model boundary for the wind component in y direction", &
+          units             = "m/s",                                           &
+          kind              = "right v",                                       &
+          input_id          = 2,                                               & ! second in (U, V) I/O group
+          output_file       = output_file,                                     &
+          grid              = v_east_grid,                                     &
+          intermediate_grid = v_east_intermediate                              &
+       )
+
+       output_var_table(24) = init_nc_var(                                     &
+          name              = 'ls_forcing_north_v',                            &
+          std_name          = "",                                              &
+          long_name         = "large-scale forcing for north model boundary for the wind component in y direction", &
+          units             = "m/s",                                           &
+          kind              = "north v",                                       &
+          input_id          = 2,                                               & ! second in (U, V) I/O group
+          output_file       = output_file,                                     &
+          grid              = v_north_grid,                                    &
+          intermediate_grid = v_north_intermediate                             &
+       )
+
+       output_var_table(25) = init_nc_var(                                     &
+          name              = 'ls_forcing_south_v',                            &
+          std_name          = "",                                              &
+          long_name         = "large-scale forcing for south model boundary for the wind component in y direction", &
+          units             = "m/s",                                           &
+          kind              = "south v",                                       &
+          input_id          = 2,                                               & ! second in (U, V) I/O group
+          output_file       = output_file,                                     &
+          grid              = v_south_grid,                                    &
+          intermediate_grid = v_south_intermediate                             &
+       )
+
+       output_var_table(26) = init_nc_var(                                     &
+          name              = 'ls_forcing_top_v',                              &
+          std_name          = "",                                              &
+          long_name         = "large-scale forcing for top model boundary for the wind component in y direction", &
+          units             = "m/s",                                           &
+          kind              = "top v",                                         &
+          input_id          = 2,                                               & ! second in (U, V) I/O group
+          output_file       = output_file,                                     &
+          grid              = v_top_grid,                                      &
+          intermediate_grid = v_top_intermediate                               &
+       )
+
+       output_var_table(27) = init_nc_var(                                     &
+          name              = 'init_atmosphere_w',                             &
+          std_name          = "",                                              &
+          long_name         = "initial wind component in z direction",         &
+          units             = "m/s",                                           &
+          kind              = "init w",                                        &
+          input_id          = 1,                                               &
+          output_file       = output_file,                                     &
+          grid              = w_initial_grid,                                  &
+          intermediate_grid = w_initial_intermediate,                          &
+          is_profile = (TRIM(ic_mode) == 'profile')                            &
+       )
+       IF (TRIM(ic_mode) == 'profile')  THEN
+          output_var_table(27) % averaging_grid => averaged_w_profile
+       END IF
+
+       output_var_table(28) = init_nc_var(                                     &
+          name              = 'ls_forcing_left_w',                             &
+          std_name          = "",                                              &
+          long_name         = "large-scale forcing for left model boundary for the wind component in z direction", &
+          units             = "m/s",                                           &
+          kind              = "left w",                                        &
+          input_id          = 1,                                               &
+          output_file       = output_file,                                     &
+          grid              = w_west_grid,                                     &
+          intermediate_grid = w_west_intermediate                              &
+       )
+
+       output_var_table(29) = init_nc_var(                                     &
+          name              = 'ls_forcing_right_w',                            &
+          std_name          = "",                                              &
+          long_name         = "large-scale forcing for right model boundary for the wind component in z direction", &
+          units             = "m/s",                                           &
+          kind              = "right w",                                       &
+          input_id          = 1,                                               &
+          output_file       = output_file,                                     &
+          grid              = w_east_grid,                                     &
+          intermediate_grid = w_east_intermediate                              &
+       )
+
+       output_var_table(30) = init_nc_var(                                     &
+          name              = 'ls_forcing_north_w',                            &
+          std_name          = "",                                              &
+          long_name         = "large-scale forcing for north model boundary for the wind component in z direction", &
+          units             = "m/s",                                           &
+          kind              = "north w",                                       &
+          input_id          = 1,                                               &
+          output_file       = output_file,                                     &
+          grid              = w_north_grid,                                    &
+          intermediate_grid = w_north_intermediate                             &
+       )
+
+       output_var_table(31) = init_nc_var(                                     &
+          name              = 'ls_forcing_south_w',                            &
+          std_name          = "",                                              &
+          long_name         = "large-scale forcing for south model boundary for the wind component in z direction", &
+          units             = "m/s",                                           &
+          kind              = "south w",                                       &
+          input_id          = 1,                                               &
+          output_file       = output_file,                                     &
+          grid              = w_south_grid,                                    &
+          intermediate_grid = w_south_intermediate                             &
+       )
+
+       output_var_table(32) = init_nc_var(                                     &
+          name              = 'ls_forcing_top_w',                              &
+          std_name          = "",                                              &
+          long_name         = "large-scale forcing for top model boundary for the wind component in z direction", &
+          units             = "m/s",                                           &
+          kind              = "top w",                                         &
+          input_id          = 1,                                               &
+          output_file       = output_file,                                     &
+          grid              = w_top_grid,                                      &
+          intermediate_grid = w_top_intermediate                               &
+       )
+
+       output_var_table(33) = init_nc_var(                                     &
+          name              = 'ls_forcing_soil_rain',                          &
+          std_name          = "",                                              &
+          long_name         = "large-scale forcing rain",                      &
+          units             = "kg/m2",                                         &
+          kind              = "surface forcing",                               &
+          input_id          = 1,                                               &
+          output_file       = output_file,                                     &
+          grid              = palm_grid,                                       &
+          intermediate_grid = palm_intermediate                                &
+       )
+
+       output_var_table(34) = init_nc_var(                                     &
+          name              = 'ls_forcing_soil_snow',                          &
+          std_name          = "",                                              &
+          long_name         = "large-scale forcing snow",                      &
+          units             = "kg/m2",                                         &
+          kind              = "surface forcing",                               &
+          input_id          = 1,                                               &
+          output_file       = output_file,                                     &
+          grid              = palm_grid,                                       &
+          intermediate_grid = palm_intermediate                                &
+       )
+
+       output_var_table(35) = init_nc_var(                                     &
+          name              = 'ls_forcing_soil_graupel',                       &
+          std_name          = "",                                              &
+          long_name         = "large-scale forcing graupel",                   &
+          units             = "kg/m2",                                         &
+          kind              = "surface forcing",                               &
+          input_id          = 1,                                               &
+          output_file       = output_file,                                     &
+          grid              = palm_grid,                                       &
+          intermediate_grid = palm_intermediate                                &
+       )
+
+       output_var_table(36) = init_nc_var(                                     &
+          name              = 'ls_forcing_soil_t_2m',                          &
+          std_name          = "",                                              &
+          long_name         = "large-scale forcing 2m air temperature",        &
+          units             = "kg/m2",                                         &
+          kind              = "surface forcing",                               &
+          input_id          = 1,                                               &
+          output_file       = output_file,                                     &
+          grid              = palm_grid,                                       &
+          intermediate_grid = palm_intermediate                                &
+       )
+
+       output_var_table(37) = init_nc_var(                                     &
+          name              = 'ls_forcing_soil_evap',                          &
+          std_name          = "",                                              &
+          long_name         = "large-scale forcing evapo-transpiration",       &
+          units             = "kg/m2",                                         &
+          kind              = "surface forcing",                               &
+          input_id          = 1,                                               &
+          output_file       = output_file,                                     &
+          grid              = palm_grid,                                       &
+          intermediate_grid = palm_intermediate                                &
+       )
+       ! Radiation fluxes and balances
+       output_var_table(38) = init_nc_var(                                     &
+          name              = 'rad_swd_dif_0',                                 &
+          std_name          = "",                                              &
+          long_name         = "incoming diffuse shortwave radiative flux at the surface", &
+          units             = "W/m2",                                          &
+          kind              = "surface forcing",                               &
+          input_id          = 1,                                               &
+          output_file       = output_file,                                     &
+          grid              = palm_grid,                                       &
+          intermediate_grid = palm_intermediate                                &
+       )
+
+       output_var_table(39) = init_nc_var(                                     &
+          name              = 'rad_swd_dir_0',                                 &
+          std_name          = "",                                              &
+          long_name         = "incoming direct shortwave radiative flux at the surface", &
+          units             = "W/m2",                                          &
+          kind              = "surface forcing",                               &
+          input_id          = 1,                                               &
+          output_file       = output_file,                                     &
+          grid              = palm_grid,                                       &
+          intermediate_grid = palm_intermediate                                &
+       )
+
+       output_var_table(40) = init_nc_var(                                     &
+          name              = 'rad_sw_bal_0',                                  &
+          std_name          = "",                                              &
+          long_name         = "shortwave radiation balance at the surface",    &
+          units             = "W/m2",                                          &
+          kind              = "surface forcing",                               &
+          input_id          = 1,                                               &
+          output_file       = output_file,                                     &
+          grid              = palm_grid,                                       &
+          intermediate_grid = palm_intermediate                                &
+       )
+
+       output_var_table(41) = init_nc_var(                                     &
+          name              = 'rad_lw_bal_0',                                  &
+          std_name          = "",                                              &
+          long_name         = "longwave radiation balance at the surface",     &
+          units             = "W/m2",                                          &
+          kind              = "surface forcing",                               &
+          input_id          = 1,                                               &
+          output_file       = output_file,                                     &
+          grid              = palm_grid,                                       &
+          intermediate_grid = palm_intermediate                                &
+       )
+!
+!------------------------------------------------------------------------------
+! Section 2.2: Idealized large-scale forcings
+!------------------------------------------------------------------------------
+       output_var_table(42) = init_nc_var(                                     &
+          name              = 'surface_forcing_surface_pressure',              &
+          std_name          = "",                                              &
+          long_name         = "surface pressure",                              &
+          units             = "Pa",                                            &
+          kind              = "time series",                                   &
+          input_id          = 2,                                               & ! second in (T, p) I/O group
+          output_file       = output_file,                                     &
+          grid              = palm_grid,                                       &
+          intermediate_grid = palm_intermediate                                &
+       )
+       output_var_table(42) % averaging_grid => averaged_scalar_profile
+
+       output_var_table(43) = init_nc_var(                                     &
+          name              = 'ls_forcing_ug',                                 &
+          std_name          = "",                                              &
+          long_name         = "geostrophic wind (u component)",                &
+          units             = "m/s",                                           &
+          kind              = "geostrophic",                                   &
+          input_id          = 1,                                               &
+          output_file       = output_file,                                     &
+          grid              = averaged_scalar_profile,                         &
+          intermediate_grid = averaged_scalar_profile                          &
+       )
+
+       output_var_table(44) = init_nc_var(                                     &
+          name              = 'ls_forcing_vg',                                 &
+          std_name          = "",                                              &
+          long_name         = "geostrophic wind (v component)",                &
+          units             = "m/s",                                           &
+          kind              = "geostrophic",                                   &
+          input_id          = 1,                                               &
+          output_file       = output_file,                                     &
+          grid              = averaged_scalar_profile,                         &
+          intermediate_grid = averaged_scalar_profile                          &
+       )
+
+       output_var_table(45) = init_nc_var(                                     &
+          name              = 'nudging_u',                                     &
+          std_name          = "",                                              &
+          long_name         = "wind component in x direction",                 &
+          units             = "m/s",                                           &
+          kind              = "geostrophic",                                   &
+          input_id          = 1,                                               &
+          output_file       = output_file,                                     &
+          grid              = averaged_scalar_profile,                         &
+          intermediate_grid = averaged_scalar_profile                          &
+       )
+       output_var_table(45) % to_be_processed = ls_forcing_variables_required
+
+       output_var_table(46) = init_nc_var(                                     &
+          name              = 'nudging_v',                                     &
+          std_name          = "",                                              &
+          long_name         = "wind component in y direction",                 &
+          units             = "m/s",                                           &
+          kind              = "large-scale scalar forcing",                    &
+          input_id          = 1,                                               &
+          output_file       = output_file,                                     &
+          grid              = averaged_scalar_profile,                         &
+          intermediate_grid = averaged_scalar_profile                          &
+       )
+       output_var_table(46) % to_be_processed = ls_forcing_variables_required
+
+       output_var_table(47) = init_nc_var(                                     &
+          name              = 'ls_forcing_sub_w',                              &
+          std_name          = "",                                              &
+          long_name         = "subsidence velocity of w",                      &
+          units             = "m/s",                                           &
+          kind              = "large-scale w forcing",                         &
+          input_id          = 1,                                               &
+          output_file       = output_file,                                     &
+          grid              = averaged_scalar_profile,                         &
+          intermediate_grid = averaged_scalar_profile                          &
+       )
+       output_var_table(47) % to_be_processed = ls_forcing_variables_required
+
+       output_var_table(48) = init_nc_var(                                     &
+          name              = 'nudging_w',                                     &
+          std_name          = "",                                              &
+          long_name         = "wind component in w direction",                 &
+          units             = "m/s",                                           &
+          kind              = "large-scale w forcing",                         &
+          input_id          = 1,                                               &
+          output_file       = output_file,                                     &
+          grid              = averaged_w_profile,                              &
+          intermediate_grid = averaged_w_profile                               &
+       )
+       output_var_table(48) % to_be_processed = ls_forcing_variables_required
+
+
+       output_var_table(49) = init_nc_var(                                     &
+          name              = 'ls_forcing_adv_pt',                             &
+          std_name          = "",                                              &
+          long_name         = "advection of potential temperature",            &
+          units             = "K/s",                                           &
+          kind              = "large-scale scalar forcing",                    &
+          input_id          = 1,                                               &
+          output_file       = output_file,                                     &
+          grid              = averaged_scalar_profile,                         &
+          intermediate_grid = averaged_scalar_profile                          &
+       )
+       output_var_table(49) % to_be_processed = ls_forcing_variables_required
+
+       output_var_table(50) = init_nc_var(                                     &
+          name              = 'ls_forcing_sub_pt',                             &
+          std_name          = "",                                              &
+          long_name         = "subsidence velocity of potential temperature",  &
+          units             = "K/s",                                           &
+          kind              = "large-scale scalar forcing",                    &
+          input_id          = 1,                                               &
+          output_file       = output_file,                                     &
+          grid              = averaged_scalar_profile,                         &
+          intermediate_grid = averaged_scalar_profile                          &
+       )
+       output_var_table(50) % to_be_processed = ls_forcing_variables_required
+
+       output_var_table(51) = init_nc_var(                                     &
+          name              = 'nudging_pt',                                    &
+          std_name          = "",                                              &
+          long_name         = "potential temperature",                         &
+          units             = "K",                                             &
+          kind              = "large-scale scalar forcing",                    &
+          input_id          = 1,                                               &
+          output_file       = output_file,                                     &
+          grid              = averaged_scalar_profile,                         &
+          intermediate_grid = averaged_scalar_profile                          &
+       )
+       output_var_table(51) % to_be_processed = ls_forcing_variables_required
+
+       output_var_table(52) = init_nc_var(                                     &
+          name              = 'ls_forcing_adv_qv',                             &
+          std_name          = "",                                              &
+          long_name         = "advection of specific humidity",                &
+          units             = "kg/kg/s",                                       &
+          kind              = "large-scale scalar forcing",                    &
+          input_id          = 3,                                               &
+          output_file       = output_file,                                     &
+          grid              = averaged_scalar_profile,                         &
+          intermediate_grid = averaged_scalar_profile                          &
+       )
+       output_var_table(52) % to_be_processed = ls_forcing_variables_required
+
+
+       output_var_table(53) = init_nc_var(                                     &
+          name              = 'ls_forcing_sub_qv',                             &
+          std_name          = "",                                              &
+          long_name         = "subsidence velocity of specific humidity",      &
+          units             = "kg/kg/s",                                       &
+          kind              = "large-scale scalar forcing",                    &
+          input_id          = 3,                                               &
+          output_file       = output_file,                                     &
+          grid              = averaged_scalar_profile,                         &
+          intermediate_grid = averaged_scalar_profile                          &
+       )
+       output_var_table(53) % to_be_processed = ls_forcing_variables_required
+
+       output_var_table(54) = init_nc_var(                                     &
+          name              = 'nudging_qv',                                    &
+          std_name          = "",                                              &
+          long_name         = "specific humidity",                             &
+          units             = "kg/kg",                                         &
+          kind              = "large-scale scalar forcing",                    &
+          input_id          = 3,                                               &
+          output_file       = output_file,                                     &
+          grid              = averaged_scalar_profile,                         &
+          intermediate_grid = averaged_scalar_profile                          &
+       )
+       output_var_table(54) % to_be_processed = ls_forcing_variables_required
+
+       output_var_table(55) = init_nc_var(                                     &
+          name              = 'nudging_tau',                                   &
+          std_name          = "",                                              &
+          long_name         = "nudging relaxation time scale",                 &
+          units             = "s",                                             &
+          kind              = "constant scalar profile",                       &
+          input_id          = 1,                                               &
+          output_file       = output_file,                                     &
+          grid              = averaged_scalar_profile,                         &
+          intermediate_grid = averaged_scalar_profile                          &
+       )
+       output_var_table(55) % to_be_processed = ls_forcing_variables_required
+
+
+       output_var_table(56) = init_nc_var(                                     &
+          name              = 'internal_density_centre',                              &
+          std_name          = "",                                              &
+          long_name         = "",                                              &
+          units             = "",                                              &
+          kind              = "internal profile",                              &
+          input_id          = 4,                                               &
+          output_file       = output_file,                                     &
+          grid              = averaged_scalar_profile,                         &
+          intermediate_grid = averaged_scalar_profile                          &
+       )
+       output_var_table(56) % averaging_grid => averaged_scalar_profile
+
+
+       output_var_table(57) = init_nc_var(                                     &
+          name              = 'internal_density_north',                       &
+          std_name          = "",                                              &
+          long_name         = "",                                              &
+          units             = "",                                              &
+          kind              = "internal profile",                              &
+          input_id          = 4,                                               &
+          output_file       = output_file,                                     &
+          grid              = north_averaged_scalar_profile,                   &
+          intermediate_grid = north_averaged_scalar_profile                    &
+       )
+       output_var_table(57) % averaging_grid => north_averaged_scalar_profile
+       output_var_table(57) % to_be_processed = .NOT. cfg % ug_is_set
+
+
+       output_var_table(58) = init_nc_var(                                     &
+          name              = 'internal_density_south',                       &
+          std_name          = "",                                              &
+          long_name         = "",                                              &
+          units             = "",                                              &
+          kind              = "internal profile",                              &
+          input_id          = 4,                                               &
+          output_file       = output_file,                                     &
+          grid              = south_averaged_scalar_profile,                   &
+          intermediate_grid = south_averaged_scalar_profile                    &
+       )
+       output_var_table(58) % averaging_grid => south_averaged_scalar_profile
+       output_var_table(58) % to_be_processed = .NOT. cfg % ug_is_set
+
+
+       output_var_table(59) = init_nc_var(                                     &
+          name              = 'internal_density_east',                        &
+          std_name          = "",                                              &
+          long_name         = "",                                              &
+          units             = "",                                              &
+          kind              = "internal profile",                              &
+          input_id          = 4,                                               &
+          output_file       = output_file,                                     &
+          grid              = east_averaged_scalar_profile,                    &
+          intermediate_grid = east_averaged_scalar_profile                     &
+       )
+       output_var_table(59) % averaging_grid => east_averaged_scalar_profile
+       output_var_table(59) % to_be_processed = .NOT. cfg % ug_is_set
+
+
+       output_var_table(60) = init_nc_var(                                     &
+          name              = 'internal_density_west',                        &
+          std_name          = "",                                              &
+          long_name         = "",                                              &
+          units             = "",                                              &
+          kind              = "internal profile",                              &
+          input_id          = 4,                                               &
+          output_file       = output_file,                                     &
+          grid              = west_averaged_scalar_profile,                    &
+          intermediate_grid = west_averaged_scalar_profile                     &
+       )
+       output_var_table(60) % averaging_grid => west_averaged_scalar_profile
+       output_var_table(60) % to_be_processed = .NOT. cfg % ug_is_set
+
+       output_var_table(61) = init_nc_var(                                     &
+          name              = 'internal_pressure_north',                       &
+          std_name          = "",                                              &
+          long_name         = "",                                              &
+          units             = "",                                              &
+          kind              = "internal profile",                              &
+          input_id          = 2,                                               &
+          output_file       = output_file,                                     &
+          grid              = north_averaged_scalar_profile,                   &
+          intermediate_grid = north_averaged_scalar_profile                    &
+       )
+       output_var_table(61) % averaging_grid => north_averaged_scalar_profile
+       output_var_table(61) % to_be_processed = .NOT. cfg % ug_is_set
+
+
+       output_var_table(62) = init_nc_var(                                     &
+          name              = 'internal_pressure_south',                       &
+          std_name          = "",                                              &
+          long_name         = "",                                              &
+          units             = "",                                              &
+          kind              = "internal profile",                              &
+          input_id          = 2,                                               &
+          output_file       = output_file,                                     &
+          grid              = south_averaged_scalar_profile,                   &
+          intermediate_grid = south_averaged_scalar_profile                    &
+       )
+       output_var_table(62) % averaging_grid => south_averaged_scalar_profile
+       output_var_table(62) % to_be_processed = .NOT. cfg % ug_is_set
+
+
+       output_var_table(63) = init_nc_var(                                     &
+          name              = 'internal_pressure_east',                        &
+          std_name          = "",                                              &
+          long_name         = "",                                              &
+          units             = "",                                              &
+          kind              = "internal profile",                              &
+          input_id          = 2,                                               &
+          output_file       = output_file,                                     &
+          grid              = east_averaged_scalar_profile,                    &
+          intermediate_grid = east_averaged_scalar_profile                     &
+       )
+       output_var_table(63) % averaging_grid => east_averaged_scalar_profile
+       output_var_table(63) % to_be_processed = .NOT. cfg % ug_is_set
+
+
+       output_var_table(64) = init_nc_var(                                     &
+          name              = 'internal_pressure_west',                        &
+          std_name          = "",                                              &
+          long_name         = "",                                              &
+          units             = "",                                              &
+          kind              = "internal profile",                              &
+          input_id          = 2,                                               &
+          output_file       = output_file,                                     &
+          grid              = west_averaged_scalar_profile,                    &
+          intermediate_grid = west_averaged_scalar_profile                     &
+       )
+       output_var_table(64) % averaging_grid => west_averaged_scalar_profile
+       output_var_table(64) % to_be_processed = .NOT. cfg % ug_is_set
+
+       ! Attributes shared among all variables
+       output_var_table(:) % source = nc_source_text
+
+
+    END SUBROUTINE setup_variable_tables
+
+
+!------------------------------------------------------------------------------!
+! Description:
+! ------------
+!> Initializes and nc_var varible with the given parameters. The 'kind'
+!> parameter is used to infer the correct netCDF IDs and the level of detail,
+!> 'lod', as defined by the PALM-4U input data standard.
+!------------------------------------------------------------------------------!
+    FUNCTION init_nc_var(name, std_name, long_name, units, kind, input_id,     &
+                         grid, intermediate_grid, output_file, is_profile)     &
+       RESULT(var)
+
+       CHARACTER(LEN=*), INTENT(IN)      ::  name, std_name, long_name, units, kind
+       INTEGER, INTENT(IN)               ::  input_id
+       TYPE(grid_definition), INTENT(IN), TARGET ::  grid, intermediate_grid
+       TYPE(nc_file), INTENT(IN)         ::  output_file
+       LOGICAL, INTENT(IN), OPTIONAL     ::  is_profile
+
+       CHARACTER(LEN=LNAME)              ::  out_var_kind 
+       TYPE(nc_var)                      ::  var
+
+       out_var_kind = TRIM(kind)
+
+       IF (PRESENT(is_profile))  THEN
+          IF (is_profile)  out_var_kind = TRIM(kind) // ' profile'
+       END IF
+
+       var % name              = name
+       var % standard_name     = std_name
+       var % long_name         = long_name
+       var % units             = units
+       var % kind              = TRIM(out_var_kind)
+       var % input_id          = input_id
+       var % nt                = SIZE (output_file % time)
+       var % grid              => grid
+       var % intermediate_grid => intermediate_grid
+
+       SELECT CASE( TRIM(out_var_kind) )
+
+       !TODO: Using global module variables 'init_variables_required' and
+       !TODO: 'boundary_variables_required'. Encapsulate in settings type
+       !TODO: and pass into init_nc_var.
+       CASE( 'init soil' )
+          var % nt              = 1
+          var % lod             = 2
+          var % ndim            = 3
+          var % dimids(1:3)     = output_file % dimids_soil
+          var % dimvarids(1:3)  = output_file % dimvarids_soil
+          var % to_be_processed = init_variables_required
+          var % is_internal     = .FALSE.
+          var % task            = "interpolate_2d"
+
+       CASE( 'init scalar' )
+          var % nt              = 1
+          var % lod             = 2
+          var % ndim            = 3
+          var % dimids(1:3)     = output_file % dimids_scl
+          var % dimvarids(1:3)  = output_file % dimvarids_scl
+          var % to_be_processed = init_variables_required
+          var % is_internal     = .FALSE.
+          var % task            = "interpolate_3d"
+
+       CASE( 'init u' )
+          var % nt              = 1
+          var % lod             = 2
+          var % ndim            = 3
+          var % dimids(1)       = output_file % dimids_vel(1)
+          var % dimids(2)       = output_file % dimids_scl(2)
+          var % dimids(3)       = output_file % dimids_scl(3)
+          var % dimvarids(1)    = output_file % dimvarids_vel(1)
+          var % dimvarids(2)    = output_file % dimvarids_scl(2)
+          var % dimvarids(3)    = output_file % dimvarids_scl(3)
+          var % to_be_processed = init_variables_required
+          var % is_internal     = .FALSE.
+          var % task            = "interpolate_3d"
+
+       CASE( 'init v' )
+          var % nt              = 1
+          var % lod             = 2
+          var % ndim            = 3
+          var % dimids(1)       = output_file % dimids_scl(1)
+          var % dimids(2)       = output_file % dimids_vel(2)
+          var % dimids(3)       = output_file % dimids_scl(3)
+          var % dimvarids(1)    = output_file % dimvarids_scl(1)
+          var % dimvarids(2)    = output_file % dimvarids_vel(2)
+          var % dimvarids(3)    = output_file % dimvarids_scl(3)
+          var % to_be_processed = init_variables_required
+          var % is_internal     = .FALSE.
+          var % task            = "interpolate_3d"
+
+       CASE( 'init w' )
+          var % nt              = 1
+          var % lod             = 2
+          var % ndim            = 3
+          var % dimids(1)       = output_file % dimids_scl(1)
+          var % dimids(2)       = output_file % dimids_scl(2)
+          var % dimids(3)       = output_file % dimids_vel(3)
+          var % dimvarids(1)    = output_file % dimvarids_scl(1)
+          var % dimvarids(2)    = output_file % dimvarids_scl(2)
+          var % dimvarids(3)    = output_file % dimvarids_vel(3)
+          var % to_be_processed = init_variables_required
+          var % is_internal     = .FALSE.
+          var % task            = "interpolate_3d"
+
+       CASE( 'init scalar profile', 'init u profile', 'init v profile')
+          var % nt              = 1
+          var % lod             = 1
+          var % ndim            = 1
+          var % dimids(1)       = output_file % dimids_scl(3)    !z
+          var % dimvarids(1)    = output_file % dimvarids_scl(3) !z
+          var % to_be_processed = init_variables_required
+          var % is_internal     = .FALSE.
+          var % task            = "average profile"
+
+       CASE( 'init w profile')
+          var % nt              = 1
+          var % lod             = 1
+          var % ndim            = 1
+          var % dimids(1)       = output_file % dimids_vel(3)    !z
+          var % dimvarids(1)    = output_file % dimvarids_vel(3) !z
+          var % to_be_processed = init_variables_required
+          var % is_internal     = .FALSE.
+          var % task            = "average profile"
+
+       CASE( 'surface forcing' )
+          var % lod             = -1
+          var % ndim            = 3
+          var % dimids(3)       = output_file % dimid_time
+          var % dimids(1:2)     = output_file % dimids_soil(1:2)
+          var % dimvarids(3)    = output_file % dimvarid_time
+          var % dimvarids(1:2)  = output_file % dimvarids_soil(1:2)
+          var % to_be_processed = boundary_variables_required
+          var % is_internal     = .FALSE.
+          var % task            = "interpolate_2d"
+
+       CASE( 'left scalar', 'right scalar') ! same as right
+          var % lod             = -1
+          var % ndim            = 3
+          var % dimids(3)       = output_file % dimid_time
+          var % dimids(1)       = output_file % dimids_scl(2)
+          var % dimids(2)       = output_file % dimids_scl(3)
+          var % dimvarids(3)    = output_file % dimvarid_time
+          var % dimvarids(1)    = output_file % dimvarids_scl(2)
+          var % dimvarids(2)    = output_file % dimvarids_scl(3)
+          var % to_be_processed = boundary_variables_required
+          var % is_internal     = .FALSE.
+          var % task            = "interpolate_3d"
+
+       CASE( 'north scalar', 'south scalar') ! same as south
+          var % lod             = -1
+          var % ndim            = 3
+          var % dimids(3)       = output_file % dimid_time
+          var % dimids(1)       = output_file % dimids_scl(1)
+          var % dimids(2)       = output_file % dimids_scl(3)
+          var % dimvarids(3)    = output_file % dimvarid_time
+          var % dimvarids(1)    = output_file % dimvarids_scl(1)
+          var % dimvarids(2)    = output_file % dimvarids_scl(3)
+          var % to_be_processed = boundary_variables_required
+          var % is_internal     = .FALSE.
+          var % task            = "interpolate_3d"
+
+       CASE( 'top scalar', 'top w' )
+          var % lod             = -1
+          var % ndim            = 3
+          var % dimids(3)       = output_file % dimid_time
+          var % dimids(1)       = output_file % dimids_scl(1)
+          var % dimids(2)       = output_file % dimids_scl(2)
+          var % dimvarids(3)    = output_file % dimvarid_time
+          var % dimvarids(1)    = output_file % dimvarids_scl(1)
+          var % dimvarids(2)    = output_file % dimvarids_scl(2)
+          var % to_be_processed = boundary_variables_required
+          var % is_internal     = .FALSE.
+          var % task            = "interpolate_3d"
+
+       CASE( 'left u', 'right u' )
+          var % lod             = -1
+          var % ndim            = 3
+          var % dimids(3)       = output_file % dimid_time
+          var % dimids(1)       = output_file % dimids_scl(2)
+          var % dimids(2)       = output_file % dimids_scl(3)
+          var % dimvarids(3)    = output_file % dimvarid_time
+          var % dimvarids(1)    = output_file % dimvarids_scl(2)
+          var % dimvarids(2)    = output_file % dimvarids_scl(3)
+          var % to_be_processed = boundary_variables_required
+          var % is_internal     = .FALSE.
+          var % task            = "interpolate_3d"
+
+       CASE( 'north u', 'south u' )
+          var % lod             = -1
+          var % ndim            = 3
+          var % dimids(3)       = output_file % dimid_time    !t
+          var % dimids(1)       = output_file % dimids_vel(1) !x
+          var % dimids(2)       = output_file % dimids_scl(3) !z
+          var % dimvarids(3)    = output_file % dimvarid_time
+          var % dimvarids(1)    = output_file % dimvarids_vel(1)
+          var % dimvarids(2)    = output_file % dimvarids_scl(3)
+          var % to_be_processed = boundary_variables_required
+          var % is_internal     = .FALSE.
+          var % task            = "interpolate_3d"
+
+       CASE( 'top u' )
+          var % lod             = -1
+          var % ndim            = 3
+          var % dimids(3)       = output_file % dimid_time    !t
+          var % dimids(1)       = output_file % dimids_vel(1) !x
+          var % dimids(2)       = output_file % dimids_scl(2) !z
+          var % dimvarids(3)    = output_file % dimvarid_time
+          var % dimvarids(1)    = output_file % dimvarids_vel(1)
+          var % dimvarids(2)    = output_file % dimvarids_scl(2)
+          var % to_be_processed = boundary_variables_required
+          var % is_internal     = .FALSE.
+          var % task            = "interpolate_3d"
+
+       CASE( 'left v', 'right v' )
+          var % lod             = -1
+          var % ndim            = 3
+          var % dimids(3)       = output_file % dimid_time
+          var % dimids(1)       = output_file % dimids_vel(2)
+          var % dimids(2)       = output_file % dimids_scl(3)
+          var % dimvarids(3)    = output_file % dimvarid_time
+          var % dimvarids(1)    = output_file % dimvarids_vel(2)
+          var % dimvarids(2)    = output_file % dimvarids_scl(3)
+          var % to_be_processed = boundary_variables_required
+          var % is_internal     = .FALSE.
+          var % task            = "interpolate_3d"
+
+       CASE( 'north v', 'south v' )
+          var % lod             = -1
+          var % ndim            = 3
+          var % dimids(3)       = output_file % dimid_time    !t
+          var % dimids(1)       = output_file % dimids_scl(1) !x
+          var % dimids(2)       = output_file % dimids_scl(3) !z
+          var % dimvarids(3)    = output_file % dimvarid_time
+          var % dimvarids(1)    = output_file % dimvarids_scl(1)
+          var % dimvarids(2)    = output_file % dimvarids_scl(3)
+          var % to_be_processed = boundary_variables_required
+          var % is_internal     = .FALSE.
+          var % task            = "interpolate_3d"
+
+       CASE( 'top v' )
+          var % lod             = -1
+          var % ndim            = 3
+          var % dimids(3)       = output_file % dimid_time    !t
+          var % dimids(1)       = output_file % dimids_scl(1) !x
+          var % dimids(2)       = output_file % dimids_vel(2) !z
+          var % dimvarids(3)    = output_file % dimvarid_time
+          var % dimvarids(1)    = output_file % dimvarids_scl(1)
+          var % dimvarids(2)    = output_file % dimvarids_vel(2)
+          var % to_be_processed = boundary_variables_required
+          var % is_internal     = .FALSE.
+          var % task            = "interpolate_3d"
+
+       CASE( 'left w', 'right w')
+          var % lod             = -1
+          var % ndim            = 3
+          var % dimids(3)       = output_file % dimid_time
+          var % dimids(1)       = output_file % dimids_scl(2)
+          var % dimids(2)       = output_file % dimids_vel(3)
+          var % dimvarids(3)    = output_file % dimvarid_time
+          var % dimvarids(1)    = output_file % dimvarids_scl(2)
+          var % dimvarids(2)    = output_file % dimvarids_vel(3)
+          var % to_be_processed = boundary_variables_required
+          var % is_internal     = .FALSE.
+          var % task            = "interpolate_3d"
+
+       CASE( 'north w', 'south w' )
+          var % lod             = -1
+          var % ndim            = 3
+          var % dimids(3)       = output_file % dimid_time    !t
+          var % dimids(1)       = output_file % dimids_scl(1) !x
+          var % dimids(2)       = output_file % dimids_vel(3) !z
+          var % dimvarids(3)    = output_file % dimvarid_time
+          var % dimvarids(1)    = output_file % dimvarids_scl(1)
+          var % dimvarids(2)    = output_file % dimvarids_vel(3)
+          var % to_be_processed = boundary_variables_required
+          var % is_internal     = .FALSE.
+          var % task            = "interpolate_3d"
+
+       CASE( 'time series' )
+          var % lod             = 0
+          var % ndim            = 1
+          var % dimids(1)       = output_file % dimid_time    !t
+          var % dimvarids(1)    = output_file % dimvarid_time
+          var % to_be_processed = .TRUE.
+          var % is_internal     = .FALSE.
+          var % task            = "average profile"
+
+       CASE( 'constant scalar profile' )
+          var % lod             = -1
+          var % ndim            = 2
+          var % dimids(2)       = output_file % dimid_time    !t
+          var % dimids(1)       = output_file % dimids_scl(3) !z
+          var % dimvarids(2)    = output_file % dimvarid_time
+          var % dimvarids(1)    = output_file % dimvarids_scl(3)
+          var % to_be_processed = .TRUE.
+          var % is_internal     = .FALSE.
+          var % task            = "set profile"
+
+       CASE( 'large-scale scalar forcing' )
+          var % lod             = -1
+          var % ndim            = 2
+          var % dimids(2)       = output_file % dimid_time    !t
+          var % dimids(1)       = output_file % dimids_scl(3) !z
+          var % dimvarids(2)    = output_file % dimvarid_time
+          var % dimvarids(1)    = output_file % dimvarids_scl(3)
+          var % to_be_processed = ls_forcing_variables_required
+          var % is_internal     = .FALSE.
+          var % task            = "average large-scale profile"
+
+       CASE( 'geostrophic' )
+          var % lod             = -1
+          var % ndim            = 2
+          var % dimids(2)       = output_file % dimid_time    !t
+          var % dimids(1)       = output_file % dimids_scl(3) !z
+          var % dimvarids(2)    = output_file % dimvarid_time
+          var % dimvarids(1)    = output_file % dimvarids_scl(3)
+          var % to_be_processed = .TRUE.
+          var % is_internal     = .FALSE.
+          var % task            = "geostrophic winds"
+
+       CASE( 'large-scale w forcing' )
+          var % lod             = -1
+          var % ndim            = 2
+          var % dimids(2)       = output_file % dimid_time    !t
+          var % dimids(1)       = output_file % dimids_vel(3) !z
+          var % dimvarids(2)    = output_file % dimvarid_time
+          var % dimvarids(1)    = output_file % dimvarids_vel(3)
+          var % to_be_processed = ls_forcing_variables_required
+          var % is_internal     = .FALSE.
+          var % task            = "average large-scale profile"
+
+       CASE( 'internal profile' )
+          var % lod             = -1
+          var % ndim            = 2
+          var % dimids(2)       = output_file % dimid_time    !t
+          var % dimids(1)       = output_file % dimids_scl(3) !z
+          var % dimvarids(2)    = output_file % dimvarid_time
+          var % dimvarids(1)    = output_file % dimvarids_scl(3)
+          var % to_be_processed = .TRUE.
+          var % is_internal     = .TRUE.
+          var % task            = "internal profile"
+
+       CASE DEFAULT
+           message = "Variable kind '" // TRIM(kind) // "' not recognized."
+           CALL abort ('init_nc_var', message)
+
+       END SELECT
+
+    END FUNCTION init_nc_var
+
+
+    SUBROUTINE fini_variables()
+
+       CALL report('fini_variables', 'Deallocating variable table', cfg % debug)
+       DEALLOCATE( input_var_table )
+
+    END SUBROUTINE fini_variables
+
+
+    SUBROUTINE fini_io_groups()
+
+       CALL report('fini_io_groups', 'Deallocating IO groups', cfg % debug)
+       DEALLOCATE( io_group_list )
+
+    END SUBROUTINE fini_io_groups
+
+
+    SUBROUTINE fini_file_lists()
+       
+       CALL report('fini_file_lists', 'Deallocating file lists', cfg % debug)
+       DEALLOCATE( flow_files, soil_files, radiation_files, soil_moisture_files )
+
+    END SUBROUTINE fini_file_lists
+
+
+    SUBROUTINE get_input_file_list(start_date_string, start_hour, end_hour,        &
+                                   step_hour, path, prefix, suffix, file_list)
+
+       CHARACTER (LEN=DATE), INTENT(IN) ::  start_date_string
+       CHARACTER (LEN=*),    INTENT(IN) ::  prefix, suffix, path
+       INTEGER,              INTENT(IN) ::  start_hour, end_hour, step_hour
+       CHARACTER(LEN=*), ALLOCATABLE, INTENT(INOUT) ::  file_list(:)
+
+       INTEGER             ::  number_of_intervals, hour, i
+       CHARACTER(LEN=DATE) ::  date_string
+
+       number_of_intervals = CEILING( REAL(end_hour - start_hour) / step_hour )
+       ALLOCATE( file_list(number_of_intervals + 1) )
+
+       DO i = 0, number_of_intervals
+          hour = start_hour + i * step_hour
+          date_string = add_hours_to(start_date_string, hour)
+
+          file_list(i+1) = TRIM(path) // TRIM(prefix) // TRIM(date_string) //    &
+                           TRIM(suffix) // '.nc'
+          message = "Set up input file name '" // TRIM(file_list(i+1)) //"'"
+          CALL report('input_file_list', message)
+       END DO
+
+    END SUBROUTINE get_input_file_list
+
+
+!------------------------------------------------------------------------------!
+! Description:
+! ------------
+!> Carries out any physical conversion of the quantities in the given input
+!> buffer needed to obtain the quantity required by PALM-4U. For instance, 
+!> velocities are rotated to the PALM-4U coordinate system and the potential
+!> temperature is computed from the absolute temperature and pressure.
+!>
+!> Note, that the preprocessing does not include any grid change. The result
+!> array will match a COSMO-DE scalar array.
+!------------------------------------------------------------------------------!
+    SUBROUTINE preprocess(group, input_buffer, cosmo_grid, iter)
+
+       TYPE(io_group), INTENT(INOUT), TARGET       ::  group
+       TYPE(container), INTENT(INOUT), ALLOCATABLE ::  input_buffer(:)
+       TYPE(grid_definition), INTENT(IN)           ::  cosmo_grid
+       INTEGER, INTENT(IN)                         ::  iter
+       
+       REAL(dp), ALLOCATABLE                       ::  basic_state_pressure(:)
+       TYPE(container), ALLOCATABLE                ::  preprocess_buffer(:)
+       INTEGER                                     ::  hour, dt
+       INTEGER                                     ::  i, j, k
+       INTEGER                                     ::  nx, ny, nz
+       
+       input_buffer(:) % is_preprocessed = .FALSE.
+        
+       SELECT CASE( group % kind )
+       
+       CASE( 'velocities' )
+          ! Allocate a compute buffer with the same number of arrays as the input
+          ALLOCATE( preprocess_buffer( SIZE(input_buffer) ) )
+
+          ! Allocate u and v arrays with scalar dimensions
+          nx = SIZE(input_buffer(1) % array, 1)
+          ny = SIZE(input_buffer(1) % array, 2)
+          nz = SIZE(input_buffer(1) % array, 3)
+          ALLOCATE( preprocess_buffer(1) % array(nx, ny, nz) ) ! u buffer
+          ALLOCATE( preprocess_buffer(2) % array(nx, ny, nz) ) ! v buffer
+
+ CALL run_control('time', 'alloc')
+
+          ! interpolate U and V to centres
+          CALL centre_velocities( u_face = input_buffer(1) % array,            &
+                                  v_face = input_buffer(2) % array,            &
+                                  u_centre = preprocess_buffer(1) % array,     &
+                                  v_centre = preprocess_buffer(2) % array )
+          
+          cfg % rotation_method = 'rotated-pole'
+          SELECT CASE(cfg % rotation_method)
+
+          CASE('rotated-pole')
+             ! rotate U and V to PALM-4U orientation and overwrite U and V with
+             ! rotated velocities
+             DO k = 1, nz
+             DO j = 1, ny
+             DO i = 1, nx
+                CALL uv2uvrot( urot = preprocess_buffer(1) % array(i,j,k),     &
+                               vrot = preprocess_buffer(2) % array(i,j,k),     &
+                               rlat = cosmo_grid % lat(j-1),                   &
+                               rlon = cosmo_grid % lon(i-1),                   &
+                               pollat = phi_cn,                                &
+                               pollon = lambda_cn,                             &
+                               u = input_buffer(1) % array(i,j,k),             &
+                               v = input_buffer(2) % array(i,j,k) )
+             END DO
+             END DO
+             END DO
+
+          CASE DEFAULT
+             message = "Rotation method '" // TRIM(cfg % rotation_method) //   &
+                "' not recognized."
+             CALL abort('preprocess', message)
+
+          END SELECT
+
+          ! set values 
+          input_buffer(1) % array(1,:,:) = 0.0_dp
+          input_buffer(2) % array(1,:,:) = 0.0_dp
+          input_buffer(1) % array(:,1,:) = 0.0_dp
+          input_buffer(2) % array(:,1,:) = 0.0_dp
+
+          input_buffer(1:2) % is_preprocessed = .TRUE.
+ CALL run_control('time', 'comp')
+
+          DEALLOCATE( preprocess_buffer )
+ CALL run_control('time', 'alloc')
+
+          message = "Input buffers for group '" // TRIM(group % kind) // "'"//&
+             " preprocessed sucessfully."
+          CALL report('preprocess', message)
+       
+       CASE( 'thermodynamics' ) ! T, P, QV
+          nx = SIZE(input_buffer(1) % array, 1)
+          ny = SIZE(input_buffer(1) % array, 2)
+          nz = SIZE(input_buffer(1) % array, 3)
+
+          ! Compute absolute pressure if presure perturbation has been read in.
+          IF ( TRIM(group % in_var_list(2) % name) == 'PP' )  THEN
+             message = "Absolute pressure, P, not available, " //              &
+                       "computing from pressure preturbation PP."
+             CALL report('preprocess', message)
+
+             ALLOCATE( basic_state_pressure(1:nz) )
+ CALL run_control('time', 'alloc')
+
+             DO j = 1, ny
+             DO i = 1, nx
+
+                CALL get_basic_state(cosmo_grid % hfl(i,j,:), BETA, P_SL, T_SL,&
+                                     RD, G, basic_state_pressure)
+
+                input_buffer (2) % array(i,j,:) =                              &
+                   HECTO * input_buffer (2) % array(i,j,:) +                   &
+                   basic_state_pressure(:)
+
+             END DO
+             END DO
+ CALL run_control('time', 'comp')
+
+             DEALLOCATE( basic_state_pressure )
+ CALL run_control('time', 'alloc')
+
+             group % in_var_list(2) % name = 'P'
+
+          END IF
+          ! pressure
+          input_buffer(2) % is_preprocessed = .TRUE.
+
+          ! Copy temperature to last input buffer array
+          ALLOCATE(                                                            &
+              input_buffer( group % n_output_quantities ) % array (nx, ny, nz) &
+          )
+          input_buffer(group % n_output_quantities) % array(:,:,:) =           &
+              input_buffer(1) % array(:,:,:)
+
+          ! Convert absolute to potential temperature
+          CALL potential_temperature(                                          &
+             t = input_buffer(1) % array(:,:,:),                               &
+             p = input_buffer(2) % array(:,:,:),                               &
+             p_ref = P_REF,                                                    &
+             r = RD_PALM,                                                      &
+             cp = CP_PALM                                                      &
+          )
+
+          ! potential temperature
+          input_buffer(1) % is_preprocessed = .TRUE.
+
+          ! Convert temperature copy to density
+          CALL moist_density(                                                  &
+             t_rho = input_buffer(group % n_output_quantities) % array(:,:,:), &
+             p = input_buffer(2) % array(:,:,:),                               &
+             qv = input_buffer(3) % array(:,:,:),                              &
+             rd = RD,                                                          &
+             rv = RV                                                           &
+          )
+
+          ! qv
+          input_buffer(3) % is_preprocessed = .TRUE.
+
+          ! density
+          input_buffer(group % n_output_quantities) % is_preprocessed = .TRUE.
+
+
+          message = "Input buffers for group '" // TRIM(group % kind) // "'"//&
+             " preprocessed sucessfully."
+          CALL report('preprocess', message)
+ CALL run_control('time', 'comp')
+       
+       CASE( 'scalar' ) ! S or W
+          input_buffer(:) % is_preprocessed = .TRUE.
+ CALL run_control('time', 'comp')
+
+       CASE( 'soil-temperature' ) ! 
+          
+          CALL fill_water_cells(soiltyp, input_buffer(1) % array, &
+                                SIZE(input_buffer(1) % array, 3), &
+                                FILL_ITERATIONS)
+          input_buffer(:) % is_preprocessed = .TRUE.
+ CALL run_control('time', 'comp')
+
+       CASE( 'soil-water' ) ! 
+
+          CALL fill_water_cells(soiltyp, input_buffer(1) % array, &
+                                SIZE(input_buffer(1) % array, 3), &
+                                FILL_ITERATIONS)
+
+          nx = SIZE(input_buffer(1) % array, 1)
+          ny = SIZE(input_buffer(1) % array, 2)
+          nz = SIZE(input_buffer(1) % array, 3)
+
+          DO k = 1, nz
+          DO j = 1, ny
+          DO i = 1, nx
+             input_buffer(1) % array(i,j,k) =                                  &
+                 input_buffer(1) % array(i,j,k) * d_depth_rho_inv(k)
+          END DO
+          END DO
+          END DO
+
+          message = "Converted soil water from [kg/m^2] to [m^3/m^3]"
+          CALL report('preprocess', message)
+
+          input_buffer(:) % is_preprocessed = .TRUE.
+ CALL run_control('time', 'comp')
+
+       CASE( 'surface' ) ! 
+          input_buffer(:) % is_preprocessed = .TRUE.
+ CALL run_control('time', 'comp')
+
+       CASE( 'accumulated' ) ! 
+          message = "De-accumulating '" // TRIM(group % in_var_list(1) % name) //&
+                    "' in iteration " // TRIM(str(iter)) 
+          CALL report('preprocess', message)
+
+          hour = iter - 1
+          dt = MODULO(hour, 3) + 1 ! averaging period
+          SELECT CASE(dt)
+
+          CASE(1)
+             !input has been accumulated over one hour. Leave as is
+             !input_buffer(1) % array(:,:,:) carrries one-hour integral
+
+          CASE(2)
+             !input has been accumulated over two hours. Subtract previous step
+             !input_buffer(1) % array(:,:,:) carrries one-hour integral
+             !input_buffer(2) % array(:,:,:) carrries two-hour integral
+             CALL deaverage(                                                   &
+                      avg_1 = input_buffer(1) % array(:,:,:), t1 = 1.0_dp,     &
+                      avg_2 = input_buffer(2) % array(:,:,:), t2 = 1.0_dp,     &
+                      avg_3 = input_buffer(1) % array(:,:,:), t3 = 1.0_dp )
+             !input_buffer(1) % array(:,:,:) carrries one-hour integral of second hour
+
+          CASE(3)
+             !input has been accumulated over three hours. Subtract previous step
+             !input_buffer(1) % array(:,:,:) carrries three-hour integral
+             !input_buffer(2) % array(:,:,:) still carrries two-hour integral
+             CALL deaverage(                                                   &
+                     avg_1 = input_buffer(2) % array(:,:,:), t1 = 1.0_dp,      &
+                     avg_2 = input_buffer(1) % array(:,:,:), t2 = 1.0_dp,      &
+                     avg_3 = input_buffer(1) % array(:,:,:), t3 = 1.0_dp )
+             !input_buffer(1) % array(:,:,:) carrries one-hour integral of third hourA
+
+          CASE DEFAULT
+             message = "Invalid averaging period '" // TRIM(str(dt)) // " hours"
+             CALL abort('preprocess', message)
+
+          END SELECT
+          input_buffer(:) % is_preprocessed = .TRUE.
+ CALL run_control('time', 'comp')
+
+       CASE( 'running average' ) ! 
+          message = "De-averaging '" // TRIM(group % in_var_list(1) % name) //   &
+                    "' in iteration " // TRIM(str(iter)) 
+          CALL report('preprocess', message)
+
+          hour = iter - 1
+          dt = MODULO(hour, 3) + 1 ! averaging period
+          SELECT CASE(dt)
+
+          CASE(1)
+             !input has been accumulated over one hour. Leave as is
+             !input_buffer(1) % array(:,:,:) carrries one-hour integral
+
+          CASE(2)
+             !input has been accumulated over two hours. Subtract previous step
+             !input_buffer(1) % array(:,:,:) carrries one-hour integral
+             !input_buffer(2) % array(:,:,:) carrries two-hour integral
+             CALL deaverage( input_buffer(1) % array(:,:,:), 1.0_dp,           &
+                             input_buffer(2) % array(:,:,:), 2.0_dp,           &
+                             input_buffer(1) % array(:,:,:), 1.0_dp)
+             !input_buffer(1) % array(:,:,:) carrries one-hour integral of second hour
+
+          CASE(3)
+             !input has been accumulated over three hours. Subtract previous step
+             !input_buffer(1) % array(:,:,:) carrries three-hour integral
+             !input_buffer(2) % array(:,:,:) still carrries two-hour integral
+             CALL deaverage( input_buffer(2) % array(:,:,:), 2.0_dp,           &
+                             input_buffer(1) % array(:,:,:), 3.0_dp,           &
+                             input_buffer(1) % array(:,:,:), 1.0_dp)
+             !input_buffer(1) % array(:,:,:) carrries one-hour integral of third hourA
+
+          CASE DEFAULT
+             message = "Invalid averaging period '" // TRIM(str(dt)) // " hours"
+             CALL abort('preprocess', message)
+
+          END SELECT
+          input_buffer(:) % is_preprocessed = .TRUE.
+
+       CASE DEFAULT
+          message = "IO group kind '" // TRIM(group % kind) // "' is not supported."
+          CALL abort('prerpocess', message)
+
+       END SELECT
+ CALL run_control('time', 'comp')
+
+    END SUBROUTINE preprocess
+
+
+! Description:
+! ------------
+!> Computes average soil values in COSMO-DE water cells from neighbouring
+!> non-water cells. This is done as a preprocessing step for the COSMO-DE
+!> soil input arrays, which contain unphysical values for water cells.
+!>
+!> This routine computes the average of up to all nine neighbouring cells
+!> or keeps the original value, if not at least one non-water neightbour
+!> is available.
+!>
+!> By repeatedly applying this step, soil data can be extrapolated into
+!> 'water' regions occupying multiple cells, one cell per iteration.
+!> 
+!> Input parameters:
+!> -----------------
+!> soiltyp : 2d map of COSMO-DE soil types
+!> nz : number of layers in the COSMO-DE soil
+!> niter : number iterations
+!> 
+!> Output parameters:
+!> ------------------
+!> array : the soil array (i.e. water content or temperature)
+!------------------------------------------------------------------------------!
+    SUBROUTINE fill_water_cells(soiltyp, array, nz, niter)
+       INTEGER(hp), DIMENSION(:,:,:), INTENT(IN) :: soiltyp
+       REAL(dp), DIMENSION(:,:,:), INTENT(INOUT) :: array
+       INTEGER, INTENT(IN)                       :: nz, niter
+
+       REAL(dp), DIMENSION(nz)                   :: column
+       INTEGER(hp), DIMENSION(:,:), ALLOCATABLE  :: old_soiltyp, new_soiltyp
+       INTEGER                                   :: l, i, j, nx, ny, n_cells, ii, jj, iter
+       INTEGER, DIMENSION(8)                     :: di, dj
+
+       nx = SIZE(array, 1)
+       ny = SIZE(array, 2)
+       di = (/ -1, -1, -1, 0,  0,  1, 1, 1 /)
+       dj = (/ -1,  0,  1, -1, 1, -1, 0, 1 /)
+
+       ALLOCATE(old_soiltyp(SIZE(soiltyp,1), &
+                            SIZE(soiltyp,2) ))
+
+       ALLOCATE(new_soiltyp(SIZE(soiltyp,1), &
+                            SIZE(soiltyp,2) ))
+
+       old_soiltyp(:,:) = soiltyp(:,:,1)
+       new_soiltyp(:,:) = soiltyp(:,:,1)
+
+       DO iter = 1, niter
+
+          DO j = 1, ny
+          DO i = 1, nx
+          
+             IF (old_soiltyp(i,j) == WATER_ID)  THEN 
+
+                n_cells = 0
+                column(:) = 0.0_dp
+                DO l = 1, SIZE(di)
+
+                   ii = MIN(nx, MAX(1, i + di(l)))
+                   jj = MIN(ny, MAX(1, j + dj(l)))
+
+                   IF (old_soiltyp(ii,jj) .NE. WATER_ID)  THEN
+                      n_cells = n_cells + 1
+                      column(:) = column(:) + array(ii,jj,:)
+                   END IF
+
+                END DO
+
+                ! Overwrite if at least one non-water neighbour cell is available
+                IF (n_cells > 0)  THEN
+                   array(i,j,:) = column(:) / n_cells
+                   new_soiltyp(i,j) = 0
+                END IF
+
+             END IF
+
+          END DO
+          END DO
+
+          old_soiltyp(:,:) = new_soiltyp(:,:)
+
+       END DO
+
+       DEALLOCATE(old_soiltyp, new_soiltyp)
+
+    END SUBROUTINE fill_water_cells
+
+ END MODULE grid
Index: palm/trunk/UTIL/inifor/src/inifor_io.f90
===================================================================
--- palm/trunk/UTIL/inifor/src/inifor_io.f90	(revision 3447)
+++ palm/trunk/UTIL/inifor/src/inifor_io.f90	(revision 3447)
@@ -0,0 +1,1087 @@
+!> @file src/inifor_io.f90
+!------------------------------------------------------------------------------!
+! This file is part of the PALM model system.
+!
+! PALM is free software: you can redistribute it and/or modify it under the
+! terms of the GNU General Public License as published by the Free Software
+! Foundation, either version 3 of the License, or (at your option) any later
+! version.
+!
+! PALM is distributed in the hope that it will be useful, but WITHOUT ANY
+! WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+! A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+!
+! You should have received a copy of the GNU General Public License along with
+! PALM. If not, see <http://www.gnu.org/licenses/>.
+!
+! Copyright 2017-2018 Leibniz Universitaet Hannover
+! Copyright 2017-2018 Deutscher Wetterdienst Offenbach
+!------------------------------------------------------------------------------!
+!
+! Current revisions:
+! -----------------
+! 
+! 
+! Former revisions:
+! -----------------
+! $Id$
+! Removed INCLUDE statement for get_netcdf_variable()
+! Renamed source files for compatibilty with PALM build system
+! 
+! 
+! 3395 2018-10-22 17:32:49Z eckhard
+! Added command-line options for configuring the computation of geostrophic
+!     winds (--averagin-mode, --averaging-angle)
+! Added command-line option --input-prefix for setting input file prefixes all
+!     at once
+! Added --debug option for more verbose terminal output
+! Added option-specific *_is_set LOGICALs to indicate invocation from the
+!     command-line 
+! Improved error messages in case of empty file-name strings
+! Improved routine naming
+! 
+! 3183 2018-07-27 14:25:55Z suehring
+! Introduced new PALM grid stretching
+! Updated variable names and metadata for PIDS v1.9 compatibility
+! Improved handling of the start date string
+! Better compatibility with older Intel compilers:
+! - avoiding implicit array allocation with new get_netcdf_variable()
+!   subroutine instead of function
+! Improved command line interface:
+! - Added configuration validation
+! - New options to configure input file prefixes
+! - GNU-style short and long option names
+! - Added version and copyright output
+! 
+!
+! 3182 2018-07-27 13:36:03Z suehring
+! Initial revision
+!
+! 
+!
+! Authors:
+! --------
+! @author Eckhard Kadasch
+!
+! Description:
+! ------------
+!> The io module contains the functions needed to read and write netCDF data in
+!> INIFOR.
+!------------------------------------------------------------------------------!
+ MODULE io
+
+    USE control
+    USE defs,                                                                  &
+        ONLY:  DATE, SNAME, PATH, PI, dp, hp, TO_RADIANS, TO_DEGREES, VERSION
+    USE netcdf
+    USE types
+    USE util,                                                                  &
+        ONLY:  reverse, str, real_to_str
+
+    IMPLICIT NONE
+
+    INTERFACE get_netcdf_variable
+        MODULE PROCEDURE get_netcdf_variable_int
+        MODULE PROCEDURE get_netcdf_variable_real
+    END INTERFACE get_netcdf_variable
+
+    PRIVATE ::  get_netcdf_variable_int, get_netcdf_variable_real
+
+ CONTAINS
+
+    SUBROUTINE get_netcdf_variable_int(in_file, in_var, buffer)
+
+       CHARACTER(LEN=PATH), INTENT(IN)         ::  in_file
+       TYPE(nc_var), INTENT(INOUT)             ::  in_var
+       INTEGER(hp), ALLOCATABLE, INTENT(INOUT) ::  buffer(:,:,:)
+
+       INTEGER               ::  ncid
+       INTEGER, DIMENSION(3) ::  start, count
+
+       IF ( nf90_open( TRIM(in_file), NF90_NOWRITE, ncid ) .EQ. NF90_NOERR .AND. &
+            nf90_inq_varid( ncid, in_var % name, in_var % varid ) .EQ. NF90_NOERR )  THEN
+
+          CALL get_input_dimensions(in_var, ncid)
+
+          CALL get_netcdf_start_and_count(in_var, start, count)
+ CALL run_control('time', 'read')
+
+          ALLOCATE( buffer( count(1), count(2), count(3) ) )
+ CALL run_control('time', 'alloc')
+
+          CALL check(nf90_get_var( ncid, in_var % varid, buffer,                  &
+                                   start = start,                                 &
+                                   count = count ))
+
+       ELSE
+
+          message = "Failed to read '" // TRIM(in_var % name) // &
+             "' from file '" // TRIM(in_file) // "'."
+          CALL abort('get_netcdf_variable', message)
+
+       END IF
+
+       CALL check(nf90_close(ncid))
+ CALL run_control('time', 'read')
+
+    END SUBROUTINE get_netcdf_variable_int
+
+
+    SUBROUTINE get_netcdf_variable_real(in_file, in_var, buffer)
+
+       CHARACTER(LEN=PATH), INTENT(IN)      ::  in_file
+       TYPE(nc_var), INTENT(INOUT)          ::  in_var
+       REAL(dp), ALLOCATABLE, INTENT(INOUT) ::  buffer(:,:,:)
+
+       INTEGER               ::  ncid
+       INTEGER, DIMENSION(3) ::  start, count
+
+       IF ( nf90_open( TRIM(in_file), NF90_NOWRITE, ncid ) .EQ. NF90_NOERR .AND. &
+            nf90_inq_varid( ncid, in_var % name, in_var % varid ) .EQ. NF90_NOERR )  THEN
+
+          CALL get_input_dimensions(in_var, ncid)
+
+          CALL get_netcdf_start_and_count(in_var, start, count)
+ CALL run_control('time', 'read')
+
+          ALLOCATE( buffer( count(1), count(2), count(3) ) )
+ CALL run_control('time', 'alloc')
+
+          CALL check(nf90_get_var( ncid, in_var % varid, buffer,                  &
+                                   start = start,                                 &
+                                   count = count ))
+
+       ELSE
+
+          message = "Failed to read '" // TRIM(in_var % name) // &
+             "' from file '" // TRIM(in_file) // "'."
+          CALL abort('get_netcdf_variable', message)
+
+       END IF
+
+       CALL check(nf90_close(ncid))
+ CALL run_control('time', 'read')
+
+    END SUBROUTINE get_netcdf_variable_real
+
+
+    SUBROUTINE get_input_dimensions(in_var, ncid)
+
+       TYPE(nc_var), INTENT(INOUT)     ::  in_var
+       INTEGER, INTENT(OUT)            ::  ncid
+
+       INTEGER ::  i
+
+       CALL check(nf90_get_att( ncid, in_var % varid, "long_name",             &
+                                in_var % long_name))
+
+       CALL check(nf90_get_att( ncid, in_var % varid, "units",                 &
+                                in_var % units ))
+
+       CALL check(nf90_inquire_variable( ncid, in_var % varid,                 &
+                                         ndims  = in_var % ndim,               &
+                                         dimids = in_var % dimids ))
+
+       DO i = 1, in_var % ndim
+          CALL check(nf90_inquire_dimension( ncid, in_var % dimids(i),         &
+                                             name = in_var % dimname(i),       &
+                                             len  = in_var % dimlen(i) ))
+       END DO
+
+    END SUBROUTINE get_input_dimensions
+
+
+    SUBROUTINE get_netcdf_start_and_count(in_var, start, count)
+
+       TYPE(nc_var), INTENT(INOUT)        ::  in_var
+       INTEGER, DIMENSION(3), INTENT(OUT) ::  start, count
+
+       INTEGER ::  ndim
+
+       IF ( in_var % ndim .LT. 2  .OR.  in_var % ndim .GT. 4 )  THEN
+
+          message = "Failed reading NetCDF variable " //                       &
+             TRIM(in_var % name) // " with " // TRIM(str(in_var%ndim)) //      &
+             " dimensions because only two- and and three-dimensional" //      &
+             " variables are supported."
+          CALL abort('get_netcdf_start_and_count', message)
+
+       END IF
+
+       start = (/ 1, 1, 1 /)
+       IF ( TRIM(in_var % name) .EQ. 'T_SO' )  THEN
+          ! Skip depth = 0.0 for T_SO and reduce number of depths from 9 to 8
+          in_var % dimlen(3) = in_var % dimlen(3) - 1
+
+          ! Start reading from second level, e.g. depth = 0.005 instead of 0.0
+          start(3) = 2
+       END IF
+
+       IF (in_var % ndim .EQ. 2)  THEN
+          in_var % dimlen(3) = 1
+       ENDIF
+
+       ndim = MIN(in_var % ndim, 3)
+       count = (/ 1, 1, 1 /)
+       count(1:ndim) = in_var % dimlen(1:ndim)
+
+    END SUBROUTINE get_netcdf_start_and_count
+
+
+    SUBROUTINE netcdf_define_variable(var, ncid)
+
+        TYPE(nc_var), INTENT(INOUT) ::  var
+        INTEGER, INTENT(IN)         ::  ncid
+
+        CALL check(nf90_def_var(ncid, var % name, NF90_FLOAT,       var % dimids(1:var % ndim), var % varid))
+        CALL check(nf90_put_att(ncid, var % varid, "long_name",     var % long_name))
+        CALL check(nf90_put_att(ncid, var % varid, "units",         var % units))
+        IF ( var % lod .GE. 0 )  THEN
+           CALL check(nf90_put_att(ncid, var % varid, "lod",           var % lod))
+        END IF 
+        CALL check(nf90_put_att(ncid, var % varid, "source",        var % source))
+        CALL check(nf90_put_att(ncid, var % varid, "_FillValue",    NF90_FILL_REAL))
+
+    END SUBROUTINE netcdf_define_variable
+    
+
+    SUBROUTINE netcdf_get_dimensions(var, ncid)
+
+        TYPE(nc_var), INTENT(INOUT) ::  var
+        INTEGER, INTENT(IN)         ::  ncid
+        INTEGER                     ::  i
+        CHARACTER(SNAME)            ::  null
+
+        ! Remember dimension lenghts for NetCDF writing routine
+        DO i = 1, var % ndim
+           CALL check(nf90_inquire_dimension(ncid, var % dimids(i), &
+                                             name = null, &
+                                             len  = var % dimlen(i)  ) )
+        END DO
+
+    END SUBROUTINE netcdf_get_dimensions
+
+
+!------------------------------------------------------------------------------!
+! Description:
+! ------------
+!> This routine initializes Inifor. This includes parsing command-line
+!> arguments, setting the names of the input and output file names as well as
+!> the name of the input namelist and, subsequently, reading in and setting grid
+!> parameters for the PALM-4U computational grid.
+!------------------------------------------------------------------------------!
+    SUBROUTINE parse_command_line_arguments( cfg )
+
+       TYPE(inifor_config), INTENT(INOUT) ::  cfg
+
+       CHARACTER(LEN=PATH)                ::  option, arg
+       INTEGER                            ::  arg_count, i
+
+       cfg % p0_is_set = .FALSE.
+       cfg % ug_is_set = .FALSE.
+       cfg % vg_is_set = .FALSE.
+       cfg % flow_prefix_is_set = .FALSE.
+       cfg % input_prefix_is_set = .FALSE.
+       cfg % radiation_prefix_is_set = .FALSE.
+       cfg % soil_prefix_is_set = .FALSE.
+       cfg % soilmoisture_prefix_is_set = .FALSE.
+
+       arg_count = COMMAND_ARGUMENT_COUNT()
+       IF (arg_count .GT. 0)  THEN
+
+          ! Every option should have an argument.
+          !IF ( MOD(arg_count, 2) .NE. 0 )  THEN
+          !   message = "Syntax error in command line."
+          !   CALL abort('parse_command_line_arguments', message)
+          !END IF
+          
+          message = "The -clon and -clat command line options are depricated. " // &
+             "Please remove them form your inifor command and specify the " // &
+             "location of the PALM-4U origin either" // NEW_LINE(' ') // &
+             "   - by setting the namelist parameters 'longitude' and 'latitude', or" // NEW_LINE(' ') // &
+             "   - by providing a static driver netCDF file via the -static command-line option."
+
+          i = 1
+          DO WHILE (i .LE. arg_count)
+
+             CALL GET_COMMAND_ARGUMENT( i, option )
+
+             SELECT CASE( TRIM(option) )
+
+             CASE( '--averaging-mode' )
+                CALL get_option_argument( i, arg )
+                cfg % averaging_mode = TRIM(arg)
+
+             CASE( '-date', '-d', '--date' )
+                CALL get_option_argument( i, arg )
+                cfg % start_date = TRIM(arg)
+
+             CASE( '--debug' )
+                cfg % debug = .TRUE.
+
+             ! Elevation of the PALM-4U domain above sea level
+             CASE( '-z0', '-z', '--elevation' )
+                CALL get_option_argument( i, arg )
+                READ(arg, *) cfg % z0
+
+             ! surface pressure, at z0
+             CASE( '-p0', '-r', '--surface-pressure' )
+                cfg % p0_is_set = .TRUE.
+                CALL get_option_argument( i, arg )
+                READ(arg, *) cfg % p0
+
+             ! geostrophic wind in x direction
+             CASE( '-ug', '-u', '--geostrophic-u' )
+                cfg % ug_is_set = .TRUE.
+                CALL get_option_argument( i, arg )
+                READ(arg, *) cfg % ug
+
+             ! geostrophic wind in y direction
+             CASE( '-vg', '-v', '--geostrophic-v' )
+                cfg % vg_is_set = .TRUE.
+                CALL get_option_argument( i, arg )
+                READ(arg, *) cfg % vg
+
+             ! domain centre geographical longitude and latitude
+             CASE( '-clon', '-clat' )
+                CALL abort('parse_command_line_arguments', message)          
+                !READ(arg, *) lambda_cg
+                !lambda_cg = lambda_cg * TO_RADIANS
+                !READ(arg, *) phi_cg
+                !phi_cg = phi_cg * TO_RADIANS
+
+             CASE( '-path', '-p', '--path' )
+                CALL get_option_argument( i, arg )
+                 cfg % input_path = TRIM(arg)
+
+             CASE( '-hhl', '-l', '--hhl-file' )
+                CALL get_option_argument( i, arg )
+                cfg % hhl_file = TRIM(arg)
+
+             CASE( '--input-prefix')
+                CALL get_option_argument( i, arg )
+                cfg % input_prefix = TRIM(arg)
+                cfg % input_prefix_is_set = .TRUE.
+   
+             CASE( '-a', '--averaging-angle' )
+                CALL get_option_argument( i, arg )
+                READ(arg, *) cfg % averaging_angle
+
+             CASE( '-static', '-t', '--static-driver' )
+                CALL get_option_argument( i, arg )
+                cfg % static_driver_file = TRIM(arg)
+
+             CASE( '-soil', '-s', '--soil-file')
+                CALL get_option_argument( i, arg )
+                cfg % soiltyp_file = TRIM(arg)
+
+             CASE( '--flow-prefix')
+                CALL get_option_argument( i, arg )
+                cfg % flow_prefix = TRIM(arg)
+                cfg % flow_prefix_is_set = .TRUE.
+   
+             CASE( '--radiation-prefix')
+                CALL get_option_argument( i, arg )
+                cfg % radiation_prefix = TRIM(arg)
+                cfg % radiation_prefix_is_set = .TRUE.
+   
+             CASE( '--soil-prefix')
+                CALL get_option_argument( i, arg )
+                cfg % soil_prefix = TRIM(arg)
+                cfg % soil_prefix_is_set = .TRUE.
+   
+             CASE( '--soilmoisture-prefix')
+                CALL get_option_argument( i, arg )
+                cfg % soilmoisture_prefix = TRIM(arg)
+                cfg % soilmoisture_prefix_is_set = .TRUE.
+
+             CASE( '-o', '--output' )
+                CALL get_option_argument( i, arg )
+                cfg % output_file = TRIM(arg)
+
+             CASE( '-n', '--namelist' )
+                CALL get_option_argument( i, arg )
+                cfg % namelist_file = TRIM(arg)
+
+             ! initial condition mode: 'profile' / 'volume'
+             CASE( '-mode', '-i', '--init-mode' )
+                CALL get_option_argument( i, arg )
+                cfg % ic_mode = TRIM(arg)
+
+             ! boundary conditions / forcing mode: 'ideal' / 'real'
+             CASE( '-f', '--forcing-mode' )
+                CALL get_option_argument( i, arg )
+                cfg % bc_mode = TRIM(arg)
+
+             CASE( '--version' )
+                CALL print_version()
+                STOP
+
+             CASE( '--help' )
+                CALL print_version()
+                PRINT *, ""
+                PRINT *, "For a list of command-line options have a look at the README file."
+                STOP
+
+             CASE DEFAULT
+                message = "unknown option '" // TRIM(option) // "'."
+                CALL abort('parse_command_line_arguments', message)
+
+             END SELECT
+
+             i = i + 1
+
+          END DO
+
+       ELSE
+            
+          message = "No arguments present, using default input and output files"
+          CALL report('parse_command_line_arguments', message)
+
+       END IF
+
+   END SUBROUTINE parse_command_line_arguments
+
+   
+   SUBROUTINE get_option_argument(i, arg)
+      CHARACTER(LEN=PATH), INTENT(INOUT) ::  arg
+      INTEGER, INTENT(INOUT)             ::  i
+
+      i = i + 1
+      CALL GET_COMMAND_ARGUMENT(i, arg)
+
+   END SUBROUTINE
+
+
+   SUBROUTINE validate_config(cfg)
+      TYPE(inifor_config), INTENT(IN) ::  cfg
+      LOGICAL                         ::  all_files_present
+
+      all_files_present = .TRUE.
+      all_files_present = all_files_present .AND. file_present(cfg % hhl_file, 'HHL')
+      all_files_present = all_files_present .AND. file_present(cfg % namelist_file, 'NAMELIST')
+      all_files_present = all_files_present .AND. file_present(cfg % soiltyp_file, 'SOILTYP')
+
+      ! Only check optional static driver file name, if it has been given.
+      IF (TRIM(cfg % static_driver_file) .NE. '')  THEN
+         all_files_present = all_files_present .AND. file_present(cfg % static_driver_file, 'static driver')
+      END IF
+
+      IF (.NOT. all_files_present)  THEN
+         message = "INIFOR configuration invalid; some input files are missing."
+         CALL abort( 'validate_config', message ) 
+      END IF
+      
+      
+      SELECT CASE( TRIM(cfg % ic_mode) )
+      CASE( 'profile', 'volume')
+      CASE DEFAULT
+         message = "Initialization mode '" // TRIM(cfg % ic_mode) //&
+                   "' is not supported. " //&
+                   "Please select either 'profile' or 'volume', " //&
+                   "or omit the -i/--init-mode/-mode option entirely, which corresponds "//&
+                   "to the latter."
+         CALL abort( 'validate_config', message ) 
+      END SELECT
+
+
+      SELECT CASE( TRIM(cfg % bc_mode) )
+      CASE( 'real', 'ideal')
+      CASE DEFAULT
+         message = "Forcing mode '" // TRIM(cfg % bc_mode) //& 
+                   "' is not supported. " //&
+                   "Please select either 'real' or 'ideal', " //&
+                   "or omit the -f/--forcing-mode option entirely, which corresponds "//&
+                   "to the latter."
+         CALL abort( 'validate_config', message ) 
+      END SELECT
+
+      SELECT CASE( TRIM(cfg % averaging_mode) )
+      CASE( 'level', 'height')
+      CASE DEFAULT
+         message = "Averaging mode '" // TRIM(cfg % averaging_mode) //&
+                   "' is not supported. " //&
+                   "Please select either 'height' or 'level', " //&
+                   "or omit the --averaging-mode option entirely, which corresponds "//&
+                   "to the latter."
+         CALL abort( 'validate_config', message ) 
+      END SELECT
+
+      IF ( cfg % ug_is_set .NEQV. cfg % vg_is_set )  THEN
+         message = "You specified only one component of the geostrophic " // &
+                   "wind. Please specify either both or none."
+         CALL abort( 'validate_config', message )
+      END IF
+
+   END SUBROUTINE validate_config
+
+
+   LOGICAL FUNCTION file_present(filename, kind)
+      CHARACTER(LEN=PATH), INTENT(IN) ::  filename
+      CHARACTER(LEN=*), INTENT(IN)    ::  kind
+
+      IF (LEN(TRIM(filename))==0)  THEN
+
+         file_present = .FALSE.
+         message = "No name was given for the " // TRIM(kind) // " file."
+         CALL report('file_present', message)
+
+      ELSE
+
+         INQUIRE(FILE=filename, EXIST=file_present)
+
+         IF (.NOT. file_present)  THEN
+            message = "The given " // TRIM(kind) // " file '" //               &
+                      TRIM(filename) // "' does not exist."
+            CALL report('file_present', message)
+         END IF
+
+      END IF
+
+   END FUNCTION file_present
+
+
+!------------------------------------------------------------------------------!
+! Description:
+! ------------
+!> This routine initializes the Inifor output file, i.e. the PALM-4U
+!> initializing and forcing data as a NetCDF file.
+!> 
+!> Besides writing metadata, such as global attributes, coordinates, variables,
+!> in the NetCDF file, various NetCDF IDs are saved for later, when Inifor
+!> writes the actual data.
+!------------------------------------------------------------------------------!
+   SUBROUTINE setup_netcdf_dimensions(output_file, palm_grid,                  &
+                                      start_date_string, origin_lon, origin_lat)
+
+       TYPE(nc_file), INTENT(INOUT)      ::  output_file
+       TYPE(grid_definition), INTENT(IN) ::  palm_grid
+       CHARACTER (LEN=DATE), INTENT(IN)  ::  start_date_string
+       REAL(dp), INTENT(IN)              ::  origin_lon, origin_lat
+
+       CHARACTER (LEN=8)     ::  date_string
+       CHARACTER (LEN=10)    ::  time_string
+       CHARACTER (LEN=5)     ::  zone_string
+       CHARACTER (LEN=SNAME) ::  history_string
+       INTEGER               ::  ncid, nx, ny, nz, nt, dimids(3), dimvarids(3)
+       REAL(dp)              ::  z0
+
+       message = "Initializing PALM-4U dynamic driver file '" //               &
+                 TRIM(output_file % name) // "' and setting up dimensions."
+       CALL report('setup_netcdf_dimensions', message)
+
+       ! Create the NetCDF file. NF90_CLOBBER selects overwrite mode.
+#if defined( __netcdf4 )
+       CALL check(nf90_create(TRIM(output_file % name), OR(NF90_CLOBBER, NF90_HDF5), ncid))
+#else
+       CALL check(nf90_create(TRIM(output_file % name), NF90_CLOBBER, ncid))
+#endif
+
+!------------------------------------------------------------------------------
+!- Section 1: Define NetCDF dimensions and coordinates
+!------------------------------------------------------------------------------
+       nt = SIZE(output_file % time)
+       nx = palm_grid % nx
+       ny = palm_grid % ny
+       nz = palm_grid % nz
+       z0 = palm_grid % z0
+
+
+!
+!------------------------------------------------------------------------------
+!- Section 2: Write global NetCDF attributes
+!------------------------------------------------------------------------------
+       CALL date_and_time(DATE=date_string, TIME=time_string, ZONE=zone_string)
+       history_string =                                                        &
+           'Created on '// date_string      //                                 &
+           ' at '       // time_string(1:2) // ':' // time_string(3:4) //      &
+           ' (UTC'      // zone_string // ')'
+
+       CALL check(nf90_put_att(ncid, NF90_GLOBAL, 'title',          'PALM input file for scenario ...'))
+       CALL check(nf90_put_att(ncid, NF90_GLOBAL, 'institution',    'Deutscher Wetterdienst, Offenbach'))
+       CALL check(nf90_put_att(ncid, NF90_GLOBAL, 'author',         'Eckhard Kadasch, eckhard.kadasch@dwd.de'))
+       CALL check(nf90_put_att(ncid, NF90_GLOBAL, 'history',        TRIM(history_string)))
+       CALL check(nf90_put_att(ncid, NF90_GLOBAL, 'references',     '--'))
+       CALL check(nf90_put_att(ncid, NF90_GLOBAL, 'comment',        '--'))
+       CALL check(nf90_put_att(ncid, NF90_GLOBAL, 'origin_lat',     TRIM(real_to_str(origin_lat*TO_DEGREES, '(F18.13)'))))
+       CALL check(nf90_put_att(ncid, NF90_GLOBAL, 'origin_lon',     TRIM(real_to_str(origin_lon*TO_DEGREES, '(F18.13)'))))
+       ! FIXME: This is the elevation relative to COSMO-DE/D2 sea level and does
+       ! FIXME: not necessarily comply with DHHN2016 (c.f. PALM Input Data
+       ! FIXME: Standard v1.9., origin_z)
+       CALL check(nf90_put_att(ncid, NF90_GLOBAL, 'origin_z',       TRIM(real_to_str(z0, '(F18.13)'))))
+       CALL check(nf90_put_att(ncid, NF90_GLOBAL, 'inifor_version', TRIM(VERSION)))
+       CALL check(nf90_put_att(ncid, NF90_GLOBAL, 'palm_version',   '--'))
+
+!
+!
+!------------------------------------------------------------------------------
+!- Section 2a: Define dimensions for cell centers (scalars in soil and atmosph.)
+!------------------------------------------------------------------------------
+       dimids = (/0, 0, 0/) ! reset dimids
+          CALL check( nf90_def_dim(ncid, "x", nx+1, dimids(1)) )
+          CALL check( nf90_def_dim(ncid, "y", ny+1, dimids(2)) )
+          CALL check( nf90_def_dim(ncid, "z", nz, dimids(3)) )
+          output_file % dimids_scl = dimids ! save dimids for later
+
+       dimvarids = (/0, 0, 0/) ! reset dimvarids
+          CALL check(nf90_def_var(ncid, "x", NF90_FLOAT, dimids(1), dimvarids(1)))
+          CALL check(nf90_put_att(ncid, dimvarids(1), "standard_name", "x coordinate of cell centers"))
+          CALL check(nf90_put_att(ncid, dimvarids(1), "units", "m"))
+
+          CALL check(nf90_def_var(ncid, "y", NF90_FLOAT, dimids(2), dimvarids(2)))
+          CALL check(nf90_put_att(ncid, dimvarids(2), "standard_name", "y coordinate of cell centers"))
+          CALL check(nf90_put_att(ncid, dimvarids(2), "units", "m"))
+
+          CALL check(nf90_def_var(ncid, "z", NF90_FLOAT, dimids(3), dimvarids(3)))
+          CALL check(nf90_put_att(ncid, dimvarids(3), "standard_name", "z coordinate of cell centers"))
+          CALL check(nf90_put_att(ncid, dimvarids(3), "units", "m"))
+       output_file % dimvarids_scl = dimvarids ! save dimvarids for later
+
+       ! overwrite third dimid with the one of depth
+       CALL check(nf90_def_dim(ncid, "zsoil", SIZE(palm_grid % depths), dimids(3)) )
+       output_file % dimids_soil = dimids ! save dimids for later
+
+       ! overwrite third dimvarid with the one of depth
+       CALL check(nf90_def_var(ncid, "zsoil", NF90_FLOAT, output_file % dimids_soil(3), dimvarids(3)))
+       CALL check(nf90_put_att(ncid, dimvarids(3), "standard_name", "depth_below_land"))
+       CALL check(nf90_put_att(ncid, dimvarids(3), "positive", "down"))
+       CALL check(nf90_put_att(ncid, dimvarids(3), "units", "m"))
+       output_file % dimvarids_soil = dimvarids ! save dimvarids for later
+!
+!------------------------------------------------------------------------------
+!- Section 2b: Define dimensions for cell faces/velocities
+!------------------------------------------------------------------------------
+       dimids = (/0, 0, 0/) ! reset dimids
+          CALL check(nf90_def_dim(ncid, "xu", nx, dimids(1)) )
+          CALL check(nf90_def_dim(ncid, "yv", ny, dimids(2)) )
+          CALL check(nf90_def_dim(ncid, "zw", nz-1, dimids(3)) )
+       output_file % dimids_vel = dimids ! save dimids for later
+
+       dimvarids = (/0, 0, 0/) ! reset dimvarids
+          CALL check(nf90_def_var(ncid, "xu", NF90_FLOAT, dimids(1), dimvarids(1)))
+          CALL check(nf90_put_att(ncid, dimvarids(1), "standard_name", "x coordinate of cell faces"))
+          CALL check(nf90_put_att(ncid, dimvarids(1), "units", "m"))
+
+          CALL check(nf90_def_var(ncid, "yv", NF90_FLOAT, dimids(2), dimvarids(2)))
+          CALL check(nf90_put_att(ncid, dimvarids(2), "standard_name", "y coordinate of cell faces"))
+          CALL check(nf90_put_att(ncid, dimvarids(2), "units", "m"))
+
+          CALL check(nf90_def_var(ncid, "zw", NF90_FLOAT, dimids(3), dimvarids(3)))
+          CALL check(nf90_put_att(ncid, dimvarids(3), "standard_name", "z coordinate of cell faces"))
+          CALL check(nf90_put_att(ncid, dimvarids(3), "units", "m"))
+       output_file % dimvarids_vel = dimvarids ! save dimvarids for later
+
+!
+!------------------------------------------------------------------------------
+!- Section 2c: Define time dimension
+!------------------------------------------------------------------------------
+       CALL check(nf90_def_dim(ncid, "time", nt, output_file % dimid_time) )
+       CALL check(nf90_def_var(ncid, "time", NF90_FLOAT, &
+                                             output_file % dimid_time, &
+                                             output_file % dimvarid_time))
+       CALL check(nf90_put_att(ncid, output_file % dimvarid_time, "standard_name", "time"))
+       CALL check(nf90_put_att(ncid, output_file % dimvarid_time, "long_name", "time"))
+       CALL check(nf90_put_att(ncid, output_file % dimvarid_time, "units",     &
+                               "seconds since " // start_date_string // " UTC"))
+
+       CALL check(nf90_enddef(ncid))
+
+!
+!------------------------------------------------------------------------------
+!- Section 3: Write grid coordinates
+!------------------------------------------------------------------------------
+       CALL check(nf90_put_var(ncid, output_file % dimvarids_scl(1), palm_grid%x))
+       CALL check(nf90_put_var(ncid, output_file % dimvarids_scl(2), palm_grid%y))
+       CALL check(nf90_put_var(ncid, output_file % dimvarids_scl(3), palm_grid%z))
+
+       CALL check(nf90_put_var(ncid, output_file % dimvarids_vel(1), palm_grid%xu))
+       CALL check(nf90_put_var(ncid, output_file % dimvarids_vel(2), palm_grid%yv))
+       CALL check(nf90_put_var(ncid, output_file % dimvarids_vel(3), palm_grid%zw))
+
+       ! TODO Read in soil depths from input file before this.
+       CALL check(nf90_put_var(ncid, output_file % dimvarids_soil(3), palm_grid%depths))
+
+       ! Write time vector
+       CALL check(nf90_put_var(ncid, output_file % dimvarid_time, output_file % time))
+
+       ! Close the file
+       CALL check(nf90_close(ncid))
+
+    END SUBROUTINE setup_netcdf_dimensions
+
+
+    SUBROUTINE setup_netcdf_variables(filename, output_variable_table)
+
+       CHARACTER (LEN=*), INTENT(IN)        ::  filename
+       TYPE(nc_var), INTENT(INOUT), TARGET  ::  output_variable_table(:)
+       TYPE(nc_var), POINTER                ::  var
+       INTEGER                              ::  i, ncid
+
+       message = "Defining variables in dynamic driver '" // TRIM(filename) // "'."
+       CALL report('setup_netcdf_variables', message)
+
+       CALL check(nf90_open(TRIM(filename), NF90_WRITE, ncid))
+       CALL check(nf90_redef(ncid))
+
+       DO i = 1, SIZE(output_variable_table)
+
+          var => output_variable_table(i)
+
+          IF ( var % to_be_processed )  THEN
+             message = "  variable #" // TRIM(str(i)) // " '" // TRIM(var%name) // "'."
+             CALL report('setup_netcdf_variables', message)
+
+             CALL netcdf_define_variable(var, ncid)
+             CALL netcdf_get_dimensions(var, ncid)
+          END IF
+           
+       END DO
+
+       CALL check(nf90_enddef(ncid))
+       CALL check(nf90_close(ncid))
+
+       message = "Dynamic driver '" // TRIM(filename) // "' initialized successfully."
+       CALL report('setup_netcdf_variables', message)
+
+    END SUBROUTINE setup_netcdf_variables
+
+
+!------------------------------------------------------------------------------!
+! Description:
+! ------------
+!> This routine reads and returns all input variables of the given IO group
+!> It accomodates the data by allocating a container variable that represents a
+!> list of arrays of the same length as the groups variable list. (This list
+!> will typically contain one or two items.) After the container, its members
+!> are allocated one by one with the appropriate, possibly different,
+!> dimensions.
+!>
+!> The 'group' is an INTENT(INOUT) variable so that 'get_netcdf_variable()' can
+!> record netCDF IDs in the 'in_var_list()' member variable.
+!------------------------------------------------------------------------------!
+    SUBROUTINE read_input_variables(group, iter, buffer)
+       TYPE(io_group), INTENT(INOUT), TARGET       ::  group
+       INTEGER, INTENT(IN)                         ::  iter
+       TYPE(container), ALLOCATABLE, INTENT(INOUT) ::  buffer(:)
+       INTEGER                                     ::  hour, buf_id
+       TYPE(nc_var), POINTER                       ::  input_var
+       CHARACTER(LEN=PATH), POINTER                ::  input_file
+       INTEGER                                     ::  ivar, nbuffers
+
+       message = "Reading data for I/O group '" // TRIM(group % in_var_list(1) % name) // "'."
+       CALL report('read_input_variables', message)
+
+       input_file => group % in_files(iter)
+
+!
+!------------------------------------------------------------------------------
+!- Section 1: Load input buffers for accumulated variables
+!------------------------------------------------------------------------------
+       IF (group % kind == 'running average' .OR.                              &
+           group % kind == 'accumulated')  THEN ! radiation budgets, precipitation
+
+          IF (SIZE(group % in_var_list) .GT. 1 ) THEN
+             message = "I/O groups may not contain more than one " // & 
+                       "accumulated variable. Group '" // TRIM(group % kind) //&
+                       "' contains " //                                        &
+                       TRIM( str(SIZE(group % in_var_list)) ) // "."
+             CALL abort('read_input_variables | accumulation', message)
+          END IF
+
+          ! use two buffer arrays
+          nbuffers = 2
+          IF ( .NOT. ALLOCATED( buffer ) )  ALLOCATE( buffer(nbuffers) )
+
+          ! chose correct buffer array
+          hour = iter - 1! hour of the day
+          buf_id = select_buffer(hour)
+
+ CALL run_control('time', 'read')
+          IF ( ALLOCATED(buffer(buf_id) % array) )  DEALLOCATE(buffer(buf_id) % array)
+ CALL run_control('time', 'alloc')
+
+          input_var => group % in_var_list(1)
+          CALL get_netcdf_variable(input_file, input_var, buffer(buf_id) % array)
+          CALL report('read_input_variables', "Read accumulated " // TRIM(group % in_var_list(1) % name)) 
+
+          IF ( input_var % is_upside_down )  CALL reverse(buffer(buf_id) % array)
+ CALL run_control('time', 'comp')
+          
+!------------------------------------------------------------------------------
+!- Section 2: Load input buffers for normal I/O groups
+!------------------------------------------------------------------------------
+       ELSE
+
+          ! Allocate one input buffer per input_variable. If more quantities
+          ! have to be computed than input variables exist in this group,
+          ! allocate more buffers. For instance, in the thermodynamics group,
+          ! there are three input variabels (PP, T, Qv) and four quantities
+          ! necessart (P, Theta, Rho, qv) for the corresponding output fields
+          ! (p0, Theta, qv, ug, and vg)
+          nbuffers = MAX( group % n_inputs, group % n_output_quantities )
+          ALLOCATE( buffer(nbuffers) )
+ CALL run_control('time', 'alloc')
+          
+          ! Read in all input variables, leave extra buffers-if any-untouched.
+          DO ivar = 1, group % n_inputs
+
+             input_var => group % in_var_list(ivar)
+
+             ! Check wheather P or PP is present in input file
+             IF (input_var % name == 'P')  THEN
+                input_var % name = TRIM( get_pressure_varname(input_file) )
+ CALL run_control('time', 'read')
+             END IF
+
+             CALL get_netcdf_variable(input_file, input_var, buffer(ivar) % array)
+
+             IF ( input_var % is_upside_down )  CALL reverse(buffer(ivar) % array)
+ CALL run_control('time', 'comp')
+
+          END DO
+       END IF
+
+    END SUBROUTINE read_input_variables
+
+
+    INTEGER FUNCTION select_buffer(hour)
+       INTEGER, INTENT(IN) ::  hour
+       INTEGER             ::  step
+
+       select_buffer = 0
+       step = MODULO(hour, 3) + 1
+
+       SELECT CASE(step)
+       CASE(1, 3)
+           select_buffer = 1
+       CASE(2)
+           select_buffer = 2
+       CASE DEFAULT
+           message = "Invalid step '" // TRIM(str(step))
+           CALL abort('select_buffer', message)
+       END SELECT
+    END FUNCTION select_buffer
+
+
+!------------------------------------------------------------------------------!
+! Description:
+! ------------
+!> Checks if the input_file contains the absolute pressure, 'P', or the pressure
+!> perturbation, 'PP', and returns the appropriate string.
+!------------------------------------------------------------------------------!
+    CHARACTER(LEN=2) FUNCTION get_pressure_varname(input_file) RESULT(var)
+       CHARACTER(LEN=*) ::  input_file
+       INTEGER          ::  ncid, varid
+
+       CALL check(nf90_open( TRIM(input_file), NF90_NOWRITE, ncid ))
+       IF ( nf90_inq_varid( ncid, 'P', varid ) .EQ. NF90_NOERR )  THEN
+
+          var = 'P'
+
+       ELSE IF ( nf90_inq_varid( ncid, 'PP', varid ) .EQ. NF90_NOERR )  THEN
+
+          var = 'PP'
+          CALL report('get_pressure_var', 'Using PP instead of P')
+
+       ELSE
+
+          message = "Failed to read '" // TRIM(var) // &
+                    "' from file '" // TRIM(input_file) // "'."
+          CALL abort('get_pressure_var', message)
+
+       END IF
+
+       CALL check(nf90_close(ncid))
+
+    END FUNCTION get_pressure_varname
+
+
+    FUNCTION get_netcdf_attribute(filename, attribute) RESULT(attribute_value)
+
+       CHARACTER(LEN=*), INTENT(IN) ::  filename, attribute
+       REAL(dp)                     ::  attribute_value
+
+       INTEGER                      :: ncid
+
+       IF ( nf90_open( TRIM(filename), NF90_NOWRITE, ncid ) == NF90_NOERR )  THEN
+
+          CALL check(nf90_get_att(ncid, NF90_GLOBAL, TRIM(attribute), attribute_value))
+          CALL check(nf90_close(ncid))
+
+       ELSE
+
+          message = "Failed to read '" // TRIM(attribute) // &
+                    "' from file '" // TRIM(filename) // "'."
+          CALL abort('get_netcdf_attribute', message)
+
+       END IF
+
+    END FUNCTION get_netcdf_attribute
+
+
+    SUBROUTINE update_output(var, array, iter, output_file)
+       TYPE(nc_var), INTENT(IN)  ::  var
+       REAL(dp), INTENT(IN)      ::  array(:,:,:)
+       INTEGER, INTENT(IN)       ::  iter
+       TYPE(nc_file), INTENT(IN) ::  output_file
+
+       INTEGER ::  ncid, ndim, start(4), count(4)
+       LOGICAL ::  var_is_time_dependent
+
+       var_is_time_dependent = (                                               &
+          var % dimids( var % ndim ) == output_file % dimid_time               &
+       )
+
+       ! Skip time dimension for output
+       ndim = var % ndim
+       IF ( var_is_time_dependent )  ndim = var % ndim - 1
+
+       start(:)      = (/1,1,1,1/)
+       start(ndim+1) = iter
+       count(1:ndim) = var%dimlen(1:ndim)
+
+       CALL check(nf90_open(output_file % name, NF90_WRITE, ncid))
+
+       ! Reduce dimension of output array according to variable kind
+       SELECT CASE (TRIM(var % kind))
+       
+       CASE ( 'init scalar profile', 'init u profile', 'init v profile',       &
+              'init w profile' )
+
+          CALL check(nf90_put_var( ncid, var%varid, array(1,1,:) ) )
+
+       CASE ( 'init soil', 'init scalar', 'init u', 'init v', 'init w' )
+
+          CALL check(nf90_put_var( ncid, var%varid, array(:,:,:) ) )
+
+       CASE( 'left scalar', 'right scalar', 'left w', 'right w' ) 
+
+          CALL check(nf90_put_var( ncid, var%varid, array(1,:,:),              &
+                                   start=start(1:ndim+1),                      &
+                                   count=count(1:ndim) ) )
+          
+
+          IF (.NOT. SIZE(array, 2) .EQ. var % dimlen(1))  THEN
+             PRINT *, "inifor: update_output: Dimension ", 1, " of variable ", &
+                 TRIM(var % name), " (", var % dimlen(1),                      &
+                 ") does not match the dimension of the output array (",       &
+                 SIZE(array, 2), ")."
+             STOP
+          END IF
+          
+
+       CASE( 'north scalar', 'south scalar', 'north w', 'south w' )
+
+          CALL check(nf90_put_var( ncid, var%varid, array(:,1,:),              &
+                                   start=start(1:ndim+1),                      &
+                                   count=count(1:ndim) ) )
+          
+
+       CASE( 'surface forcing', 'top scalar', 'top w' )
+
+          CALL check(nf90_put_var( ncid, var%varid, array(:,:,1),              &
+                                   start=start(1:ndim+1),                      &
+                                   count=count(1:ndim) ) )
+          
+       CASE ( 'left u', 'right u', 'left v', 'right v' )
+
+          CALL check(nf90_put_var( ncid, var%varid, array(1,:,:),              &
+                                   start=start(1:ndim+1),                      &
+                                   count=count(1:ndim) ) )
+
+       CASE ( 'north u', 'south u', 'north v', 'south v' )
+
+          CALL check(nf90_put_var( ncid, var%varid, array(:,1,:),              &
+                                   start=start(1:ndim+1),                      &
+                                   count=count(1:ndim) ) )
+
+       CASE ( 'top u', 'top v' )
+
+          CALL check(nf90_put_var( ncid, var%varid, array(:,:,1),              &
+                                   start=start(1:ndim+1),                      &
+                                   count=count(1:ndim) ) )
+
+       CASE ( 'time series' )
+
+          CALL check(nf90_put_var( ncid, var%varid, array(1,1,1),              &
+                                   start=start(1:ndim+1) ) )
+
+       CASE ( 'constant scalar profile', 'geostrophic', 'internal profile' )
+
+          CALL check(nf90_put_var( ncid, var%varid, array(1,1,:),              &
+                                   start=start(1:ndim+1),                      &
+                                   count=count(1:ndim) ) )
+
+       CASE ( 'large-scale scalar forcing', 'large-scale w forcing' )
+
+           message = "Doing nothing in terms of writing large-scale forings."
+           CALL report('update_output', message)
+
+       CASE DEFAULT
+
+           message = "Variable kind '" // TRIM(var % kind) //                  &
+                    "' not recognized."
+           CALL abort('update_output', message)
+
+       END SELECT
+
+       CALL check(nf90_close(ncid))
+
+    END SUBROUTINE update_output
+
+
+    SUBROUTINE write_netcdf_variable_2d(var, iter, output_file, buffer)
+       TYPE(nc_var), INTENT(IN)          ::  var
+       INTEGER, INTENT(IN)               ::  iter
+       TYPE(nc_file), INTENT(IN)         ::  output_file
+       REAL(dp), INTENT(IN)              ::  buffer(:,:,:)
+
+       INTEGER ::  ncid, ndim_out, start(4), count(4)
+       LOGICAL ::  last_dimension_is_time
+
+       ndim_out = var % ndim
+
+       last_dimension_is_time = var % dimids( var % ndim ) == output_file % dimid_time
+       IF ( last_dimension_is_time )  THEN
+          ndim_out = ndim_out - 1
+       END IF
+
+       start(:)      = (/1,1,1,iter/)
+       count(1:ndim_out) = var%dimlen(1:ndim_out)
+
+       CALL check(nf90_open(output_file % name, NF90_WRITE, ncid))
+
+       IF (TRIM(var % kind) .EQ. 'left/right scalar')  THEN
+
+          CALL check(nf90_put_var( ncid, var%varid, buffer(1,:,:) ) )
+
+       ELSE IF (TRIM(var % kind) .EQ. 'north/south scalar')  THEN
+
+          CALL check(nf90_put_var( ncid, var%varid, buffer(:,1,:) ) )
+
+       ELSE IF (TRIM(var % kind) .EQ. 'top scalar')  THEN
+
+          CALL check(nf90_put_var( ncid, var%varid, buffer(:,:,1) ) )
+       ELSE
+
+          CALL check(nf90_put_var( ncid, var%varid, buffer ) )
+
+       END IF
+       CALL check(nf90_close(ncid))
+
+    END SUBROUTINE write_netcdf_variable_2d
+
+
+    SUBROUTINE check(status)
+
+       INTEGER, INTENT(IN) ::  status
+
+       IF (status /= nf90_noerr)  THEN
+          message = "NetCDF API call failed with error: " //                     &
+                    TRIM( nf90_strerror(status) )
+          CALL abort('io.check', message) 
+       END IF
+
+    END SUBROUTINE check
+
+ END MODULE io
Index: palm/trunk/UTIL/inifor/src/inifor_transform.f90
===================================================================
--- palm/trunk/UTIL/inifor/src/inifor_transform.f90	(revision 3447)
+++ palm/trunk/UTIL/inifor/src/inifor_transform.f90	(revision 3447)
@@ -0,0 +1,1211 @@
+!> @file src/inifor_transform.f90
+!------------------------------------------------------------------------------!
+! This file is part of the PALM model system.
+!
+! PALM is free software: you can redistribute it and/or modify it under the
+! terms of the GNU General Public License as published by the Free Software
+! Foundation, either version 3 of the License, or (at your option) any later
+! version.
+!
+! PALM is distributed in the hope that it will be useful, but WITHOUT ANY
+! WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+! A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+!
+! You should have received a copy of the GNU General Public License along with
+! PALM. If not, see <http://www.gnu.org/licenses/>.
+!
+! Copyright 2017-2018 Leibniz Universitaet Hannover
+! Copyright 2017-2018 Deutscher Wetterdienst Offenbach
+!------------------------------------------------------------------------------!
+!
+! Current revisions:
+! -----------------
+! 
+! 
+! Former revisions:
+! -----------------
+! $Id$
+! Renamed source files for compatibilty with PALM build system
+! 
+! 
+! 3395 2018-10-22 17:32:49Z eckhard
+! Switched addressing of averaging regions from index bounds to list of columns
+! Added routines for the computation of geostrophic winds including:
+!    - the downward extrapolation of density (linear) and
+!    - pressure (hydrostatic equation) and
+!    - rotation of geostrophic wind components to PALM frame of reference
+! 
+! 3183 2018-07-27 14:25:55Z suehring
+! Introduced new PALM grid stretching
+! Removed unnecessary subroutine parameters
+! Renamed kcur to k_intermediate
+! 
+! 
+! 3182 2018-07-27 13:36:03Z suehring
+! Initial revision
+!
+! 
+!
+! Authors:
+! --------
+! @author Eckhard Kadasch
+!
+! Description:
+! ------------
+!> The transform module provides INIFOR's low-level transformation and
+!> interpolation routines. The rotated-pole transformation routines phirot2phi,
+!> phi2phirot, rlarot2rla, rla2rlarot, uv2uvrot, and uvrot2uv are adapted from
+!> int2lm's utility routines.
+!------------------------------------------------------------------------------!
+ MODULE transform
+
+    USE control
+    USE defs,                                                                  &
+        ONLY: G, TO_DEGREES, TO_RADIANS, PI, dp
+    USE types
+    USE util,                                                                  &       
+        ONLY: real_to_str, str
+
+    IMPLICIT NONE
+
+ CONTAINS
+
+!------------------------------------------------------------------------------!
+! Description:
+! ------------
+!> Interpolates linearly in the vertical direction in very column (i,j) of the
+!> output array outvar(i,j,:) using values of the source array invar. In cells
+!> that are outside the COSMO-DE domain, indicated by negative interpolation
+!> weights, extrapolate constantly from the cell above.
+!> 
+!> Input parameters:
+!> -----------------
+!> invar : Array of source data
+!> 
+!> outgrid % kk : Array of vertical neighbour indices. kk(i,j,k,:) contain the
+!>     indices of the two vertical neighbors of PALM-4U point (i,j,k) on the
+!>     input grid corresponding to the source data invar.
+!> 
+!> outgrid % w_verti : Array of weights for vertical linear interpolation
+!>     corresponding to neighbour points indexed by kk.
+!>
+!> Output papameters:
+!> ------------------
+!> outvar : Array of interpolated data
+!------------------------------------------------------------------------------!
+    SUBROUTINE interpolate_1d(in_arr, out_arr, outgrid)
+       TYPE(grid_definition), INTENT(IN) ::  outgrid
+       REAL(dp), INTENT(IN)              ::  in_arr(0:,0:,0:)
+       REAL(dp), INTENT(OUT)             ::  out_arr(0:,0:,:)
+
+       INTEGER :: i, j, k, l, nz
+
+       nz = UBOUND(out_arr, 3)
+
+       DO j = LBOUND(out_arr, 2), UBOUND(out_arr, 2)
+       DO i = LBOUND(out_arr, 1), UBOUND(out_arr, 1)
+       DO k = nz, LBOUND(out_arr, 3), -1
+
+          ! TODO: Remove IF clause and extrapolate based on a critical vertical
+          ! TODO: index marking the lower bound of COSMO-DE data coverage.
+          ! Check for negative interpolation weights indicating grid points 
+          ! below COSMO-DE domain and extrapolate from the top in such cells.
+          IF (outgrid % w_verti(i,j,k,1) < -1.0_dp .AND. k < nz)  THEN
+             out_arr(i,j,k) = out_arr(i,j,k+1)
+          ELSE
+             out_arr(i,j,k) = 0.0_dp
+             DO l = 1, 2
+                out_arr(i,j,k) = out_arr(i,j,k) +                              &
+                    outgrid % w_verti(i,j,k,l) *                               &
+                    in_arr(i,j,outgrid % kk(i,j,k, l) )
+             END DO
+          END IF
+       END DO
+       END DO
+       END DO
+    END SUBROUTINE interpolate_1d
+
+
+!------------------------------------------------------------------------------!
+! Description:
+! ------------
+!> Interpolates bi-linearly in horizontal planes on every k level of the output
+!> array outvar(:,:,k) using values of the source array invar(:,:,:). The source
+!> (invar) and interpolation array (outvar) need to have matching dimensions.
+!>
+!> Input parameters:
+!> -----------------
+!> invar : Array of source data
+!> 
+!> outgrid % ii, % jj : Array of neighbour indices in x and y direction.
+!>     ii(i,j,k,:), and jj(i,j,k,:) contain the four horizontal neighbour points
+!>     of PALM-4U point (i,j,k) on the input grid corresponding to the source
+!>     data invar. (The outgrid carries the relationship with the ingrid in the
+!      form of the interpoaltion weights.)
+!> 
+!> outgrid % w_horiz: Array of weights for horizontal bi-linear interpolation
+!>     corresponding to neighbour points indexed by ii and jj.
+!>
+!> Output papameters:
+!> ------------------
+!> outvar : Array of interpolated data
+!------------------------------------------------------------------------------!
+    SUBROUTINE interpolate_2d(invar, outvar, outgrid, ncvar)
+    ! I index 0-based for the indices of the outvar to be consistent with the
+    ! outgrid indices and interpolation weights.
+       TYPE(grid_definition), INTENT(IN)  ::  outgrid
+       REAL(dp), INTENT(IN)               ::  invar(0:,0:,0:)
+       REAL(dp), INTENT(OUT)              ::  outvar(0:,0:,0:)
+       TYPE(nc_var), INTENT(IN), OPTIONAL ::  ncvar
+
+       INTEGER ::  i, j, k, l
+
+       ! TODO: check if input dimensions are consistent, i.e. ranges are correct
+       IF (UBOUND(outvar, 3) .GT. UBOUND(invar, 3))  THEN
+           message = "Output array for '" // TRIM(ncvar % name) // "' has ' more levels (" // &
+              TRIM(str(UBOUND(outvar, 3))) // ") than input variable ("//&
+              TRIM(str(UBOUND(invar, 3))) // ")."
+           CALL abort('interpolate_2d', message) 
+       END IF
+
+       DO k = 0, UBOUND(outvar, 3)
+       DO j = 0, UBOUND(outvar, 2)
+       DO i = 0, UBOUND(outvar, 1)
+          outvar(i,j,k) = 0.0_dp
+          DO l = 1, 4
+             
+             outvar(i,j,k) = outvar(i,j,k) +                                   &
+                outgrid % w_horiz(i,j,l) * invar( outgrid % ii(i,j,l),         & 
+                                                  outgrid % jj(i,j,l),         &
+                                                  k )
+          END DO
+       END DO
+       END DO
+       END DO
+        
+    END SUBROUTINE interpolate_2d
+
+
+    SUBROUTINE average_2d(in_arr, out_arr, ii, jj)
+       REAL(dp), INTENT(IN)              ::  in_arr(0:,0:,0:)
+       REAL(dp), INTENT(OUT)             ::  out_arr(0:)
+       INTEGER, INTENT(IN), DIMENSION(:) ::  ii, jj
+
+       INTEGER  ::  i, j, k, l
+       REAL(dp) ::  ni
+
+       IF (SIZE(ii) .NE. SIZE(jj))  THEN
+          message = "Length of 'ii' and 'jj' index lists do not match." //     &
+             NEW_LINE(' ') // "ii has " // str(SIZE(ii)) // " elements, " //        &
+             NEW_LINE(' ') // "jj has " // str(SIZE(jj)) // "."
+          CALL abort('average_2d', message)
+       END IF
+
+       DO k = 0, UBOUND(out_arr, 1)
+
+          out_arr(k) = 0.0_dp
+          DO l = 1, UBOUND(ii, 1)
+             i = ii(l)
+             j = jj(l)
+             out_arr(k) = out_arr(k) +&
+                         in_arr(i, j, k)
+          END DO
+
+       END DO
+
+       ni = 1.0_dp / SIZE(ii)
+       out_arr(:) = out_arr(:) * ni
+
+    END SUBROUTINE average_2d
+
+
+    SUBROUTINE interpolate_3d(source_array, palm_array, palm_intermediate, palm_grid)
+       TYPE(grid_definition), INTENT(IN) ::  palm_intermediate, palm_grid
+       REAL(dp), DIMENSION(:,:,:), INTENT(IN)  ::  source_array
+       REAL(dp), DIMENSION(:,:,:), INTENT(OUT) ::  palm_array
+       REAL(dp), DIMENSION(:,:,:), ALLOCATABLE ::  intermediate_array
+       INTEGER ::  nx, ny, nlev
+
+       nx = palm_intermediate % nx
+       ny = palm_intermediate % ny
+       nlev = palm_intermediate % nz ! nlev
+
+       ! Interpolate from COSMO-DE to intermediate grid. Allocating with one
+       ! less point in the vertical, since scalars like T have 50 instead of 51
+       ! points in COSMO-DE.
+       ALLOCATE(intermediate_array(0:nx, 0:ny, 0:nlev-1)) !
+
+       CALL interpolate_2d(source_array, intermediate_array, palm_intermediate)
+
+       ! Interpolate from intermediate grid to palm_grid grid, includes
+       ! extrapolation for cells below COSMO-DE domain.
+       CALL interpolate_1d(intermediate_array, palm_array, palm_grid)
+
+       DEALLOCATE(intermediate_array)
+
+    END SUBROUTINE interpolate_3d
+
+
+    SUBROUTINE average_profile(source_array, profile_array, avg_grid)
+       TYPE(grid_definition), INTENT(IN)          ::  avg_grid
+       REAL(dp), DIMENSION(:,:,:), INTENT(IN)     ::  source_array
+       REAL(dp), DIMENSION(:), INTENT(OUT)        ::  profile_array
+
+       INTEGER ::  i_source, j_source, k_profile, k_source, l, m
+
+       REAL ::  ni_columns
+
+       profile_array(:) = 0.0_dp
+
+       DO l = 1, avg_grid % n_columns
+          i_source = avg_grid % iii(l)
+          j_source = avg_grid % jjj(l)
+
+          DO k_profile = avg_grid % k_min, UBOUND(profile_array, 1) ! PALM levels
+
+             DO m = 1, 2 ! vertical interpolation neighbours
+
+                k_source = avg_grid % kkk(l, k_profile, m)
+
+                profile_array(k_profile) = profile_array(k_profile)    &
+                   + avg_grid % w(l, k_profile, m)                             &
+                   * source_array(i_source, j_source, k_source)
+
+             END DO ! m, vertical interpolation neighbours
+
+          END DO    ! k_profile, PALM levels
+
+       END DO       ! l, horizontal neighbours
+
+       ni_columns = 1.0_dp / avg_grid % n_columns
+       profile_array(:) = profile_array(:) * ni_columns
+
+       ! Extrapolate constant to the bottom
+       profile_array(1:avg_grid % k_min-1) = profile_array(avg_grid % k_min)
+
+    END SUBROUTINE average_profile
+
+
+    SUBROUTINE extrapolate_density(rho, avg_grid)
+       REAL(dp), DIMENSION(:), INTENT(INOUT) ::  rho
+       TYPE(grid_definition), INTENT(IN)     ::  avg_grid
+
+       REAL(dp) ::  drhodz, dz, zk, rhok
+       INTEGER  ::  k_min
+
+       k_min  = avg_grid % k_min
+       zk     = avg_grid % z(k_min)
+       rhok   = rho(k_min)
+       dz     = avg_grid % z(k_min + 1) - avg_grid % z(k_min)
+       drhodz = (rho(k_min + 1) - rho(k_min)) / dz
+
+       rho(1:k_min-1) = rhok + drhodz * (avg_grid % z(1:k_min-1) - zk)
+
+    END SUBROUTINE extrapolate_density
+
+
+    SUBROUTINE extrapolate_pressure(p, rho, avg_grid)
+       REAL(dp), DIMENSION(:), INTENT(IN)    ::  rho
+       REAL(dp), DIMENSION(:), INTENT(INOUT) ::  p
+       TYPE(grid_definition), INTENT(IN)     ::  avg_grid
+
+       REAL(dp) ::  drhodz, dz, zk, rhok
+       INTEGER  ::  k, k_min
+
+       k_min = avg_grid % k_min
+       zk    = avg_grid % z(k_min)
+       rhok  = rho(k_min)
+       dz    = avg_grid % z(k_min + 1) - avg_grid % z(k_min)
+       drhodz = 0.5_dp * (rho(k_min + 1) - rho(k_min)) / dz
+
+       DO k = 1, k_min-1
+          p(k) = constant_density_pressure(p(k_min), zk, rhok, drhodz,         &
+                                           avg_grid % z(k), G)
+       END DO
+
+    END SUBROUTINE extrapolate_pressure
+
+
+!------------------------------------------------------------------------------!
+! Description:
+! ------------
+!> Takes the averaged pressure profile <p> and sets the lowest entry to the
+!> extrapolated pressure at the surface.
+!------------------------------------------------------------------------------!
+    SUBROUTINE get_surface_pressure(p, rho, avg_grid)
+       REAL(dp), DIMENSION(:), INTENT(IN)    ::  rho
+       REAL(dp), DIMENSION(:), INTENT(INOUT) ::  p
+       TYPE(grid_definition), INTENT(IN)     ::  avg_grid
+
+       REAL(dp) ::  drhodz, dz, zk, rhok
+       INTEGER  ::  k, k_min
+
+       k_min = avg_grid % k_min
+       zk    = avg_grid % z(k_min)
+       rhok  = rho(k_min)
+       dz    = avg_grid % z(k_min + 1) - avg_grid % z(k_min)
+       drhodz = 0.5_dp * (rho(k_min + 1) - rho(k_min)) / dz
+
+       p(1) = constant_density_pressure(p(k_min), zk, rhok, drhodz,            &
+                                        0.0, G)
+
+    END SUBROUTINE get_surface_pressure
+
+
+    FUNCTION constant_density_pressure(pk, zk, rhok, drhodz, z, g)  RESULT(p)
+
+       REAL(dp), INTENT(IN)  ::  pk, zk, rhok, drhodz, g, z
+       REAL(dp) ::  p
+
+       p = pk + ( zk - z ) * g * ( rhok + 0.5*drhodz * (zk - z) )
+
+    END FUNCTION constant_density_pressure
+
+!-----------------------------------------------------------------------------!
+! Description:
+! -----------
+!> This routine computes profiles of the two geostrophic wind components ug and
+!> vg.
+!-----------------------------------------------------------------------------!
+    SUBROUTINE geostrophic_winds(p_north, p_south, p_east, p_west, rho, f3,    &
+                                 Lx, Ly, phi_n, lam_n, phi_g, lam_g, ug, vg)
+
+    REAL(dp), DIMENSION(:), INTENT(IN)  ::  p_north, p_south, p_east, p_west,  &
+                                            rho
+    REAL(dp), INTENT(IN)                ::  f3, Lx, Ly, phi_n, lam_n, phi_g, lam_g
+    REAL(dp), DIMENSION(:), INTENT(OUT) ::  ug, vg
+    REAL(dp)                            ::  facx, facy
+
+    facx = 1.0_dp / (Lx * f3)
+    facy = 1.0_dp / (Ly * f3)
+    ug(:) = - facy / rho(:) * (p_north(:) - p_south(:))
+    vg(:) =   facx / rho(:) * (p_east(:) - p_west(:))
+
+    CALL rotate_vector_field(                                                  &
+       ug, vg, angle = meridian_convergence_rotated(phi_n, lam_n, phi_g, lam_g)&
+    )
+
+    END SUBROUTINE geostrophic_winds
+
+
+!-----------------------------------------------------------------------------!
+! Description:
+! -----------
+!> This routine computes the inverse Plate Carree projection, i.e. in projects
+!> Cartesian coordinates (x,y) onto a sphere. It returns the latitude and
+!> lngitude of a geographical system centered at x0 and y0.
+!-----------------------------------------------------------------------------!
+    SUBROUTINE inv_plate_carree(x, y, x0, y0, r, lat, lon)
+       REAL(dp), INTENT(IN)  ::  x(:), y(:), x0, y0, r
+       REAL(dp), INTENT(OUT) ::  lat(:), lon(:)
+       
+       REAL(dp) :: ri
+
+       ! TODO check dimensions of lat/lon and y/x match
+
+       ri = 1.0_dp / r
+       
+       lat(:) = (y(:) - y0) * ri
+       lon(:) = (x(:) - x0) * ri
+    END SUBROUTINE 
+
+
+!-----------------------------------------------------------------------------!
+! Description:
+! ------------
+!> Computes the reverse Plate-Carree projection of a x or y position on a
+!> Cartesian grid.
+!>
+!> Input parameters:
+!> -----------------
+!> xy : x or y coordinate of the Cartasian grid point [m].
+!>
+!> xy0 : x or y coordinate that coincides with the origin of the underlying
+!>     sperical system (crossing point of the equator and prime meridian) [m].
+!>
+!> r : Radius of the of the underlying sphere, e.g. EARTH_RADIUS [m].
+!> 
+!> Returns:
+!> --------
+!> project : Longitude (in case xy = x) or latitude (xy = y) of the given input
+!>     coordinate xy.
+!------------------------------------------------------------------------------!
+    ELEMENTAL REAL(dp) FUNCTION project(xy, xy0, r)
+       REAL(dp), INTENT(IN)  ::  xy, xy0, r
+       REAL(dp) :: ri
+
+       ! If this elemental function is called with a large array as xy, it is
+       ! computationally more efficient to precompute the inverse radius and
+       ! then muliply.
+       ri = 1.0_dp / r
+
+       project = (xy - xy0) * ri
+
+    END FUNCTION project
+
+
+    REAL(dp) FUNCTION phic_to_phin(phi_c)
+        REAL(dp), INTENT(IN) ::  phi_c
+
+        phic_to_phin = 0.5_dp * PI - ABS(phi_c)
+
+    END FUNCTION phic_to_phin
+
+    
+    REAL(dp) FUNCTION lamc_to_lamn(phi_c, lam_c)
+       REAL(dp), INTENT(IN) ::  phi_c, lam_c
+        
+       lamc_to_lamn = lam_c
+       IF (phi_c > 0.0_dp)  THEN
+          lamc_to_lamn = lam_c - SIGN(PI, lam_c)
+       END IF
+
+    END FUNCTION lamc_to_lamn
+
+
+    REAL(dp) FUNCTION gamma_from_hemisphere(phi_cg, phi_ref)
+       REAL(dp), INTENT(IN) ::  phi_cg, phi_ref
+       LOGICAL ::  palm_centre_is_south_of_cosmo_origin
+       
+       palm_centre_is_south_of_cosmo_origin = (phi_cg < phi_ref)
+
+       IF (palm_centre_is_south_of_cosmo_origin)  THEN
+           gamma_from_hemisphere = PI
+       ELSE
+           gamma_from_hemisphere = 0.0_dp
+       END IF
+    END FUNCTION gamma_from_hemisphere
+
+
+!------------------------------------------------------------------------------!
+! Description:
+! ------------
+!> Computes the geographical coordinates corresponding to the given rotated-pole
+!> coordinates.
+!>
+!> In INIFOR, this routine is used to convert coordinates between two
+!> rotated-pole systems: COSMO-DE's rotated-pole system, and one centred at the
+!> PALM-4U domain centre. In this case, the PALM-4U system is thought of as the
+!> rotated-pole system and the routine is used to rotate back to COSMO-DE's
+!> system which is thought of as the geographical one.
+!> 
+!> Input parameters:
+!> -----------------
+!> phir(:), lamr(: ): latitudes and longitudes of the rotated-pole grid
+!> 
+!> phip, lamp: latitude and longitude of the rotated north pole
+!>
+!> gam: "angle between the north poles. If [gam] is not present, the other
+!>       system is the real geographical system." (original phiro2rot
+!>       description)
+!> 
+!> Output parameters:
+!> ------------------
+!> phi(:,:), lam(:,:): geographical latitudes and logitudes
+!------------------------------------------------------------------------------!
+    SUBROUTINE rotate_to_cosmo(phir, lamr, phip, lamp, phi, lam, gam)
+       REAL(dp), INTENT(IN)  ::  phir(0:), lamr(0:), phip, lamp, gam
+       REAL(dp), INTENT(OUT) ::  phi(0:,0:), lam(0:,0:)
+
+       INTEGER ::  i, j
+       
+       IF ( SIZE(phi, 1) .NE. SIZE(lam, 1) .OR. &
+            SIZE(phi, 2) .NE. SIZE(lam, 2) )  THEN
+          PRINT *, "inifor: rotate_to_cosmo: Dimensions of phi and lambda do not match. Dimensions are:"
+          PRINT *, "inifor: rotate_to_cosmo: phi: ", SIZE(phi, 1), SIZE(phi, 2)
+          PRINT *, "inifor: rotate_to_cosmo: lam: ", SIZE(lam, 1), SIZE(lam, 2)
+          STOP
+       END IF
+
+       IF ( SIZE(phir) .NE. SIZE(phi, 2) .OR. &
+            SIZE(lamr) .NE. SIZE(phi, 1) )  THEN
+          PRINT *, "inifor: rotate_to_cosmo: Dimensions of phir and lamr do not match. Dimensions are:"
+          PRINT *, "inifor: rotate_to_cosmo: phir: ", SIZE(phir), SIZE(phi, 2)
+          PRINT *, "inifor: rotate_to_cosmo: lamr: ", SIZE(lamr), SIZE(phi, 1)
+          STOP
+       END IF
+       
+       DO j = 0, UBOUND(phir, 1)
+          DO i = 0, UBOUND(lamr, 1)
+
+             phi(i,j) = phirot2phi(phir(j) * TO_DEGREES,                       &
+                                   lamr(i) * TO_DEGREES,                       &
+                                   phip * TO_DEGREES,                          &
+                                   lamp * TO_DEGREES,                          &
+                                   gam  * TO_DEGREES) * TO_RADIANS
+
+             lam(i,j) = rlarot2rla(phir(j) * TO_DEGREES,                       &
+                                   lamr(i) * TO_DEGREES,                       &
+                                   phip * TO_DEGREES,                          &
+                                   lamp * TO_DEGREES,                          &
+                                   gam  * TO_DEGREES) * TO_RADIANS
+
+          END DO
+       END DO
+
+    END SUBROUTINE rotate_to_cosmo
+       
+
+    SUBROUTINE rotate_vector_field(x, y, angle)
+       REAL(dp), DIMENSION(:), INTENT(INOUT) :: x, y  !< x and y coodrinate in arbitrary units
+       REAL(dp), INTENT(IN)                  :: angle !< rotation angle [deg]
+
+       INTEGER  :: i
+       REAL(dp) :: sine, cosine, v_rot(2), rotation(2,2)
+
+       sine = SIN(angle * TO_RADIANS)
+       cosine = COS(angle * TO_RADIANS)
+       ! RESAHPE() fills columns first, so the rotation matrix becomes
+       !
+       ! rotation = [ cosine   -sine  ]
+       !            [  sine    cosine ]
+       rotation = RESHAPE( (/cosine, sine, -sine, cosine/), (/2, 2/) )
+
+       DO i = LBOUND(x, 1), UBOUND(x, 1)
+
+          v_rot(:) = MATMUL(rotation, (/x(i), y(i)/))
+
+          x(i) = v_rot(1)
+          y(i) = v_rot(2)
+
+       END DO
+
+    END SUBROUTINE rotate_vector_field
+
+
+
+!------------------------------------------------------------------------------!
+! Description:
+! ------------
+!> This routine computes the local meridian convergence between a rotated-pole
+!> and a geographical system using the Eq. (6) given in the DWD manual
+!> 
+!>    Baldauf et al. (2018), Beschreibung des operationelle KuÌrzestfrist-
+!>    vorhersagemodells COSMO-D2 und COSMO-D2-EPS und seiner Ausgabe in die
+!>    Datenbanken des DWD.
+!>    https://www.dwd.de/SharedDocs/downloads/DE/modelldokumentationen/nwv/cosmo_d2/cosmo_d2_dbbeschr_aktuell.pdf?__blob=publicationFile&v=2
+!>
+    FUNCTION meridian_convergence_rotated(phi_n, lam_n, phi_g, lam_g)          &
+       RESULT(delta)
+
+       REAL(dp), INTENT(IN) ::  phi_n, lam_n, phi_g, lam_g
+       REAL(dp)             ::  delta
+
+       delta = atan2( COS(phi_n) * SIN(lam_n - lam_g),                         &
+                      COS(phi_g) * SIN(phi_n) -                                &
+                      SIN(phi_g) * COS(phi_n) * COS(lam_n - lam_g) )
+
+    END FUNCTION meridian_convergence_rotated
+
+!------------------------------------------------------------------------------!
+! Description:
+! ------------
+!> Compute indices of PALM-4U grid point neighbours in the target 
+!> system (COSMO-DE) by rounding up and down. (i,j) are the indices of
+!> the PALM-4U grid and (ii(i,j,1-4), jj(i,j,1-4)) contain the indices
+!> of the its four neigbouring points in the COSMO-DE grid.
+!>
+!>
+!>                     COSMO-DE grid
+!>                     -------------
+!>           jj, lat
+!>              ^        j
+!>              |         \          i
+!>  jj(i,j,2/3) + ... 2 ---\--------/------ 3
+!>              |     | ^   \      /        |
+!>              |     | |wp  \    /         |
+!>              |     | v     \  /          |
+!>       latpos + ............ o/ (i,j)     |
+!>              |     |        :            |
+!>              |     |        :<----wl---->|
+!>  jj(i,j,1/4) + ... 1 -------:----------- 4
+!>              |     :        :            :
+!>              |     :        :            :
+!>              |     :      lonpos         :
+!>              L-----+--------+------------+------> ii, lon 
+!>               ii(i,j,1/2)        ii(i,j,3/4)
+!>
+!> 
+!> Input parameters:
+!> -----------------
+!> source_lat, source_lon : (rotated-pole) coordinates of the source grid (e.g.
+!>    COSMO-DE)
+!>
+!> source_dxi, source_dyi : inverse grid spacings of the source grid.
+!>
+!> target_lat, target_lon : (rotated-pole) coordinates of the target grid (e.g.
+!>    COSMO-DE)
+!> 
+!> Output parameters:
+!> ------------------
+!> palm_ii, palm_jj : x and y index arrays of horizontal neighbour columns
+!> 
+!------------------------------------------------------------------------------!
+    SUBROUTINE find_horizontal_neighbours(cosmo_lat, cosmo_lon,                &
+                                          palm_clat, palm_clon,                &
+                                          palm_ii, palm_jj)
+
+       REAL(dp), DIMENSION(0:), INTENT(IN)        ::  cosmo_lat, cosmo_lon
+       REAL(dp), DIMENSION(0:,0:), INTENT(IN)     ::  palm_clat, palm_clon
+       REAL(dp)                                   ::  cosmo_dxi, cosmo_dyi
+       INTEGER, DIMENSION(0:,0:,1:), INTENT(OUT)  ::  palm_ii, palm_jj
+
+       REAL(dp) ::  lonpos, latpos, lon0, lat0
+       INTEGER  ::  i, j
+
+       lon0 = cosmo_lon(0)
+       lat0 = cosmo_lat(0)
+       cosmo_dxi = 1.0_dp / (cosmo_lon(1) - cosmo_lon(0))
+       cosmo_dyi = 1.0_dp / (cosmo_lat(1) - cosmo_lat(0))
+
+       DO j = 0, UBOUND(palm_clon, 2)!palm_grid % ny
+       DO i = 0, UBOUND(palm_clon, 1)!palm_grid % nx
+          ! Compute the floating point index corrseponding to PALM-4U grid point
+          ! location along target grid (COSMO-DE) axes.
+          lonpos = (palm_clon(i,j) - lon0) * cosmo_dxi
+          latpos = (palm_clat(i,j) - lat0) * cosmo_dyi
+
+          IF (lonpos < 0.0 .OR. latpos < 0.0)  THEN
+             PRINT *, " Error while finding neighbours: lonpos or latpos out of bounds!"
+             PRINT *, "     (i,j) = (", i, ",",j,")"
+             PRINT *, "      lonpos ", lonpos*TO_DEGREES, ", latpos ", latpos*TO_DEGREES
+             PRINT *, "        lon0 ", lon0  *TO_DEGREES,   ", lat0   ", lat0*TO_DEGREES
+             PRINT *, "    PALM lon ", palm_clon(i,j)*TO_DEGREES,   ", PALM lat ",palm_clat(i,j)*TO_DEGREES
+             STOP
+          END IF
+
+          palm_ii(i,j,1) = FLOOR(lonpos)
+          palm_ii(i,j,2) = FLOOR(lonpos)
+          palm_ii(i,j,3) = CEILING(lonpos)
+          palm_ii(i,j,4) = CEILING(lonpos)
+
+          palm_jj(i,j,1) = FLOOR(latpos)
+          palm_jj(i,j,2) = CEILING(latpos)
+          palm_jj(i,j,3) = CEILING(latpos)
+          palm_jj(i,j,4) = FLOOR(latpos)
+       END DO
+       END DO
+
+    END SUBROUTINE find_horizontal_neighbours
+
+    
+    SUBROUTINE find_vertical_neighbours_and_weights_interp( palm_grid,         &
+                                                            palm_intermediate )
+       TYPE(grid_definition), INTENT(INOUT) ::  palm_grid
+       TYPE(grid_definition), INTENT(IN)    ::  palm_intermediate
+
+       INTEGER  ::  i, j, k, nx, ny, nz, nlev, k_intermediate
+       LOGICAL  ::  point_is_below_grid, point_is_above_grid,                  &
+                    point_is_in_current_cell
+       REAL(dp) ::  current_height, column_base, column_top, h_top, h_bottom,  &
+                    weight
+
+       nx   = palm_grid % nx
+       ny   = palm_grid % ny
+       nz   = palm_grid % nz
+       nlev = palm_intermediate % nz
+
+       ! in each column of the fine grid, find vertical neighbours of every cell
+       DO j = 0, ny
+       DO i = 0, nx
+
+          k_intermediate = 0
+
+          column_base = palm_intermediate % h(i,j,0)
+          column_top  = palm_intermediate % h(i,j,nlev)
+
+          ! scan through palm_grid column and set neighbour indices in
+          ! case current_height is either below column_base, in the current
+          ! cell, or above column_top. Keep increasing current cell index until
+          ! the current cell overlaps with the current_height.
+          DO k = 1, nz
+
+             ! Memorize the top and bottom boundaries of the coarse cell and the
+             ! current height within it
+             current_height = palm_grid % z(k) + palm_grid % z0
+             h_top    = palm_intermediate % h(i,j,k_intermediate+1)
+             h_bottom = palm_intermediate % h(i,j,k_intermediate)
+
+             point_is_above_grid = (current_height > column_top) !22000m, very unlikely
+             point_is_below_grid = (current_height < column_base)
+
+             point_is_in_current_cell = (                                      &
+                current_height >= h_bottom .AND.                               &
+                current_height <  h_top                                        &
+             )
+
+             ! set default weights
+             palm_grid % w_verti(i,j,k,1:2) = 0.0_dp
+
+             IF (point_is_above_grid)  THEN
+
+                palm_grid % kk(i,j,k,1:2) = nlev
+                palm_grid % w_verti(i,j,k,1:2) = - 2.0_dp
+
+                message = "PALM-4U grid extends above COSMO-DE model top."
+                CALL abort('find_vertical_neighbours_and_weights', message)
+
+             ELSE IF (point_is_below_grid)  THEN
+
+                palm_grid % kk(i,j,k,1:2) = 0
+                palm_grid % w_verti(i,j,k,1:2) = - 2.0_dp
+
+             ELSE
+                ! cycle through intermediate levels until current
+                ! intermediate-grid cell overlaps with current_height
+                DO WHILE (.NOT. point_is_in_current_cell .AND. k_intermediate <= nlev-1)
+                   k_intermediate = k_intermediate + 1
+
+                   h_top    = palm_intermediate % h(i,j,k_intermediate+1)
+                   h_bottom = palm_intermediate % h(i,j,k_intermediate)
+                   point_is_in_current_cell = (                                &
+                      current_height >= h_bottom .AND.                         &
+                      current_height <  h_top                                  &
+                   )
+                END DO
+
+                IF (k_intermediate > nlev-1)  THEN
+                   message = "Index " // TRIM(str(k_intermediate)) //          &
+                             " is above intermediate grid range."
+                   CALL abort('find_vertical_neighbours', message)
+                END IF
+   
+                palm_grid % kk(i,j,k,1) = k_intermediate
+                palm_grid % kk(i,j,k,2) = k_intermediate + 1
+
+                ! copmute vertical weights
+                weight = (h_top - current_height) / (h_top - h_bottom)
+                palm_grid % w_verti(i,j,k,1) = weight
+                palm_grid % w_verti(i,j,k,2) = 1.0_dp - weight
+             END IF
+
+          END DO
+
+       END DO
+       END DO
+
+    END SUBROUTINE find_vertical_neighbours_and_weights_interp
+
+
+    SUBROUTINE find_vertical_neighbours_and_weights_average( avg_grid )
+       TYPE(grid_definition), INTENT(INOUT) ::  avg_grid
+
+       INTEGER  ::  i, j, k_palm, k_intermediate, l, nlev
+       LOGICAL  ::  point_is_below_grid, point_is_above_grid,                  &
+                    point_is_in_current_cell
+       REAL(dp) ::  current_height, column_base, column_top, h_top, h_bottom,  &
+                    weight
+
+
+       avg_grid % k_min = LBOUND(avg_grid % z, 1)
+
+       nlev = SIZE(avg_grid % cosmo_h, 3)
+
+       ! in each column of the fine grid, find vertical neighbours of every cell
+       DO l = 1, avg_grid % n_columns
+
+          i = avg_grid % iii(l)
+          j = avg_grid % jjj(l)
+
+          column_base = avg_grid % cosmo_h(i,j,1)
+          column_top  = avg_grid % cosmo_h(i,j,nlev)
+
+          ! scan through avg_grid column until and set neighbour indices in
+          ! case current_height is either below column_base, in the current
+          ! cell, or above column_top. Keep increasing current cell index until
+          ! the current cell overlaps with the current_height.
+          k_intermediate = 1 !avg_grid % cosmo_h is indezed 1-based.
+          DO k_palm = 1, avg_grid % nz
+
+             ! Memorize the top and bottom boundaries of the coarse cell and the
+             ! current height within it
+             current_height = avg_grid % z(k_palm) + avg_grid % z0
+             h_top    = avg_grid % cosmo_h(i,j,k_intermediate+1)
+             h_bottom = avg_grid % cosmo_h(i,j,k_intermediate)
+
+             point_is_above_grid = (current_height > column_top) !22000m, very unlikely
+             point_is_below_grid = (current_height < column_base)
+
+             point_is_in_current_cell = (                                      &
+                current_height >= h_bottom .AND.                               &
+                current_height <  h_top                                        &
+             )
+
+             ! set default weights
+             avg_grid % w(l,k_palm,1:2) = 0.0_dp
+
+             IF (point_is_above_grid)  THEN
+
+                avg_grid % kkk(l,k_palm,1:2) = nlev
+                avg_grid % w(l,k_palm,1:2) = - 2.0_dp
+
+                message = "PALM-4U grid extends above COSMO-DE model top."
+                CALL abort('find_vertical_neighbours_and_weights_average', message)
+
+             ELSE IF (point_is_below_grid)  THEN
+
+                avg_grid % kkk(l,k_palm,1:2) = 0
+                avg_grid % w(l,k_palm,1:2) = - 2.0_dp
+                avg_grid % k_min = MAX(k_palm + 1, avg_grid % k_min)
+             ELSE
+                ! cycle through intermediate levels until current
+                ! intermediate-grid cell overlaps with current_height
+                DO WHILE (.NOT. point_is_in_current_cell .AND. k_intermediate <= nlev-1)
+                   k_intermediate = k_intermediate + 1
+
+                   h_top    = avg_grid % cosmo_h(i,j,k_intermediate+1)
+                   h_bottom = avg_grid % cosmo_h(i,j,k_intermediate)
+                   point_is_in_current_cell = (                                &
+                      current_height >= h_bottom .AND.                         &
+                      current_height <  h_top                                  &
+                   )
+                END DO
+
+                ! k_intermediate = 48 indicates the last section (indices 48 and 49), i.e.
+                ! k_intermediate = 49 is not the beginning of a valid cell.
+                IF (k_intermediate > nlev-1)  THEN
+                   message = "Index " // TRIM(str(k_intermediate)) //          &
+                             " is above intermediate grid range."
+                   CALL abort('find_vertical_neighbours', message)
+                END IF
+   
+                avg_grid % kkk(l,k_palm,1) = k_intermediate
+                avg_grid % kkk(l,k_palm,2) = k_intermediate + 1
+
+                ! copmute vertical weights
+                weight = (h_top - current_height) / (h_top - h_bottom)
+                avg_grid % w(l,k_palm,1) = weight
+                avg_grid % w(l,k_palm,2) = 1.0_dp - weight
+             END IF
+
+          END DO ! k, PALM levels
+       END DO ! l, averaging columns
+ 
+    END SUBROUTINE find_vertical_neighbours_and_weights_average
+
+!------------------------------------------------------------------------------!
+! Description:
+! ------------
+!> Compute the four weights for horizontal bilinear interpolation given the
+!> coordinates clon(i,j) clat(i,j) of the PALM-4U grid in the COSMO-DE
+!> rotated-pole grid and the neightbour indices ii(i,j,1-4) and jj(i,j,1-4).
+!>
+!> Input parameters:
+!> -----------------
+!> palm_grid % clon : longitudes of PALM-4U scalars (cell centres) in COSMO-DE's rotated-pole grid [rad]
+!>
+!> palm_grid % clat : latitudes of PALM-4U cell centres in COSMO-DE's rotated-pole grid [rad]
+!>
+!> cosmo_grid % lon : rotated-pole longitudes of scalars (cell centres) of the COSMO-DE grid [rad] 
+!>
+!> cosmo_grid % lat : rotated-pole latitudes of scalars (cell centers) of the COSMO-DE grid [rad]
+!>
+!> cosmo_grid % dxi : inverse grid spacing in the first dimension [m^-1]
+!>
+!> cosmo_grid % dyi : inverse grid spacing in the second dimension [m^-1]
+!>
+!> Output parameters:
+!> ------------------
+!> palm_grid % w_horiz(:,:,1-4) : weights for bilinear horizontal interpolation
+!
+!                               COSMO-DE grid
+!                               -------------
+!                     jj, lat
+!                        ^        j
+!                        |         \          i
+!            jj(i,j,2/3) + ... 2 ---\--------/------ 3
+!                        |     | ^   \      /        |
+!                        |     | |wp  \    /         |
+!                        |     | v     \  /          |
+!                 latpos + ............ o/ (i,j)     |
+!                        |     |        :            |
+!                        |     |        :<----wl---->|
+!            jj(i,j,1/4) + ... 1 -------:----------- 4
+!                        |     :        :            :
+!                        |     :        :            :
+!                        |     :      lonpos         :
+!                        L-----+--------+------------+------> ii, lon 
+!                         ii(i,j,1/2)        ii(i,j,3/4)
+!          
+    SUBROUTINE compute_horizontal_interp_weights(cosmo_lat, cosmo_lon,         &
+       palm_clat, palm_clon, palm_ii, palm_jj, palm_w_horiz)
+       
+       REAL(dp), DIMENSION(0:), INTENT(IN)        ::  cosmo_lat, cosmo_lon
+       REAL(dp)                                   ::  cosmo_dxi, cosmo_dyi
+       REAL(dp), DIMENSION(0:,0:), INTENT(IN)     ::  palm_clat, palm_clon
+       INTEGER, DIMENSION(0:,0:,1:), INTENT(IN)   ::  palm_ii, palm_jj
+
+       REAL(dp), DIMENSION(0:,0:,1:), INTENT(OUT) ::  palm_w_horiz
+
+       REAL(dp) ::  wl, wp
+       INTEGER  ::  i, j
+
+       cosmo_dxi = 1.0_dp / (cosmo_lon(1) - cosmo_lon(0))
+       cosmo_dyi = 1.0_dp / (cosmo_lat(1) - cosmo_lat(0))
+
+       DO j = 0, UBOUND(palm_clon, 2)
+       DO i = 0, UBOUND(palm_clon, 1)
+      
+          ! weight in lambda direction
+          wl = ( cosmo_lon(palm_ii(i,j,4)) - palm_clon(i,j) ) * cosmo_dxi
+
+          ! weight in phi direction
+          wp = ( cosmo_lat(palm_jj(i,j,2)) - palm_clat(i,j) ) * cosmo_dyi
+
+          IF (wl > 1.0_dp .OR. wl < 0.0_dp)  THEN
+              message = "Horizontal weight wl = " // TRIM(real_to_str(wl)) //   &
+                        " is out bounds."
+              CALL abort('compute_horizontal_interp_weights', message)
+          END IF
+          IF (wp > 1.0_dp .OR. wp < 0.0_dp)  THEN
+              message = "Horizontal weight wp = " // TRIM(real_to_str(wp)) //   &
+                        " is out bounds."
+              CALL abort('compute_horizontal_interp_weights', message)
+          END IF
+
+          palm_w_horiz(i,j,1) = wl * wp
+          palm_w_horiz(i,j,2) = wl * (1.0_dp - wp)
+          palm_w_horiz(i,j,3) = (1.0_dp - wl) * (1.0_dp - wp)
+          palm_w_horiz(i,j,4) = 1.0_dp - SUM( palm_w_horiz(i,j,1:3) )
+
+       END DO
+       END DO
+       
+    END SUBROUTINE compute_horizontal_interp_weights
+
+
+!------------------------------------------------------------------------------!
+! Description:
+! ------------
+!> Interpolates u and v components of velocities located at cell faces to the
+!> cell centres by averaging neighbouring values.
+!>
+!> This routine is designed to be used with COSMO-DE arrays where there are the
+!> same number of grid points for scalars (centres) and velocities (faces). In
+!> COSMO-DE the velocity points are staggared one half grid spaceing up-grid
+!> which means the first centre point has to be omitted and is set to zero.
+    SUBROUTINE centre_velocities(u_face, v_face, u_centre, v_centre)
+       REAL(dp), DIMENSION(0:,0:,0:), INTENT(IN)  ::  u_face, v_face
+       REAL(dp), DIMENSION(0:,0:,0:), INTENT(OUT) ::  u_centre, v_centre
+       INTEGER ::  nx, ny
+
+       nx = UBOUND(u_face, 1)
+       ny = UBOUND(u_face, 2)
+
+       u_centre(0,:,:)  = 0.0_dp
+       u_centre(1:,:,:) = 0.5_dp * ( u_face(0:nx-1,:,:) + u_face(1:,:,:) )
+
+       v_centre(:,0,:)  = 0.0_dp
+       v_centre(:,1:,:) = 0.5_dp * ( v_face(:,0:ny-1,:) + v_face(:,1:,:) )
+    END SUBROUTINE centre_velocities
+
+
+    FUNCTION phirot2phi (phirot, rlarot, polphi, pollam, polgam)
+    
+       REAL(dp), INTENT (IN) ::  polphi      !< latitude of the rotated north pole
+       REAL(dp), INTENT (IN) ::  pollam      !< longitude of the rotated north pole
+       REAL(dp), INTENT (IN) ::  phirot      !< latitude in the rotated system
+       REAL(dp), INTENT (IN) ::  rlarot      !< longitude in the rotated system
+       REAL(dp), INTENT (IN) ::  polgam      !< angle between the north poles of the systems
+
+       REAL(dp)              ::  phirot2phi  !< latitude in the geographical system
+       
+       REAL(dp)              ::  zsinpol, zcospol, zphis, zrlas, zarg, zgam
+    
+       zsinpol = SIN(polphi * TO_RADIANS)
+       zcospol = COS(polphi * TO_RADIANS)
+       zphis   = phirot * TO_RADIANS
+
+       IF (rlarot > 180.0_dp)  THEN
+          zrlas = rlarot - 360.0_dp
+       ELSE
+          zrlas = rlarot
+       END IF
+       zrlas = zrlas * TO_RADIANS
+     
+       IF (polgam /= 0.0_dp)  THEN
+          zgam = polgam * TO_RADIANS
+          zarg = zsinpol * SIN (zphis) +                                       &
+                 zcospol * COS(zphis) * ( COS(zrlas) * COS(zgam) -             &
+                                          SIN(zgam)  * SIN(zrlas) )
+       ELSE
+          zarg = zcospol * COS (zphis) * COS (zrlas) + zsinpol * SIN (zphis)
+       END IF
+      
+       phirot2phi = ASIN (zarg) * TO_DEGREES
+    
+    END FUNCTION phirot2phi
+
+
+    FUNCTION phi2phirot (phi, rla, polphi, pollam)
+    
+       REAL(dp), INTENT (IN) ::  polphi !< latitude of the rotated north pole
+       REAL(dp), INTENT (IN) ::  pollam !< longitude of the rotated north pole
+       REAL(dp), INTENT (IN) ::  phi    !< latitude in the geographical system
+       REAL(dp), INTENT (IN) ::  rla    !< longitude in the geographical system
+       
+       REAL(dp) ::  phi2phirot          !< longitude in the rotated system
+       
+       REAL(dp) ::  zsinpol, zcospol, zlampol, zphi, zrla, zarg1, zarg2, zrla1
+       
+       zsinpol = SIN(polphi * TO_RADIANS)
+       zcospol = COS(polphi * TO_RADIANS)
+       zlampol = pollam * TO_RADIANS
+       zphi    = phi * TO_RADIANS
+
+       IF (rla > 180.0_dp)  THEN
+          zrla1 = rla - 360.0_dp
+       ELSE
+          zrla1 = rla
+       END IF
+       zrla = zrla1 * TO_RADIANS
+       
+       zarg1 = SIN(zphi) * zsinpol
+       zarg2 = COS(zphi) * zcospol * COS(zrla - zlampol)
+       
+       phi2phirot = ASIN(zarg1 + zarg2) * TO_DEGREES
+    
+    END FUNCTION phi2phirot
+
+
+    FUNCTION rlarot2rla(phirot, rlarot, polphi, pollam, polgam)
+    
+       REAL(dp), INTENT (IN) ::  polphi !< latitude of the rotated north pole
+       REAL(dp), INTENT (IN) ::  pollam !< longitude of the rotated north pole
+       REAL(dp), INTENT (IN) ::  phirot !< latitude in the rotated system
+       REAL(dp), INTENT (IN) ::  rlarot !< longitude in the rotated system
+       REAL(dp), INTENT (IN) ::  polgam !< angle between the north poles of the systems
+       
+       REAL(dp) ::  rlarot2rla          !< latitude in the geographical system
+       
+       REAL(dp) ::  zsinpol, zcospol, zlampol, zphis, zrlas, zarg1, zarg2, zgam
+       
+       zsinpol = SIN(TO_RADIANS * polphi)
+       zcospol = COS(TO_RADIANS * polphi)
+       zlampol = TO_RADIANS * pollam
+       zphis   = TO_RADIANS * phirot
+
+       IF (rlarot > 180.0_dp)  THEN
+          zrlas = rlarot - 360.0_dp
+       ELSE
+          zrlas = rlarot
+       END IF
+       zrlas   = TO_RADIANS * zrlas
+      
+       IF (polgam /= 0.0_dp)  THEN
+          zgam  = TO_RADIANS * polgam
+          zarg1 = SIN(zlampol) * (zcospol * SIN(zphis) - zsinpol*COS(zphis) *  &
+                  (COS(zrlas) * COS(zgam) - SIN(zrlas) * SIN(zgam)) ) -        &
+                  COS(zlampol) * COS(zphis) * ( SIN(zrlas) * COS(zgam) +       &
+                                                COS(zrlas) * SIN(zgam) )
+       
+          zarg2 = COS (zlampol) * (zcospol * SIN(zphis) - zsinpol*COS(zphis) * &
+                  (COS(zrlas) * COS(zgam) - SIN(zrlas) * SIN(zgam)) ) +        &
+                  SIN(zlampol) * COS(zphis) * ( SIN(zrlas) * COS(zgam) +       &
+                                                COS(zrlas) * SIN(zgam) )
+       ELSE
+          zarg1   = SIN (zlampol) * (-zsinpol * COS(zrlas) * COS(zphis)  +     &
+                                      zcospol *              SIN(zphis)) -     &
+                    COS (zlampol) *             SIN(zrlas) * COS(zphis)
+          zarg2   = COS (zlampol) * (-zsinpol * COS(zrlas) * COS(zphis)  +     &
+                                      zcospol *              SIN(zphis)) +     &
+                    SIN (zlampol) *             SIN(zrlas) * COS(zphis)
+       END IF
+      
+       IF (zarg2 == 0.0_dp)  zarg2 = 1.0E-20_dp
+      
+       rlarot2rla = ATAN2(zarg1,zarg2) * TO_DEGREES
+        
+    END FUNCTION rlarot2rla
+
+
+    FUNCTION rla2rlarot ( phi, rla, polphi, pollam, polgam )
+
+       REAL(dp), INTENT (IN) ::  polphi !< latitude of the rotated north pole
+       REAL(dp), INTENT (IN) ::  pollam !< longitude of the rotated north pole
+       REAL(dp), INTENT (IN) ::  phi    !< latitude in geographical system
+       REAL(dp), INTENT (IN) ::  rla    !< longitude in geographical system
+       REAL(dp), INTENT (IN) ::  polgam !< angle between the north poles of the systems
+       
+       REAL (KIND=dp) ::  rla2rlarot    !< latitude in the the rotated system
+       
+       REAL (KIND=dp) ::  zsinpol, zcospol, zlampol, zphi, zrla, zarg1, zarg2, zrla1
+       
+       zsinpol = SIN(polphi * TO_RADIANS)
+       zcospol = COS(polphi * TO_RADIANS)
+       zlampol = pollam * TO_RADIANS
+       zphi    = phi * TO_RADIANS
+
+       IF (rla > 180.0_dp)  THEN
+          zrla1 = rla - 360.0_dp
+       ELSE
+          zrla1 = rla
+       END IF
+       zrla = zrla1 * TO_RADIANS
+       
+       zarg1 = - SIN (zrla-zlampol) * COS(zphi)
+       zarg2 = - zsinpol * COS(zphi) * COS(zrla-zlampol) + zcospol * SIN(zphi)
+       
+       IF (zarg2 == 0.0_dp)  zarg2 = 1.0E-20_dp
+       
+       rla2rlarot = ATAN2 (zarg1,zarg2) * TO_DEGREES
+       
+       IF (polgam /= 0.0_dp )  THEN
+          rla2rlarot = polgam + rla2rlarot
+          IF (rla2rlarot > 180._dp)  rla2rlarot = rla2rlarot - 360.0_dp
+       END IF
+       
+    END FUNCTION rla2rlarot
+
+
+    SUBROUTINE uv2uvrot(u, v, rlat, rlon, pollat, pollon, urot, vrot)
+    
+       REAL(dp), INTENT (IN)  ::  u, v           !< wind components in the true geographical system
+       REAL(dp), INTENT (IN)  ::  rlat, rlon     !< coordinates in the true geographical system
+       REAL(dp), INTENT (IN)  ::  pollat, pollon !< latitude and longitude of the north pole of the rotated grid
+       
+       REAL(dp), INTENT (OUT) ::  urot, vrot     !< wind components in the rotated grid             
+       
+       REAL (dp) ::  zsinpol, zcospol, zlonp, zlat, zarg1, zarg2, znorm
+       
+       zsinpol = SIN(pollat * TO_RADIANS)
+       zcospol = COS(pollat * TO_RADIANS)
+       zlonp   = (pollon-rlon) * TO_RADIANS
+       zlat    = rlat * TO_RADIANS
+       
+       zarg1 = zcospol * SIN(zlonp)
+       zarg2 = zsinpol * COS(zlat) - zcospol * SIN(zlat) * COS(zlonp)
+       znorm = 1.0_dp / SQRT(zarg1*zarg1 + zarg2*zarg2)
+       
+       urot = u * zarg2 * znorm - v * zarg1 * znorm
+       vrot = u * zarg1 * znorm + v * zarg2 * znorm
+    
+    END SUBROUTINE uv2uvrot
+
+
+    SUBROUTINE uvrot2uv (urot, vrot, rlat, rlon, pollat, pollon, u, v)
+    
+       REAL(dp), INTENT(IN) ::  urot, vrot     !< wind components in the rotated grid
+       REAL(dp), INTENT(IN) ::  rlat, rlon     !< latitude and longitude in the true geographical system
+       REAL(dp), INTENT(IN) ::  pollat, pollon !< latitude and longitude of the north pole of the rotated grid
+       
+       REAL(dp), INTENT(OUT) ::  u, v          !< wind components in the true geographical system
+       
+       REAL(dp) ::  zsinpol, zcospol, zlonp, zlat, zarg1, zarg2, znorm
+     
+       zsinpol = SIN(pollat * TO_RADIANS)
+       zcospol = COS(pollat * TO_RADIANS)
+       zlonp   = (pollon-rlon) * TO_RADIANS
+       zlat    = rlat * TO_RADIANS
+     
+       zarg1 = zcospol * SIN(zlonp)
+       zarg2 = zsinpol * COS(zlat) - zcospol * SIN(zlat) * COS(zlonp)
+       znorm = 1.0_dp / SQRT(zarg1*zarg1 + zarg2*zarg2)
+     
+       u =   urot * zarg2 * znorm + vrot * zarg1 * znorm
+       v = - urot * zarg1 * znorm + vrot * zarg2 * znorm
+    
+    END SUBROUTINE uvrot2uv
+
+ END MODULE
+
Index: palm/trunk/UTIL/inifor/src/inifor_types.f90
===================================================================
--- palm/trunk/UTIL/inifor/src/inifor_types.f90	(revision 3447)
+++ palm/trunk/UTIL/inifor/src/inifor_types.f90	(revision 3447)
@@ -0,0 +1,216 @@
+!> @file src/inifor_types.f90
+!------------------------------------------------------------------------------!
+! This file is part of the PALM model system.
+!
+! PALM is free software: you can redistribute it and/or modify it under the
+! terms of the GNU General Public License as published by the Free Software
+! Foundation, either version 3 of the License, or (at your option) any later
+! version.
+!
+! PALM is distributed in the hope that it will be useful, but WITHOUT ANY
+! WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+! A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+!
+! You should have received a copy of the GNU General Public License along with
+! PALM. If not, see <http://www.gnu.org/licenses/>.
+!
+! Copyright 2017-2018 Leibniz Universitaet Hannover
+! Copyright 2017-2018 Deutscher Wetterdienst Offenbach
+!------------------------------------------------------------------------------!
+!
+! Current revisions:
+! -----------------
+! 
+! 
+! Former revisions:
+! -----------------
+! $Id$
+! Renamed source files for compatibilty with PALM build system
+! 
+! 
+! 3395 2018-10-22 17:32:49Z eckhard
+! Added *_is_set LOGICALs to inifor_config type to indicate option invocation
+!     from the command-line 
+! Added 1D index vertical weights lists to support addressing averaging regions
+!     by list of columns instead of index bounds
+! 
+! 
+! 3183 2018-07-27 14:25:55Z suehring
+! Introduced new PALM grid stretching:
+! - Converted vertical grid_definition coordinte variables to pointers
+! Improved command line interface:
+! - Moved INIFOR configuration into a new derived data type
+! Removed unnecessary variables 
+! 
+! 
+! 3182 2018-07-27 13:36:03Z suehring
+! Initial revision
+!
+! 
+!
+! Authors:
+! --------
+! @author Eckhard Kadasch
+!
+! Description:
+! ------------
+!> The types module provides derived data types used in INIFOR.
+!------------------------------------------------------------------------------!
+ MODULE types
+ 
+ USE defs,                                                                     &
+    ONLY:  dp, DATE, PATH, SNAME, LNAME
+ USE netcdf,                                                                   &
+    ONLY:  NF90_MAX_VAR_DIMS, NF90_MAX_NAME
+
+ IMPLICIT NONE
+
+ TYPE inifor_config
+    CHARACTER(LEN=DATE)  ::  start_date           !< String of the FORMAT YYYYMMDDHH indicating the start of the intended PALM-4U simulation
+
+    CHARACTER(LEN=PATH)  ::  input_path           !< Path to the input data file directory
+    CHARACTER(LEN=PATH)  ::  hhl_file             !< Path to the file containing the COSMO-DE HHL variable (height of half layers, i.e. vertical cell faces)
+    CHARACTER(LEN=PATH)  ::  namelist_file        !< Path to the PALM-4U namelist file
+    CHARACTER(LEN=PATH)  ::  output_file          !< Path to the INIFOR output file (i.e. PALM-4U dynamic driver')
+    CHARACTER(LEN=PATH)  ::  soiltyp_file         !< Path to the file containing the COSMO-DE SOILTYP variable (map of COSMO-DE soil types)
+    CHARACTER(LEN=PATH)  ::  static_driver_file   !< Path to the file containing the COSMO-DE SOILTYP variable (map of COSMO-DE soil types)
+
+    CHARACTER(LEN=SNAME) ::  flow_prefix          !< Prefix of flow input files, e.g. 'laf' for COSMO-DE analyses
+    CHARACTER(LEN=SNAME) ::  input_prefix         !< Prefix of all input files, e.g. 'laf' for COSMO-DE analyses
+    CHARACTER(LEN=SNAME) ::  radiation_prefix     !< Prefix of radiation input files, e.g 'laf' for COSMO-DE analyses
+    CHARACTER(LEN=SNAME) ::  soil_prefix          !< Prefix of soil input files, e.g. 'laf' for COSMO-DE analyses
+    CHARACTER(LEN=SNAME) ::  soilmoisture_prefix  !< Prefix of input files for soil moisture spin-up, e.g 'laf' for COSMO-DE analyses
+
+    CHARACTER(LEN=SNAME) ::  averaging_mode
+    CHARACTER(LEN=SNAME) ::  bc_mode
+    CHARACTER(LEN=SNAME) ::  ic_mode
+    CHARACTER(LEN=SNAME) ::  rotation_method
+
+    REAL(dp)             ::  p0
+    REAL(dp)             ::  ug
+    REAL(dp)             ::  vg
+    REAL(dp)             ::  z0                   !< Elevation of the PALM-4U domain above sea level [m]
+    REAL(dp)             ::  averaging_angle      !< latitudal and longitudal width of averaging regions [deg]
+    
+
+    LOGICAL              ::  debug
+    LOGICAL              ::  p0_is_set
+    LOGICAL              ::  ug_is_set
+    LOGICAL              ::  vg_is_set
+    LOGICAL              ::  flow_prefix_is_set          !< 
+    LOGICAL              ::  input_prefix_is_set         !< 
+    LOGICAL              ::  radiation_prefix_is_set     !< 
+    LOGICAL              ::  soil_prefix_is_set          !< 
+    LOGICAL              ::  soilmoisture_prefix_is_set  !< 
+ END TYPE inifor_config
+
+ TYPE grid_definition
+    CHARACTER(LEN=SNAME)  ::  name(3)       !< names of the grid dimensions, e.g. (/'x', 'y', 'z'/) or (/'latitude', 'longitude', 'height'/)
+    CHARACTER(LEN=SNAME)  ::  kind          !< names of the grid dimensions, e.g. (/'x', 'y', 'z'/) or (/'latitude', 'longitude', 'height'/)
+    INTEGER               ::  k_min         !< Index of lowest PALM grid level that is not cut by local COSMO orography; vertically separates interpolation and extrapolation region.
+    INTEGER               ::  nx            !< number of gridpoints in the first dimension
+    INTEGER               ::  ny            !< number of gridpoints in the second dimension
+    INTEGER               ::  nz            !< number of gridpoints in the third dimension, used for PALM points
+    INTEGER               ::  nlev          !< number of COSMO grid levels
+    INTEGER               ::  n_columns     !< number of averaging columns of the source grid 
+    INTEGER, ALLOCATABLE  ::  ii(:,:,:)     !< Given a point (i,j,k) in the PALM-4U grid, ii(i,j,l) gives the x index of the l'th horizontl neighbour on the COSMO-DE grid.
+    INTEGER, ALLOCATABLE  ::  jj(:,:,:)     !< Given a point (i,j,k) in the PALM-4U grid, jj(i,j,l) gives the y index of the l'th horizontl neighbour on the COSMO-DE grid.
+    INTEGER, ALLOCATABLE  ::  kk(:,:,:,:)   !< Given a point (i,j,k) in the PALM-4U grid, kk(i,j,k,l) gives the z index of the l'th vertical neighbour in the intermediate grid.
+    INTEGER, ALLOCATABLE  ::  iii(:)        !< profile averaging neighbour indices 
+    INTEGER, ALLOCATABLE  ::  jjj(:)        !< profile averaging neighbour indices 
+    INTEGER, ALLOCATABLE  ::  kkk(:,:,:)    !< indices of vertical interpolation neightbours, kkk(<source column>, <PALM k level>, <neighbour index>)
+    REAL(dp)              ::  lx            !< domain length in the first dimension [m]
+    REAL(dp)              ::  ly            !< domain length in the second dimension [m]
+    REAL(dp)              ::  x0            !< x coordinate of PALM-4U domain projection centre, i.e. location of zero distortion
+    REAL(dp)              ::  y0            !< y coordinate of PALM-4U domain projection centre, i.e. location of zwro distortion
+    REAL(dp)              ::  z0            !< displacement of the coordinate origin above sea level [m]
+    REAL(dp), ALLOCATABLE ::  x(:)          !< coordinates of cell centers in x direction [m]
+    REAL(dp), ALLOCATABLE ::  y(:)          !< coordinates of cell centers in y direction [m]
+    REAL(dp), POINTER     ::  z(:)          !< coordinates of cell centers in z direction [m]
+    REAL(dp), ALLOCATABLE ::  h(:,:,:)      !< heights grid point for intermediate grids [m]
+    REAL(dp), POINTER     ::  cosmo_h(:,:,:)!< pointer to appropriate COSMO level heights (scalar/w) [m]
+    REAL(dp), POINTER     ::  hhl(:,:,:)    !< heights of half layers (cell faces) above sea level in COSMO-DE, read in from 
+    REAL(dp), POINTER     ::  hfl(:,:,:)    !< heights of full layers (cell centres) above sea level in COSMO-DE, computed as arithmetic average of hhl
+    REAL(dp), POINTER     ::  depths(:)     !< depths of output soil layers, equal the depths of the source model (e.g. COSMO-DE)
+    REAL(dp), ALLOCATABLE ::  xu(:)         !< coordinates of cell faces in x direction [m]
+    REAL(dp), ALLOCATABLE ::  yv(:)         !< coordinates of cell faces in y direction [m]
+    REAL(dp), POINTER     ::  zw(:)         !< coordinates of cell faces in z direction [m]
+    REAL(dp), ALLOCATABLE ::  lat(:)        !< rotated-pole latitudes of scalars (cell centers) of the COSMO-DE grid [rad]
+    REAL(dp), ALLOCATABLE ::  lon(:)        !< rotated-pole longitudes of scalars (cell centres) of the COSMO-DE grid [rad]
+    REAL(dp), ALLOCATABLE ::  latv(:)       !< rotated-pole latitudes of v winds (face centres in latitudal/y direction) [rad]
+    REAL(dp), ALLOCATABLE ::  lonu(:)       !< rotated-pole latitudes of u winds (face centres in longitudal/x direction) [rad]
+    REAL(dp), ALLOCATABLE ::  clat(:,:)     !< latitudes of PALM-4U cell centres in COSMO-DE's rotated-pole grid [rad]
+    REAL(dp), ALLOCATABLE ::  clon(:,:)     !< longitudes of PALM-4U scalars (cell centres) in COSMO-DE's rotated-pole grid [rad]
+    REAL(dp), ALLOCATABLE ::  clatu(:,:)    !< latitudes of PALM-4U u winds (cell faces in u direction) in COSMO-DE's rotated-pole grid [rad]
+    REAL(dp), ALLOCATABLE ::  clonu(:,:)    !< longitudes of PALM-4U u winds (cell faces in u direction) in COSMO-DE's rotated-pole grid [rad]
+    REAL(dp), ALLOCATABLE ::  clatv(:,:)    !< latitudes of PALM-4U v winds (cell faces in v direction) in COSMO-DE's rotated-pole grid [rad]
+    REAL(dp), ALLOCATABLE ::  clonv(:,:)    !< longitudes of PALM-4U v winds (cell faces in v direction) in COSMO-DE's rotated-pole grid [rad]
+    REAL(dp), ALLOCATABLE ::  w_horiz(:,:,:)   !< weights for bilinear horizontal interpolation
+    REAL(dp), ALLOCATABLE ::  w_verti(:,:,:,:) !< weights for linear vertical interpolation
+    REAL(dp), ALLOCATABLE ::  w(:,:,:)      !< vertical interpolation weights, w(<source_column>, <PALM k level>, <neighbour index>) [-]
+ END TYPE grid_definition
+
+
+ TYPE nc_file
+    CHARACTER(LEN=PATH)   ::  name          !< file name
+    INTEGER               ::  dimid_time    !< NetCDF IDs of the time dimension
+    INTEGER               ::  dimids_scl(3) !< NetCDF IDs of the grid dimensions for scalar points x, y, z 
+    INTEGER               ::  dimids_vel(3) !< NetCDF IDs of the grid dimensions for velocity points xu, yu, zu
+    INTEGER               ::  dimids_soil(3)!< NetCDF IDs of the grid dimensions for soil points x, y, depth
+    INTEGER               ::  dimvarid_time !< NetCDF IDs of the time variable
+    INTEGER               ::  dimvarids_scl(3) !< NetCDF IDs of the grid coordinates of scalars x, y, z 
+    INTEGER               ::  dimvarids_vel(3) !< NetCDF IDs of the grid coordinates of velocities xu, yu, zu. Note that velocities are located at mix of both coordinates, e.g. u(xu, y, z).
+    INTEGER               ::  dimvarids_soil(3)!< NetCDF IDs of the grid coordinates for soil points x, y, depth 
+    REAL(dp), POINTER     ::  time(:)       ! vector of output time steps
+ END TYPE nc_file
+
+
+ TYPE nc_var
+    INTEGER                               ::  varid     !< NetCDF ID of the variable
+    INTEGER                               ::  input_id  !< ID of the correpsonding input variables, only valid for output variables
+    INTEGER                               ::  ndim      !< number of NetCDF dimensions
+    INTEGER                               ::  nt        !< number of output time steps
+    INTEGER                               ::  lod       !< NetCDF attribute indicating the PALM-4U level of detail
+    INTEGER, DIMENSION(NF90_MAX_VAR_DIMS) ::  dimids    !< NetCDF IDs of the dimensions
+    INTEGER, DIMENSION(NF90_MAX_VAR_DIMS) ::  dimvarids !< IDs of NetCDF dimension variables
+    INTEGER, DIMENSION(NF90_MAX_VAR_DIMS) ::  dimlen    !< length of NetCDF dimensions
+    CHARACTER(LEN=NF90_MAX_NAME), DIMENSION(NF90_MAX_VAR_DIMS) ::  dimname !< names of NetCDF dimensions
+    CHARACTER(LEN=SNAME)                  ::  name                      !< NetCDF short name of the variable
+    CHARACTER(LEN=LNAME)                  ::  standard_name             !< NetCDF standard name of the variable
+    CHARACTER(LEN=LNAME)                  ::  long_name                 !< NetCDF long name of the variable
+    CHARACTER(LEN=LNAME)                  ::  source                    !< NetCDF attribute indicating the data source for the output
+    CHARACTER(LEN=SNAME)                  ::  units                     !< NetCDF units of the variable
+    CHARACTER(LEN=SNAME)                  ::  kind                      !< Kind of grid
+    CHARACTER(LEN=SNAME)                  ::  task                      !< Processing task that generates this variable, e.g. 'interpolate_2d' or 'average profile'
+    LOGICAL                               ::  to_be_processed = .FALSE. !< INIFOR flag indicating whether variable shall be processed
+    LOGICAL                               ::  is_internal = .FALSE.     !< INIFOR flag indicating whether variable shall be written to netCDF file (.FALSE.) or kept for later (.TRUE.)
+    LOGICAL                               ::  is_read = .FALSE.         !< INIFOR flag indicating whether variable has been read
+    LOGICAL                               ::  is_upside_down  = .FALSE. !< INIFOR flag indicating whether vertical dimension is reversed (typically the case with COSMO-DE atmospheric fields)
+    TYPE(grid_definition), POINTER        ::  grid                      !< Pointer to the corresponding output grid
+    TYPE(grid_definition), POINTER        ::  intermediate_grid         !< Pointer to the corresponding intermediate grid
+    TYPE(grid_definition), POINTER        ::  averaging_grid         !< Pointer to the corresponding intermediate grid
+ END TYPE nc_var
+
+
+ TYPE io_group                                          !< Input/Output group, groups together output variabels that share their input variables. For instance, all boundary surfaces and initialization fields of the potential temperature are base on T and p.
+    INTEGER                          ::  nt             !< maximum number of output time steps across all output variables
+    INTEGER                          ::  nv             !< number of netCDF output variables
+    INTEGER                          ::  n_inputs       !< number of input variables
+    INTEGER                          ::  n_output_quantities !< number of physical quantities required for computing netCDF output variables
+    CHARACTER(LEN=SNAME)             ::  kind           !< kind of I/O group
+    CHARACTER(LEN=PATH), ALLOCATABLE ::  in_files(:)    !< list of nt input files
+    TYPE(nc_var), ALLOCATABLE        ::  out_vars(:)    !< list of output variables 
+    TYPE(nc_var), ALLOCATABLE        ::  in_var_list(:) !< list of input variables
+    LOGICAL                          ::  to_be_processed = .FALSE. !< Inifor flag indicating whether I/O group shall be processed
+    LOGICAL                          ::  is_accumulated = .FALSE.  !< Flag indicating whether this I/O group contains accumulated variables
+    LOGICAL                          ::  is_preprocessed = .FALSE. !< Inifor flag indicating whether the I/O group has been preprocessed
+ END TYPE io_group 
+
+
+ TYPE container
+   REAL(dp), ALLOCATABLE ::  array(:,:,:)
+   LOGICAL               ::  is_preprocessed = .FALSE.
+ END TYPE container
+
+ END MODULE types
+
Index: palm/trunk/UTIL/inifor/src/inifor_util.f90
===================================================================
--- palm/trunk/UTIL/inifor/src/inifor_util.f90	(revision 3447)
+++ palm/trunk/UTIL/inifor/src/inifor_util.f90	(revision 3447)
@@ -0,0 +1,394 @@
+!> @file src/inifor_util.f90
+!------------------------------------------------------------------------------!
+! This file is part of the PALM model system.
+!
+! PALM is free software: you can redistribute it and/or modify it under the
+! terms of the GNU General Public License as published by the Free Software
+! Foundation, either version 3 of the License, or (at your option) any later
+! version.
+!
+! PALM is distributed in the hope that it will be useful, but WITHOUT ANY
+! WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+! A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+!
+! You should have received a copy of the GNU General Public License along with
+! PALM. If not, see <http://www.gnu.org/licenses/>.
+!
+! Copyright 2017-2018 Leibniz Universitaet Hannover
+! Copyright 2017-2018 Deutscher Wetterdienst Offenbach
+!------------------------------------------------------------------------------!
+!
+! Current revisions:
+! -----------------
+! 
+! 
+! Former revisions:
+! -----------------
+! $Id$
+! Renamed source files for compatibilty with PALM build system
+! 
+! 
+! 3395 2018-10-22 17:32:49Z eckhard
+! New routines for computing potential temperature and moist air density
+! Increased number of digits in real-to-str conversion
+! 
+! 3183 2018-07-27 14:25:55Z suehring
+! Improved real-to-string conversion
+! 
+! 
+! 3182 2018-07-27 13:36:03Z suehring
+! Initial revision
+!
+! 
+!
+! Authors:
+! --------
+! @author Eckhard Kadasch
+!
+! Description:
+! ------------
+!> The util module provides miscellaneous utility routines for INIFOR.
+!------------------------------------------------------------------------------!
+ MODULE util
+
+    USE, INTRINSIC :: ISO_C_BINDING,                                           &
+        ONLY :  C_CHAR, C_INT, C_PTR, C_SIZE_T
+    USE defs,                                                                  &
+        ONLY :  dp, PI, DATE, SNAME
+    USE types,                                                                 &
+        ONLY :  grid_definition
+
+    IMPLICIT NONE
+
+    TYPE, BIND(c) :: tm_struct
+       INTEGER(C_INT) :: tm_sec     !< seconds after the minute [0, 61]
+       INTEGER(C_INT) :: tm_min     !< minutes after the hour [0, 59]
+       INTEGER(C_INT) :: tm_hour    !< hours since midnight [0, 23]
+       INTEGER(C_INT) :: tm_mday    !< day of the month [1, 31]
+       INTEGER(C_INT) :: tm_mon     !< month since January [0, 11]
+       INTEGER(C_INT) :: tm_year    !< years since 1900
+       INTEGER(C_INT) :: tm_wday    !< days since Sunday [0, 6]
+       INTEGER(C_INT) :: tm_yday    !< days since January 1st [0, 356]
+       INTEGER(C_INT) :: tm_isdst   !< Daylight Saving Time flag
+    END TYPE
+
+    INTERFACE
+
+       FUNCTION strptime(string, format, timeinfo) BIND(c, NAME='strptime')
+          IMPORT :: C_CHAR, C_SIZE_T, tm_struct
+
+          IMPLICIT NONE
+
+          CHARACTER(KIND=C_CHAR), DIMENSION(*), INTENT(IN) ::  string, format
+          TYPE(tm_struct), INTENT(OUT)                     ::  timeinfo
+
+          INTEGER(C_SIZE_T)                                ::  strptime
+       END FUNCTION
+
+
+       FUNCTION strftime(string, string_len, format, timeinfo) BIND(c, NAME='strftime')
+          IMPORT :: C_CHAR, C_SIZE_T, tm_struct
+
+          IMPLICIT NONE
+
+          CHARACTER(KIND=C_CHAR), DIMENSION(*), INTENT(OUT) ::  string
+          CHARACTER(KIND=C_CHAR), DIMENSION(*), INTENT(IN)  ::  format
+          INTEGER(C_SIZE_T), INTENT(IN)                     ::  string_len
+          TYPE(tm_struct), INTENT(IN)                       ::  timeinfo
+
+          INTEGER(C_SIZE_T)                                 ::  strftime
+       END FUNCTION
+
+
+       FUNCTION mktime(timeinfo) BIND(c, NAME='mktime')
+          IMPORT :: C_PTR, tm_struct
+
+          IMPLICIT NONE
+
+          TYPE(tm_struct), INTENT(IN) ::  timeinfo
+
+          TYPE(C_PTR)                 ::  mktime
+       END FUNCTION
+
+    END INTERFACE
+
+ CONTAINS
+
+    CHARACTER(LEN=DATE) FUNCTION add_hours_to(date_string, hours)
+       CHARACTER(LEN=DATE), INTENT(IN)          ::  date_string
+       INTEGER, INTENT(IN)                      ::  hours
+
+       CHARACTER(KIND=C_CHAR, LEN=*), PARAMETER ::  format_string = "%Y%m%d%H"
+       CHARACTER(KIND=C_CHAR, LEN=DATE)         ::  c_date_string
+       TYPE(C_PTR)                              ::  c_pointer
+       TYPE(tm_struct)                          ::  time_info
+       INTEGER                                  ::  err
+
+       c_date_string = date_string
+
+       ! Convert C string to C tm struct
+       CALL init_tm(time_info)
+       err = strptime(c_date_string, format_string, time_info)
+    
+       ! Manipulate and normalize C tm struct
+       time_info % tm_hour = time_info % tm_hour + hours
+       c_pointer = mktime(time_info)
+
+       ! Convert back to C string
+       err = strftime(c_date_string, INT(DATE, KIND=C_SIZE_T),                 &
+                      format_string, time_info)
+
+       add_hours_to = c_date_string
+    END FUNCTION
+
+
+    SUBROUTINE print_tm(timeinfo)
+       TYPE(tm_struct), INTENT(IN) :: timeinfo
+
+       PRINT *, "sec: ", timeinfo % tm_sec,  &  !< seconds after the minute [0, 61]
+                "min: ", timeinfo % tm_min,  &  !< minutes after the hour [0, 59]
+                "hr:  ", timeinfo % tm_hour, &  !< hours since midnight [0, 23]
+                "day: ", timeinfo % tm_mday, &  !< day of the month [1, 31]
+                "mon: ", timeinfo % tm_mon,  &  !< month since January [0, 11]
+                "yr:  ", timeinfo % tm_year, &  !< years since 1900
+                "wday:", timeinfo % tm_wday, &  !< days since Sunday [0, 6]
+                "yday:", timeinfo % tm_yday, &  !< days since January 1st [0, 356]
+                "dst: ", timeinfo % tm_isdst    !< Daylight Saving time flag
+    END SUBROUTINE print_tm
+
+    
+    SUBROUTINE init_tm(timeinfo)
+       TYPE(tm_struct), INTENT(INOUT) :: timeinfo
+
+       timeinfo % tm_sec   = 0
+       timeinfo % tm_min   = 0
+       timeinfo % tm_hour  = 0
+       timeinfo % tm_mday  = 0
+       timeinfo % tm_mon   = 0
+       timeinfo % tm_year  = 0
+       timeinfo % tm_wday  = 0
+       timeinfo % tm_yday  = 0
+
+       ! We use UTC times, so marking Daylight Saving Time (DST) 'not available'
+       ! (< 0). If this is set to 0, mktime will convert the timeinfo to DST and
+       ! add one hour.
+       timeinfo % tm_isdst = -1
+    END SUBROUTINE init_tm
+
+
+    SUBROUTINE fake_output_3d(a)
+
+       REAL(dp), INTENT(INOUT)       ::  a(:,:,:)
+       REAL(dp)                      ::  lxi, lyi
+       INTEGER ::  i,j,k
+
+       lyi = 2.0_dp * PI / (SIZE(a, 2) - 1.0_dp)
+       lxi = 2.0_dp * PI / (SIZE(a, 1) - 1.0_dp)
+
+       DO k = 1, SIZE(a, 3)
+       DO j = 1, SIZE(a, 2)
+       DO i = 1, SIZE(a, 1)
+           a(i,j,k) = SIN(lxi * i) * COS(lyi * j) + k
+       END DO
+       END DO
+       END DO
+
+    END SUBROUTINE fake_output_3d
+
+
+    SUBROUTINE fake_output_2d(a, offset)
+
+       REAL(dp), INTENT(INOUT) ::  a(:,:)
+       INTEGER, INTENT(IN)     ::  offset
+       REAL(dp)                ::  lxi, lyi
+       INTEGER                 ::  i,j
+
+       lyi = 2.0_dp*PI / (SIZE(a, 2) - 1.0_dp)
+       lxi = 2.0_dp*PI / (SIZE(a, 1) - 1.0_dp)
+
+       a(:,:) = 1.0_dp
+       DO j = 1, SIZE(a, 2)
+       DO i = 1, SIZE(a, 1)
+          a(i,j) = SIN(lxi * i) * COS(lyi * j) + offset
+       END DO
+       END DO
+
+    END SUBROUTINE fake_output_2d
+
+
+    SUBROUTINE linspace(start, stop, array)
+
+       REAL(dp), INTENT(IN)    ::  start, stop
+       REAL(dp), INTENT(INOUT) ::  array(0:)
+       INTEGER                 ::  i, n
+
+       n = UBOUND(array, 1)
+
+       IF (n .EQ. 0)  THEN
+
+          array(0) = start
+
+       ELSE
+
+          DO i = 0, n
+             array(i) = start + REAL(i, dp) / n * (stop - start)
+          END DO
+
+       END IF
+       
+    END SUBROUTINE linspace
+
+
+!------------------------------------------------------------------------------!
+! Description:
+! ------------
+!> Reverse the order of the third (vertical) array dimension from top-down
+!> (COSMO) to bottom-up (PALM)
+!------------------------------------------------------------------------------!
+    SUBROUTINE reverse(input_arr)
+
+       REAL(dp), INTENT(INOUT) ::  input_arr(:,:,:)
+
+       input_arr = input_arr(:,:,size(input_arr, 3):1:-1)
+
+    END SUBROUTINE reverse
+
+
+    SUBROUTINE deaverage(avg_1, t1, avg_2, t2, avg_3, t3)
+
+       REAL(dp), DIMENSION(:,:,:), INTENT(IN)  ::  avg_1, avg_2
+       REAL(dp), INTENT(IN)                    ::  t1, t2, t3
+       REAL(dp), DIMENSION(:,:,:), INTENT(OUT) ::  avg_3
+
+       REAL(dp)                                ::  ti
+ 
+       ti = 1.0_dp / t3
+
+       avg_3(:,:,:) = ti * ( t2 * avg_2(:,:,:) - t1 * avg_1(:,:,:) )
+
+    END SUBROUTINE deaverage
+
+
+    SUBROUTINE get_basic_state(z, beta, p_sl, t_sl, rd, g, p0)
+
+       REAL(dp), INTENT(IN)  ::  z(1:)  !< height [m]
+       REAL(dp), INTENT(IN)  ::  beta   !< logarithmic lapse rate, dT / d ln(p) [K]
+       REAL(dp), INTENT(IN)  ::  p_sl   !< reference pressure [Pa]
+       REAL(dp), INTENT(IN)  ::  t_sl   !< reference tempereature [K]
+       REAL(dp), INTENT(IN)  ::  rd     !< ideal gas constant of dry air [J/kg/K]
+       REAL(dp), INTENT(IN)  ::  g      !< acceleration of Earth's gravity [m/s^2]
+       REAL(dp), INTENT(OUT) ::  p0(1:) !< COSMO-DE basic state pressure [Pa]
+       REAL(dp) ::  root_frac, factor   !< precomputed factors
+
+       factor = - t_sl / beta
+       root_frac = (2.0_dp * beta * g) / (rd * t_sl*t_sl)
+
+       p0(:) = p_sl * EXP(                                                     &
+                  factor * ( 1.0_dp - SQRT( 1.0_dp - root_frac * z(:) ) )  &
+               )
+
+    END SUBROUTINE get_basic_state
+
+
+!------------------------------------------------------------------------------!
+! Description:
+! ------------
+!> Converts the absolute temperature to the potential temperature in place using
+!> the identity a^b = e^(b ln(a)).
+!>
+!>     theta = T * (p_ref/p)^(R/c_p) = T * e^( R/c_p * ln(p_ref/p) )
+!------------------------------------------------------------------------------!
+    SUBROUTINE potential_temperature(t, p, p_ref, r, cp)
+       REAL(dp), DIMENSION(:,:,:), INTENT(INOUT) ::  t
+       REAL(dp), DIMENSION(:,:,:), INTENT(IN)    ::  p
+       REAL(dp), INTENT(IN)                      ::  p_ref, r, cp
+       REAL(dp)                                  ::  rcp
+
+       rcp = r/cp
+       t(:,:,:) =  t(:,:,:) * EXP( rcp * LOG(p_ref / p(:,:,:)) )
+
+    END SUBROUTINE potential_temperature
+
+
+!------------------------------------------------------------------------------!
+! Description:
+! ------------
+!> Compute the density in place of the given temperature (t_rho).
+!------------------------------------------------------------------------------!
+   SUBROUTINE moist_density(t_rho, p, qv, rd, rv)
+       REAL(dp), DIMENSION(:,:,:), INTENT(INOUT) ::  t_rho
+       REAL(dp), DIMENSION(:,:,:), INTENT(IN)    ::  p, qv
+       REAL(dp), INTENT(IN)                      ::  rd, rv
+
+       t_rho(:,:,:) = p(:,:,:) / (                                             &
+          (rv * qv(:,:,:) + rd * (1.0_dp - qv(:,:,:))) * t_rho(:,:,:)          &
+       )
+
+    END SUBROUTINE moist_density
+
+
+    ! Convert a real number to a string in scientific notation
+    ! showing four significant digits.
+    CHARACTER(LEN=SNAME) FUNCTION real_to_str(val, format)
+
+        REAL(dp), INTENT(IN)                   ::  val
+        CHARACTER(LEN=*), OPTIONAL, INTENT(IN) ::  format
+
+        IF (PRESENT(format))  THEN
+           WRITE(real_to_str, format) val
+        ELSE
+           WRITE(real_to_str, '(E11.4)') val
+        END IF
+        real_to_str = ADJUSTL(real_to_str)
+
+    END FUNCTION real_to_str
+
+
+    CHARACTER(LEN=16) FUNCTION real_to_str_f(val)
+
+        REAL(dp), INTENT(IN) ::  val
+
+        WRITE(real_to_str_f, '(F16.8)') val
+        real_to_str_f = ADJUSTL(real_to_str_f)
+
+    END FUNCTION real_to_str_f
+
+
+    CHARACTER(LEN=10) FUNCTION str(val)
+
+        INTEGER, INTENT(IN) ::  val
+
+        WRITE(str, '(i10)') val
+        str = ADJUSTL(str)
+
+    END FUNCTION str
+
+
+    CHARACTER(LEN=30) FUNCTION strs(vals)
+
+        INTEGER, INTENT(IN) ::  vals(:)
+        INTEGER ::  i
+
+        strs = ''
+        DO i = 1, SIZE(vals)
+           strs = TRIM(strs) // TRIM(str(vals(i)))
+        END DO
+
+    END FUNCTION strs
+
+
+    SUBROUTINE normalize_path(path)
+        
+        CHARACTER(LEN=*), INTENT(INOUT) ::  path
+        INTEGER ::  n
+
+        n = LEN_TRIM(path)
+
+        IF (path(n:n) .NE. '/')  THEN
+           path = TRIM(path) // '/'
+        END IF
+
+    END SUBROUTINE
+
+ END MODULE
+
Index: palm/trunk/UTIL/inifor/src/io.f90
===================================================================
--- palm/trunk/UTIL/inifor/src/io.f90	(revision 3401)
+++ 	(revision )
@@ -1,965 +1,0 @@
-!> @file src/io.f90
-!------------------------------------------------------------------------------!
-! This file is part of the PALM model system.
-!
-! PALM is free software: you can redistribute it and/or modify it under the
-! terms of the GNU General Public License as published by the Free Software
-! Foundation, either version 3 of the License, or (at your option) any later
-! version.
-!
-! PALM is distributed in the hope that it will be useful, but WITHOUT ANY
-! WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-! A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
-!
-! You should have received a copy of the GNU General Public License along with
-! PALM. If not, see <http://www.gnu.org/licenses/>.
-!
-! Copyright 2017-2018 Leibniz Universitaet Hannover
-! Copyright 2017-2018 Deutscher Wetterdienst Offenbach
-!------------------------------------------------------------------------------!
-!
-! Current revisions:
-! -----------------
-! 
-! 
-! Former revisions:
-! -----------------
-! $Id$
-! Added command-line options for configuring the computation of geostrophic
-!     winds (--averagin-mode, --averaging-angle)
-! Added command-line option --input-prefix for setting input file prefixes all
-!     at once
-! Added --debug option for more verbose terminal output
-! Added option-specific *_is_set LOGICALs to indicate invocation from the
-!     command-line 
-! Improved error messages in case of empty file-name strings
-! Improved routine naming
-! 
-! 3183 2018-07-27 14:25:55Z suehring
-! Introduced new PALM grid stretching
-! Updated variable names and metadata for PIDS v1.9 compatibility
-! Improved handling of the start date string
-! Better compatibility with older Intel compilers:
-! - avoiding implicit array allocation with new get_netcdf_variable()
-!   subroutine instead of function
-! Improved command line interface:
-! - Added configuration validation
-! - New options to configure input file prefixes
-! - GNU-style short and long option names
-! - Added version and copyright output
-! 
-!
-! 3182 2018-07-27 13:36:03Z suehring
-! Initial revision
-!
-! 
-!
-! Authors:
-! --------
-! @author Eckhard Kadasch
-!
-! Description:
-! ------------
-!> The io module contains the functions needed to read and write netCDF data in
-!> INIFOR.
-!------------------------------------------------------------------------------!
- MODULE io
-
-    USE control
-    USE defs,                                                                  &
-        ONLY:  DATE, SNAME, PATH, PI, dp, hp, TO_RADIANS, TO_DEGREES, VERSION
-    USE netcdf
-    USE types
-    USE util,                                                                  &
-        ONLY:  reverse, str, real_to_str
-
-    IMPLICIT NONE
-
-    INTERFACE get_netcdf_variable
-        MODULE PROCEDURE get_netcdf_variable_int
-        MODULE PROCEDURE get_netcdf_variable_real
-    END INTERFACE get_netcdf_variable
-
-    PRIVATE ::  get_netcdf_variable_int, get_netcdf_variable_real
-
- CONTAINS
-
-    SUBROUTINE get_netcdf_variable_int(in_file, in_var, buffer)
-
-       CHARACTER(LEN=PATH), INTENT(IN)         ::  in_file
-       TYPE(nc_var), INTENT(INOUT)             ::  in_var
-       INTEGER(hp), ALLOCATABLE, INTENT(INOUT) ::  buffer(:,:,:)
-
-       INCLUDE 'get_netcdf_variable.inc'
-
-    END SUBROUTINE get_netcdf_variable_int
-
-
-    SUBROUTINE get_netcdf_variable_real(in_file, in_var, buffer)
-
-       CHARACTER(LEN=PATH), INTENT(IN)      ::  in_file
-       TYPE(nc_var), INTENT(INOUT)          ::  in_var
-       REAL(dp), ALLOCATABLE, INTENT(INOUT) ::  buffer(:,:,:)
-
-       INCLUDE 'get_netcdf_variable.inc'
-
-    END SUBROUTINE get_netcdf_variable_real
-
-
-    SUBROUTINE netcdf_define_variable(var, ncid)
-
-        TYPE(nc_var), INTENT(INOUT) ::  var
-        INTEGER, INTENT(IN)         ::  ncid
-
-        CALL check(nf90_def_var(ncid, var % name, NF90_FLOAT,       var % dimids(1:var % ndim), var % varid))
-        CALL check(nf90_put_att(ncid, var % varid, "long_name",     var % long_name))
-        CALL check(nf90_put_att(ncid, var % varid, "units",         var % units))
-        IF ( var % lod .GE. 0 )  THEN
-           CALL check(nf90_put_att(ncid, var % varid, "lod",           var % lod))
-        END IF 
-        CALL check(nf90_put_att(ncid, var % varid, "source",        var % source))
-        CALL check(nf90_put_att(ncid, var % varid, "_FillValue",    NF90_FILL_REAL))
-
-    END SUBROUTINE netcdf_define_variable
-    
-
-    SUBROUTINE netcdf_get_dimensions(var, ncid)
-
-        TYPE(nc_var), INTENT(INOUT) ::  var
-        INTEGER, INTENT(IN)         ::  ncid
-        INTEGER                     ::  i
-        CHARACTER(SNAME)            ::  null
-
-        ! Remember dimension lenghts for NetCDF writing routine
-        DO i = 1, var % ndim
-           CALL check(nf90_inquire_dimension(ncid, var % dimids(i), &
-                                             name = null, &
-                                             len  = var % dimlen(i)  ) )
-        END DO
-
-    END SUBROUTINE netcdf_get_dimensions
-
-
-!------------------------------------------------------------------------------!
-! Description:
-! ------------
-!> This routine initializes Inifor. This includes parsing command-line
-!> arguments, setting the names of the input and output file names as well as
-!> the name of the input namelist and, subsequently, reading in and setting grid
-!> parameters for the PALM-4U computational grid.
-!------------------------------------------------------------------------------!
-    SUBROUTINE parse_command_line_arguments( cfg )
-
-       TYPE(inifor_config), INTENT(INOUT) ::  cfg
-
-       CHARACTER(LEN=PATH)                ::  option, arg
-       INTEGER                            ::  arg_count, i
-
-       cfg % p0_is_set = .FALSE.
-       cfg % ug_is_set = .FALSE.
-       cfg % vg_is_set = .FALSE.
-       cfg % flow_prefix_is_set = .FALSE.
-       cfg % input_prefix_is_set = .FALSE.
-       cfg % radiation_prefix_is_set = .FALSE.
-       cfg % soil_prefix_is_set = .FALSE.
-       cfg % soilmoisture_prefix_is_set = .FALSE.
-
-       arg_count = COMMAND_ARGUMENT_COUNT()
-       IF (arg_count .GT. 0)  THEN
-
-          ! Every option should have an argument.
-          !IF ( MOD(arg_count, 2) .NE. 0 )  THEN
-          !   message = "Syntax error in command line."
-          !   CALL abort('parse_command_line_arguments', message)
-          !END IF
-          
-          message = "The -clon and -clat command line options are depricated. " // &
-             "Please remove them form your inifor command and specify the " // &
-             "location of the PALM-4U origin either" // NEW_LINE(' ') // &
-             "   - by setting the namelist parameters 'longitude' and 'latitude', or" // NEW_LINE(' ') // &
-             "   - by providing a static driver netCDF file via the -static command-line option."
-
-          i = 1
-          DO WHILE (i .LE. arg_count)
-
-             CALL GET_COMMAND_ARGUMENT( i, option )
-
-             SELECT CASE( TRIM(option) )
-
-             CASE( '--averaging-mode' )
-                CALL get_option_argument( i, arg )
-                cfg % averaging_mode = TRIM(arg)
-
-             CASE( '-date', '-d', '--date' )
-                CALL get_option_argument( i, arg )
-                cfg % start_date = TRIM(arg)
-
-             CASE( '--debug' )
-                cfg % debug = .TRUE.
-
-             ! Elevation of the PALM-4U domain above sea level
-             CASE( '-z0', '-z', '--elevation' )
-                CALL get_option_argument( i, arg )
-                READ(arg, *) cfg % z0
-
-             ! surface pressure, at z0
-             CASE( '-p0', '-r', '--surface-pressure' )
-                cfg % p0_is_set = .TRUE.
-                CALL get_option_argument( i, arg )
-                READ(arg, *) cfg % p0
-
-             ! geostrophic wind in x direction
-             CASE( '-ug', '-u', '--geostrophic-u' )
-                cfg % ug_is_set = .TRUE.
-                CALL get_option_argument( i, arg )
-                READ(arg, *) cfg % ug
-
-             ! geostrophic wind in y direction
-             CASE( '-vg', '-v', '--geostrophic-v' )
-                cfg % vg_is_set = .TRUE.
-                CALL get_option_argument( i, arg )
-                READ(arg, *) cfg % vg
-
-             ! domain centre geographical longitude and latitude
-             CASE( '-clon', '-clat' )
-                CALL abort('parse_command_line_arguments', message)          
-                !READ(arg, *) lambda_cg
-                !lambda_cg = lambda_cg * TO_RADIANS
-                !READ(arg, *) phi_cg
-                !phi_cg = phi_cg * TO_RADIANS
-
-             CASE( '-path', '-p', '--path' )
-                CALL get_option_argument( i, arg )
-                 cfg % input_path = TRIM(arg)
-
-             CASE( '-hhl', '-l', '--hhl-file' )
-                CALL get_option_argument( i, arg )
-                cfg % hhl_file = TRIM(arg)
-
-             CASE( '--input-prefix')
-                CALL get_option_argument( i, arg )
-                cfg % input_prefix = TRIM(arg)
-                cfg % input_prefix_is_set = .TRUE.
-   
-             CASE( '-a', '--averaging-angle' )
-                CALL get_option_argument( i, arg )
-                READ(arg, *) cfg % averaging_angle
-
-             CASE( '-static', '-t', '--static-driver' )
-                CALL get_option_argument( i, arg )
-                cfg % static_driver_file = TRIM(arg)
-
-             CASE( '-soil', '-s', '--soil-file')
-                CALL get_option_argument( i, arg )
-                cfg % soiltyp_file = TRIM(arg)
-
-             CASE( '--flow-prefix')
-                CALL get_option_argument( i, arg )
-                cfg % flow_prefix = TRIM(arg)
-                cfg % flow_prefix_is_set = .TRUE.
-   
-             CASE( '--radiation-prefix')
-                CALL get_option_argument( i, arg )
-                cfg % radiation_prefix = TRIM(arg)
-                cfg % radiation_prefix_is_set = .TRUE.
-   
-             CASE( '--soil-prefix')
-                CALL get_option_argument( i, arg )
-                cfg % soil_prefix = TRIM(arg)
-                cfg % soil_prefix_is_set = .TRUE.
-   
-             CASE( '--soilmoisture-prefix')
-                CALL get_option_argument( i, arg )
-                cfg % soilmoisture_prefix = TRIM(arg)
-                cfg % soilmoisture_prefix_is_set = .TRUE.
-
-             CASE( '-o', '--output' )
-                CALL get_option_argument( i, arg )
-                cfg % output_file = TRIM(arg)
-
-             CASE( '-n', '--namelist' )
-                CALL get_option_argument( i, arg )
-                cfg % namelist_file = TRIM(arg)
-
-             ! initial condition mode: 'profile' / 'volume'
-             CASE( '-mode', '-i', '--init-mode' )
-                CALL get_option_argument( i, arg )
-                cfg % ic_mode = TRIM(arg)
-
-             ! boundary conditions / forcing mode: 'ideal' / 'real'
-             CASE( '-f', '--forcing-mode' )
-                CALL get_option_argument( i, arg )
-                cfg % bc_mode = TRIM(arg)
-
-             CASE( '--version' )
-                CALL print_version()
-                STOP
-
-             CASE( '--help' )
-                CALL print_version()
-                PRINT *, ""
-                PRINT *, "For a list of command-line options have a look at the README file."
-                STOP
-
-             CASE DEFAULT
-                message = "unknown option '" // TRIM(option) // "'."
-                CALL abort('parse_command_line_arguments', message)
-
-             END SELECT
-
-             i = i + 1
-
-          END DO
-
-       ELSE
-            
-          message = "No arguments present, using default input and output files"
-          CALL report('parse_command_line_arguments', message)
-
-       END IF
-
-   END SUBROUTINE parse_command_line_arguments
-
-   
-   SUBROUTINE get_option_argument(i, arg)
-      CHARACTER(LEN=PATH), INTENT(INOUT) ::  arg
-      INTEGER, INTENT(INOUT)             ::  i
-
-      i = i + 1
-      CALL GET_COMMAND_ARGUMENT(i, arg)
-
-   END SUBROUTINE
-
-
-   SUBROUTINE validate_config(cfg)
-      TYPE(inifor_config), INTENT(IN) ::  cfg
-      LOGICAL                         ::  all_files_present
-
-      all_files_present = .TRUE.
-      all_files_present = all_files_present .AND. file_present(cfg % hhl_file, 'HHL')
-      all_files_present = all_files_present .AND. file_present(cfg % namelist_file, 'NAMELIST')
-      all_files_present = all_files_present .AND. file_present(cfg % soiltyp_file, 'SOILTYP')
-
-      ! Only check optional static driver file name, if it has been given.
-      IF (TRIM(cfg % static_driver_file) .NE. '')  THEN
-         all_files_present = all_files_present .AND. file_present(cfg % static_driver_file, 'static driver')
-      END IF
-
-      IF (.NOT. all_files_present)  THEN
-         message = "INIFOR configuration invalid; some input files are missing."
-         CALL abort( 'validate_config', message ) 
-      END IF
-      
-      
-      SELECT CASE( TRIM(cfg % ic_mode) )
-      CASE( 'profile', 'volume')
-      CASE DEFAULT
-         message = "Initialization mode '" // TRIM(cfg % ic_mode) //&
-                   "' is not supported. " //&
-                   "Please select either 'profile' or 'volume', " //&
-                   "or omit the -i/--init-mode/-mode option entirely, which corresponds "//&
-                   "to the latter."
-         CALL abort( 'validate_config', message ) 
-      END SELECT
-
-
-      SELECT CASE( TRIM(cfg % bc_mode) )
-      CASE( 'real', 'ideal')
-      CASE DEFAULT
-         message = "Forcing mode '" // TRIM(cfg % bc_mode) //& 
-                   "' is not supported. " //&
-                   "Please select either 'real' or 'ideal', " //&
-                   "or omit the -f/--forcing-mode option entirely, which corresponds "//&
-                   "to the latter."
-         CALL abort( 'validate_config', message ) 
-      END SELECT
-
-      SELECT CASE( TRIM(cfg % averaging_mode) )
-      CASE( 'level', 'height')
-      CASE DEFAULT
-         message = "Averaging mode '" // TRIM(cfg % averaging_mode) //&
-                   "' is not supported. " //&
-                   "Please select either 'height' or 'level', " //&
-                   "or omit the --averaging-mode option entirely, which corresponds "//&
-                   "to the latter."
-         CALL abort( 'validate_config', message ) 
-      END SELECT
-
-      IF ( cfg % ug_is_set .NEQV. cfg % vg_is_set )  THEN
-         message = "You specified only one component of the geostrophic " // &
-                   "wind. Please specify either both or none."
-         CALL abort( 'validate_config', message )
-      END IF
-
-   END SUBROUTINE validate_config
-
-
-   LOGICAL FUNCTION file_present(filename, kind)
-      CHARACTER(LEN=PATH), INTENT(IN) ::  filename
-      CHARACTER(LEN=*), INTENT(IN)    ::  kind
-
-      IF (LEN(TRIM(filename))==0)  THEN
-
-         file_present = .FALSE.
-         message = "No name was given for the " // TRIM(kind) // " file."
-         CALL report('file_present', message)
-
-      ELSE
-
-         INQUIRE(FILE=filename, EXIST=file_present)
-
-         IF (.NOT. file_present)  THEN
-            message = "The given " // TRIM(kind) // " file '" //               &
-                      TRIM(filename) // "' does not exist."
-            CALL report('file_present', message)
-         END IF
-
-      END IF
-
-   END FUNCTION file_present
-
-
-!------------------------------------------------------------------------------!
-! Description:
-! ------------
-!> This routine initializes the Inifor output file, i.e. the PALM-4U
-!> initializing and forcing data as a NetCDF file.
-!> 
-!> Besides writing metadata, such as global attributes, coordinates, variables,
-!> in the NetCDF file, various NetCDF IDs are saved for later, when Inifor
-!> writes the actual data.
-!------------------------------------------------------------------------------!
-   SUBROUTINE setup_netcdf_dimensions(output_file, palm_grid,                  &
-                                      start_date_string, origin_lon, origin_lat)
-
-       TYPE(nc_file), INTENT(INOUT)      ::  output_file
-       TYPE(grid_definition), INTENT(IN) ::  palm_grid
-       CHARACTER (LEN=DATE), INTENT(IN)  ::  start_date_string
-       REAL(dp), INTENT(IN)              ::  origin_lon, origin_lat
-
-       CHARACTER (LEN=8)     ::  date_string
-       CHARACTER (LEN=10)    ::  time_string
-       CHARACTER (LEN=5)     ::  zone_string
-       CHARACTER (LEN=SNAME) ::  history_string
-       INTEGER               ::  ncid, nx, ny, nz, nt, dimids(3), dimvarids(3)
-       REAL(dp)              ::  z0
-
-       message = "Initializing PALM-4U dynamic driver file '" //               &
-                 TRIM(output_file % name) // "' and setting up dimensions."
-       CALL report('setup_netcdf_dimensions', message)
-
-       ! Create the NetCDF file. NF90_CLOBBER selects overwrite mode.
-#if defined( __netcdf4 )
-       CALL check(nf90_create(TRIM(output_file % name), OR(NF90_CLOBBER, NF90_HDF5), ncid))
-#else
-       CALL check(nf90_create(TRIM(output_file % name), NF90_CLOBBER, ncid))
-#endif
-
-!------------------------------------------------------------------------------
-!- Section 1: Define NetCDF dimensions and coordinates
-!------------------------------------------------------------------------------
-       nt = SIZE(output_file % time)
-       nx = palm_grid % nx
-       ny = palm_grid % ny
-       nz = palm_grid % nz
-       z0 = palm_grid % z0
-
-
-!
-!------------------------------------------------------------------------------
-!- Section 2: Write global NetCDF attributes
-!------------------------------------------------------------------------------
-       CALL date_and_time(DATE=date_string, TIME=time_string, ZONE=zone_string)
-       history_string =                                                        &
-           'Created on '// date_string      //                                 &
-           ' at '       // time_string(1:2) // ':' // time_string(3:4) //      &
-           ' (UTC'      // zone_string // ')'
-
-       CALL check(nf90_put_att(ncid, NF90_GLOBAL, 'title',          'PALM input file for scenario ...'))
-       CALL check(nf90_put_att(ncid, NF90_GLOBAL, 'institution',    'Deutscher Wetterdienst, Offenbach'))
-       CALL check(nf90_put_att(ncid, NF90_GLOBAL, 'author',         'Eckhard Kadasch, eckhard.kadasch@dwd.de'))
-       CALL check(nf90_put_att(ncid, NF90_GLOBAL, 'history',        TRIM(history_string)))
-       CALL check(nf90_put_att(ncid, NF90_GLOBAL, 'references',     '--'))
-       CALL check(nf90_put_att(ncid, NF90_GLOBAL, 'comment',        '--'))
-       CALL check(nf90_put_att(ncid, NF90_GLOBAL, 'origin_lat',     TRIM(real_to_str(origin_lat*TO_DEGREES, '(F18.13)'))))
-       CALL check(nf90_put_att(ncid, NF90_GLOBAL, 'origin_lon',     TRIM(real_to_str(origin_lon*TO_DEGREES, '(F18.13)'))))
-       ! FIXME: This is the elevation relative to COSMO-DE/D2 sea level and does
-       ! FIXME: not necessarily comply with DHHN2016 (c.f. PALM Input Data
-       ! FIXME: Standard v1.9., origin_z)
-       CALL check(nf90_put_att(ncid, NF90_GLOBAL, 'origin_z',       TRIM(real_to_str(z0, '(F18.13)'))))
-       CALL check(nf90_put_att(ncid, NF90_GLOBAL, 'inifor_version', TRIM(VERSION)))
-       CALL check(nf90_put_att(ncid, NF90_GLOBAL, 'palm_version',   '--'))
-
-!
-!
-!------------------------------------------------------------------------------
-!- Section 2a: Define dimensions for cell centers (scalars in soil and atmosph.)
-!------------------------------------------------------------------------------
-       dimids = (/0, 0, 0/) ! reset dimids
-          CALL check( nf90_def_dim(ncid, "x", nx+1, dimids(1)) )
-          CALL check( nf90_def_dim(ncid, "y", ny+1, dimids(2)) )
-          CALL check( nf90_def_dim(ncid, "z", nz, dimids(3)) )
-          output_file % dimids_scl = dimids ! save dimids for later
-
-       dimvarids = (/0, 0, 0/) ! reset dimvarids
-          CALL check(nf90_def_var(ncid, "x", NF90_FLOAT, dimids(1), dimvarids(1)))
-          CALL check(nf90_put_att(ncid, dimvarids(1), "standard_name", "x coordinate of cell centers"))
-          CALL check(nf90_put_att(ncid, dimvarids(1), "units", "m"))
-
-          CALL check(nf90_def_var(ncid, "y", NF90_FLOAT, dimids(2), dimvarids(2)))
-          CALL check(nf90_put_att(ncid, dimvarids(2), "standard_name", "y coordinate of cell centers"))
-          CALL check(nf90_put_att(ncid, dimvarids(2), "units", "m"))
-
-          CALL check(nf90_def_var(ncid, "z", NF90_FLOAT, dimids(3), dimvarids(3)))
-          CALL check(nf90_put_att(ncid, dimvarids(3), "standard_name", "z coordinate of cell centers"))
-          CALL check(nf90_put_att(ncid, dimvarids(3), "units", "m"))
-       output_file % dimvarids_scl = dimvarids ! save dimvarids for later
-
-       ! overwrite third dimid with the one of depth
-       CALL check(nf90_def_dim(ncid, "zsoil", SIZE(palm_grid % depths), dimids(3)) )
-       output_file % dimids_soil = dimids ! save dimids for later
-
-       ! overwrite third dimvarid with the one of depth
-       CALL check(nf90_def_var(ncid, "zsoil", NF90_FLOAT, output_file % dimids_soil(3), dimvarids(3)))
-       CALL check(nf90_put_att(ncid, dimvarids(3), "standard_name", "depth_below_land"))
-       CALL check(nf90_put_att(ncid, dimvarids(3), "positive", "down"))
-       CALL check(nf90_put_att(ncid, dimvarids(3), "units", "m"))
-       output_file % dimvarids_soil = dimvarids ! save dimvarids for later
-!
-!------------------------------------------------------------------------------
-!- Section 2b: Define dimensions for cell faces/velocities
-!------------------------------------------------------------------------------
-       dimids = (/0, 0, 0/) ! reset dimids
-          CALL check(nf90_def_dim(ncid, "xu", nx, dimids(1)) )
-          CALL check(nf90_def_dim(ncid, "yv", ny, dimids(2)) )
-          CALL check(nf90_def_dim(ncid, "zw", nz-1, dimids(3)) )
-       output_file % dimids_vel = dimids ! save dimids for later
-
-       dimvarids = (/0, 0, 0/) ! reset dimvarids
-          CALL check(nf90_def_var(ncid, "xu", NF90_FLOAT, dimids(1), dimvarids(1)))
-          CALL check(nf90_put_att(ncid, dimvarids(1), "standard_name", "x coordinate of cell faces"))
-          CALL check(nf90_put_att(ncid, dimvarids(1), "units", "m"))
-
-          CALL check(nf90_def_var(ncid, "yv", NF90_FLOAT, dimids(2), dimvarids(2)))
-          CALL check(nf90_put_att(ncid, dimvarids(2), "standard_name", "y coordinate of cell faces"))
-          CALL check(nf90_put_att(ncid, dimvarids(2), "units", "m"))
-
-          CALL check(nf90_def_var(ncid, "zw", NF90_FLOAT, dimids(3), dimvarids(3)))
-          CALL check(nf90_put_att(ncid, dimvarids(3), "standard_name", "z coordinate of cell faces"))
-          CALL check(nf90_put_att(ncid, dimvarids(3), "units", "m"))
-       output_file % dimvarids_vel = dimvarids ! save dimvarids for later
-
-!
-!------------------------------------------------------------------------------
-!- Section 2c: Define time dimension
-!------------------------------------------------------------------------------
-       CALL check(nf90_def_dim(ncid, "time", nt, output_file % dimid_time) )
-       CALL check(nf90_def_var(ncid, "time", NF90_FLOAT, &
-                                             output_file % dimid_time, &
-                                             output_file % dimvarid_time))
-       CALL check(nf90_put_att(ncid, output_file % dimvarid_time, "standard_name", "time"))
-       CALL check(nf90_put_att(ncid, output_file % dimvarid_time, "long_name", "time"))
-       CALL check(nf90_put_att(ncid, output_file % dimvarid_time, "units",     &
-                               "seconds since " // start_date_string // " UTC"))
-
-       CALL check(nf90_enddef(ncid))
-
-!
-!------------------------------------------------------------------------------
-!- Section 3: Write grid coordinates
-!------------------------------------------------------------------------------
-       CALL check(nf90_put_var(ncid, output_file % dimvarids_scl(1), palm_grid%x))
-       CALL check(nf90_put_var(ncid, output_file % dimvarids_scl(2), palm_grid%y))
-       CALL check(nf90_put_var(ncid, output_file % dimvarids_scl(3), palm_grid%z))
-
-       CALL check(nf90_put_var(ncid, output_file % dimvarids_vel(1), palm_grid%xu))
-       CALL check(nf90_put_var(ncid, output_file % dimvarids_vel(2), palm_grid%yv))
-       CALL check(nf90_put_var(ncid, output_file % dimvarids_vel(3), palm_grid%zw))
-
-       ! TODO Read in soil depths from input file before this.
-       CALL check(nf90_put_var(ncid, output_file % dimvarids_soil(3), palm_grid%depths))
-
-       ! Write time vector
-       CALL check(nf90_put_var(ncid, output_file % dimvarid_time, output_file % time))
-
-       ! Close the file
-       CALL check(nf90_close(ncid))
-
-    END SUBROUTINE setup_netcdf_dimensions
-
-
-    SUBROUTINE setup_netcdf_variables(filename, output_variable_table)
-
-       CHARACTER (LEN=*), INTENT(IN)        ::  filename
-       TYPE(nc_var), INTENT(INOUT), TARGET  ::  output_variable_table(:)
-       TYPE(nc_var), POINTER                ::  var
-       INTEGER                              ::  i, ncid
-
-       message = "Defining variables in dynamic driver '" // TRIM(filename) // "'."
-       CALL report('setup_netcdf_variables', message)
-
-       CALL check(nf90_open(TRIM(filename), NF90_WRITE, ncid))
-       CALL check(nf90_redef(ncid))
-
-       DO i = 1, SIZE(output_variable_table)
-
-          var => output_variable_table(i)
-
-          IF ( var % to_be_processed )  THEN
-             message = "  variable #" // TRIM(str(i)) // " '" // TRIM(var%name) // "'."
-             CALL report('setup_netcdf_variables', message)
-
-             CALL netcdf_define_variable(var, ncid)
-             CALL netcdf_get_dimensions(var, ncid)
-          END IF
-           
-       END DO
-
-       CALL check(nf90_enddef(ncid))
-       CALL check(nf90_close(ncid))
-
-       message = "Dynamic driver '" // TRIM(filename) // "' initialized successfully."
-       CALL report('setup_netcdf_variables', message)
-
-    END SUBROUTINE setup_netcdf_variables
-
-
-!------------------------------------------------------------------------------!
-! Description:
-! ------------
-!> This routine reads and returns all input variables of the given IO group
-!> It accomodates the data by allocating a container variable that represents a
-!> list of arrays of the same length as the groups variable list. (This list
-!> will typically contain one or two items.) After the container, its members
-!> are allocated one by one with the appropriate, possibly different,
-!> dimensions.
-!>
-!> The 'group' is an INTENT(INOUT) variable so that 'get_netcdf_variable()' can
-!> record netCDF IDs in the 'in_var_list()' member variable.
-!------------------------------------------------------------------------------!
-    SUBROUTINE read_input_variables(group, iter, buffer)
-       TYPE(io_group), INTENT(INOUT), TARGET       ::  group
-       INTEGER, INTENT(IN)                         ::  iter
-       TYPE(container), ALLOCATABLE, INTENT(INOUT) ::  buffer(:)
-       INTEGER                                     ::  hour, buf_id
-       TYPE(nc_var), POINTER                       ::  input_var
-       CHARACTER(LEN=PATH), POINTER                ::  input_file
-       INTEGER                                     ::  ivar, nbuffers
-
-       message = "Reading data for I/O group '" // TRIM(group % in_var_list(1) % name) // "'."
-       CALL report('read_input_variables', message)
-
-       input_file => group % in_files(iter)
-
-!
-!------------------------------------------------------------------------------
-!- Section 1: Load input buffers for accumulated variables
-!------------------------------------------------------------------------------
-       IF (group % kind == 'running average' .OR.                              &
-           group % kind == 'accumulated')  THEN ! radiation budgets, precipitation
-
-          IF (SIZE(group % in_var_list) .GT. 1 ) THEN
-             message = "I/O groups may not contain more than one " // & 
-                       "accumulated variable. Group '" // TRIM(group % kind) //&
-                       "' contains " //                                        &
-                       TRIM( str(SIZE(group % in_var_list)) ) // "."
-             CALL abort('read_input_variables | accumulation', message)
-          END IF
-
-          ! use two buffer arrays
-          nbuffers = 2
-          IF ( .NOT. ALLOCATED( buffer ) )  ALLOCATE( buffer(nbuffers) )
-
-          ! chose correct buffer array
-          hour = iter - 1! hour of the day
-          buf_id = select_buffer(hour)
-
- CALL run_control('time', 'read')
-          IF ( ALLOCATED(buffer(buf_id) % array) )  DEALLOCATE(buffer(buf_id) % array)
- CALL run_control('time', 'alloc')
-
-          input_var => group % in_var_list(1)
-          CALL get_netcdf_variable(input_file, input_var, buffer(buf_id) % array)
-          CALL report('read_input_variables', "Read accumulated " // TRIM(group % in_var_list(1) % name)) 
-
-          IF ( input_var % is_upside_down )  CALL reverse(buffer(buf_id) % array)
- CALL run_control('time', 'comp')
-          
-!------------------------------------------------------------------------------
-!- Section 2: Load input buffers for normal I/O groups
-!------------------------------------------------------------------------------
-       ELSE
-
-          ! Allocate one input buffer per input_variable. If more quantities
-          ! have to be computed than input variables exist in this group,
-          ! allocate more buffers. For instance, in the thermodynamics group,
-          ! there are three input variabels (PP, T, Qv) and four quantities
-          ! necessart (P, Theta, Rho, qv) for the corresponding output fields
-          ! (p0, Theta, qv, ug, and vg)
-          nbuffers = MAX( group % n_inputs, group % n_output_quantities )
-          ALLOCATE( buffer(nbuffers) )
- CALL run_control('time', 'alloc')
-          
-          ! Read in all input variables, leave extra buffers-if any-untouched.
-          DO ivar = 1, group % n_inputs
-
-             input_var => group % in_var_list(ivar)
-
-             ! Check wheather P or PP is present in input file
-             IF (input_var % name == 'P')  THEN
-                input_var % name = TRIM( get_pressure_varname(input_file) )
- CALL run_control('time', 'read')
-             END IF
-
-             CALL get_netcdf_variable(input_file, input_var, buffer(ivar) % array)
-
-             IF ( input_var % is_upside_down )  CALL reverse(buffer(ivar) % array)
- CALL run_control('time', 'comp')
-
-          END DO
-       END IF
-
-    END SUBROUTINE read_input_variables
-
-
-    INTEGER FUNCTION select_buffer(hour)
-       INTEGER, INTENT(IN) ::  hour
-       INTEGER             ::  step
-
-       select_buffer = 0
-       step = MODULO(hour, 3) + 1
-
-       SELECT CASE(step)
-       CASE(1, 3)
-           select_buffer = 1
-       CASE(2)
-           select_buffer = 2
-       CASE DEFAULT
-           message = "Invalid step '" // TRIM(str(step))
-           CALL abort('select_buffer', message)
-       END SELECT
-    END FUNCTION select_buffer
-
-
-!------------------------------------------------------------------------------!
-! Description:
-! ------------
-!> Checks if the input_file contains the absolute pressure, 'P', or the pressure
-!> perturbation, 'PP', and returns the appropriate string.
-!------------------------------------------------------------------------------!
-    CHARACTER(LEN=2) FUNCTION get_pressure_varname(input_file) RESULT(var)
-       CHARACTER(LEN=*) ::  input_file
-       INTEGER          ::  ncid, varid
-
-       CALL check(nf90_open( TRIM(input_file), NF90_NOWRITE, ncid ))
-       IF ( nf90_inq_varid( ncid, 'P', varid ) .EQ. NF90_NOERR )  THEN
-
-          var = 'P'
-
-       ELSE IF ( nf90_inq_varid( ncid, 'PP', varid ) .EQ. NF90_NOERR )  THEN
-
-          var = 'PP'
-          CALL report('get_pressure_var', 'Using PP instead of P')
-
-       ELSE
-
-          message = "Failed to read '" // TRIM(var) // &
-                    "' from file '" // TRIM(input_file) // "'."
-          CALL abort('get_pressure_var', message)
-
-       END IF
-
-       CALL check(nf90_close(ncid))
-
-    END FUNCTION get_pressure_varname
-
-
-    FUNCTION get_netcdf_attribute(filename, attribute) RESULT(attribute_value)
-
-       CHARACTER(LEN=*), INTENT(IN) ::  filename, attribute
-       REAL(dp)                     ::  attribute_value
-
-       INTEGER                      :: ncid
-
-       IF ( nf90_open( TRIM(filename), NF90_NOWRITE, ncid ) == NF90_NOERR )  THEN
-
-          CALL check(nf90_get_att(ncid, NF90_GLOBAL, TRIM(attribute), attribute_value))
-          CALL check(nf90_close(ncid))
-
-       ELSE
-
-          message = "Failed to read '" // TRIM(attribute) // &
-                    "' from file '" // TRIM(filename) // "'."
-          CALL abort('get_netcdf_attribute', message)
-
-       END IF
-
-    END FUNCTION get_netcdf_attribute
-
-
-    SUBROUTINE update_output(var, array, iter, output_file)
-       TYPE(nc_var), INTENT(IN)  ::  var
-       REAL(dp), INTENT(IN)      ::  array(:,:,:)
-       INTEGER, INTENT(IN)       ::  iter
-       TYPE(nc_file), INTENT(IN) ::  output_file
-
-       INTEGER ::  ncid, ndim, start(4), count(4)
-       LOGICAL ::  var_is_time_dependent
-
-       var_is_time_dependent = (                                               &
-          var % dimids( var % ndim ) == output_file % dimid_time               &
-       )
-
-       ! Skip time dimension for output
-       ndim = var % ndim
-       IF ( var_is_time_dependent )  ndim = var % ndim - 1
-
-       start(:)      = (/1,1,1,1/)
-       start(ndim+1) = iter
-       count(1:ndim) = var%dimlen(1:ndim)
-
-       CALL check(nf90_open(output_file % name, NF90_WRITE, ncid))
-
-       ! Reduce dimension of output array according to variable kind
-       SELECT CASE (TRIM(var % kind))
-       
-       CASE ( 'init scalar profile', 'init u profile', 'init v profile',       &
-              'init w profile' )
-
-          CALL check(nf90_put_var( ncid, var%varid, array(1,1,:) ) )
-
-       CASE ( 'init soil', 'init scalar', 'init u', 'init v', 'init w' )
-
-          CALL check(nf90_put_var( ncid, var%varid, array(:,:,:) ) )
-
-       CASE( 'left scalar', 'right scalar', 'left w', 'right w' ) 
-
-          CALL check(nf90_put_var( ncid, var%varid, array(1,:,:),              &
-                                   start=start(1:ndim+1),                      &
-                                   count=count(1:ndim) ) )
-          
-
-          IF (.NOT. SIZE(array, 2) .EQ. var % dimlen(1))  THEN
-             PRINT *, "inifor: update_output: Dimension ", 1, " of variable ", &
-                 TRIM(var % name), " (", var % dimlen(1),                      &
-                 ") does not match the dimension of the output array (",       &
-                 SIZE(array, 2), ")."
-             STOP
-          END IF
-          
-
-       CASE( 'north scalar', 'south scalar', 'north w', 'south w' )
-
-          CALL check(nf90_put_var( ncid, var%varid, array(:,1,:),              &
-                                   start=start(1:ndim+1),                      &
-                                   count=count(1:ndim) ) )
-          
-
-       CASE( 'surface forcing', 'top scalar', 'top w' )
-
-          CALL check(nf90_put_var( ncid, var%varid, array(:,:,1),              &
-                                   start=start(1:ndim+1),                      &
-                                   count=count(1:ndim) ) )
-          
-       CASE ( 'left u', 'right u', 'left v', 'right v' )
-
-          CALL check(nf90_put_var( ncid, var%varid, array(1,:,:),              &
-                                   start=start(1:ndim+1),                      &
-                                   count=count(1:ndim) ) )
-
-       CASE ( 'north u', 'south u', 'north v', 'south v' )
-
-          CALL check(nf90_put_var( ncid, var%varid, array(:,1,:),              &
-                                   start=start(1:ndim+1),                      &
-                                   count=count(1:ndim) ) )
-
-       CASE ( 'top u', 'top v' )
-
-          CALL check(nf90_put_var( ncid, var%varid, array(:,:,1),              &
-                                   start=start(1:ndim+1),                      &
-                                   count=count(1:ndim) ) )
-
-       CASE ( 'time series' )
-
-          CALL check(nf90_put_var( ncid, var%varid, array(1,1,1),              &
-                                   start=start(1:ndim+1) ) )
-
-       CASE ( 'constant scalar profile', 'geostrophic', 'internal profile' )
-
-          CALL check(nf90_put_var( ncid, var%varid, array(1,1,:),              &
-                                   start=start(1:ndim+1),                      &
-                                   count=count(1:ndim) ) )
-
-       CASE ( 'large-scale scalar forcing', 'large-scale w forcing' )
-
-           message = "Doing nothing in terms of writing large-scale forings."
-           CALL report('update_output', message)
-
-       CASE DEFAULT
-
-           message = "Variable kind '" // TRIM(var % kind) //                  &
-                    "' not recognized."
-           CALL abort('update_output', message)
-
-       END SELECT
-
-       CALL check(nf90_close(ncid))
-
-    END SUBROUTINE update_output
-
-
-    SUBROUTINE write_netcdf_variable_2d(var, iter, output_file, buffer)
-       TYPE(nc_var), INTENT(IN)          ::  var
-       INTEGER, INTENT(IN)               ::  iter
-       TYPE(nc_file), INTENT(IN)         ::  output_file
-       REAL(dp), INTENT(IN)              ::  buffer(:,:,:)
-
-       INTEGER ::  ncid, ndim_out, start(4), count(4)
-       LOGICAL ::  last_dimension_is_time
-
-       ndim_out = var % ndim
-
-       last_dimension_is_time = var % dimids( var % ndim ) == output_file % dimid_time
-       IF ( last_dimension_is_time )  THEN
-          ndim_out = ndim_out - 1
-       END IF
-
-       start(:)      = (/1,1,1,iter/)
-       count(1:ndim_out) = var%dimlen(1:ndim_out)
-
-       CALL check(nf90_open(output_file % name, NF90_WRITE, ncid))
-
-       IF (TRIM(var % kind) .EQ. 'left/right scalar')  THEN
-
-          CALL check(nf90_put_var( ncid, var%varid, buffer(1,:,:) ) )
-
-       ELSE IF (TRIM(var % kind) .EQ. 'north/south scalar')  THEN
-
-          CALL check(nf90_put_var( ncid, var%varid, buffer(:,1,:) ) )
-
-       ELSE IF (TRIM(var % kind) .EQ. 'top scalar')  THEN
-
-          CALL check(nf90_put_var( ncid, var%varid, buffer(:,:,1) ) )
-       ELSE
-
-          CALL check(nf90_put_var( ncid, var%varid, buffer ) )
-
-       END IF
-       CALL check(nf90_close(ncid))
-
-    END SUBROUTINE write_netcdf_variable_2d
-
-
-    SUBROUTINE check(status)
-
-       INTEGER, INTENT(IN) ::  status
-
-       IF (status /= nf90_noerr)  THEN
-          message = "NetCDF API call failed with error: " //                     &
-                    TRIM( nf90_strerror(status) )
-          CALL abort('io.check', message) 
-       END IF
-
-    END SUBROUTINE check
-
- END MODULE io
Index: palm/trunk/UTIL/inifor/src/transform.f90
===================================================================
--- palm/trunk/UTIL/inifor/src/transform.f90	(revision 3401)
+++ 	(revision )
@@ -1,1207 +1,0 @@
-!> @file src/transform.f90
-!------------------------------------------------------------------------------!
-! This file is part of the PALM model system.
-!
-! PALM is free software: you can redistribute it and/or modify it under the
-! terms of the GNU General Public License as published by the Free Software
-! Foundation, either version 3 of the License, or (at your option) any later
-! version.
-!
-! PALM is distributed in the hope that it will be useful, but WITHOUT ANY
-! WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-! A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
-!
-! You should have received a copy of the GNU General Public License along with
-! PALM. If not, see <http://www.gnu.org/licenses/>.
-!
-! Copyright 2017-2018 Leibniz Universitaet Hannover
-! Copyright 2017-2018 Deutscher Wetterdienst Offenbach
-!------------------------------------------------------------------------------!
-!
-! Current revisions:
-! -----------------
-! 
-! 
-! Former revisions:
-! -----------------
-! $Id$
-! Switched addressing of averaging regions from index bounds to list of columns
-! Added routines for the computation of geostrophic winds including:
-!    - the downward extrapolation of density (linear) and
-!    - pressure (hydrostatic equation) and
-!    - rotation of geostrophic wind components to PALM frame of reference
-! 
-! 3183 2018-07-27 14:25:55Z suehring
-! Introduced new PALM grid stretching
-! Removed unnecessary subroutine parameters
-! Renamed kcur to k_intermediate
-! 
-! 
-! 3182 2018-07-27 13:36:03Z suehring
-! Initial revision
-!
-! 
-!
-! Authors:
-! --------
-! @author Eckhard Kadasch
-!
-! Description:
-! ------------
-!> The transform module provides INIFOR's low-level transformation and
-!> interpolation routines. The rotated-pole transformation routines phirot2phi,
-!> phi2phirot, rlarot2rla, rla2rlarot, uv2uvrot, and uvrot2uv are adapted from
-!> int2lm's utility routines.
-!------------------------------------------------------------------------------!
- MODULE transform
-
-    USE control
-    USE defs,                                                                  &
-        ONLY: G, TO_DEGREES, TO_RADIANS, PI, dp
-    USE types
-    USE util,                                                                  &       
-        ONLY: real_to_str, str
-
-    IMPLICIT NONE
-
- CONTAINS
-
-!------------------------------------------------------------------------------!
-! Description:
-! ------------
-!> Interpolates linearly in the vertical direction in very column (i,j) of the
-!> output array outvar(i,j,:) using values of the source array invar. In cells
-!> that are outside the COSMO-DE domain, indicated by negative interpolation
-!> weights, extrapolate constantly from the cell above.
-!> 
-!> Input parameters:
-!> -----------------
-!> invar : Array of source data
-!> 
-!> outgrid % kk : Array of vertical neighbour indices. kk(i,j,k,:) contain the
-!>     indices of the two vertical neighbors of PALM-4U point (i,j,k) on the
-!>     input grid corresponding to the source data invar.
-!> 
-!> outgrid % w_verti : Array of weights for vertical linear interpolation
-!>     corresponding to neighbour points indexed by kk.
-!>
-!> Output papameters:
-!> ------------------
-!> outvar : Array of interpolated data
-!------------------------------------------------------------------------------!
-    SUBROUTINE interpolate_1d(in_arr, out_arr, outgrid)
-       TYPE(grid_definition), INTENT(IN) ::  outgrid
-       REAL(dp), INTENT(IN)              ::  in_arr(0:,0:,0:)
-       REAL(dp), INTENT(OUT)             ::  out_arr(0:,0:,:)
-
-       INTEGER :: i, j, k, l, nz
-
-       nz = UBOUND(out_arr, 3)
-
-       DO j = LBOUND(out_arr, 2), UBOUND(out_arr, 2)
-       DO i = LBOUND(out_arr, 1), UBOUND(out_arr, 1)
-       DO k = nz, LBOUND(out_arr, 3), -1
-
-          ! TODO: Remove IF clause and extrapolate based on a critical vertical
-          ! TODO: index marking the lower bound of COSMO-DE data coverage.
-          ! Check for negative interpolation weights indicating grid points 
-          ! below COSMO-DE domain and extrapolate from the top in such cells.
-          IF (outgrid % w_verti(i,j,k,1) < -1.0_dp .AND. k < nz)  THEN
-             out_arr(i,j,k) = out_arr(i,j,k+1)
-          ELSE
-             out_arr(i,j,k) = 0.0_dp
-             DO l = 1, 2
-                out_arr(i,j,k) = out_arr(i,j,k) +                              &
-                    outgrid % w_verti(i,j,k,l) *                               &
-                    in_arr(i,j,outgrid % kk(i,j,k, l) )
-             END DO
-          END IF
-       END DO
-       END DO
-       END DO
-    END SUBROUTINE interpolate_1d
-
-
-!------------------------------------------------------------------------------!
-! Description:
-! ------------
-!> Interpolates bi-linearly in horizontal planes on every k level of the output
-!> array outvar(:,:,k) using values of the source array invar(:,:,:). The source
-!> (invar) and interpolation array (outvar) need to have matching dimensions.
-!>
-!> Input parameters:
-!> -----------------
-!> invar : Array of source data
-!> 
-!> outgrid % ii, % jj : Array of neighbour indices in x and y direction.
-!>     ii(i,j,k,:), and jj(i,j,k,:) contain the four horizontal neighbour points
-!>     of PALM-4U point (i,j,k) on the input grid corresponding to the source
-!>     data invar. (The outgrid carries the relationship with the ingrid in the
-!      form of the interpoaltion weights.)
-!> 
-!> outgrid % w_horiz: Array of weights for horizontal bi-linear interpolation
-!>     corresponding to neighbour points indexed by ii and jj.
-!>
-!> Output papameters:
-!> ------------------
-!> outvar : Array of interpolated data
-!------------------------------------------------------------------------------!
-    SUBROUTINE interpolate_2d(invar, outvar, outgrid, ncvar)
-    ! I index 0-based for the indices of the outvar to be consistent with the
-    ! outgrid indices and interpolation weights.
-       TYPE(grid_definition), INTENT(IN)  ::  outgrid
-       REAL(dp), INTENT(IN)               ::  invar(0:,0:,0:)
-       REAL(dp), INTENT(OUT)              ::  outvar(0:,0:,0:)
-       TYPE(nc_var), INTENT(IN), OPTIONAL ::  ncvar
-
-       INTEGER ::  i, j, k, l
-
-       ! TODO: check if input dimensions are consistent, i.e. ranges are correct
-       IF (UBOUND(outvar, 3) .GT. UBOUND(invar, 3))  THEN
-           message = "Output array for '" // TRIM(ncvar % name) // "' has ' more levels (" // &
-              TRIM(str(UBOUND(outvar, 3))) // ") than input variable ("//&
-              TRIM(str(UBOUND(invar, 3))) // ")."
-           CALL abort('interpolate_2d', message) 
-       END IF
-
-       DO k = 0, UBOUND(outvar, 3)
-       DO j = 0, UBOUND(outvar, 2)
-       DO i = 0, UBOUND(outvar, 1)
-          outvar(i,j,k) = 0.0_dp
-          DO l = 1, 4
-             
-             outvar(i,j,k) = outvar(i,j,k) +                                   &
-                outgrid % w_horiz(i,j,l) * invar( outgrid % ii(i,j,l),         & 
-                                                  outgrid % jj(i,j,l),         &
-                                                  k )
-          END DO
-       END DO
-       END DO
-       END DO
-        
-    END SUBROUTINE interpolate_2d
-
-
-    SUBROUTINE average_2d(in_arr, out_arr, ii, jj)
-       REAL(dp), INTENT(IN)              ::  in_arr(0:,0:,0:)
-       REAL(dp), INTENT(OUT)             ::  out_arr(0:)
-       INTEGER, INTENT(IN), DIMENSION(:) ::  ii, jj
-
-       INTEGER  ::  i, j, k, l
-       REAL(dp) ::  ni
-
-       IF (SIZE(ii) .NE. SIZE(jj))  THEN
-          message = "Length of 'ii' and 'jj' index lists do not match." //     &
-             NEW_LINE(' ') // "ii has " // str(SIZE(ii)) // " elements, " //        &
-             NEW_LINE(' ') // "jj has " // str(SIZE(jj)) // "."
-          CALL abort('average_2d', message)
-       END IF
-
-       DO k = 0, UBOUND(out_arr, 1)
-
-          out_arr(k) = 0.0_dp
-          DO l = 1, UBOUND(ii, 1)
-             i = ii(l)
-             j = jj(l)
-             out_arr(k) = out_arr(k) +&
-                         in_arr(i, j, k)
-          END DO
-
-       END DO
-
-       ni = 1.0_dp / SIZE(ii)
-       out_arr(:) = out_arr(:) * ni
-
-    END SUBROUTINE average_2d
-
-
-    SUBROUTINE interpolate_3d(source_array, palm_array, palm_intermediate, palm_grid)
-       TYPE(grid_definition), INTENT(IN) ::  palm_intermediate, palm_grid
-       REAL(dp), DIMENSION(:,:,:), INTENT(IN)  ::  source_array
-       REAL(dp), DIMENSION(:,:,:), INTENT(OUT) ::  palm_array
-       REAL(dp), DIMENSION(:,:,:), ALLOCATABLE ::  intermediate_array
-       INTEGER ::  nx, ny, nlev
-
-       nx = palm_intermediate % nx
-       ny = palm_intermediate % ny
-       nlev = palm_intermediate % nz ! nlev
-
-       ! Interpolate from COSMO-DE to intermediate grid. Allocating with one
-       ! less point in the vertical, since scalars like T have 50 instead of 51
-       ! points in COSMO-DE.
-       ALLOCATE(intermediate_array(0:nx, 0:ny, 0:nlev-1)) !
-
-       CALL interpolate_2d(source_array, intermediate_array, palm_intermediate)
-
-       ! Interpolate from intermediate grid to palm_grid grid, includes
-       ! extrapolation for cells below COSMO-DE domain.
-       CALL interpolate_1d(intermediate_array, palm_array, palm_grid)
-
-       DEALLOCATE(intermediate_array)
-
-    END SUBROUTINE interpolate_3d
-
-
-    SUBROUTINE average_profile(source_array, profile_array, avg_grid)
-       TYPE(grid_definition), INTENT(IN)          ::  avg_grid
-       REAL(dp), DIMENSION(:,:,:), INTENT(IN)     ::  source_array
-       REAL(dp), DIMENSION(:), INTENT(OUT)        ::  profile_array
-
-       INTEGER ::  i_source, j_source, k_profile, k_source, l, m
-
-       REAL ::  ni_columns
-
-       profile_array(:) = 0.0_dp
-
-       DO l = 1, avg_grid % n_columns
-          i_source = avg_grid % iii(l)
-          j_source = avg_grid % jjj(l)
-
-          DO k_profile = avg_grid % k_min, UBOUND(profile_array, 1) ! PALM levels
-
-             DO m = 1, 2 ! vertical interpolation neighbours
-
-                k_source = avg_grid % kkk(l, k_profile, m)
-
-                profile_array(k_profile) = profile_array(k_profile)    &
-                   + avg_grid % w(l, k_profile, m)                             &
-                   * source_array(i_source, j_source, k_source)
-
-             END DO ! m, vertical interpolation neighbours
-
-          END DO    ! k_profile, PALM levels
-
-       END DO       ! l, horizontal neighbours
-
-       ni_columns = 1.0_dp / avg_grid % n_columns
-       profile_array(:) = profile_array(:) * ni_columns
-
-       ! Extrapolate constant to the bottom
-       profile_array(1:avg_grid % k_min-1) = profile_array(avg_grid % k_min)
-
-    END SUBROUTINE average_profile
-
-
-    SUBROUTINE extrapolate_density(rho, avg_grid)
-       REAL(dp), DIMENSION(:), INTENT(INOUT) ::  rho
-       TYPE(grid_definition), INTENT(IN)     ::  avg_grid
-
-       REAL(dp) ::  drhodz, dz, zk, rhok
-       INTEGER  ::  k_min
-
-       k_min  = avg_grid % k_min
-       zk     = avg_grid % z(k_min)
-       rhok   = rho(k_min)
-       dz     = avg_grid % z(k_min + 1) - avg_grid % z(k_min)
-       drhodz = (rho(k_min + 1) - rho(k_min)) / dz
-
-       rho(1:k_min-1) = rhok + drhodz * (avg_grid % z(1:k_min-1) - zk)
-
-    END SUBROUTINE extrapolate_density
-
-
-    SUBROUTINE extrapolate_pressure(p, rho, avg_grid)
-       REAL(dp), DIMENSION(:), INTENT(IN)    ::  rho
-       REAL(dp), DIMENSION(:), INTENT(INOUT) ::  p
-       TYPE(grid_definition), INTENT(IN)     ::  avg_grid
-
-       REAL(dp) ::  drhodz, dz, zk, rhok
-       INTEGER  ::  k, k_min
-
-       k_min = avg_grid % k_min
-       zk    = avg_grid % z(k_min)
-       rhok  = rho(k_min)
-       dz    = avg_grid % z(k_min + 1) - avg_grid % z(k_min)
-       drhodz = 0.5_dp * (rho(k_min + 1) - rho(k_min)) / dz
-
-       DO k = 1, k_min-1
-          p(k) = constant_density_pressure(p(k_min), zk, rhok, drhodz,         &
-                                           avg_grid % z(k), G)
-       END DO
-
-    END SUBROUTINE extrapolate_pressure
-
-
-!------------------------------------------------------------------------------!
-! Description:
-! ------------
-!> Takes the averaged pressure profile <p> and sets the lowest entry to the
-!> extrapolated pressure at the surface.
-!------------------------------------------------------------------------------!
-    SUBROUTINE get_surface_pressure(p, rho, avg_grid)
-       REAL(dp), DIMENSION(:), INTENT(IN)    ::  rho
-       REAL(dp), DIMENSION(:), INTENT(INOUT) ::  p
-       TYPE(grid_definition), INTENT(IN)     ::  avg_grid
-
-       REAL(dp) ::  drhodz, dz, zk, rhok
-       INTEGER  ::  k, k_min
-
-       k_min = avg_grid % k_min
-       zk    = avg_grid % z(k_min)
-       rhok  = rho(k_min)
-       dz    = avg_grid % z(k_min + 1) - avg_grid % z(k_min)
-       drhodz = 0.5_dp * (rho(k_min + 1) - rho(k_min)) / dz
-
-       p(1) = constant_density_pressure(p(k_min), zk, rhok, drhodz,            &
-                                        0.0, G)
-
-    END SUBROUTINE get_surface_pressure
-
-
-    FUNCTION constant_density_pressure(pk, zk, rhok, drhodz, z, g)  RESULT(p)
-
-       REAL(dp), INTENT(IN)  ::  pk, zk, rhok, drhodz, g, z
-       REAL(dp) ::  p
-
-       p = pk + ( zk - z ) * g * ( rhok + 0.5*drhodz * (zk - z) )
-
-    END FUNCTION constant_density_pressure
-
-!-----------------------------------------------------------------------------!
-! Description:
-! -----------
-!> This routine computes profiles of the two geostrophic wind components ug and
-!> vg.
-!-----------------------------------------------------------------------------!
-    SUBROUTINE geostrophic_winds(p_north, p_south, p_east, p_west, rho, f3,    &
-                                 Lx, Ly, phi_n, lam_n, phi_g, lam_g, ug, vg)
-
-    REAL(dp), DIMENSION(:), INTENT(IN)  ::  p_north, p_south, p_east, p_west,  &
-                                            rho
-    REAL(dp), INTENT(IN)                ::  f3, Lx, Ly, phi_n, lam_n, phi_g, lam_g
-    REAL(dp), DIMENSION(:), INTENT(OUT) ::  ug, vg
-    REAL(dp)                            ::  facx, facy
-
-    facx = 1.0_dp / (Lx * f3)
-    facy = 1.0_dp / (Ly * f3)
-    ug(:) = - facy / rho(:) * (p_north(:) - p_south(:))
-    vg(:) =   facx / rho(:) * (p_east(:) - p_west(:))
-
-    CALL rotate_vector_field(                                                  &
-       ug, vg, angle = meridian_convergence_rotated(phi_n, lam_n, phi_g, lam_g)&
-    )
-
-    END SUBROUTINE geostrophic_winds
-
-
-!-----------------------------------------------------------------------------!
-! Description:
-! -----------
-!> This routine computes the inverse Plate Carree projection, i.e. in projects
-!> Cartesian coordinates (x,y) onto a sphere. It returns the latitude and
-!> lngitude of a geographical system centered at x0 and y0.
-!-----------------------------------------------------------------------------!
-    SUBROUTINE inv_plate_carree(x, y, x0, y0, r, lat, lon)
-       REAL(dp), INTENT(IN)  ::  x(:), y(:), x0, y0, r
-       REAL(dp), INTENT(OUT) ::  lat(:), lon(:)
-       
-       REAL(dp) :: ri
-
-       ! TODO check dimensions of lat/lon and y/x match
-
-       ri = 1.0_dp / r
-       
-       lat(:) = (y(:) - y0) * ri
-       lon(:) = (x(:) - x0) * ri
-    END SUBROUTINE 
-
-
-!-----------------------------------------------------------------------------!
-! Description:
-! ------------
-!> Computes the reverse Plate-Carree projection of a x or y position on a
-!> Cartesian grid.
-!>
-!> Input parameters:
-!> -----------------
-!> xy : x or y coordinate of the Cartasian grid point [m].
-!>
-!> xy0 : x or y coordinate that coincides with the origin of the underlying
-!>     sperical system (crossing point of the equator and prime meridian) [m].
-!>
-!> r : Radius of the of the underlying sphere, e.g. EARTH_RADIUS [m].
-!> 
-!> Returns:
-!> --------
-!> project : Longitude (in case xy = x) or latitude (xy = y) of the given input
-!>     coordinate xy.
-!------------------------------------------------------------------------------!
-    ELEMENTAL REAL(dp) FUNCTION project(xy, xy0, r)
-       REAL(dp), INTENT(IN)  ::  xy, xy0, r
-       REAL(dp) :: ri
-
-       ! If this elemental function is called with a large array as xy, it is
-       ! computationally more efficient to precompute the inverse radius and
-       ! then muliply.
-       ri = 1.0_dp / r
-
-       project = (xy - xy0) * ri
-
-    END FUNCTION project
-
-
-    REAL(dp) FUNCTION phic_to_phin(phi_c)
-        REAL(dp), INTENT(IN) ::  phi_c
-
-        phic_to_phin = 0.5_dp * PI - ABS(phi_c)
-
-    END FUNCTION phic_to_phin
-
-    
-    REAL(dp) FUNCTION lamc_to_lamn(phi_c, lam_c)
-       REAL(dp), INTENT(IN) ::  phi_c, lam_c
-        
-       lamc_to_lamn = lam_c
-       IF (phi_c > 0.0_dp)  THEN
-          lamc_to_lamn = lam_c - SIGN(PI, lam_c)
-       END IF
-
-    END FUNCTION lamc_to_lamn
-
-
-    REAL(dp) FUNCTION gamma_from_hemisphere(phi_cg, phi_ref)
-       REAL(dp), INTENT(IN) ::  phi_cg, phi_ref
-       LOGICAL ::  palm_centre_is_south_of_cosmo_origin
-       
-       palm_centre_is_south_of_cosmo_origin = (phi_cg < phi_ref)
-
-       IF (palm_centre_is_south_of_cosmo_origin)  THEN
-           gamma_from_hemisphere = PI
-       ELSE
-           gamma_from_hemisphere = 0.0_dp
-       END IF
-    END FUNCTION gamma_from_hemisphere
-
-
-!------------------------------------------------------------------------------!
-! Description:
-! ------------
-!> Computes the geographical coordinates corresponding to the given rotated-pole
-!> coordinates.
-!>
-!> In INIFOR, this routine is used to convert coordinates between two
-!> rotated-pole systems: COSMO-DE's rotated-pole system, and one centred at the
-!> PALM-4U domain centre. In this case, the PALM-4U system is thought of as the
-!> rotated-pole system and the routine is used to rotate back to COSMO-DE's
-!> system which is thought of as the geographical one.
-!> 
-!> Input parameters:
-!> -----------------
-!> phir(:), lamr(: ): latitudes and longitudes of the rotated-pole grid
-!> 
-!> phip, lamp: latitude and longitude of the rotated north pole
-!>
-!> gam: "angle between the north poles. If [gam] is not present, the other
-!>       system is the real geographical system." (original phiro2rot
-!>       description)
-!> 
-!> Output parameters:
-!> ------------------
-!> phi(:,:), lam(:,:): geographical latitudes and logitudes
-!------------------------------------------------------------------------------!
-    SUBROUTINE rotate_to_cosmo(phir, lamr, phip, lamp, phi, lam, gam)
-       REAL(dp), INTENT(IN)  ::  phir(0:), lamr(0:), phip, lamp, gam
-       REAL(dp), INTENT(OUT) ::  phi(0:,0:), lam(0:,0:)
-
-       INTEGER ::  i, j
-       
-       IF ( SIZE(phi, 1) .NE. SIZE(lam, 1) .OR. &
-            SIZE(phi, 2) .NE. SIZE(lam, 2) )  THEN
-          PRINT *, "inifor: rotate_to_cosmo: Dimensions of phi and lambda do not match. Dimensions are:"
-          PRINT *, "inifor: rotate_to_cosmo: phi: ", SIZE(phi, 1), SIZE(phi, 2)
-          PRINT *, "inifor: rotate_to_cosmo: lam: ", SIZE(lam, 1), SIZE(lam, 2)
-          STOP
-       END IF
-
-       IF ( SIZE(phir) .NE. SIZE(phi, 2) .OR. &
-            SIZE(lamr) .NE. SIZE(phi, 1) )  THEN
-          PRINT *, "inifor: rotate_to_cosmo: Dimensions of phir and lamr do not match. Dimensions are:"
-          PRINT *, "inifor: rotate_to_cosmo: phir: ", SIZE(phir), SIZE(phi, 2)
-          PRINT *, "inifor: rotate_to_cosmo: lamr: ", SIZE(lamr), SIZE(phi, 1)
-          STOP
-       END IF
-       
-       DO j = 0, UBOUND(phir, 1)
-          DO i = 0, UBOUND(lamr, 1)
-
-             phi(i,j) = phirot2phi(phir(j) * TO_DEGREES,                       &
-                                   lamr(i) * TO_DEGREES,                       &
-                                   phip * TO_DEGREES,                          &
-                                   lamp * TO_DEGREES,                          &
-                                   gam  * TO_DEGREES) * TO_RADIANS
-
-             lam(i,j) = rlarot2rla(phir(j) * TO_DEGREES,                       &
-                                   lamr(i) * TO_DEGREES,                       &
-                                   phip * TO_DEGREES,                          &
-                                   lamp * TO_DEGREES,                          &
-                                   gam  * TO_DEGREES) * TO_RADIANS
-
-          END DO
-       END DO
-
-    END SUBROUTINE rotate_to_cosmo
-       
-
-    SUBROUTINE rotate_vector_field(x, y, angle)
-       REAL(dp), DIMENSION(:), INTENT(INOUT) :: x, y  !< x and y coodrinate in arbitrary units
-       REAL(dp), INTENT(IN)                  :: angle !< rotation angle [deg]
-
-       INTEGER  :: i
-       REAL(dp) :: sine, cosine, v_rot(2), rotation(2,2)
-
-       sine = SIN(angle * TO_RADIANS)
-       cosine = COS(angle * TO_RADIANS)
-       ! RESAHPE() fills columns first, so the rotation matrix becomes
-       !
-       ! rotation = [ cosine   -sine  ]
-       !            [  sine    cosine ]
-       rotation = RESHAPE( (/cosine, sine, -sine, cosine/), (/2, 2/) )
-
-       DO i = LBOUND(x, 1), UBOUND(x, 1)
-
-          v_rot(:) = MATMUL(rotation, (/x(i), y(i)/))
-
-          x(i) = v_rot(1)
-          y(i) = v_rot(2)
-
-       END DO
-
-    END SUBROUTINE rotate_vector_field
-
-
-
-!------------------------------------------------------------------------------!
-! Description:
-! ------------
-!> This routine computes the local meridian convergence between a rotated-pole
-!> and a geographical system using the Eq. (6) given in the DWD manual
-!> 
-!>    Baldauf et al. (2018), Beschreibung des operationelle KuÌrzestfrist-
-!>    vorhersagemodells COSMO-D2 und COSMO-D2-EPS und seiner Ausgabe in die
-!>    Datenbanken des DWD.
-!>    https://www.dwd.de/SharedDocs/downloads/DE/modelldokumentationen/nwv/cosmo_d2/cosmo_d2_dbbeschr_aktuell.pdf?__blob=publicationFile&v=2
-!>
-    FUNCTION meridian_convergence_rotated(phi_n, lam_n, phi_g, lam_g)          &
-       RESULT(delta)
-
-       REAL(dp), INTENT(IN) ::  phi_n, lam_n, phi_g, lam_g
-       REAL(dp)             ::  delta
-
-       delta = atan2( COS(phi_n) * SIN(lam_n - lam_g),                         &
-                      COS(phi_g) * SIN(phi_n) -                                &
-                      SIN(phi_g) * COS(phi_n) * COS(lam_n - lam_g) )
-
-    END FUNCTION meridian_convergence_rotated
-
-!------------------------------------------------------------------------------!
-! Description:
-! ------------
-!> Compute indices of PALM-4U grid point neighbours in the target 
-!> system (COSMO-DE) by rounding up and down. (i,j) are the indices of
-!> the PALM-4U grid and (ii(i,j,1-4), jj(i,j,1-4)) contain the indices
-!> of the its four neigbouring points in the COSMO-DE grid.
-!>
-!>
-!>                     COSMO-DE grid
-!>                     -------------
-!>           jj, lat
-!>              ^        j
-!>              |         \          i
-!>  jj(i,j,2/3) + ... 2 ---\--------/------ 3
-!>              |     | ^   \      /        |
-!>              |     | |wp  \    /         |
-!>              |     | v     \  /          |
-!>       latpos + ............ o/ (i,j)     |
-!>              |     |        :            |
-!>              |     |        :<----wl---->|
-!>  jj(i,j,1/4) + ... 1 -------:----------- 4
-!>              |     :        :            :
-!>              |     :        :            :
-!>              |     :      lonpos         :
-!>              L-----+--------+------------+------> ii, lon 
-!>               ii(i,j,1/2)        ii(i,j,3/4)
-!>
-!> 
-!> Input parameters:
-!> -----------------
-!> source_lat, source_lon : (rotated-pole) coordinates of the source grid (e.g.
-!>    COSMO-DE)
-!>
-!> source_dxi, source_dyi : inverse grid spacings of the source grid.
-!>
-!> target_lat, target_lon : (rotated-pole) coordinates of the target grid (e.g.
-!>    COSMO-DE)
-!> 
-!> Output parameters:
-!> ------------------
-!> palm_ii, palm_jj : x and y index arrays of horizontal neighbour columns
-!> 
-!------------------------------------------------------------------------------!
-    SUBROUTINE find_horizontal_neighbours(cosmo_lat, cosmo_lon,                &
-                                          palm_clat, palm_clon,                &
-                                          palm_ii, palm_jj)
-
-       REAL(dp), DIMENSION(0:), INTENT(IN)        ::  cosmo_lat, cosmo_lon
-       REAL(dp), DIMENSION(0:,0:), INTENT(IN)     ::  palm_clat, palm_clon
-       REAL(dp)                                   ::  cosmo_dxi, cosmo_dyi
-       INTEGER, DIMENSION(0:,0:,1:), INTENT(OUT)  ::  palm_ii, palm_jj
-
-       REAL(dp) ::  lonpos, latpos, lon0, lat0
-       INTEGER  ::  i, j
-
-       lon0 = cosmo_lon(0)
-       lat0 = cosmo_lat(0)
-       cosmo_dxi = 1.0_dp / (cosmo_lon(1) - cosmo_lon(0))
-       cosmo_dyi = 1.0_dp / (cosmo_lat(1) - cosmo_lat(0))
-
-       DO j = 0, UBOUND(palm_clon, 2)!palm_grid % ny
-       DO i = 0, UBOUND(palm_clon, 1)!palm_grid % nx
-          ! Compute the floating point index corrseponding to PALM-4U grid point
-          ! location along target grid (COSMO-DE) axes.
-          lonpos = (palm_clon(i,j) - lon0) * cosmo_dxi
-          latpos = (palm_clat(i,j) - lat0) * cosmo_dyi
-
-          IF (lonpos < 0.0 .OR. latpos < 0.0)  THEN
-             PRINT *, " Error while finding neighbours: lonpos or latpos out of bounds!"
-             PRINT *, "     (i,j) = (", i, ",",j,")"
-             PRINT *, "      lonpos ", lonpos*TO_DEGREES, ", latpos ", latpos*TO_DEGREES
-             PRINT *, "        lon0 ", lon0  *TO_DEGREES,   ", lat0   ", lat0*TO_DEGREES
-             PRINT *, "    PALM lon ", palm_clon(i,j)*TO_DEGREES,   ", PALM lat ",palm_clat(i,j)*TO_DEGREES
-             STOP
-          END IF
-
-          palm_ii(i,j,1) = FLOOR(lonpos)
-          palm_ii(i,j,2) = FLOOR(lonpos)
-          palm_ii(i,j,3) = CEILING(lonpos)
-          palm_ii(i,j,4) = CEILING(lonpos)
-
-          palm_jj(i,j,1) = FLOOR(latpos)
-          palm_jj(i,j,2) = CEILING(latpos)
-          palm_jj(i,j,3) = CEILING(latpos)
-          palm_jj(i,j,4) = FLOOR(latpos)
-       END DO
-       END DO
-
-    END SUBROUTINE find_horizontal_neighbours
-
-    
-    SUBROUTINE find_vertical_neighbours_and_weights_interp( palm_grid,         &
-                                                            palm_intermediate )
-       TYPE(grid_definition), INTENT(INOUT) ::  palm_grid
-       TYPE(grid_definition), INTENT(IN)    ::  palm_intermediate
-
-       INTEGER  ::  i, j, k, nx, ny, nz, nlev, k_intermediate
-       LOGICAL  ::  point_is_below_grid, point_is_above_grid,                  &
-                    point_is_in_current_cell
-       REAL(dp) ::  current_height, column_base, column_top, h_top, h_bottom,  &
-                    weight
-
-       nx   = palm_grid % nx
-       ny   = palm_grid % ny
-       nz   = palm_grid % nz
-       nlev = palm_intermediate % nz
-
-       ! in each column of the fine grid, find vertical neighbours of every cell
-       DO j = 0, ny
-       DO i = 0, nx
-
-          k_intermediate = 0
-
-          column_base = palm_intermediate % h(i,j,0)
-          column_top  = palm_intermediate % h(i,j,nlev)
-
-          ! scan through palm_grid column and set neighbour indices in
-          ! case current_height is either below column_base, in the current
-          ! cell, or above column_top. Keep increasing current cell index until
-          ! the current cell overlaps with the current_height.
-          DO k = 1, nz
-
-             ! Memorize the top and bottom boundaries of the coarse cell and the
-             ! current height within it
-             current_height = palm_grid % z(k) + palm_grid % z0
-             h_top    = palm_intermediate % h(i,j,k_intermediate+1)
-             h_bottom = palm_intermediate % h(i,j,k_intermediate)
-
-             point_is_above_grid = (current_height > column_top) !22000m, very unlikely
-             point_is_below_grid = (current_height < column_base)
-
-             point_is_in_current_cell = (                                      &
-                current_height >= h_bottom .AND.                               &
-                current_height <  h_top                                        &
-             )
-
-             ! set default weights
-             palm_grid % w_verti(i,j,k,1:2) = 0.0_dp
-
-             IF (point_is_above_grid)  THEN
-
-                palm_grid % kk(i,j,k,1:2) = nlev
-                palm_grid % w_verti(i,j,k,1:2) = - 2.0_dp
-
-                message = "PALM-4U grid extends above COSMO-DE model top."
-                CALL abort('find_vertical_neighbours_and_weights', message)
-
-             ELSE IF (point_is_below_grid)  THEN
-
-                palm_grid % kk(i,j,k,1:2) = 0
-                palm_grid % w_verti(i,j,k,1:2) = - 2.0_dp
-
-             ELSE
-                ! cycle through intermediate levels until current
-                ! intermediate-grid cell overlaps with current_height
-                DO WHILE (.NOT. point_is_in_current_cell .AND. k_intermediate <= nlev-1)
-                   k_intermediate = k_intermediate + 1
-
-                   h_top    = palm_intermediate % h(i,j,k_intermediate+1)
-                   h_bottom = palm_intermediate % h(i,j,k_intermediate)
-                   point_is_in_current_cell = (                                &
-                      current_height >= h_bottom .AND.                         &
-                      current_height <  h_top                                  &
-                   )
-                END DO
-
-                IF (k_intermediate > nlev-1)  THEN
-                   message = "Index " // TRIM(str(k_intermediate)) //          &
-                             " is above intermediate grid range."
-                   CALL abort('find_vertical_neighbours', message)
-                END IF
-   
-                palm_grid % kk(i,j,k,1) = k_intermediate
-                palm_grid % kk(i,j,k,2) = k_intermediate + 1
-
-                ! copmute vertical weights
-                weight = (h_top - current_height) / (h_top - h_bottom)
-                palm_grid % w_verti(i,j,k,1) = weight
-                palm_grid % w_verti(i,j,k,2) = 1.0_dp - weight
-             END IF
-
-          END DO
-
-       END DO
-       END DO
-
-    END SUBROUTINE find_vertical_neighbours_and_weights_interp
-
-
-    SUBROUTINE find_vertical_neighbours_and_weights_average( avg_grid )
-       TYPE(grid_definition), INTENT(INOUT) ::  avg_grid
-
-       INTEGER  ::  i, j, k_palm, k_intermediate, l, nlev
-       LOGICAL  ::  point_is_below_grid, point_is_above_grid,                  &
-                    point_is_in_current_cell
-       REAL(dp) ::  current_height, column_base, column_top, h_top, h_bottom,  &
-                    weight
-
-
-       avg_grid % k_min = LBOUND(avg_grid % z, 1)
-
-       nlev = SIZE(avg_grid % cosmo_h, 3)
-
-       ! in each column of the fine grid, find vertical neighbours of every cell
-       DO l = 1, avg_grid % n_columns
-
-          i = avg_grid % iii(l)
-          j = avg_grid % jjj(l)
-
-          column_base = avg_grid % cosmo_h(i,j,1)
-          column_top  = avg_grid % cosmo_h(i,j,nlev)
-
-          ! scan through avg_grid column until and set neighbour indices in
-          ! case current_height is either below column_base, in the current
-          ! cell, or above column_top. Keep increasing current cell index until
-          ! the current cell overlaps with the current_height.
-          k_intermediate = 1 !avg_grid % cosmo_h is indezed 1-based.
-          DO k_palm = 1, avg_grid % nz
-
-             ! Memorize the top and bottom boundaries of the coarse cell and the
-             ! current height within it
-             current_height = avg_grid % z(k_palm) + avg_grid % z0
-             h_top    = avg_grid % cosmo_h(i,j,k_intermediate+1)
-             h_bottom = avg_grid % cosmo_h(i,j,k_intermediate)
-
-             point_is_above_grid = (current_height > column_top) !22000m, very unlikely
-             point_is_below_grid = (current_height < column_base)
-
-             point_is_in_current_cell = (                                      &
-                current_height >= h_bottom .AND.                               &
-                current_height <  h_top                                        &
-             )
-
-             ! set default weights
-             avg_grid % w(l,k_palm,1:2) = 0.0_dp
-
-             IF (point_is_above_grid)  THEN
-
-                avg_grid % kkk(l,k_palm,1:2) = nlev
-                avg_grid % w(l,k_palm,1:2) = - 2.0_dp
-
-                message = "PALM-4U grid extends above COSMO-DE model top."
-                CALL abort('find_vertical_neighbours_and_weights_average', message)
-
-             ELSE IF (point_is_below_grid)  THEN
-
-                avg_grid % kkk(l,k_palm,1:2) = 0
-                avg_grid % w(l,k_palm,1:2) = - 2.0_dp
-                avg_grid % k_min = MAX(k_palm + 1, avg_grid % k_min)
-             ELSE
-                ! cycle through intermediate levels until current
-                ! intermediate-grid cell overlaps with current_height
-                DO WHILE (.NOT. point_is_in_current_cell .AND. k_intermediate <= nlev-1)
-                   k_intermediate = k_intermediate + 1
-
-                   h_top    = avg_grid % cosmo_h(i,j,k_intermediate+1)
-                   h_bottom = avg_grid % cosmo_h(i,j,k_intermediate)
-                   point_is_in_current_cell = (                                &
-                      current_height >= h_bottom .AND.                         &
-                      current_height <  h_top                                  &
-                   )
-                END DO
-
-                ! k_intermediate = 48 indicates the last section (indices 48 and 49), i.e.
-                ! k_intermediate = 49 is not the beginning of a valid cell.
-                IF (k_intermediate > nlev-1)  THEN
-                   message = "Index " // TRIM(str(k_intermediate)) //          &
-                             " is above intermediate grid range."
-                   CALL abort('find_vertical_neighbours', message)
-                END IF
-   
-                avg_grid % kkk(l,k_palm,1) = k_intermediate
-                avg_grid % kkk(l,k_palm,2) = k_intermediate + 1
-
-                ! copmute vertical weights
-                weight = (h_top - current_height) / (h_top - h_bottom)
-                avg_grid % w(l,k_palm,1) = weight
-                avg_grid % w(l,k_palm,2) = 1.0_dp - weight
-             END IF
-
-          END DO ! k, PALM levels
-       END DO ! l, averaging columns
- 
-    END SUBROUTINE find_vertical_neighbours_and_weights_average
-
-!------------------------------------------------------------------------------!
-! Description:
-! ------------
-!> Compute the four weights for horizontal bilinear interpolation given the
-!> coordinates clon(i,j) clat(i,j) of the PALM-4U grid in the COSMO-DE
-!> rotated-pole grid and the neightbour indices ii(i,j,1-4) and jj(i,j,1-4).
-!>
-!> Input parameters:
-!> -----------------
-!> palm_grid % clon : longitudes of PALM-4U scalars (cell centres) in COSMO-DE's rotated-pole grid [rad]
-!>
-!> palm_grid % clat : latitudes of PALM-4U cell centres in COSMO-DE's rotated-pole grid [rad]
-!>
-!> cosmo_grid % lon : rotated-pole longitudes of scalars (cell centres) of the COSMO-DE grid [rad] 
-!>
-!> cosmo_grid % lat : rotated-pole latitudes of scalars (cell centers) of the COSMO-DE grid [rad]
-!>
-!> cosmo_grid % dxi : inverse grid spacing in the first dimension [m^-1]
-!>
-!> cosmo_grid % dyi : inverse grid spacing in the second dimension [m^-1]
-!>
-!> Output parameters:
-!> ------------------
-!> palm_grid % w_horiz(:,:,1-4) : weights for bilinear horizontal interpolation
-!
-!                               COSMO-DE grid
-!                               -------------
-!                     jj, lat
-!                        ^        j
-!                        |         \          i
-!            jj(i,j,2/3) + ... 2 ---\--------/------ 3
-!                        |     | ^   \      /        |
-!                        |     | |wp  \    /         |
-!                        |     | v     \  /          |
-!                 latpos + ............ o/ (i,j)     |
-!                        |     |        :            |
-!                        |     |        :<----wl---->|
-!            jj(i,j,1/4) + ... 1 -------:----------- 4
-!                        |     :        :            :
-!                        |     :        :            :
-!                        |     :      lonpos         :
-!                        L-----+--------+------------+------> ii, lon 
-!                         ii(i,j,1/2)        ii(i,j,3/4)
-!          
-    SUBROUTINE compute_horizontal_interp_weights(cosmo_lat, cosmo_lon,         &
-       palm_clat, palm_clon, palm_ii, palm_jj, palm_w_horiz)
-       
-       REAL(dp), DIMENSION(0:), INTENT(IN)        ::  cosmo_lat, cosmo_lon
-       REAL(dp)                                   ::  cosmo_dxi, cosmo_dyi
-       REAL(dp), DIMENSION(0:,0:), INTENT(IN)     ::  palm_clat, palm_clon
-       INTEGER, DIMENSION(0:,0:,1:), INTENT(IN)   ::  palm_ii, palm_jj
-
-       REAL(dp), DIMENSION(0:,0:,1:), INTENT(OUT) ::  palm_w_horiz
-
-       REAL(dp) ::  wl, wp
-       INTEGER  ::  i, j
-
-       cosmo_dxi = 1.0_dp / (cosmo_lon(1) - cosmo_lon(0))
-       cosmo_dyi = 1.0_dp / (cosmo_lat(1) - cosmo_lat(0))
-
-       DO j = 0, UBOUND(palm_clon, 2)
-       DO i = 0, UBOUND(palm_clon, 1)
-      
-          ! weight in lambda direction
-          wl = ( cosmo_lon(palm_ii(i,j,4)) - palm_clon(i,j) ) * cosmo_dxi
-
-          ! weight in phi direction
-          wp = ( cosmo_lat(palm_jj(i,j,2)) - palm_clat(i,j) ) * cosmo_dyi
-
-          IF (wl > 1.0_dp .OR. wl < 0.0_dp)  THEN
-              message = "Horizontal weight wl = " // TRIM(real_to_str(wl)) //   &
-                        " is out bounds."
-              CALL abort('compute_horizontal_interp_weights', message)
-          END IF
-          IF (wp > 1.0_dp .OR. wp < 0.0_dp)  THEN
-              message = "Horizontal weight wp = " // TRIM(real_to_str(wp)) //   &
-                        " is out bounds."
-              CALL abort('compute_horizontal_interp_weights', message)
-          END IF
-
-          palm_w_horiz(i,j,1) = wl * wp
-          palm_w_horiz(i,j,2) = wl * (1.0_dp - wp)
-          palm_w_horiz(i,j,3) = (1.0_dp - wl) * (1.0_dp - wp)
-          palm_w_horiz(i,j,4) = 1.0_dp - SUM( palm_w_horiz(i,j,1:3) )
-
-       END DO
-       END DO
-       
-    END SUBROUTINE compute_horizontal_interp_weights
-
-
-!------------------------------------------------------------------------------!
-! Description:
-! ------------
-!> Interpolates u and v components of velocities located at cell faces to the
-!> cell centres by averaging neighbouring values.
-!>
-!> This routine is designed to be used with COSMO-DE arrays where there are the
-!> same number of grid points for scalars (centres) and velocities (faces). In
-!> COSMO-DE the velocity points are staggared one half grid spaceing up-grid
-!> which means the first centre point has to be omitted and is set to zero.
-    SUBROUTINE centre_velocities(u_face, v_face, u_centre, v_centre)
-       REAL(dp), DIMENSION(0:,0:,0:), INTENT(IN)  ::  u_face, v_face
-       REAL(dp), DIMENSION(0:,0:,0:), INTENT(OUT) ::  u_centre, v_centre
-       INTEGER ::  nx, ny
-
-       nx = UBOUND(u_face, 1)
-       ny = UBOUND(u_face, 2)
-
-       u_centre(0,:,:)  = 0.0_dp
-       u_centre(1:,:,:) = 0.5_dp * ( u_face(0:nx-1,:,:) + u_face(1:,:,:) )
-
-       v_centre(:,0,:)  = 0.0_dp
-       v_centre(:,1:,:) = 0.5_dp * ( v_face(:,0:ny-1,:) + v_face(:,1:,:) )
-    END SUBROUTINE centre_velocities
-
-
-    FUNCTION phirot2phi (phirot, rlarot, polphi, pollam, polgam)
-    
-       REAL(dp), INTENT (IN) ::  polphi      !< latitude of the rotated north pole
-       REAL(dp), INTENT (IN) ::  pollam      !< longitude of the rotated north pole
-       REAL(dp), INTENT (IN) ::  phirot      !< latitude in the rotated system
-       REAL(dp), INTENT (IN) ::  rlarot      !< longitude in the rotated system
-       REAL(dp), INTENT (IN) ::  polgam      !< angle between the north poles of the systems
-
-       REAL(dp)              ::  phirot2phi  !< latitude in the geographical system
-       
-       REAL(dp)              ::  zsinpol, zcospol, zphis, zrlas, zarg, zgam
-    
-       zsinpol = SIN(polphi * TO_RADIANS)
-       zcospol = COS(polphi * TO_RADIANS)
-       zphis   = phirot * TO_RADIANS
-
-       IF (rlarot > 180.0_dp)  THEN
-          zrlas = rlarot - 360.0_dp
-       ELSE
-          zrlas = rlarot
-       END IF
-       zrlas = zrlas * TO_RADIANS
-     
-       IF (polgam /= 0.0_dp)  THEN
-          zgam = polgam * TO_RADIANS
-          zarg = zsinpol * SIN (zphis) +                                       &
-                 zcospol * COS(zphis) * ( COS(zrlas) * COS(zgam) -             &
-                                          SIN(zgam)  * SIN(zrlas) )
-       ELSE
-          zarg = zcospol * COS (zphis) * COS (zrlas) + zsinpol * SIN (zphis)
-       END IF
-      
-       phirot2phi = ASIN (zarg) * TO_DEGREES
-    
-    END FUNCTION phirot2phi
-
-
-    FUNCTION phi2phirot (phi, rla, polphi, pollam)
-    
-       REAL(dp), INTENT (IN) ::  polphi !< latitude of the rotated north pole
-       REAL(dp), INTENT (IN) ::  pollam !< longitude of the rotated north pole
-       REAL(dp), INTENT (IN) ::  phi    !< latitude in the geographical system
-       REAL(dp), INTENT (IN) ::  rla    !< longitude in the geographical system
-       
-       REAL(dp) ::  phi2phirot          !< longitude in the rotated system
-       
-       REAL(dp) ::  zsinpol, zcospol, zlampol, zphi, zrla, zarg1, zarg2, zrla1
-       
-       zsinpol = SIN(polphi * TO_RADIANS)
-       zcospol = COS(polphi * TO_RADIANS)
-       zlampol = pollam * TO_RADIANS
-       zphi    = phi * TO_RADIANS
-
-       IF (rla > 180.0_dp)  THEN
-          zrla1 = rla - 360.0_dp
-       ELSE
-          zrla1 = rla
-       END IF
-       zrla = zrla1 * TO_RADIANS
-       
-       zarg1 = SIN(zphi) * zsinpol
-       zarg2 = COS(zphi) * zcospol * COS(zrla - zlampol)
-       
-       phi2phirot = ASIN(zarg1 + zarg2) * TO_DEGREES
-    
-    END FUNCTION phi2phirot
-
-
-    FUNCTION rlarot2rla(phirot, rlarot, polphi, pollam, polgam)
-    
-       REAL(dp), INTENT (IN) ::  polphi !< latitude of the rotated north pole
-       REAL(dp), INTENT (IN) ::  pollam !< longitude of the rotated north pole
-       REAL(dp), INTENT (IN) ::  phirot !< latitude in the rotated system
-       REAL(dp), INTENT (IN) ::  rlarot !< longitude in the rotated system
-       REAL(dp), INTENT (IN) ::  polgam !< angle between the north poles of the systems
-       
-       REAL(dp) ::  rlarot2rla          !< latitude in the geographical system
-       
-       REAL(dp) ::  zsinpol, zcospol, zlampol, zphis, zrlas, zarg1, zarg2, zgam
-       
-       zsinpol = SIN(TO_RADIANS * polphi)
-       zcospol = COS(TO_RADIANS * polphi)
-       zlampol = TO_RADIANS * pollam
-       zphis   = TO_RADIANS * phirot
-
-       IF (rlarot > 180.0_dp)  THEN
-          zrlas = rlarot - 360.0_dp
-       ELSE
-          zrlas = rlarot
-       END IF
-       zrlas   = TO_RADIANS * zrlas
-      
-       IF (polgam /= 0.0_dp)  THEN
-          zgam  = TO_RADIANS * polgam
-          zarg1 = SIN(zlampol) * (zcospol * SIN(zphis) - zsinpol*COS(zphis) *  &
-                  (COS(zrlas) * COS(zgam) - SIN(zrlas) * SIN(zgam)) ) -        &
-                  COS(zlampol) * COS(zphis) * ( SIN(zrlas) * COS(zgam) +       &
-                                                COS(zrlas) * SIN(zgam) )
-       
-          zarg2 = COS (zlampol) * (zcospol * SIN(zphis) - zsinpol*COS(zphis) * &
-                  (COS(zrlas) * COS(zgam) - SIN(zrlas) * SIN(zgam)) ) +        &
-                  SIN(zlampol) * COS(zphis) * ( SIN(zrlas) * COS(zgam) +       &
-                                                COS(zrlas) * SIN(zgam) )
-       ELSE
-          zarg1   = SIN (zlampol) * (-zsinpol * COS(zrlas) * COS(zphis)  +     &
-                                      zcospol *              SIN(zphis)) -     &
-                    COS (zlampol) *             SIN(zrlas) * COS(zphis)
-          zarg2   = COS (zlampol) * (-zsinpol * COS(zrlas) * COS(zphis)  +     &
-                                      zcospol *              SIN(zphis)) +     &
-                    SIN (zlampol) *             SIN(zrlas) * COS(zphis)
-       END IF
-      
-       IF (zarg2 == 0.0_dp)  zarg2 = 1.0E-20_dp
-      
-       rlarot2rla = ATAN2(zarg1,zarg2) * TO_DEGREES
-        
-    END FUNCTION rlarot2rla
-
-
-    FUNCTION rla2rlarot ( phi, rla, polphi, pollam, polgam )
-
-       REAL(dp), INTENT (IN) ::  polphi !< latitude of the rotated north pole
-       REAL(dp), INTENT (IN) ::  pollam !< longitude of the rotated north pole
-       REAL(dp), INTENT (IN) ::  phi    !< latitude in geographical system
-       REAL(dp), INTENT (IN) ::  rla    !< longitude in geographical system
-       REAL(dp), INTENT (IN) ::  polgam !< angle between the north poles of the systems
-       
-       REAL (KIND=dp) ::  rla2rlarot    !< latitude in the the rotated system
-       
-       REAL (KIND=dp) ::  zsinpol, zcospol, zlampol, zphi, zrla, zarg1, zarg2, zrla1
-       
-       zsinpol = SIN(polphi * TO_RADIANS)
-       zcospol = COS(polphi * TO_RADIANS)
-       zlampol = pollam * TO_RADIANS
-       zphi    = phi * TO_RADIANS
-
-       IF (rla > 180.0_dp)  THEN
-          zrla1 = rla - 360.0_dp
-       ELSE
-          zrla1 = rla
-       END IF
-       zrla = zrla1 * TO_RADIANS
-       
-       zarg1 = - SIN (zrla-zlampol) * COS(zphi)
-       zarg2 = - zsinpol * COS(zphi) * COS(zrla-zlampol) + zcospol * SIN(zphi)
-       
-       IF (zarg2 == 0.0_dp)  zarg2 = 1.0E-20_dp
-       
-       rla2rlarot = ATAN2 (zarg1,zarg2) * TO_DEGREES
-       
-       IF (polgam /= 0.0_dp )  THEN
-          rla2rlarot = polgam + rla2rlarot
-          IF (rla2rlarot > 180._dp)  rla2rlarot = rla2rlarot - 360.0_dp
-       END IF
-       
-    END FUNCTION rla2rlarot
-
-
-    SUBROUTINE uv2uvrot(u, v, rlat, rlon, pollat, pollon, urot, vrot)
-    
-       REAL(dp), INTENT (IN)  ::  u, v           !< wind components in the true geographical system
-       REAL(dp), INTENT (IN)  ::  rlat, rlon     !< coordinates in the true geographical system
-       REAL(dp), INTENT (IN)  ::  pollat, pollon !< latitude and longitude of the north pole of the rotated grid
-       
-       REAL(dp), INTENT (OUT) ::  urot, vrot     !< wind components in the rotated grid             
-       
-       REAL (dp) ::  zsinpol, zcospol, zlonp, zlat, zarg1, zarg2, znorm
-       
-       zsinpol = SIN(pollat * TO_RADIANS)
-       zcospol = COS(pollat * TO_RADIANS)
-       zlonp   = (pollon-rlon) * TO_RADIANS
-       zlat    = rlat * TO_RADIANS
-       
-       zarg1 = zcospol * SIN(zlonp)
-       zarg2 = zsinpol * COS(zlat) - zcospol * SIN(zlat) * COS(zlonp)
-       znorm = 1.0_dp / SQRT(zarg1*zarg1 + zarg2*zarg2)
-       
-       urot = u * zarg2 * znorm - v * zarg1 * znorm
-       vrot = u * zarg1 * znorm + v * zarg2 * znorm
-    
-    END SUBROUTINE uv2uvrot
-
-
-    SUBROUTINE uvrot2uv (urot, vrot, rlat, rlon, pollat, pollon, u, v)
-    
-       REAL(dp), INTENT(IN) ::  urot, vrot     !< wind components in the rotated grid
-       REAL(dp), INTENT(IN) ::  rlat, rlon     !< latitude and longitude in the true geographical system
-       REAL(dp), INTENT(IN) ::  pollat, pollon !< latitude and longitude of the north pole of the rotated grid
-       
-       REAL(dp), INTENT(OUT) ::  u, v          !< wind components in the true geographical system
-       
-       REAL(dp) ::  zsinpol, zcospol, zlonp, zlat, zarg1, zarg2, znorm
-     
-       zsinpol = SIN(pollat * TO_RADIANS)
-       zcospol = COS(pollat * TO_RADIANS)
-       zlonp   = (pollon-rlon) * TO_RADIANS
-       zlat    = rlat * TO_RADIANS
-     
-       zarg1 = zcospol * SIN(zlonp)
-       zarg2 = zsinpol * COS(zlat) - zcospol * SIN(zlat) * COS(zlonp)
-       znorm = 1.0_dp / SQRT(zarg1*zarg1 + zarg2*zarg2)
-     
-       u =   urot * zarg2 * znorm + vrot * zarg1 * znorm
-       v = - urot * zarg1 * znorm + vrot * zarg2 * znorm
-    
-    END SUBROUTINE uvrot2uv
-
- END MODULE
-
Index: palm/trunk/UTIL/inifor/src/types.f90
===================================================================
--- palm/trunk/UTIL/inifor/src/types.f90	(revision 3401)
+++ 	(revision )
@@ -1,212 +1,0 @@
-!> @file src/types.f90
-!------------------------------------------------------------------------------!
-! This file is part of the PALM model system.
-!
-! PALM is free software: you can redistribute it and/or modify it under the
-! terms of the GNU General Public License as published by the Free Software
-! Foundation, either version 3 of the License, or (at your option) any later
-! version.
-!
-! PALM is distributed in the hope that it will be useful, but WITHOUT ANY
-! WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-! A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
-!
-! You should have received a copy of the GNU General Public License along with
-! PALM. If not, see <http://www.gnu.org/licenses/>.
-!
-! Copyright 2017-2018 Leibniz Universitaet Hannover
-! Copyright 2017-2018 Deutscher Wetterdienst Offenbach
-!------------------------------------------------------------------------------!
-!
-! Current revisions:
-! -----------------
-! 
-! 
-! Former revisions:
-! -----------------
-! $Id$
-! Added *_is_set LOGICALs to inifor_config type to indicate option invocation
-!     from the command-line 
-! Added 1D index vertical weights lists to support addressing averaging regions
-!     by list of columns instead of index bounds
-! 
-! 
-! 3183 2018-07-27 14:25:55Z suehring
-! Introduced new PALM grid stretching:
-! - Converted vertical grid_definition coordinte variables to pointers
-! Improved command line interface:
-! - Moved INIFOR configuration into a new derived data type
-! Removed unnecessary variables 
-! 
-! 
-! 3182 2018-07-27 13:36:03Z suehring
-! Initial revision
-!
-! 
-!
-! Authors:
-! --------
-! @author Eckhard Kadasch
-!
-! Description:
-! ------------
-!> The types module provides derived data types used in INIFOR.
-!------------------------------------------------------------------------------!
- MODULE types
- 
- USE defs,                                                                     &
-    ONLY:  dp, DATE, PATH, SNAME, LNAME
- USE netcdf,                                                                   &
-    ONLY:  NF90_MAX_VAR_DIMS, NF90_MAX_NAME
-
- IMPLICIT NONE
-
- TYPE inifor_config
-    CHARACTER(LEN=DATE)  ::  start_date           !< String of the FORMAT YYYYMMDDHH indicating the start of the intended PALM-4U simulation
-
-    CHARACTER(LEN=PATH)  ::  input_path           !< Path to the input data file directory
-    CHARACTER(LEN=PATH)  ::  hhl_file             !< Path to the file containing the COSMO-DE HHL variable (height of half layers, i.e. vertical cell faces)
-    CHARACTER(LEN=PATH)  ::  namelist_file        !< Path to the PALM-4U namelist file
-    CHARACTER(LEN=PATH)  ::  output_file          !< Path to the INIFOR output file (i.e. PALM-4U dynamic driver')
-    CHARACTER(LEN=PATH)  ::  soiltyp_file         !< Path to the file containing the COSMO-DE SOILTYP variable (map of COSMO-DE soil types)
-    CHARACTER(LEN=PATH)  ::  static_driver_file   !< Path to the file containing the COSMO-DE SOILTYP variable (map of COSMO-DE soil types)
-
-    CHARACTER(LEN=SNAME) ::  flow_prefix          !< Prefix of flow input files, e.g. 'laf' for COSMO-DE analyses
-    CHARACTER(LEN=SNAME) ::  input_prefix         !< Prefix of all input files, e.g. 'laf' for COSMO-DE analyses
-    CHARACTER(LEN=SNAME) ::  radiation_prefix     !< Prefix of radiation input files, e.g 'laf' for COSMO-DE analyses
-    CHARACTER(LEN=SNAME) ::  soil_prefix          !< Prefix of soil input files, e.g. 'laf' for COSMO-DE analyses
-    CHARACTER(LEN=SNAME) ::  soilmoisture_prefix  !< Prefix of input files for soil moisture spin-up, e.g 'laf' for COSMO-DE analyses
-
-    CHARACTER(LEN=SNAME) ::  averaging_mode
-    CHARACTER(LEN=SNAME) ::  bc_mode
-    CHARACTER(LEN=SNAME) ::  ic_mode
-    CHARACTER(LEN=SNAME) ::  rotation_method
-
-    REAL(dp)             ::  p0
-    REAL(dp)             ::  ug
-    REAL(dp)             ::  vg
-    REAL(dp)             ::  z0                   !< Elevation of the PALM-4U domain above sea level [m]
-    REAL(dp)             ::  averaging_angle      !< latitudal and longitudal width of averaging regions [deg]
-    
-
-    LOGICAL              ::  debug
-    LOGICAL              ::  p0_is_set
-    LOGICAL              ::  ug_is_set
-    LOGICAL              ::  vg_is_set
-    LOGICAL              ::  flow_prefix_is_set          !< 
-    LOGICAL              ::  input_prefix_is_set         !< 
-    LOGICAL              ::  radiation_prefix_is_set     !< 
-    LOGICAL              ::  soil_prefix_is_set          !< 
-    LOGICAL              ::  soilmoisture_prefix_is_set  !< 
- END TYPE inifor_config
-
- TYPE grid_definition
-    CHARACTER(LEN=SNAME)  ::  name(3)       !< names of the grid dimensions, e.g. (/'x', 'y', 'z'/) or (/'latitude', 'longitude', 'height'/)
-    CHARACTER(LEN=SNAME)  ::  kind          !< names of the grid dimensions, e.g. (/'x', 'y', 'z'/) or (/'latitude', 'longitude', 'height'/)
-    INTEGER               ::  k_min         !< Index of lowest PALM grid level that is not cut by local COSMO orography; vertically separates interpolation and extrapolation region.
-    INTEGER               ::  nx            !< number of gridpoints in the first dimension
-    INTEGER               ::  ny            !< number of gridpoints in the second dimension
-    INTEGER               ::  nz            !< number of gridpoints in the third dimension, used for PALM points
-    INTEGER               ::  nlev          !< number of COSMO grid levels
-    INTEGER               ::  n_columns     !< number of averaging columns of the source grid 
-    INTEGER, ALLOCATABLE  ::  ii(:,:,:)     !< Given a point (i,j,k) in the PALM-4U grid, ii(i,j,l) gives the x index of the l'th horizontl neighbour on the COSMO-DE grid.
-    INTEGER, ALLOCATABLE  ::  jj(:,:,:)     !< Given a point (i,j,k) in the PALM-4U grid, jj(i,j,l) gives the y index of the l'th horizontl neighbour on the COSMO-DE grid.
-    INTEGER, ALLOCATABLE  ::  kk(:,:,:,:)   !< Given a point (i,j,k) in the PALM-4U grid, kk(i,j,k,l) gives the z index of the l'th vertical neighbour in the intermediate grid.
-    INTEGER, ALLOCATABLE  ::  iii(:)        !< profile averaging neighbour indices 
-    INTEGER, ALLOCATABLE  ::  jjj(:)        !< profile averaging neighbour indices 
-    INTEGER, ALLOCATABLE  ::  kkk(:,:,:)    !< indices of vertical interpolation neightbours, kkk(<source column>, <PALM k level>, <neighbour index>)
-    REAL(dp)              ::  lx            !< domain length in the first dimension [m]
-    REAL(dp)              ::  ly            !< domain length in the second dimension [m]
-    REAL(dp)              ::  x0            !< x coordinate of PALM-4U domain projection centre, i.e. location of zero distortion
-    REAL(dp)              ::  y0            !< y coordinate of PALM-4U domain projection centre, i.e. location of zwro distortion
-    REAL(dp)              ::  z0            !< displacement of the coordinate origin above sea level [m]
-    REAL(dp), ALLOCATABLE ::  x(:)          !< coordinates of cell centers in x direction [m]
-    REAL(dp), ALLOCATABLE ::  y(:)          !< coordinates of cell centers in y direction [m]
-    REAL(dp), POINTER     ::  z(:)          !< coordinates of cell centers in z direction [m]
-    REAL(dp), ALLOCATABLE ::  h(:,:,:)      !< heights grid point for intermediate grids [m]
-    REAL(dp), POINTER     ::  cosmo_h(:,:,:)!< pointer to appropriate COSMO level heights (scalar/w) [m]
-    REAL(dp), POINTER     ::  hhl(:,:,:)    !< heights of half layers (cell faces) above sea level in COSMO-DE, read in from 
-    REAL(dp), POINTER     ::  hfl(:,:,:)    !< heights of full layers (cell centres) above sea level in COSMO-DE, computed as arithmetic average of hhl
-    REAL(dp), POINTER     ::  depths(:)     !< depths of output soil layers, equal the depths of the source model (e.g. COSMO-DE)
-    REAL(dp), ALLOCATABLE ::  xu(:)         !< coordinates of cell faces in x direction [m]
-    REAL(dp), ALLOCATABLE ::  yv(:)         !< coordinates of cell faces in y direction [m]
-    REAL(dp), POINTER     ::  zw(:)         !< coordinates of cell faces in z direction [m]
-    REAL(dp), ALLOCATABLE ::  lat(:)        !< rotated-pole latitudes of scalars (cell centers) of the COSMO-DE grid [rad]
-    REAL(dp), ALLOCATABLE ::  lon(:)        !< rotated-pole longitudes of scalars (cell centres) of the COSMO-DE grid [rad]
-    REAL(dp), ALLOCATABLE ::  latv(:)       !< rotated-pole latitudes of v winds (face centres in latitudal/y direction) [rad]
-    REAL(dp), ALLOCATABLE ::  lonu(:)       !< rotated-pole latitudes of u winds (face centres in longitudal/x direction) [rad]
-    REAL(dp), ALLOCATABLE ::  clat(:,:)     !< latitudes of PALM-4U cell centres in COSMO-DE's rotated-pole grid [rad]
-    REAL(dp), ALLOCATABLE ::  clon(:,:)     !< longitudes of PALM-4U scalars (cell centres) in COSMO-DE's rotated-pole grid [rad]
-    REAL(dp), ALLOCATABLE ::  clatu(:,:)    !< latitudes of PALM-4U u winds (cell faces in u direction) in COSMO-DE's rotated-pole grid [rad]
-    REAL(dp), ALLOCATABLE ::  clonu(:,:)    !< longitudes of PALM-4U u winds (cell faces in u direction) in COSMO-DE's rotated-pole grid [rad]
-    REAL(dp), ALLOCATABLE ::  clatv(:,:)    !< latitudes of PALM-4U v winds (cell faces in v direction) in COSMO-DE's rotated-pole grid [rad]
-    REAL(dp), ALLOCATABLE ::  clonv(:,:)    !< longitudes of PALM-4U v winds (cell faces in v direction) in COSMO-DE's rotated-pole grid [rad]
-    REAL(dp), ALLOCATABLE ::  w_horiz(:,:,:)   !< weights for bilinear horizontal interpolation
-    REAL(dp), ALLOCATABLE ::  w_verti(:,:,:,:) !< weights for linear vertical interpolation
-    REAL(dp), ALLOCATABLE ::  w(:,:,:)      !< vertical interpolation weights, w(<source_column>, <PALM k level>, <neighbour index>) [-]
- END TYPE grid_definition
-
-
- TYPE nc_file
-    CHARACTER(LEN=PATH)   ::  name          !< file name
-    INTEGER               ::  dimid_time    !< NetCDF IDs of the time dimension
-    INTEGER               ::  dimids_scl(3) !< NetCDF IDs of the grid dimensions for scalar points x, y, z 
-    INTEGER               ::  dimids_vel(3) !< NetCDF IDs of the grid dimensions for velocity points xu, yu, zu
-    INTEGER               ::  dimids_soil(3)!< NetCDF IDs of the grid dimensions for soil points x, y, depth
-    INTEGER               ::  dimvarid_time !< NetCDF IDs of the time variable
-    INTEGER               ::  dimvarids_scl(3) !< NetCDF IDs of the grid coordinates of scalars x, y, z 
-    INTEGER               ::  dimvarids_vel(3) !< NetCDF IDs of the grid coordinates of velocities xu, yu, zu. Note that velocities are located at mix of both coordinates, e.g. u(xu, y, z).
-    INTEGER               ::  dimvarids_soil(3)!< NetCDF IDs of the grid coordinates for soil points x, y, depth 
-    REAL(dp), POINTER     ::  time(:)       ! vector of output time steps
- END TYPE nc_file
-
-
- TYPE nc_var
-    INTEGER                               ::  varid     !< NetCDF ID of the variable
-    INTEGER                               ::  input_id  !< ID of the correpsonding input variables, only valid for output variables
-    INTEGER                               ::  ndim      !< number of NetCDF dimensions
-    INTEGER                               ::  nt        !< number of output time steps
-    INTEGER                               ::  lod       !< NetCDF attribute indicating the PALM-4U level of detail
-    INTEGER, DIMENSION(NF90_MAX_VAR_DIMS) ::  dimids    !< NetCDF IDs of the dimensions
-    INTEGER, DIMENSION(NF90_MAX_VAR_DIMS) ::  dimvarids !< IDs of NetCDF dimension variables
-    INTEGER, DIMENSION(NF90_MAX_VAR_DIMS) ::  dimlen    !< length of NetCDF dimensions
-    CHARACTER(LEN=NF90_MAX_NAME), DIMENSION(NF90_MAX_VAR_DIMS) ::  dimname !< names of NetCDF dimensions
-    CHARACTER(LEN=SNAME)                  ::  name                      !< NetCDF short name of the variable
-    CHARACTER(LEN=LNAME)                  ::  standard_name             !< NetCDF standard name of the variable
-    CHARACTER(LEN=LNAME)                  ::  long_name                 !< NetCDF long name of the variable
-    CHARACTER(LEN=LNAME)                  ::  source                    !< NetCDF attribute indicating the data source for the output
-    CHARACTER(LEN=SNAME)                  ::  units                     !< NetCDF units of the variable
-    CHARACTER(LEN=SNAME)                  ::  kind                      !< Kind of grid
-    CHARACTER(LEN=SNAME)                  ::  task                      !< Processing task that generates this variable, e.g. 'interpolate_2d' or 'average profile'
-    LOGICAL                               ::  to_be_processed = .FALSE. !< INIFOR flag indicating whether variable shall be processed
-    LOGICAL                               ::  is_internal = .FALSE.     !< INIFOR flag indicating whether variable shall be written to netCDF file (.FALSE.) or kept for later (.TRUE.)
-    LOGICAL                               ::  is_read = .FALSE.         !< INIFOR flag indicating whether variable has been read
-    LOGICAL                               ::  is_upside_down  = .FALSE. !< INIFOR flag indicating whether vertical dimension is reversed (typically the case with COSMO-DE atmospheric fields)
-    TYPE(grid_definition), POINTER        ::  grid                      !< Pointer to the corresponding output grid
-    TYPE(grid_definition), POINTER        ::  intermediate_grid         !< Pointer to the corresponding intermediate grid
-    TYPE(grid_definition), POINTER        ::  averaging_grid         !< Pointer to the corresponding intermediate grid
- END TYPE nc_var
-
-
- TYPE io_group                                          !< Input/Output group, groups together output variabels that share their input variables. For instance, all boundary surfaces and initialization fields of the potential temperature are base on T and p.
-    INTEGER                          ::  nt             !< maximum number of output time steps across all output variables
-    INTEGER                          ::  nv             !< number of netCDF output variables
-    INTEGER                          ::  n_inputs       !< number of input variables
-    INTEGER                          ::  n_output_quantities !< number of physical quantities required for computing netCDF output variables
-    CHARACTER(LEN=SNAME)             ::  kind           !< kind of I/O group
-    CHARACTER(LEN=PATH), ALLOCATABLE ::  in_files(:)    !< list of nt input files
-    TYPE(nc_var), ALLOCATABLE        ::  out_vars(:)    !< list of output variables 
-    TYPE(nc_var), ALLOCATABLE        ::  in_var_list(:) !< list of input variables
-    LOGICAL                          ::  to_be_processed = .FALSE. !< Inifor flag indicating whether I/O group shall be processed
-    LOGICAL                          ::  is_accumulated = .FALSE.  !< Flag indicating whether this I/O group contains accumulated variables
-    LOGICAL                          ::  is_preprocessed = .FALSE. !< Inifor flag indicating whether the I/O group has been preprocessed
- END TYPE io_group 
-
-
- TYPE container
-   REAL(dp), ALLOCATABLE ::  array(:,:,:)
-   LOGICAL               ::  is_preprocessed = .FALSE.
- END TYPE container
-
- END MODULE types
-
Index: palm/trunk/UTIL/inifor/src/util.f90
===================================================================
--- palm/trunk/UTIL/inifor/src/util.f90	(revision 3401)
+++ 	(revision )
@@ -1,390 +1,0 @@
-!> @file src/util.f90
-!------------------------------------------------------------------------------!
-! This file is part of the PALM model system.
-!
-! PALM is free software: you can redistribute it and/or modify it under the
-! terms of the GNU General Public License as published by the Free Software
-! Foundation, either version 3 of the License, or (at your option) any later
-! version.
-!
-! PALM is distributed in the hope that it will be useful, but WITHOUT ANY
-! WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-! A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
-!
-! You should have received a copy of the GNU General Public License along with
-! PALM. If not, see <http://www.gnu.org/licenses/>.
-!
-! Copyright 2017-2018 Leibniz Universitaet Hannover
-! Copyright 2017-2018 Deutscher Wetterdienst Offenbach
-!------------------------------------------------------------------------------!
-!
-! Current revisions:
-! -----------------
-! 
-! 
-! Former revisions:
-! -----------------
-! $Id$
-! New routines for computing potential temperature and moist air density
-! Increased number of digits in real-to-str conversion
-! 
-! 3183 2018-07-27 14:25:55Z suehring
-! Improved real-to-string conversion
-! 
-! 
-! 3182 2018-07-27 13:36:03Z suehring
-! Initial revision
-!
-! 
-!
-! Authors:
-! --------
-! @author Eckhard Kadasch
-!
-! Description:
-! ------------
-!> The util module provides miscellaneous utility routines for INIFOR.
-!------------------------------------------------------------------------------!
- MODULE util
-
-    USE, INTRINSIC :: ISO_C_BINDING,                                           &
-        ONLY :  C_CHAR, C_INT, C_PTR, C_SIZE_T
-    USE defs,                                                                  &
-        ONLY :  dp, PI, DATE, SNAME
-    USE types,                                                                 &
-        ONLY :  grid_definition
-
-    IMPLICIT NONE
-
-    TYPE, BIND(c) :: tm_struct
-       INTEGER(C_INT) :: tm_sec     !< seconds after the minute [0, 61]
-       INTEGER(C_INT) :: tm_min     !< minutes after the hour [0, 59]
-       INTEGER(C_INT) :: tm_hour    !< hours since midnight [0, 23]
-       INTEGER(C_INT) :: tm_mday    !< day of the month [1, 31]
-       INTEGER(C_INT) :: tm_mon     !< month since January [0, 11]
-       INTEGER(C_INT) :: tm_year    !< years since 1900
-       INTEGER(C_INT) :: tm_wday    !< days since Sunday [0, 6]
-       INTEGER(C_INT) :: tm_yday    !< days since January 1st [0, 356]
-       INTEGER(C_INT) :: tm_isdst   !< Daylight Saving Time flag
-    END TYPE
-
-    INTERFACE
-
-       FUNCTION strptime(string, format, timeinfo) BIND(c, NAME='strptime')
-          IMPORT :: C_CHAR, C_SIZE_T, tm_struct
-
-          IMPLICIT NONE
-
-          CHARACTER(KIND=C_CHAR), DIMENSION(*), INTENT(IN) ::  string, format
-          TYPE(tm_struct), INTENT(OUT)                     ::  timeinfo
-
-          INTEGER(C_SIZE_T)                                ::  strptime
-       END FUNCTION
-
-
-       FUNCTION strftime(string, string_len, format, timeinfo) BIND(c, NAME='strftime')
-          IMPORT :: C_CHAR, C_SIZE_T, tm_struct
-
-          IMPLICIT NONE
-
-          CHARACTER(KIND=C_CHAR), DIMENSION(*), INTENT(OUT) ::  string
-          CHARACTER(KIND=C_CHAR), DIMENSION(*), INTENT(IN)  ::  format
-          INTEGER(C_SIZE_T), INTENT(IN)                     ::  string_len
-          TYPE(tm_struct), INTENT(IN)                       ::  timeinfo
-
-          INTEGER(C_SIZE_T)                                 ::  strftime
-       END FUNCTION
-
-
-       FUNCTION mktime(timeinfo) BIND(c, NAME='mktime')
-          IMPORT :: C_PTR, tm_struct
-
-          IMPLICIT NONE
-
-          TYPE(tm_struct), INTENT(IN) ::  timeinfo
-
-          TYPE(C_PTR)                 ::  mktime
-       END FUNCTION
-
-    END INTERFACE
-
- CONTAINS
-
-    CHARACTER(LEN=DATE) FUNCTION add_hours_to(date_string, hours)
-       CHARACTER(LEN=DATE), INTENT(IN)          ::  date_string
-       INTEGER, INTENT(IN)                      ::  hours
-
-       CHARACTER(KIND=C_CHAR, LEN=*), PARAMETER ::  format_string = "%Y%m%d%H"
-       CHARACTER(KIND=C_CHAR, LEN=DATE)         ::  c_date_string
-       TYPE(C_PTR)                              ::  c_pointer
-       TYPE(tm_struct)                          ::  time_info
-       INTEGER                                  ::  err
-
-       c_date_string = date_string
-
-       ! Convert C string to C tm struct
-       CALL init_tm(time_info)
-       err = strptime(c_date_string, format_string, time_info)
-    
-       ! Manipulate and normalize C tm struct
-       time_info % tm_hour = time_info % tm_hour + hours
-       c_pointer = mktime(time_info)
-
-       ! Convert back to C string
-       err = strftime(c_date_string, INT(DATE, KIND=C_SIZE_T),                 &
-                      format_string, time_info)
-
-       add_hours_to = c_date_string
-    END FUNCTION
-
-
-    SUBROUTINE print_tm(timeinfo)
-       TYPE(tm_struct), INTENT(IN) :: timeinfo
-
-       PRINT *, "sec: ", timeinfo % tm_sec,  &  !< seconds after the minute [0, 61]
-                "min: ", timeinfo % tm_min,  &  !< minutes after the hour [0, 59]
-                "hr:  ", timeinfo % tm_hour, &  !< hours since midnight [0, 23]
-                "day: ", timeinfo % tm_mday, &  !< day of the month [1, 31]
-                "mon: ", timeinfo % tm_mon,  &  !< month since January [0, 11]
-                "yr:  ", timeinfo % tm_year, &  !< years since 1900
-                "wday:", timeinfo % tm_wday, &  !< days since Sunday [0, 6]
-                "yday:", timeinfo % tm_yday, &  !< days since January 1st [0, 356]
-                "dst: ", timeinfo % tm_isdst    !< Daylight Saving time flag
-    END SUBROUTINE print_tm
-
-    
-    SUBROUTINE init_tm(timeinfo)
-       TYPE(tm_struct), INTENT(INOUT) :: timeinfo
-
-       timeinfo % tm_sec   = 0
-       timeinfo % tm_min   = 0
-       timeinfo % tm_hour  = 0
-       timeinfo % tm_mday  = 0
-       timeinfo % tm_mon   = 0
-       timeinfo % tm_year  = 0
-       timeinfo % tm_wday  = 0
-       timeinfo % tm_yday  = 0
-
-       ! We use UTC times, so marking Daylight Saving Time (DST) 'not available'
-       ! (< 0). If this is set to 0, mktime will convert the timeinfo to DST and
-       ! add one hour.
-       timeinfo % tm_isdst = -1
-    END SUBROUTINE init_tm
-
-
-    SUBROUTINE fake_output_3d(a)
-
-       REAL(dp), INTENT(INOUT)       ::  a(:,:,:)
-       REAL(dp)                      ::  lxi, lyi
-       INTEGER ::  i,j,k
-
-       lyi = 2.0_dp * PI / (SIZE(a, 2) - 1.0_dp)
-       lxi = 2.0_dp * PI / (SIZE(a, 1) - 1.0_dp)
-
-       DO k = 1, SIZE(a, 3)
-       DO j = 1, SIZE(a, 2)
-       DO i = 1, SIZE(a, 1)
-           a(i,j,k) = SIN(lxi * i) * COS(lyi * j) + k
-       END DO
-       END DO
-       END DO
-
-    END SUBROUTINE fake_output_3d
-
-
-    SUBROUTINE fake_output_2d(a, offset)
-
-       REAL(dp), INTENT(INOUT) ::  a(:,:)
-       INTEGER, INTENT(IN)     ::  offset
-       REAL(dp)                ::  lxi, lyi
-       INTEGER                 ::  i,j
-
-       lyi = 2.0_dp*PI / (SIZE(a, 2) - 1.0_dp)
-       lxi = 2.0_dp*PI / (SIZE(a, 1) - 1.0_dp)
-
-       a(:,:) = 1.0_dp
-       DO j = 1, SIZE(a, 2)
-       DO i = 1, SIZE(a, 1)
-          a(i,j) = SIN(lxi * i) * COS(lyi * j) + offset
-       END DO
-       END DO
-
-    END SUBROUTINE fake_output_2d
-
-
-    SUBROUTINE linspace(start, stop, array)
-
-       REAL(dp), INTENT(IN)    ::  start, stop
-       REAL(dp), INTENT(INOUT) ::  array(0:)
-       INTEGER                 ::  i, n
-
-       n = UBOUND(array, 1)
-
-       IF (n .EQ. 0)  THEN
-
-          array(0) = start
-
-       ELSE
-
-          DO i = 0, n
-             array(i) = start + REAL(i, dp) / n * (stop - start)
-          END DO
-
-       END IF
-       
-    END SUBROUTINE linspace
-
-
-!------------------------------------------------------------------------------!
-! Description:
-! ------------
-!> Reverse the order of the third (vertical) array dimension from top-down
-!> (COSMO) to bottom-up (PALM)
-!------------------------------------------------------------------------------!
-    SUBROUTINE reverse(input_arr)
-
-       REAL(dp), INTENT(INOUT) ::  input_arr(:,:,:)
-
-       input_arr = input_arr(:,:,size(input_arr, 3):1:-1)
-
-    END SUBROUTINE reverse
-
-
-    SUBROUTINE deaverage(avg_1, t1, avg_2, t2, avg_3, t3)
-
-       REAL(dp), DIMENSION(:,:,:), INTENT(IN)  ::  avg_1, avg_2
-       REAL(dp), INTENT(IN)                    ::  t1, t2, t3
-       REAL(dp), DIMENSION(:,:,:), INTENT(OUT) ::  avg_3
-
-       REAL(dp)                                ::  ti
- 
-       ti = 1.0_dp / t3
-
-       avg_3(:,:,:) = ti * ( t2 * avg_2(:,:,:) - t1 * avg_1(:,:,:) )
-
-    END SUBROUTINE deaverage
-
-
-    SUBROUTINE get_basic_state(z, beta, p_sl, t_sl, rd, g, p0)
-
-       REAL(dp), INTENT(IN)  ::  z(1:)  !< height [m]
-       REAL(dp), INTENT(IN)  ::  beta   !< logarithmic lapse rate, dT / d ln(p) [K]
-       REAL(dp), INTENT(IN)  ::  p_sl   !< reference pressure [Pa]
-       REAL(dp), INTENT(IN)  ::  t_sl   !< reference tempereature [K]
-       REAL(dp), INTENT(IN)  ::  rd     !< ideal gas constant of dry air [J/kg/K]
-       REAL(dp), INTENT(IN)  ::  g      !< acceleration of Earth's gravity [m/s^2]
-       REAL(dp), INTENT(OUT) ::  p0(1:) !< COSMO-DE basic state pressure [Pa]
-       REAL(dp) ::  root_frac, factor   !< precomputed factors
-
-       factor = - t_sl / beta
-       root_frac = (2.0_dp * beta * g) / (rd * t_sl*t_sl)
-
-       p0(:) = p_sl * EXP(                                                     &
-                  factor * ( 1.0_dp - SQRT( 1.0_dp - root_frac * z(:) ) )  &
-               )
-
-    END SUBROUTINE get_basic_state
-
-
-!------------------------------------------------------------------------------!
-! Description:
-! ------------
-!> Converts the absolute temperature to the potential temperature in place using
-!> the identity a^b = e^(b ln(a)).
-!>
-!>     theta = T * (p_ref/p)^(R/c_p) = T * e^( R/c_p * ln(p_ref/p) )
-!------------------------------------------------------------------------------!
-    SUBROUTINE potential_temperature(t, p, p_ref, r, cp)
-       REAL(dp), DIMENSION(:,:,:), INTENT(INOUT) ::  t
-       REAL(dp), DIMENSION(:,:,:), INTENT(IN)    ::  p
-       REAL(dp), INTENT(IN)                      ::  p_ref, r, cp
-       REAL(dp)                                  ::  rcp
-
-       rcp = r/cp
-       t(:,:,:) =  t(:,:,:) * EXP( rcp * LOG(p_ref / p(:,:,:)) )
-
-    END SUBROUTINE potential_temperature
-
-
-!------------------------------------------------------------------------------!
-! Description:
-! ------------
-!> Compute the density in place of the given temperature (t_rho).
-!------------------------------------------------------------------------------!
-   SUBROUTINE moist_density(t_rho, p, qv, rd, rv)
-       REAL(dp), DIMENSION(:,:,:), INTENT(INOUT) ::  t_rho
-       REAL(dp), DIMENSION(:,:,:), INTENT(IN)    ::  p, qv
-       REAL(dp), INTENT(IN)                      ::  rd, rv
-
-       t_rho(:,:,:) = p(:,:,:) / (                                             &
-          (rv * qv(:,:,:) + rd * (1.0_dp - qv(:,:,:))) * t_rho(:,:,:)          &
-       )
-
-    END SUBROUTINE moist_density
-
-
-    ! Convert a real number to a string in scientific notation
-    ! showing four significant digits.
-    CHARACTER(LEN=SNAME) FUNCTION real_to_str(val, format)
-
-        REAL(dp), INTENT(IN)                   ::  val
-        CHARACTER(LEN=*), OPTIONAL, INTENT(IN) ::  format
-
-        IF (PRESENT(format))  THEN
-           WRITE(real_to_str, format) val
-        ELSE
-           WRITE(real_to_str, '(E11.4)') val
-        END IF
-        real_to_str = ADJUSTL(real_to_str)
-
-    END FUNCTION real_to_str
-
-
-    CHARACTER(LEN=16) FUNCTION real_to_str_f(val)
-
-        REAL(dp), INTENT(IN) ::  val
-
-        WRITE(real_to_str_f, '(F16.8)') val
-        real_to_str_f = ADJUSTL(real_to_str_f)
-
-    END FUNCTION real_to_str_f
-
-
-    CHARACTER(LEN=10) FUNCTION str(val)
-
-        INTEGER, INTENT(IN) ::  val
-
-        WRITE(str, '(i10)') val
-        str = ADJUSTL(str)
-
-    END FUNCTION str
-
-
-    CHARACTER(LEN=30) FUNCTION strs(vals)
-
-        INTEGER, INTENT(IN) ::  vals(:)
-        INTEGER ::  i
-
-        strs = ''
-        DO i = 1, SIZE(vals)
-           strs = TRIM(strs) // TRIM(str(vals(i)))
-        END DO
-
-    END FUNCTION strs
-
-
-    SUBROUTINE normalize_path(path)
-        
-        CHARACTER(LEN=*), INTENT(INOUT) ::  path
-        INTEGER ::  n
-
-        n = LEN_TRIM(path)
-
-        IF (path(n:n) .NE. '/')  THEN
-           path = TRIM(path) // '/'
-        END IF
-
-    END SUBROUTINE
-
- END MODULE
-
